mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-26 22:41:03 +08:00
Better error handling for RL NET
This commit is contained in:
parent
d1c9d7ffdc
commit
1612e1d142
116
mongoose.c
116
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
|
||||
|
41
mongoose.h
41
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
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
20
src/net_rl.h
20
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
|
||||
|
110
src/sock.c
110
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user