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 <wangyingd...@xiaomi.com>
AuthorDate: Thu May 25 19:52:41 2023 +0800

    net: Add msg_peek support for udp and tcp
    
    Signed-off-by: wangyingdong <wangyingd...@xiaomi.com>
---
 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 */
 

Reply via email to