net/udp: Support zero-length UDP datagrams

According to RFC768 page2 and referring to the Linux implementation, the message with udp length of 0 is supported.

Signed-off-by: gaohedong <gaohedong@xiaomi.com>
This commit is contained in:
gaohedong
2025-09-05 16:31:40 +08:00
committed by Xiang Xiao
parent c72ae882da
commit 4d525505e4
5 changed files with 153 additions and 138 deletions
+2 -1
View File
@@ -74,7 +74,8 @@ ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
{ {
/* Verify that non-NULL pointers were passed */ /* Verify that non-NULL pointers were passed */
if (msg == NULL || msg->msg_iov == NULL || msg->msg_iov->iov_base == NULL) if (msg == NULL || msg->msg_iov == NULL ||
(psock->s_type != SOCK_DGRAM && msg->msg_iov->iov_base == NULL))
{ {
return -EINVAL; return -EINVAL;
} }
+1 -1
View File
@@ -103,7 +103,7 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
/* If the application has data to send, setup the UDP/IP header */ /* If the application has data to send, setup the UDP/IP header */
if (dev->d_sndlen > 0) if (dev->d_len > 0)
{ {
udp_send(dev, conn); udp_send(dev, conn);
return; return;
+1 -1
View File
@@ -155,7 +155,7 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
ninfo("UDP payload: %d (%d) bytes\n", dev->d_sndlen, dev->d_len); ninfo("UDP payload: %d (%d) bytes\n", dev->d_sndlen, dev->d_len);
if (dev->d_sndlen > 0) if (dev->d_len > 0)
{ {
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
+5 -7
View File
@@ -687,8 +687,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
BUF_DUMP("psock_udp_sendto", buf, len); BUF_DUMP("psock_udp_sendto", buf, len);
if (len > 0)
{
net_lock(); net_lock();
#if CONFIG_NET_SEND_BUFSIZE > 0 #if CONFIG_NET_SEND_BUFSIZE > 0
@@ -735,8 +733,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
} }
else else
{ {
wrb = udp_wrbuffer_timedalloc(udp_send_gettimeout(start, wrb = udp_wrbuffer_timedalloc(udp_send_gettimeout(start, timeout));
timeout));
} }
#endif #endif
@@ -792,8 +789,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
addr6->sin6_family = AF_INET6; addr6->sin6_family = AF_INET6;
addr6->sin6_port = conn->rport; addr6->sin6_port = conn->rport;
net_ipv6addr_copy(addr6->sin6_addr.s6_addr, net_ipv6addr_copy(addr6->sin6_addr.s6_addr, conn->u.ipv6.raddr);
conn->u.ipv6.raddr);
} }
#endif /* CONFIG_NET_IPv6 */ #endif /* CONFIG_NET_IPv6 */
} }
@@ -817,6 +813,8 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
* buffer space if the socket was opened non-blocking. * buffer space if the socket was opened non-blocking.
*/ */
if (len > 0)
{
if (nonblock) if (nonblock)
{ {
ret = iob_trycopyin(wrb->wb_iob, (FAR uint8_t *)buf, ret = iob_trycopyin(wrb->wb_iob, (FAR uint8_t *)buf,
@@ -845,6 +843,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
{ {
goto errout_with_wrb; goto errout_with_wrb;
} }
}
/* Dump I/O buffer chain */ /* Dump I/O buffer chain */
@@ -885,7 +884,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
} }
net_unlock(); net_unlock();
}
/* Return the number of bytes that will be sent */ /* Return the number of bytes that will be sent */
+16
View File
@@ -197,6 +197,8 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
{ {
/* Copy the user data into d_appdata and send it */ /* Copy the user data into d_appdata and send it */
if (pstate->st_buflen > 0)
{
int ret = devif_send(dev, pstate->st_buffer, pstate->st_buflen, int ret = devif_send(dev, pstate->st_buffer, pstate->st_buflen,
udpip_hdrsize(pstate->st_conn)); udpip_hdrsize(pstate->st_conn));
if (ret <= 0) if (ret <= 0)
@@ -204,6 +206,20 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
pstate->st_sndlen = ret; pstate->st_sndlen = ret;
goto end_wait; goto end_wait;
} }
}
else
{
if (netdev_iob_prepare(dev, false, 0) != OK)
{
pstate->st_sndlen = -ENOMEM;
goto end_wait;
}
iob_update_pktlen(dev->d_iob, udpip_hdrsize(pstate->st_conn),
false);
dev->d_sndlen = 0;
dev->d_len = dev->d_iob->io_pktlen;
}
#ifdef NEED_IPDOMAIN_SUPPORT #ifdef NEED_IPDOMAIN_SUPPORT
/* If both IPv4 and IPv6 support are enabled, then we will need to /* If both IPv4 and IPv6 support are enabled, then we will need to