From 1612e1d14218afc785a0653f60746259e1fa4a5b Mon Sep 17 00:00:00 2001 From: cpq Date: Wed, 1 Feb 2023 12:25:30 +0000 Subject: [PATCH] Better error handling for RL NET --- mongoose.c | 116 ++++++++++++++++++++++------------------------- mongoose.h | 41 +++++++++++------ src/arch_win32.h | 21 +++++---- src/net_rl.h | 20 +++++--- src/sock.c | 110 +++++++++++++++++++++----------------------- 5 files changed, 158 insertions(+), 150 deletions(-) diff --git a/mongoose.c b/mongoose.c index b6d371d8..78f8a7ed 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4003,6 +4003,24 @@ struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url, #define AF_INET6 10 #endif +#ifndef MG_SOCK_ERR +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? errno : 0) +#endif + +#ifndef MG_SOCK_INTR +#define MG_SOCK_INTR(fd) (fd == MG_INVALID_SOCKET && MG_SOCK_ERR(-1) == EINTR) +#endif + +#ifndef MG_SOCK_PENDING +#define MG_SOCK_PENDING(errcode) \ + (((errcode) < 0) && (errno == EINPROGRESS || errno == EWOULDBLOCK)) +#endif + +#ifndef MG_SOCK_RESET +#define MG_SOCK_RESET(errcode) \ + (((errcode) < 0) && (errno == EPIPE || errno == ECONNRESET)) +#endif + union usa { struct sockaddr sa; struct sockaddr_in sin; @@ -4040,27 +4058,6 @@ static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { #endif } -static bool mg_sock_would_block(void) { - int err = MG_SOCKET_ERRNO; - return err == EINPROGRESS || err == EWOULDBLOCK -#ifndef WINCE - || err == EAGAIN || err == EINTR -#endif -#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK - || err == WSAEINTR || err == WSAEWOULDBLOCK -#endif - ; -} - -static bool mg_sock_conn_reset(void) { - int err = MG_SOCKET_ERRNO; -#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK - return err == WSAECONNRESET; -#else - return err == EPIPE || err == ECONNRESET; -#endif -} - static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { union usa usa; socklen_t n = sizeof(usa); @@ -4107,12 +4104,9 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { if (n > 0) setlocaddr(FD(c), &c->loc); } else { n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING); -#if MG_ARCH == MG_ARCH_RTX - if (n == EWOULDBLOCK) return MG_IO_WAIT; -#endif } - if (n < 0 && mg_sock_would_block()) return MG_IO_WAIT; - if (n < 0 && mg_sock_conn_reset()) return MG_IO_RESET; + if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; + if (MG_SOCK_RESET(n)) return MG_IO_RESET; if (n <= 0) return MG_IO_ERR; return n; } @@ -4121,7 +4115,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { if (c->is_udp) { long n = mg_io_send(c, buf, len); MG_DEBUG(("%lu %p %d:%d %ld err %d", c->id, c->fd, (int) c->send.len, - (int) c->recv.len, n, MG_SOCKET_ERRNO)); + (int) c->recv.len, n, MG_SOCK_ERR(n))); iolog(c, (char *) buf, n, false); return n > 0; } else { @@ -4169,17 +4163,17 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { } else { union usa usa; socklen_t slen = tousa(&c->loc, &usa); - int on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET; + int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET; int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM; int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP; (void) on; if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) { - MG_ERROR(("socket: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("socket: %d", MG_SOCK_ERR(-1))); #if ((MG_ARCH == MG_ARCH_WIN32) || (MG_ARCH == MG_ARCH_UNIX) || \ (defined(LWIP_SOCKET) && SO_REUSE == 1)) - } else if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, - sizeof(on)) != 0) { + } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, + sizeof(on))) != 0) { // 1. SO_RESUSEADDR is not enabled on Windows because the semantics of // SO_REUSEADDR on UNIX and Windows is different. On Windows, // SO_REUSEADDR allows to bind a socket to a port without error even @@ -4191,21 +4185,21 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { // defining // SO_REUSE (in lwipopts.h), otherwise the code below will compile // but won't work! (setsockopt will return EINVAL) - MG_ERROR(("reuseaddr: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("reuseaddr: %d", MG_SOCK_ERR(rc))); #endif #if MG_ARCH == MG_ARCH_WIN32 && !defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE) - } else if (setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &on, - sizeof(on)) != 0) { + } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, + (char *) &on, sizeof(on))) != 0) { // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" - MG_ERROR(("exclusiveaddruse: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("exclusiveaddruse: %d", MG_SOCK_ERR(rc))); #endif - } else if (bind(fd, &usa.sa, slen) != 0) { - MG_ERROR(("bind: %d", MG_SOCKET_ERRNO)); + } else if ((rc = bind(fd, &usa.sa, slen)) != 0) { + MG_ERROR(("bind: %d", MG_SOCK_ERR(rc))); } else if ((type == SOCK_STREAM && - listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE) != 0)) { + (rc = listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE)) != 0)) { // NOTE(lsm): FreeRTOS uses backlog value as a connection limit // In case port was set to 0, get the real port number - MG_ERROR(("listen: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("listen: %d", MG_SOCK_ERR(rc))); } else { setlocaddr(fd, &c->loc); mg_set_non_blocking_mode(fd); @@ -4228,8 +4222,8 @@ long mg_io_recv(struct mg_connection *c, void *buf, size_t len) { } else { n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING); } - if (n < 0 && mg_sock_would_block()) return MG_IO_WAIT; - if (n < 0 && mg_sock_conn_reset()) return MG_IO_RESET; + if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; + if (MG_SOCK_RESET(n)) return MG_IO_RESET; if (n <= 0) return MG_IO_ERR; return n; } @@ -4249,7 +4243,7 @@ static void read_conn(struct mg_connection *c) { n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_io_recv(c, buf, len); MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCKET_ERRNO)); + (long) c->recv.size, n, MG_SOCK_ERR(n))); iolog(c, buf, n, true); } } @@ -4260,7 +4254,7 @@ static void write_conn(struct mg_connection *c) { long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len); MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCKET_ERRNO)); + (long) c->recv.size, n, MG_SOCK_ERR(n))); iolog(c, buf, n, false); } @@ -4314,14 +4308,14 @@ void mg_connect_resolved(struct mg_connection *c) { c->fd = S2PTR(socket(af, type, 0)); // Create outbound socket c->is_resolving = 0; // Clear resolving flag if (FD(c) == MG_INVALID_SOCKET) { - mg_error(c, "socket(): %d", MG_SOCKET_ERRNO); + mg_error(c, "socket(): %d", MG_SOCK_ERR(-1)); } else if (c->is_udp) { MG_EPOLL_ADD(c); #if MG_ARCH == MG_ARCH_TIRTOS union usa usa; // TI-RTOS NDK requires binding to receive on UDP sockets socklen_t slen = tousa(&c->loc, &usa); - if (bind(c->fd, &usa.sa, slen) != 0) - MG_ERROR(("bind: %d", MG_SOCKET_ERRNO)); + if ((rc = bind(c->fd, &usa.sa, slen)) != 0) + MG_ERROR(("bind: %d", MG_SOCK_ERR(rc))); #endif mg_call(c, MG_EV_RESOLVE, NULL); mg_call(c, MG_EV_CONNECT, NULL); @@ -4332,26 +4326,26 @@ void mg_connect_resolved(struct mg_connection *c) { setsockopts(c); MG_EPOLL_ADD(c); mg_call(c, MG_EV_RESOLVE, NULL); - if ((rc = connect(FD(c), &usa.sa, slen)) == 0) { - mg_call(c, MG_EV_CONNECT, NULL); - } else if (mg_sock_would_block()) { + rc = connect(FD(c), &usa.sa, slen); // Attempt to connect + if (rc == 0) { // Success + mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user + } else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake MG_DEBUG(("%lu %p -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem)); c->is_connecting = 1; } else { - mg_error(c, "connect: %d", MG_SOCKET_ERRNO); + mg_error(c, "connect: %d", MG_SOCK_ERR(rc)); } } - (void) rc; } static MG_SOCKET_TYPE raccept(MG_SOCKET_TYPE sock, union usa *usa, socklen_t *len) { - MG_SOCKET_TYPE s = MG_INVALID_SOCKET; + MG_SOCKET_TYPE fd = MG_INVALID_SOCKET; do { memset(usa, 0, sizeof(*usa)); - s = accept(sock, &usa->sa, len); - } while (s == MG_INVALID_SOCKET && errno == EINTR); - return s; + fd = accept(sock, &usa->sa, len); + } while (MG_SOCK_INTR(fd)); + return fd; } static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { @@ -4364,9 +4358,9 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { // AzureRTOS, in non-block socket mode can mark listening socket readable // even it is not. See comment for 'select' func implementation in // nx_bsd.c That's not an error, just should try later - if (MG_SOCKET_ERRNO != EAGAIN) + if (errno != EAGAIN) #endif - MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCKET_ERRNO)); + MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERR(-1))); #if (MG_ARCH != MG_ARCH_WIN32) && !MG_ENABLE_FREERTOS_TCP && \ (MG_ARCH != MG_ARCH_TIRTOS) && !MG_ENABLE_POLL } else if ((long) fd >= FD_SETSIZE) { @@ -4576,7 +4570,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { #if MG_ARCH == MG_ARCH_WIN32 if (maxfd == 0) Sleep(ms); // On Windows, select fails if no sockets #else - MG_ERROR(("select: %d %d", rc, MG_SOCKET_ERRNO)); + MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc))); #endif FD_ZERO(&rset); FD_ZERO(&wset); @@ -5352,6 +5346,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { if (opts->srvname.len > 0) { char *s = mg_mprintf("%.*s", (int) opts->srvname.len, opts->srvname.ptr); SSL_set1_host(tls->ssl, s); + SSL_set_tlsext_host_name(tls->ssl, s); free(s); } #endif @@ -6110,7 +6105,6 @@ static size_t mip_driver_stm32_tx(const void *buf, size_t len, struct mip_if *if s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over if (++s_txno >= ETH_DESC_CNT) s_txno = 0; - printf("sent\n"); } ETH->DMASR = BIT(2) | BIT(5); // Clear any prior TBUS/TUS ETH->DMATPDR = 0; // and resume @@ -6124,11 +6118,9 @@ static bool mip_driver_stm32_up(struct mip_if *ifp) { return bsr & BIT(2) ? 1 : 0; } -static uint32_t s_rxno; void ETH_IRQHandler(void); +static uint32_t s_rxno; void ETH_IRQHandler(void) { - static int cnt; - printf("--> %d\n", cnt++); qp_mark(QP_IRQTRIGGERED, 0); if (ETH->DMASR & BIT(6)) { // Frame received, loop ETH->DMASR = BIT(16) | BIT(6); // Clear flag diff --git a/mongoose.h b/mongoose.h index 544b90f6..70470b96 100644 --- a/mongoose.h +++ b/mongoose.h @@ -403,7 +403,6 @@ typedef enum { false = 0, true = 1 } bool; #define MG_INVALID_SOCKET INVALID_SOCKET #define MG_SOCKET_TYPE SOCKET typedef unsigned long nfds_t; -#define MG_SOCKET_ERRNO WSAGetLastError() #if defined(_MSC_VER) #pragma comment(lib, "ws2_32.lib") #ifndef alloca @@ -411,9 +410,6 @@ typedef unsigned long nfds_t; #endif #endif #define poll(a, b, c) WSAPoll((a), (b), (c)) -#ifndef SO_EXCLUSIVEADDRUSE -#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) -#endif #define closesocket(x) closesocket(x) typedef int socklen_t; @@ -423,13 +419,20 @@ typedef int socklen_t; #define MG_PATH_MAX FILENAME_MAX #endif -#ifndef EINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK +#ifndef SO_EXCLUSIVEADDRUSE +#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) #endif +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0) + +#define MG_SOCK_PENDING(errcode) \ + (((errcode) < 0) && \ + (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || \ + WSAGetLastError() == WSAEWOULDBLOCK)) + +#define MG_SOCK_RESET(errcode) \ + (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET)) + #define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX) #define sleep(x) Sleep(x) #define mkdir(a, b) _mkdir(a) @@ -568,13 +571,21 @@ struct timeval { #define MG_ENABLE_CUSTOM_MILLIS 1 #define closesocket(x) closesocket(x) #define mkdir(a, b) (-1) -#define EWOULDBLOCK BSD_EWOULDBLOCK -#define EAGAIN BSD_EWOULDBLOCK -#define EINPROGRESS BSD_EWOULDBLOCK -#define EINTR BSD_EWOULDBLOCK -#define ECONNRESET BSD_ECONNRESET -#define EPIPE BSD_ECONNRESET + #define TCP_NODELAY SO_KEEPALIVE + +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0) + +#define MG_SOCK_PENDING(errcode) \ + ((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || \ + (errcode) == BSD_EINPROGRESS) + +#define MG_SOCK_RESET(errcode) \ + ((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET) + +#define MG_SOCK_INTR(fd) 0 + +#define socklen_t int #endif diff --git a/src/arch_win32.h b/src/arch_win32.h index 2b1f8ae6..121d5c39 100644 --- a/src/arch_win32.h +++ b/src/arch_win32.h @@ -63,7 +63,6 @@ typedef enum { false = 0, true = 1 } bool; #define MG_INVALID_SOCKET INVALID_SOCKET #define MG_SOCKET_TYPE SOCKET typedef unsigned long nfds_t; -#define MG_SOCKET_ERRNO WSAGetLastError() #if defined(_MSC_VER) #pragma comment(lib, "ws2_32.lib") #ifndef alloca @@ -71,9 +70,6 @@ typedef unsigned long nfds_t; #endif #endif #define poll(a, b, c) WSAPoll((a), (b), (c)) -#ifndef SO_EXCLUSIVEADDRUSE -#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) -#endif #define closesocket(x) closesocket(x) typedef int socklen_t; @@ -83,13 +79,20 @@ typedef int socklen_t; #define MG_PATH_MAX FILENAME_MAX #endif -#ifndef EINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK +#ifndef SO_EXCLUSIVEADDRUSE +#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) #endif +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? WSAGetLastError() : 0) + +#define MG_SOCK_PENDING(errcode) \ + (((errcode) < 0) && \ + (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS || \ + WSAGetLastError() == WSAEWOULDBLOCK)) + +#define MG_SOCK_RESET(errcode) \ + (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET)) + #define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX) #define sleep(x) Sleep(x) #define mkdir(a, b) _mkdir(a) diff --git a/src/net_rl.h b/src/net_rl.h index 28b7bd54..2e4b6874 100644 --- a/src/net_rl.h +++ b/src/net_rl.h @@ -6,11 +6,19 @@ #define MG_ENABLE_CUSTOM_MILLIS 1 #define closesocket(x) closesocket(x) #define mkdir(a, b) (-1) -#define EWOULDBLOCK BSD_EWOULDBLOCK -#define EAGAIN BSD_EWOULDBLOCK -#define EINPROGRESS BSD_EWOULDBLOCK -#define EINTR BSD_EWOULDBLOCK -#define ECONNRESET BSD_ECONNRESET -#define EPIPE BSD_ECONNRESET + #define TCP_NODELAY SO_KEEPALIVE + +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? (errcode) : 0) + +#define MG_SOCK_PENDING(errcode) \ + ((errcode) == BSD_EWOULDBLOCK || (errcode) == BSD_EALREADY || \ + (errcode) == BSD_EINPROGRESS) + +#define MG_SOCK_RESET(errcode) \ + ((errcode) == BSD_ECONNABORTED || (errcode) == BSD_ECONNRESET) + +#define MG_SOCK_INTR(fd) 0 + +#define socklen_t int #endif diff --git a/src/sock.c b/src/sock.c index cba4edff..aaf58ca9 100644 --- a/src/sock.c +++ b/src/sock.c @@ -25,6 +25,24 @@ #define AF_INET6 10 #endif +#ifndef MG_SOCK_ERR +#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? errno : 0) +#endif + +#ifndef MG_SOCK_INTR +#define MG_SOCK_INTR(fd) (fd == MG_INVALID_SOCKET && MG_SOCK_ERR(-1) == EINTR) +#endif + +#ifndef MG_SOCK_PENDING +#define MG_SOCK_PENDING(errcode) \ + (((errcode) < 0) && (errno == EINPROGRESS || errno == EWOULDBLOCK)) +#endif + +#ifndef MG_SOCK_RESET +#define MG_SOCK_RESET(errcode) \ + (((errcode) < 0) && (errno == EPIPE || errno == ECONNRESET)) +#endif + union usa { struct sockaddr sa; struct sockaddr_in sin; @@ -62,27 +80,6 @@ static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { #endif } -static bool mg_sock_would_block(void) { - int err = MG_SOCKET_ERRNO; - return err == EINPROGRESS || err == EWOULDBLOCK -#ifndef WINCE - || err == EAGAIN || err == EINTR -#endif -#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK - || err == WSAEINTR || err == WSAEWOULDBLOCK -#endif - ; -} - -static bool mg_sock_conn_reset(void) { - int err = MG_SOCKET_ERRNO; -#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK - return err == WSAECONNRESET; -#else - return err == EPIPE || err == ECONNRESET; -#endif -} - static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { union usa usa; socklen_t n = sizeof(usa); @@ -129,12 +126,9 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { if (n > 0) setlocaddr(FD(c), &c->loc); } else { n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING); -#if MG_ARCH == MG_ARCH_RTX - if (n == EWOULDBLOCK) return MG_IO_WAIT; -#endif } - if (n < 0 && mg_sock_would_block()) return MG_IO_WAIT; - if (n < 0 && mg_sock_conn_reset()) return MG_IO_RESET; + if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; + if (MG_SOCK_RESET(n)) return MG_IO_RESET; if (n <= 0) return MG_IO_ERR; return n; } @@ -143,7 +137,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) { if (c->is_udp) { long n = mg_io_send(c, buf, len); MG_DEBUG(("%lu %p %d:%d %ld err %d", c->id, c->fd, (int) c->send.len, - (int) c->recv.len, n, MG_SOCKET_ERRNO)); + (int) c->recv.len, n, MG_SOCK_ERR(n))); iolog(c, (char *) buf, n, false); return n > 0; } else { @@ -191,17 +185,17 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { } else { union usa usa; socklen_t slen = tousa(&c->loc, &usa); - int on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET; + int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET; int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM; int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP; (void) on; if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) { - MG_ERROR(("socket: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("socket: %d", MG_SOCK_ERR(-1))); #if ((MG_ARCH == MG_ARCH_WIN32) || (MG_ARCH == MG_ARCH_UNIX) || \ (defined(LWIP_SOCKET) && SO_REUSE == 1)) - } else if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, - sizeof(on)) != 0) { + } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, + sizeof(on))) != 0) { // 1. SO_RESUSEADDR is not enabled on Windows because the semantics of // SO_REUSEADDR on UNIX and Windows is different. On Windows, // SO_REUSEADDR allows to bind a socket to a port without error even @@ -213,21 +207,21 @@ bool mg_open_listener(struct mg_connection *c, const char *url) { // defining // SO_REUSE (in lwipopts.h), otherwise the code below will compile // but won't work! (setsockopt will return EINVAL) - MG_ERROR(("reuseaddr: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("reuseaddr: %d", MG_SOCK_ERR(rc))); #endif #if MG_ARCH == MG_ARCH_WIN32 && !defined(SO_EXCLUSIVEADDRUSE) && !defined(WINCE) - } else if (setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &on, - sizeof(on)) != 0) { + } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, + (char *) &on, sizeof(on))) != 0) { // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" - MG_ERROR(("exclusiveaddruse: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("exclusiveaddruse: %d", MG_SOCK_ERR(rc))); #endif - } else if (bind(fd, &usa.sa, slen) != 0) { - MG_ERROR(("bind: %d", MG_SOCKET_ERRNO)); + } else if ((rc = bind(fd, &usa.sa, slen)) != 0) { + MG_ERROR(("bind: %d", MG_SOCK_ERR(rc))); } else if ((type == SOCK_STREAM && - listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE) != 0)) { + (rc = listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE)) != 0)) { // NOTE(lsm): FreeRTOS uses backlog value as a connection limit // In case port was set to 0, get the real port number - MG_ERROR(("listen: %d", MG_SOCKET_ERRNO)); + MG_ERROR(("listen: %d", MG_SOCK_ERR(rc))); } else { setlocaddr(fd, &c->loc); mg_set_non_blocking_mode(fd); @@ -250,8 +244,8 @@ long mg_io_recv(struct mg_connection *c, void *buf, size_t len) { } else { n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING); } - if (n < 0 && mg_sock_would_block()) return MG_IO_WAIT; - if (n < 0 && mg_sock_conn_reset()) return MG_IO_RESET; + if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; + if (MG_SOCK_RESET(n)) return MG_IO_RESET; if (n <= 0) return MG_IO_ERR; return n; } @@ -271,7 +265,7 @@ static void read_conn(struct mg_connection *c) { n = c->is_tls ? mg_tls_recv(c, buf, len) : mg_io_recv(c, buf, len); MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCKET_ERRNO)); + (long) c->recv.size, n, MG_SOCK_ERR(n))); iolog(c, buf, n, true); } } @@ -282,7 +276,7 @@ static void write_conn(struct mg_connection *c) { long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len); MG_DEBUG(("%lu %p snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd, (long) c->send.len, (long) c->send.size, (long) c->recv.len, - (long) c->recv.size, n, MG_SOCKET_ERRNO)); + (long) c->recv.size, n, MG_SOCK_ERR(n))); iolog(c, buf, n, false); } @@ -336,14 +330,14 @@ void mg_connect_resolved(struct mg_connection *c) { c->fd = S2PTR(socket(af, type, 0)); // Create outbound socket c->is_resolving = 0; // Clear resolving flag if (FD(c) == MG_INVALID_SOCKET) { - mg_error(c, "socket(): %d", MG_SOCKET_ERRNO); + mg_error(c, "socket(): %d", MG_SOCK_ERR(-1)); } else if (c->is_udp) { MG_EPOLL_ADD(c); #if MG_ARCH == MG_ARCH_TIRTOS union usa usa; // TI-RTOS NDK requires binding to receive on UDP sockets socklen_t slen = tousa(&c->loc, &usa); - if (bind(c->fd, &usa.sa, slen) != 0) - MG_ERROR(("bind: %d", MG_SOCKET_ERRNO)); + if ((rc = bind(c->fd, &usa.sa, slen)) != 0) + MG_ERROR(("bind: %d", MG_SOCK_ERR(rc))); #endif mg_call(c, MG_EV_RESOLVE, NULL); mg_call(c, MG_EV_CONNECT, NULL); @@ -354,26 +348,26 @@ void mg_connect_resolved(struct mg_connection *c) { setsockopts(c); MG_EPOLL_ADD(c); mg_call(c, MG_EV_RESOLVE, NULL); - if ((rc = connect(FD(c), &usa.sa, slen)) == 0) { - mg_call(c, MG_EV_CONNECT, NULL); - } else if (mg_sock_would_block()) { + rc = connect(FD(c), &usa.sa, slen); // Attempt to connect + if (rc == 0) { // Success + mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user + } else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake MG_DEBUG(("%lu %p -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem)); c->is_connecting = 1; } else { - mg_error(c, "connect: %d", MG_SOCKET_ERRNO); + mg_error(c, "connect: %d", MG_SOCK_ERR(rc)); } } - (void) rc; } static MG_SOCKET_TYPE raccept(MG_SOCKET_TYPE sock, union usa *usa, socklen_t *len) { - MG_SOCKET_TYPE s = MG_INVALID_SOCKET; + MG_SOCKET_TYPE fd = MG_INVALID_SOCKET; do { memset(usa, 0, sizeof(*usa)); - s = accept(sock, &usa->sa, len); - } while (s == MG_INVALID_SOCKET && errno == EINTR); - return s; + fd = accept(sock, &usa->sa, len); + } while (MG_SOCK_INTR(fd)); + return fd; } static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { @@ -386,9 +380,9 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) { // AzureRTOS, in non-block socket mode can mark listening socket readable // even it is not. See comment for 'select' func implementation in // nx_bsd.c That's not an error, just should try later - if (MG_SOCKET_ERRNO != EAGAIN) + if (errno != EAGAIN) #endif - MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCKET_ERRNO)); + MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERR(-1))); #if (MG_ARCH != MG_ARCH_WIN32) && !MG_ENABLE_FREERTOS_TCP && \ (MG_ARCH != MG_ARCH_TIRTOS) && !MG_ENABLE_POLL } else if ((long) fd >= FD_SETSIZE) { @@ -598,7 +592,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) { #if MG_ARCH == MG_ARCH_WIN32 if (maxfd == 0) Sleep(ms); // On Windows, select fails if no sockets #else - MG_ERROR(("select: %d %d", rc, MG_SOCKET_ERRNO)); + MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc))); #endif FD_ZERO(&rset); FD_ZERO(&wset);