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

commit 98c6cd45db421db610c60801ca8d54a75379f0d9
Author: ligd <[email protected]>
AuthorDate: Wed Aug 14 20:41:23 2024 +0800

    local_socket: add SO_SNDBUF & SO_RCVBUF support
    
    lets a user program modify the size of the local_socket buffer
    using setsockopt.
    
    Signed-off-by: ligd <[email protected]>
---
 net/local/local.h            |  9 ++---
 net/local/local_conn.c       |  2 ++
 net/local/local_connect.c    |  5 ++-
 net/local/local_fifo.c       | 15 +++++----
 net/local/local_recvmsg.c    |  2 +-
 net/local/local_sendmsg.c    |  2 +-
 net/local/local_sendpacket.c |  2 +-
 net/local/local_sockif.c     | 79 ++++++++++++++++++++++++++++++++++++++++++--
 8 files changed, 98 insertions(+), 18 deletions(-)

diff --git a/net/local/local.h b/net/local/local.h
index c46b0c1df7..428c3e5b4e 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -49,8 +49,6 @@
 #define LOCAL_NPOLLWAITERS 2
 #define LOCAL_NCONTROLFDS  4
 
-#define LOCAL_SEND_LIMIT   (CONFIG_DEV_FIFO_SIZE - sizeof(uint16_t))
-
 /****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
@@ -122,6 +120,8 @@ struct local_conn_s
   char lc_path[UNIX_PATH_MAX];   /* Path assigned by bind() */
   int32_t lc_instance_id;        /* Connection instance ID for stream
                                   * server<->client connection pair */
+  uint32_t lc_sndsize;           /* Send buffer size */
+  uint32_t lc_rcvsize;           /* Receive buffer size */
 
   FAR struct local_conn_s *
                         lc_peer; /* Peer connection instance */
@@ -558,7 +558,8 @@ int local_getaddr(FAR struct local_conn_s *conn, FAR struct 
sockaddr *addr,
  *
  ****************************************************************************/
 
-int local_create_fifos(FAR struct local_conn_s *conn);
+int local_create_fifos(FAR struct local_conn_s *conn,
+                       uint32_t cssize, uint32_t scsize);
 
 /****************************************************************************
  * Name: local_create_halfduplex
@@ -570,7 +571,7 @@ int local_create_fifos(FAR struct local_conn_s *conn);
 
 #ifdef CONFIG_NET_LOCAL_DGRAM
 int local_create_halfduplex(FAR struct local_conn_s *conn,
-                            FAR const char *path);
+                            FAR const char *path, uint32_t bufsize);
 #endif
 
 /****************************************************************************
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index d1403a3a1d..bbd67db723 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -153,6 +153,8 @@ FAR struct local_conn_s *local_alloc(void)
        */
 
       conn->lc_crefs = 1;
+      conn->lc_sndsize = CONFIG_DEV_FIFO_SIZE;
+      conn->lc_rcvsize = CONFIG_DEV_FIFO_SIZE;
 
 #ifdef CONFIG_NET_LOCAL_STREAM
       nxsem_init(&conn->lc_waitsem, 0, 0);
diff --git a/net/local/local_connect.c b/net/local/local_connect.c
index b768a2bc92..b7c3aefa95 100644
--- a/net/local/local_connect.c
+++ b/net/local/local_connect.c
@@ -35,6 +35,7 @@
 
 #include <arch/irq.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 
 #include "utils/utils.h"
 #include "socket/socket.h"
@@ -87,7 +88,9 @@ static int inline local_stream_connect(FAR struct 
local_conn_s *client,
 
   /* Create the FIFOs needed for the connection */
 
-  ret = local_create_fifos(client);
+  ret = local_create_fifos(client,
+          MIN(client->lc_sndsize, server->lc_rcvsize),
+          MIN(client->lc_rcvsize, server->lc_sndsize));
   if (ret < 0)
     {
       nerr("ERROR: Failed to create FIFOs for %s: %d\n",
diff --git a/net/local/local_fifo.c b/net/local/local_fifo.c
index 1cc96c1052..daf454b70a 100644
--- a/net/local/local_fifo.c
+++ b/net/local/local_fifo.c
@@ -166,7 +166,7 @@ static bool local_fifo_exists(FAR const char *path)
  *
  ****************************************************************************/
 
-static int local_create_fifo(FAR const char *path)
+static int local_create_fifo(FAR const char *path, uint32_t bufsize)
 {
   int ret;
 
@@ -174,7 +174,7 @@ static int local_create_fifo(FAR const char *path)
 
   if (!local_fifo_exists(path))
     {
-      ret = nx_mkfifo(path, 0644, CONFIG_DEV_FIFO_SIZE);
+      ret = nx_mkfifo(path, 0644, bufsize);
       if (ret < 0)
         {
           nerr("ERROR: Failed to create FIFO %s: %d\n", path, ret);
@@ -422,7 +422,8 @@ int local_set_pollthreshold(FAR struct local_conn_s *conn,
  *
  ****************************************************************************/
 
-int local_create_fifos(FAR struct local_conn_s *conn)
+int local_create_fifos(FAR struct local_conn_s *conn,
+                       uint32_t cssize, uint32_t scsize)
 {
   char path[LOCAL_FULLPATH_LEN];
   int ret;
@@ -430,13 +431,13 @@ int local_create_fifos(FAR struct local_conn_s *conn)
   /* Create the client-to-server FIFO if it does not already exist. */
 
   local_cs_name(conn, path);
-  ret = local_create_fifo(path);
+  ret = local_create_fifo(path, cssize);
   if (ret >= 0)
     {
       /* Create the server-to-client FIFO if it does not already exist. */
 
       local_sc_name(conn, path);
-      ret = local_create_fifo(path);
+      ret = local_create_fifo(path, scsize);
     }
 
   return ret;
@@ -452,14 +453,14 @@ int local_create_fifos(FAR struct local_conn_s *conn)
 
 #ifdef CONFIG_NET_LOCAL_DGRAM
 int local_create_halfduplex(FAR struct local_conn_s *conn,
-                            FAR const char *path)
+                            FAR const char *path, uint32_t bufsize)
 {
   char fullpath[LOCAL_FULLPATH_LEN];
 
   /* Create the half duplex FIFO if it does not already exist. */
 
   local_hd_name(path, fullpath);
-  return local_create_fifo(fullpath);
+  return local_create_fifo(fullpath, bufsize);
 }
 #endif /* CONFIG_NET_LOCAL_DGRAM */
 
diff --git a/net/local/local_recvmsg.c b/net/local/local_recvmsg.c
index c96226ef16..9ef506d302 100644
--- a/net/local/local_recvmsg.c
+++ b/net/local/local_recvmsg.c
@@ -397,7 +397,7 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void 
*buf, size_t len,
 
       /* Make sure that half duplex FIFO has been created */
 
-      ret = local_create_halfduplex(conn, conn->lc_path);
+      ret = local_create_halfduplex(conn, conn->lc_path, conn->lc_rcvsize);
       if (ret < 0)
         {
           nerr("ERROR: Failed to create FIFO for %s: %d\n",
diff --git a/net/local/local_sendmsg.c b/net/local/local_sendmsg.c
index 75adc8aaba..6b61eb4e3f 100644
--- a/net/local/local_sendmsg.c
+++ b/net/local/local_sendmsg.c
@@ -335,7 +335,7 @@ static ssize_t local_sendto(FAR struct socket *psock,
    * REVISIT:  Or should be just make sure that it already exists?
    */
 
-  ret = local_create_halfduplex(conn, unaddr->sun_path);
+  ret = local_create_halfduplex(conn, unaddr->sun_path, conn->lc_sndsize);
   if (ret < 0)
     {
       nerr("ERROR: Failed to create FIFO for %s: %zd\n",
diff --git a/net/local/local_sendpacket.c b/net/local/local_sendpacket.c
index 939dde1169..8560efdff0 100644
--- a/net/local/local_sendpacket.c
+++ b/net/local/local_sendpacket.c
@@ -136,7 +136,7 @@ int local_send_preamble(FAR struct local_conn_s *conn,
       len16 += iov->iov_len;
     }
 
-  if (len16 > LOCAL_SEND_LIMIT)
+  if (len16 > conn->lc_sndsize - sizeof(uint32_t))
     {
       nerr("ERROR: Packet is too big: %d\n", len16);
       return -EMSGSIZE;
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index 47f16c87b5..1b45f679ab 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -34,6 +34,7 @@
 #include <debug.h>
 
 #include <netinet/in.h>
+#include <sys/param.h>
 
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/net/net.h>
@@ -545,6 +546,8 @@ static int local_getpeername(FAR struct socket *psock,
 static int local_getsockopt(FAR struct socket *psock, int level, int option,
                             FAR void *value, FAR socklen_t *value_len)
 {
+  FAR struct local_conn_s *conn = psock->s_conn;
+
   DEBUGASSERT(psock->s_domain == PF_LOCAL);
 
   if (level == SOL_SOCKET)
@@ -554,7 +557,6 @@ static int local_getsockopt(FAR struct socket *psock, int 
level, int option,
 #ifdef CONFIG_NET_LOCAL_SCM
           case SO_PEERCRED:
             {
-              FAR struct local_conn_s *conn = psock->s_conn;
               if (*value_len != sizeof(struct ucred))
                 {
                   return -EINVAL;
@@ -572,7 +574,36 @@ static int local_getsockopt(FAR struct socket *psock, int 
level, int option,
                   return -EINVAL;
                 }
 
-              *(FAR int *)value = LOCAL_SEND_LIMIT;
+              if (psock->s_type == SOCK_STREAM)
+                {
+                  *(FAR int *)value = conn->lc_sndsize;
+                }
+              else
+                {
+                  *(FAR int *)value = conn->lc_sndsize -
+                                      sizeof(uint32_t) -
+                                      UNIX_PATH_MAX;
+                }
+              return OK;
+            }
+
+          case SO_RCVBUF:
+            {
+              if (*value_len != sizeof(int))
+                {
+                  return -EINVAL;
+                }
+
+              if (psock->s_type == SOCK_STREAM)
+                {
+                  *(FAR int *)value = conn->lc_rcvsize;
+                }
+              else
+                {
+                  *(FAR int *)value = conn->lc_rcvsize -
+                                      sizeof(uint32_t) -
+                                      UNIX_PATH_MAX;
+                }
               return OK;
             }
         }
@@ -606,6 +637,46 @@ static int local_getsockopt(FAR struct socket *psock, int 
level, int option,
 static int local_setsockopt(FAR struct socket *psock, int level, int option,
                             FAR const void *value, socklen_t value_len)
 {
+  FAR struct local_conn_s *conn = psock->s_conn;
+
+  DEBUGASSERT(psock->s_domain == PF_LOCAL);
+
+  if (level == SOL_SOCKET)
+    {
+      switch (option)
+        {
+          case SO_SNDBUF:
+            {
+              if (psock->s_type == SOCK_STREAM)
+                {
+                  conn->lc_sndsize = *(FAR const int *)value;
+                }
+              else
+                {
+                  conn->lc_sndsize = *(FAR const int *)value +
+                                     sizeof(uint32_t) +
+                                     UNIX_PATH_MAX;
+                }
+              return OK;
+            }
+
+          case SO_RCVBUF:
+            {
+              if (psock->s_type == SOCK_STREAM)
+                {
+                  conn->lc_rcvsize = *(FAR const int *)value;
+                }
+              else
+                {
+                  conn->lc_rcvsize = *(FAR const int *)value +
+                                     sizeof(uint32_t) +
+                                     UNIX_PATH_MAX;
+                }
+              return OK;
+            }
+        }
+    }
+
   return -ENOPROTOOPT;
 }
 
@@ -902,7 +973,9 @@ static int local_socketpair(FAR struct socket *psocks[2])
 
   /* Create the FIFOs needed for the connection */
 
-  ret = local_create_fifos(conns[0]);
+  ret = local_create_fifos(conns[0],
+          MIN(conns[0]->lc_sndsize, conns[1]->lc_rcvsize),
+          MIN(conns[0]->lc_rcvsize, conns[1]->lc_sndsize));
   if (ret < 0)
     {
       goto errout;

Reply via email to