Newer
Older
*/
data->set.httpversion = va_arg(param, long);
break;
case CURLOPT_HTTPPROXYTUNNEL:
* Tunnel operations through the proxy instead of normal proxy use
data->set.tunnel_thru_httpproxy = (bool)(0 != va_arg(param, long));
case CURLOPT_CUSTOMREQUEST:
* Set a custom string to use as request
data->set.customrequest = va_arg(param, char *);
/* we don't set
data->set.httpreq = HTTPREQ_CUSTOM;
here, we continue as if we were using the already set type
and this just changes the actual request keyword */
/*
* Explicitly set HTTP proxy port number.
*/
Daniel Stenberg
committed
data->set.proxyport = va_arg(param, long);
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
*/
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
Daniel Stenberg
committed
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
#endif
if(!auth)
return CURLE_FAILED_INIT; /* no supported types left! */
data->set.httpauth = auth;
}
break;
case CURLOPT_PROXYAUTH:
/*
* Set HTTP Authentication type BITMASK.
*/
{
long auth = va_arg(param, long);
/* switch off bits we can't support */
Daniel Stenberg
committed
#ifndef USE_NTLM
auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */
#endif
#ifndef HAVE_GSSAPI
auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */
#endif
if(!auth)
return CURLE_FAILED_INIT; /* no supported types left! */
data->set.proxyauth = auth;
}
break;
#endif /* CURL_DISABLE_HTTP */
Daniel Stenberg
committed
case CURLOPT_PROXY:
/*
* Set proxy server:port to use as HTTP proxy.
*
* If the proxy is set to "" we explicitly say that we don't want to use a
* proxy (even though there might be environment variables saying so).
*
* Setting it to NULL, means no proxy but allows the environment variables
* to decide for us.
*/
if(data->change.proxy_alloc) {
/*
* The already set string is allocated, free that first
*/
Daniel Stenberg
committed
free(data->change.proxy);
}
data->set.set_proxy = va_arg(param, char *);
data->change.proxy = data->set.set_proxy;
break;
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
case CURLOPT_WRITEHEADER:
/*
* Custom pointer to pass the header write callback function
*/
data->set.writeheader = (void *)va_arg(param, void *);
break;
case CURLOPT_ERRORBUFFER:
/*
* Error buffer provided by the caller to get the human readable
* error string in.
*/
data->set.errorbuffer = va_arg(param, char *);
break;
case CURLOPT_FILE:
/*
* FILE pointer to write to or include in the data write callback
*/
data->set.out = va_arg(param, FILE *);
break;
case CURLOPT_FTPPORT:
/*
* Use FTP PORT, this also specifies which IP address to use
*/
data->set.ftpport = va_arg(param, char *);
data->set.ftp_use_port = (bool)(NULL != data->set.ftpport);
break;
case CURLOPT_FTP_USE_EPRT:
data->set.ftp_use_eprt = (bool)(0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_EPSV:
data->set.ftp_use_epsv = (bool)(0 != va_arg(param, long));
break;
case CURLOPT_FTP_SKIP_PASV_IP:
/*
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
data->set.ftp_skip_ip = (bool)(0 != va_arg(param, long));
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
case CURLOPT_INFILE:
/*
* FILE pointer to read the file to be uploaded from. Or possibly
* used as argument to the read callback.
*/
data->set.in = va_arg(param, FILE *);
break;
case CURLOPT_INFILESIZE:
/*
* If known, this should inform curl about the file size of the
* to-be-uploaded file.
*/
data->set.infilesize = va_arg(param, long);
break;
case CURLOPT_INFILESIZE_LARGE:
/*
* If known, this should inform curl about the file size of the
* to-be-uploaded file.
*/
data->set.infilesize = va_arg(param, curl_off_t);
break;
case CURLOPT_LOW_SPEED_LIMIT:
/*
* The low speed limit that if transfers are below this for
* CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
*/
data->set.low_speed_limit=va_arg(param, long);
break;
case CURLOPT_MAX_SEND_SPEED_LARGE:
/*
* The max speed limit that sends transfer more than
* CURLOPT_MAX_SEND_PER_SECOND bytes per second the transfer is
* throttled..
*/
data->set.max_send_speed=va_arg(param, curl_off_t);
break;
case CURLOPT_MAX_RECV_SPEED_LARGE:
/*
* The max speed limit that sends transfer more than
* CURLOPT_MAX_RECV_PER_SECOND bytes per second the transfer is
* throttled..
*/
data->set.max_recv_speed=va_arg(param, curl_off_t);
break;
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
case CURLOPT_LOW_SPEED_TIME:
/*
* The low speed time that if transfers are below the set
* CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
*/
data->set.low_speed_time=va_arg(param, long);
break;
case CURLOPT_URL:
/*
* The URL to fetch.
*/
if(data->change.url_alloc) {
/* the already set URL is allocated, free it first! */
free(data->change.url);
data->change.url_alloc=FALSE;
}
data->set.set_url = va_arg(param, char *);
data->change.url = data->set.set_url;
data->change.url_changed = TRUE;
break;
case CURLOPT_PORT:
/*
* The port number to use when getting the URL
*/
data->set.use_port = va_arg(param, long);
break;
case CURLOPT_TIMEOUT:
/*
* The maximum time you allow curl to use for a single transfer
* operation.
*/
data->set.timeout = va_arg(param, long);
break;
case CURLOPT_CONNECTTIMEOUT:
/*
* The maximum time you allow curl to use to connect.
*/
data->set.connecttimeout = va_arg(param, long);
break;
/*
* user:password to use in the operation
*/
Daniel Stenberg
committed
data->set.userpwd = va_arg(param, char *);
* List of RAW FTP commands to use after a transfer
Daniel Stenberg
committed
data->set.postquote = va_arg(param, struct curl_slist *);
case CURLOPT_PREQUOTE:
/*
* List of RAW FTP commands to use prior to RETR (Wesley Laxton)
*/
data->set.prequote = va_arg(param, struct curl_slist *);
break;
case CURLOPT_QUOTE:
/*
* List of RAW FTP commands to use before a transfer
Daniel Stenberg
committed
data->set.quote = va_arg(param, struct curl_slist *);
case CURLOPT_PROGRESSFUNCTION:
/*
* Progress callback function
*/
Daniel Stenberg
committed
data->set.fprogress = va_arg(param, curl_progress_callback);
Daniel Stenberg
committed
if(data->set.fprogress)
data->progress.callback = TRUE; /* no longer internal */
else
data->progress.callback = FALSE; /* NULL enforces internal */
break;
case CURLOPT_PROGRESSDATA:
/*
* Custom client data to pass to the progress callback
*/
Daniel Stenberg
committed
data->set.progress_client = va_arg(param, void *);
break;
/*
* user:password needed to use the proxy
*/
Daniel Stenberg
committed
data->set.proxyuserpwd = va_arg(param, char *);
/*
* What range of the file you want to transfer
*/
Daniel Stenberg
committed
data->set.set_range = va_arg(param, char *);
/*
* Resume transfer at the give file position
*/
Daniel Stenberg
committed
data->set.set_resume_from = va_arg(param, long);
case CURLOPT_RESUME_FROM_LARGE:
/*
* Resume transfer at the give file position
*/
data->set.set_resume_from = va_arg(param, curl_off_t);
case CURLOPT_DEBUGFUNCTION:
/*
* stderr write callback.
*/
data->set.fdebug = va_arg(param, curl_debug_callback);
/*
* if the callback provided is NULL, it'll use the default callback
*/
break;
case CURLOPT_DEBUGDATA:
/*
* Set to a void * that should receive all error writes. This
* defaults to CURLOPT_STDERR for normal operations.
*/
data->set.debugdata = va_arg(param, void *);
break;
/*
* Set to a FILE * that should receive all error writes. This
* defaults to stderr for normal operations.
*/
Daniel Stenberg
committed
data->set.err = va_arg(param, FILE *);
if(!data->set.err)
data->set.err = stderr;
case CURLOPT_HEADERFUNCTION:
/*
* Set header write callback
*/
Daniel Stenberg
committed
data->set.fwrite_header = va_arg(param, curl_write_callback);
/*
* Set data write callback
*/
Daniel Stenberg
committed
data->set.fwrite = va_arg(param, curl_write_callback);
if(!data->set.fwrite)
/* When set to NULL, reset to our internal default function */
data->set.fwrite = (curl_write_callback)fwrite;
/*
* Read data callback
*/
Daniel Stenberg
committed
data->set.fread = va_arg(param, curl_read_callback);
if(!data->set.fread)
/* When set to NULL, reset to our internal default function */
data->set.fread = (curl_read_callback)fread;
case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
/*
* "Convert from network encoding" callback
*/
data->set.convfromnetwork = va_arg(param, curl_conv_callback);
break;
case CURLOPT_CONV_TO_NETWORK_FUNCTION:
/*
* "Convert to network encoding" callback
*/
data->set.convtonetwork = va_arg(param, curl_conv_callback);
break;
case CURLOPT_CONV_FROM_UTF8_FUNCTION:
/*
* "Convert from UTF-8 encoding" callback
*/
data->set.convfromutf8 = va_arg(param, curl_conv_callback);
break;
case CURLOPT_IOCTLFUNCTION:
/*
* I/O control callback. Might be NULL.
*/
data->set.ioctl = va_arg(param, curl_ioctl_callback);
break;
case CURLOPT_IOCTLDATA:
/*
* I/O control data pointer. Might be NULL.
*/
data->set.ioctl_client = va_arg(param, void *);
/*
* String that holds file name of the SSL certificate to use
*/
Daniel Stenberg
committed
data->set.cert = va_arg(param, char *);
* String that holds file type of the SSL certificate to use
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
data->set.cert_type = va_arg(param, char *);
break;
case CURLOPT_SSLKEY:
/*
* String that holds file name of the SSL certificate to use
*/
data->set.key = va_arg(param, char *);
break;
case CURLOPT_SSLKEYTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
data->set.key_type = va_arg(param, char *);
break;
case CURLOPT_SSLKEYPASSWD:
/*
* String that holds the SSL private key password.
*/
data->set.key_passwd = va_arg(param, char *);
break;
case CURLOPT_SSLENGINE:
/*
* String that holds the SSL crypto engine.
*/
argptr = va_arg(param, char *);
Daniel Stenberg
committed
result = Curl_ssl_set_engine(data, argptr);
break;
Daniel Stenberg
committed
case CURLOPT_SSLENGINE_DEFAULT:
/*
* flag to set engine as default.
*/
Daniel Stenberg
committed
result = Curl_ssl_set_engine_default(data);
* Kludgy option to enable CRLF conversions. Subject for removal.
Daniel Stenberg
committed
Daniel Stenberg
committed
* Set what interface or address/hostname to bind the socket to when
* performing an operation and thus what from-IP your connection will use.
Daniel Stenberg
committed
data->set.device = va_arg(param, char *);
Daniel Stenberg
committed
case CURLOPT_LOCALPORT:
/*
* Set what local port to bind the socket to when performing an operation.
*/
data->set.localport = (unsigned short) va_arg(param, long);
break;
case CURLOPT_LOCALPORTRANGE:
/*
* Set number of local ports to try, starting with CURLOPT_LOCALPORT.
*/
data->set.localportrange = (int) va_arg(param, long);
break;
/*
* A string that defines the krb4 security level.
*/
Daniel Stenberg
committed
data->set.krb4_level = va_arg(param, char *);
Daniel Stenberg
committed
case CURLOPT_SSL_VERIFYPEER:
/*
* Enable peer SSL verifying.
*/
Daniel Stenberg
committed
data->set.ssl.verifypeer = va_arg(param, long);
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
case CURLOPT_SSL_VERIFYHOST:
/*
* Enable verification of the CN contained in the peer certificate
*/
Daniel Stenberg
committed
data->set.ssl.verifyhost = va_arg(param, long);
Daniel Stenberg
committed
break;
case CURLOPT_SSL_CTX_FUNCTION:
/*
* Set a SSL_CTX callback
*/
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
break;
case CURLOPT_SSL_CTX_DATA:
/*
* Set a SSL_CTX callback parameter pointer
*/
data->set.ssl.fsslctxp = va_arg(param, void *);
break;
Daniel Stenberg
committed
case CURLOPT_CAINFO:
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
Daniel Stenberg
committed
data->set.ssl.CAfile = va_arg(param, char *);
break;
case CURLOPT_CAPATH:
/*
* Set CA path info for SSL connection. Specify directory name of the CA
* certificates which have been prepared using openssl c_rehash utility.
/* This does not work on windows. */
data->set.ssl.CApath = va_arg(param, char *);
Daniel Stenberg
committed
break;
case CURLOPT_TELNETOPTIONS:
/*
* Set a linked list of telnet options
*/
Daniel Stenberg
committed
data->set.telnet_options = va_arg(param, struct curl_slist *);
case CURLOPT_BUFFERSIZE:
/*
* The application kindly asks for a differently sized receive buffer.
* If it seems reasonable, we'll use it.
*/
data->set.buffer_size = va_arg(param, long);
Daniel Stenberg
committed
if((data->set.buffer_size> (BUFSIZE -1 )) ||
(data->set.buffer_size < 1))
data->set.buffer_size = 0; /* huge internal default */
break;
case CURLOPT_NOSIGNAL:
/*
* The application asks not to set any signal() or alarm() handlers,
* even when using a timeout.
*/
data->set.no_signal = (bool)(0 != va_arg(param, long));
case CURLOPT_SHARE:
{
struct Curl_share *set;
set = va_arg(param, struct Curl_share *);
Daniel Stenberg
committed
/* disconnect from old share, if any */
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
Daniel Stenberg
committed
if(data->dns.hostcachetype == HCACHE_SHARED) {
data->dns.hostcache = NULL;
data->dns.hostcachetype = HCACHE_NONE;
}
Daniel Stenberg
committed
if(data->share->cookies == data->cookies)
data->cookies = NULL;
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
Daniel Stenberg
committed
data->share = NULL;
Daniel Stenberg
committed
/* use new share if it set */
Daniel Stenberg
committed
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
Daniel Stenberg
committed
data->share->dirty++;
Daniel Stenberg
committed
if(data->share->hostcache) {
Daniel Stenberg
committed
/* use shared host cache, first free the private one if any */
if(data->dns.hostcachetype == HCACHE_PRIVATE)
Curl_hash_destroy(data->dns.hostcache);
Daniel Stenberg
committed
data->dns.hostcache = data->share->hostcache;
data->dns.hostcachetype = HCACHE_SHARED;
Daniel Stenberg
committed
}
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Daniel Stenberg
committed
if(data->share->cookies) {
/* use shared cookie list, first free own one if any */
if (data->cookies)
Curl_cookie_cleanup(data->cookies);
data->cookies = data->share->cookies;
}
#endif /* CURL_DISABLE_HTTP */
Daniel Stenberg
committed
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Daniel Stenberg
committed
/* check cookie list is set */
if(!data->cookies)
data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE );
#endif /* CURL_DISABLE_HTTP */
Daniel Stenberg
committed
/* check for host cache not needed,
Daniel Stenberg
committed
case CURLOPT_PROXYTYPE:
/*
* Set proxy type. HTTP/SOCKS4/SOCKS5
*/
data->set.proxytype = (curl_proxytype)va_arg(param, long);
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
case CURLOPT_PRIVATE:
/*
* Set private data pointer.
*/
data->set.private_data = va_arg(param, char *);
Daniel Stenberg
committed
break;
case CURLOPT_MAXFILESIZE:
/*
* Set the maximum size of a file to download.
*/
data->set.max_filesize = va_arg(param, long);
break;
Daniel Stenberg
committed
case CURLOPT_FTP_SSL:
/*
* Make FTP transfers attempt to use SSL/TLS.
*/
data->set.ftp_ssl = (curl_ftpssl)va_arg(param, long);
Daniel Stenberg
committed
break;
case CURLOPT_FTPSSLAUTH:
/*
* Set a specific auth for FTP-SSL transfers.
*/
data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
break;
case CURLOPT_IPRESOLVE:
data->set.ip_version = va_arg(param, long);
break;
case CURLOPT_MAXFILESIZE_LARGE:
/*
* Set the maximum size of a file to download.
*/
data->set.max_filesize = va_arg(param, curl_off_t);
case CURLOPT_TCP_NODELAY:
/*
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
* algorithm
*/
data->set.tcp_nodelay = (bool)(0 != va_arg(param, long));
/*
case CURLOPT_SOURCE_URL:
case CURLOPT_SOURCE_USERPWD:
case CURLOPT_SOURCE_QUOTE:
case CURLOPT_SOURCE_PREQUOTE:
case CURLOPT_SOURCE_POSTQUOTE:
These former 3rd party transfer options are deprecated */
Daniel Stenberg
committed
case CURLOPT_FTP_ACCOUNT:
data->set.ftp_account = va_arg(param, char *);
break;
Daniel Stenberg
committed
case CURLOPT_IGNORE_CONTENT_LENGTH:
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
case CURLOPT_CONNECT_ONLY:
/*
* No data transfer, set up connection and let application use the socket
*/
data->set.connect_only = (bool)(0 != va_arg(param, long));
Daniel Stenberg
committed
break;
Daniel Stenberg
committed
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
data->set.ftp_alternative_to_user = va_arg(param, char *);
break;
case CURLOPT_SOCKOPTFUNCTION:
/*
* socket callback function: called after socket() but before connect()
*/
data->set.fsockopt = va_arg(param, curl_sockopt_callback);
break;
case CURLOPT_SOCKOPTDATA:
/*
* socket callback data pointer. Might be NULL.
*/
data->set.sockopt_client = va_arg(param, void *);
break;
Daniel Stenberg
committed
case CURLOPT_SSL_SESSIONID_CACHE:
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
Daniel Stenberg
committed
break;
default:
/* unknown tag and its companion, just ignore: */
Daniel Stenberg
committed
result = CURLE_FAILED_INIT; /* correct this */
break;
Daniel Stenberg
committed
return result;
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
static void conn_free(struct connectdata *conn)
{
if (!conn)
return;
/* close possibly still open sockets */
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
sclose(conn->sock[SECONDARYSOCKET]);
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
sclose(conn->sock[FIRSTSOCKET]);
Curl_safefree(conn->user);
Curl_safefree(conn->passwd);
Curl_safefree(conn->proxyuser);
Curl_safefree(conn->proxypasswd);
Curl_safefree(conn->allocptr.proxyuserpwd);
Curl_safefree(conn->allocptr.uagent);
Curl_safefree(conn->allocptr.userpwd);
Curl_safefree(conn->allocptr.accept_encoding);
Curl_safefree(conn->allocptr.rangeline);
Curl_safefree(conn->allocptr.ref);
Curl_safefree(conn->allocptr.host);
Curl_safefree(conn->allocptr.cookiehost);
Curl_safefree(conn->ip_addr_str);
Curl_safefree(conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
Curl_llist_destroy(conn->send_pipe, NULL);
Curl_llist_destroy(conn->recv_pipe, NULL);
/* possible left-overs from the async name resolvers */
#if defined(USE_ARES)
Curl_safefree(conn->async.hostname);
Curl_safefree(conn->async.os_specific);
#elif defined(CURLRES_THREADED)
Curl_destroy_thread_data(&conn->async);
#endif
Curl_free_ssl_config(&conn->ssl_config);
free(conn); /* free all the connection oriented data */
}
CURLcode Curl_disconnect(struct connectdata *conn)
struct SessionHandle *data;
if(!conn)
return CURLE_OK; /* this is closed and fine already */
Daniel Stenberg
committed
if(!data) {
DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
return CURLE_OK;
}
Daniel Stenberg
committed
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
/* scan for DNS cache entries still marked as in use */
Curl_hash_apply(data->hostcache,
NULL, Curl_scan_cache_used);
#endif
Daniel Stenberg
committed
Curl_expire(data, 0); /* shut off timers */
Daniel Stenberg
committed
Curl_hostcache_prune(data); /* kill old DNS cache entries */
/*
* The range string is usually freed in curl_done(), but we might
* get here *instead* if we fail prematurely. Thus we need to be able
* to free this resource here as well.
*/
if(data->reqdata.rangestringalloc) {
free(data->reqdata.range);
data->reqdata.rangestringalloc = FALSE;
}
if((conn->ntlm.state != NTLMSTATE_NONE) ||
(conn->proxyntlm.state != NTLMSTATE_NONE)) {
/* Authentication data is a mix of connection-related and sessionhandle-
related stuff. NTLM is connection-related so when we close the shop
we shall forget. */
data->state.authhost.done = FALSE;
data->state.authhost.want;
data->state.authproxy.done = FALSE;
data->state.authproxy.want;
data->state.authproblem = FALSE;
Curl_ntlm_cleanup(conn);
Daniel Stenberg
committed
if(conn->curl_disconnect)
/* This is set if protocol-specific cleanups should be made */
conn->curl_disconnect(conn);
Daniel Stenberg
committed
/* unlink ourselves! */
infof(data, "Closing connection #%ld\n", conn->connectindex);
data->state.connc->connects[conn->connectindex] = NULL;
Daniel Stenberg
committed
if(conn->host.encalloc)
Daniel Stenberg
committed
idn_free(conn->host.encalloc); /* encoded host name buffer, must be freed
with idn_free() since this was allocated
by libidn */
if(conn->proxy.encalloc)
Daniel Stenberg
committed
idn_free(conn->proxy.encalloc); /* encoded proxy name buffer, must be
freed with idn_free() since this was
allocated by libidn */
Curl_ssl_close(conn);
/* Indicate to all handles on the pipe that we're dead */
signalPipeClose(conn->send_pipe);
signalPipeClose(conn->recv_pipe);
Daniel Stenberg
committed
conn_free(conn);
/*
* This function should return TRUE if the socket is to be assumed to
* be dead. Most commonly this happens when the server has closed the
* connection due to inactivity.
*/
static bool SocketIsDead(curl_socket_t sock)
{
int sval;
bool ret_val = TRUE;
sval = Curl_select(sock, CURL_SOCKET_BAD, 0);
Daniel Stenberg
committed
if(sval == 0)
ret_val = FALSE;
static bool IsPipeliningPossible(struct SessionHandle *handle)
{
if (handle->multi && Curl_multi_canPipeline(handle->multi) &&
(handle->set.httpreq == HTTPREQ_GET ||
handle->set.httpreq == HTTPREQ_HEAD) &&
handle->set.httpversion != CURL_HTTP_VERSION_1_0)
return TRUE;
return FALSE;
}
Daniel Stenberg
committed
void Curl_addHandleToPipeline(struct SessionHandle *data,
struct curl_llist *pipe)
{
Daniel Stenberg
committed
#ifdef CURLDEBUG
if(!IsPipeliningPossible(data)) {
/* when not pipelined, there MUST be no handle in the list already */
if(pipe->head)
infof(data, "PIPE when no PIPE supposed!\n");
}
#endif
Curl_llist_insert_next(pipe, pipe->tail, data);
}
Daniel Stenberg
committed
int Curl_removeHandleFromPipeline(struct SessionHandle *handle,
struct curl_llist *pipe)
{
struct curl_llist_element *curr;
curr = pipe->head;
while (curr) {
if (curr->ptr == handle) {
Curl_llist_remove(pipe, curr, NULL);
Daniel Stenberg
committed
return 1; /* we removed a handle */
}
curr = curr->next;
}
Daniel Stenberg
committed
Daniel Stenberg
committed
return 0;
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
}
#if 0
static void Curl_printPipeline(struct curl_llist *pipe)
{
struct curl_llist_element *curr;
curr = pipe->head;
while (curr) {
struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
infof(data, "Handle in pipeline: %s\n",
data->reqdata.path);
curr = curr->next;
}
}
#endif
bool Curl_isHandleAtHead(struct SessionHandle *handle,
struct curl_llist *pipe)
{
struct curl_llist_element *curr = pipe->head;
if (curr) {
}
return FALSE;
}
static void signalPipeClose(struct curl_llist *pipe)
{
struct curl_llist_element *curr;
curr = pipe->head;
while (curr) {
struct curl_llist_element *next = curr->next;
struct SessionHandle *data = (struct SessionHandle *) curr->ptr;
Daniel Stenberg
committed
#ifdef CURLDEBUG /* debug-only code */
if(data->magic != CURLEASY_MAGIC_NUMBER) {
/* MAJOR BADNESS */
fprintf(stderr, "signalPipeClose() found BAAD easy handle\n");
}
else
#endif
Daniel Stenberg
committed
data->state.pipe_broke = TRUE;
Curl_llist_remove(pipe, curr, NULL);
curr = next;
}
}
* Given one filled in connection struct (named needle), this function should
* detect if there already is one that has all the significant details
* exactly the same and thus should be used instead.
*
* If there is a match, this function returns TRUE - and has marked the
* connection as 'in-use'. It must later be called with ConnectionDone() to
* return back to 'idle' (unused) state.
Daniel Stenberg
committed
ConnectionExists(struct SessionHandle *data,
struct connectdata *needle,
struct connectdata **usethis)
struct connectdata *check;
bool canPipeline = IsPipeliningPossible(data);
for(i=0; i< data->state.connc->num; i++) {
bool match = FALSE;
/*
* Note that if we use a HTTP proxy, we check connections to that
* proxy and not to the actual remote server.
*/
check = data->state.connc->connects[i];
if(!check)
/* NULL pointer means not filled-in entry */
continue;
Daniel Stenberg
committed
#ifdef USE_ARES
/* ip_addr_str is NULL only if the resolving of the name hasn't completed
yet and until then we don't re-use this connection */
if (!check->ip_addr_str)
continue;
#endif
if(check->inuse && !canPipeline)
/* can only happen within multi handles, and means that another easy
handle is using this connection */
continue;
Daniel Stenberg
committed
if (check->send_pipe->size +
check->recv_pipe->size >= MAX_PIPELINE_LENGTH)
continue;
if((needle->protocol&PROT_SSL) != (check->protocol&PROT_SSL))
/* don't do mixed SSL and non-SSL connections */
continue;
if(!needle->bits.httpproxy || needle->protocol&PROT_SSL) {
/* The requested connection does not use a HTTP proxy or it
uses SSL. */
if(!(needle->protocol&PROT_SSL) && check->bits.httpproxy)
/* we don't do SSL but the cached connection has a proxy,
then don't match this */
continue;
if(strequal(needle->protostr, check->protostr) &&
strequal(needle->host.name, check->host.name) &&
(needle->remote_port == check->remote_port) ) {
Daniel Stenberg
committed
if(needle->protocol & PROT_SSL) {
/* This is SSL, verify that we're using the same
ssl options as well */
if(!Curl_ssl_config_matches(&needle->ssl_config,
&check->ssl_config)) {
Daniel Stenberg
committed
continue;
}
}
if((needle->protocol & PROT_FTP) ||
((needle->protocol & PROT_HTTP) &&
(data->state.authhost.want==CURLAUTH_NTLM))) {
/* This is FTP or HTTP+NTLM, verify that we're using the same name
and password as well */
if(!strequal(needle->user, check->user) ||
!strequal(needle->passwd, check->passwd)) {
/* one of them was different */
continue;
}
}
match = TRUE;
else { /* The requested needle connection is using a proxy,
is the checked one using the same? */
if(check->bits.httpproxy &&
strequal(needle->proxy.name, check->proxy.name) &&
needle->port == check->port) {
/* This is the same proxy connection, use it! */
match = TRUE;