You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/09/24 15:09:34 UTC

[incubator-nuttx] branch master updated (b7a5b24 -> 1b5d6aa)

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

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from b7a5b24  Add support for MT25Q1G SPI NOR
     new 1ba922a  net/local: replace the listener list to global
     new 1e07879  net/local: split the waiter node from lc_node
     new ea82a0b  net/local: add local_peerconn helper
     new 1b5d6aa  net/local: add socket message control support

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 net/local/Kconfig         |   6 ++
 net/local/local.h         |  48 ++++++++++------
 net/local/local_accept.c  |  13 ++++-
 net/local/local_conn.c    |  85 ++++++++++++++++++++++++----
 net/local/local_connect.c |  20 ++++---
 net/local/local_listen.c  |  14 -----
 net/local/local_recvmsg.c | 111 ++++++++++++++++++++++++++++++++++--
 net/local/local_release.c |  15 +++--
 net/local/local_sendmsg.c | 139 ++++++++++++++++++++++++++++++++++++++++++++--
 9 files changed, 382 insertions(+), 69 deletions(-)

[incubator-nuttx] 01/04: net/local: replace the listener list to global

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit 1ba922a826b753288617c0843e550db111a00db2
Author: chao.an <an...@xiaomi.com>
AuthorDate: Mon Sep 13 15:06:15 2021 +0800

    net/local: replace the listener list to global
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/local/local.h         |  6 ------
 net/local/local_conn.c    | 38 +++++++++++++++++++++++++-------------
 net/local/local_connect.c | 15 +++++++--------
 net/local/local_listen.c  | 14 --------------
 net/local/local_release.c |  4 ----
 5 files changed, 32 insertions(+), 45 deletions(-)

diff --git a/net/local/local.h b/net/local/local.h
index bc60487..3088e1f 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -200,12 +200,6 @@ extern "C"
 
 EXTERN const struct sock_intf_s g_local_sockif;
 
-#ifdef CONFIG_NET_LOCAL_STREAM
-/* A list of all SOCK_STREAM listener connections */
-
-EXTERN dq_queue_t g_local_listeners;
-#endif
-
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index e6e421e..bf4faf3 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -36,6 +36,14 @@
 #include "local/local.h"
 
 /****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* A list of all allocated packet socket connections */
+
+static dq_queue_t g_local_connections;
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -50,16 +58,14 @@
 
 void local_initialize(void)
 {
-#ifdef CONFIG_NET_LOCAL_STREAM
-  dq_init(&g_local_listeners);
-#endif
+  dq_init(&g_local_connections);
 }
 
 /****************************************************************************
  * Name: local_nextconn
  *
  * Description:
- *   Traverse the list of listened local connections
+ *   Traverse the list of local connections
  *
  * Assumptions:
  *   This function must be called with the network locked.
@@ -68,18 +74,12 @@ void local_initialize(void)
 
 FAR struct local_conn_s *local_nextconn(FAR struct local_conn_s *conn)
 {
-#ifdef CONFIG_NET_LOCAL_STREAM
   if (!conn)
     {
-      return (FAR struct local_conn_s *)g_local_listeners.head;
+      return (FAR struct local_conn_s *)g_local_connections.head;
     }
-  else
-    {
-      return (FAR struct local_conn_s *)conn->lc_node.flink;
-    }
-#else
-  return NULL;
-#endif
+
+  return (FAR struct local_conn_s *)conn->lc_node.flink;
 }
 
 /****************************************************************************
@@ -112,6 +112,12 @@ FAR struct local_conn_s *local_alloc(void)
       nxsem_init(&conn->lc_waitsem, 0, 0);
       nxsem_set_protocol(&conn->lc_waitsem, SEM_PRIO_NONE);
 #endif
+
+      /* Add the connection structure to the list of listeners */
+
+      net_lock();
+      dq_addlast(&conn->lc_node, &g_local_connections);
+      net_unlock();
     }
 
   return conn;
@@ -130,6 +136,12 @@ void local_free(FAR struct local_conn_s *conn)
 {
   DEBUGASSERT(conn != NULL);
 
+  /* Remove the server from the list of listeners. */
+
+  net_lock();
+  dq_rem(&conn->lc_node, &g_local_connections);
+  net_unlock();
+
   /* Make sure that the read-only FIFO is closed */
 
   if (conn->lc_infile.f_inode != NULL)
diff --git a/net/local/local_connect.c b/net/local/local_connect.c
index 5bcf426..6dda5c5 100644
--- a/net/local/local_connect.c
+++ b/net/local/local_connect.c
@@ -267,13 +267,6 @@ int psock_local_connect(FAR struct socket *psock,
   net_lock();
   while ((conn = local_nextconn(conn)) != NULL)
     {
-      /* Anything in the listener list should be a stream socket in the
-       * listening state
-       */
-
-      DEBUGASSERT(conn->lc_state == LOCAL_STATE_LISTENING &&
-                  conn->lc_proto == SOCK_STREAM);
-
       /* Handle according to the server connection type */
 
       switch (conn->lc_type)
@@ -289,7 +282,13 @@ int psock_local_connect(FAR struct socket *psock,
 
         case LOCAL_TYPE_PATHNAME:  /* lc_path holds a null terminated string */
           {
-            if (strncmp(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX - 1)
+            /* Anything in the listener list should be a stream socket in the
+             * listening state
+             */
+
+            if (conn->lc_state == LOCAL_STATE_LISTENING &&
+                conn->lc_proto == SOCK_STREAM &&
+                strncmp(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX - 1)
                 == 0)
               {
                 int ret = OK;
diff --git a/net/local/local_listen.c b/net/local/local_listen.c
index f3d3271..a69ca1d 100644
--- a/net/local/local_listen.c
+++ b/net/local/local_listen.c
@@ -37,14 +37,6 @@
 #include "local/local.h"
 
 /****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/* A list of all allocated packet socket connections */
-
-dq_queue_t g_local_listeners;
-
-/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -118,12 +110,6 @@ int local_listen(FAR struct socket *psock, int backlog)
       DEBUGASSERT(server->lc_node.flink == NULL &&
                   server->lc_node.flink == NULL);
 
-      /* Add the connection structure to the list of listeners */
-
-      net_lock();
-      dq_addlast(&server->lc_node, &g_local_listeners);
-      net_unlock();
-
       /* And change the server state to listing */
 
       server->lc_state = LOCAL_STATE_LISTENING;
diff --git a/net/local/local_release.c b/net/local/local_release.c
index 22a81d4..dbbd796 100644
--- a/net/local/local_release.c
+++ b/net/local/local_release.c
@@ -97,10 +97,6 @@ int local_release(FAR struct local_conn_s *conn)
         }
 
       conn->u.server.lc_pending = 0;
-
-      /* Remove the server from the list of listeners. */
-
-      dq_rem(&conn->lc_node, &g_local_listeners);
     }
 #endif /* CONFIG_NET_LOCAL_STREAM */
 

[incubator-nuttx] 03/04: net/local: add local_peerconn helper

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit ea82a0b63824e488deea57eaa745387bc87e45e1
Author: chao.an <an...@xiaomi.com>
AuthorDate: Tue Sep 14 15:21:38 2021 +0800

    net/local: add local_peerconn helper
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/local/local.h      | 13 +++++++++++++
 net/local/local_conn.c | 27 +++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/net/local/local.h b/net/local/local.h
index e65078b..c746b51 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -255,6 +255,19 @@ void local_free(FAR struct local_conn_s *conn);
 FAR struct local_conn_s *local_nextconn(FAR struct local_conn_s *conn);
 
 /****************************************************************************
+ * Name: local_peerconn
+ *
+ * Description:
+ *   Traverse the connections list to find the peer
+ *
+ * Assumptions:
+ *   This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+FAR struct local_conn_s *local_peerconn(FAR struct local_conn_s *conn);
+
+/****************************************************************************
  * Name: psock_local_bind
  *
  * Description:
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index bf4faf3..3b27400 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -83,6 +83,33 @@ FAR struct local_conn_s *local_nextconn(FAR struct local_conn_s *conn)
 }
 
 /****************************************************************************
+ * Name: local_peerconn
+ *
+ * Description:
+ *   Traverse the connections list to find the peer
+ *
+ * Assumptions:
+ *   This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+FAR struct local_conn_s *local_peerconn(FAR struct local_conn_s *conn)
+{
+  FAR struct local_conn_s *peer = NULL;
+
+  while ((peer = local_nextconn(peer)) != NULL)
+    {
+      if (conn->lc_proto == peer->lc_proto && conn != peer &&
+          !strncmp(conn->lc_path, peer->lc_path, UNIX_PATH_MAX - 1))
+        {
+          return peer;
+        }
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
  * Name: local_alloc()
  *
  * Description:

[incubator-nuttx] 04/04: net/local: add socket message control support

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit 1b5d6aa068ec5113ae5b105f8120b865ea89b5a0
Author: chao.an <an...@xiaomi.com>
AuthorDate: Wed Sep 15 23:22:18 2021 +0800

    net/local: add socket message control support
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/local/Kconfig         |   6 ++
 net/local/local.h         |  26 ++++++---
 net/local/local_accept.c  |   3 +
 net/local/local_conn.c    |  26 +++++++++
 net/local/local_connect.c |   3 +
 net/local/local_recvmsg.c | 111 ++++++++++++++++++++++++++++++++++--
 net/local/local_sendmsg.c | 139 ++++++++++++++++++++++++++++++++++++++++++++--
 7 files changed, 296 insertions(+), 18 deletions(-)

diff --git a/net/local/Kconfig b/net/local/Kconfig
index e32c0b3..158282b 100644
--- a/net/local/Kconfig
+++ b/net/local/Kconfig
@@ -33,6 +33,12 @@ config NET_LOCAL_DGRAM
 	---help---
 		Enable support for Unix domain SOCK_DGRAM type sockets
 
+config NET_LOCAL_SCM
+	bool "Unix domain socket control message"
+	default n
+	---help---
+		Enable support for Unix domain socket control message
+
 endif # NET_LOCAL
 
 endmenu # Unix Domain Sockets
diff --git a/net/local/local.h b/net/local/local.h
index c746b51..df0777d 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -46,6 +46,7 @@
  ****************************************************************************/
 
 #define LOCAL_NPOLLWAITERS 2
+#define LOCAL_NCONTROLFDS  4
 
 /* Packet format in FIFO:
  *
@@ -136,15 +137,22 @@ struct local_conn_s
 
   /* Fields common to SOCK_STREAM and SOCK_DGRAM */
 
-  uint8_t lc_crefs;            /* Reference counts on this instance */
-  uint8_t lc_proto;            /* SOCK_STREAM or SOCK_DGRAM */
-  uint8_t lc_type;             /* See enum local_type_e */
-  uint8_t lc_state;            /* See enum local_state_e */
-  struct file lc_infile;       /* File for read-only FIFO (peers) */
-  struct file lc_outfile;      /* File descriptor of write-only FIFO (peers) */
-  char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */
-  int32_t lc_instance_id;      /* Connection instance ID for stream
-                                * server<->client connection pair */
+  uint8_t lc_crefs;              /* Reference counts on this instance */
+  uint8_t lc_proto;              /* SOCK_STREAM or SOCK_DGRAM */
+  uint8_t lc_type;               /* See enum local_type_e */
+  uint8_t lc_state;              /* See enum local_state_e */
+  struct file lc_infile;         /* File for read-only FIFO (peers) */
+  struct file lc_outfile;        /* File descriptor of write-only FIFO (peers) */
+  char lc_path[UNIX_PATH_MAX];   /* Path assigned by bind() */
+  int32_t lc_instance_id;        /* Connection instance ID for stream
+                                  * server<->client connection pair */
+#ifdef CONFIG_NET_LOCAL_SCM
+  FAR struct local_conn_s *
+                        lc_peer; /* Peer connection instance */
+  uint16_t lc_cfpcount;          /* Control file pointer counter */
+  FAR struct file *
+     lc_cfps[LOCAL_NCONTROLFDS]; /* Socket message control filep */
+#endif /* CONFIG_NET_LOCAL_SCM */
 
 #ifdef CONFIG_NET_LOCAL_STREAM
   /* SOCK_STREAM fields common to both client and server */
diff --git a/net/local/local_accept.c b/net/local/local_accept.c
index 4529dab..8d4bec5 100644
--- a/net/local/local_accept.c
+++ b/net/local/local_accept.c
@@ -168,6 +168,9 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
               conn->lc_type   = LOCAL_TYPE_PATHNAME;
               conn->lc_state  = LOCAL_STATE_CONNECTED;
               conn->lc_psock  = psock;
+#ifdef CONFIG_NET_LOCAL_SCM
+              conn->lc_peer   = client;
+#endif /* CONFIG_NET_LOCAL_SCM */
 
               strncpy(conn->lc_path, client->lc_path, UNIX_PATH_MAX - 1);
               conn->lc_path[UNIX_PATH_MAX - 1] = '\0';
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index 3b27400..c968cca 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -161,12 +161,24 @@ FAR struct local_conn_s *local_alloc(void)
 
 void local_free(FAR struct local_conn_s *conn)
 {
+#ifdef CONFIG_NET_LOCAL_SCM
+  int i;
+#endif /* CONFIG_NET_LOCAL_SCM */
+
   DEBUGASSERT(conn != NULL);
 
   /* Remove the server from the list of listeners. */
 
   net_lock();
   dq_rem(&conn->lc_node, &g_local_connections);
+
+#ifdef CONFIG_NET_LOCAL_SCM
+  if (local_peerconn(conn) && conn->lc_peer)
+    {
+      conn->lc_peer->lc_peer = NULL;
+    }
+#endif /* CONFIG_NET_LOCAL_SCM */
+
   net_unlock();
 
   /* Make sure that the read-only FIFO is closed */
@@ -185,6 +197,20 @@ void local_free(FAR struct local_conn_s *conn)
       conn->lc_outfile.f_inode = NULL;
     }
 
+#ifdef CONFIG_NET_LOCAL_SCM
+  /* Free the pending control file pointer */
+
+  for (i = 0; i < conn->lc_cfpcount; i++)
+    {
+      if (conn->lc_cfps[i])
+        {
+          file_close(conn->lc_cfps[i]);
+          kmm_free(conn->lc_cfps[i]);
+          conn->lc_cfps[i] = NULL;
+        }
+    }
+#endif /* CONFIG_NET_LOCAL_SCM */
+
 #ifdef CONFIG_NET_LOCAL_STREAM
   /* Destroy all FIFOs associted with the connection */
 
diff --git a/net/local/local_connect.c b/net/local/local_connect.c
index b3aff31..1c3f407 100644
--- a/net/local/local_connect.c
+++ b/net/local/local_connect.c
@@ -301,6 +301,9 @@ int psock_local_connect(FAR struct socket *psock,
                         UNIX_PATH_MAX - 1);
                 client->lc_path[UNIX_PATH_MAX - 1] = '\0';
                 client->lc_instance_id = local_generate_instance_id();
+#ifdef CONFIG_NET_LOCAL_SCM
+                client->lc_peer = conn;
+#endif /* CONFIG_NET_LOCAL_SCM */
 
                 /* The client is now bound to an address */
 
diff --git a/net/local/local_recvmsg.c b/net/local/local_recvmsg.c
index 6cc1237..9ef2287 100644
--- a/net/local/local_recvmsg.c
+++ b/net/local/local_recvmsg.c
@@ -33,6 +33,8 @@
 #include <assert.h>
 #include <debug.h>
 
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/fs.h>
 #include <nuttx/net/net.h>
 
 #include "socket/socket.h"
@@ -106,6 +108,93 @@ static int psock_fifo_read(FAR struct socket *psock, FAR void *buf,
 }
 
 /****************************************************************************
+ * Name: local_recvctl
+ *
+ * Description:
+ *   Handle the socket message conntrol field
+ *
+ * Input Parameters:
+ *   conn     Local connection instance
+ *   msg      Message to send
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_LOCAL_SCM
+static void local_recvctl(FAR struct local_conn_s *conn,
+                          FAR struct msghdr *msg)
+{
+  FAR struct local_conn_s *peer;
+  struct cmsghdr *cmsg;
+  int count;
+  int *fds;
+  int i;
+
+  net_lock();
+
+  cmsg  = CMSG_FIRSTHDR(msg);
+  count = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
+  cmsg->cmsg_len = 0;
+
+  if (count == 0)
+    {
+      goto out;
+    }
+
+  if (conn->lc_peer == NULL)
+    {
+      peer = local_peerconn(conn);
+      if (peer == NULL)
+        {
+          goto out;
+        }
+    }
+  else
+    {
+      peer = conn;
+    }
+
+  if (peer->lc_cfpcount == 0)
+    {
+      goto out;
+    }
+
+  fds = (int *)CMSG_DATA(cmsg);
+
+  count = count > peer->lc_cfpcount ?
+                  peer->lc_cfpcount : count;
+  for (i = 0; i < count; i++)
+    {
+      fds[i] = file_dup(peer->lc_cfps[i], 0);
+      file_close(peer->lc_cfps[i]);
+      kmm_free(peer->lc_cfps[i]);
+      peer->lc_cfps[i] = NULL;
+      peer->lc_cfpcount--;
+      if (fds[i] < 0)
+        {
+          i++;
+          break;
+        }
+    }
+
+  if (i > 0)
+    {
+      if (peer->lc_cfpcount)
+        {
+          memmove(peer->lc_cfps[0], peer->lc_cfps[i],
+                  sizeof(FAR void *) * peer->lc_cfpcount);
+        }
+
+      cmsg->cmsg_len   = CMSG_LEN(sizeof(int) * i);
+      cmsg->cmsg_level = SOL_SOCKET;
+      cmsg->cmsg_type  = SCM_RIGHTS;
+    }
+
+out:
+  net_unlock();
+}
+#endif /* CONFIG_NET_LOCAL_SCM */
+
+/****************************************************************************
  * Name: psock_stream_recvfrom
  *
  * Description:
@@ -382,10 +471,10 @@ errout_with_halfduplex:
 ssize_t local_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
                       int flags)
 {
+  FAR socklen_t *fromlen = &msg->msg_namelen;
+  FAR struct sockaddr *from = msg->msg_name;
   FAR void *buf = msg->msg_iov->iov_base;
   size_t len = msg->msg_iov->iov_len;
-  FAR struct sockaddr *from = msg->msg_name;
-  FAR socklen_t *fromlen = &msg->msg_namelen;
 
   DEBUGASSERT(psock && psock->s_conn && buf);
 
@@ -394,7 +483,7 @@ ssize_t local_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
 #ifdef CONFIG_NET_LOCAL_STREAM
   if (psock->s_type == SOCK_STREAM)
     {
-      return psock_stream_recvfrom(psock, buf, len, flags, from, fromlen);
+      len = psock_stream_recvfrom(psock, buf, len, flags, from, fromlen);
     }
   else
 #endif
@@ -402,15 +491,27 @@ ssize_t local_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
 #ifdef CONFIG_NET_LOCAL_DGRAM
   if (psock->s_type == SOCK_DGRAM)
     {
-      return psock_dgram_recvfrom(psock, buf, len, flags, from, fromlen);
+      len = psock_dgram_recvfrom(psock, buf, len, flags, from, fromlen);
     }
   else
 #endif
     {
       DEBUGPANIC();
       nerr("ERROR: Unrecognized socket type: %" PRIu8 "\n", psock->s_type);
-      return -EINVAL;
+      len = -EINVAL;
+    }
+
+#ifdef CONFIG_NET_LOCAL_SCM
+  /* Receive the control message */
+
+  if (len >= 0 && msg->msg_control &&
+      msg->msg_controllen > sizeof(struct cmsghdr))
+    {
+      local_recvctl(psock->s_conn, msg);
     }
+#endif /* CONFIG_NET_LOCAL_SCM */
+
+  return len;
 }
 
 #endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/net/local/local_sendmsg.c b/net/local/local_sendmsg.c
index dd50f40..31c2114 100644
--- a/net/local/local_sendmsg.c
+++ b/net/local/local_sendmsg.c
@@ -32,6 +32,7 @@
 #include <assert.h>
 #include <debug.h>
 
+#include <nuttx/kmalloc.h>
 #include <nuttx/net/net.h>
 
 #include "socket/socket.h"
@@ -42,6 +43,105 @@
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: local_sendctl
+ *
+ * Description:
+ *   Handle the socket message conntrol field
+ *
+ * Input Parameters:
+ *   conn     Local connection instance
+ *   msg      Message to send
+ *
+ * Returned Value:
+ *  On any failure, a negated errno value is returned
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_LOCAL_SCM
+static int local_sendctl(FAR struct local_conn_s *conn,
+                         FAR struct msghdr *msg)
+{
+  FAR struct local_conn_s *peer;
+  FAR struct file *filep2;
+  FAR struct file *filep;
+  struct cmsghdr *cmsg;
+  int count;
+  int *fds;
+  int ret;
+  int i;
+
+  net_lock();
+
+  peer = conn->lc_peer;
+  if (peer == NULL)
+    {
+      peer = conn;
+    }
+
+  for_each_cmsghdr(cmsg, msg)
+    {
+      if (!CMSG_OK(msg, cmsg) ||
+          cmsg->cmsg_level != SOL_SOCKET ||
+          cmsg->cmsg_type != SCM_RIGHTS)
+        {
+          ret = -EOPNOTSUPP;
+          goto fail;
+        }
+
+      fds = (int *)CMSG_DATA(cmsg);
+      count = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
+
+      if (count + peer->lc_cfpcount > LOCAL_NCONTROLFDS)
+        {
+          ret = -EMFILE;
+          goto fail;
+        }
+
+      for (i = 0; i < count; i++)
+        {
+          ret = fs_getfilep(fds[i], &filep);
+          if (ret < 0)
+            {
+              goto fail;
+            }
+
+          filep2 = (FAR struct file *)kmm_zalloc(sizeof(*filep2));
+          if (!filep2)
+            {
+              ret = -ENOMEM;
+              goto fail;
+            }
+
+          ret = file_dup2(filep, filep2);
+          if (ret < 0)
+            {
+              kmm_free(filep2);
+              goto fail;
+            }
+
+          peer->lc_cfps[peer->lc_cfpcount++] = filep2;
+        }
+    }
+
+  net_unlock();
+
+  return count;
+
+fail:
+  while (i-- > 0)
+    {
+      file_close(peer->lc_cfps[--peer->lc_cfpcount]);
+      kmm_free(peer->lc_cfps[peer->lc_cfpcount]);
+      peer->lc_cfps[peer->lc_cfpcount] = NULL;
+    }
+
+  net_unlock();
+
+  return ret;
+}
+#endif /* CONFIG_NET_LOCAL_SCM */
+
+/****************************************************************************
  * Name: local_send
  *
  * Description:
@@ -284,13 +384,44 @@ errout_with_halfduplex:
 ssize_t local_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
                       int flags)
 {
-  FAR const struct iovec *buf = msg->msg_iov;
-  size_t len = msg->msg_iovlen;
   FAR const struct sockaddr *to = msg->msg_name;
+  FAR const struct iovec *buf = msg->msg_iov;
   socklen_t tolen = msg->msg_namelen;
+  size_t len = msg->msg_iovlen;
+#ifdef CONFIG_NET_LOCAL_SCM
+  FAR struct local_conn_s *conn = psock->s_conn;
+  int count;
+
+  if (msg->msg_control &&
+      msg->msg_controllen > sizeof(struct cmsghdr))
+    {
+      count = local_sendctl(conn, msg);
+      if (count < 0)
+        {
+          return count;
+        }
+    }
+#endif /* CONFIG_NET_LOCAL_SCM */
+
+  len = to ? local_sendto(psock, buf, len, flags, to, tolen) :
+             local_send(psock, buf, len, flags);
+#ifdef CONFIG_NET_LOCAL_SCM
+  if (len < 0 && count > 0)
+    {
+      net_lock();
+
+      while (count-- > 0)
+        {
+          file_close(conn->lc_cfps[--conn->lc_cfpcount]);
+          kmm_free(conn->lc_cfps[conn->lc_cfpcount]);
+          conn->lc_cfps[conn->lc_cfpcount] = NULL;
+        }
+
+      net_unlock();
+    }
+#endif
 
-  return to ? local_sendto(psock, buf, len, flags, to, tolen) :
-              local_send(psock, buf, len, flags);
+  return len;
 }
 
 #endif /* CONFIG_NET && CONFIG_NET_LOCAL */

[incubator-nuttx] 02/04: net/local: split the waiter node from lc_node

Posted by xi...@apache.org.
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/incubator-nuttx.git

commit 1e078795fb6d4d6c743a906648b8df78f032c289
Author: chao.an <an...@xiaomi.com>
AuthorDate: Thu Sep 16 13:40:02 2021 +0800

    net/local: split the waiter node from lc_node
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/local/local.h         |  3 ++-
 net/local/local_accept.c  | 10 +++++++---
 net/local/local_connect.c |  2 +-
 net/local/local_release.c | 11 +++++++----
 4 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/net/local/local.h b/net/local/local.h
index 3088e1f..e65078b 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -119,7 +119,7 @@ struct local_conn_s
 
   /* lc_node supports a doubly linked list: Listening SOCK_STREAM servers
    * will be linked into a list of listeners; SOCK_STREAM clients will be
-   * linked to the lc_waiters and lc_conn lists.
+   * linked to the lc_conn lists.
    */
 
   dq_entry_t lc_node;          /* Supports a doubly linked list */
@@ -179,6 +179,7 @@ struct local_conn_s
     struct
     {
       volatile int lc_result;  /* Result of the connection operation (client) */
+      dq_entry_t lc_waiter;    /* Linked to the lc_waiters lists */
     } client;
   } u;
 #endif /* CONFIG_NET_LOCAL_STREAM */
diff --git a/net/local/local_accept.c b/net/local/local_accept.c
index 53a3ab2..4529dab 100644
--- a/net/local/local_accept.c
+++ b/net/local/local_accept.c
@@ -31,6 +31,7 @@
 #include <queue.h>
 #include <debug.h>
 
+#include <nuttx/nuttx.h>
 #include <nuttx/net/net.h>
 
 #include "socket/socket.h"
@@ -100,6 +101,7 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
   FAR struct local_conn_s *server;
   FAR struct local_conn_s *client;
   FAR struct local_conn_s *conn;
+  FAR dq_entry_t *waiter;
   int ret;
 
   /* Some sanity checks */
@@ -135,11 +137,13 @@ int local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
        * head of the waiting list.
        */
 
-      client = (FAR struct local_conn_s *)
-        dq_remfirst(&server->u.server.lc_waiters);
+      waiter = dq_remfirst(&server->u.server.lc_waiters);
 
-      if (client)
+      if (waiter)
         {
+          client = container_of(waiter, struct local_conn_s,
+                                u.client.lc_waiter);
+
           /* Decrement the number of pending clients */
 
           DEBUGASSERT(server->u.server.lc_pending > 0);
diff --git a/net/local/local_connect.c b/net/local/local_connect.c
index 6dda5c5..b3aff31 100644
--- a/net/local/local_connect.c
+++ b/net/local/local_connect.c
@@ -138,7 +138,7 @@ static int inline local_stream_connect(FAR struct local_conn_s *client,
 
   /* Add ourself to the list of waiting connections and notify the server. */
 
-  dq_addlast(&client->lc_node, &server->u.server.lc_waiters);
+  dq_addlast(&client->u.client.lc_waiter, &server->u.server.lc_waiters);
   local_event_pollnotify(server, POLLIN);
 
   if (nxsem_get_value(&server->lc_waitsem, &sval) >= 0 && sval < 1)
diff --git a/net/local/local_release.c b/net/local/local_release.c
index dbbd796..7b10671 100644
--- a/net/local/local_release.c
+++ b/net/local/local_release.c
@@ -29,6 +29,7 @@
 #include <queue.h>
 #include <assert.h>
 
+#include <nuttx/nuttx.h>
 #include <nuttx/net/net.h>
 
 #include <arch/irq.h>
@@ -81,16 +82,18 @@ int local_release(FAR struct local_conn_s *conn)
   else if (conn->lc_state == LOCAL_STATE_LISTENING)
     {
       FAR struct local_conn_s *client;
+      FAR dq_entry_t *waiter;
 
       DEBUGASSERT(conn->lc_proto == SOCK_STREAM);
 
       /* Are there still clients waiting for a connection to the server? */
 
-      for (client =
-          (FAR struct local_conn_s *)conn->u.server.lc_waiters.head;
-           client;
-           client = (FAR struct local_conn_s *)dq_next(&client->lc_node))
+      for (waiter = dq_peek(&conn->u.server.lc_waiters);
+           waiter;
+           waiter = dq_next(&client->u.client.lc_waiter))
         {
+          client = container_of(waiter, struct local_conn_s,
+                                u.client.lc_waiter);
           client->u.client.lc_result = -ENOTCONN;
           nxsem_post(&client->lc_waitsem);
           local_event_pollnotify(client, POLLOUT);