diff --git a/CHANGES b/CHANGES index f1a644fd4..e3ad05c69 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,15 @@ Changelog +Daniel Stenberg (8 May 2009) +- Constantine Sapuntzakis fixed bug report #2784055 + (http://curl.haxx.se/bug/view.cgi?id=2784055) identifying a problem to + connect to SOCKS proxies when using the multi interface. It turned out to + almost not work at all previously. We need to wait for the TCP connect to + be properly verified before doing the SOCKS magic. + + There's still a flaw in the FTP code for this. + Daniel Stenberg (7 May 2009) - Made the SO_SNDBUF setting for the data connection socket for ftp uploads as well. See change 28 Apr 2009. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 31f89956a..3770f15be 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -42,6 +42,7 @@ This release includes the following bugfixes: o Rejected SSL session ids are killed properly (for OpenSSL and GnuTLS builds) o Deal with the TFTP OACK packet o fixed roff mistakes in man pages + o use SOCKS proxy with the multi interface This release includes the following known bugs: diff --git a/lib/multi.c b/lib/multi.c index 95d386f85..c5712f619 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1055,9 +1055,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, easy->result = Curl_is_connected(easy->easy_conn, FIRSTSOCKET, &connected); - if(connected) - easy->result = Curl_protocol_connect(easy->easy_conn, - &protocol_connect); + if(connected) { + /* see if we need to do any proxy magic first once we connected */ + easy->result = Curl_connected_proxy(easy->easy_conn); + + if(!easy->result) + /* if everything is still fine we do the protocol-specific connect + setup */ + easy->result = Curl_protocol_connect(easy->easy_conn, + &protocol_connect); + } if(CURLE_OK != easy->result) { /* failure detected */ diff --git a/lib/url.c b/lib/url.c index f177b7ffe..684358067 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2814,6 +2814,47 @@ ConnectionStore(struct SessionHandle *data, return i; } +/* after a TCP connection to the proxy has been verified, this function does + the next magic step. + + Note: this function (and its sub-functions) calls failf() + +*/ +CURLcode Curl_connected_proxy(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct SessionHandle *data = conn->data; + + switch(data->set.proxytype) { +#ifndef CURL_DISABLE_PROXY + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, + conn->host.name, conn->remote_port, + FIRSTSOCKET, conn); + break; + case CURLPROXY_SOCKS4: + result = Curl_SOCKS4(conn->proxyuser, conn->host.name, + conn->remote_port, FIRSTSOCKET, conn, FALSE); + break; + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->proxyuser, conn->host.name, + conn->remote_port, FIRSTSOCKET, conn, TRUE); + break; +#endif /* CURL_DISABLE_PROXY */ + case CURLPROXY_HTTP: + case CURLPROXY_HTTP_1_0: + /* do nothing here. handled later. */ + break; + default: + failf(data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + break; + } /* switch proxytype */ + + return result; +} + static CURLcode ConnectPlease(struct SessionHandle *data, struct connectdata *conn, struct Curl_dns_entry *hostaddr, @@ -2838,39 +2879,14 @@ static CURLcode ConnectPlease(struct SessionHandle *data, &addr, connected); if(CURLE_OK == result) { - /* All is cool, then we store the current information */ + /* All is cool, we store the current information */ conn->dns_entry = hostaddr; conn->ip_addr = addr; - switch(data->set.proxytype) { -#ifndef CURL_DISABLE_PROXY - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, - conn->host.name, conn->remote_port, - FIRSTSOCKET, conn); - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, conn->host.name, - conn->remote_port, FIRSTSOCKET, conn, FALSE); - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, conn->host.name, - conn->remote_port, FIRSTSOCKET, conn, TRUE); - break; -#endif /* CURL_DISABLE_PROXY */ - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } /* switch proxytype */ - } /* if result is ok */ - - if(result) + if(*connected) + result = Curl_connected_proxy(conn); + } + else *connected = FALSE; /* mark it as not connected */ return result; @@ -4761,8 +4777,6 @@ CURLcode Curl_done(struct connectdata **connp, Curl_expire(data, 0); /* stop timer */ - Curl_getoff_all_pipelines(data, conn); - if(conn->bits.done || (conn->send_pipe->size + conn->recv_pipe->size != 0 && !data->set.reuse_forbid && @@ -4773,6 +4787,8 @@ CURLcode Curl_done(struct connectdata **connp, conn->bits.done = TRUE; /* called just now! */ + Curl_getoff_all_pipelines(data, conn); + /* Cleanup possible redirect junk */ if(data->req.newurl) { free(data->req.newurl); diff --git a/lib/url.h b/lib/url.h index 7e22b7397..35900812f 100644 --- a/lib/url.h +++ b/lib/url.h @@ -85,4 +85,6 @@ void Curl_reset_reqproto(struct connectdata *conn); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi service */ +CURLcode Curl_connected_proxy(struct connectdata *conn); + #endif