diff --git a/CHANGELOG b/CHANGELOG index e87eaa9b..5952c5f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -170,6 +170,9 @@ HISTORY ++ Bug fixes: + 2007-05-22 Simon Goldschmidt + * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. + 2007-05-23 Frédéric Bernon * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only allocated by do_listen if success) and netconn_accept errors handling. In diff --git a/src/api/sockets.c b/src/api/sockets.c index e8a64e0c..09b9c1a5 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -43,6 +43,7 @@ #include "lwip/igmp.h" #include "lwip/inet.h" #include "lwip/tcp.h" +#include "lwip/tcpip.h" #if !NO_SYS @@ -67,14 +68,26 @@ struct lwip_select_cb { sys_sem_t sem; }; +/* 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 { + struct lwip_socket *sock; + int s; + int level; + int optname; + void *optval; + socklen_t *optlen; +}; + static struct lwip_socket sockets[NUM_SOCKETS]; static struct lwip_select_cb *select_cb_list = 0; static sys_sem_t socksem = 0; static sys_sem_t selectsem = 0; -static void -event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); +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); static int err_to_errno_table[] = { 0, /* ERR_OK 0 No error, everything OK. */ @@ -949,6 +962,7 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl { int err = ERR_OK; struct lwip_socket *sock = get_socket(s); + struct lwip_setgetsockopt_data data; if (!sock) return -1; @@ -1061,6 +1075,36 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl } /* Now do the actual option processing */ + data.sock = sock; + data.level = level; + data.optname = optname; + data.optval = optval; + data.optlen = optlen; + tcpip_callback(lwip_getsockopt_internal, &data); + sys_arch_mbox_fetch(sock->conn->mbox, NULL, 0); + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + + +static void lwip_getsockopt_internal(void *arg) +{ + struct lwip_socket *sock; + int s, level, optname; + void *optval; + socklen_t *optlen; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; + s = data->s; + level = data->level; + optname = data->optname; + optval = data->optval; + optlen = data->optlen; switch (level) { @@ -1172,15 +1216,14 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl } /* switch (optname) */ break; } /* switch (level) */ - - sock_set_errno(sock, err); - return err ? -1 : 0; + sys_mbox_post(sock->conn->mbox, NULL); } int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) { struct lwip_socket *sock = get_socket(s); int err = ERR_OK; + struct lwip_setgetsockopt_data data; if (!sock) return -1; @@ -1302,6 +1345,36 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t /* Now do the actual option processing */ + data.sock = sock; + data.level = level; + data.optname = optname; + data.optval = (void*)optval; + data.optlen = &optlen; + tcpip_callback(lwip_getsockopt_internal, &data); + sys_arch_mbox_fetch(sock->conn->mbox, NULL, 0); + + sock_set_errno(sock, err); + return err ? -1 : 0; +} + +static void lwip_setsockopt_internal(void *arg) +{ + struct lwip_socket *sock; + int s, level, optname; + const void *optval; + socklen_t optlen; + struct lwip_setgetsockopt_data *data; + + LWIP_ASSERT("arg != NULL", arg != NULL); + + data = (struct lwip_setgetsockopt_data*)arg; + sock = data->sock; + s = data->s; + level = data->level; + optname = data->optname; + optval = data->optval; + optlen = *(data->optlen); + switch (level) { @@ -1363,9 +1436,13 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t err = EAFNOSUPPORT; } else { struct ip_mreq *imr = (struct ip_mreq *)optval; - if (netconn_join_leave_group(sock->conn, (struct ip_addr *)&(imr->imr_multiaddr.s_addr), - (struct ip_addr *)&(imr->imr_interface.s_addr), - ((optname==IP_ADD_MEMBERSHIP)?NETCONN_JOIN:NETCONN_LEAVE)) < 0) { + err_t err; + if(optname == IP_ADD_MEMBERSHIP){ + err = igmp_joingroup(netif_default, imr); + } else { + err = igmp_leavegroup(netif_default, imr->imr_multiaddr.s_addr); + } + if(err < 0) { err = EADDRNOTAVAIL; } } @@ -1413,9 +1490,7 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t } /* switch (optname) */ break; } /* switch (level) */ - - sock_set_errno(sock, err); - return err ? -1 : 0; + sys_mbox_post(sock->conn->mbox, NULL); } int lwip_ioctl(int s, long cmd, void *argp)