diff --git a/CHANGELOG b/CHANGELOG index 34cff580..c2149e8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,10 @@ HISTORY * [Enter new changes just after this line - do not remove this line] ++ 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) * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated diff --git a/src/api/api_lib.c b/src/api/api_lib.c index e042f385..fc7c29e9 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -224,16 +224,17 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, memp_free(MEMP_NETCONN, conn); return NULL; } - conn->state = NETCONN_NONE; - conn->socket = 0; - conn->callback = callback; - conn->recv_avail = 0; + conn->state = NETCONN_NONE; + conn->socket = 0; + conn->recv_timeout = 0; + conn->callback = callback; + conn->recv_avail = 0; msg.type = API_MSG_NEWCONN; msg.msg.msg.bc.port = proto; /* misusing the port field */ msg.msg.conn = conn; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); if ( conn->err != ERR_OK ) { memp_free(MEMP_NETCONN, conn); @@ -271,7 +272,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); + sys_mbox_fetch(conn->mbox, NULL, 0); /* Drain the recvmbox. */ 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.port = port; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); 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.port = port; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); return conn->err; } @@ -429,7 +430,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); + sys_mbox_fetch(conn->mbox, NULL, 0); return conn->err; } @@ -453,7 +454,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); + sys_mbox_fetch(conn->mbox, NULL, 0); return conn->err; } @@ -466,7 +467,7 @@ netconn_accept(struct netconn *conn) return NULL; } - sys_mbox_fetch(conn->acceptmbox, (void *)&newconn); + sys_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0); /* Register event with callback */ if (conn->callback) (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0); @@ -481,7 +482,7 @@ netconn_recv(struct netconn *conn) struct netbuf *buf = NULL; struct pbuf *p; u16_t len; - + if (conn == NULL) { return NULL; } @@ -509,7 +510,7 @@ netconn_recv(struct netconn *conn) return NULL; } - sys_mbox_fetch(conn->recvmbox, (void *)&p); + sys_mbox_fetch(conn->recvmbox, (void *)&p, 0); if (p != NULL) { @@ -547,13 +548,15 @@ netconn_recv(struct netconn *conn) } api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); } else { - sys_mbox_fetch(conn->recvmbox, (void *)&buf); - conn->recv_avail -= buf->p->tot_len; - /* Register event with callback */ - if (conn->callback) - (*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len); + sys_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout); + if (buf!=NULL) + { conn->recv_avail -= buf->p->tot_len; + /* Register event with callback */ + if (conn->callback) + (*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; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); 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)); msg.msg.msg.w.len = len; api_msg_post(&msg); - sys_mbox_fetch(conn->mbox, NULL); + sys_mbox_fetch(conn->mbox, NULL, 0); if (conn->err == ERR_OK) { dataptr = (void *)((u8_t *)dataptr + len); size -= len; @@ -663,7 +666,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); + sys_mbox_fetch(conn->mbox, NULL, 0); if (conn->err == ERR_MEM && conn->sem != SYS_SEM_NULL) { sys_sem_wait(conn->sem); diff --git a/src/api/sockets.c b/src/api/sockets.c index 75539f5c..80284836 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -73,18 +73,21 @@ static sys_sem_t selectsem = 0; static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -static int err_to_errno_table[11] = { - 0, /* ERR_OK 0 No error, everything OK. */ - ENOMEM, /* ERR_MEM -1 Out of memory error. */ - ENOBUFS, /* ERR_BUF -2 Buffer error. */ - ECONNABORTED, /* ERR_ABRT -3 Connection aborted. */ - ECONNRESET, /* ERR_RST -4 Connection reset. */ - ESHUTDOWN, /* ERR_CLSD -5 Connection closed. */ - ENOTCONN, /* ERR_CONN -6 Not connected. */ - EINVAL, /* ERR_VAL -7 Illegal value. */ - EIO, /* ERR_ARG -8 Illegal argument. */ - EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */ - EADDRINUSE /* ERR_USE -10 Address in use. */ +static int err_to_errno_table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + ECONNABORTED, /* ERR_ABRT -3 Connection aborted. */ + ECONNRESET, /* ERR_RST -4 Connection reset. */ + ESHUTDOWN, /* ERR_CLSD -5 Connection closed. */ + ENOTCONN, /* ERR_CONN -6 Not connected. */ + EINVAL, /* ERR_VAL -7 Illegal value. */ + EIO, /* ERR_ARG -8 Illegal argument. */ + EHOSTUNREACH, /* ERR_RTE -9 Routing problem. */ + 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 \ @@ -146,13 +149,13 @@ alloc_socket(struct netconn *newconn) /* allocate a new socket identifier */ for(i = 0; i < NUM_SOCKETS; ++i) { if (!sockets[i].conn) { - sockets[i].conn = newconn; - sockets[i].lastdata = NULL; + sockets[i].conn = newconn; + sockets[i].lastdata = NULL; sockets[i].lastoffset = 0; - sockets[i].rcvevent = 0; - sockets[i].sendevent = 1; /* TCP send buf is empty */ - sockets[i].flags = 0; - sockets[i].err = 0; + sockets[i].rcvevent = 0; + sockets[i].sendevent = 1; /* TCP send buf is empty */ + sockets[i].flags = 0; + sockets[i].err = 0; sys_sem_signal(socksem); return i; } @@ -349,10 +352,10 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, struct sockaddr *from, socklen_t *fromlen) { struct lwip_socket *sock; - struct netbuf *buf; - u16_t buflen, copylen; - struct ip_addr *addr; - u16_t port; + struct netbuf *buf; + u16_t buflen, copylen; + struct ip_addr *addr; + u16_t port; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags)); @@ -364,44 +367,43 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, /* Check if there is data left from the last recv operation. */ if (sock->lastdata) { - buf = sock->lastdata; - } else { - /* If this is non-blocking call, then check first */ - if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) - && !sock->rcvevent) - { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); - sock_set_errno(sock, EWOULDBLOCK); - return -1; - } - - /* No data was left from the previous operation, so we try to get - some from the network. */ - buf = netconn_recv(sock->conn); - - if (!buf) { - /* We should really do some error checking here. */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s)); - sock_set_errno(sock, 0); - return 0; - } - } + buf = sock->lastdata; + } else { + /* If this is non-blocking call, then check first */ + if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) + { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); + sock_set_errno(sock, EWOULDBLOCK); + return -1; + } + + /* No data was left from the previous operation, so we try to get + some from the network. */ + buf = netconn_recv(sock->conn); + + if (!buf) { + /* We should really do some error checking here. */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL!\n", s)); + sock_set_errno(sock, (sock->conn->type==NETCONN_UDP)?ETIMEDOUT:0); + return 0; + } + } buflen = netbuf_len(buf); buflen -= sock->lastoffset; - + if (len > buflen) { - copylen = buflen; - } else { - copylen = len; - } - + copylen = buflen; + } else { + copylen = len; + } + /* copy the contents of the received buffer into - the supplied memory pointer mem */ + the supplied memory pointer mem */ netbuf_copy_partial(buf, mem, copylen, sock->lastoffset); - /* Check to see from where the data was. */ + /* Check to see from where the data was.*/ if (from && fromlen) { struct sockaddr_in sin; @@ -527,7 +529,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags, struct lwip_socket *sock; struct ip_addr remote_addr, addr; u16_t remote_port, port; - int ret,connected; + int err,connected; sock = get_socket(s); 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)); - ret = lwip_send(s, data, size, flags); + err = lwip_send(s, data, size, flags); /* reset the remote address and port number of the connection */ @@ -555,7 +557,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags, netconn_connect(sock->conn, &addr, port); else netconn_disconnect(sock->conn); - return ret; + return err; } int @@ -632,7 +634,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) { FD_SET(i, &lreadset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); nready++; } } @@ -643,7 +645,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) if (p_sock && p_sock->sendevent) { FD_SET(i, &lwriteset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); nready++; } } @@ -709,8 +711,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, if (exceptset) FD_ZERO(exceptset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); - set_errno(0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); + set_errno(0); return 0; } @@ -765,8 +767,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, if (exceptset) FD_ZERO(exceptset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); - set_errno(0); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); + set_errno(0); return 0; } @@ -972,7 +974,7 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt struct lwip_socket *sock = get_socket(s); if(!sock) { - set_errno(EBADF); + set_errno(EBADF); return -1; } @@ -994,6 +996,8 @@ 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_SNDTIMEO: */ + case SO_RCVTIMEO: /* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_RCVBUF: */ /* 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; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval)); break; + + case SO_RCVTIMEO: + *(int *)optval = sock->conn->recv_timeout; + break; } /* switch */ break; @@ -1162,7 +1170,7 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_ int err = 0; if(!sock) { - set_errno(EBADF); + set_errno(EBADF); return -1; } @@ -1183,6 +1191,8 @@ 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_SNDTIMEO: */ + case SO_RCVTIMEO: /* UNIMPL case SO_OOBINLINE: */ /* UNIMPL case SO_RCVBUF: */ /* 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"))); break; + case SO_RCVTIMEO: + sock->conn->recv_timeout = ( *(int*)optval ); + break; } /* switch */ break; @@ -1327,7 +1340,7 @@ int lwip_ioctl(int s, long cmd, void *argp) struct lwip_socket *sock = get_socket(s); if(!sock) { - set_errno(EBADF); + set_errno(EBADF); return -1; } diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 1e5765ae..972989bf 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -156,7 +156,7 @@ tcpip_thread(void *arg) } while (1) { /* MAIN Loop */ - sys_mbox_fetch(mbox, (void *)&msg); + sys_mbox_fetch(mbox, (void *)&msg, 0); 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 b7bfbf98..b70c9a4e 100644 --- a/src/core/sys.c +++ b/src/core/sys.c @@ -46,7 +46,7 @@ struct sswt_cb 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; struct sys_timeouts *timeouts; @@ -59,7 +59,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg) timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { - sys_arch_mbox_fetch(mbox, msg, 0); + sys_arch_mbox_fetch(mbox, msg, timeout); } else { if (timeouts->next->time > 0) { time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); @@ -78,7 +78,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg) 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); + h(arg); } /* We try again to fetch a message from the mbox. */ diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 7f0ad596..758c7bf4 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -92,6 +92,7 @@ struct netconn { sys_mbox_t acceptmbox; sys_sem_t sem; int socket; + int recv_timeout; u16_t recv_avail; void (* callback)(struct netconn *, enum netconn_evt, u16_t len); }; diff --git a/src/include/lwip/err.h b/src/include/lwip/err.h index d286cc70..b4c2a7eb 100644 --- a/src/include/lwip/err.h +++ b/src/include/lwip/err.h @@ -40,26 +40,28 @@ typedef s8_t err_t; /* Definitions for error constants. */ -#define ERR_OK 0 /* No error, everything OK. */ -#define ERR_MEM -1 /* Out of memory error. */ -#define ERR_BUF -2 /* Buffer error. */ +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ -#define ERR_ABRT -3 /* Connection aborted. */ -#define ERR_RST -4 /* Connection reset. */ -#define ERR_CLSD -5 /* Connection closed. */ -#define ERR_CONN -6 /* Not connected. */ +#define ERR_ABRT -3 /* Connection aborted. */ +#define ERR_RST -4 /* Connection reset. */ +#define ERR_CLSD -5 /* Connection closed. */ +#define ERR_CONN -6 /* Not connected. */ -#define ERR_VAL -7 /* Illegal value. */ +#define ERR_VAL -7 /* Illegal value. */ -#define ERR_ARG -8 /* Illegal argument. */ +#define ERR_ARG -8 /* Illegal argument. */ -#define ERR_RTE -9 /* Routing problem. */ +#define ERR_RTE -9 /* Routing problem. */ -#define ERR_USE -10 /* Address in use. */ +#define ERR_USE -10 /* Address in use. */ -#define ERR_IF -11 /* Low-level netif error */ -#define ERR_ISCONN -12 /* Already connected. */ +#define ERR_IF -11 /* Low-level netif error */ +#define ERR_ISCONN -12 /* Already connected. */ + +#define ERR_TIMEOUT -13 /* Timeout. */ #ifdef LWIP_DEBUG diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 1ebdf434..3373337e 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -87,7 +87,7 @@ struct sockaddr { #define SO_RCVTIMEO 0x1006 /* receive timeout */ #define SO_ERROR 0x1007 /* get error status and clear */ #define SO_TYPE 0x1008 /* get socket type */ - +#define SO_CONTIMEO 0x1009 /* connect timeout */ /* diff --git a/src/include/lwip/sys.h b/src/include/lwip/sys.h index c18c3abf..d3d79396 100644 --- a/src/include/lwip/sys.h +++ b/src/include/lwip/sys.h @@ -53,7 +53,7 @@ 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) +#define sys_mbox_fetch(m,d,t) #define sys_mbox_post(m,d) #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); 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); +void sys_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); /* Thread functions. */