651
651
close handles not in use.
653
653
for(i=newamount; i< c->num; i++)
654
Curl_disconnect(c->connects[i]);
654
Curl_disconnect(c->connects[i], /* dead_connection */ FALSE);
656
656
/* If the most recent connection is no longer valid, mark it
1006
1006
* An FTP option that modifies an upload to create missing directories on
1009
data->set.ftp_create_missing_dirs = (int)va_arg(param, long);
1009
switch(va_arg(param, long)) {
1011
data->set.ftp_create_missing_dirs = 0;
1014
data->set.ftp_create_missing_dirs = 1;
1017
data->set.ftp_create_missing_dirs = 2;
1020
/* reserve other values for future use */
1021
result = CURLE_FAILED_INIT;
1011
1025
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
1751
1765
data->set.quote = va_arg(param, struct curl_slist *);
1767
case CURLOPT_RESOLVE:
1769
* List of NAME:[address] names to populate the DNS cache with
1770
* Prefix the NAME with dash (-) to _remove_ the name from the cache.
1772
* Names added with this API will remain in the cache until explicitly
1773
* removed or the handle is cleaned up.
1775
* This API can remove any name from the DNS cache, but only entries
1776
* that aren't actually in use right now will be pruned immediately.
1778
data->set.resolve = va_arg(param, struct curl_slist *);
1779
data->change.resolve = data->set.resolve;
1753
1781
case CURLOPT_PROGRESSFUNCTION:
1755
1783
* Progress callback function
1988
2016
* Set what local port to bind the socket to when performing an operation.
1990
data->set.localport = (unsigned short) va_arg(param, long);
2018
data->set.localport = curlx_sltous(va_arg(param, long));
1992
2020
case CURLOPT_LOCALPORTRANGE:
1994
2022
* Set number of local ports to try, starting with CURLOPT_LOCALPORT.
1996
data->set.localportrange = (int) va_arg(param, long);
2024
data->set.localportrange = curlx_sltosi(va_arg(param, long));
1998
2026
case CURLOPT_KRBLEVEL:
2710
2739
#endif /* CURL_DISABLE_RTSP */
2712
static bool IsPipeliningPossible(const struct SessionHandle *handle)
2741
static bool IsPipeliningPossible(const struct SessionHandle *handle,
2742
const struct connectdata *conn)
2714
if(handle->multi && Curl_multi_canPipeline(handle->multi) &&
2715
(handle->set.httpreq == HTTPREQ_GET ||
2716
handle->set.httpreq == HTTPREQ_HEAD) &&
2717
handle->set.httpversion != CURL_HTTP_VERSION_1_0)
2744
if((conn->handler->protocol & PROT_HTTP) &&
2745
handle->multi && Curl_multi_canPipeline(handle->multi) &&
2746
(handle->set.httpreq == HTTPREQ_GET ||
2747
handle->set.httpreq == HTTPREQ_HEAD) &&
2748
handle->set.httpversion != CURL_HTTP_VERSION_1_0)
2731
2762
CURLcode Curl_addHandleToPipeline(struct SessionHandle *data,
2732
2763
struct curl_llist *pipeline)
2735
if(!IsPipeliningPossible(data)) {
2736
/* when not pipelined, there MUST be no handle in the list already */
2738
infof(data, "PIPE when no PIPE supposed!\n");
2741
2765
if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
2742
2766
return CURLE_OUT_OF_MEMORY;
2743
2767
return CURLE_OK;
2886
2910
check->data = data;
2887
2911
infof(data, "Connection #%ld seems to be dead!\n", i);
2889
Curl_disconnect(check); /* disconnect resources */
2913
/* disconnect resources */
2914
Curl_disconnect(check, /* dead_connection */ TRUE);
2890
2915
data->state.connc->connects[i]=NULL; /* nothing here */
2898
2923
struct SessionHandle* sh = gethandleathead(check->send_pipe);
2899
2924
struct SessionHandle* rh = gethandleathead(check->recv_pipe);
2901
if(!IsPipeliningPossible(sh))
2926
if(!IsPipeliningPossible(sh, check))
2905
if(!IsPipeliningPossible(rh))
2930
if(!IsPipeliningPossible(rh, check))
3468
static void llist_dtor(void *user, void *element)
3444
3476
* Allocate and initialize a new connectdata object.
3446
static struct connectdata *allocate_conn(void)
3478
static struct connectdata *allocate_conn(struct SessionHandle *data)
3448
struct connectdata *conn;
3450
conn = calloc(1, sizeof(struct connectdata));
3480
struct connectdata *conn = calloc(1, sizeof(struct connectdata));
3470
3500
/* Store creation time to help future close decision making */
3471
3501
conn->created = Curl_tvnow();
3503
conn->data = data; /* Setup the association between this connection
3504
and the SessionHandle */
3506
conn->proxytype = data->set.proxytype; /* type */
3508
#ifdef CURL_DISABLE_PROXY
3510
conn->bits.proxy = FALSE;
3511
conn->bits.httpproxy = FALSE;
3512
conn->bits.proxy_user_passwd = FALSE;
3513
conn->bits.tunnel_proxy = FALSE;
3515
#else /* CURL_DISABLE_PROXY */
3517
conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
3518
*data->set.str[STRING_PROXY]);
3519
conn->bits.httpproxy = (bool)(conn->bits.proxy &&
3520
(conn->proxytype == CURLPROXY_HTTP ||
3521
conn->proxytype == CURLPROXY_HTTP_1_0));
3522
conn->bits.proxy_user_passwd =
3523
(bool)(NULL != data->set.str[STRING_PROXYUSERNAME]);
3524
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
3526
#endif /* CURL_DISABLE_PROXY */
3528
conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERNAME]);
3529
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
3530
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
3532
conn->verifypeer = data->set.ssl.verifypeer;
3533
conn->verifyhost = data->set.ssl.verifyhost;
3535
conn->ip_version = data->set.ipver;
3537
if(data->multi && Curl_multi_canPipeline(data->multi) &&
3538
!conn->master_buffer) {
3539
/* Allocate master_buffer to be used for pipelining */
3540
conn->master_buffer = calloc(BUFSIZE, sizeof (char));
3541
if(!conn->master_buffer)
3545
/* Initialize the pipeline lists */
3546
conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3547
conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3548
conn->pend_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3549
conn->done_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
3550
if(!conn->send_pipe || !conn->recv_pipe || !conn->pend_pipe ||
3554
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
3555
conn->data_prot = PROT_CLEAR;
3560
Curl_llist_destroy(conn->send_pipe, NULL);
3561
Curl_llist_destroy(conn->recv_pipe, NULL);
3562
Curl_llist_destroy(conn->pend_pipe, NULL);
3563
Curl_llist_destroy(conn->done_pipe, NULL);
3564
Curl_safefree(conn->master_buffer);
3565
Curl_safefree(conn);
3476
3569
static CURLcode findprotocol(struct SessionHandle *data,
3604
3697
* The URL was badly formatted, let's try the browser-style _without_
3605
3698
* protocol specified like 'http://'.
3607
rc = sscanf(data->change.url, "%[^\n/]%[^\n]", conn->host.name, path);
3700
rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
3610
3703
* We couldn't even get this format.
4079
4165
*prox_portno = 0x0; /* cut off number from host name */
4080
4166
prox_portno ++;
4081
4167
/* now set the local port number */
4082
conn->port = atoi(prox_portno);
4168
conn->port = strtol(prox_portno, NULL, 10);
4085
4171
/* without a port number after the host name, some people seem to use
4580
4669
parts for checking against the already present connections. In order
4581
4670
to not have to modify everything at once, we allocate a temporary
4582
4671
connection data struct and fill in for comparison purposes. */
4672
conn = allocate_conn(data);
4584
conn = allocate_conn();
4675
return CURLE_OUT_OF_MEMORY;
4586
4677
/* We must set the return variable as soon as possible, so that our
4587
4678
parent can cleanup any possible allocs we may have done before
4589
4680
*in_connect = conn;
4592
return CURLE_OUT_OF_MEMORY;
4594
conn->data = data; /* Setup the association between this connection
4595
and the SessionHandle */
4597
conn->proxytype = data->set.proxytype; /* type */
4599
#ifdef CURL_DISABLE_PROXY
4601
conn->bits.proxy = FALSE;
4602
conn->bits.httpproxy = FALSE;
4603
conn->bits.proxy_user_passwd = FALSE;
4604
conn->bits.tunnel_proxy = FALSE;
4606
#else /* CURL_DISABLE_PROXY */
4608
conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
4609
*data->set.str[STRING_PROXY]);
4610
conn->bits.httpproxy = (bool)(conn->bits.proxy &&
4611
(conn->proxytype == CURLPROXY_HTTP ||
4612
conn->proxytype == CURLPROXY_HTTP_1_0));
4613
conn->bits.proxy_user_passwd =
4614
(bool)(NULL != data->set.str[STRING_PROXYUSERNAME]);
4615
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
4617
#endif /* CURL_DISABLE_PROXY */
4619
conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERNAME]);
4620
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
4621
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
4623
conn->verifypeer = data->set.ssl.verifypeer;
4624
conn->verifyhost = data->set.ssl.verifyhost;
4626
if(data->multi && Curl_multi_canPipeline(data->multi) &&
4627
!conn->master_buffer) {
4628
/* Allocate master_buffer to be used for pipelining */
4629
conn->master_buffer = calloc(BUFSIZE, sizeof (char));
4630
if(!conn->master_buffer)
4631
return CURLE_OUT_OF_MEMORY;
4634
/* Initialize the pipeline lists */
4635
conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
4636
conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
4637
conn->pend_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
4638
conn->done_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
4639
if(!conn->send_pipe || !conn->recv_pipe || !conn->pend_pipe ||
4641
return CURLE_OUT_OF_MEMORY;
4643
4682
/* This initing continues below, see the comment "Continue connectdata
4644
4683
* initialization here" */
4899
4938
infof(data, "Re-using existing connection! (#%ld) with host %s\n",
4900
4939
conn->connectindex,
4901
4940
conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
4902
/* copy this IP address to the common buffer for the easy handle so that
4903
the address can actually survice the removal of this connection. strcpy
4904
is safe since the target buffer is big enough to hold the largest
4905
possible IP address */
4906
strcpy(data->info.ip, conn->ip_addr_str);
5079
5112
if(code && *in_connect) {
5080
5113
/* We're not allowed to return failure with memory left allocated
5081
5114
in the connectdata struct, free those here */
5082
Curl_disconnect(*in_connect); /* close the connection */
5115
Curl_disconnect(*in_connect, FALSE); /* close the connection */
5083
5116
*in_connect = NULL; /* return a NULL */
5200
5233
if(data->set.reuse_forbid || conn->bits.close || premature ||
5201
5234
(-1 == conn->connectindex)) {
5202
CURLcode res2 = Curl_disconnect(conn); /* close the connection */
5235
CURLcode res2 = Curl_disconnect(conn, FALSE); /* close the connection */
5204
5237
/* If we had an error already, make sure we return that one. But
5205
5238
if we got a new error, return that. */