diff options
-rw-r--r-- | include/curl/curl.h | 8 | ||||
-rw-r--r-- | lib/connect.c | 29 | ||||
-rw-r--r-- | lib/connect.h | 3 | ||||
-rw-r--r-- | lib/ftp.c | 18 | ||||
-rw-r--r-- | lib/hostip6.c | 2 | ||||
-rw-r--r-- | lib/http_proxy.c | 3 | ||||
-rw-r--r-- | lib/setup_once.h | 1 | ||||
-rw-r--r-- | lib/transfer.c | 2 | ||||
-rw-r--r-- | lib/url.c | 24 | ||||
-rw-r--r-- | lib/urldata.h | 6 |
10 files changed, 71 insertions, 25 deletions
diff --git a/include/curl/curl.h b/include/curl/curl.h index 09f305466..e4fbfdf89 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -341,6 +341,9 @@ typedef curl_socket_t curlsocktype purpose, struct curl_sockaddr *address); +typedef void +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + typedef enum { CURLIOE_OK, /* I/O operation successful */ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ @@ -1475,6 +1478,11 @@ typedef enum { */ CINIT(TRANSFER_ENCODING, LONG, 207), + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/connect.c b/lib/connect.c index 732fc6721..2802c5d61 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -510,7 +510,7 @@ static CURLcode trynextip(struct connectdata *conn, *connected = FALSE; if(sockindex != FIRSTSOCKET) { - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_COULDNT_CONNECT; /* no next */ } @@ -525,12 +525,12 @@ static CURLcode trynextip(struct connectdata *conn, /* store the new socket descriptor */ conn->sock[sockindex] = sockfd; conn->ip_addr = ai; - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_OK; } ai = ai->ai_next; } - sclose(fd_to_close); + Curl_closesocket(conn, fd_to_close); return CURLE_COULDNT_CONNECT; } @@ -905,7 +905,7 @@ singleipconnect(struct connectdata *conn, error = ERRNO; failf(data, "sa_addr inet_ntop() failed with errno %d: %s", error, Curl_strerror(conn, error)); - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_OK; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); @@ -934,7 +934,7 @@ singleipconnect(struct connectdata *conn, if(error == CURL_SOCKOPT_ALREADY_CONNECTED) isconnected = TRUE; else if(error) { - sclose(sockfd); /* close the socket and bail out */ + Curl_closesocket(conn, sockfd); /* close the socket and bail out */ return CURLE_ABORTED_BY_CALLBACK; } } @@ -942,7 +942,7 @@ singleipconnect(struct connectdata *conn, /* possibly bind the local end to an IP, interface or port */ res = bindlocal(conn, sockfd, addr.family); if(res) { - sclose(sockfd); /* close socket and bail out */ + Curl_closesocket(conn, sockfd); /* close socket and bail out */ return res; } @@ -976,7 +976,7 @@ singleipconnect(struct connectdata *conn, #endif rc = waitconnect(conn, sockfd, timeout_ms); if(WAITCONN_ABORTED == rc) { - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_ABORTED_BY_CALLBACK; } break; @@ -1017,7 +1017,7 @@ singleipconnect(struct connectdata *conn, } /* connect failed or timed out */ - sclose(sockfd); + Curl_closesocket(conn, sockfd); return CURLE_OK; } @@ -1163,3 +1163,16 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, return sockfd; } + +/* + * Close a socket. + * + * 'conn' can be NULL, beware! + */ +int Curl_closesocket(struct connectdata *conn, + curl_socket_t sock) +{ + (void)conn; + + return sclose(sock); +} diff --git a/lib/connect.h b/lib/connect.h index 0720085c2..3df9d970e 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -68,7 +68,6 @@ void Curl_sndbufset(curl_socket_t sockfd); #endif void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); - void Curl_persistconninfo(struct connectdata *conn); - +int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); #endif @@ -357,7 +357,7 @@ static CURLcode AllowServerConnect(struct connectdata *conn) s=accept(sock, (struct sockaddr *) &add, &size); } - sclose(sock); /* close the first socket */ + Curl_closesocket(conn, sock); /* close the first socket */ if(CURL_SOCKET_BAD == s) { failf(data, "Error accept()ing server connect"); @@ -912,7 +912,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", Curl_strerror(conn, SOCKERRNO) ); - sclose(portsock); + Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } port = port_min; @@ -921,7 +921,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, else if(error != EADDRINUSE && error != EACCES) { failf(data, "bind(port=%hu) failed: %s", port, Curl_strerror(conn, error) ); - sclose(portsock); + Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } } @@ -934,7 +934,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* maybe all ports were in use already*/ if(port > port_max) { failf(data, "bind() failed, we ran out of ports!"); - sclose(portsock); + Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -944,7 +944,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { failf(data, "getsockname() failed: %s", Curl_strerror(conn, SOCKERRNO) ); - sclose(portsock); + Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -952,7 +952,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(listen(portsock, 1)) { failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO)); - sclose(portsock); + Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1038,7 +1038,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, the cleanup function will close it in case we fail before the true secondary stuff is made */ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - sclose(conn->sock[SECONDARYSOCKET]); + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = portsock; /* this tcpconnect assignment below is a hackish work-around to make the @@ -3100,7 +3100,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, still requested to use SSL */ } if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { - sclose(conn->sock[SECONDARYSOCKET]); + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; } } @@ -4080,7 +4080,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) { /* Failure detected, close the second socket if it was created already */ - sclose(conn->sock[SECONDARYSOCKET]); + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; return result; } diff --git a/lib/hostip6.c b/lib/hostip6.c index b847f5953..b944401c5 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -125,7 +125,7 @@ bool Curl_ipv6works(void) ipv6_works = 0; else { ipv6_works = 1; - sclose(s); + Curl_closesocket(NULL, s); } } return (ipv6_works>0)?TRUE:FALSE; diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 523f4aea8..08ca1006f 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -37,6 +37,7 @@ #include "rawstr.h" #include "progress.h" #include "non-ascii.h" +#include "connect.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -482,7 +483,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(closeConnection && data->req.newurl) { /* Connection closed by server. Don't use it anymore */ - sclose(conn->sock[sockindex]); + Curl_closesocket(conn, conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; break; } diff --git a/lib/setup_once.h b/lib/setup_once.h index 1b6fde527..b449807db 100644 --- a/lib/setup_once.h +++ b/lib/setup_once.h @@ -240,7 +240,6 @@ struct timeval { # define sclose(x) close((x)) #endif - /* * Uppercase macro versions of ANSI/ISO is*() functions/macros which * avoid negative number inputs with argument byte codes > 127. diff --git a/lib/transfer.c b/lib/transfer.c index ddbbe529b..59d4792fd 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -2185,7 +2185,7 @@ static CURLcode Curl_do_perform(struct SessionHandle *data) if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { /* if we failed anywhere, we must clean up the secondary socket if it was used */ - sclose(conn->sock[SECONDARYSOCKET]); + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; } } @@ -2232,6 +2232,21 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.opensocket_client = va_arg(param, void *); break; + case CURLOPT_CLOSESOCKETFUNCTION: + /* + * close socket callback function: called instead of close() + * when shutting down a connection + */ + data->set.fclosesocket = va_arg(param, curl_closesocket_callback); + break; + + case CURLOPT_CLOSESOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.closesocket_client = va_arg(param, void *); + break; + case CURLOPT_SSL_SESSIONID_CACHE: data->set.ssl.sessionid = (bool)(0 != va_arg(param, long)); break; @@ -2524,9 +2539,9 @@ static void conn_free(struct connectdata *conn) /* close possibly still open sockets */ if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) - sclose(conn->sock[SECONDARYSOCKET]); + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET]) - sclose(conn->sock[FIRSTSOCKET]); + Curl_closesocket(conn, conn->sock[FIRSTSOCKET]); Curl_safefree(conn->user); Curl_safefree(conn->passwd); @@ -3538,6 +3553,11 @@ static struct connectdata *allocate_conn(struct SessionHandle *data) conn->localportrange = data->set.localportrange; conn->localport = data->set.localport; + /* the close socket stuff needs to be copied to the connection struct as + it may live on without (this specific) SessionHandle */ + conn->fclosesocket = data->set.fclosesocket; + conn->closesocket_client = data->set.closesocket_client; + return conn; error: diff --git a/lib/urldata.h b/lib/urldata.h index f4b4bcc6c..6d0de89af 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -737,6 +737,9 @@ struct connectdata { and a HTTP proxy may in fact respond using chunked encoding */ struct Curl_chunker chunk; + curl_closesocket_callback fclosesocket; /* function closing the socket(s) */ + void *closesocket_client; + bool inuse; /* This is a marker for the connection cache logic. If this is TRUE this handle is being used by an easy handle and cannot be used by any other easy handle without careful @@ -1369,6 +1372,9 @@ struct UserDefined { the address and opening the socket */ void* opensocket_client; + curl_closesocket_callback fclosesocket; /* function for closing the + socket */ + void* closesocket_client; void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ |