Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO on UDP sockets/netconn.

This commit is contained in:
fbernon 2007-03-08 20:58:46 +00:00
parent a868832776
commit fdcb87db19
9 changed files with 126 additions and 52 deletions

View File

@ -23,6 +23,11 @@ HISTORY
++ New features: ++ 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 2007-03-08 Simon Goldschmidt
* snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time.

View File

@ -226,7 +226,9 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
} }
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
conn->socket = 0; conn->socket = 0;
#if LWIP_SO_RCVTIMEO
conn->recv_timeout = 0; conn->recv_timeout = 0;
#endif /* LWIP_SO_RCVTIMEO */
conn->callback = callback; conn->callback = callback;
conn->recv_avail = 0; 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.msg.bc.port = proto; /* misusing the port field */
msg.msg.conn = conn; msg.msg.conn = conn;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
if ( conn->err != ERR_OK ) { if ( conn->err != ERR_OK ) {
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
@ -272,7 +274,7 @@ netconn_delete(struct netconn *conn)
msg.type = API_MSG_DELCONN; msg.type = API_MSG_DELCONN;
msg.msg.conn = conn; msg.msg.conn = conn;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
/* Drain the recvmbox. */ /* Drain the recvmbox. */
if (conn->recvmbox != SYS_MBOX_NULL) { 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.ipaddr = addr;
msg.msg.msg.bc.port = port; msg.msg.msg.bc.port = port;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
return conn->err; 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.ipaddr = addr;
msg.msg.msg.bc.port = port; msg.msg.msg.bc.port = port;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
return conn->err; return conn->err;
} }
@ -430,7 +432,7 @@ netconn_disconnect(struct netconn *conn)
msg.type = API_MSG_DISCONNECT; msg.type = API_MSG_DISCONNECT;
msg.msg.conn = conn; msg.msg.conn = conn;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
return conn->err; return conn->err;
} }
@ -454,7 +456,7 @@ netconn_listen(struct netconn *conn)
msg.type = API_MSG_LISTEN; msg.type = API_MSG_LISTEN;
msg.msg.conn = conn; msg.msg.conn = conn;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
return conn->err; return conn->err;
} }
@ -467,7 +469,7 @@ netconn_accept(struct netconn *conn)
return NULL; return NULL;
} }
sys_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0); sys_mbox_fetch(conn->acceptmbox, (void *)&newconn);
/* Register event with callback */ /* Register event with callback */
if (conn->callback) if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0); (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
@ -510,7 +512,7 @@ netconn_recv(struct netconn *conn)
return NULL; return NULL;
} }
sys_mbox_fetch(conn->recvmbox, (void *)&p, 0); sys_mbox_fetch(conn->recvmbox, (void *)&p);
if (p != NULL) if (p != NULL)
{ {
@ -548,9 +550,13 @@ netconn_recv(struct netconn *conn)
} }
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
} else { } 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) if (buf!=NULL)
{ conn->recv_avail -= buf->p->tot_len; { conn->recv_avail -= buf->p->tot_len;
/* Register event with callback */ /* Register event with callback */
@ -587,7 +593,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
msg.msg.msg.p = buf->p; msg.msg.msg.p = buf->p;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
return conn->err; 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)); LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
msg.msg.msg.w.len = len; msg.msg.msg.w.len = len;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
if (conn->err == ERR_OK) { if (conn->err == ERR_OK) {
dataptr = (void *)((u8_t *)dataptr + len); dataptr = (void *)((u8_t *)dataptr + len);
size -= len; size -= len;
@ -666,7 +672,7 @@ netconn_close(struct netconn *conn)
msg.type = API_MSG_CLOSE; msg.type = API_MSG_CLOSE;
msg.msg.conn = conn; msg.msg.conn = conn;
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL, 0); sys_mbox_fetch(conn->mbox, NULL);
if (conn->err == ERR_MEM && if (conn->err == ERR_MEM &&
conn->sem != SYS_SEM_NULL) { conn->sem != SYS_SEM_NULL) {
sys_sem_wait(conn->sem); sys_sem_wait(conn->sem);

View File

@ -34,17 +34,21 @@
#ifdef LWIP_DEBUG #ifdef LWIP_DEBUG
static const char *err_strerr[] = {"Ok.", static const char *err_strerr[] = {
"Out of memory error.", "Ok.", /* ERR_OK 0 */
"Buffer error.", "Out of memory error.", /* ERR_MEM -1 */
"Connection aborted.", "Buffer error.", /* ERR_BUF -2 */
"Connection reset.", "Connection aborted.", /* ERR_ABRT -3 */
"Connection closed.", "Connection reset.", /* ERR_RST -4 */
"Not connected.", "Connection closed.", /* ERR_CLSD -5 */
"Illegal value.", "Not connected.", /* ERR_CONN -6 */
"Illegal argument.", "Illegal value.", /* ERR_VAL -7 */
"Routing problem.", "Illegal argument.", /* ERR_ARG -8 */
"Address in use." "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 */
}; };

View File

@ -996,8 +996,11 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
/* UNIMPL case SO_DONTROUTE: */ /* UNIMPL case SO_DONTROUTE: */
case SO_ERROR: case SO_ERROR:
case SO_KEEPALIVE: case SO_KEEPALIVE:
/* UNIMPL case SO_CONTIMEO: */
/* UNIMPL case SO_SNDTIMEO: */ /* UNIMPL case SO_SNDTIMEO: */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
/* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */ /* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */ /* 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)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
break; break;
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
*(int *)optval = sock->conn->recv_timeout; *(int *)optval = sock->conn->recv_timeout;
break; break;
#endif /* LWIP_SO_RCVTIMEO */
} /* switch */ } /* switch */
break; 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_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */ /* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE: case SO_KEEPALIVE:
/* UNIMPL case case SO_CONTIMEO: */
/* UNIMPL case case SO_SNDTIMEO: */ /* UNIMPL case case SO_SNDTIMEO: */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
/* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */ /* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */ /* 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"))); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
break; break;
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO: case SO_RCVTIMEO:
sock->conn->recv_timeout = ( *(int*)optval ); sock->conn->recv_timeout = ( *(int*)optval );
break; break;
#endif /* LWIP_SO_RCVTIMEO */
} /* switch */ } /* switch */
break; break;

View File

@ -174,7 +174,7 @@ tcpip_thread(void *arg)
} }
while (1) { /* MAIN Loop */ while (1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg, 0); sys_mbox_fetch(mbox, (void *)&msg);
switch (msg->type) { switch (msg->type) {
case TCPIP_MSG_API: case TCPIP_MSG_API:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));

View File

@ -44,9 +44,11 @@ struct sswt_cb
}; };
#if LWIP_SO_RCVTIMEO
void void sys_mbox_fetch_timeout(sys_mbox_t mbox, void **msg, u32_t timeout)
sys_mbox_fetch(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; u32_t time;
struct sys_timeouts *timeouts; struct sys_timeouts *timeouts;
@ -54,47 +56,85 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
sys_timeout_handler h; sys_timeout_handler h;
void *arg; void *arg;
again: again:
timeouts = sys_arch_timeouts(); timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) { 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 { } else {
if (timeouts->next->time > 0) { if (timeouts->next->time > 0) {
#if LWIP_SO_RCVTIMEO
time = sys_arch_mbox_fetch(mbox, msg, (timeout?((timeout<timeouts->next->time)?timeout:timeouts->next->time):timeouts->next->time));
#else
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
#endif /* LWIP_SO_RCVTIMEO */
} else { } else {
time = SYS_ARCH_TIMEOUT; time = SYS_ARCH_TIMEOUT;
} }
if (time == SYS_ARCH_TIMEOUT) { if (time == SYS_ARCH_TIMEOUT) {
#if LWIP_SO_RCVTIMEO
if ((timeout) && (timeout<timeouts->next->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 /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
could be fetched. We should now call the timeout handler and could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */ deallocate the memory allocated for the timeout. */
tmptimeout = timeouts->next; tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next; timeouts->next = tmptimeout->next;
h = tmptimeout->h; h = tmptimeout->h;
arg = tmptimeout->arg; arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout); memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) { if (h != NULL) {
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg)); LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));
h(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. */ /* We try again to fetch a message from the mbox. */
goto again; goto again;
#if LWIP_SO_RCVTIMEO
}
#endif /* LWIP_SO_RCVTIMEO */
} else { } else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
occured. The time variable is set to the number of occured. The time variable is set to the number of
milliseconds we waited for the message. */ milliseconds we waited for the message. */
if (time <= timeouts->next->time) { if (time < timeouts->next->time) {
timeouts->next->time -= time; timeouts->next->time -= time;
} else { } 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 void
@ -106,9 +146,6 @@ sys_sem_wait(sys_sem_t sem)
sys_timeout_handler h; sys_timeout_handler h;
void *arg; void *arg;
/* while (sys_arch_sem_wait(sem, 1000) == 0);
return;*/
again: again:
timeouts = sys_arch_timeouts(); 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) {
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
could be fetched. We should now call the timeout handler and could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */ deallocate the memory allocated for the timeout. */
tmptimeout = timeouts->next; tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next; timeouts->next = tmptimeout->next;
h = tmptimeout->h; h = tmptimeout->h;
@ -141,12 +178,12 @@ sys_sem_wait(sys_sem_t sem)
goto again; goto again;
} else { } else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
occured. The time variable is set to the number of occured. The time variable is set to the number of
milliseconds we waited for the message. */ milliseconds we waited for the message. */
if (time <= timeouts->next->time) { if (time < timeouts->next->time) {
timeouts->next->time -= time; timeouts->next->time -= time;
} else { } else {
timeouts->next->time = 0; timeouts->next->time = 0;
} }
} }

View File

@ -92,7 +92,9 @@ struct netconn {
sys_mbox_t acceptmbox; sys_mbox_t acceptmbox;
sys_sem_t sem; sys_sem_t sem;
int socket; int socket;
#if LWIP_SO_RCVTIMEO
int recv_timeout; int recv_timeout;
#endif /* LWIP_SO_RCVTIMEO */
u16_t recv_avail; u16_t recv_avail;
void (* callback)(struct netconn *, enum netconn_evt, u16_t len); void (* callback)(struct netconn *, enum netconn_evt, u16_t len);
}; };

View File

@ -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 #define LWIP_POSIX_SOCKETS_IO_NAMES 1
#endif #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 */ /* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifndef SO_REUSE #ifndef SO_REUSE
#define SO_REUSE 0 #define SO_REUSE 0

View File

@ -53,7 +53,8 @@ struct sys_timeo {u8_t dummy;};
#define sys_sem_wait(s) #define sys_sem_wait(s)
#define sys_sem_free(s) #define sys_sem_free(s)
#define sys_mbox_new() 0 #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_post(m,d)
#define sys_mbox_free(m) #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); 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); 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_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. */ /* Thread functions. */
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio); sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio);