mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
CLOSESOCKETFUNCTION: added
Introduced the initial setup to allow closesocket callbacks by making sure sclose() is only ever called from one place in the libcurl source and still run all test cases fine.
This commit is contained in:
parent
d4e000906a
commit
b5d170b551
@ -341,6 +341,9 @@ typedef curl_socket_t
|
|||||||
curlsocktype purpose,
|
curlsocktype purpose,
|
||||||
struct curl_sockaddr *address);
|
struct curl_sockaddr *address);
|
||||||
|
|
||||||
|
typedef void
|
||||||
|
(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CURLIOE_OK, /* I/O operation successful */
|
CURLIOE_OK, /* I/O operation successful */
|
||||||
CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
|
CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
|
||||||
@ -1475,6 +1478,11 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
CINIT(TRANSFER_ENCODING, LONG, 207),
|
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 */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
@ -510,7 +510,7 @@ static CURLcode trynextip(struct connectdata *conn,
|
|||||||
*connected = FALSE;
|
*connected = FALSE;
|
||||||
|
|
||||||
if(sockindex != FIRSTSOCKET) {
|
if(sockindex != FIRSTSOCKET) {
|
||||||
sclose(fd_to_close);
|
Curl_closesocket(conn, fd_to_close);
|
||||||
return CURLE_COULDNT_CONNECT; /* no next */
|
return CURLE_COULDNT_CONNECT; /* no next */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,12 +525,12 @@ static CURLcode trynextip(struct connectdata *conn,
|
|||||||
/* store the new socket descriptor */
|
/* store the new socket descriptor */
|
||||||
conn->sock[sockindex] = sockfd;
|
conn->sock[sockindex] = sockfd;
|
||||||
conn->ip_addr = ai;
|
conn->ip_addr = ai;
|
||||||
sclose(fd_to_close);
|
Curl_closesocket(conn, fd_to_close);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
ai = ai->ai_next;
|
ai = ai->ai_next;
|
||||||
}
|
}
|
||||||
sclose(fd_to_close);
|
Curl_closesocket(conn, fd_to_close);
|
||||||
return CURLE_COULDNT_CONNECT;
|
return CURLE_COULDNT_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,7 +905,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
error = ERRNO;
|
error = ERRNO;
|
||||||
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
||||||
error, Curl_strerror(conn, error));
|
error, Curl_strerror(conn, error));
|
||||||
sclose(sockfd);
|
Curl_closesocket(conn, sockfd);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
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)
|
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
|
||||||
isconnected = TRUE;
|
isconnected = TRUE;
|
||||||
else if(error) {
|
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;
|
return CURLE_ABORTED_BY_CALLBACK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -942,7 +942,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
/* possibly bind the local end to an IP, interface or port */
|
/* possibly bind the local end to an IP, interface or port */
|
||||||
res = bindlocal(conn, sockfd, addr.family);
|
res = bindlocal(conn, sockfd, addr.family);
|
||||||
if(res) {
|
if(res) {
|
||||||
sclose(sockfd); /* close socket and bail out */
|
Curl_closesocket(conn, sockfd); /* close socket and bail out */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,7 +976,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
#endif
|
#endif
|
||||||
rc = waitconnect(conn, sockfd, timeout_ms);
|
rc = waitconnect(conn, sockfd, timeout_ms);
|
||||||
if(WAITCONN_ABORTED == rc) {
|
if(WAITCONN_ABORTED == rc) {
|
||||||
sclose(sockfd);
|
Curl_closesocket(conn, sockfd);
|
||||||
return CURLE_ABORTED_BY_CALLBACK;
|
return CURLE_ABORTED_BY_CALLBACK;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1017,7 +1017,7 @@ singleipconnect(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* connect failed or timed out */
|
/* connect failed or timed out */
|
||||||
sclose(sockfd);
|
Curl_closesocket(conn, sockfd);
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
@ -1163,3 +1163,16 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
|
|||||||
|
|
||||||
return sockfd;
|
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);
|
||||||
|
}
|
||||||
|
@ -68,7 +68,6 @@ void Curl_sndbufset(curl_socket_t sockfd);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
|
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
|
||||||
|
|
||||||
void Curl_persistconninfo(struct connectdata *conn);
|
void Curl_persistconninfo(struct connectdata *conn);
|
||||||
|
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
|
||||||
#endif
|
#endif
|
||||||
|
18
lib/ftp.c
18
lib/ftp.c
@ -357,7 +357,7 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
|
|||||||
|
|
||||||
s=accept(sock, (struct sockaddr *) &add, &size);
|
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) {
|
if(CURL_SOCKET_BAD == s) {
|
||||||
failf(data, "Error accept()ing server connect");
|
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)) {
|
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
|
||||||
failf(data, "getsockname() failed: %s",
|
failf(data, "getsockname() failed: %s",
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
sclose(portsock);
|
Curl_closesocket(conn, portsock);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
port = port_min;
|
port = port_min;
|
||||||
@ -921,7 +921,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
else if(error != EADDRINUSE && error != EACCES) {
|
else if(error != EADDRINUSE && error != EACCES) {
|
||||||
failf(data, "bind(port=%hu) failed: %s", port,
|
failf(data, "bind(port=%hu) failed: %s", port,
|
||||||
Curl_strerror(conn, error) );
|
Curl_strerror(conn, error) );
|
||||||
sclose(portsock);
|
Curl_closesocket(conn, portsock);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
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*/
|
/* maybe all ports were in use already*/
|
||||||
if(port > port_max) {
|
if(port > port_max) {
|
||||||
failf(data, "bind() failed, we ran out of ports!");
|
failf(data, "bind() failed, we ran out of ports!");
|
||||||
sclose(portsock);
|
Curl_closesocket(conn, portsock);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
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)) {
|
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
|
||||||
failf(data, "getsockname() failed: %s",
|
failf(data, "getsockname() failed: %s",
|
||||||
Curl_strerror(conn, SOCKERRNO) );
|
Curl_strerror(conn, SOCKERRNO) );
|
||||||
sclose(portsock);
|
Curl_closesocket(conn, portsock);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,7 +952,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
|
|
||||||
if(listen(portsock, 1)) {
|
if(listen(portsock, 1)) {
|
||||||
failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
|
failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
|
||||||
sclose(portsock);
|
Curl_closesocket(conn, portsock);
|
||||||
return CURLE_FTP_PORT_FAILED;
|
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
|
the cleanup function will close it in case we fail before the true
|
||||||
secondary stuff is made */
|
secondary stuff is made */
|
||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = portsock;
|
conn->sock[SECONDARYSOCKET] = portsock;
|
||||||
|
|
||||||
/* this tcpconnect assignment below is a hackish work-around to make the
|
/* 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 */
|
still requested to use SSL */
|
||||||
}
|
}
|
||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
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)) {
|
if(result && (conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD)) {
|
||||||
/* Failure detected, close the second socket if it was created already */
|
/* 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;
|
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ bool Curl_ipv6works(void)
|
|||||||
ipv6_works = 0;
|
ipv6_works = 0;
|
||||||
else {
|
else {
|
||||||
ipv6_works = 1;
|
ipv6_works = 1;
|
||||||
sclose(s);
|
Curl_closesocket(NULL, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (ipv6_works>0)?TRUE:FALSE;
|
return (ipv6_works>0)?TRUE:FALSE;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "rawstr.h"
|
#include "rawstr.h"
|
||||||
#include "progress.h"
|
#include "progress.h"
|
||||||
#include "non-ascii.h"
|
#include "non-ascii.h"
|
||||||
|
#include "connect.h"
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@ -482,7 +483,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
|
|||||||
|
|
||||||
if(closeConnection && data->req.newurl) {
|
if(closeConnection && data->req.newurl) {
|
||||||
/* Connection closed by server. Don't use it anymore */
|
/* 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;
|
conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,6 @@ struct timeval {
|
|||||||
# define sclose(x) close((x))
|
# define sclose(x) close((x))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Uppercase macro versions of ANSI/ISO is*() functions/macros which
|
* Uppercase macro versions of ANSI/ISO is*() functions/macros which
|
||||||
* avoid negative number inputs with argument byte codes > 127.
|
* avoid negative number inputs with argument byte codes > 127.
|
||||||
|
@ -2185,7 +2185,7 @@ static CURLcode Curl_do_perform(struct SessionHandle *data)
|
|||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
||||||
/* if we failed anywhere, we must clean up the secondary socket if
|
/* if we failed anywhere, we must clean up the secondary socket if
|
||||||
it was used */
|
it was used */
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
lib/url.c
24
lib/url.c
@ -2232,6 +2232,21 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
data->set.opensocket_client = va_arg(param, void *);
|
data->set.opensocket_client = va_arg(param, void *);
|
||||||
break;
|
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:
|
case CURLOPT_SSL_SESSIONID_CACHE:
|
||||||
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
|
data->set.ssl.sessionid = (bool)(0 != va_arg(param, long));
|
||||||
break;
|
break;
|
||||||
@ -2524,9 +2539,9 @@ static void conn_free(struct connectdata *conn)
|
|||||||
|
|
||||||
/* close possibly still open sockets */
|
/* close possibly still open sockets */
|
||||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
|
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
|
||||||
sclose(conn->sock[FIRSTSOCKET]);
|
Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
|
||||||
|
|
||||||
Curl_safefree(conn->user);
|
Curl_safefree(conn->user);
|
||||||
Curl_safefree(conn->passwd);
|
Curl_safefree(conn->passwd);
|
||||||
@ -3538,6 +3553,11 @@ static struct connectdata *allocate_conn(struct SessionHandle *data)
|
|||||||
conn->localportrange = data->set.localportrange;
|
conn->localportrange = data->set.localportrange;
|
||||||
conn->localport = data->set.localport;
|
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;
|
return conn;
|
||||||
error:
|
error:
|
||||||
|
|
||||||
|
@ -737,6 +737,9 @@ struct connectdata {
|
|||||||
and a HTTP proxy may in fact respond using chunked encoding */
|
and a HTTP proxy may in fact respond using chunked encoding */
|
||||||
struct Curl_chunker chunk;
|
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
|
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
|
TRUE this handle is being used by an easy handle and cannot
|
||||||
be used by any other easy handle without careful
|
be used by any other easy handle without careful
|
||||||
@ -1369,6 +1372,9 @@ struct UserDefined {
|
|||||||
the address and opening the
|
the address and opening the
|
||||||
socket */
|
socket */
|
||||||
void* opensocket_client;
|
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 */
|
void *seek_client; /* pointer to pass to the seek callback */
|
||||||
/* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
|
/* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
|
||||||
|
Loading…
Reference in New Issue
Block a user