mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 21:36:28 +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_NPOLLWAITERS 2
|
||||||
#define LOCAL_NCONTROLFDS 4
|
#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
|
* Public Type Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -120,8 +128,7 @@ struct local_conn_s
|
|||||||
char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */
|
char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */
|
||||||
int32_t lc_instance_id; /* Connection instance ID for stream
|
int32_t lc_instance_id; /* Connection instance ID for stream
|
||||||
* server<->client connection pair */
|
* server<->client connection pair */
|
||||||
uint32_t lc_sndsize; /* Send buffer size */
|
lc_size_t lc_rcvsize; /* Receive buffer size */
|
||||||
uint32_t lc_rcvsize; /* Receive buffer size */
|
|
||||||
|
|
||||||
FAR struct local_conn_s *
|
FAR struct local_conn_s *
|
||||||
lc_peer; /* Peer connection instance */
|
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,
|
int local_send_preamble(FAR struct local_conn_s *conn,
|
||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
FAR const struct iovec *buf,
|
FAR const struct iovec *buf,
|
||||||
size_t len);
|
size_t len, size_t rcvsize);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: local_send_packet
|
* Name: local_send_packet
|
||||||
|
|||||||
@@ -153,7 +153,6 @@ FAR struct local_conn_s *local_alloc(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
conn->lc_crefs = 1;
|
conn->lc_crefs = 1;
|
||||||
conn->lc_sndsize = CONFIG_DEV_FIFO_SIZE;
|
|
||||||
conn->lc_rcvsize = CONFIG_DEV_FIFO_SIZE;
|
conn->lc_rcvsize = CONFIG_DEV_FIFO_SIZE;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_LOCAL_STREAM
|
#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 */
|
/* Create the FIFOs needed for the connection */
|
||||||
|
|
||||||
ret = local_create_fifos(client,
|
ret = local_create_fifos(client, server->lc_rcvsize, client->lc_rcvsize);
|
||||||
MIN(client->lc_sndsize, server->lc_rcvsize),
|
|
||||||
MIN(client->lc_rcvsize, server->lc_sndsize));
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nerr("ERROR: Failed to create FIFOs for %s: %d\n",
|
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,
|
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,
|
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 readlen;
|
||||||
size_t pathlen;
|
size_t pathlen;
|
||||||
bool bclose = false;
|
bool bclose = false;
|
||||||
uint16_t addrlen;
|
lc_size_t addrlen;
|
||||||
uint16_t pktlen;
|
lc_size_t pktlen;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int ret;
|
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 */
|
/* Verify that this is a bound, un-connected peer socket */
|
||||||
|
|
||||||
if (conn->lc_state != LOCAL_STATE_BOUND &&
|
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
|
#ifdef CONFIG_NET_LOCAL_DGRAM
|
||||||
FAR struct local_conn_s *conn = psock->s_conn;
|
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;
|
FAR const struct sockaddr_un *unaddr = (FAR const struct sockaddr_un *)to;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
@@ -307,7 +308,9 @@ static ssize_t local_sendto(FAR struct socket *psock,
|
|||||||
}
|
}
|
||||||
|
|
||||||
net_lock();
|
net_lock();
|
||||||
if (local_findconn(conn, unaddr) == NULL)
|
|
||||||
|
server = local_findconn(conn, unaddr);
|
||||||
|
if (server == NULL)
|
||||||
{
|
{
|
||||||
net_unlock();
|
net_unlock();
|
||||||
nerr("ERROR: No such file or directory\n");
|
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?
|
* 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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nerr("ERROR: Failed to create FIFO for %s: %zd\n",
|
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 */
|
/* 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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
nerr("ERROR: Failed to send the preamble: %zd\n", ret);
|
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,
|
int local_send_preamble(FAR struct local_conn_s *conn,
|
||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
FAR const struct iovec *buf,
|
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 *end = buf + len;
|
||||||
FAR const struct iovec *iov;
|
FAR const struct iovec *iov;
|
||||||
int ret;
|
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,
|
/* Send the packet length */
|
||||||
sizeof(uint16_t));
|
|
||||||
if (ret != sizeof(uint16_t))
|
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);
|
nerr("ERROR: local send path length failed ret: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the packet length */
|
ret = local_fifo_write(filep, (FAR const uint8_t *)&pktlen,
|
||||||
|
sizeof(lc_size_t));
|
||||||
for (len16 = 0, iov = buf; iov != end; iov++)
|
if (ret != sizeof(lc_size_t))
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return local_fifo_write(&conn->lc_outfile, (uint8_t *)conn->lc_path,
|
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 *end = buf + len;
|
||||||
FAR const struct iovec *iov;
|
FAR const struct iovec *iov;
|
||||||
int ret = -EINVAL;
|
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);
|
ret = local_fifo_write(filep, iov->iov_base, iov->iov_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -193,7 +195,7 @@ int local_send_packet(FAR struct file *filep, FAR const struct iovec *buf,
|
|||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
len16 += ret;
|
sendlen += ret;
|
||||||
if (ret != iov->iov_len)
|
if (ret != iov->iov_len)
|
||||||
{
|
{
|
||||||
break;
|
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:
|
case SO_SNDBUF:
|
||||||
{
|
{
|
||||||
|
int sendsize;
|
||||||
|
|
||||||
if (*value_len != sizeof(int))
|
if (*value_len != sizeof(int))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
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
|
else
|
||||||
{
|
{
|
||||||
*(FAR int *)value = conn->lc_sndsize -
|
sendsize = CONFIG_DEV_FIFO_SIZE;
|
||||||
sizeof(uint32_t) -
|
|
||||||
UNIX_PATH_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SO_RCVBUF:
|
case SO_RCVBUF:
|
||||||
{
|
{
|
||||||
|
int recvsize;
|
||||||
|
|
||||||
if (*value_len != sizeof(int))
|
if (*value_len != sizeof(int))
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
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;
|
recvsize -= sizeof(lc_size_t) * 2 + UNIX_PATH_MAX;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(FAR int *)value = conn->lc_rcvsize -
|
|
||||||
sizeof(uint32_t) -
|
|
||||||
UNIX_PATH_MAX;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*(FAR int *)value = recvsize;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -647,32 +657,102 @@ static int local_setsockopt(FAR struct socket *psock, int level, int option,
|
|||||||
{
|
{
|
||||||
case SO_SNDBUF:
|
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 +
|
rcvsize = MIN(*(FAR const int *)value,
|
||||||
sizeof(uint32_t) +
|
CONFIG_DEV_PIPE_MAXSIZE);
|
||||||
UNIX_PATH_MAX;
|
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:
|
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 +
|
rcvsize += sizeof(lc_size_t) * 2 + UNIX_PATH_MAX;
|
||||||
sizeof(uint32_t) +
|
|
||||||
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 */
|
/* Create the FIFOs needed for the connection */
|
||||||
|
|
||||||
ret = local_create_fifos(conns[0],
|
ret = local_create_fifos(conns[0], conns[0]->lc_rcvsize,
|
||||||
MIN(conns[0]->lc_sndsize, conns[1]->lc_rcvsize),
|
conns[1]->lc_rcvsize);
|
||||||
MIN(conns[0]->lc_rcvsize, conns[1]->lc_sndsize));
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1023,7 +1102,7 @@ static int local_socketpair(FAR struct socket *psocks[2])
|
|||||||
{
|
{
|
||||||
for (i = 0; i < 2; i++)
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|||||||
Reference in New Issue
Block a user