Skip to content

Commit

Permalink
fix: re-use of bound connections
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bagder committed Mar 25, 2011
1 parent d02f444 commit 11c2db2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
2 changes: 0 additions & 2 deletions TODO-RELEASE
@@ -1,8 +1,6 @@
To be addressed in 7.21.5
=========================

272 - re-using connections bound to local port

275 - Introduce a way to avoid sending USER for FTP connections

278 - "Configure $as_echo does not work"
Expand Down
32 changes: 31 additions & 1 deletion lib/url.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 10 additions & 0 deletions lib/urldata.h
Expand Up @@ -936,6 +936,16 @@ struct connectdata {

long verifypeer;
long verifyhost;

/* When this connection is created, store the conditions for the local end
bind. This is stored before the actual bind and before any connection is
made and will serve the purpose of being used for comparison reasons so
that subsequent bound-requested connections aren't accidentally re-using
wrong connections. */
char *localdev;
unsigned short localport;
int localportrange;

};

/* The end of connectdata. */
Expand Down

0 comments on commit 11c2db2

Please sign in to comment.