diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-08-23 20:13:10 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2016-08-23 20:13:10 +0000 |
commit | 515c50a1fa2706b2d0cd9687c381662e39b30be8 (patch) | |
tree | f1b12a1a332c10673b413f8d2e74882212176af0 | |
parent | a3fc78c87acc9a411959115c071f60adf54a2e11 (diff) |
mhd_sockets: better sockets errors abstraction, improved performance on W32
-rw-r--r-- | src/microhttpd/connection.c | 22 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 77 | ||||
-rw-r--r-- | src/microhttpd/mhd_compat.h | 6 | ||||
-rw-r--r-- | src/microhttpd/mhd_sockets.c | 318 | ||||
-rw-r--r-- | src/microhttpd/mhd_sockets.h | 434 |
5 files changed, 339 insertions, 518 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 2c799d16..7c0ce674 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c @@ -1855,10 +1855,10 @@ do_read (struct MHD_Connection *connection) connection->read_buffer_offset); if (bytes_read < 0) { - const int err = MHD_socket_errno_; - if ((EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err)) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err) || MHD_SCKT_ERR_IS_EAGAIN_ (err)) return MHD_NO; - if (ECONNRESET == err) + if (MHD_SCKT_ERR_IS_REMOTE_DISCNN_ (err)) { CONNECTION_CLOSE_ERROR (connection, NULL); return MHD_NO; @@ -1902,8 +1902,8 @@ do_write (struct MHD_Connection *connection) if (ret < 0) { - const int err = MHD_socket_errno_; - if ((EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err)) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err) || MHD_SCKT_ERR_IS_EAGAIN_ (err)) return MHD_NO; CONNECTION_CLOSE_ERROR (connection, NULL); return MHD_YES; @@ -2276,13 +2276,13 @@ MHD_connection_handle_write (struct MHD_Connection *connection) connection->continue_message_write_offset); if (ret < 0) { - const int err = MHD_socket_errno_; - if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err)) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err) || MHD_SCKT_ERR_IS_EAGAIN_ (err)) break; #ifdef HAVE_MESSAGES MHD_DLOG (connection->daemon, "Failed to send data: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif CONNECTION_CLOSE_ERROR (connection, NULL); return MHD_YES; @@ -2330,7 +2330,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection) [(size_t)data_write_offset], response->data_size - (size_t)data_write_offset); - err = MHD_socket_errno_; + err = MHD_socket_get_error_ (); #if DEBUG_SEND_DATA if (ret > 0) fprintf (stderr, @@ -2344,12 +2344,12 @@ MHD_connection_handle_write (struct MHD_Connection *connection) (void) MHD_mutex_unlock_ (&response->mutex); if (ret < 0) { - if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err)) + if (MHD_SCKT_ERR_IS_EINTR_ (err) || MHD_SCKT_ERR_IS_EAGAIN_ (err)) return MHD_YES; #ifdef HAVE_MESSAGES MHD_DLOG (connection->daemon, "Failed to send data: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif CONNECTION_CLOSE_ERROR (connection, NULL); return MHD_YES; diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 7a784daf..68491938 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c @@ -457,7 +457,7 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { - MHD_set_socket_errno_ (EINTR); + MHD_socket_set_error_ (MHD_SCKT_EINTR_); #if EPOLL_SUPPORT connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; #endif @@ -468,7 +468,7 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication disrupted); set errno to something caller will interpret correctly as a hard error */ - MHD_set_socket_errno_ (ECONNRESET); + MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); return res; } if ((size_t)res == i) @@ -498,7 +498,7 @@ send_tls_adapter (struct MHD_Connection *connection, if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { - MHD_set_socket_errno_ (EINTR); + MHD_socket_set_error_ (MHD_SCKT_EINTR_); #if EPOLL_SUPPORT connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; #endif @@ -510,7 +510,7 @@ send_tls_adapter (struct MHD_Connection *connection, really understand the error (not listed in GnuTLS documentation explicitly), we set 'errno' to something that will cause the connection to fail. */ - MHD_set_socket_errno_ (ECONNRESET); + MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); return -1; } return res; @@ -971,13 +971,14 @@ MHD_handle_connection (void *data) num_ready = MHD_SYS_select_ (maxsock + 1, &rs, &ws, NULL, tvp); if (num_ready < 0) { - if (EINTR == MHD_socket_errno_) + const int err = MHD_socket_get_error_(); + if (MHD_SCKT_ERR_IS_EINTR_(err)) continue; #ifdef HAVE_MESSAGES MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", - MHD_socket_errno_, - MHD_socket_last_strerr_ ()); + err, + MHD_socket_strerr_ (err)); #endif break; } @@ -1039,7 +1040,7 @@ MHD_handle_connection (void *data) #endif (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0) { - if (EINTR == MHD_socket_errno_) + if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_)) continue; #ifdef HAVE_MESSAGES MHD_DLOG (con->daemon, @@ -1117,7 +1118,7 @@ recv_param_adapter (struct MHD_Connection *connection, if ( (MHD_INVALID_SOCKET == connection->socket_fd) || (MHD_CONNECTION_CLOSED == connection->state) ) { - MHD_set_socket_errno_ (ENOTCONN); + MHD_socket_set_error_ (MHD_SCKT_ENOTCONN_); return -1; } #ifdef MHD_POSIX_SOCKETS @@ -1133,7 +1134,7 @@ recv_param_adapter (struct MHD_Connection *connection, (_MHD_socket_funcs_size) i, MSG_NOSIGNAL); #if EPOLL_SUPPORT - if ( (0 > ret) && (EAGAIN == MHD_socket_errno_) ) + if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ())) ) { /* Got EAGAIN --- no longer read-ready */ connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; @@ -1157,6 +1158,7 @@ send_param_adapter (struct MHD_Connection *connection, size_t i) { ssize_t ret; + int err; #if LINUX MHD_socket fd; #endif @@ -1164,7 +1166,7 @@ send_param_adapter (struct MHD_Connection *connection, if ( (MHD_INVALID_SOCKET == connection->socket_fd) || (MHD_CONNECTION_CLOSED == connection->state) ) { - MHD_set_socket_errno_ (ENOTCONN); + MHD_socket_set_error_ (MHD_SCKT_ENOTCONN_); return -1; } #ifdef MHD_POSIX_SOCKETS @@ -1189,7 +1191,6 @@ send_param_adapter (struct MHD_Connection *connection, /* can use sendfile */ uint64_t left; uint64_t offsetu64; - int err; #ifndef HAVE_SENDFILE64 off_t offset; #else /* HAVE_SENDFILE64 */ @@ -1198,7 +1199,7 @@ send_param_adapter (struct MHD_Connection *connection, offsetu64 = connection->response_write_position + connection->response->fd_off; left = connection->response->total_size - connection->response_write_position; ret = 0; - MHD_set_socket_errno_(ENOMEM); + MHD_socket_set_error_to_ENOMEM (); #ifndef HAVE_SENDFILE64 offset = (off_t) offsetu64; if ( (offsetu64 <= (uint64_t) OFF_T_MAX) && @@ -1212,17 +1213,17 @@ send_param_adapter (struct MHD_Connection *connection, /* write successful */ return ret; } - err = MHD_socket_errno_; + err = MHD_socket_get_error_(); #if EPOLL_SUPPORT - if ( (0 > ret) && (EAGAIN == err) ) + if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) ) { /* EAGAIN --- no longer write-ready */ connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; } #endif - if ( (EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err) ) + if (MHD_SCKT_ERR_IS_EINTR_ (err) || MHD_SCKT_ERR_IS_EAGAIN_ (err)) return 0; - if (EBADF == err) + if (MHD_SCKT_ERR_IS_(err, MHD_SCKT_EBADF_)) return -1; /* sendfile() failed with EINVAL if mmap()-like operations are not supported for FD or other 'unusual' errors occurred, so we should try @@ -1232,8 +1233,9 @@ send_param_adapter (struct MHD_Connection *connection, } #endif ret = (ssize_t) send (connection->socket_fd, other, (_MHD_socket_funcs_size)i, MSG_NOSIGNAL); + err = MHD_socket_get_error_(); #if EPOLL_SUPPORT - if ( (0 > ret) && (EAGAIN == MHD_socket_errno_) ) + if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) ) { /* EAGAIN --- no longer write-ready */ connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; @@ -1242,8 +1244,8 @@ send_param_adapter (struct MHD_Connection *connection, /* Handle broken kernel / libc, returning -1 but not setting errno; kill connection as that should be safe; reported on mailinglist here: http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */ - if ( (0 > ret) && (0 == MHD_socket_errno_) ) - MHD_set_socket_errno_(ECONNRESET); + if ( (0 > ret) && (0 == err) ) + MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); return ret; } @@ -1970,16 +1972,18 @@ MHD_accept_connection (struct MHD_Daemon *daemon) #endif /* ! USE_ACCEPT4 */ if ((MHD_INVALID_SOCKET == s) || (addrlen <= 0)) { - const int err = MHD_socket_errno_; + const int err = MHD_socket_get_error_ (); /* This could be a common occurance with multiple worker threads */ - if ( (EINVAL == err) && + if ( (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_EINVAL_)) && (MHD_INVALID_SOCKET == daemon->socket_fd) ) return MHD_NO; /* can happen during shutdown */ + if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)) + return MHD_NO; /* do not print error if client just disconnected early */ #ifdef HAVE_MESSAGES - if ((EAGAIN != err) && (EWOULDBLOCK != err)) + if ( !MHD_SCKT_ERR_IS_EAGAIN_ (err) ) MHD_DLOG (daemon, "Error accepting connection: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_(err)); #endif if (MHD_INVALID_SOCKET != s) { @@ -1987,10 +1991,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) MHD_PANIC ("close failed\n"); /* just in case */ } - if ( (EMFILE == err) || - (ENFILE == err) || - (ENOMEM == err) || - (ENOBUFS == err) ) + if ( MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err) ) { /* system/process out of resources */ if (0 == daemon->connections) @@ -2430,12 +2431,13 @@ MHD_select (struct MHD_Daemon *daemon, return MHD_NO; if (num_ready < 0) { - if (EINTR == MHD_socket_errno_) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_(err)) return (MHD_NO == err_state) ? MHD_YES : MHD_NO; #ifdef HAVE_MESSAGES MHD_DLOG (daemon, "select failed: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif return MHD_NO; } @@ -2551,7 +2553,8 @@ MHD_poll_all (struct MHD_Daemon *daemon, } if (MHD_sys_poll_(p, poll_server + num_connections, timeout) < 0) { - if (EINTR == MHD_socket_errno_) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err)) { free(p); return MHD_YES; @@ -2559,7 +2562,7 @@ MHD_poll_all (struct MHD_Daemon *daemon, #ifdef HAVE_MESSAGES MHD_DLOG (daemon, "poll failed: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif free(p); return MHD_NO; @@ -2645,12 +2648,13 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon, return MHD_YES; if (MHD_sys_poll_(p, poll_count, timeout) < 0) { - if (EINTR == MHD_socket_errno_) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err)) return MHD_YES; #ifdef HAVE_MESSAGES MHD_DLOG (daemon, "poll failed: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif return MHD_NO; } @@ -2790,12 +2794,13 @@ MHD_epoll (struct MHD_Daemon *daemon, events, MAX_EVENTS, timeout_ms); if (-1 == num_events) { - if (EINTR == MHD_socket_errno_) + const int err = MHD_socket_get_error_ (); + if (MHD_SCKT_ERR_IS_EINTR_ (err)) return MHD_YES; #ifdef HAVE_MESSAGES MHD_DLOG (daemon, "Call to epoll_wait failed: %s\n", - MHD_socket_last_strerr_ ()); + MHD_socket_strerr_ (err)); #endif return MHD_NO; } diff --git a/src/microhttpd/mhd_compat.h b/src/microhttpd/mhd_compat.h index 3f88055f..19ebac5f 100644 --- a/src/microhttpd/mhd_compat.h +++ b/src/microhttpd/mhd_compat.h @@ -36,6 +36,12 @@ #include "mhd_options.h" #include <stdlib.h> +#ifdef HAVE_STRING_H /* for strerror() */ +#include <string.h> +#endif /* HAVE_STRING_H */ + + /* MHD_strerror_ is strerror */ +#define MHD_strerror_(errnum) strerror((errnum)) /* Platform-independent snprintf name */ #if defined(HAVE_SNPRINTF) diff --git a/src/microhttpd/mhd_sockets.c b/src/microhttpd/mhd_sockets.c index 4214108e..643ed849 100644 --- a/src/microhttpd/mhd_sockets.c +++ b/src/microhttpd/mhd_sockets.c @@ -29,166 +29,13 @@ #ifdef MHD_WINSOCK_SOCKETS /** - * Return errno equivalent of last winsock error - * @return errno equivalent of last winsock error + * Return pointer to string description of specified WinSock error + * @param err the WinSock error code. + * @return pointer to string description of specified WinSock error. */ -int MHD_W32_errno_from_winsock_(void) +const char* MHD_W32_strerror_winsock_(int err) { - switch(WSAGetLastError()) - { - case 0: return 0; - case WSA_INVALID_HANDLE: return EBADF; - case WSA_NOT_ENOUGH_MEMORY: return ENOMEM; - case WSA_INVALID_PARAMETER: return EINVAL; - case WSAEINTR: return EINTR; - case WSAEWOULDBLOCK: return EWOULDBLOCK; - case WSAEINPROGRESS: return EINPROGRESS; - case WSAEALREADY: return EALREADY; - case WSAENOTSOCK: return ENOTSOCK; - case WSAEDESTADDRREQ: return EDESTADDRREQ; - case WSAEMSGSIZE: return EMSGSIZE; - case WSAEPROTOTYPE: return EPROTOTYPE; - case WSAENOPROTOOPT: return ENOPROTOOPT; - case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT; - case WSAESOCKTNOSUPPORT: return ESOCKTNOSUPPORT; - case WSAEOPNOTSUPP: return EOPNOTSUPP; - case WSAEPFNOSUPPORT: return EPFNOSUPPORT; - case WSAEAFNOSUPPORT: return EAFNOSUPPORT; - case WSAEADDRINUSE: return EADDRINUSE; - case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL; - case WSAENETDOWN: return ENETDOWN; - case WSAENETUNREACH: return ENETUNREACH; - case WSAENETRESET: return ENETRESET; - case WSAECONNABORTED: return ECONNABORTED; - case WSAECONNRESET: return ECONNRESET; - case WSAENOBUFS: return ENOBUFS; - case WSAEISCONN: return EISCONN; - case WSAENOTCONN: return ENOTCONN; - case WSAESHUTDOWN: return ESHUTDOWN; - case WSAETOOMANYREFS: return ETOOMANYREFS; - case WSAETIMEDOUT: return ETIMEDOUT; - case WSAECONNREFUSED: return ECONNREFUSED; - case WSAELOOP: return ELOOP; - case WSAENAMETOOLONG: return ENAMETOOLONG; - case WSAEHOSTDOWN: return EHOSTDOWN; - case WSAEHOSTUNREACH: return EHOSTUNREACH; - case WSAENOTEMPTY: return ENOTEMPTY; - case WSAEPROCLIM: return EPROCLIM; - case WSAEUSERS: return EUSERS; - case WSAEDQUOT: return EDQUOT; - case WSAESTALE: return ESTALE; - case WSAEREMOTE: return EREMOTE; - case WSAEINVAL: return EINVAL; - case WSAEFAULT: return EFAULT; - case WSANO_DATA: return ENODATA; - /* Rough equivalents */ - case WSAEDISCON: return ECONNRESET; - case WSAEINVALIDPROCTABLE: return EFAULT; - case WSASYSNOTREADY: - case WSANOTINITIALISED: - case WSASYSCALLFAILURE: return ENOBUFS; - case WSAVERNOTSUPPORTED: return EOPNOTSUPP; - case WSAEREFUSED: return EIO; - } - return EINVAL; -} - -/** - * Return pointer to string description of errnum error - * Works fine with both standard errno errnums - * and errnums from MHD_W32_errno_from_winsock_ - * @param errnum the errno or value from MHD_W32_errno_from_winsock_() - * @return pointer to string description of error - */ -const char* MHD_W32_strerror_(int errnum) -{ - switch(errnum) - { - case 0: - return "No error"; - case EWOULDBLOCK: - return "Operation would block"; - case EINPROGRESS: - return "Connection already in progress"; - case EALREADY: - return "Socket already connected"; - case ENOTSOCK: - return "Socket operation on non-socket"; - case EDESTADDRREQ: - return "Destination address required"; - case EMSGSIZE: - return "Message too long"; - case EPROTOTYPE: - return "Protocol wrong type for socket"; - case ENOPROTOOPT: - return "Protocol not available"; - case EPROTONOSUPPORT: - return "Unknown protocol"; - case ESOCKTNOSUPPORT: - return "Socket type not supported"; - case EOPNOTSUPP: - return "Operation not supported on socket"; - case EPFNOSUPPORT: - return "Protocol family not supported"; - case EAFNOSUPPORT: - return "Address family not supported by protocol family"; - case EADDRINUSE: - return "Address already in use"; - case EADDRNOTAVAIL: - return "Cannot assign requested address"; - case ENETDOWN: - return "Network is down"; - case ENETUNREACH: - return "Network is unreachable"; - case ENETRESET: - return "Network dropped connection on reset"; - case ECONNABORTED: - return "Software caused connection abort"; - case ECONNRESET: - return "Connection reset by peer"; - case ENOBUFS: - return "No system resources available"; - case EISCONN: - return "Socket is already connected"; - case ENOTCONN: - return "Socket is not connected"; - case ESHUTDOWN: - return "Can't send after socket shutdown"; - case ETOOMANYREFS: - return "Too many references: cannot splice"; - case ETIMEDOUT: - return "Connection timed out"; - case ECONNREFUSED: - return "Connection refused"; - case ELOOP: - return "Cannot translate name"; - case EHOSTDOWN: - return "Host is down"; - case EHOSTUNREACH: - return "Host is unreachable"; - case EPROCLIM: - return "Too many processes"; - case EUSERS: - return "Too many users"; - case EDQUOT: - return "Disk quota exceeded"; - case ESTALE: - return "Stale file handle reference"; - case EREMOTE: - return "Resource is remote"; - case ENODATA: - return "No data available"; - } - return strerror(errnum); -} - -/** - * Return pointer to string description of last winsock error - * @return pointer to string description of last winsock error - */ -const char* MHD_W32_strerror_last_winsock_(void) -{ - switch (WSAGetLastError()) + switch (err) { case 0: return "No error"; @@ -386,160 +233,5 @@ const char* MHD_W32_strerror_last_winsock_(void) return "Unknown winsock error"; } -/** - * Set last winsock error to equivalent of given errno value - * @param errnum the errno value to set - */ -void MHD_W32_set_last_winsock_error_(int errnum) -{ - switch (errnum) - { - case 0: - WSASetLastError(0); - break; - case EBADF: - WSASetLastError(WSA_INVALID_HANDLE); - break; - case ENOMEM: - WSASetLastError(WSA_NOT_ENOUGH_MEMORY); - break; - case EINVAL: - WSASetLastError(WSA_INVALID_PARAMETER); - break; - case EINTR: - WSASetLastError(WSAEINTR); - break; - case EWOULDBLOCK: - WSASetLastError(WSAEWOULDBLOCK); - break; - case EINPROGRESS: - WSASetLastError(WSAEINPROGRESS); - break; - case EALREADY: - WSASetLastError(WSAEALREADY); - break; - case ENOTSOCK: - WSASetLastError(WSAENOTSOCK); - break; - case EDESTADDRREQ: - WSASetLastError(WSAEDESTADDRREQ); - break; - case EMSGSIZE: - WSASetLastError(WSAEMSGSIZE); - break; - case EPROTOTYPE: - WSASetLastError(WSAEPROTOTYPE); - break; - case ENOPROTOOPT: - WSASetLastError(WSAENOPROTOOPT); - break; - case EPROTONOSUPPORT: - WSASetLastError(WSAEPROTONOSUPPORT); - break; - case ESOCKTNOSUPPORT: - WSASetLastError(WSAESOCKTNOSUPPORT); - break; - case EOPNOTSUPP: - WSASetLastError(WSAEOPNOTSUPP); - break; - case EPFNOSUPPORT: - WSASetLastError(WSAEPFNOSUPPORT); - break; - case EAFNOSUPPORT: - WSASetLastError(WSAEAFNOSUPPORT); - break; - case EADDRINUSE: - WSASetLastError(WSAEADDRINUSE); - break; - case EADDRNOTAVAIL: - WSASetLastError(WSAEADDRNOTAVAIL); - break; - case ENETDOWN: - WSASetLastError(WSAENETDOWN); - break; - case ENETUNREACH: - WSASetLastError(WSAENETUNREACH); - break; - case ENETRESET: - WSASetLastError(WSAENETRESET); - break; - case ECONNABORTED: - WSASetLastError(WSAECONNABORTED); - break; - case ECONNRESET: - WSASetLastError(WSAECONNRESET); - break; - case ENOBUFS: - WSASetLastError(WSAENOBUFS); - break; - case EISCONN: - WSASetLastError(WSAEISCONN); - break; - case ENOTCONN: - WSASetLastError(WSAENOTCONN); - break; - case ESHUTDOWN: - WSASetLastError(WSAESHUTDOWN); - break; - case ETOOMANYREFS: - WSASetLastError(WSAETOOMANYREFS); - break; - case ETIMEDOUT: - WSASetLastError(WSAETIMEDOUT); - break; - case ECONNREFUSED: - WSASetLastError(WSAECONNREFUSED); - break; - case ELOOP: - WSASetLastError(WSAELOOP); - break; - case ENAMETOOLONG: - WSASetLastError(WSAENAMETOOLONG); - break; - case EHOSTDOWN: - WSASetLastError(WSAEHOSTDOWN); - break; - case EHOSTUNREACH: - WSASetLastError(WSAEHOSTUNREACH); - break; - case ENOTEMPTY: - WSASetLastError(WSAENOTEMPTY); - break; - case EPROCLIM: - WSASetLastError(WSAEPROCLIM); - break; - case EUSERS: - WSASetLastError(WSAEUSERS); - break; - case EDQUOT: - WSASetLastError(WSAEDQUOT); - break; - case ESTALE: - WSASetLastError(WSAESTALE); - break; - case EREMOTE: - WSASetLastError(WSAEREMOTE); - break; - case EFAULT: - WSASetLastError(WSAEFAULT); - break; - case ENODATA: - WSASetLastError(WSANO_DATA); - break; -#if EAGAIN != EWOULDBLOCK - case EAGAIN: - WSASetLastError(WSAEWOULDBLOCK); - break; -#endif - /* Rough equivalent */ - case EIO: - WSASetLastError(WSAEREFUSED); - break; - - default: /* Unmapped errors */ - WSASetLastError(WSAENOBUFS); - break; - } -} #endif /* MHD_WINSOCK_SOCKETS */ diff --git a/src/microhttpd/mhd_sockets.h b/src/microhttpd/mhd_sockets.h index 3a3e4b85..b38a5d55 100644 --- a/src/microhttpd/mhd_sockets.h +++ b/src/microhttpd/mhd_sockets.h @@ -204,38 +204,6 @@ # define MHD_socket_close_(fd) closesocket((fd)) #endif -/** - * MHD_socket_errno_ is errno of last function (non-W32) / errno of - * last socket function (W32) - */ -#if !defined(MHD_WINSOCK_SOCKETS) -# define MHD_socket_errno_ errno -#else -# define MHD_socket_errno_ MHD_W32_errno_from_winsock_() -#endif - - /* MHD_socket_last_strerr_ is description string of last errno (non-W32) / - * description string of last socket error (W32) */ -#if !defined(MHD_WINSOCK_SOCKETS) -# define MHD_socket_last_strerr_() strerror(errno) -#else -# define MHD_socket_last_strerr_() MHD_W32_strerror_last_winsock_() -#endif - - /* MHD_strerror_ is strerror (both non-W32/W32) */ -#if !defined(MHD_WINSOCK_SOCKETS) -# define MHD_strerror_(errnum) strerror((errnum)) -#else -# define MHD_strerror_(errnum) MHD_W32_strerror_((errnum)) -#endif - - /* MHD_set_socket_errno_ set errno to errnum (non-W32) / set socket last error to errnum (W32) */ -#if !defined(MHD_WINSOCK_SOCKETS) -# define MHD_set_socket_errno_(errnum) errno=(errnum) -#else -# define MHD_set_socket_errno_(errnum) MHD_W32_set_last_winsock_error_((errnum)) -#endif - /* MHD_SYS_select_ is wrapper macro for system select() function */ #if !defined(MHD_WINSOCK_SOCKETS) # define MHD_SYS_select_(n,r,w,e,t) select((n),(r),(w),(e),(t)) @@ -257,150 +225,300 @@ # endif /* MHD_WINSOCK_SOCKETS */ #endif /* HAVE_POLL */ +#define MHD_SCKT_MISSING_ERR_CODE_ 31450 + +#if defined(MHD_POSIX_SOCKETS) +# if defined(EAGAIN) +# define MHD_SCKT_EAGAIN_ EAGAIN +# elif defined(EWOULDBLOCK) +# define MHD_SCKT_EAGAIN_ EWOULDBLOCK +# else /* !EAGAIN && !EWOULDBLOCK */ +# define MHD_SCKT_EAGAIN_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* !EAGAIN && !EWOULDBLOCK */ +# if defined(EWOULDBLOCK) +# define MHD_SCKT_EWOULDBLOCK_ EWOULDBLOCK +# elif defined(EAGAIN) +# define MHD_SCKT_EWOULDBLOCK_ EAGAIN +# else /* !EWOULDBLOCK && !EAGAIN */ +# define MHD_SCKT_EWOULDBLOCK_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* !EWOULDBLOCK && !EAGAIN */ +# ifdef EINTR +# define MHD_SCKT_EINTR_ EINTR +# else /* ! EINTR */ +# define MHD_SCKT_EINTR_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EINTR */ +# ifdef ECONNRESET +# define MHD_SCKT_ECONNRESET_ ECONNRESET +# else /* ! ECONNRESET */ +# define MHD_SCKT_ECONNRESET_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ECONNRESET */ +# ifdef ECONNABORTED +# define MHD_SCKT_ECONNABORTED_ ECONNABORTED +# else /* ! ECONNABORTED */ +# define MHD_SCKT_ECONNABORTED_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ECONNABORTED */ +# ifdef ENOTCONN +# define MHD_SCKT_ENOTCONN_ ENOTCONN +# else /* ! ENOTCONN */ +# define MHD_SCKT_ENOTCONN_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOTCONN */ +# ifdef EMFILE +# define MHD_SCKT_EMFILE_ EMFILE +# else /* ! EMFILE */ +# define MHD_SCKT_EMFILE_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EMFILE */ +# ifdef ENFILE +# define MHD_SCKT_ENFILE_ ENFILE +# else /* ! ENFILE */ +# define MHD_SCKT_ENFILE_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENFILE */ +# ifdef ENOMEM +# define MHD_SCKT_ENOMEM_ ENOMEM +# else /* ! ENOMEM */ +# define MHD_SCKT_ENOMEM_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOMEM */ +# ifdef ENOBUFS +# define MHD_SCKT_ENOBUFS_ ENOBUFS +# else /* ! ENOBUFS */ +# define MHD_SCKT_ENOBUFS_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOBUFS */ +# ifdef EBADF +# define MHD_SCKT_EBADF_ EBADF +# else /* ! EBADF */ +# define MHD_SCKT_EBADF_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EBADF */ +# ifdef ENOTSOCK +# define MHD_SCKT_ENOTSOCK_ ENOTSOCK +# else /* ! ENOTSOCK */ +# define MHD_SCKT_ENOTSOCK_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOTSOCK */ +# ifdef EINVAL +# define MHD_SCKT_EINVAL_ EINVAL +# else /* ! EINVAL */ +# define MHD_SCKT_EINVAL_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EINVAL */ +# ifdef EFAULT +# define MHD_SCKT_EFAUL_ EFAULT +# else /* ! EFAULT */ +# define MHD_SCKT_EFAUL_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EFAULT */ +# ifdef ENOSYS +# define MHD_SCKT_ENOSYS_ ENOSYS +# else /* ! ENOSYS */ +# define MHD_SCKT_ENOSYS_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOSYS */ +# ifdef ENOTSUP +# define MHD_SCKT_ENOTSUP_ ENOTSUP +# else /* ! ENOTSUP */ +# define MHD_SCKT_ENOTSUP_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENOTSUP */ +# ifdef EOPNOTSUPP +# define MHD_SCKT_EOPNOTSUPP_ EOPNOTSUPP +# else /* ! EOPNOTSUPP */ +# define MHD_SCKT_EOPNOTSUPP_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EOPNOTSUPP */ +# ifdef EACCES +# define MHD_SCKT_EACCESS_ EACCES +# else /* ! EACCES */ +# define MHD_SCKT_EACCESS_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! EACCES */ +# ifdef ENETDOWN +# define MHD_SCKT_ENETDOWN_ ENETDOWN +# else /* ! ENETDOWN */ +# define MHD_SCKT_ENETDOWN_ MHD_SCKT_MISSING_ERR_CODE_ +# endif /* ! ENETDOWN */ +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_SCKT_EAGAIN_ WSAEWOULDBLOCK +# define MHD_SCKT_EWOULDBLOCK_ WSAEWOULDBLOCK +# define MHD_SCKT_EINTR_ WSAEINTR +# define MHD_SCKT_ECONNRESET_ WSAECONNRESET +# define MHD_SCKT_ECONNABORTED_ WSAECONNABORTED +# define MHD_SCKT_ENOTCONN_ WSAENOTCONN +# define MHD_SCKT_EMFILE_ WSAEMFILE +# define MHD_SCKT_ENFILE_ MHD_SCKT_MISSING_ERR_CODE_ +# define MHD_SCKT_ENOMEM_ MHD_SCKT_MISSING_ERR_CODE_ +# define MHD_SCKT_ENOBUFS_ WSAENOBUFS +# define MHD_SCKT_EBADF_ WSAEBADF +# define MHD_SCKT_ENOTSOCK_ WSAENOTSOCK +# define MHD_SCKT_EINVAL_ WSAEINVAL +# define MHD_SCKT_EFAUL_ WSAEFAULT +# define MHD_SCKT_ENOSYS_ MHD_SCKT_MISSING_ERR_CODE_ +# define MHD_SCKT_ENOTSUP_ MHD_SCKT_MISSING_ERR_CODE_ +# define MHD_SCKT_EOPNOTSUPP_ WSAEOPNOTSUPP +# define MHD_SCKT_EACCESS_ WSAEACCES +# define MHD_SCKT_ENETDOWN_ WSAENETDOWN +#endif + +/** + * MHD_socket_error_ return system native error code for last socket error. + * @return system error code for last socket error. + */ +#if defined(MHD_POSIX_SOCKETS) +# define MHD_socket_get_error_() (errno) +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_socket_get_error_() WSAGetLastError() +#endif #ifdef MHD_WINSOCK_SOCKETS + /* POSIX-W32 sockets compatibility functions */ -/* POSIX-W32 compatibility functions and macros */ +/** + * Return pointer to string description of specified WinSock error + * @param err the WinSock error code. + * @return pointer to string description of specified WinSock error. + */ + const char* MHD_W32_strerror_winsock_(int err); +#endif /* MHD_WINSOCK_SOCKETS */ -# define MHDW32ERRBASE 3300 +/* MHD_socket_last_strerr_ is description string of specified socket error code */ +#if defined(MHD_POSIX_SOCKETS) +# define MHD_socket_strerr_(err) strerror((err)) +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_socket_strerr_(err) MHD_W32_strerror_winsock_((err)) +#endif -# ifndef EWOULDBLOCK -# define EWOULDBLOCK (MHDW32ERRBASE+1) -# endif -# ifndef EINPROGRESS -# define EINPROGRESS (MHDW32ERRBASE+2) -# endif -# ifndef EALREADY -# define EALREADY (MHDW32ERRBASE+3) -# endif -# ifndef ENOTSOCK -# define ENOTSOCK (MHDW32ERRBASE+4) -# endif -# ifndef EDESTADDRREQ -# define EDESTADDRREQ (MHDW32ERRBASE+5) -# endif -# ifndef EMSGSIZE -# define EMSGSIZE (MHDW32ERRBASE+6) -# endif -# ifndef EPROTOTYPE -# define EPROTOTYPE (MHDW32ERRBASE+7) -# endif -# ifndef ENOPROTOOPT -# define ENOPROTOOPT (MHDW32ERRBASE+8) -# endif -# ifndef EPROTONOSUPPORT -# define EPROTONOSUPPORT (MHDW32ERRBASE+9) -# endif -# ifndef EOPNOTSUPP -# define EOPNOTSUPP (MHDW32ERRBASE+10) -# endif -# ifndef EAFNOSUPPORT -# define EAFNOSUPPORT (MHDW32ERRBASE+11) -# endif -# ifndef EADDRINUSE -# define EADDRINUSE (MHDW32ERRBASE+12) -# endif -# ifndef EADDRNOTAVAIL -# define EADDRNOTAVAIL (MHDW32ERRBASE+13) -# endif -# ifndef ENETDOWN -# define ENETDOWN (MHDW32ERRBASE+14) -# endif -# ifndef ENETUNREACH -# define ENETUNREACH (MHDW32ERRBASE+15) -# endif -# ifndef ENETRESET -# define ENETRESET (MHDW32ERRBASE+16) -# endif -# ifndef ECONNABORTED -# define ECONNABORTED (MHDW32ERRBASE+17) -# endif -# ifndef ECONNRESET -# define ECONNRESET (MHDW32ERRBASE+18) -# endif -# ifndef ENOBUFS -# define ENOBUFS (MHDW32ERRBASE+19) -# endif -# ifndef EISCONN -# define EISCONN (MHDW32ERRBASE+20) -# endif -# ifndef ENOTCONN -# define ENOTCONN (MHDW32ERRBASE+21) -# endif -# ifndef ETOOMANYREFS -# define ETOOMANYREFS (MHDW32ERRBASE+22) -# endif -# ifndef ECONNREFUSED -# define ECONNREFUSED (MHDW32ERRBASE+23) -# endif -# ifndef ELOOP -# define ELOOP (MHDW32ERRBASE+24) -# endif -# ifndef EHOSTDOWN -# define EHOSTDOWN (MHDW32ERRBASE+25) -# endif -# ifndef EHOSTUNREACH -# define EHOSTUNREACH (MHDW32ERRBASE+26) -# endif -# ifndef EPROCLIM -# define EPROCLIM (MHDW32ERRBASE+27) -# endif -# ifndef EUSERS -# define EUSERS (MHDW32ERRBASE+28) -# endif -# ifndef EDQUOT -# define EDQUOT (MHDW32ERRBASE+29) -# endif -# ifndef ESTALE -# define ESTALE (MHDW32ERRBASE+30) -# endif -# ifndef EREMOTE -# define EREMOTE (MHDW32ERRBASE+31) -# endif -# ifndef ESOCKTNOSUPPORT -# define ESOCKTNOSUPPORT (MHDW32ERRBASE+32) -# endif -# ifndef EPFNOSUPPORT -# define EPFNOSUPPORT (MHDW32ERRBASE+33) -# endif -# ifndef ESHUTDOWN -# define ESHUTDOWN (MHDW32ERRBASE+34) -# endif -# ifndef ENODATA -# define ENODATA (MHDW32ERRBASE+35) -# endif -# ifndef ETIMEDOUT -# define ETIMEDOUT (MHDW32ERRBASE+36) -# endif +/* MHD_socket_last_strerr_ is description string of last errno (non-W32) / + * description string of last socket error (W32) */ +#define MHD_socket_last_strerr_() MHD_socket_strerr_(MHD_socket_get_error_()) /** - * Return errno equivalent of last winsock error - * @return errno equivalent of last winsock error + * MHD_socket_fset_error_() set socket system native error code. */ - int MHD_W32_errno_from_winsock_(void); +#if defined(MHD_POSIX_SOCKETS) +# define MHD_socket_fset_error_(err) (errno = (err)) +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_socket_fset_error_(err) (WSASetLastError((err))) +#endif /** - * Return pointer to string description of errnum error - * Works fine with both standard errno errnums - * and errnums from MHD_W32_errno_from_winsock_ - * @param errnum the errno or value from MHD_W32_errno_from_winsock_() - * @return pointer to string description of error + * MHD_socket_try_set_error_() set socket system native error code if + * specified code is defined on system. + * @return non-zero if specified @a err code is defined on system + * and error was set; + * zero if specified @a err code is not defined on system + * and error was not set. */ - const char* MHD_W32_strerror_(int errnum); +#define MHD_socket_try_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ != (err)) ? \ + (MHD_socket_fset_error_((err)), !0) : 0 ) /** - * Return pointer to string description of last winsock error - * @return pointer to string description of last winsock error + * MHD_socket_set_error_() set socket system native error code to + * specified code or replacement code if specified code is not + * defined on system. */ - const char* MHD_W32_strerror_last_winsock_(void); +#if defined(MHD_POSIX_SOCKETS) +# if defined(ENOSYS) +# define MHD_socket_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ == (err)) ? \ + (errno = ENOSYS) : (errno = (err)) ) +# elif defined(EOPNOTSUPP) +# define MHD_socket_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ == (err)) ? \ + (errno = EOPNOTSUPP) : (errno = (err)) ) +# elif defined (EFAULT) +# define MHD_socket_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ == (err)) ? \ + (errno = EFAULT) : (errno = (err)) ) +# elif defined (EINVAL) +# define MHD_socket_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ == (err)) ? \ + (errno = EINVAL) : (errno = (err)) ) +# else /* !EOPNOTSUPP && !EFAULT && !EINVAL */ +# warning No suitable replacement for missing socket error code is found. Edit this file and add replacement code which is defined on system. +# define MHD_socket_set_error_(err) (errno = (err)) +# endif /* !EOPNOTSUPP && !EFAULT && !EINVAL*/ +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_socket_set_error_(err) ( (MHD_SCKT_MISSING_ERR_CODE_ == (err)) ? \ + (WSASetLastError((WSAEOPNOTSUPP))) : \ + (WSASetLastError((err))) ) +#endif /** - * Set last winsock error to equivalent of given errno value - * @param errnum the errno value to set + * Check whether given socket error is equal to specified system + * native MHD_SCKT_E*_ code. + * If platform don't have specific error code, result is + * always boolean false. + * @return boolean true if @a code is real error code and + * @a err equals to MHD_SCKT_E*_ @a code; + * boolean false otherwise */ - void MHD_W32_set_last_winsock_error_(int errnum); +#define MHD_SCKT_ERR_IS_(err,code) ( (MHD_SCKT_MISSING_ERR_CODE_ != (code)) && \ + ((code) == (err)) ) +/** + * Check whether last socket error is equal to specified system + * native MHD_SCKT_E*_ code. + * If platform don't have specific error code, result is + * always boolean false. + * @return boolean true if @a code is real error code and + * last socket error equals to MHD_SCKT_E*_ @a code; + * boolean false otherwise + */ +#define MHD_SCKT_LAST_ERR_IS_(code) MHD_SCKT_ERR_IS_(MHD_socket_get_error_() ,(code)) -#endif /* MHD_WINSOCK_SOCKETS */ +/* Specific error code checks */ + +/** + * Check whether given socket error is equal to system's + * socket error codes for EINTR. + * @return boolean true if @a err is equal to sockets' EINTR code; + * boolean false otherwise. + */ +#define MHD_SCKT_ERR_IS_EINTR_(err) MHD_SCKT_ERR_IS_((err),MHD_SCKT_EINTR_) + +/** + * Check whether given socket error is equal to system's + * socket error codes for EAGAIN or EWOULDBLOCK. + * @return boolean true if @a err is equal to sockets' EAGAIN or EWOULDBLOCK codes; + * boolean false otherwise. + */ +#if MHD_SCKT_EAGAIN_ == MHD_SCKT_EWOULDBLOCK_ +# define MHD_SCKT_ERR_IS_EAGAIN_(err) MHD_SCKT_ERR_IS_((err),MHD_SCKT_EAGAIN_) +#else /* MHD_SCKT_EAGAIN_ != MHD_SCKT_EWOULDBLOCK_ */ +# define MHD_SCKT_ERR_IS_EAGAIN_(err) ( MHD_SCKT_ERR_IS_((err),MHD_SCKT_EAGAIN_) || \ + MHD_SCKT_ERR_IS_((err),MHD_SCKT_EWOULDBLOCK_) ) +#endif /* MHD_SCKT_EAGAIN_ != MHD_SCKT_EWOULDBLOCK_ */ + +/** + * Check whether given socket error is any kind of "low resource" error. + * @return boolean true if @a err is any kind of "low resource" error, + * boolean false otherwise. + */ +#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err) ( MHD_SCKT_ERR_IS_((err),MHD_SCKT_EMFILE_) || \ + MHD_SCKT_ERR_IS_((err),MHD_SCKT_ENFILE_) || \ + MHD_SCKT_ERR_IS_((err),MHD_SCKT_ENOMEM_) || \ + MHD_SCKT_ERR_IS_((err),MHD_SCKT_ENOBUFS_) ) + +/** + * Check whether is given socket error is type of "incoming connection + * was disconnected before 'accept()' is called". + * @return boolean true is @a err match described socket error code, + * boolean false otherwise. + */ +#if defined(MHD_POSIX_SOCKETS) +# define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err) MHD_SCKT_ERR_IS_((err),MHD_SCKT_ECONNABORTED_) +#elif defined(MHD_WINSOCK_SOCKETS) +# define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err) MHD_SCKT_ERR_IS_((err),MHD_SCKT_ECONNRESET_) +#endif + +/** + * Check whether is given socket error is type of "connection was terminated + * by remote side". + * @return boolean true is @a err match described socket error code, + * boolean false otherwise. + */ +#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err) ( MHD_SCKT_ERR_IS_((err),MHD_SCKT_ECONNRESET_) || \ + MHD_SCKT_ERR_IS_((err),MHD_SCKT_ECONNABORTED_)) + +/* Specific error code set */ + +/** + * Set socket's error code to ENOMEM or equivalent if ENOMEM is not + * available on platform. + */ +#if MHD_SCKT_MISSING_ERR_CODE_ != MHD_SCKT_ENOMEM_ +# define MHD_socket_set_error_to_ENOMEM() MHD_socket_set_error_(MHD_SCKT_ENOMEM_) +#elif MHD_SCKT_MISSING_ERR_CODE_ != MHD_SCKT_ENOBUFS_ +# define MHD_socket_set_error_to_ENOMEM() MHD_socket_set_error_(MHD_SCKT_ENOBUFS_) +#else +# warning No suitable replacement for ENOMEM error codes is found. Edit this file and add replacement code which is defined on system. +# define MHD_socket_set_error_to_ENOMEM() MHD_socket_set_error_(MHD_SCKT_ENOMEM_) +#endif #endif /* ! MHD_SOCKETS_H */ |