diff --git a/CHANGELOG b/CHANGELOG index 7f32a03b..2038d9ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,14 @@ HISTORY ++ New features: + 2007-05-04 Frédéric Bernon, Jonathan Larmour + * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible + to corrupt remote addr/port connection state". Reduce problems "not enought memory" with + netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between + sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. + Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, + these fields are now renamed "addr" & "port". + 2007-04-11 Jonathan Larmour * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return @@ -503,9 +511,9 @@ HISTORY 2004-10-16 Kieran Mansley * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, - even if one is already pending, if the rcv_wnd is above a threshold - (currently TCP_WND/2). This avoids waiting for a timer to expire to send a - delayed ACK in order to open the window if the stack is only receiving data. + even if one is already pending, if the rcv_wnd is above a threshold + (currently TCP_WND/2). This avoids waiting for a timer to expire to send a + delayed ACK in order to open the window if the stack is only receiving data. 2004-09-12 Kieran Mansley * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. diff --git a/src/api/api_lib.c b/src/api/api_lib.c index de47f92f..d5478108 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -49,6 +49,7 @@ netbuf *netbuf_new(void) if (buf != NULL) { buf->p = NULL; buf->ptr = NULL; + buf->addr = NULL; return buf; } else { return NULL; @@ -116,12 +117,6 @@ netbuf_chain(struct netbuf *head, struct netbuf *tail) memp_free(MEMP_NETBUF, tail); } -u16_t -netbuf_len(struct netbuf *buf) -{ - return buf->p->tot_len; -} - err_t netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) { @@ -184,24 +179,6 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset) } } -void -netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len) -{ - netbuf_copy_partial(buf, dataptr, len, 0); -} - -struct ip_addr * -netbuf_fromaddr(struct netbuf *buf) -{ - return buf->fromaddr; -} - -u16_t -netbuf_fromport(struct netbuf *buf) -{ - return buf->fromport; -} - struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, void (*callback)(struct netconn *, enum netconn_evt, u16_t len)) @@ -253,7 +230,6 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, return conn; } - struct netconn *netconn_new(enum netconn_type t) { @@ -267,7 +243,6 @@ netconn *netconn_new_with_callback(enum netconn_type t, return netconn_new_with_proto_and_callback(t,0,callback); } - err_t netconn_delete(struct netconn *conn) { @@ -485,10 +460,12 @@ netconn_recv(struct netconn *conn) if (conn == NULL) { return NULL; } - + if (conn->recvmbox == SYS_MBOX_NULL) { - conn->err = ERR_CONN; - return NULL; + if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) { + conn->err = ERR_CONN; + return NULL; + } } if (conn->err != ERR_OK) { @@ -533,8 +510,8 @@ netconn_recv(struct netconn *conn) buf->p = p; buf->ptr = p; - buf->fromport = 0; - buf->fromaddr = NULL; + buf->port = 0; + buf->addr = NULL; /* Let the stack know that we have taken the data. */ msg.type = API_MSG_RECV; @@ -564,6 +541,16 @@ netconn_recv(struct netconn *conn) return buf; } +err_t +netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port) +{ if (buf!=NULL) { + buf->addr = addr; + buf->port = port; + return netconn_send( conn, buf); + } + return ERR_VAL; +} + err_t netconn_send(struct netconn *conn, struct netbuf *buf) { @@ -580,7 +567,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf) LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len)); msg.type = API_MSG_SEND; msg.msg.conn = conn; - msg.msg.msg.p = buf->p; + msg.msg.msg.b = buf; api_msg_post(&msg); return conn->err; } diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 16afcc82..21d1aa12 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -57,8 +57,8 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, pbuf_ref(p); buf->p = p; buf->ptr = p; - buf->fromaddr = addr; - buf->fromport = pcb->protocol; + buf->addr = addr; + buf->port = pcb->protocol; conn->recv_avail += p->tot_len; /* Register event with callback */ @@ -95,8 +95,8 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, } else { buf->p = p; buf->ptr = p; - buf->fromaddr = addr; - buf->fromport = port; + buf->addr = addr; + buf->port = port; } conn->recv_avail += p->tot_len; @@ -581,7 +581,11 @@ do_send(struct api_msg_msg *msg) switch (msg->conn->type) { #if LWIP_RAW case NETCONN_RAW: - raw_send(msg->conn->pcb.raw, msg->msg.p); + if (msg->msg.b->addr==NULL) { + raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr); + } break; #endif #if LWIP_UDP @@ -590,7 +594,11 @@ do_send(struct api_msg_msg *msg) case NETCONN_UDPNOCHKSUM: /* FALLTHROUGH */ case NETCONN_UDP: - udp_send(msg->conn->pcb.udp, msg->msg.p); + if (msg->msg.b->addr==NULL) { + udp_send(msg->conn->pcb.udp, msg->msg.b->p); + } else { + udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port); + } break; #endif /* LWIP_UDP */ case NETCONN_TCP: diff --git a/src/api/sockets.c b/src/api/sockets.c index 61a8e520..6ba7840b 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -461,7 +461,6 @@ int lwip_send(int s, const void *data, int size, unsigned int flags) { struct lwip_socket *sock; - struct netbuf *buf; err_t err; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags)); @@ -470,45 +469,14 @@ lwip_send(int s, const void *data, int size, unsigned int flags) if (!sock) return -1; - switch (netconn_type(sock->conn)) { - case NETCONN_RAW: - case NETCONN_UDP: - case NETCONN_UDPLITE: - case NETCONN_UDPNOCHKSUM: - /* create a buffer */ - buf = netbuf_new(); - - if (!buf) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s)); - sock_set_errno(sock, ENOBUFS); - return -1; - } - - /* make the buffer point to the data that should be sent */ - if ((err = netbuf_ref(buf, data, size))==ERR_OK) { - /* send the data */ - err = netconn_send(sock->conn, buf); - } - - /* deallocated the buffer */ - netbuf_delete(buf); - break; - case NETCONN_TCP: - err = netconn_write(sock->conn, data, size, NETCONN_COPY); - break; - default: - err = ERR_ARG; - break; - } - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size)); - sock_set_errno(sock, 0); - return size; + if (sock->conn->type!=NETCONN_TCP) + return lwip_sendto( s, data, size, flags, NULL, 0); + + err = netconn_write( sock->conn, data, size, NETCONN_COPY); + + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size)); + sock_set_errno(sock, err_to_errno(err)); + return (err==ERR_OK?size:-1); } int @@ -516,37 +484,51 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags, struct sockaddr *to, socklen_t tolen) { struct lwip_socket *sock; - struct ip_addr remote_addr, addr; - u16_t remote_port, port; - int err,connected; + struct netbuf buf; + struct ip_addr remote_addr; + u16_t remote_port; + int err; sock = get_socket(s); if (!sock) return -1; - LWIP_ASSERT("lwip_sendto: invalid address", (tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET)); + if (sock->conn->type==NETCONN_TCP) + return lwip_send( s, data, size, flags); + + LWIP_ASSERT("lwip_sendto: invalid address", (((to==NULL) && (tolen==0)) || ((tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET))) ); - /* get the peer if currently connected */ - connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK); - - remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; - remote_port = ((struct sockaddr_in *)to)->sin_port; + /* initialize a buffer */ + buf.p = buf.ptr = NULL; + if (to) { + remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; + remote_port = ntohs(((struct sockaddr_in *)to)->sin_port); + buf.addr = &remote_addr; + buf.port = remote_port; + } else { + remote_addr.addr = 0; + remote_port = 0; + buf.addr = NULL; + buf.port = 0; + } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags)); ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port))); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port)); + + /* make the buffer point to the data that should be sent */ + if ((err = netbuf_ref(&buf, data, size))==ERR_OK) { + /* send the data */ + err = netconn_send(sock->conn, &buf); + } - netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); - - err = lwip_send(s, data, size, flags); - - /* reset the remote address and port number - of the connection */ - if (connected) - netconn_connect(sock->conn, &addr, port); - else - netconn_disconnect(sock->conn); - return err; + /* deallocated the buffer */ + if (buf.p != NULL) { + pbuf_free(buf.p); + } + + sock_set_errno(sock, err_to_errno(err)); + return (err==ERR_OK?size:-1); } int @@ -600,7 +582,6 @@ lwip_write(int s, const void *data, int size) return lwip_send(s, data, size, 0); } - static int lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) { @@ -646,8 +627,6 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) return nready; } - - int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) @@ -794,7 +773,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, return nready; } - static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) { @@ -877,12 +855,8 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) break; } } - } - - - int lwip_shutdown(int s, int how) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); @@ -1063,7 +1037,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt return -1; } - /* Now do the actual option processing */ switch(level) { @@ -1167,7 +1140,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt break; } - sock_set_errno(sock, err); return err ? -1 : 0; } @@ -1185,7 +1157,6 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_ return -1; } - /* Do length and type checks for the various options first, to keep it readable. */ switch( level ) { @@ -1420,15 +1391,15 @@ int lwip_ioctl(int s, long cmd, void *argp) *((u16_t*)argp) = sock->conn->recv_avail; - /* Check if there is data left from the last recv operation. /maq 041215 */ + /* Check if there is data left from the last recv operation. /maq 041215 */ if (sock->lastdata) { buflen = netbuf_len(sock->lastdata); buflen -= sock->lastoffset; - *((u16_t*)argp) += buflen; - } + *((u16_t*)argp) += buflen; + } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp))); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp))); sock_set_errno(sock, 0); return 0; diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 6240910e..a7a25e1b 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -80,8 +80,8 @@ enum netconn_igmp { struct netbuf { struct pbuf *p, *ptr; - struct ip_addr *fromaddr; - u16_t fromport; + struct ip_addr *addr; + u16_t port; }; struct netconn { @@ -121,12 +121,13 @@ err_t netbuf_data (struct netbuf *buf, s8_t netbuf_next (struct netbuf *buf); void netbuf_first (struct netbuf *buf); -void netbuf_copy (struct netbuf *buf, - void *dataptr, u16_t len); void netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset); -struct ip_addr * netbuf_fromaddr (struct netbuf *buf); -u16_t netbuf_fromport (struct netbuf *buf); + +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) ((buf)->addr) +#define netbuf_fromport(buf) ((buf)->port) /* Network connection functions: */ struct netconn * netconn_new (enum netconn_type type); @@ -154,6 +155,8 @@ err_t netconn_disconnect (struct netconn *conn); err_t netconn_listen (struct netconn *conn); struct netconn * netconn_accept (struct netconn *conn); struct netbuf * netconn_recv (struct netconn *conn); +err_t netconn_sendto (struct netconn *conn, + struct netbuf *buf, struct ip_addr *addr, u16_t port); err_t netconn_send (struct netconn *conn, struct netbuf *buf); err_t netconn_write (struct netconn *conn, diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h index d99760a1..3bf8aa49 100644 --- a/src/include/lwip/api_msg.h +++ b/src/include/lwip/api_msg.h @@ -70,7 +70,8 @@ struct api_msg_msg { struct netconn *conn; enum netconn_type conntype; union { - struct pbuf *p; + struct pbuf *p; + struct netbuf *b; struct { struct ip_addr *ipaddr; u16_t port;