aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE-NOTES3
-rw-r--r--lib/gtls.c41
2 files changed, 41 insertions, 3 deletions
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index f23e2f3d5..6e783c2c7 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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)
diff --git a/lib/gtls.c b/lib/gtls.c
index 84410eda8..93bb91de6 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -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()