aboutsummaryrefslogtreecommitdiff
path: root/lib/url.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2011-03-25 16:00:41 +0100
committerDaniel Stenberg <daniel@haxx.se>2011-03-25 16:03:37 +0100
commit11c2db2aa2a8ce5f3c151d6075066283e65bfd85 (patch)
tree1d93f381909ae59d57b63b5459344c03aef32af2 /lib/url.c
parentd02f444759eab5901a3d5439cf00657669b198c7 (diff)
fix: re-use of bound connections
When asked to bind the local end of a connection when doing a request, the code will now disqualify other existing connections from re-use even if they are connected to the correct remote host. This will also affect which connections that can be used for pipelining, so that only connections that aren't bound or bound to the same device/port you're asking for will be considered.
Diffstat (limited to 'lib/url.c')
-rw-r--r--lib/url.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/lib/url.c b/lib/url.c
index 106d4e7ec..25f03b7e2 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2606,7 +2606,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->async.hostname);
Curl_safefree(conn->async.os_specific);
#endif
-
+ Curl_safefree(conn->localdev);
Curl_free_ssl_config(&conn->ssl_config);
free(conn); /* free all the connection oriented data */
@@ -2987,6 +2987,25 @@ ConnectionExists(struct SessionHandle *data,
in use so we skip it */
continue;
+ if(needle->localdev || needle->localport) {
+ /* If we are bound to a specific local end (IP+port), we must not re-use
+ a random other one, although if we didn't ask for a particular one we
+ can reuse one that was bound.
+
+ This comparison is a bit rough and too strict. Since the input
+ parameters can be specified in numerous ways and still end up the
+ same it would take a lot of processing to make it really accurate.
+ Instead, this matching will assume that re-uses of bound connections
+ will most likely also re-use the exact same binding parameters and
+ missing out a few edge cases shouldn't hurt anyone very much.
+ */
+ if((check->localport != needle->localport) ||
+ (check->localportrange != needle->localportrange) ||
+ !check->localdev ||
+ strcmp(check->localdev, needle->localdev))
+ continue;
+ }
+
if(!needle->bits.httpproxy || needle->handler->flags&PROTOPT_SSL ||
(needle->bits.httpproxy && check->bits.httpproxy &&
needle->bits.tunnel_proxy && check->bits.tunnel_proxy &&
@@ -3568,13 +3587,24 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
conn->data_prot = PROT_CLEAR;
#endif
+ /* Store the local bind parameters that will be used for this connection */
+ if(data->set.str[STRING_DEVICE]) {
+ conn->localdev = strdup(data->set.str[STRING_DEVICE]);
+ if(!conn->localdev)
+ goto error;
+ }
+ conn->localportrange = data->set.localportrange;
+ conn->localport = data->set.localport;
+
return conn;
error:
+
Curl_llist_destroy(conn->send_pipe, NULL);
Curl_llist_destroy(conn->recv_pipe, NULL);
Curl_llist_destroy(conn->pend_pipe, NULL);
Curl_llist_destroy(conn->done_pipe, NULL);
Curl_safefree(conn->master_buffer);
+ Curl_safefree(conn->localdev);
Curl_safefree(conn);
return NULL;
}