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 */
*/
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;
*connected = FALSE;
if(sockindex != FIRSTSOCKET) {
- sclose(fd_to_close);
+ Curl_closesocket(conn, fd_to_close);
return CURLE_COULDNT_CONNECT; /* no next */
}
/* 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;
}
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);
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;
}
}
/* 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;
}
#endif
rc = waitconnect(conn, sockfd, timeout_ms);
if(WAITCONN_ABORTED == rc) {
- sclose(sockfd);
+ Curl_closesocket(conn, sockfd);
return CURLE_ABORTED_BY_CALLBACK;
}
break;
}
/* connect failed or timed out */
- sclose(sockfd);
+ Curl_closesocket(conn, sockfd);
return CURLE_OK;
}
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);
+}
#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
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");
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;
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;
}
}
/* 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;
}
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;
}
if(listen(portsock, 1)) {
failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
- sclose(portsock);
+ Curl_closesocket(conn, portsock);
return CURLE_FTP_PORT_FAILED;
}
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
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;
}
}
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;
}
ipv6_works = 0;
else {
ipv6_works = 1;
- sclose(s);
+ Curl_closesocket(NULL, s);
}
}
return (ipv6_works>0)?TRUE:FALSE;
#include "rawstr.h"
#include "progress.h"
#include "non-ascii.h"
+#include "connect.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
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;
}
# 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.
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;
}
}
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;
/* 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);
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:
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
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 */