mirror of
https://github.com/apache/nuttx.git
synced 2026-05-29 20:56:47 +08:00
Implement poll/select for sockets
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1277 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -571,4 +571,5 @@
|
|||||||
full buffer of read data before return. This means that getc would stall when it needed
|
full buffer of read data before return. This means that getc would stall when it needed
|
||||||
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
||||||
contexts, so it is still available within the driver as a configuration option.
|
contexts, so it is still available within the driver as a configuration option.
|
||||||
|
* Implement poll() and select() support for TCP/IP sockets
|
||||||
|
|
||||||
|
|||||||
@@ -1207,6 +1207,7 @@ nuttx-0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
|||||||
full buffer of read data before return. This means that getc would stall when it needed
|
full buffer of read data before return. This means that getc would stall when it needed
|
||||||
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
to refill the input buffer. The old behavior (read full blocks) might be useful in other
|
||||||
contexts, so it is still available within the driver as a configuration option.
|
contexts, so it is still available within the driver as a configuration option.
|
||||||
|
* Implement poll() and select() support for TCP/IP sockets
|
||||||
|
|
||||||
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
static ssize_t devconsole_read(struct file *, char *, size_t);
|
static ssize_t devconsole_read(struct file *, char *, size_t);
|
||||||
static ssize_t devconsole_write(struct file *, const char *, size_t);
|
static ssize_t devconsole_write(struct file *, const char *, size_t);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds);
|
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -85,7 +85,7 @@ static ssize_t devconsole_write(struct file *filp, const char *buffer, size_t le
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -56,7 +56,7 @@
|
|||||||
static ssize_t devnull_read(FAR struct file *, FAR char *, size_t);
|
static ssize_t devnull_read(FAR struct file *, FAR char *, size_t);
|
||||||
static ssize_t devnull_write(FAR struct file *, FAR const char *, size_t);
|
static ssize_t devnull_write(FAR struct file *, FAR const char *, size_t);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *poll);
|
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -103,9 +103,9 @@ static ssize_t devnull_write(FAR struct file *filp, FAR const char *buffer, size
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds)
|
static int devnull_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
if (fds)
|
if (setup)
|
||||||
{
|
{
|
||||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||||
if (fds->revents != 0)
|
if (fds->revents != 0)
|
||||||
|
|||||||
+3
-3
@@ -56,7 +56,7 @@
|
|||||||
static ssize_t devzero_read(FAR struct file *, FAR char *, size_t);
|
static ssize_t devzero_read(FAR struct file *, FAR char *, size_t);
|
||||||
static ssize_t devzero_write(FAR struct file *, FAR const char *, size_t);
|
static ssize_t devzero_write(FAR struct file *, FAR const char *, size_t);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds);
|
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -104,9 +104,9 @@ static ssize_t devzero_write(FAR struct file *filp, FAR const char *buffer, size
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds)
|
static int devzero_poll(FAR struct file *filp, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
if (fds)
|
if (setup)
|
||||||
{
|
{
|
||||||
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
fds->revents |= (fds->events & (POLLIN|POLLOUT));
|
||||||
if (fds->revents != 0)
|
if (fds->revents != 0)
|
||||||
|
|||||||
+13
-10
@@ -517,7 +517,7 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode = filep->f_inode;
|
FAR struct inode *inode = filep->f_inode;
|
||||||
FAR struct pipe_dev_s *dev = inode->i_private;
|
FAR struct pipe_dev_s *dev = inode->i_private;
|
||||||
@@ -539,7 +539,7 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++)
|
for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++)
|
||||||
{
|
{
|
||||||
/* Find the slot with the value equal to filep->f_priv. If there
|
/* Find the slot with the value equal to filep->f_priv. If there
|
||||||
* is not previously installed poll structure, then f_priv will
|
* is no previously installed poll structure, then f_priv will
|
||||||
* be NULL and we will find the first unused slot. If f_priv is
|
* be NULL and we will find the first unused slot. If f_priv is
|
||||||
* is non-NULL, then we will find the slot that was used for the
|
* is non-NULL, then we will find the slot that was used for the
|
||||||
* previous setup.
|
* previous setup.
|
||||||
@@ -547,14 +547,14 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
|
|
||||||
if (dev->d_fds[i] == filep->f_priv)
|
if (dev->d_fds[i] == filep->f_priv)
|
||||||
{
|
{
|
||||||
dev->d_fds[i] = fds;
|
dev->d_fds[i] = (setup ? fds : NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= CONFIG_DEV_PIPE_NPOLLWAITERS)
|
if (i >= CONFIG_DEV_PIPE_NPOLLWAITERS)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(fds == NULL);
|
DEBUGASSERT(setup);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,13 +562,16 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
* private data.
|
* private data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
filep->f_priv = fds;
|
filep->f_priv = NULL; /* Assume teardown */
|
||||||
|
if (setup)
|
||||||
/* Check if we should immediately notify on any of the requested events */
|
|
||||||
|
|
||||||
if (fds)
|
|
||||||
{
|
{
|
||||||
/* Determine how many bytes are in the buffer */
|
/* Set the poll event structure reference in the 'struct file' private data. */
|
||||||
|
|
||||||
|
filep->f_priv = fds;
|
||||||
|
|
||||||
|
/* Check if we should immediately notify on any of the requested events. First,
|
||||||
|
* Determine how many bytes are in the buffer
|
||||||
|
*/
|
||||||
|
|
||||||
if (dev->d_wrndx >= dev->d_rdndx)
|
if (dev->d_wrndx >= dev->d_rdndx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ EXTERN int pipecommon_close(FAR struct file *filep);
|
|||||||
EXTERN ssize_t pipecommon_read(FAR struct file *, FAR char *, size_t);
|
EXTERN ssize_t pipecommon_read(FAR struct file *, FAR char *, size_t);
|
||||||
EXTERN ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t);
|
EXTERN ssize_t pipecommon_write(FAR struct file *, FAR const char *, size_t);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
EXTERN int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds);
|
EXTERN int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
|
|||||||
+10
-11
@@ -79,7 +79,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
|
|||||||
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
|
||||||
static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds);
|
static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@@ -400,7 +400,7 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
FAR struct inode *inode = filep->f_inode;
|
FAR struct inode *inode = filep->f_inode;
|
||||||
FAR uart_dev_t *dev = inode->i_private;
|
FAR uart_dev_t *dev = inode->i_private;
|
||||||
@@ -422,7 +422,7 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++)
|
for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++)
|
||||||
{
|
{
|
||||||
/* Find the slot with the value equal to filep->f_priv. If there
|
/* Find the slot with the value equal to filep->f_priv. If there
|
||||||
* is not previously installed poll structure, then f_priv will
|
* is no previously installed poll structure, then f_priv will
|
||||||
* be NULL and we will find the first unused slot. If f_priv is
|
* be NULL and we will find the first unused slot. If f_priv is
|
||||||
* is non-NULL, then we will find the slot that was used for the
|
* is non-NULL, then we will find the slot that was used for the
|
||||||
* previous setup.
|
* previous setup.
|
||||||
@@ -430,14 +430,14 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
|
|
||||||
if (dev->fds[i] == filep->f_priv)
|
if (dev->fds[i] == filep->f_priv)
|
||||||
{
|
{
|
||||||
dev->fds[i] = fds;
|
dev->fds[i] = (setup ? fds : NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= CONFIG_DEV_CONSOLE_NPOLLWAITERS)
|
if (i >= CONFIG_DEV_CONSOLE_NPOLLWAITERS)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(fds == NULL);
|
DEBUGASSERT(setup);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,13 +445,12 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
|
|||||||
* private data.
|
* private data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
filep->f_priv = fds;
|
filep->f_priv = NULL; /* Assume teardown */
|
||||||
|
if (setup)
|
||||||
/* Check if we should immediately notify on any of the requested events */
|
|
||||||
|
|
||||||
if (fds)
|
|
||||||
{
|
{
|
||||||
/* Check if the xmit buffer is full. */
|
/* Check if we should immediately notify on any of the requested events.
|
||||||
|
* First, check if the xmit buffer is full.
|
||||||
|
*/
|
||||||
|
|
||||||
eventset = 0;
|
eventset = 0;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -93,7 +93,7 @@ static void poll_semtake(FAR sem_t *sem)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
static int poll_fdsetup(int fd, FAR struct pollfd *fds)
|
static int poll_fdsetup(int fd, FAR struct pollfd *fds, boolean setup)
|
||||||
{
|
{
|
||||||
FAR struct filelist *list;
|
FAR struct filelist *list;
|
||||||
FAR struct file *this_file;
|
FAR struct file *this_file;
|
||||||
@@ -137,7 +137,7 @@ static int poll_fdsetup(int fd, FAR struct pollfd *fds)
|
|||||||
{
|
{
|
||||||
/* Yes, then setup the poll */
|
/* Yes, then setup the poll */
|
||||||
|
|
||||||
ret = (int)inode->u.i_ops->poll(this_file, fds);
|
ret = (int)inode->u.i_ops->poll(this_file, fds, setup);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,7 @@ static inline int poll_setup(FAR struct pollfd *fds, nfds_t nfds, sem_t *sem)
|
|||||||
|
|
||||||
/* Set up the poll */
|
/* Set up the poll */
|
||||||
|
|
||||||
ret = poll_fdsetup(fds[i].fd, &fds[i]);
|
ret = poll_fdsetup(fds[i].fd, &fds[i], TRUE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
@@ -201,7 +201,7 @@ static inline int poll_teardown(FAR struct pollfd *fds, nfds_t nfds, int *count)
|
|||||||
{
|
{
|
||||||
/* Teardown the poll */
|
/* Teardown the poll */
|
||||||
|
|
||||||
status = poll_fdsetup(fds[i].fd, NULL);
|
status = poll_fdsetup(fds[i].fd, &fds[i], FALSE);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
ret = status;
|
ret = status;
|
||||||
|
|||||||
@@ -118,6 +118,7 @@
|
|||||||
|
|
||||||
struct uip_driver_s; /* Forward reference */
|
struct uip_driver_s; /* Forward reference */
|
||||||
struct uip_callback_s; /* Forward reference */
|
struct uip_callback_s; /* Forward reference */
|
||||||
|
|
||||||
struct uip_conn
|
struct uip_conn
|
||||||
{
|
{
|
||||||
dq_entry_t node; /* Implements a doubly linked list */
|
dq_entry_t node; /* Implements a doubly linked list */
|
||||||
@@ -179,13 +180,13 @@ struct uip_conn
|
|||||||
|
|
||||||
/* accept() is called when the TCP logic has created a connection */
|
/* accept() is called when the TCP logic has created a connection */
|
||||||
|
|
||||||
void *accept_private;
|
FAR void *accept_private;
|
||||||
int (*accept)(struct uip_conn *listener, struct uip_conn *conn);
|
int (*accept)(FAR struct uip_conn *listener, struct uip_conn *conn);
|
||||||
|
|
||||||
/* connection_event() is called on any of the subset of connection-related events */
|
/* connection_event() is called on any of the subset of connection-related events */
|
||||||
|
|
||||||
void *connection_private;
|
FAR void *connection_private;
|
||||||
void (*connection_event)(struct uip_conn *conn, uint16 flags);
|
void (*connection_event)(FAR struct uip_conn *conn, uint16 flags);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The following structure is used to handle read-ahead buffering for TCP
|
/* The following structure is used to handle read-ahead buffering for TCP
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@ struct file_operations
|
|||||||
off_t (*seek)(FAR struct file *filp, off_t offset, int whence);
|
off_t (*seek)(FAR struct file *filp, off_t offset, int whence);
|
||||||
int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
|
int (*ioctl)(FAR struct file *filp, int cmd, unsigned long arg);
|
||||||
#ifndef CONFIG_DISABLE_POLL
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
int (*poll)(FAR struct file *filp, struct pollfd *fds);
|
int (*poll)(FAR struct file *filp, struct pollfd *fds, boolean setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The two structures need not be common after this point */
|
/* The two structures need not be common after this point */
|
||||||
|
|||||||
+7
-7
@@ -84,17 +84,17 @@ typedef uint16 socktimeo_t;
|
|||||||
|
|
||||||
struct socket
|
struct socket
|
||||||
{
|
{
|
||||||
int s_crefs; /* Reference count on the socket */
|
int s_crefs; /* Reference count on the socket */
|
||||||
uint8 s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
|
uint8 s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
|
||||||
uint8 s_flags; /* See _SF_* definitions */
|
uint8 s_flags; /* See _SF_* definitions */
|
||||||
#ifdef CONFIG_NET_SOCKOPTS
|
#ifdef CONFIG_NET_SOCKOPTS
|
||||||
sockopt_t s_options; /* Selected socket options */
|
sockopt_t s_options; /* Selected socket options */
|
||||||
#ifndef CONFIG_DISABLE_CLOCK
|
#ifndef CONFIG_DISABLE_CLOCK
|
||||||
socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */
|
socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */
|
||||||
socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */
|
socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */
|
void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This defines a list of sockets indexed by the socket descriptor */
|
/* This defines a list of sockets indexed by the socket descriptor */
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ struct pollfd
|
|||||||
sem_t *sem; /* Pointer to semaphore used to post output event */
|
sem_t *sem; /* Pointer to semaphore used to post output event */
|
||||||
pollevent_t events; /* The input event flags */
|
pollevent_t events; /* The input event flags */
|
||||||
pollevent_t revents; /* The output event flags */
|
pollevent_t revents; /* The output event flags */
|
||||||
|
|
||||||
|
/* The socket poll logic needs a place to retain state info */
|
||||||
|
|
||||||
|
#if CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||||
|
FAR void *private;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net-internal.h
|
* net/net-internal.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* notice, this list of conditions and the following disclaimer in
|
* notice, this list of conditions and the following disclaimer in
|
||||||
* the documentation and/or other materials provided with the
|
* the documentation and/or other materials provided with the
|
||||||
* distribution.
|
* distribution.
|
||||||
* 3. Neither the name Gregory Nutt nor the names of its contributors may be
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
* used to endorse or promote products derived from this software
|
* used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
|||||||
+285
-9
@@ -49,7 +49,231 @@
|
|||||||
#include "net-internal.h"
|
#include "net-internal.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Global Functions
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Network polling can only be supported on TCP and only if read-ahead buffering
|
||||||
|
* is enabled (it could be supported on UDP as will if it also had read-ahead
|
||||||
|
* buffering.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
|
||||||
|
defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
|
||||||
|
# define HAVE_NETPOLL 1
|
||||||
|
#else
|
||||||
|
# undef HAVE_NETPOLL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct net_poll_s
|
||||||
|
{
|
||||||
|
FAR struct pollfd *fds; /* The descriptor poll info */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: poll_interrupt
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is called from the interrupt level to perform the actual
|
||||||
|
* TCP receive operation via by the uIP layer.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* dev The structure of the network driver that caused the interrupt
|
||||||
|
* conn The connection structure associated with the socket
|
||||||
|
* flags Set of events describing why the callback was invoked
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* Running at the interrupt level
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_NETPOLL
|
||||||
|
static uint16 poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
|
||||||
|
FAR void *pvprivate, uint16 flags)
|
||||||
|
{
|
||||||
|
struct pollfd *fds = (struct recvfrom_s *)pvprivate;
|
||||||
|
|
||||||
|
nvdbg("flags: %04x\n", flags);
|
||||||
|
|
||||||
|
/* 'private' might be null in some race conditions (?) */
|
||||||
|
|
||||||
|
if (fds)
|
||||||
|
{
|
||||||
|
pollevent_t eventset = 0;
|
||||||
|
|
||||||
|
/* Check for data availability events. */
|
||||||
|
|
||||||
|
if ((flags & UIP_NEWDATA) != 0)
|
||||||
|
{
|
||||||
|
eventset |= POLLIN & fds->events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A poll is a sign that we are free to send data. */
|
||||||
|
|
||||||
|
if ((flags & UIP_POLL) != 0)
|
||||||
|
{
|
||||||
|
eventset |= POLLOUT & fds->events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for a loss of connection events */
|
||||||
|
|
||||||
|
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
|
||||||
|
{
|
||||||
|
eventset |= (POLLERR|POLLHUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventset)
|
||||||
|
{
|
||||||
|
fds->revevents |= eventset;
|
||||||
|
sem_post(fds->sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_NETPOLL */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: net_pollsetup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup to monitor events on one TCP/IP socket
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* conn - The TCP/IP connection of interest
|
||||||
|
* fds - The structure describing the events to be monitored, OR NULL if
|
||||||
|
* this is a request to stop monitoring events.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0: Success; Negated errno on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_NETPOLL
|
||||||
|
static inline int net_pollsetup((FAR struct uip_conn *)conn, struct pollfd *fds)
|
||||||
|
{
|
||||||
|
FAR struct uip_callback_s *cb;
|
||||||
|
irqstate_t flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
if (!conn || !fds || fds->private)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some of the following must be atomic */
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
|
|
||||||
|
/* Allocate a TCP/IP callback structure */
|
||||||
|
|
||||||
|
cb = uip_tcpcallbackalloc(conn);
|
||||||
|
if (!cb)
|
||||||
|
{
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto errout_with_irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the callbcack structure */
|
||||||
|
|
||||||
|
cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||||
|
cb->private = (FAR void *)fds;
|
||||||
|
cb->event = poll_interrupt;
|
||||||
|
|
||||||
|
/* Save the nps reference in the poll structure for use at teardown as well */
|
||||||
|
|
||||||
|
fds->private = (FAR void *)cb;
|
||||||
|
|
||||||
|
/* Check for read data availability now */
|
||||||
|
|
||||||
|
if (!sq_empty(&conn->readahead))
|
||||||
|
{
|
||||||
|
fds->revents = fds->events & POLLIN;
|
||||||
|
if (fds->revents != 0)
|
||||||
|
{
|
||||||
|
/* If data is available now, the signal the poll logic */
|
||||||
|
|
||||||
|
sem_post(fds->sem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irqrestore(flags);
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
errout_with_irq:
|
||||||
|
irqrestore(flags);
|
||||||
|
free(nps);
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_NETPOLL */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Function: net_pollteardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Teardown monitoring of events on an TCP/IP socket
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* conn - The TCP/IP connection of interest
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* 0: Success; Negated errno on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_NETPOLL
|
||||||
|
static inline int net_pollteardown((FAR struct uip_conn *)conn, struct pollfd *fds)
|
||||||
|
{
|
||||||
|
FAR struct uip_callback_s *cb;
|
||||||
|
irqstate_t flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
if (!conn || !fds || !fds->private)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Recover the socket descriptor poll state info from the poll structure */
|
||||||
|
|
||||||
|
cb = (FAR struct uip_callback_s *)fds->private;
|
||||||
|
if (cb)
|
||||||
|
{
|
||||||
|
/* Release the callback */
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
|
uip_tcpcallbackfree(conn, cb);
|
||||||
|
irqrestore(flags);
|
||||||
|
|
||||||
|
/* Release the poll/select data slot */
|
||||||
|
|
||||||
|
fds->private = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_NETPOLL */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -59,22 +283,74 @@
|
|||||||
* The standard poll() operation redirects operations on socket descriptors
|
* The standard poll() operation redirects operations on socket descriptors
|
||||||
* to this function.
|
* to this function.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Input Parameters:
|
||||||
* fd - The socket descriptor of interest
|
* fd - The socket descriptor of interest
|
||||||
* fds - The structures describing events to be monitored, OR NULL if
|
* fds - The structure describing the events to be monitored, OR NULL if
|
||||||
* this is a request to stop monitoring events.
|
* this is a request to stop monitoring events.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* TBD
|
* 0: Success; Negated errno on failure
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
int net_poll(int sockfd, struct pollfd *fds)
|
int net_poll(int sockfd, struct pollfd *fds)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CPP_HAVE_WARNING
|
#ifndef HAVE_NETPOLL
|
||||||
# warning To be provided
|
|
||||||
#endif
|
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
#else
|
||||||
|
FAR struct socket *psock;
|
||||||
|
int ret;
|
||||||
|
|
||||||
#endif /* CONFIG_NET&& !CONFIG_DISABLE_POLL */
|
/* Verify that non-NULL pointers were passed */
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
if (!fds)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get the underlying socket structure and verify that the sockfd
|
||||||
|
* corresponds to valid, allocated socket
|
||||||
|
*/
|
||||||
|
|
||||||
|
psock = sockfd_socket(sockfd);
|
||||||
|
if (!psock || psock->s_crefs <= 0)
|
||||||
|
{
|
||||||
|
ret = -EBADF;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_UDP
|
||||||
|
/* poll() not supported for UDP */
|
||||||
|
|
||||||
|
if (psock->s_type != SOCK_STREAM)
|
||||||
|
{
|
||||||
|
ret = -ENOSYS;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check if we are setting up or tearing down the poll */
|
||||||
|
if (fds)
|
||||||
|
{
|
||||||
|
/* Perform the TCP/IP poll() setup */
|
||||||
|
|
||||||
|
ret = net_pollsetup((FAR struct uip_conn *)psock->conn, fds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Perform the TCP/IP poll() teardown */
|
||||||
|
|
||||||
|
ret = net_pollteardown((FAR struct uip_conn *)psock->conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return ret;
|
||||||
|
#endif /* HAVE_NETPOLL */
|
||||||
|
}
|
||||||
|
#endif /* !CONFIG_DISABLE_POLL */
|
||||||
|
|
||||||
|
#endif /* CONFIG_NET && !CONFIG_DISABLE_POLL */
|
||||||
|
|||||||
Reference in New Issue
Block a user