mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
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:
@@ -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 */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user