This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit c6878db03188169e847f67f10dabc75057e0b2d4
Author: OceanfromXiaomi <[email protected]>
AuthorDate: Thu Nov 27 12:03:31 2025 +0800

    net/utils: extract cmsg_store_timestamp helper
    
    Extract a common cmsg_store_timestamp() helper that checks
    SO_TIMESTAMP/SO_TIMESTAMPNS via s_options and appends the
    appropriate cmsg. Replaces per-protocol timestamp formatting
    in CAN, PKT, and UDP receive paths.
    
    
    Signed-off-by: OceanfromXiaomi <[email protected]>
---
 net/can/can_recvmsg.c  | 106 +++++++++++++++++++++++--------------------------
 net/pkt/pkt_recvmsg.c  |  60 ++--------------------------
 net/udp/udp_recvfrom.c |  19 ++-------
 net/utils/net_cmsg.c   |  37 ++++++++++++++++-
 net/utils/utils.h      |  22 +++++++++-
 5 files changed, 114 insertions(+), 130 deletions(-)

diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c
index 82fdb3a1f51..8dd4879ab3c 100644
--- a/net/can/can_recvmsg.c
+++ b/net/can/can_recvmsg.c
@@ -63,12 +63,9 @@ struct can_recvfrom_s
 {
   FAR struct can_conn_s *pr_conn;      /* Connection associated with the 
socket */
   FAR struct devif_callback_s *pr_cb;  /* Reference to callback instance */
+  FAR struct msghdr *pr_msg;           /* Pointer to receive buffer */
   sem_t        pr_sem;                 /* Semaphore signals recv completion */
-  size_t       pr_buflen;              /* Length of receive buffer */
-  FAR uint8_t *pr_buffer;              /* Pointer to receive buffer */
   ssize_t      pr_recvlen;             /* The received length */
-  size_t       pr_msglen;              /* Length of msg buffer */
-  FAR uint8_t *pr_msgbuf;              /* Pointer to msg buffer */
   int          pr_result;              /* Success:OK, failure:negated errno */
 };
 
@@ -76,6 +73,37 @@ struct can_recvfrom_s
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: can_recvfrom_initialize
+ *
+ * Description:
+ *   Initialize the state structure
+ *
+ * Input Parameters:
+ *   conn     The CAN connection of interest
+ *   msg      Receive info and buffer for receive data
+ *   pstate   A pointer to the state structure to be initialized
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void can_recvfrom_initialize(FAR struct can_conn_s *conn,
+                                    FAR struct msghdr *msg,
+                                    FAR struct can_recvfrom_s *pstate)
+{
+  /* Initialize the state structure. */
+
+  memset(pstate, 0, sizeof(struct can_recvfrom_s));
+  nxsem_init(&pstate->pr_sem, 0, 0);
+
+  pstate->pr_conn = conn;
+  pstate->pr_msg  = msg;
+}
+
 /****************************************************************************
  * Name: can_add_recvlen
  *
@@ -102,8 +130,6 @@ static inline void can_add_recvlen(FAR struct 
can_recvfrom_s *pstate,
     }
 
   pstate->pr_recvlen += recvlen;
-  pstate->pr_buffer  += recvlen;
-  pstate->pr_buflen  -= recvlen;
 }
 
 /****************************************************************************
@@ -129,34 +155,20 @@ static size_t can_recvfrom_newdata(FAR struct 
net_driver_s *dev,
 {
   unsigned int offset;
   size_t recvlen;
-#ifdef CONFIG_NET_TIMESTAMP
-  FAR struct can_conn_s *conn = pstate->pr_conn;
 
-  if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) &&
-      pstate->pr_msglen == sizeof(struct timeval))
-    {
-      struct timeval tv;
-
-      tv.tv_sec = dev->d_iob->io_time.tv_sec;
-      tv.tv_usec = dev->d_iob->io_time.tv_nsec / 1000;
-      memcpy(pstate->pr_msgbuf, &tv, sizeof(struct timeval));
-    }
+#ifdef CONFIG_NET_TIMESTAMP
+  cmsg_store_timestamp(pstate->pr_msg, &dev->d_iob->io_time,
+                       pstate->pr_conn->sconn.s_options);
 #endif
 
-  if (dev->d_len > pstate->pr_buflen)
-    {
-      recvlen = pstate->pr_buflen;
-    }
-  else
-    {
-      recvlen = dev->d_len;
-    }
+  recvlen = MIN(pstate->pr_msg->msg_iov->iov_len, dev->d_len);
 
   /* Copy the new packet data into the user buffer */
 
   offset = (dev->d_appdata - dev->d_iob->io_data) - dev->d_iob->io_offset;
 
-  recvlen = iob_copyout(pstate->pr_buffer, dev->d_iob, recvlen, offset);
+  recvlen = iob_copyout(pstate->pr_msg->msg_iov->iov_base,
+                        dev->d_iob, recvlen, offset);
 
   /* Trim the copied buffers */
 
@@ -241,30 +253,28 @@ static inline int can_readahead(struct can_recvfrom_s 
*pstate)
    * buffer.
    */
 
-  pstate->pr_recvlen = -1;
+  pstate->pr_recvlen = -ENODATA;
 
-  if (pstate->pr_buflen > 0 &&
+  if (pstate->pr_msg->msg_iov->iov_len > 0 &&
       (iob = iob_remove_queue(&conn->readahead)) != NULL)
     {
       DEBUGASSERT(iob->io_pktlen > 0);
 
 #ifdef CONFIG_NET_TIMESTAMP
-      if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) &&
-          pstate->pr_msglen == sizeof(struct timeval))
-        {
-          struct timeval tv;
-
-          tv.tv_sec = iob->io_time.tv_sec;
-          tv.tv_usec = iob->io_time.tv_nsec / 1000;
-          memcpy(pstate->pr_msgbuf, &tv, sizeof(struct timeval));
-        }
+      cmsg_store_timestamp(pstate->pr_msg, &iob->io_time,
+                           conn->sconn.s_options);
 #endif
 
       /* Transfer that buffered data from the I/O buffer chain into
        * the user buffer.
        */
 
-      recvlen = iob_copyout(pstate->pr_buffer, iob, pstate->pr_buflen, 0);
+      recvlen = iob_copyout(pstate->pr_msg->msg_iov->iov_base,
+                            iob, pstate->pr_msg->msg_iov->iov_len, 0);
+
+      /* Update the accumulated size of the data read */
+
+      pstate->pr_recvlen = recvlen;
 
       /* We should have taken all of the data from the I/O buffer chain,
        * so release it. There is no trimming needed, since One CAN/CANFD
@@ -440,25 +450,7 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
 
   /* Initialize the state structure. */
 
-  memset(&state, 0, sizeof(struct can_recvfrom_s));
-  nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
-
-  state.pr_buflen = msg->msg_iov->iov_len;
-  state.pr_buffer = msg->msg_iov->iov_base;
-
-#ifdef CONFIG_NET_TIMESTAMP
-  if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP))
-    {
-      state.pr_msgbuf = cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP,
-                                    NULL, sizeof(struct timeval));
-      if (state.pr_msgbuf != NULL)
-        {
-          state.pr_msglen = sizeof(struct timeval);
-        }
-    }
-#endif
-
-  state.pr_conn = conn;
+  can_recvfrom_initialize(conn, msg, &state);
 
   /* Handle any any CAN 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/pkt/pkt_recvmsg.c b/net/pkt/pkt_recvmsg.c
index 79489a9ca49..f3f675eddbe 100644
--- a/net/pkt/pkt_recvmsg.c
+++ b/net/pkt/pkt_recvmsg.c
@@ -65,46 +65,6 @@ struct pkt_recvfrom_s
   uint8_t                      pr_type;    /* Protocol type */
 };
 
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: pkt_store_cmsg_timestamp
- *
- * Description:
- *   Store the timestamp in the cmsg
- *
- * Input Parameters:
- *   pstate     Recicve state information
- *   timestamp  Timestamp  information
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-#ifdef CONFIG_NET_TIMESTAMP
-static void pkt_store_cmsg_timestamp(FAR struct pkt_recvfrom_s *pstate,
-                                     FAR struct timespec *timestamp)
-{
-  FAR struct msghdr *msg = pstate->pr_msg;
-  struct timeval tv;
-
-  if (_SO_GETOPT(pstate->pr_conn->sconn.s_options, SO_TIMESTAMPNS))
-    {
-      cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMPNS, timestamp,
-                  sizeof(struct timespec));
-    }
-  else
-    {
-      TIMESPEC_TO_TIMEVAL(&tv, timestamp);
-      cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP, &tv,
-                  sizeof(struct timeval));
-    }
-}
-#endif
-
 /****************************************************************************
  * Name: pkt_add_recvlen
  *
@@ -158,13 +118,8 @@ static void pkt_recvfrom_newdata(FAR struct net_driver_s 
*dev,
   size_t recvlen;
 
 #ifdef CONFIG_NET_TIMESTAMP
-  /* Unpack stored timestamp if SO_TIMESTAMP socket option is enabled */
-
-  if (_SO_GETOPT(pstate->pr_conn->sconn.s_options, SO_TIMESTAMP) ||
-      _SO_GETOPT(pstate->pr_conn->sconn.s_options, SO_TIMESTAMPNS))
-    {
-      pkt_store_cmsg_timestamp(pstate, &dev->d_iob->io_time);
-    }
+  cmsg_store_timestamp(pstate->pr_msg, &dev->d_iob->io_time,
+                       pstate->pr_conn->sconn.s_options);
 #endif
 
   recvlen = MIN(pstate->pr_msg->msg_iov->iov_len, dev->d_len);
@@ -385,15 +340,8 @@ static inline void pkt_readahead(FAR struct pkt_recvfrom_s 
*pstate)
       DEBUGASSERT(iob->io_pktlen > 0);
 
 #ifdef CONFIG_NET_TIMESTAMP
-      /* Unpack stored timestamp if SO_TIMESTAMP/SO_TIMESTAMPNS socket option
-       * is enabled
-       */
-
-      if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) ||
-          _SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMPNS))
-        {
-          pkt_store_cmsg_timestamp(pstate, &iob->io_time);
-        }
+      cmsg_store_timestamp(pstate->pr_msg, &iob->io_time,
+                           conn->sconn.s_options);
 #endif
 
       /* Copy to user */
diff --git a/net/udp/udp_recvfrom.c b/net/udp/udp_recvfrom.c
index 3514069fd07..a7357d78b87 100644
--- a/net/udp/udp_recvfrom.c
+++ b/net/udp/udp_recvfrom.c
@@ -67,19 +67,6 @@ struct udp_recvfrom_s
  * Private Functions
  ****************************************************************************/
 
-#ifdef CONFIG_NET_TIMESTAMP
-static void udp_store_cmsg_timestamp(FAR struct udp_recvfrom_s *pstate,
-                                     FAR struct timespec *timestamp)
-{
-  FAR struct msghdr *msg = pstate->ir_msg;
-  struct timeval tv;
-
-  TIMESPEC_TO_TIMEVAL(&tv, timestamp);
-  cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP,
-              &tv, sizeof(struct timeval));
-}
-#endif
-
 #ifdef CONFIG_NET_SOCKOPTS
 static void udp_recvpktinfo(FAR struct udp_recvfrom_s *pstate,
                             FAR void *srcaddr, uint8_t ifindex)
@@ -224,7 +211,8 @@ static inline void udp_readahead(struct udp_recvfrom_s 
*pstate)
 
       if (conn->timestamp)
         {
-          udp_store_cmsg_timestamp(pstate, &iob->io_time);
+          cmsg_store_timestamp(pstate->ir_msg, &iob->io_time,
+                               conn->sconn.s_options);
         }
 #endif
 
@@ -465,7 +453,8 @@ static uint32_t udp_eventhandler(FAR struct net_driver_s 
*dev,
 #ifdef CONFIG_NET_TIMESTAMP
           if (pstate->ir_conn->timestamp)
             {
-              udp_store_cmsg_timestamp(pstate, &dev->d_iob->io_time);
+              cmsg_store_timestamp(pstate->ir_msg, &dev->d_iob->io_time,
+                                   pstate->ir_conn->sconn.s_options);
             }
 #endif
 
diff --git a/net/utils/net_cmsg.c b/net/utils/net_cmsg.c
index c36c989c3ce..0cbfb41bc2e 100644
--- a/net/utils/net_cmsg.c
+++ b/net/utils/net_cmsg.c
@@ -28,6 +28,7 @@
 
 #include <sys/socket.h>
 
+#include "socket/socket.h"
 #include "utils/utils.h"
 
 /****************************************************************************
@@ -60,7 +61,7 @@
  ****************************************************************************/
 
 FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type,
-                      FAR void *value, int value_len)
+                      FAR const void *value, int value_len)
 {
   FAR struct cmsghdr *cmsg;
   unsigned long cmsgspace = CMSG_SPACE(value_len);
@@ -86,3 +87,37 @@ FAR void *cmsg_append(FAR struct msghdr *msg, int level, int 
type,
 
   return cmsgdata;
 }
+
+/****************************************************************************
+ * Name: cmsg_store_timestamp
+ *
+ * Description:
+ *   Store the timestamp in the cmsg
+ *
+ * Input Parameters:
+ *   msg    - Pointer to the msghdr containing ancillary data (CMSG).
+ *   tstamp - Timestamp information.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TIMESTAMP
+void cmsg_store_timestamp(FAR struct msghdr *msg,
+                          FAR const struct timespec *tstamp, sockopt_t opt)
+{
+  if (_SO_GETOPT(opt, SO_TIMESTAMP))
+    {
+      struct timeval tv;
+      TIMESPEC_TO_TIMEVAL(&tv, tstamp);
+      cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP, &tv,
+                  sizeof(struct timeval));
+    }
+  else if (_SO_GETOPT(opt, SO_TIMESTAMPNS))
+    {
+      cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMPNS, tstamp,
+                  sizeof(struct timespec));
+    }
+}
+#endif /* CONFIG_NET_TIMESTAMP */
diff --git a/net/utils/utils.h b/net/utils/utils.h
index 03fe8d15d2c..5b34ae2976c 100644
--- a/net/utils/utils.h
+++ b/net/utils/utils.h
@@ -668,7 +668,27 @@ uint16_t icmpv6_chksum(FAR struct net_driver_s *dev, 
unsigned int iplen);
  ****************************************************************************/
 
 FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type,
-                      FAR void *value, int value_len);
+                      FAR const void *value, int value_len);
+
+/****************************************************************************
+ * Name: cmsg_store_timestamp
+ *
+ * Description:
+ *   Store the timestamp in the cmsg
+ *
+ * Input Parameters:
+ *   msg    - Pointer to the msghdr containing ancillary data (CMSG).
+ *   tstamp - Timestamp information.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TIMESTAMP
+void cmsg_store_timestamp(FAR struct msghdr *msg,
+                          FAR const struct timespec *tstamp, sockopt_t opt);
+#endif /* CONFIG_NET_TIMESTAMP */
 
 #undef EXTERN
 #ifdef __cplusplus

Reply via email to