From 8cfd923aaa0477a008a9a66e3456546a67b8fd45 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Sat, 24 Nov 2007 17:39:53 +0000 Subject: [PATCH] Added some documentation (mainly what is unimplemented in contrast to 'std-BSD'), alloc_socket returns the sock pointer directly (for speedup) --- src/api/sockets.c | 115 +++++++++++++++++++++++++++++++++---- src/include/lwip/sockets.h | 47 ++++++++------- 2 files changed, 130 insertions(+), 32 deletions(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index cca3b932..c15e8874 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -55,47 +55,74 @@ #define NUM_SOCKETS MEMP_NUM_NETCONN +/** Contains all internal pointers and states used for a socket */ struct lwip_socket { + /** sockets currently are built on netconns, each socket has one netconn */ struct netconn *conn; + /** data that was left from the previous read */ struct netbuf *lastdata; + /** offset in the data that was left from the previous read */ u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ u16_t rcvevent; + /** number of times data was received, set by event_callback(), + tested by select */ u16_t sendevent; - u16_t flags; + /** socket flags (currently, only used for O_NONBLOCK) */ + u16_t flags; + /** last error that occurred on this socket */ int err; }; +/** Description for a task waiting in select */ struct lwip_select_cb { + /** Pointer to the next waiting task */ struct lwip_select_cb *next; + /** readset passed to select */ fd_set *readset; + /** writeset passed to select */ fd_set *writeset; + /** unimplemented: exceptset passed to select */ fd_set *exceptset; + /** don't signal the same semaphore twice: set to 1 when signalled */ int sem_signalled; + /** semaphore to wake up a task waiting for select */ sys_sem_t sem; }; -/* This struct is used to pass data to the set/getsockopt_internal +/** This struct is used to pass data to the set/getsockopt_internal * functions running in tcpip_thread context (only a void* is allowed) */ struct lwip_setgetsockopt_data { + /** socket struct for which to change options */ struct lwip_socket *sock; + /** socket index for which to change options */ int s; + /** level of the option to process */ int level; + /** name of the option to process */ int optname; + /** set: value to set the option to + * get: value of the option is stored here */ void *optval; + /** size of *optval */ socklen_t *optlen; + /** if an error occures, it is temporarily stored here */ err_t err; }; +/** The global array of available sockets */ static struct lwip_socket sockets[NUM_SOCKETS]; +/** The global list of tasks waiting for select */ static struct lwip_select_cb *select_cb_list; +/** Semaphore protecting the sockets array */ static sys_sem_t socksem; +/** Semaphore protecting select_cb_list */ static sys_sem_t selectsem; -static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -static void lwip_getsockopt_internal(void *arg); -static void lwip_setsockopt_internal(void *arg); - +/** Table to quickly map an lwIP error (err_t) to a socket error + * by using -err as an index */ static const int err_to_errno_table[] = { 0, /* ERR_OK 0 No error, everything OK. */ ENOMEM, /* ERR_MEM -1 Out of memory error. */ @@ -131,7 +158,15 @@ static const int err_to_errno_table[] = { set_errno(sk->err); \ } while (0) +/* Forward delcaration of some functions */ +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +static void lwip_getsockopt_internal(void *arg); +static void lwip_setsockopt_internal(void *arg); +/** + * Initialize this module. This function has to be called before any other + * functions in this module! + */ void lwip_socket_init(void) { @@ -139,6 +174,12 @@ lwip_socket_init(void) selectsem = sys_sem_new(1); } +/** + * Map a externally used socket index to the internal socket representation. + * + * @param s externally used socket index + * @return struct lwip_socket for the socket or NULL if not found + */ static struct lwip_socket * get_socket(int s) { @@ -161,10 +202,21 @@ get_socket(int s) return sock; } +/** + * Allocate a new socket for a given netconn. + * + * @param newconn the netconn for which to allocate a socket + * @return the index of the new socket; -1 on error + */ static int -alloc_socket(struct netconn *newconn) +alloc_socket(struct netconn *newconn, struct lwip_socket **sock) { int i; + struct lwip_socket *unused; + if (sock == NULL) { + sock = &unused; + } + *sock = NULL; /* Protect socket array */ sys_sem_wait(socksem); @@ -180,6 +232,7 @@ alloc_socket(struct netconn *newconn) sockets[i].flags = 0; sockets[i].err = 0; sys_sem_signal(socksem); + *sock = &sockets[i]; return i; } } @@ -187,6 +240,12 @@ alloc_socket(struct netconn *newconn) return -1; } +/* Below this, the well-known socket functions are implemented. + * Use google.com or opengroup.org to get a good description :-) + * + * Exceptions are documented! + */ + int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) { @@ -229,14 +288,15 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) SMEMCPY(addr, &sin, *addrlen); - newsock = alloc_socket(newconn); + newsock = alloc_socket(newconn, &sock); if (newsock == -1) { netconn_delete(newconn); sock_set_errno(sock, ENFILE); return -1; } newconn->callback = event_callback; - sock = get_socket(newsock); + LWIP_ASSERT("invalid socket pointer", sock != NULL); + LWIP_ASSERT("socket pointer doesn't match the array", &sockets[newsock] == sock); sys_sem_wait(socksem); sock->rcvevent += -1 - newconn->socket; @@ -355,6 +415,14 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) return 0; } +/** + * Set a socket into listen mode. + * The socket may not have been used for another connection previously. + * + * @param s the socket to set to listening mode + * @param backlog (ATTENTION: this is not implemented, yet!) + * @return 0 on success, non-zero on failure + */ int lwip_listen(int s, int backlog) { @@ -676,7 +744,7 @@ lwip_socket(int domain, int type, int protocol) return -1; } - i = alloc_socket(conn); + i = alloc_socket(conn, NULL); if (i == -1) { netconn_delete(conn); @@ -695,6 +763,21 @@ lwip_write(int s, const void *data, int size) return lwip_send(s, data, size, 0); } +/** + * Go through the readset and writeset lists and see which socket of the sockets + * set in the sets has events. On return, readset, writeset and exceptset have + * the sockets enabled that had events. + * + * exceptset is not used for now!!! + * + * @param maxfdp1 the highest socket index in the sets + * @param readset in: set of sockets to check for read events; + * out: set of sockets that had read events + * @param writeset in: set of sockets to check for write events; + * out: set of sockets that had write events + * @param exceptset not yet implemented + * @return number of sockets that had events (read+write) + */ static int lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) { @@ -735,6 +818,10 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) return nready; } + +/** + * Processing exceptset is not yet implemented. + */ int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) @@ -880,6 +967,10 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, return nready; } +/** + * Callback registered in the netconn layer for each socket-netconn. + * Processes recvevent (data available) and wakes up tasks waiting for select. + */ static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) { @@ -958,6 +1049,10 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) } } +/** + * Unimplemented: Close one end of a full-duplex connection. + * Currently, the full connection is closed. + */ int lwip_shutdown(int s, int how) { diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 6d45fa44..749f5122 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -64,39 +64,39 @@ struct sockaddr { # define socklen_t u32_t #endif - +/* Socket protocol types (TCP/UDP/RAW) */ #define SOCK_STREAM 1 #define SOCK_DGRAM 2 #define SOCK_RAW 3 /* - * Option flags per-socket. + * Option flags per-socket. These must match the SOF_ flags in ip.h! */ -#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ #define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */ #define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_DONTROUTE 0x0010 /* just use interface addresses */ -#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ -#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* Unimplemented: permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ #define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ -#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ #define SO_DONTLINGER ((int)(~SO_LINGER)) /* * Additional options, not kept in so_options. */ -#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ #define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ #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 */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ #define SO_NO_CHECK 0x100a /* don't create UDP checksum */ @@ -129,8 +129,8 @@ struct linger { /* Flags we can use with send and recv. */ #define MSG_PEEK 0x01 /* Peeks at an incoming message */ -#define MSG_WAITALL 0x02 /* Requests that the function block until the full amount of data requested can be returned */ -#define MSG_OOB 0x04 /* Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ #define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ #define MSG_MORE 0x10 /* Sender will send more */ @@ -177,6 +177,7 @@ typedef struct ip_mreq { } ip_mreq; #endif /* LWIP_IGMP */ +/* Unimplemented for now... */ #define IPTOS_TOS_MASK 0x1E #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) #define IPTOS_LOWDELAY 0x10 @@ -186,7 +187,7 @@ typedef struct ip_mreq { #define IPTOS_MINCOST IPTOS_LOWCOST /* - * Definitions for IP precedence (also in ip_tos) (hopefully unused) + * Definitions for IP precedence (also in ip_tos) (Unimplemented) */ #define IPTOS_PREC_MASK 0xe0 #define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) @@ -202,7 +203,7 @@ typedef struct ip_mreq { /* * Commands for ioctlsocket(), taken from the BSD file fcntl.h. - * + * lwip_ioctl only supports FIONREAD and FIONBIO, for now * * Ioctl's have the command encoded in the lower word, * and the size of any in or out parameters in the upper @@ -223,7 +224,7 @@ typedef struct ip_mreq { #define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) #define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -#endif +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ #ifndef FIONREAD #define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ @@ -232,7 +233,7 @@ typedef struct ip_mreq { #define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ #endif -/* Socket I/O Controls */ +/* Socket I/O Controls: unimplemented */ #ifndef SIOCSHIWAT #define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ #define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ @@ -241,10 +242,12 @@ typedef struct ip_mreq { #define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ #endif +/* Socket flags: */ #ifndef O_NONBLOCK #define O_NONBLOCK 04000U #endif +/* FD_SET used for lwip_select */ #ifndef FD_SET #undef FD_SETSIZE /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ @@ -271,9 +274,9 @@ typedef struct ip_mreq { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; -#endif +#endif /* LWIP_TIMEVAL_PRIVATE */ -#endif +#endif /* FD_SET */ void lwip_socket_init(void);