gtls: define and use gtls_EAGAIN, gtls_EINTR and gtls_EIO.

Winsock builds clobber some errno.h defines in setup_once.
This commit is contained in:
Yang Tse 2010-11-20 05:00:12 +01:00
parent 46041ee918
commit 13d537e404

View File

@ -78,6 +78,7 @@ static void tls_log_func(int level, const char *str)
} }
#endif #endif
static bool gtls_inited = FALSE; static bool gtls_inited = FALSE;
/* /*
* Custom push and pull callback functions used by GNU TLS to read and write * Custom push and pull callback functions used by GNU TLS to read and write
* to the socket. These functions are simple wrappers to send() and recv() * to the socket. These functions are simple wrappers to send() and recv()
@ -86,28 +87,32 @@ static bool gtls_inited = FALSE;
* us to get specific about the fourth "flags" argument, and to use arbitrary * us to get specific about the fourth "flags" argument, and to use arbitrary
* private data with gnutls_transport_set_ptr if we wish. * private data with gnutls_transport_set_ptr if we wish.
* *
* On Windows translate WSAGetLastError() to errno values as GNU TLS does it * When these custom push and pull callbacks fail, GNU TLS checks its own
* internally too. This is necessary because send() and recv() on Windows * session-specific error variable, and when not set also its own global
* don't set errno when they fail but GNU TLS expects a proper errno value. * errno variable, in order to take appropriate action. GNU TLS does not
* * require that the transport is actually a socket. This implies that for
* Use gnutls_transport_set_global_errno() like the GNU TLS documentation * Windows builds these callbacks should ideally set the session-specific
* suggests to avoid problems with different errno variables when GNU TLS and * error variable using function gnutls_transport_set_errno or as a last
* curl are linked to different versions of msvcrt.dll. * resort global errno variable using gnutls_transport_set_global_errno,
* with a transport agnostic error value. This implies that some winsock
* error translation must take place in these callbacks.
*/ */
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
static void translate_wsa_to_errno(void) # define gtls_EINTR 4
# define gtls_EIO 5
# define gtls_EAGAIN 11
static int gtls_mapped_sockerrno(void)
{ {
switch(WSAGetLastError()) { switch(SOCKERRNO) {
case WSAEWOULDBLOCK: case WSAEWOULDBLOCK:
gnutls_transport_set_global_errno(EAGAIN); return gtls_EAGAIN;
break;
case WSAEINTR: case WSAEINTR:
gnutls_transport_set_global_errno(EINTR); return gtls_EINTR;
break;
default: default:
gnutls_transport_set_global_errno(EIO);
break; break;
} }
return gtls_EIO;
} }
#endif #endif
@ -115,9 +120,8 @@ static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{ {
ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
if(ret < 0) { if(ret < 0)
translate_wsa_to_errno(); gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
}
#endif #endif
return ret; return ret;
} }
@ -126,9 +130,8 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{ {
ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len); ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
if(ret < 0) { if(ret < 0)
translate_wsa_to_errno(); gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
}
#endif #endif
return ret; return ret;
} }