From fdcb87db192f6293a44e7f6d0f69aacd68a4bda0 Mon Sep 17 00:00:00 2001 From: fbernon Date: Thu, 8 Mar 2007 20:58:46 +0000 Subject: [PATCH] Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO on UDP sockets/netconn. --- CHANGELOG | 5 +++ src/api/api_lib.c | 32 +++++++++------- src/api/err.c | 26 +++++++------ src/api/sockets.c | 10 +++++ src/api/tcpip.c | 2 +- src/core/sys.c | 85 ++++++++++++++++++++++++++++++------------ src/include/lwip/api.h | 2 + src/include/lwip/opt.h | 5 +++ src/include/lwip/sys.h | 11 ++++-- 9 files changed, 126 insertions(+), 52 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e7b974b4..e43172c2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,11 @@ HISTORY ++ New features: + 2007-03-08 Frédéric Bernon + * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: + Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO + on UDP sockets/netconn. + 2007-03-08 Simon Goldschmidt * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. diff --git a/src/api/api_lib.c b/src/api/api_lib.c index fc7c29e9..0f98a65b 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -226,7 +226,9 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, } conn->state = NETCONN_NONE; conn->socket = 0; +#if LWIP_SO_RCVTIMEO conn->recv_timeout = 0; +#endif /* LWIP_SO_RCVTIMEO */ conn->callback = callback; conn->recv_avail = 0; @@ -234,7 +236,7 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, msg.msg.msg.bc.port = proto; /* misusing the port field */ msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); if ( conn->err != ERR_OK ) { memp_free(MEMP_NETCONN, conn); @@ -272,7 +274,7 @@ netconn_delete(struct netconn *conn) msg.type = API_MSG_DELCONN; msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); /* Drain the recvmbox. */ if (conn->recvmbox != SYS_MBOX_NULL) { @@ -387,7 +389,7 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, msg.msg.msg.bc.ipaddr = addr; msg.msg.msg.bc.port = port; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); return conn->err; } @@ -414,7 +416,7 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr, msg.msg.msg.bc.ipaddr = addr; msg.msg.msg.bc.port = port; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); return conn->err; } @@ -430,7 +432,7 @@ netconn_disconnect(struct netconn *conn) msg.type = API_MSG_DISCONNECT; msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); return conn->err; } @@ -454,7 +456,7 @@ netconn_listen(struct netconn *conn) msg.type = API_MSG_LISTEN; msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); return conn->err; } @@ -467,7 +469,7 @@ netconn_accept(struct netconn *conn) return NULL; } - sys_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0); + sys_mbox_fetch(conn->acceptmbox, (void *)&newconn); /* Register event with callback */ if (conn->callback) (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0); @@ -510,7 +512,7 @@ netconn_recv(struct netconn *conn) return NULL; } - sys_mbox_fetch(conn->recvmbox, (void *)&p, 0); + sys_mbox_fetch(conn->recvmbox, (void *)&p); if (p != NULL) { @@ -548,9 +550,13 @@ netconn_recv(struct netconn *conn) } api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); } else { - sys_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout); +#if LWIP_SO_RCVTIMEO + sys_mbox_fetch_timeout(conn->recvmbox, (void *)&buf, conn->recv_timeout); +#else + sys_mbox_fetch(conn->recvmbox, (void *)&buf); +#endif /* LWIP_SO_RCVTIMEO*/ if (buf!=NULL) { conn->recv_avail -= buf->p->tot_len; /* Register event with callback */ @@ -587,7 +593,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf) msg.msg.msg.p = buf->p; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); return conn->err; } @@ -635,7 +641,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy) LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy)); msg.msg.msg.w.len = len; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); if (conn->err == ERR_OK) { dataptr = (void *)((u8_t *)dataptr + len); size -= len; @@ -666,7 +672,7 @@ netconn_close(struct netconn *conn) msg.type = API_MSG_CLOSE; msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL, 0); + sys_mbox_fetch(conn->mbox, NULL); if (conn->err == ERR_MEM && conn->sem != SYS_SEM_NULL) { sys_sem_wait(conn->sem); diff --git a/src/api/err.c b/src/api/err.c index 6d784966..171e1cbc 100644 --- a/src/api/err.c +++ b/src/api/err.c @@ -34,17 +34,21 @@ #ifdef LWIP_DEBUG -static const char *err_strerr[] = {"Ok.", - "Out of memory error.", - "Buffer error.", - "Connection aborted.", - "Connection reset.", - "Connection closed.", - "Not connected.", - "Illegal value.", - "Illegal argument.", - "Routing problem.", - "Address in use." +static const char *err_strerr[] = { + "Ok.", /* ERR_OK 0 */ + "Out of memory error.", /* ERR_MEM -1 */ + "Buffer error.", /* ERR_BUF -2 */ + "Connection aborted.", /* ERR_ABRT -3 */ + "Connection reset.", /* ERR_RST -4 */ + "Connection closed.", /* ERR_CLSD -5 */ + "Not connected.", /* ERR_CONN -6 */ + "Illegal value.", /* ERR_VAL -7 */ + "Illegal argument.", /* ERR_ARG -8 */ + "Routing problem.", /* ERR_RTE -9 */ + "Address in use.", /* ERR_USE -10 */ + "Low-level netif error.", /* ERR_IF -11 */ + "Already connected.", /* ERR_ISCONN -12 */ + "Timeout." /* ERR_TIMEOUT -13 */ }; diff --git a/src/api/sockets.c b/src/api/sockets.c index 80284836..aaa8c762 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -996,8 +996,11 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt /* UNIMPL case SO_DONTROUTE: */ case SO_ERROR: case SO_KEEPALIVE: + /* UNIMPL case SO_CONTIMEO: */ /* UNIMPL case SO_SNDTIMEO: */ +#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ /* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_RCVBUF: */ /* UNIMPL case SO_SNDBUF: */ @@ -1124,9 +1127,11 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval)); break; +#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO: *(int *)optval = sock->conn->recv_timeout; break; +#endif /* LWIP_SO_RCVTIMEO */ } /* switch */ break; @@ -1191,8 +1196,11 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_ /* UNIMPL case SO_DEBUG: */ /* UNIMPL case SO_DONTROUTE: */ case SO_KEEPALIVE: + /* UNIMPL case case SO_CONTIMEO: */ /* UNIMPL case case SO_SNDTIMEO: */ +#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO: +#endif /* LWIP_SO_RCVTIMEO */ /* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_RCVBUF: */ /* UNIMPL case SO_SNDBUF: */ @@ -1292,9 +1300,11 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_ } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off"))); break; +#if LWIP_SO_RCVTIMEO case SO_RCVTIMEO: sock->conn->recv_timeout = ( *(int*)optval ); break; +#endif /* LWIP_SO_RCVTIMEO */ } /* switch */ break; diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 129f5fed..cc55756c 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -174,7 +174,7 @@ tcpip_thread(void *arg) } while (1) { /* MAIN Loop */ - sys_mbox_fetch(mbox, (void *)&msg, 0); + sys_mbox_fetch(mbox, (void *)&msg); switch (msg->type) { case TCPIP_MSG_API: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); diff --git a/src/core/sys.c b/src/core/sys.c index b70c9a4e..8ff288b4 100644 --- a/src/core/sys.c +++ b/src/core/sys.c @@ -44,9 +44,11 @@ struct sswt_cb }; - -void -sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) +#if LWIP_SO_RCVTIMEO +void sys_mbox_fetch_timeout(sys_mbox_t mbox, void **msg, u32_t timeout) +#else +void sys_mbox_fetch(sys_mbox_t mbox, void **msg) +#endif /* LWIP_SO_RCVTIMEO */ { u32_t time; struct sys_timeouts *timeouts; @@ -54,47 +56,85 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) sys_timeout_handler h; void *arg; - again: timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { - sys_arch_mbox_fetch(mbox, msg, timeout); +#if LWIP_SO_RCVTIMEO + time = sys_arch_mbox_fetch(mbox, msg, timeout); +#else + time = sys_arch_mbox_fetch(mbox, msg, 0); +#endif /* LWIP_SO_RCVTIMEO */ } else { if (timeouts->next->time > 0) { +#if LWIP_SO_RCVTIMEO + time = sys_arch_mbox_fetch(mbox, msg, (timeout?((timeoutnext->time)?timeout:timeouts->next->time):timeouts->next->time)); +#else time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); +#endif /* LWIP_SO_RCVTIMEO */ } else { time = SYS_ARCH_TIMEOUT; } if (time == SYS_ARCH_TIMEOUT) { +#if LWIP_SO_RCVTIMEO + if ((timeout) && (timeoutnext->time)) { + /* If time == SYS_ARCH_TIMEOUT, and we have wait "fetch's timeout" and not "timer's timeout", + The timeout variable is the number of milliseconds we have waited for the message. */ + if (timeout < timeouts->next->time) { + timeouts->next->time -= timeout; + } else { + timeouts->next->time = 0; + } + } else { + /* The timeouts->next->time variable is the number of milliseconds we have waited for the message. */ + if (timeouts->next->time < timeout) { + timeout -= timeouts->next->time; + } else { + if (timeout) timeout = SYS_ARCH_TIMEOUT; + } +#endif /* LWIP_SO_RCVTIMEO */ + /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message - could be fetched. We should now call the timeout handler and - deallocate the memory allocated for the timeout. */ + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ tmptimeout = timeouts->next; timeouts->next = tmptimeout->next; - h = tmptimeout->h; + h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (h != NULL) { LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg)); h(arg); } - + +#if LWIP_SO_RCVTIMEO + if (timeout != SYS_ARCH_TIMEOUT) +#endif /* LWIP_SO_RCVTIMEO */ + /* We try again to fetch a message from the mbox. */ goto again; +#if LWIP_SO_RCVTIMEO + } +#endif /* LWIP_SO_RCVTIMEO */ } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout - occured. The time variable is set to the number of - milliseconds we waited for the message. */ - if (time <= timeouts->next->time) { - timeouts->next->time -= time; + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time < timeouts->next->time) { + timeouts->next->time -= time; } else { - timeouts->next->time = 0; + timeouts->next->time = 0; } } } + +#if LWIP_SO_RCVTIMEO + if ((time == SYS_ARCH_TIMEOUT) && (msg)) + { (*msg)=NULL; + } +#endif /* LWIP_SO_RCVTIMEO */ } void @@ -106,9 +146,6 @@ sys_sem_wait(sys_sem_t sem) sys_timeout_handler h; void *arg; - /* while (sys_arch_sem_wait(sem, 1000) == 0); - return;*/ - again: timeouts = sys_arch_timeouts(); @@ -124,8 +161,8 @@ sys_sem_wait(sys_sem_t sem) if (time == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message - could be fetched. We should now call the timeout handler and - deallocate the memory allocated for the timeout. */ + could be fetched. We should now call the timeout handler and + deallocate the memory allocated for the timeout. */ tmptimeout = timeouts->next; timeouts->next = tmptimeout->next; h = tmptimeout->h; @@ -141,12 +178,12 @@ sys_sem_wait(sys_sem_t sem) goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout - occured. The time variable is set to the number of - milliseconds we waited for the message. */ - if (time <= timeouts->next->time) { - timeouts->next->time -= time; + occured. The time variable is set to the number of + milliseconds we waited for the message. */ + if (time < timeouts->next->time) { + timeouts->next->time -= time; } else { - timeouts->next->time = 0; + timeouts->next->time = 0; } } diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 758c7bf4..bf7b59d4 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -92,7 +92,9 @@ struct netconn { sys_mbox_t acceptmbox; sys_sem_t sem; int socket; +#if LWIP_SO_RCVTIMEO int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ u16_t recv_avail; void (* callback)(struct netconn *, enum netconn_evt, u16_t len); }; diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 665a3b57..0e1839ba 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -420,6 +420,11 @@ a lot of data that needs to be copied, this should be set high. */ #define LWIP_POSIX_SOCKETS_IO_NAMES 1 #endif +/* Enable SO_RCVTIMEO processing (only for UDP sockets) */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + /* Enable SO_REUSEADDR and SO_REUSEPORT options */ #ifndef SO_REUSE #define SO_REUSE 0 diff --git a/src/include/lwip/sys.h b/src/include/lwip/sys.h index d3d79396..6a429abc 100644 --- a/src/include/lwip/sys.h +++ b/src/include/lwip/sys.h @@ -53,7 +53,8 @@ struct sys_timeo {u8_t dummy;}; #define sys_sem_wait(s) #define sys_sem_free(s) #define sys_mbox_new() 0 -#define sys_mbox_fetch(m,d,t) +#define sys_mbox_fetch_timeout(m,d,t) +#define sys_mbox_fetch(m,d) #define sys_mbox_post(m,d) #define sys_mbox_free(m) @@ -116,8 +117,12 @@ sys_mbox_t sys_mbox_new(void); void sys_mbox_post(sys_mbox_t mbox, void *msg); u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); void sys_mbox_free(sys_mbox_t mbox); -void sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); - +#if LWIP_SO_RCVTIMEO +void sys_mbox_fetch_timeout(sys_mbox_t mbox, void **msg, u32_t timeout); +#define sys_mbox_fetch(m,d) sys_mbox_fetch_timeout(m,d,0) +#else +void sys_mbox_fetch(sys_mbox_t mbox, void **msg); +#endif /* LWIP_SO_RCVTIMEO */ /* Thread functions. */ sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio);