summaryrefslogtreecommitdiff
path: root/nuttx/net/local
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-29 07:47:09 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-29 07:47:09 -0600
commit49beb2cc412461f1893e91bc76f91fdb6e3fc8cc (patch)
tree7b15166b1783c966eef69f99dfb11393e43df687 /nuttx/net/local
parent08fc909b93fed9f0d209ce122d8fc6092963d9d7 (diff)
downloadpx4-nuttx-49beb2cc412461f1893e91bc76f91fdb6e3fc8cc.tar.gz
px4-nuttx-49beb2cc412461f1893e91bc76f91fdb6e3fc8cc.tar.bz2
px4-nuttx-49beb2cc412461f1893e91bc76f91fdb6e3fc8cc.zip
Unix domain: Add initial cut at redvfrom() for Unix domain datagram sockets
Diffstat (limited to 'nuttx/net/local')
-rw-r--r--nuttx/net/local/local.h48
-rw-r--r--nuttx/net/local/local_fifo.c157
-rw-r--r--nuttx/net/local/local_recvfrom.c251
3 files changed, 383 insertions, 73 deletions
diff --git a/nuttx/net/local/local.h b/nuttx/net/local/local.h
index 668bca66b..7c0cf44a2 100644
--- a/nuttx/net/local/local.h
+++ b/nuttx/net/local/local.h
@@ -488,21 +488,41 @@ int local_sync(int fd);
* Name: local_create_fifos
*
* Description:
- * Create the FIFO pair needed for a connection.
+ * Create the FIFO pair needed for a SOCK_STREAM connection.
*
****************************************************************************/
-int local_create_fifos(FAR struct local_conn_s *client);
+int local_create_fifos(FAR struct local_conn_s *conn);
+
+/****************************************************************************
+ * Name: local_create_halfduplex
+ *
+ * Description:
+ * Create the half-duplex FIFO needed for SOCK_DGRAM communication.
+ *
+ ****************************************************************************/
+
+int local_create_halfduplex(FAR struct local_conn_s *conn);
/****************************************************************************
* Name: local_destroy_fifos
*
* Description:
- * Destroy the FIFO pair used for a connection.
+ * Destroy the FIFO pair used for a SOCK_STREAM connection.
+ *
+ ****************************************************************************/
+
+int local_destroy_fifos(FAR struct local_conn_s *conn);
+
+/****************************************************************************
+ * Name: local_destroy_halfduplex
+ *
+ * Description:
+ * Destroy the FIFO used for SOCK_DGRAM communication
*
****************************************************************************/
-int local_destroy_fifos(FAR struct local_conn_s *client);
+int local_destroy_halfduplex(FAR struct local_conn_s *conn);
/****************************************************************************
* Name: local_open_client_rx
@@ -544,6 +564,26 @@ int local_open_server_rx(FAR struct local_conn_s *server);
int local_open_server_tx(FAR struct local_conn_s *server);
+/****************************************************************************
+ * Name: local_open_receiver
+ *
+ * Description:
+ * Only the receiving side of the half duplex FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_receiver(FAR struct local_conn_s *conn);
+
+/****************************************************************************
+ * Name: local_open_sender
+ *
+ * Description:
+ * Only the sending side of the half duplex FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_sender(FAR struct local_conn_s *conn);
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/nuttx/net/local/local_fifo.c b/nuttx/net/local/local_fifo.c
index ee5cb1072..0817f33bc 100644
--- a/nuttx/net/local/local_fifo.c
+++ b/nuttx/net/local/local_fifo.c
@@ -55,8 +55,9 @@
* Private Functions
****************************************************************************/
-#define LOCAL_RX_SUFFIX "RX"
-#define LOCAL_TX_SUFFIX "TX"
+#define LOCAL_CS_SUFFIX "CS" /* Name of the client-to-server FIFO */
+#define LOCAL_SC_SUFFIX "SC" /* Name of the server-to-client FIFO */
+#define LOCAL_HD_SUFFIX "HD" /* Name of the half duplex datagram FIFO */
#define LOCAL_SUFFIX_LEN 2
#define LOCAL_FULLPATH_LEN (UNIX_PATH_MAX + LOCAL_SUFFIX_LEN)
@@ -66,33 +67,49 @@
****************************************************************************/
/****************************************************************************
- * Name: local_rx_name
+ * Name: local_cs_name
*
* Description:
- * Create the name of the RX (client-to-server) FIFO name.
+ * Create the name of the client-to-server FIFO.
*
****************************************************************************/
-static inline void local_rx_name(FAR struct local_conn_s *conn,
+static inline void local_cs_name(FAR struct local_conn_s *conn,
FAR char *path)
{
- (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_RX_SUFFIX,
+ (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_CS_SUFFIX,
conn->lc_path);
path[LOCAL_FULLPATH_LEN-1] = '\0';
}
/****************************************************************************
- * Name: local_tx_name
+ * Name: local_sc_name
*
* Description:
- * Create the name of the TX (server-to-client) FIFO name.
+ * Create the name of the server-to-client FIFO.
*
****************************************************************************/
-static inline void local_tx_name(FAR struct local_conn_s *conn,
+static inline void local_sc_name(FAR struct local_conn_s *conn,
FAR char *path)
{
- (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_TX_SUFFIX,
+ (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_SC_SUFFIX,
+ conn->lc_path);
+ path[LOCAL_FULLPATH_LEN-1] = '\0';
+}
+
+/****************************************************************************
+ * Name: local_hd_name
+ *
+ * Description:
+ * Create the name of the half duplex, datagram FIFO.
+ *
+ ****************************************************************************/
+
+static inline void local_hd_name(FAR struct local_conn_s *conn,
+ FAR char *path)
+{
+ (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_HD_SUFFIX,
conn->lc_path);
path[LOCAL_FULLPATH_LEN-1] = '\0';
}
@@ -130,7 +147,7 @@ static bool local_fifo_exists(FAR const char *path)
* Name: local_create_fifo
*
* Description:
- * Create the one of FIFOs needed for a connection.
+ * Create the one FIFO.
*
****************************************************************************/
@@ -172,7 +189,12 @@ static int local_destroy_fifo(FAR const char *path)
{
int ret;
- /* Unlink the client-to-server FIFO if it exists. */
+ /* Unlink the client-to-server FIFO if it exists.
+ * REVISIT: This is wrong! Un-linking the FIFO does not eliminate it.
+ * it only removes it from the namespace. A new interface will be required
+ * to remove the FIFO and all of its resources.
+ */
+#warning Missing logic
if (local_fifo_exists(path))
{
@@ -268,24 +290,24 @@ static inline int local_tx_open(FAR struct local_conn_s *conn,
* Name: local_create_fifos
*
* Description:
- * Create the FIFO pair needed for a connection.
+ * Create the FIFO pair needed for a SOCK_STREAM connection.
*
****************************************************************************/
-int local_create_fifos(FAR struct local_conn_s *client)
+int local_create_fifos(FAR struct local_conn_s *conn)
{
char path[LOCAL_FULLPATH_LEN];
int ret;
/* Create the client-to-server FIFO if it does not already exist. */
- local_tx_name(client, path);
+ local_cs_name(conn, path);
ret = local_create_fifo(path);
if (ret >= 0)
{
/* Create the server-to-client FIFO if it does not already exist. */
- local_rx_name(client, path);
+ local_sc_name(conn, path);
ret = local_create_fifo(path);
}
@@ -293,14 +315,32 @@ int local_create_fifos(FAR struct local_conn_s *client)
}
/****************************************************************************
+ * Name: local_create_halfduplex
+ *
+ * Description:
+ * Create the half-duplex FIFO needed for SOCK_DGRAM communication.
+ *
+ ****************************************************************************/
+
+int local_create_halfduplex(FAR struct local_conn_s *conn)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Create the half duplex FIFO if it does not already exist. */
+
+ local_hd_name(conn, path);
+ return local_create_fifo(path);
+}
+
+/****************************************************************************
* Name: local_destroy_fifos
*
* Description:
- * Destroy the FIFO pair used for a connection.
+ * Destroy the FIFO pair used for a SOCK_STREAM connection.
*
****************************************************************************/
-int local_destroy_fifos(FAR struct local_conn_s *client)
+int local_destroy_fifos(FAR struct local_conn_s *conn)
{
char path[LOCAL_FULLPATH_LEN];
int ret1;
@@ -308,12 +348,12 @@ int local_destroy_fifos(FAR struct local_conn_s *client)
/* Destroy the client-to-server FIFO if it exists. */
- local_tx_name(client, path);
+ local_sc_name(conn, path);
ret1 = local_destroy_fifo(path);
/* Destroy the server-to-client FIFO if it exists. */
- local_rx_name(client, path);
+ local_cs_name(conn, path);
ret2 = local_create_fifo(path);
/* Return a failure if one occurred. */
@@ -322,10 +362,28 @@ int local_destroy_fifos(FAR struct local_conn_s *client)
}
/****************************************************************************
+ * Name: local_destroy_halfduplex
+ *
+ * Description:
+ * Destroy the FIFO used for SOCK_DGRAM communication
+ *
+ ****************************************************************************/
+
+int local_destroy_halfduplex(FAR struct local_conn_s *conn)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Destroy the half duplex FIFO if it exists. */
+
+ local_hd_name(conn, path);
+ return local_destroy_fifo(path);
+}
+
+/****************************************************************************
* Name: local_open_client_rx
*
* Description:
- * Only the client-side Rx FIFO.
+ * Open the client-side of the server-to-client FIFO.
*
****************************************************************************/
@@ -335,7 +393,7 @@ int local_open_client_rx(FAR struct local_conn_s *client)
/* Get the server-to-client path name */
- local_tx_name(client, path);
+ local_sc_name(client, path);
/* Then open the file for read-only access */
@@ -346,7 +404,7 @@ int local_open_client_rx(FAR struct local_conn_s *client)
* Name: local_open_client_tx
*
* Description:
- * Only the client-side Tx FIFO.
+ * Open the client-side of the client-to-server FIFO.
*
****************************************************************************/
@@ -356,7 +414,7 @@ int local_open_client_tx(FAR struct local_conn_s *client)
/* Get the client-to-server path name */
- local_rx_name(client, path);
+ local_cs_name(client, path);
/* Then open the file for write-only access */
@@ -367,7 +425,7 @@ int local_open_client_tx(FAR struct local_conn_s *client)
* Name: local_open_server_rx
*
* Description:
- * Only the server-side Rx FIFO.
+ * Open the server-side of the client-to-server FIFO.
*
****************************************************************************/
@@ -377,7 +435,7 @@ int local_open_server_rx(FAR struct local_conn_s *server)
/* Get the client-to-server path name */
- local_rx_name(server, path);
+ local_cs_name(server, path);
/* Then open the file for write-only access */
@@ -388,7 +446,7 @@ int local_open_server_rx(FAR struct local_conn_s *server)
* Name: local_open_server_tx
*
* Description:
- * Only the server-side Tx FIFO.
+ * Only the server-side of the server-to-client FIFO.
*
****************************************************************************/
@@ -398,10 +456,53 @@ int local_open_server_tx(FAR struct local_conn_s *server)
/* Get the server-to-client path name */
- local_tx_name(server, path);
+ local_sc_name(server, path);
/* Then open the file for read-only access */
return local_tx_open(server, path);
}
+
+/****************************************************************************
+ * Name: local_open_receiver
+ *
+ * Description:
+ * Only the receiving side of the half duplex FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_receiver(FAR struct local_conn_s *conn)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the server-to-client path name */
+
+ local_hd_name(conn, path);
+
+ /* Then open the file for read-only access */
+
+ return local_rx_open(conn, path);
+}
+
+/****************************************************************************
+ * Name: local_open_sender
+ *
+ * Description:
+ * Only the sending side of the half duplex FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_sender(FAR struct local_conn_s *conn)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the server-to-client path name */
+
+ local_hd_name(conn, path);
+
+ /* Then open the file for read-only access */
+
+ return local_tx_open(conn, path);
+}
+
#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_recvfrom.c b/nuttx/net/local/local_recvfrom.c
index 7ce5bb0da..731b5cc99 100644
--- a/nuttx/net/local/local_recvfrom.c
+++ b/nuttx/net/local/local_recvfrom.c
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
@@ -60,13 +61,14 @@
#endif
/****************************************************************************
- * Public Functions
+ * Private Functions
****************************************************************************/
+
/****************************************************************************
* Name: psock_fifo_read
*
* Description:
- * A thin layer aroudn local_fifo_read that handles socket-related loss-of-
+ * A thin layer around local_fifo_read that handles socket-related loss-of-
* connection events.
*
****************************************************************************/
@@ -118,22 +120,12 @@ static int psock_fifo_read(FAR struct socket *psock, FAR void *buf,
}
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: psock_recvfrom
+ * Function: psock_stream_recvfrom
*
* Description:
- * recvfrom() receives messages from a local socket, and may be used to
- * receive data on a socket whether or not it is connection-oriented.
- *
- * If from is not NULL, and the underlying protocol provides the source
- * address, this source address is filled in. The argument fromlen
- * initialized to the size of the buffer associated with from, and modified
- * on return to indicate the actual size of the address stored there.
+ * psock_stream_recvfrom() receives messages from a local stream socket.
*
- * Parameters:
+ * Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
@@ -142,35 +134,34 @@ static int psock_fifo_read(FAR struct socket *psock, FAR void *buf,
* fromlen The length of the address structure
*
* Returned Value:
- * On success, returns the number of characters sent. If no data is
+ * On success, returns the number of characters received. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on errors, -1 is returned, and errno
* is set appropriately (see receive from for the complete list).
*
****************************************************************************/
-ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
- size_t len, int flags, FAR struct sockaddr *from,
- FAR socklen_t *fromlen)
+static inline ssize_t
+psock_stream_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
{
- FAR struct local_conn_s *conn;
+ FAR struct local_conn_s *conn = (FAR struct local_conn_s *)psock->s_conn;
size_t readlen;
int ret;
- DEBUGASSERT(psock && psock->s_conn && buf);
- conn = (FAR struct local_conn_s *)psock->s_conn;
-
- /* Verify that this is a connected peer socket and that it has opened the
- * incoming FIFO for read-only access.
- */
+ /* Verify that this is a connected peer socket */
- if (conn->lc_state != LOCAL_STATE_CONNECTED ||
- conn->lc_infd < 0)
+ if (conn->lc_state != LOCAL_STATE_CONNECTED)
{
ndbg("ERROR: not connected\n");
return -ENOTCONN;
}
+ /* The incoming FIFO should be open */
+
+ DEBUGASSERT(conn->lc_infd >= 0);
+
/* Are there still bytes in the FIFO from the last packet? */
if (conn->u.peer.lc_remaining == 0)
@@ -185,7 +176,7 @@ ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
ndbg("ERROR: Failed to get packet length: %d\n", ret);
return ret;
}
- else if (ret > 0xffff)
+ else if (ret > UINT16_MAX)
{
ndbg("ERROR: Packet is too big: %d\n", ret);
return -E2BIG;
@@ -195,7 +186,6 @@ ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
}
/* Read the packet */
- /* REVISIT: Does this make sense if the socket is SOCK_DGRAM? */
readlen = MIN(conn->u.peer.lc_remaining, len);
ret = psock_fifo_read(psock, buf, &readlen);
@@ -209,36 +199,154 @@ ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
DEBUGASSERT(readlen <= conn->u.peer.lc_remaining);
conn->u.peer.lc_remaining -= readlen;
- /* If this is a SOCK_STREAM socket and there are unread bytes remaining
- * in the packet, we will get those bytes the next time recv is called.
- * What if this is a SOCK_DRAM? REVISIT: Here we flush the remainder of
- * the packet to the bit bucket.
+ /* Return the address family */
+
+ if (from)
+ {
+ ret = local_getaddr(conn, from, fromlen);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+
+ return readlen;
+}
+
+/****************************************************************************
+ * Function: psock_dgram_recvfrom
+ *
+ * Description:
+ * psock_dgram_recvfrom() receives messages from a local datagram socket.
+ *
+ * Input Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters received. Otherwise, on
+ * errors, -1 is returned, and errno is set appropriately (see receive
+ * from for the complete list).
+ *
+ ****************************************************************************/
+
+static inline ssize_t
+psock_dgram_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
+{
+ FAR struct local_conn_s *conn = (FAR struct local_conn_s *)psock->s_conn;
+ uint16_t pktlen;
+ size_t readlen;
+ 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 */
+
+ if (conn->lc_state != LOCAL_STATE_BOUND)
+ {
+ /* Either not bound to address or it is connected */
+
+ ndbg("ERROR: Connected or not bound\n");
+ return -EISCONN;
+ }
+
+ /* The incoming FIFO should not be open */
+
+ DEBUGASSERT(conn->lc_infd < 0);
+
+ /* Make sure that half duplex FIFO has been created */
+
+ ret = local_create_halfduplex(conn);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to create FIFO for %s: %d\n",
+ conn->lc_path, ret);
+ return ret;
+ }
+
+ /* Open the receiving side of the transfer */
+
+ ret = local_open_receiver(conn);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to open FIFO for %s: %d\n",
+ conn->lc_path, ret);
+ return ret;
+ }
+
+ /* Sync to the start of the next packet in the stream and get the size of
+ * the next packet.
*/
- if (psock->s_type == SOCK_DGRAM && conn->u.peer.lc_remaining > 0)
+ ret = local_sync(conn->lc_infd);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to get packet length: %d\n", ret);
+ goto errout_with_infd;
+ }
+ else if (ret > UINT16_MAX)
+ {
+ ndbg("ERROR: Packet is too big: %d\n", ret);
+ goto errout_with_infd;
+ }
+
+ pktlen = ret;
+
+ /* Read the packet */
+
+ readlen = MIN(pktlen, len);
+ ret = psock_fifo_read(psock, buf, &readlen);
+ if (ret < 0)
+ {
+ goto errout_with_infd;
+ }
+
+ /* If there are unread bytes remaining in the packet, flush the remainder
+ * of the packet to the bit bucket.
+ */
+
+ DEBUGASSERT(readlen <= pktlen);
+ if (readlen < pktlen)
{
uint8_t bitbucket[32];
+ uint16_t remaining;
size_t tmplen;
+ remaining = pktlen - readlen;
do
{
/* Read 32 bytes into the bit bucket */
- tmplen = MIN(conn->u.peer.lc_remaining, 32);
- ret = psock_fifo_read(psock, bitbucket, &tmplen);
+ readlen = MIN(remaining, 32);
+ ret = psock_fifo_read(psock, bitbucket, &tmplen);
if (ret < 0)
{
- return ret;
+ goto errout_with_infd;
}
/* Adjust the number of bytes remaining to be read from the packet */
- DEBUGASSERT(tmplen <= conn->u.peer.lc_remaining);
- conn->u.peer.lc_remaining -= tmplen;
+ DEBUGASSERT(tmplen <= remain);
+ remaining -= tmplen;
}
- while (conn->u.peer.lc_remaining > 0);
+ while (remaining > 0);
}
+ /* Now we can close the read-only socket descriptor */
+
+ close(conn->lc_infd);
+ conn->lc_infd = -1;
+
/* Return the address family */
if (from)
@@ -251,6 +359,67 @@ ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
}
return readlen;
+
+errout_with_infd:
+ close(conn->lc_infd);
+ conn->lc_infd = -1;
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: psock_local_recvfrom
+ *
+ * Description:
+ * psock_local_recvfrom() receives messages from a local socket and may be
+ * used to receive data on a socket whether or not it is connection-oriented.
+ *
+ * If from is not NULL, and the underlying protocol provides the source
+ * address, this source address is filled in. The argument fromlen
+ * initialized to the size of the buffer associated with from, and modified
+ * on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters received. If no data is
+ * available to be received and the peer has performed an orderly shutdown,
+ * recv() will return 0. Otherwise, on errors, -1 is returned, and errno
+ * is set appropriately (see receive from for the complete list).
+ *
+ ****************************************************************************/
+
+ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
+{
+ DEBUGASSERT(psock && psock->s_conn && buf);
+
+ /* Check for a stream socket */
+
+ if (psock->s_type == SOCK_STREAM)
+ {
+ return psock_stream_recvfrom(psock, buf, len, flags, from, fromlen);
+ }
+ else if (psock->s_type == SOCK_DGRAM)
+ {
+ return psock_dgram_recvfrom(psock, buf, len, flags, from, fromlen);
+ }
+ else
+ {
+ DEBUGPANIC();
+ ndbg("ERROR: Unrecognized socket type: %s\n", psock->s_type);
+ return -EINVAL;
+ }
}
#endif /* CONFIG_NET && CONFIG_NET_LOCAL */