]> granicus.if.org Git - curl/commitdiff
CLOSESOCKETFUNCTION: added
authorDaniel Stenberg <daniel@haxx.se>
Mon, 16 May 2011 21:46:43 +0000 (23:46 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 18 May 2011 20:56:46 +0000 (22:56 +0200)
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.

include/curl/curl.h
lib/connect.c
lib/connect.h
lib/ftp.c
lib/hostip6.c
lib/http_proxy.c
lib/setup_once.h
lib/transfer.c
lib/url.c
lib/urldata.h

index 09f305466cacbc78fce49dc76d05c39f72d35517..e4fbfdf8951760ce612cd77f8316c13a33826dcb 100644 (file)
@@ -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;
 
index 732fc6721330ff93e6754479c7308f630e9c4380..2802c5d61d42ab170aadeb2fa4f5bce4b335c508 100644 (file)
@@ -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);
+}
index 0720085c2f3e7bf5fdec45331a5aa1f4f22503b2..3df9d970e801abb760c1ecdb5afcc06faa2253c6 100644 (file)
@@ -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
index a0e9280875e321433c32d18e6536cbb695664130..0cf19a882a8cc26993de3cd6ccdacba64d06e89c 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -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;
   }
index b847f595383638452d960aef204a48c1282de611..b944401c59686afb5176822b46bac4e7560bf575 100644 (file)
@@ -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;
index 523f4aea8df0c6d3f0086f82f62bda1cf58e5636..08ca1006fe17d6126da18119ea5e582394ddc45c 100644 (file)
@@ -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;
       }
index 1b6fde5278bd39ff7aeabcb1bbfa2a9ebe5dfcc7..b449807db31be7654f4d610e592a5c2f1089fd1e 100644 (file)
@@ -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.
index ddbbe529be495b5f51447e47ebc12990ac73a851..59d4792fd67eb904eff27d9eee1dffdeadb67ca2 100644 (file)
@@ -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;
           }
         }
index 038a02d4352d890760705ea81dac6d49ae5435ed..b0b2d8f1303e3585cda92f87e619bea4088ec3cf 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -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:
 
index f4b4bcc6c940a9f033432ca15dd66c2ebd51fc59..6d0de89af4aa42c52f1e571174a3e448deb41648 100644 (file)
@@ -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 */