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 cd86499e83358c3181653330a04734abeddd0b5b
Author: zhanghongyu <[email protected]>
AuthorDate: Mon Aug 26 14:48:55 2024 +0800

    local_socket: add SO_SNDBUF & SO_RCVBUF support for accept socket
    
    SO_SNDBUF takes effect only after the connection in STREAM mode
    is successful
    support full life cycle modification of SO_RCVBUF
    
    Signed-off-by: zhanghongyu <[email protected]>
---
 net/local/local.h            |  13 +++-
 net/local/local_conn.c       |   1 -
 net/local/local_connect.c    |   4 +-
 net/local/local_fifo.c       |   4 +-
 net/local/local_recvmsg.c    |  10 +--
 net/local/local_sendmsg.c    |  10 ++-
 net/local/local_sendpacket.c |  46 +++++++-------
 net/local/local_sockif.c     | 141 +++++++++++++++++++++++++++++++++----------
 8 files changed, 156 insertions(+), 73 deletions(-)

diff --git a/net/local/local.h b/net/local/local.h
index 428c3e5b4e..45c1d3d0ce 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -49,6 +49,14 @@
 #define LOCAL_NPOLLWAITERS 2
 #define LOCAL_NCONTROLFDS  4
 
+#if CONFIG_DEV_PIPE_MAXSIZE > 65535
+typedef uint32_t lc_size_t;  /* 32-bit index */
+#elif CONFIG_DEV_PIPE_MAXSIZE > 255
+typedef uint16_t lc_size_t;  /* 16-bit index */
+#else
+typedef uint8_t lc_size_t;   /*  8-bit index */
+#endif
+
 /****************************************************************************
  * Public Type Definitions
  ****************************************************************************/
@@ -120,8 +128,7 @@ 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 */
+  lc_size_t lc_rcvsize;          /* Receive buffer size */
 
   FAR struct local_conn_s *
                         lc_peer; /* Peer connection instance */
@@ -456,7 +463,7 @@ ssize_t local_sendmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
 int local_send_preamble(FAR struct local_conn_s *conn,
                         FAR struct file *filep,
                         FAR const struct iovec *buf,
-                        size_t len);
+                        size_t len, size_t rcvsize);
 
 /****************************************************************************
  * Name: local_send_packet
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index bbd67db723..02dbeea281 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -153,7 +153,6 @@ 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
diff --git a/net/local/local_connect.c b/net/local/local_connect.c
index b7c3aefa95..d743832c08 100644
--- a/net/local/local_connect.c
+++ b/net/local/local_connect.c
@@ -88,9 +88,7 @@ static int inline local_stream_connect(FAR struct 
local_conn_s *client,
 
   /* Create the FIFOs needed for the connection */
 
-  ret = local_create_fifos(client,
-          MIN(client->lc_sndsize, server->lc_rcvsize),
-          MIN(client->lc_rcvsize, server->lc_sndsize));
+  ret = local_create_fifos(client, server->lc_rcvsize, client->lc_rcvsize);
   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 daf454b70a..bb5cd14362 100644
--- a/net/local/local_fifo.c
+++ b/net/local/local_fifo.c
@@ -687,7 +687,7 @@ int local_open_receiver(FAR struct local_conn_s *conn, bool 
nonblock)
            */
 
           ret = local_set_pollinthreshold(&conn->lc_infile,
-                                          2 * sizeof(uint16_t));
+                                          2 * sizeof(lc_size_t));
         }
     }
 
@@ -730,7 +730,7 @@ int local_open_sender(FAR struct local_conn_s *conn, FAR 
const char *path,
            */
 
           ret = local_set_polloutthreshold(&conn->lc_outfile,
-                                           2 * sizeof(uint16_t));
+                                           2 * sizeof(lc_size_t));
         }
     }
 
diff --git a/net/local/local_recvmsg.c b/net/local/local_recvmsg.c
index 9ef506d302..bcd406f42f 100644
--- a/net/local/local_recvmsg.c
+++ b/net/local/local_recvmsg.c
@@ -369,17 +369,11 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void 
*buf, size_t len,
   size_t readlen;
   size_t pathlen;
   bool bclose = false;
-  uint16_t addrlen;
-  uint16_t pktlen;
+  lc_size_t addrlen;
+  lc_size_t pktlen;
   int offset = 0;
   int ret;
 
-  /* We keep packet sizes in a uint16_t, so there is a upper limit to the
-   * 'len' that can be supported.
-   */
-
-  DEBUGASSERT(len <= UINT16_MAX);
-
   /* Verify that this is a bound, un-connected peer socket */
 
   if (conn->lc_state != LOCAL_STATE_BOUND &&
diff --git a/net/local/local_sendmsg.c b/net/local/local_sendmsg.c
index 6b61eb4e3f..670505dff5 100644
--- a/net/local/local_sendmsg.c
+++ b/net/local/local_sendmsg.c
@@ -261,6 +261,7 @@ static ssize_t local_sendto(FAR struct socket *psock,
 {
 #ifdef CONFIG_NET_LOCAL_DGRAM
   FAR struct local_conn_s *conn = psock->s_conn;
+  FAR struct local_conn_s *server;
   FAR const struct sockaddr_un *unaddr = (FAR const struct sockaddr_un *)to;
   ssize_t ret;
 
@@ -307,7 +308,9 @@ static ssize_t local_sendto(FAR struct socket *psock,
     }
 
   net_lock();
-  if (local_findconn(conn, unaddr) == NULL)
+
+  server = local_findconn(conn, unaddr);
+  if (server == NULL)
     {
       net_unlock();
       nerr("ERROR: No such file or directory\n");
@@ -335,7 +338,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, conn->lc_sndsize);
+  ret = local_create_halfduplex(conn, unaddr->sun_path, server->lc_rcvsize);
   if (ret < 0)
     {
       nerr("ERROR: Failed to create FIFO for %s: %zd\n",
@@ -358,7 +361,8 @@ static ssize_t local_sendto(FAR struct socket *psock,
 
   /* Send the preamble */
 
-  ret = local_send_preamble(conn, &conn->lc_outfile, buf, len);
+  ret = local_send_preamble(conn, &conn->lc_outfile, buf, len,
+                            server->lc_rcvsize);
   if (ret < 0)
     {
       nerr("ERROR: Failed to send the preamble: %zd\n", ret);
diff --git a/net/local/local_sendpacket.c b/net/local/local_sendpacket.c
index 8560efdff0..8debf03d66 100644
--- a/net/local/local_sendpacket.c
+++ b/net/local/local_sendpacket.c
@@ -114,43 +114,45 @@ static int local_fifo_write(FAR struct file *filep, FAR 
const uint8_t *buf,
 int local_send_preamble(FAR struct local_conn_s *conn,
                         FAR struct file *filep,
                         FAR const struct iovec *buf,
-                        size_t len)
+                        size_t len, size_t rcvsize)
 {
   FAR const struct iovec *end = buf + len;
   FAR const struct iovec *iov;
   int ret;
-  uint16_t len16 = strlen(conn->lc_path);
-
-  ret = local_fifo_write(&conn->lc_outfile, (FAR const uint8_t *)&len16,
-                         sizeof(uint16_t));
-  if (ret != sizeof(uint16_t))
-    {
-      nerr("ERROR: local send path length failed ret: %d\n", ret);
-      return ret;
-    }
+  lc_size_t pathlen;
+  lc_size_t pktlen;
 
   /* Send the packet length */
 
-  for (len16 = 0, iov = buf; iov != end; iov++)
+  for (pktlen = 0, iov = buf; iov != end; iov++)
     {
-      len16 += iov->iov_len;
+      pktlen += iov->iov_len;
     }
 
-  if (len16 > conn->lc_sndsize - sizeof(uint32_t))
+  if (pktlen > rcvsize - sizeof(lc_size_t))
     {
-      nerr("ERROR: Packet is too big: %d\n", len16);
+      nerr("ERROR: Packet is too big: %d\n", pktlen);
       return -EMSGSIZE;
     }
 
-  ret = local_fifo_write(filep, (FAR const uint8_t *)&len16,
-                        sizeof(uint16_t));
-  if (ret != sizeof(uint16_t))
+  pathlen = strlen(conn->lc_path);
+  ret = local_fifo_write(&conn->lc_outfile, (FAR const uint8_t *)&pathlen,
+                         sizeof(lc_size_t));
+  if (ret != sizeof(lc_size_t))
+    {
+      nerr("ERROR: local send path length failed ret: %d\n", ret);
+      return ret;
+    }
+
+  ret = local_fifo_write(filep, (FAR const uint8_t *)&pktlen,
+                         sizeof(lc_size_t));
+  if (ret != sizeof(lc_size_t))
     {
       return ret;
     }
 
   return local_fifo_write(&conn->lc_outfile, (uint8_t *)conn->lc_path,
-                          strlen(conn->lc_path));
+                          pathlen);
 }
 
 /****************************************************************************
@@ -176,9 +178,9 @@ int local_send_packet(FAR struct file *filep, FAR const 
struct iovec *buf,
   FAR const struct iovec *end = buf + len;
   FAR const struct iovec *iov;
   int ret = -EINVAL;
-  uint16_t len16;
+  lc_size_t sendlen;
 
-  for (len16 = 0, iov = buf; iov != end; iov++)
+  for (sendlen = 0, iov = buf; iov != end; iov++)
     {
       ret = local_fifo_write(filep, iov->iov_base, iov->iov_len);
       if (ret < 0)
@@ -193,7 +195,7 @@ int local_send_packet(FAR struct file *filep, FAR const 
struct iovec *buf,
 
       if (ret > 0)
         {
-          len16 += ret;
+          sendlen += ret;
           if (ret != iov->iov_len)
             {
               break;
@@ -201,5 +203,5 @@ int local_send_packet(FAR struct file *filep, FAR const 
struct iovec *buf,
         }
     }
 
-  return len16 > 0 ? len16 : ret;
+  return sendlen > 0 ? sendlen : ret;
 }
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index 1b45f679ab..1b7367ad98 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -569,41 +569,51 @@ static int local_getsockopt(FAR struct socket *psock, int 
level, int option,
 
           case SO_SNDBUF:
             {
+              int sendsize;
+
               if (*value_len != sizeof(int))
                 {
                   return -EINVAL;
                 }
 
-              if (psock->s_type == SOCK_STREAM)
+              if (conn->lc_peer)
                 {
-                  *(FAR int *)value = conn->lc_sndsize;
+                  sendsize = conn->lc_peer->lc_rcvsize;
                 }
               else
                 {
-                  *(FAR int *)value = conn->lc_sndsize -
-                                      sizeof(uint32_t) -
-                                      UNIX_PATH_MAX;
+                  sendsize = CONFIG_DEV_FIFO_SIZE;
+                }
+
+#ifdef CONFIG_NET_LOCAL_DGRAM
+              if (psock->s_type == SOCK_DGRAM)
+                {
+                  sendsize -= sizeof(lc_size_t) * 2 + UNIX_PATH_MAX;
                 }
+#endif
+
+              *(FAR int *)value = sendsize;
               return OK;
             }
 
           case SO_RCVBUF:
             {
+              int recvsize;
+
               if (*value_len != sizeof(int))
                 {
                   return -EINVAL;
                 }
 
-              if (psock->s_type == SOCK_STREAM)
-                {
-                  *(FAR int *)value = conn->lc_rcvsize;
-                }
-              else
+              recvsize = conn->lc_rcvsize;
+#ifdef CONFIG_NET_LOCAL_DGRAM
+              if (psock->s_type == SOCK_DGRAM)
                 {
-                  *(FAR int *)value = conn->lc_rcvsize -
-                                      sizeof(uint32_t) -
-                                      UNIX_PATH_MAX;
+                  recvsize -= sizeof(lc_size_t) * 2 + UNIX_PATH_MAX;
                 }
+#endif
+
+              *(FAR int *)value = recvsize;
               return OK;
             }
         }
@@ -647,32 +657,102 @@ static int local_setsockopt(FAR struct socket *psock, 
int level, int option,
         {
           case SO_SNDBUF:
             {
-              if (psock->s_type == SOCK_STREAM)
+              int ret = OK;
+              int rcvsize;
+
+              if (value_len < sizeof(int))
                 {
-                  conn->lc_sndsize = *(FAR const int *)value;
+                  return -EINVAL;
                 }
-              else
+
+              net_lock();
+
+              /* Only SOCK_STREAM sockets need set the send buffer size */
+
+              if (conn->lc_peer)
                 {
-                  conn->lc_sndsize = *(FAR const int *)value +
-                                     sizeof(uint32_t) +
-                                     UNIX_PATH_MAX;
+                  rcvsize = MIN(*(FAR const int *)value,
+                                CONFIG_DEV_PIPE_MAXSIZE);
+                  if (conn->lc_peer->lc_infile.f_inode != NULL)
+                    {
+                      ret = file_ioctl(&conn->lc_peer->lc_infile,
+                                       PIPEIOC_SETSIZE, rcvsize);
+                    }
+
+                  if (ret == OK)
+                    {
+                      conn->lc_peer->lc_rcvsize = rcvsize;
+                    }
                 }
-              return OK;
+#ifdef CONFIG_NET_LOCAL_STREAM
+              else if (psock->s_type == SOCK_STREAM)
+                {
+                  ret = -ENOTCONN;
+                }
+#endif
+
+              net_unlock();
+
+              return ret;
             }
 
           case SO_RCVBUF:
             {
-              if (psock->s_type == SOCK_STREAM)
+              int ret = OK;
+              int rcvsize;
+
+              if (value_len < sizeof(int))
                 {
-                  conn->lc_rcvsize = *(FAR const int *)value;
+                  return -EINVAL;
                 }
-              else
+
+              net_lock();
+
+              rcvsize = *(FAR const int *)value;
+#ifdef CONFIG_NET_LOCAL_DGRAM
+              if (psock->s_type == SOCK_DGRAM)
                 {
-                  conn->lc_rcvsize = *(FAR const int *)value +
-                                     sizeof(uint32_t) +
-                                     UNIX_PATH_MAX;
+                  rcvsize += sizeof(lc_size_t) * 2 + UNIX_PATH_MAX;
                 }
-              return OK;
+#endif
+
+              rcvsize = MIN(rcvsize, CONFIG_DEV_PIPE_MAXSIZE);
+              if (conn->lc_infile.f_inode != NULL)
+                {
+                  ret = file_ioctl(&conn->lc_infile, PIPEIOC_SETSIZE,
+                                   rcvsize);
+                }
+#ifdef CONFIG_NET_LOCAL_DGRAM
+              else if (psock->s_type == SOCK_DGRAM &&
+                       conn->lc_state == LOCAL_STATE_BOUND)
+                {
+                  ret = local_create_halfduplex(conn, conn->lc_path,
+                                                rcvsize);
+                  if (ret >= 0)
+                    {
+                      ret = local_open_receiver(conn, true);
+                      if (ret >= 0)
+                        {
+                          ret = file_ioctl(&conn->lc_infile, PIPEIOC_SETSIZE,
+                                           rcvsize);
+                        }
+
+                      if (conn->lc_infile.f_inode != NULL)
+                        {
+                          file_close(&conn->lc_infile);
+                        }
+                    }
+                }
+#endif
+
+              if (ret == OK)
+                {
+                  conn->lc_rcvsize = rcvsize;
+                }
+
+              net_unlock();
+
+              return ret;
             }
         }
     }
@@ -973,9 +1053,8 @@ static int local_socketpair(FAR struct socket *psocks[2])
 
   /* Create the FIFOs needed for the connection */
 
-  ret = local_create_fifos(conns[0],
-          MIN(conns[0]->lc_sndsize, conns[1]->lc_rcvsize),
-          MIN(conns[0]->lc_rcvsize, conns[1]->lc_sndsize));
+  ret = local_create_fifos(conns[0], conns[0]->lc_rcvsize,
+                           conns[1]->lc_rcvsize);
   if (ret < 0)
     {
       goto errout;
@@ -1023,7 +1102,7 @@ static int local_socketpair(FAR struct socket *psocks[2])
     {
       for (i = 0; i < 2; i++)
         {
-          ret = local_set_pollthreshold(conns[i], sizeof(uint16_t));
+          ret = local_set_pollthreshold(conns[i], sizeof(lc_size_t));
           if (ret < 0)
             {
               goto errout;

Reply via email to