diff --git a/CHANGELOG b/CHANGELOG index c9b58bf8..f23d5d18 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -108,6 +108,11 @@ HISTORY ++ Bugfixes: + 2009-07-09 Kieran Mansley + * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for + recv_avail and don't increment counters until message successfully + sent to mbox + 2009-06-25 Kieran Mansley * api_msg.c api.h: BUG26722: initialise netconn write variables in netconn_alloc diff --git a/src/api/api_msg.c b/src/api/api_msg.c index fdb1a207..d674812c 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -108,11 +108,13 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, buf->addr = &(((struct ip_hdr*)(q->payload))->src); buf->port = pcb->protocol; - SYS_ARCH_INC(conn->recv_avail, q->tot_len); - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len); if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); + return 0; + } else { + SYS_ARCH_INC(conn->recv_avail, q->tot_len); + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len); } } } @@ -166,12 +168,13 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, buf->port = port; } - SYS_ARCH_INC(conn->recv_avail, p->tot_len); - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return; + } else { + SYS_ARCH_INC(conn->recv_avail, p->tot_len); + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); } } #endif /* LWIP_UDP */ @@ -206,10 +209,12 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) } else { len = 0; } - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); + if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) { return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } return ERR_OK; @@ -365,8 +370,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) newconn->pcb.tcp = newpcb; setup_tcp(newconn); newconn->err = err; - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) { /* When returning != ERR_OK, the connection is aborted in tcp_process(), @@ -374,7 +377,11 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) newconn->pcb.tcp = NULL; netconn_free(newconn); return ERR_MEM; + } else { + /* Register event with callback */ + API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); } + return ERR_OK; } #endif /* LWIP_TCP */ diff --git a/src/api/sockets.c b/src/api/sockets.c index 6b745af0..f177261e 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -66,7 +66,7 @@ struct lwip_socket { u16_t lastoffset; /** number of times data was received, set by event_callback(), tested by the receive and select functions */ - u16_t rcvevent; + s16_t rcvevent; /** number of times data was received, set by event_callback(), tested by select */ u16_t sendevent; @@ -260,7 +260,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) if (!sock) return -1; - if ((sock->flags & O_NONBLOCK) && !sock->rcvevent) { + if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); sock_set_errno(sock, EWOULDBLOCK); return -1; @@ -494,7 +494,8 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags, buf = sock->lastdata; } else { /* If this is non-blocking call, then check first */ - if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) { + if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && + (sock->rcvevent <= 0)) { if (off > 0) { /* already received data, return that */ sock_set_errno(sock, 0); @@ -545,7 +546,10 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags, if (netconn_type(sock->conn) == NETCONN_TCP) { LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); len -= copylen; - if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent || ((flags & MSG_PEEK)!=0)) { + if ( (len <= 0) || + (buf->p->flags & PBUF_FLAG_PUSH) || + (sock->rcvevent <= 0) || + ((flags & MSG_PEEK)!=0)) { done = 1; } } else { @@ -852,7 +856,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) if (FD_ISSET(i, readset)) { /* See if netconn of this socket is ready for read */ p_sock = get_socket(i); - if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) { + if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) { FD_SET(i, &lreadset); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); nready++; @@ -1100,7 +1104,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) if (scb->sem_signalled == 0) { /* Test this select call for our socket */ if (scb->readset && FD_ISSET(s, scb->readset)) - if (sock->rcvevent) + if (sock->rcvevent > 0) break; if (scb->writeset && FD_ISSET(s, scb->writeset)) if (sock->sendevent) @@ -1918,6 +1922,7 @@ lwip_ioctl(int s, long cmd, void *argp) { struct lwip_socket *sock = get_socket(s); u16_t buflen = 0; + s16_t recv_avail; if (!sock) return -1; @@ -1929,7 +1934,10 @@ lwip_ioctl(int s, long cmd, void *argp) return -1; } - SYS_ARCH_GET(sock->conn->recv_avail, *((u16_t*)argp)); + SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); + if (recv_avail < 0) + recv_avail = 0; + *((u16_t*)argp) = (u16_t)recv_avail; /* Check if there is data left from the last recv operation. /maq 041215 */ if (sock->lastdata) { diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index ecd22a19..65998a01 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -137,7 +137,7 @@ struct netconn { /** maximum amount of bytes queued in recvmbox */ int recv_bufsize; #endif /* LWIP_SO_RCVBUF */ - u16_t recv_avail; + s16_t recv_avail; #if LWIP_TCP /** TCP: when data passed to netconn_write doesn't fit into the send buffer, this temporarily stores the message. */