net/local:Add peek support for pipe and MSG_PEEK support for local socket

fifo peek example:
struct pipe_peek_s peek_buf;
peek_buf.len = len;
peek_buf.data = buf;
ret = file_ioctl(filep, PIPEIOC_PEEK,(unsigned long)((uintptr_t)&peek_buf));

Signed-off-by: wangyingdong <wangyingdong@xiaomi.com>
This commit is contained in:
wangyingdong
2023-06-29 11:35:25 +08:00
committed by Xiang Xiao
parent 8cee6f0cc8
commit 8f6f601ec1
4 changed files with 76 additions and 22 deletions
+10
View File
@@ -838,6 +838,16 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case PIPEIOC_PEEK:
{
FAR struct pipe_peek_s *peek = (FAR struct pipe_peek_s *)arg;
DEBUGASSERT(peek && peek->buf);
ret = circbuf_peek(&dev->d_buffer, peek->buf, peek->size);
}
break;
case FIONWRITE: /* Number of bytes waiting in send queue */ case FIONWRITE: /* Number of bytes waiting in send queue */
case FIONREAD: /* Number of bytes available for reading */ case FIONREAD: /* Number of bytes available for reading */
{ {
+11
View File
@@ -26,6 +26,7 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <sys/types.h>
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@@ -447,6 +448,10 @@
* threshold. * threshold.
* OUT: None */ * OUT: None */
#define PIPEIOC_PEEK _PIPEIOC(0x0004) /* Pipe peek interface
* IN: pipe_peek_s
* OUT: Length of data */
/* RTC driver ioctl definitions *********************************************/ /* RTC driver ioctl definitions *********************************************/
/* (see nuttx/include/rtc.h */ /* (see nuttx/include/rtc.h */
@@ -661,6 +666,12 @@
* Public Type Definitions * Public Type Definitions
****************************************************************************/ ****************************************************************************/
struct pipe_peek_s
{
FAR void *buf;
size_t size;
};
/**************************************************************************** /****************************************************************************
* Public Data * Public Data
****************************************************************************/ ****************************************************************************/
+4
View File
@@ -122,6 +122,10 @@ 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 */
#ifdef CONFIG_NET_LOCAL_DGRAM
uint16_t pktlen; /* Read-ahead packet length */
#endif /* CONFIG_NET_LOCAL_DGRAM */
FAR struct local_conn_s * FAR struct local_conn_s *
lc_peer; /* Peer connection instance */ lc_peer; /* Peer connection instance */
#ifdef CONFIG_NET_LOCAL_SCM #ifdef CONFIG_NET_LOCAL_SCM
+51 -22
View File
@@ -56,12 +56,27 @@
****************************************************************************/ ****************************************************************************/
static int psock_fifo_read(FAR struct socket *psock, FAR void *buf, static int psock_fifo_read(FAR struct socket *psock, FAR void *buf,
FAR size_t *readlen, bool once) FAR size_t *readlen, int flags, bool once)
{ {
FAR struct local_conn_s *conn = psock->s_conn; FAR struct local_conn_s *conn = psock->s_conn;
int ret; int ret;
ret = local_fifo_read(&conn->lc_infile, buf, readlen, once); if (flags & MSG_PEEK)
{
struct pipe_peek_s peek =
{
buf,
*readlen
};
ret = file_ioctl(&conn->lc_infile, PIPEIOC_PEEK,
(unsigned long)((uintptr_t)&peek));
}
else
{
ret = local_fifo_read(&conn->lc_infile, buf, readlen, once);
}
if (ret < 0) if (ret < 0)
{ {
/* -ECONNRESET is a special case. We may or not have received /* -ECONNRESET is a special case. We may or not have received
@@ -245,7 +260,7 @@ psock_stream_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Read the packet */ /* Read the packet */
ret = psock_fifo_read(psock, buf, &readlen, true); ret = psock_fifo_read(psock, buf, &readlen, flags, true);
if (ret < 0) if (ret < 0)
{ {
return ret; return ret;
@@ -294,10 +309,9 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR socklen_t *fromlen) FAR socklen_t *fromlen)
{ {
FAR struct local_conn_s *conn = psock->s_conn; FAR struct local_conn_s *conn = psock->s_conn;
uint16_t pktlen;
size_t readlen; size_t readlen;
bool bclose = false; bool bclose = false;
int ret; int ret = 0;
/* We keep packet sizes in a uint16_t, so there is a upper limit to the /* We keep packet sizes in a uint16_t, so there is a upper limit to the
* 'len' that can be supported. * 'len' that can be supported.
@@ -346,24 +360,28 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* the next packet. * the next packet.
*/ */
ret = local_sync(&conn->lc_infile); if (conn->pktlen <= 0)
if (ret < 0)
{ {
nerr("ERROR: Failed to get packet length: %d\n", ret); ret = local_sync(&conn->lc_infile);
goto errout_with_infd;
}
else if (ret > UINT16_MAX)
{
nerr("ERROR: Packet is too big: %d\n", ret);
goto errout_with_infd;
}
pktlen = ret; if (ret < 0)
{
nerr("ERROR: Failed to get packet length: %d\n", ret);
goto errout_with_infd;
}
else if (ret > UINT16_MAX)
{
nerr("ERROR: Packet is too big: %d\n", ret);
goto errout_with_infd;
}
conn->pktlen = ret;
}
/* Read the packet */ /* Read the packet */
readlen = MIN(pktlen, len); readlen = MIN(conn->pktlen, len);
ret = psock_fifo_read(psock, buf, &readlen, false); ret = psock_fifo_read(psock, buf, &readlen, flags, false);
if (ret < 0) if (ret < 0)
{ {
goto errout_with_infd; goto errout_with_infd;
@@ -373,20 +391,25 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
* of the packet to the bit bucket. * of the packet to the bit bucket.
*/ */
DEBUGASSERT(readlen <= pktlen); if (flags & MSG_PEEK)
if (readlen < pktlen) {
goto skip_flush;
}
DEBUGASSERT(readlen <= conn->pktlen);
if (readlen < conn->pktlen)
{ {
uint8_t bitbucket[32]; uint8_t bitbucket[32];
uint16_t remaining; uint16_t remaining;
size_t tmplen; size_t tmplen;
remaining = pktlen - readlen; remaining = conn->pktlen - readlen;
do do
{ {
/* Read 32 bytes into the bit bucket */ /* Read 32 bytes into the bit bucket */
tmplen = MIN(remaining, 32); tmplen = MIN(remaining, 32);
ret = psock_fifo_read(psock, bitbucket, &tmplen, false); ret = psock_fifo_read(psock, bitbucket, &tmplen, flags, false);
if (ret < 0) if (ret < 0)
{ {
goto errout_with_infd; goto errout_with_infd;
@@ -402,6 +425,12 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
while (remaining > 0); while (remaining > 0);
} }
/* The fifo has been read and the pktlen needs to be cleared */
conn->pktlen = 0;
skip_flush:
/* Return the address family */ /* Return the address family */
if (from) if (from)