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 <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu
2024-08-26 14:48:55 +08:00
committed by Xiang Xiao
parent 98c6cd45db
commit cd86499e83
8 changed files with 160 additions and 77 deletions
+10 -3
View File
@@ -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
-1
View File
@@ -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
+1 -3
View File
@@ -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",
+2 -2
View File
@@ -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));
}
}
+2 -8
View File
@@ -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 &&
+7 -3
View File
@@ -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);
+28 -26
View File
@@ -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);
lc_size_t pathlen;
lc_size_t pktlen;
ret = local_fifo_write(&conn->lc_outfile, (FAR const uint8_t *)&len16,
sizeof(uint16_t));
if (ret != sizeof(uint16_t))
/* Send the packet length */
for (pktlen = 0, iov = buf; iov != end; iov++)
{
pktlen += iov->iov_len;
}
if (pktlen > rcvsize - sizeof(lc_size_t))
{
nerr("ERROR: Packet is too big: %d\n", pktlen);
return -EMSGSIZE;
}
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;
}
/* Send the packet length */
for (len16 = 0, iov = buf; iov != end; iov++)
{
len16 += iov->iov_len;
}
if (len16 > conn->lc_sndsize - sizeof(uint32_t))
{
nerr("ERROR: Packet is too big: %d\n", len16);
return -EMSGSIZE;
}
ret = local_fifo_write(filep, (FAR const uint8_t *)&len16,
sizeof(uint16_t));
if (ret != sizeof(uint16_t))
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;
}
+110 -31
View File
@@ -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)
recvsize = conn->lc_rcvsize;
#ifdef CONFIG_NET_LOCAL_DGRAM
if (psock->s_type == SOCK_DGRAM)
{
*(FAR int *)value = conn->lc_rcvsize;
}
else
{
*(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;