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
+5 -4
View File
@@ -10797,10 +10797,11 @@
* arch/arm/src/samv7: Add the framework for an SPI slave drvier. This * 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). 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 * 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 * 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 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 * 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).
+6
View File
@@ -101,6 +101,12 @@ int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
{ {
offset -= iob->io_len; offset -= iob->io_len;
iob = iob->io_flink; 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 */ /* Then loop until all of the I/O data is copied to the user buffer */
+19 -11
View File
@@ -101,7 +101,7 @@ struct recvfrom_s
uint8_t *rf_buffer; /* Pointer to receive buffer */ uint8_t *rf_buffer; /* Pointer to receive buffer */
FAR struct sockaddr *rf_from; /* Address of sender */ FAR struct sockaddr *rf_from; /* Address of sender */
FAR socklen_t *rf_fromlen; /* Number of bytes allocated for 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 */ int rf_result; /* Success:OK, failure:negated errno */
}; };
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
@@ -404,8 +404,9 @@ static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate)
* buffer. * buffer.
*/ */
if ((iob = iob_peek_queue(&conn->readahead)) != NULL && pstate->rf_recvlen = -1;
pstate->rf_buflen > 0)
if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
{ {
FAR struct iob_s *tmp; FAR struct iob_s *tmp;
uint8_t src_addr_size; 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, if (pstate->rf_buflen > 0)
src_addr_size + sizeof(uint8_t)); {
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_recvlen = recvlen;
pstate->rf_buffer += recvlen; pstate->rf_buffer += recvlen;
pstate->rf_buflen -= recvlen; pstate->rf_buflen -= recvlen;
}
else
{
pstate->rf_recvlen = 0;
}
out: out:
/* Remove the I/O buffer chain from the head of the read-ahead /* 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. * something was received (already in 'ret'); EAGAIN if not.
*/ */
if (ret <= 0) if (ret < 0)
{ {
/* Nothing was received */ /* Nothing was received */
+34 -34
View File
@@ -200,19 +200,23 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev, FAR struct udp_con
return 0; return 0;
} }
/* Copy the new appdata into the I/O buffer chain */ if (buflen > 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 /* Copy the new appdata into the I/O buffer chain */
* not free any I/O buffers.
*/
nlldbg("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret); ret = iob_trycopyin(iob, buffer, buflen,
(void)iob_free_chain(iob); src_addr_size + sizeof(uint8_t), true);
return 0; 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 */ /* 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 flags)
{ {
uint16_t ret; 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); 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). * 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 #ifdef CONFIG_NET_UDP_READAHEAD
uint8_t *buffer = dev->d_appdata; /* Save as the packet data as in the read-ahead buffer. NOTE that
int buflen = dev->d_len; * partial packets will not be buffered.
uint16_t recvlen; */
recvlen = udp_datahandler(dev, conn, buffer, buflen);
if (recvlen < buflen)
#endif #endif
{
nllvdbg("No receive on connection\n"); /* There is no handler to receive new data and there are no free
* read-ahead buffers to retain the data -- drop the packet.
#ifdef CONFIG_NET_UDP_READAHEAD
/* 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); nllvdbg("Dropped %d bytes\n", dev->d_len);
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); #ifdef CONFIG_NET_STATISTICS
g_netstats.udp.drop++;
#ifdef CONFIG_NET_STATISTICS
g_netstats.udp.drop++;
#endif #endif
}
} }
/* In any event, the new data has now been handled */ /* In any event, the new data has now been handled */