This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 57bf3e1fea net: Add msg_peek support for udp and tcp
57bf3e1fea is described below
commit 57bf3e1feae599aec41ba25c175e36c85611998e
Author: wangyingdong <[email protected]>
AuthorDate: Thu May 25 19:52:41 2023 +0800
net: Add msg_peek support for udp and tcp
Signed-off-by: wangyingdong <[email protected]>
---
net/tcp/tcp_recvfrom.c | 21 +++++++++++++++++----
net/udp/udp_recvfrom.c | 34 ++++++++++++++++++++++++----------
2 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/net/tcp/tcp_recvfrom.c b/net/tcp/tcp_recvfrom.c
index c3c3f08cd9..68379418a1 100644
--- a/net/tcp/tcp_recvfrom.c
+++ b/net/tcp/tcp_recvfrom.c
@@ -57,6 +57,7 @@ struct tcp_recvfrom_s
FAR socklen_t *ir_fromlen; /* Number of bytes allocated for
address of sender */
ssize_t ir_recvlen; /* The received length */
int ir_result; /* Success:OK, failure:negated errno
*/
+ int ir_flags; /* Flags on received message. */
};
/****************************************************************************
@@ -135,7 +136,8 @@ static size_t tcp_recvfrom_newdata(FAR struct net_driver_s
*dev,
/* Trim the copied buffers */
- dev->d_iob = iob_trimhead(dev->d_iob, recvlen + offset);
+ dev->d_iob = iob_trimhead(dev->d_iob,
+ pstate->ir_flags & MSG_PEEK ? offset : recvlen + offset);
ninfo("Received %d bytes (of %d)\n", (int)recvlen, (int)dev->d_len);
@@ -143,7 +145,7 @@ static size_t tcp_recvfrom_newdata(FAR struct net_driver_s
*dev,
tcp_update_recvlen(pstate, recvlen);
- return recvlen;
+ return pstate->ir_flags & MSG_PEEK ? 0: recvlen;
}
/****************************************************************************
@@ -261,6 +263,15 @@ static inline void tcp_readahead(struct tcp_recvfrom_s
*pstate)
tcp_update_recvlen(pstate, recvlen);
+ /* If it is in read-ahead mode,
+ * exit directly to avoid iob being released
+ */
+
+ if (pstate->ir_flags & MSG_PEEK)
+ {
+ break;
+ }
+
/* If we took all of the data from the I/O buffer chain is empty, then
* release it. If there is still data available in the I/O buffer
* chain, then just trim the data that we have taken from the
@@ -511,7 +522,8 @@ static void tcp_recvfrom_initialize(FAR struct tcp_conn_s
*conn,
FAR void *buf, size_t len,
FAR struct sockaddr *infrom,
FAR socklen_t *fromlen,
- FAR struct tcp_recvfrom_s *pstate)
+ FAR struct tcp_recvfrom_s *pstate,
+ int flags)
{
/* Initialize the state structure. */
@@ -522,6 +534,7 @@ static void tcp_recvfrom_initialize(FAR struct tcp_conn_s
*conn,
pstate->ir_buffer = buf;
pstate->ir_from = infrom;
pstate->ir_fromlen = fromlen;
+ pstate->ir_flags = flags;
/* Set up the start time for the timeout */
@@ -612,7 +625,7 @@ ssize_t psock_tcp_recvfrom(FAR struct socket *psock, FAR
struct msghdr *msg,
* because we don't want anything to happen until we are ready.
*/
- tcp_recvfrom_initialize(conn, buf, len, from, fromlen, &state);
+ tcp_recvfrom_initialize(conn, buf, len, from, fromlen, &state, flags);
/* Handle any any TCP data already buffered in a read-ahead buffer. NOTE
* that there may be read-ahead data to be retrieved even after the
diff --git a/net/udp/udp_recvfrom.c b/net/udp/udp_recvfrom.c
index e24690a5ba..e96543ff89 100644
--- a/net/udp/udp_recvfrom.c
+++ b/net/udp/udp_recvfrom.c
@@ -56,6 +56,7 @@ struct udp_recvfrom_s
sem_t ir_sem; /* Semaphore signals recv completion
*/
ssize_t ir_recvlen; /* The received length */
int ir_result; /* Success:OK, failure:negated errno
*/
+ int ir_flags; /* Flags on received message. */
};
/****************************************************************************
@@ -208,11 +209,14 @@ static inline void udp_readahead(struct udp_recvfrom_s
*pstate)
* buffer queue.
*/
- iob_remove_queue(&conn->readahead);
+ if (!(pstate->ir_flags & MSG_PEEK))
+ {
+ iob_remove_queue(&conn->readahead);
- /* And free the I/O buffer chain */
+ /* And free the I/O buffer chain */
- iob_free_chain(iob);
+ iob_free_chain(iob);
+ }
}
}
@@ -422,13 +426,21 @@ static uint16_t udp_eventhandler(FAR struct net_driver_s
*dev,
udp_terminate(pstate, OK);
- /* Indicate that the data has been consumed */
+ /* In read-ahead mode, UDP_NEWDATA and iob need to be reserved
+ * and let udp_callback to call net_dataevent and put this packet
+ * into conn->readahead
+ */
+
+ if (!(pstate->ir_flags & MSG_PEEK))
+ {
+ /* Indicate that the data has been consumed */
- flags &= ~UDP_NEWDATA;
+ flags &= ~UDP_NEWDATA;
- /* Indicate no data in the buffer */
+ /* Indicate no data in the buffer */
- netdev_iob_release(dev);
+ netdev_iob_release(dev);
+ }
}
}
@@ -455,14 +467,16 @@ static uint16_t udp_eventhandler(FAR struct net_driver_s
*dev,
static void udp_recvfrom_initialize(FAR struct udp_conn_s *conn,
FAR struct msghdr *msg,
- FAR struct udp_recvfrom_s *pstate)
+ FAR struct udp_recvfrom_s *pstate,
+ int flags)
{
/* Initialize the state structure. */
memset(pstate, 0, sizeof(struct udp_recvfrom_s));
nxsem_init(&pstate->ir_sem, 0, 0); /* Doesn't really fail */
- pstate->ir_msg = msg;
+ pstate->ir_msg = msg;
+ pstate->ir_flags = flags;
/* Set up the start time for the timeout */
@@ -558,7 +572,7 @@ ssize_t psock_udp_recvfrom(FAR struct socket *psock, FAR
struct msghdr *msg,
*/
net_lock();
- udp_recvfrom_initialize(conn, msg, &state);
+ udp_recvfrom_initialize(conn, msg, &state, flags);
/* Copy the read-ahead data from the packet */