diff --git a/ChangeLog b/ChangeLog index 229e496b8a..eed77b2bee 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10797,10 +10797,11 @@ * arch/arm/src/samv7: Add the framework for an SPI slave drvier. This driver has a lot of missing logic on initial commit (2015-08-09). * arch/arm/src/samv7: Basic, no-DMA SPI slave driver is in place - (2015-080=-10). + (2015-08-10). * fs/vfs/epoll.c and include/sys/epoll.h: Add a very simple epoll layer just around poll calls. To satisfy build app requirements. From Anton - D. Kachalov. + D. Kachalov (2015-08-10). * drivers/mtd/ramtron.c: Update to include supportf for newer - RAMTRON parts. From David Sidrane. - + RAMTRON parts. From David Sidrane (2015-08-10). + * Networking: Allow receipt of empty UDP packets. From Max Neklyudov + (2015-08-11). diff --git a/net/iob/iob_copyout.c b/net/iob/iob_copyout.c index 300b63df81..e7b682651c 100644 --- a/net/iob/iob_copyout.c +++ b/net/iob/iob_copyout.c @@ -101,6 +101,12 @@ int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob, { offset -= iob->io_len; iob = iob->io_flink; + if (iob == NULL) + { + /* We have no requested data in iob chain */ + + return 0; + } } /* Then loop until all of the I/O data is copied to the user buffer */ diff --git a/net/socket/recvfrom.c b/net/socket/recvfrom.c index cf26072ac9..32b2067ffc 100644 --- a/net/socket/recvfrom.c +++ b/net/socket/recvfrom.c @@ -101,7 +101,7 @@ struct recvfrom_s uint8_t *rf_buffer; /* Pointer to receive buffer */ FAR struct sockaddr *rf_from; /* Address of sender */ FAR socklen_t *rf_fromlen; /* Number of bytes allocated for address of sender */ - size_t rf_recvlen; /* The received length */ + ssize_t rf_recvlen; /* The received length */ int rf_result; /* Success:OK, failure:negated errno */ }; #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ @@ -404,8 +404,9 @@ static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate) * buffer. */ - if ((iob = iob_peek_queue(&conn->readahead)) != NULL && - pstate->rf_buflen > 0) + pstate->rf_recvlen = -1; + + if ((iob = iob_peek_queue(&conn->readahead)) != NULL) { FAR struct iob_s *tmp; uint8_t src_addr_size; @@ -445,16 +446,23 @@ static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate) } } - recvlen = iob_copyout(pstate->rf_buffer, iob, pstate->rf_buflen, - src_addr_size + sizeof(uint8_t)); + if (pstate->rf_buflen > 0) + { + recvlen = iob_copyout(pstate->rf_buffer, iob, pstate->rf_buflen, + src_addr_size + sizeof(uint8_t)); - nllvdbg("Received %d bytes (of %d)\n", recvlen, iob->io_pktlen); + nllvdbg("Received %d bytes (of %d)\n", recvlen, iob->io_pktlen); - /* Update the accumulated size of the data read */ + /* Update the accumulated size of the data read */ - pstate->rf_recvlen += recvlen; - pstate->rf_buffer += recvlen; - pstate->rf_buflen -= recvlen; + pstate->rf_recvlen = recvlen; + pstate->rf_buffer += recvlen; + pstate->rf_buflen -= recvlen; + } + else + { + pstate->rf_recvlen = 0; + } out: /* Remove the I/O buffer chain from the head of the read-ahead @@ -1482,7 +1490,7 @@ static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, * something was received (already in 'ret'); EAGAIN if not. */ - if (ret <= 0) + if (ret < 0) { /* Nothing was received */ diff --git a/net/udp/udp_callback.c b/net/udp/udp_callback.c index f99aa2eac1..1f09ede313 100644 --- a/net/udp/udp_callback.c +++ b/net/udp/udp_callback.c @@ -200,19 +200,23 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev, FAR struct udp_con return 0; } - /* Copy the new appdata into the I/O buffer chain */ - - ret = iob_trycopyin(iob, buffer, buflen, src_addr_size + sizeof(uint8_t), - true); - if (ret < 0) + if (buflen > 0) { - /* On a failure, iob_trycopyin return a negated error value but does - * not free any I/O buffers. - */ + /* Copy the new appdata into the I/O buffer chain */ - nlldbg("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret); - (void)iob_free_chain(iob); - return 0; + ret = iob_trycopyin(iob, buffer, buflen, + src_addr_size + sizeof(uint8_t), true); + if (ret < 0) + { + /* On a failure, iob_trycopyin return a negated error value but + * does not free any I/O buffers. + */ + + nlldbg("ERROR: Failed to add data to the I/O buffer chain: %d\n", + ret); + (void)iob_free_chain(iob); + return 0; + } } /* Add the new I/O buffer chain to the tail of the read-ahead queue */ @@ -243,6 +247,11 @@ net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, uint16_t flags) { uint16_t ret; +#ifdef CONFIG_NET_UDP_READAHEAD + uint8_t *buffer = dev->d_appdata; + int buflen = dev->d_len; + uint16_t recvlen; +#endif ret = (flags & ~UDP_NEWDATA); @@ -250,35 +259,26 @@ net_dataevent(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn, * can have zero-length with UDP_NEWDATA set just to cause an ACK). */ - if (dev->d_len > 0) - { + nllvdbg("No receive on connection\n"); + #ifdef CONFIG_NET_UDP_READAHEAD - uint8_t *buffer = dev->d_appdata; - int buflen = dev->d_len; - uint16_t recvlen; + /* Save as the packet data as in the read-ahead buffer. NOTE that + * partial packets will not be buffered. + */ + + recvlen = udp_datahandler(dev, conn, buffer, buflen); + if (recvlen < buflen) #endif - - nllvdbg("No receive on connection\n"); - -#ifdef CONFIG_NET_UDP_READAHEAD - /* Save as the packet data as in the read-ahead buffer. NOTE that - * partial packets will not be buffered. + { + /* There is no handler to receive new data and there are no free + * read-ahead buffers to retain the data -- drop the packet. */ - recvlen = udp_datahandler(dev, conn, buffer, buflen); - if (recvlen < buflen) -#endif - { - /* There is no handler to receive new data and there are no free - * read-ahead buffers to retain the data -- drop the packet. - */ + nllvdbg("Dropped %d bytes\n", dev->d_len); - nllvdbg("Dropped %d bytes\n", dev->d_len); - - #ifdef CONFIG_NET_STATISTICS - g_netstats.udp.drop++; +#ifdef CONFIG_NET_STATISTICS + g_netstats.udp.drop++; #endif - } } /* In any event, the new data has now been handled */