forked from nuttx/nuttx-update
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:
parent
8cee6f0cc8
commit
8f6f601ec1
4 changed files with 76 additions and 22 deletions
|
@ -838,6 +838,16 @@ int pipecommon_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
}
|
||||
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 FIONREAD: /* Number of bytes available for reading */
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -447,6 +448,10 @@
|
|||
* threshold.
|
||||
* OUT: None */
|
||||
|
||||
#define PIPEIOC_PEEK _PIPEIOC(0x0004) /* Pipe peek interface
|
||||
* IN: pipe_peek_s
|
||||
* OUT: Length of data */
|
||||
|
||||
/* RTC driver ioctl definitions *********************************************/
|
||||
|
||||
/* (see nuttx/include/rtc.h */
|
||||
|
@ -661,6 +666,12 @@
|
|||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
struct pipe_peek_s
|
||||
{
|
||||
FAR void *buf;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
|
|
@ -122,6 +122,10 @@ 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 */
|
||||
#ifdef CONFIG_NET_LOCAL_DGRAM
|
||||
uint16_t pktlen; /* Read-ahead packet length */
|
||||
#endif /* CONFIG_NET_LOCAL_DGRAM */
|
||||
|
||||
FAR struct local_conn_s *
|
||||
lc_peer; /* Peer connection instance */
|
||||
#ifdef CONFIG_NET_LOCAL_SCM
|
||||
|
|
|
@ -56,12 +56,27 @@
|
|||
****************************************************************************/
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
/* -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 */
|
||||
|
||||
ret = psock_fifo_read(psock, buf, &readlen, true);
|
||||
ret = psock_fifo_read(psock, buf, &readlen, flags, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -294,10 +309,9 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
FAR socklen_t *fromlen)
|
||||
{
|
||||
FAR struct local_conn_s *conn = psock->s_conn;
|
||||
uint16_t pktlen;
|
||||
size_t readlen;
|
||||
bool bclose = false;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* We keep packet sizes in a uint16_t, so there is a upper limit to the
|
||||
* '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.
|
||||
*/
|
||||
|
||||
ret = local_sync(&conn->lc_infile);
|
||||
if (ret < 0)
|
||||
if (conn->pktlen <= 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;
|
||||
}
|
||||
ret = local_sync(&conn->lc_infile);
|
||||
|
||||
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 */
|
||||
|
||||
readlen = MIN(pktlen, len);
|
||||
ret = psock_fifo_read(psock, buf, &readlen, false);
|
||||
readlen = MIN(conn->pktlen, len);
|
||||
ret = psock_fifo_read(psock, buf, &readlen, flags, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(readlen <= pktlen);
|
||||
if (readlen < pktlen)
|
||||
if (flags & MSG_PEEK)
|
||||
{
|
||||
goto skip_flush;
|
||||
}
|
||||
|
||||
DEBUGASSERT(readlen <= conn->pktlen);
|
||||
if (readlen < conn->pktlen)
|
||||
{
|
||||
uint8_t bitbucket[32];
|
||||
uint16_t remaining;
|
||||
size_t tmplen;
|
||||
|
||||
remaining = pktlen - readlen;
|
||||
remaining = conn->pktlen - readlen;
|
||||
do
|
||||
{
|
||||
/* Read 32 bytes into the bit bucket */
|
||||
|
||||
tmplen = MIN(remaining, 32);
|
||||
ret = psock_fifo_read(psock, bitbucket, &tmplen, false);
|
||||
ret = psock_fifo_read(psock, bitbucket, &tmplen, flags, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_infd;
|
||||
|
@ -402,6 +425,12 @@ psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
while (remaining > 0);
|
||||
}
|
||||
|
||||
/* The fifo has been read and the pktlen needs to be cleared */
|
||||
|
||||
conn->pktlen = 0;
|
||||
|
||||
skip_flush:
|
||||
|
||||
/* Return the address family */
|
||||
|
||||
if (from)
|
||||
|
|
Loading…
Reference in a new issue