mirror of
https://github.com/apache/nuttx.git
synced 2026-05-25 01:39:44 +08:00
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:
+10
-3
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user