David McCreedy provided a fix for CURLINFO_LASTSOCKET that does extended
authorDaniel Stenberg <daniel@haxx.se>
Wed, 10 May 2006 22:17:42 +0000 (22:17 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 10 May 2006 22:17:42 +0000 (22:17 +0000)
checks on the to-be-returned socket to make sure it truly seems to be alive
and well. For SSL connection it (only) uses OpenSSL functions.

CHANGES
RELEASE-NOTES
lib/getinfo.c
lib/sslgen.c
lib/sslgen.h
lib/ssluse.c
lib/ssluse.h

diff --git a/CHANGES b/CHANGES
index c700e2f..9f08a30 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@
 
                                   Changelog
 
+Daniel (11 May 2006)
+- David McCreedy provided a fix for CURLINFO_LASTSOCKET that does extended
+  checks on the to-be-returned socket to make sure it truly seems to be alive
+  and well. For SSL connection it (only) uses OpenSSL functions.
+
 Daniel (10 May 2006)
 - Fixed DICT in two aspects:
 
index 3d42c7b..cebc62a 100644 (file)
@@ -11,6 +11,7 @@ Curl and libcurl 7.15.4
 
 This release includes the following changes:
 
+ o CURLINFO_LASTSOCKET returned sockets are now checked more before returned
  o curl-config got a --checkfor option to compare version numbers
  o line end conversions for FTP ASCII transfers
  o curl_multi_socket() API added (still mostly untested)
index c7b4cfa..d74fbcf 100644 (file)
@@ -75,6 +75,8 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
   double *param_doublep=NULL;
   char **param_charp=NULL;
   struct curl_slist **param_slistp=NULL;
+  char buf;
+
   va_start(arg, info);
 
   switch(info&CURLINFO_TYPEMASK) {
@@ -197,9 +199,23 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
     break;
   case CURLINFO_LASTSOCKET:
     if((data->state.lastconnect != -1) &&
-       (data->state.connects[data->state.lastconnect] != NULL))
+       (data->state.connects[data->state.lastconnect] != NULL)) {
       *param_longp = data->state.connects[data->state.lastconnect]->
         sock[FIRSTSOCKET];
+      /* we have a socket connected, let's determine if the server shut down */
+      /* determine if ssl */
+      if(data->state.connects[data->state.lastconnect]->protocol & PROT_SSL) {
+        /* use the SSL context */
+        if (!Curl_ssl_check_cxn(data->state.connects[data->state.lastconnect]))
+          *param_longp = -1;   /* FIN received */
+      }
+      else {
+        /* use the socket */
+        if(recv((int)data->state.connects[data->state.lastconnect]->
+                sock[FIRSTSOCKET], (void*)&buf, 1, MSG_PEEK) == 0)
+          *param_longp = -1;   /* FIN received */
+      }
+    }
     else
       *param_longp = -1;
     break;
index a4c9410..f8f8ec6 100644 (file)
@@ -554,3 +554,21 @@ size_t Curl_ssl_version(char *buffer, size_t size)
 #endif /* USE_SSLEAY */
 }
 
+
+/*
+ * This function tries to determine connection status.
+ *
+ * Return codes:
+ *     1 means the connection is still in place
+ *     0 means the connection has been closed
+ *    -1 means the connection status is unknown
+ */
+int Curl_ssl_check_cxn(struct connectdata *conn)
+{
+#ifdef USE_SSLEAY
+  return Curl_ossl_check_cxn(conn);
+#else
+  /* TODO: we lack implementation of this for GnuTLS */
+  return -1; /* connection status unknown */
+#endif /* USE_SSLEAY */
+}
index 6b63c36..cd1b663 100644 (file)
@@ -67,6 +67,8 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data);
 
 size_t Curl_ssl_version(char *buffer, size_t size);
 
+int Curl_ssl_check_cxn(struct connectdata *conn);
+
 #if !defined(USE_SSL) && !defined(SSLGEN_C)
 /* set up blank macros for none-SSL builds */
 #define Curl_ssl_close_all(x)
index 503f7ef..ab17700 100644 (file)
@@ -584,6 +584,29 @@ void Curl_ossl_cleanup(void)
 #endif
 }
 
+/*
+ * This function uses SSL_peek to determine connection status.
+ *
+ * Return codes:
+ *     1 means the connection is still in place
+ *     0 means the connection has been closed
+ *    -1 means the connection status is unknown
+ */
+int Curl_ossl_check_cxn(struct connectdata *conn)
+{
+  int rc;
+  char buf;
+
+  rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1);
+  if (rc > 0)
+    return 1; /* connection still in place */
+
+  if (rc == 0)
+    return 0; /* connection has been closed */
+
+  return -1; /* connection status unknown */
+}
+
 #endif /* USE_SSLEAY */
 
 /* Selects an OpenSSL crypto engine
index 1bbc2cc..5cc2f70 100644 (file)
@@ -64,4 +64,6 @@ ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
 
 size_t Curl_ossl_version(char *buffer, size_t size);
 
+int Curl_ossl_check_cxn(struct connectdata *cxn);
+
 #endif