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;
