]> granicus.if.org Git - curl/commitdiff
Detect socket errors in GnuTLS on Windows
authorMatthias Bolte <photron@users.sourceforge.net>
Fri, 19 Nov 2010 21:31:34 +0000 (13:31 -0800)
committerDan Fandrich <dan@coneharvesters.com>
Fri, 19 Nov 2010 21:34:07 +0000 (13:34 -0800)
On Windows, translate WSAGetLastError() to errno values as GNU
TLS does it internally, too. This is necessary because send() and
recv() on Windows don't set errno when they fail but GNU TLS
expects a proper errno value.

Bug: http://curl.haxx.se/bug/view.cgi?id=3110991

RELEASE-NOTES
lib/gtls.c

index f23e2f3d5681a18c6080725a35a741f5b1e2594c..6e783c2c7354689b1b921e4c3ed5b5e3d1b612ff 100644 (file)
@@ -31,6 +31,7 @@ This release includes the following bugfixes:
  o krb5: Use GSS_ERROR to check for error
  o TFTP: resend the correct data
  o configure: fix autoconf 2.68 warning: no AC_LANG_SOURCE call detected
+ o GnuTLS: now detects socket errors on Windows
 
 This release includes the following known bugs:
 
@@ -41,6 +42,6 @@ advice from friends like these:
 
  Dan Fandrich, Guenter Knauf, Pat Ray, Hongli Lai, Kamil Dudka,
  Stefan Tomanek, Alfred Gebert, Yang Tse, Julien Chaffraix, Adam Light,
- Rutger Hofman
+ Rutger Hofman, Matthias Bolte
 
         Thanks! (and sorry if I forgot to mention someone)
index 84410eda8108153479c6a2f69e985d47fb268869..93bb91de6cc331322d43d1f512d397908da3385e 100644 (file)
@@ -85,15 +85,52 @@ static bool gtls_inited = FALSE;
  * We use custom functions rather than the GNU TLS defaults because it allows
  * us to get specific about the fourth "flags" argument, and to use arbitrary
  * private data with gnutls_transport_set_ptr if we wish.
+ *
+ * On Windows translate WSAGetLastError() to errno values as GNU TLS does it
+ * internally too. This is necessary because send() and recv() on Windows
+ * don't set errno when they fail but GNU TLS expects a proper errno value.
+ *
+ * Use gnutls_transport_set_global_errno() like the GNU TLS documentation
+ * suggests to avoid problems with different errno variables when GNU TLS and
+ * curl are linked to different versions of msvcrt.dll.
  */
+#ifdef USE_WINSOCK
+static void translate_wsa_to_errno(void)
+{
+  switch(WSAGetLastError()) {
+  case WSAEWOULDBLOCK:
+    gnutls_transport_set_global_errno(EAGAIN);
+    break;
+  case WSAEINTR:
+    gnutls_transport_set_global_errno(EINTR);
+    break;
+  default:
+    gnutls_transport_set_global_errno(EIO);
+    break;
+  }
+}
+#endif
+
 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
 {
-  return swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+  ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#ifdef USE_WINSOCK
+  if(ret < 0) {
+    translate_wsa_to_errno();
+  }
+#endif
+  return ret;
 }
 
 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
 {
-  return sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+  ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
+#ifdef USE_WINSOCK
+  if(ret < 0) {
+    translate_wsa_to_errno();
+  }
+#endif
+  return ret;
 }
 
 /* Curl_gtls_init()