Networking: Allow receipt of empty UDP packets. From Max Neklyudov

This commit is contained in:
Max Neklyudov 2015-08-11 07:55:40 -06:00 committed by Gregory Nutt
parent e0238df359
commit 7d04104485
4 changed files with 64 additions and 49 deletions

View File

@ -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).

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */