Implement SO_RCVTIMEO on UDP sockets/netconn.

This commit is contained in:
fbernon 2007-03-06 16:41:02 +00:00
parent 874bfe19d2
commit 7fd37d4e87
9 changed files with 129 additions and 106 deletions

View File

@ -23,6 +23,10 @@ HISTORY
++ New features: ++ New features:
2007-03-06 Frédéric Bernon
* api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h:
Implement SO_RCVTIMEO on UDP sockets/netconn.
2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt)
* api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated
on the stack and remove the API msg type from memp on the stack and remove the API msg type from memp

View File

@ -226,6 +226,7 @@ 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;
conn->recv_timeout = 0;
conn->callback = callback; conn->callback = callback;
conn->recv_avail = 0; conn->recv_avail = 0;
@ -233,7 +234,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); sys_mbox_fetch(conn->mbox, NULL, 0);
if ( conn->err != ERR_OK ) { if ( conn->err != ERR_OK ) {
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
@ -271,7 +272,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); sys_mbox_fetch(conn->mbox, NULL, 0);
/* Drain the recvmbox. */ /* Drain the recvmbox. */
if (conn->recvmbox != SYS_MBOX_NULL) { if (conn->recvmbox != SYS_MBOX_NULL) {
@ -386,7 +387,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); sys_mbox_fetch(conn->mbox, NULL, 0);
return conn->err; return conn->err;
} }
@ -413,7 +414,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); sys_mbox_fetch(conn->mbox, NULL, 0);
return conn->err; return conn->err;
} }
@ -429,7 +430,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); sys_mbox_fetch(conn->mbox, NULL, 0);
return conn->err; return conn->err;
} }
@ -453,7 +454,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); sys_mbox_fetch(conn->mbox, NULL, 0);
return conn->err; return conn->err;
} }
@ -466,7 +467,7 @@ netconn_accept(struct netconn *conn)
return NULL; return NULL;
} }
sys_mbox_fetch(conn->acceptmbox, (void *)&newconn); sys_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
/* 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);
@ -509,7 +510,7 @@ netconn_recv(struct netconn *conn)
return NULL; return NULL;
} }
sys_mbox_fetch(conn->recvmbox, (void *)&p); sys_mbox_fetch(conn->recvmbox, (void *)&p, 0);
if (p != NULL) if (p != NULL)
{ {
@ -547,14 +548,16 @@ netconn_recv(struct netconn *conn)
} }
api_msg_post(&msg); api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL); sys_mbox_fetch(conn->mbox, NULL, 0);
} else { } else {
sys_mbox_fetch(conn->recvmbox, (void *)&buf); sys_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout);
conn->recv_avail -= buf->p->tot_len; if (buf!=NULL)
{ conn->recv_avail -= buf->p->tot_len;
/* Register event with callback */ /* Register event with callback */
if (conn->callback) if (conn->callback)
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len); (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
} }
}
@ -584,7 +587,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); sys_mbox_fetch(conn->mbox, NULL, 0);
return conn->err; return conn->err;
} }
@ -632,7 +635,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); sys_mbox_fetch(conn->mbox, NULL, 0);
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;
@ -663,7 +666,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); sys_mbox_fetch(conn->mbox, NULL, 0);
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

@ -73,7 +73,7 @@ static sys_sem_t selectsem = 0;
static void static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
static int err_to_errno_table[11] = { static int err_to_errno_table[] = {
0, /* ERR_OK 0 No error, everything OK. */ 0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */ ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */ ENOBUFS, /* ERR_BUF -2 Buffer error. */
@ -84,7 +84,10 @@ static int err_to_errno_table[11] = {
EINVAL, /* ERR_VAL -7 Illegal value. */ EINVAL, /* ERR_VAL -7 Illegal value. */
EIO, /* ERR_ARG -8 Illegal argument. */ EIO, /* ERR_ARG -8 Illegal argument. */
EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */ EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */
EADDRINUSE /* ERR_USE -10 Address in use. */ EADDRINUSE, /* ERR_USE -10 Address in use. */
-1, /* ERR_IF -11 Low-level netif error */
-1, /* ERR_ISCONN -12 Already connected. */
ETIMEDOUT /* ERR_TIMEOUT -13 Timeout */
}; };
#define ERR_TO_ERRNO_TABLE_SIZE \ #define ERR_TO_ERRNO_TABLE_SIZE \
@ -367,8 +370,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
buf = sock->lastdata; buf = sock->lastdata;
} else { } else {
/* If this is non-blocking call, then check first */ /* If this is non-blocking call, then check first */
if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent)
&& !sock->rcvevent)
{ {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
sock_set_errno(sock, EWOULDBLOCK); sock_set_errno(sock, EWOULDBLOCK);
@ -382,7 +384,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
if (!buf) { if (!buf) {
/* We should really do some error checking here. */ /* We should really do some error checking here. */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s));
sock_set_errno(sock, 0); sock_set_errno(sock, (sock->conn->type==NETCONN_UDP)?ETIMEDOUT:0);
return 0; return 0;
} }
} }
@ -527,7 +529,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
struct lwip_socket *sock; struct lwip_socket *sock;
struct ip_addr remote_addr, addr; struct ip_addr remote_addr, addr;
u16_t remote_port, port; u16_t remote_port, port;
int ret,connected; int err,connected;
sock = get_socket(s); sock = get_socket(s);
if (!sock) { if (!sock) {
@ -547,7 +549,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
ret = lwip_send(s, data, size, flags); err = lwip_send(s, data, size, flags);
/* reset the remote address and port number /* reset the remote address and port number
of the connection */ of the connection */
@ -555,7 +557,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
netconn_connect(sock->conn, &addr, port); netconn_connect(sock->conn, &addr, port);
else else
netconn_disconnect(sock->conn); netconn_disconnect(sock->conn);
return ret; return err;
} }
int int
@ -994,6 +996,8 @@ 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_SNDTIMEO: */
case 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: */
@ -1119,6 +1123,10 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
sock->err = 0; sock->err = 0;
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;
case SO_RCVTIMEO:
*(int *)optval = sock->conn->recv_timeout;
break;
} /* switch */ } /* switch */
break; break;
@ -1183,6 +1191,8 @@ 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_SNDTIMEO: */
case 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: */
@ -1282,6 +1292,9 @@ 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;
case SO_RCVTIMEO:
sock->conn->recv_timeout = ( *(int*)optval );
break;
} /* switch */ } /* switch */
break; break;

View File

@ -156,7 +156,7 @@ tcpip_thread(void *arg)
} }
while (1) { /* MAIN Loop */ while (1) { /* MAIN Loop */
sys_mbox_fetch(mbox, (void *)&msg); sys_mbox_fetch(mbox, (void *)&msg, 0);
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

@ -46,7 +46,7 @@ struct sswt_cb
void void
sys_mbox_fetch(sys_mbox_t mbox, void **msg) sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{ {
u32_t time; u32_t time;
struct sys_timeouts *timeouts; struct sys_timeouts *timeouts;
@ -59,7 +59,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
timeouts = sys_arch_timeouts(); timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) { if (!timeouts || !timeouts->next) {
sys_arch_mbox_fetch(mbox, msg, 0); sys_arch_mbox_fetch(mbox, msg, timeout);
} else { } else {
if (timeouts->next->time > 0) { if (timeouts->next->time > 0) {
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);

View File

@ -92,6 +92,7 @@ struct netconn {
sys_mbox_t acceptmbox; sys_mbox_t acceptmbox;
sys_sem_t sem; sys_sem_t sem;
int socket; int socket;
int recv_timeout;
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

@ -61,6 +61,8 @@ typedef s8_t err_t;
#define ERR_IF -11 /* Low-level netif error */ #define ERR_IF -11 /* Low-level netif error */
#define ERR_ISCONN -12 /* Already connected. */ #define ERR_ISCONN -12 /* Already connected. */
#define ERR_TIMEOUT -13 /* Timeout. */
#ifdef LWIP_DEBUG #ifdef LWIP_DEBUG
extern const char *lwip_strerr(err_t err); extern const char *lwip_strerr(err_t err);

View File

@ -87,7 +87,7 @@ struct sockaddr {
#define SO_RCVTIMEO 0x1006 /* receive timeout */ #define SO_RCVTIMEO 0x1006 /* receive timeout */
#define SO_ERROR 0x1007 /* get error status and clear */ #define SO_ERROR 0x1007 /* get error status and clear */
#define SO_TYPE 0x1008 /* get socket type */ #define SO_TYPE 0x1008 /* get socket type */
#define SO_CONTIMEO 0x1009 /* connect timeout */
/* /*

View File

@ -53,7 +53,7 @@ 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) #define sys_mbox_fetch(m,d,t)
#define sys_mbox_post(m,d) #define sys_mbox_post(m,d)
#define sys_mbox_free(m) #define sys_mbox_free(m)
@ -116,7 +116,7 @@ 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); void sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
/* Thread functions. */ /* Thread functions. */