Unix domain: Add initial cut at redvfrom() for Unix domain datagram sockets
This commit is contained in:
parent
1c8ddae655
commit
ffb16f658f
@ -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 *client);
|
||||
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_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
|
||||
}
|
||||
|
@ -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_destroy_fifos
|
||||
* Name: local_create_halfduplex
|
||||
*
|
||||
* Description:
|
||||
* Destroy the FIFO pair used for a connection.
|
||||
* Create the half-duplex FIFO needed for SOCK_DGRAM communication.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int local_destroy_fifos(FAR struct local_conn_s *client)
|
||||
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 SOCK_STREAM connection.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
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. */
|
||||
@ -321,11 +361,29 @@ int local_destroy_fifos(FAR struct local_conn_s *client)
|
||||
return ret1 < 0 ? ret1 : ret2;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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 */
|
||||
|
@ -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.
|
||||
* psock_stream_recvfrom() receives messages from a local stream socket.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 */
|
||||
|
||||
/* Verify that this is a connected peer socket and that it has opened the
|
||||
* incoming FIFO for read-only access.
|
||||
*/
|
||||
|
||||
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,6 @@ 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.
|
||||
*/
|
||||
|
||||
if (psock->s_type == SOCK_DGRAM && conn->u.peer.lc_remaining > 0)
|
||||
{
|
||||
uint8_t bitbucket[32];
|
||||
size_t tmplen;
|
||||
|
||||
do
|
||||
{
|
||||
/* Read 32 bytes into the bit bucket */
|
||||
|
||||
tmplen = MIN(conn->u.peer.lc_remaining, 32);
|
||||
ret = psock_fifo_read(psock, bitbucket, &tmplen);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
while (conn->u.peer.lc_remaining > 0);
|
||||
}
|
||||
|
||||
/* Return the address family */
|
||||
|
||||
if (from)
|
||||
@ -253,4 +213,213 @@ ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
|
||||
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.
|
||||
*/
|
||||
|
||||
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 */
|
||||
|
||||
readlen = MIN(remaining, 32);
|
||||
ret = psock_fifo_read(psock, bitbucket, &tmplen);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_infd;
|
||||
}
|
||||
|
||||
/* Adjust the number of bytes remaining to be read from the packet */
|
||||
|
||||
DEBUGASSERT(tmplen <= remain);
|
||||
remaining -= tmplen;
|
||||
}
|
||||
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)
|
||||
{
|
||||
ret = local_getaddr(conn, from, fromlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user