Add user-space networking stack API (usrsock)

User-space networking stack API allows user-space daemon to
provide TCP/IP stack implementation for NuttX network.

Main use for this is to allow use and seamless integration of
HW-provided TCP/IP stacks to NuttX.

For example, user-space daemon can translate /dev/usrsock
API requests to HW TCP/IP API requests while rest of the
user-space can access standard socket API, with socket
descriptors that can be used with NuttX system calls.
This commit is contained in:
Jussi Kivilinna
2017-03-31 08:58:14 -06:00
committed by Gregory Nutt
parent c999519bf2
commit cd3c9634c8
51 changed files with 6283 additions and 124 deletions
+13 -1
View File
@@ -97,7 +97,7 @@
*
* - Maximum Transfer Unit (MTU)
* - TCP Receive Window size (See TCP configuration options below)
*
*
* A better solution would be to support device-by-device MTU and receive
* window sizes. This minimum support is require to support the optimal
* SLIP MTU of 296 bytes and the standard Ethernet MTU of 1500
@@ -547,6 +547,18 @@
# define CONFIG_NET_ARP_MAXAGE 120
#endif
/* Usrsock configuration options */
/* The maximum amount of concurrent usrsock connections, Default: 6 */
#ifndef CONFIG_NET_USRSOCK_CONNS
# ifdef CONFIG_NET_USRSOCK
# define CONFIG_NET_USRSOCK_CONNS 6
# else
# define CONFIG_NET_USRSOCK_CONNS 0
# endif
#endif
/* General configuration options */
/* Delay after receive to catch a following packet. No delay should be
+233
View File
@@ -0,0 +1,233 @@
/****************************************************************************
* include/nuttx/net/usrsock.h
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_NET_USRSOCK_H
#define __INCLUDE_NUTTX_NET_USRSOCK_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/compiler.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Event message flags */
#define USRSOCK_EVENT_ABORT (1 << 0)
#define USRSOCK_EVENT_SENDTO_READY (1 << 1)
#define USRSOCK_EVENT_RECVFROM_AVAIL (1 << 2)
#define USRSOCK_EVENT_REMOTE_CLOSED (1 << 3)
/* Response message flags */
#define USRSOCK_MESSAGE_FLAG_REQ_IN_PROGRESS (1 << 0)
#define USRSOCK_MESSAGE_FLAG_EVENT (1 << 1)
#define USRSOCK_MESSAGE_IS_EVENT(flags) \
(!!((flags) & USRSOCK_MESSAGE_FLAG_EVENT))
#define USRSOCK_MESSAGE_IS_REQ_RESPONSE(flags) \
(!USRSOCK_MESSAGE_IS_EVENT(flags))
#define USRSOCK_MESSAGE_REQ_IN_PROGRESS(flags) \
(!!((flags) & USRSOCK_MESSAGE_FLAG_REQ_IN_PROGRESS))
#define USRSOCK_MESSAGE_REQ_COMPLETED(flags) \
(!USRSOCK_MESSAGE_REQ_IN_PROGRESS(flags))
/****************************************************************************
* Public Types
****************************************************************************/
/* Request types */
enum usrsock_request_types_e
{
USRSOCK_REQUEST_SOCKET = 0,
USRSOCK_REQUEST_CLOSE,
USRSOCK_REQUEST_CONNECT,
USRSOCK_REQUEST_SENDTO,
USRSOCK_REQUEST_RECVFROM,
USRSOCK_REQUEST_SETSOCKOPT,
USRSOCK_REQUEST_GETSOCKOPT,
USRSOCK_REQUEST_GETSOCKNAME,
USRSOCK_REQUEST_BIND,
USRSOCK_REQUEST__MAX
};
/* Response/event message types */
enum usrsock_message_types_e
{
USRSOCK_MESSAGE_RESPONSE_ACK = 0,
USRSOCK_MESSAGE_RESPONSE_DATA_ACK,
USRSOCK_MESSAGE_SOCKET_EVENT,
};
/* Request structures (kernel => /dev/usrsock => daemon) */
begin_packed_struct struct usrsock_request_common_s
{
int8_t reqid;
uint8_t xid;
} end_packed_struct;
begin_packed_struct struct usrsock_request_socket_s
{
struct usrsock_request_common_s head;
int16_t domain;
int16_t type;
int16_t protocol;
} end_packed_struct;
begin_packed_struct struct usrsock_request_close_s
{
struct usrsock_request_common_s head;
int16_t usockid;
} end_packed_struct;
begin_packed_struct struct usrsock_request_bind_s
{
struct usrsock_request_common_s head;
int16_t usockid;
uint16_t addrlen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_connect_s
{
struct usrsock_request_common_s head;
int16_t usockid;
uint16_t addrlen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_sendto_s
{
struct usrsock_request_common_s head;
int16_t usockid;
uint16_t addrlen;
uint16_t buflen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_recvfrom_s
{
struct usrsock_request_common_s head;
int16_t usockid;
uint16_t max_buflen;
uint16_t max_addrlen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_setsockopt_s
{
struct usrsock_request_common_s head;
int16_t usockid;
int16_t level;
int16_t option;
uint16_t valuelen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_getsockopt_s
{
struct usrsock_request_common_s head;
int16_t usockid;
int16_t level;
int16_t option;
uint16_t max_valuelen;
} end_packed_struct;
begin_packed_struct struct usrsock_request_getsockname_s
{
struct usrsock_request_common_s head;
int16_t usockid;
uint16_t max_addrlen;
} end_packed_struct;
/* Response/event message structures (kernel <= /dev/usrsock <= daemon) */
begin_packed_struct struct usrsock_message_common_s
{
int8_t msgid;
int8_t flags;
} end_packed_struct;
/* Request acknowledgment/completion message */
begin_packed_struct struct usrsock_message_req_ack_s
{
struct usrsock_message_common_s head;
uint8_t xid;
int32_t result;
} end_packed_struct;
/* Request acknowledgment/completion message */
begin_packed_struct struct usrsock_message_datareq_ack_s
{
struct usrsock_message_req_ack_s reqack;
/* head.result => positive buflen, negative error-code. */
uint16_t valuelen; /* length of value returned after buffer */
uint16_t valuelen_nontrunc; /* actual non-truncated length of value at
* daemon-sïde. */
} end_packed_struct;
/* Socket event message */
begin_packed_struct struct usrsock_message_socket_event_s
{
struct usrsock_message_common_s head;
int16_t usockid;
uint16_t events;
} end_packed_struct;
#endif /* __INCLUDE_NUTTX_NET_USRSOCK_H */
+18
View File
@@ -236,6 +236,23 @@ config TUN_LPWORK
endchoice # Work queue
endif # NET_TUN
config NET_USRSOCK
bool "User-space networking stack API"
default n
---help---
Enable or disable user-space networking stack support.
User-space networking stack API allows user-space daemon to
provide TCP/IP stack implementation for NuttX network.
Main use for this is to allow use and integration of
HW-provided TCP/IP stacks for NuttX.
For example, user-space daemon can translate /dev/usrsock API
requests to HW TCP/IP API requests while rest of the user-space
can access standard socket API, with socket descriptors that
can be used with NuttX system calls.
endmenu # Data link support
source "net/netdev/Kconfig"
@@ -271,6 +288,7 @@ source "net/arp/Kconfig"
source "net/loopback/Kconfig"
source "net/iob/Kconfig"
source "net/procfs/Kconfig"
source "net/usrsock/Kconfig"
source "net/utils/Kconfig"
config NET_STATISTICS
+1
View File
@@ -72,6 +72,7 @@ include devif/Make.defs
include loopback/Make.defs
include route/Make.defs
include procfs/Make.defs
include usrsock/Make.defs
include utils/Make.defs
endif
+19 -15
View File
@@ -22,21 +22,25 @@ Directory Structure
+- route - Routing table support
+- tcp - Transmission Control Protocol
+- udp - User Datagram Protocol
+- usrsock - User socket API for user-space networking stack
`- utils - Miscellaneous utility functions
+----------------------------------------------------------------+
| Application layer |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
| Socket layer (socket/) |
+----------------------------------------------------------------+
+------------++--------------------------------------------------+
| Network || Protocol stacks (arp, ipv6, icmp, pkt, tcp, udp) |
| Device |+--------------------------------------------------+
| Interface |+------------------------------------++------------+
| (netdev/) || Network Device Interface (devif/) || Utilities |
+------------++------------------------------------++------------+
+----------------------------------------------------------------+
| Network Device Drivers |
+----------------------------------------------------------------+
+-------------------------------------------------------------------++------------------------+
| Application layer || usrsock daemon |
+-------------------------------------------------------------------++------------------------+
+-------------------------------------------------------------------++----------------+ +-----+
| Socket layer (socket/) || /dev/usrsock | | |
+-------------------------------------------------------------------++----------------+ | |
+------------++--------------------------------------------------++-------------------+ | |
| Network || Protocol stacks (arp, ipv6, icmp, pkt, tcp, udp) || usrsock/ | | |
| Device |+--------------------------------------------------++-------------------+ | |
| Interface |+------------------------------------++---------------------------------+ | |
| (netdev/) || Network Device Interface (devif/) || Utilities | | |
+------------++------------------------------------++---------------------------------+ | |
+----------------------------------------------------------------+ | |
| Network Device Drivers | | HAL |
+----------------------------------------------------------------+ +-----+
+----------------------------------------------------------------+ +--------------------------+
| Networking Hardware | | Hardware TCP/IP Stack |
+----------------------------------------------------------------+ +--------------------------+
+7 -2
View File
@@ -234,12 +234,17 @@
*/
struct net_driver_s; /* Forward reference */
typedef CODE uint16_t (*devif_callback_event_t)(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv,
uint16_t flags);
struct devif_callback_s
{
FAR struct devif_callback_s *nxtconn;
FAR struct devif_callback_s *nxtdev;
uint16_t (*event)(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags);
FAR devif_callback_event_t event;
FAR void *priv;
uint16_t flags;
};
+7 -7
View File
@@ -186,7 +186,7 @@ static inline int devif_poll_igmp(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
devif_poll_callback_t callback)
{
@@ -208,7 +208,7 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
return bstop;
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: devif_poll_tcp_connections
@@ -222,7 +222,7 @@ static int devif_poll_udp_connections(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int devif_poll_tcp_connections(FAR struct net_driver_s *dev,
devif_poll_callback_t callback)
{
@@ -261,7 +261,7 @@ static inline int devif_poll_tcp_connections(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int devif_poll_tcp_timer(FAR struct net_driver_s *dev,
devif_poll_callback_t callback,
int hsec)
@@ -349,7 +349,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
if (!bstop)
#endif
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
{
/* Traverse all of the active TCP connections and perform the poll
* action.
@@ -360,7 +360,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
if (!bstop)
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
{
/* Traverse all of the allocated UDP connections and perform
* the poll action
@@ -467,7 +467,7 @@ int devif_timer(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
neighbor_periodic(hsec);
#endif
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
/* Traverse all of the active TCP connections and perform the
* timer action.
*/
+3 -3
View File
@@ -391,7 +391,7 @@ int ipv4_input(FAR struct net_driver_s *dev)
#endif /* CONFIG_NET_TCP_REASSEMBLY */
}
#if defined(CONFIG_NET_BROADCAST) && defined(CONFIG_NET_UDP)
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
/* If IP broadcast support is configured, we check for a broadcast
* UDP packet, which may be destined to us (even if there is no IP
* address yet assigned to the device as is the case when we are
@@ -459,13 +459,13 @@ int ipv4_input(FAR struct net_driver_s *dev)
switch (pbuf->proto)
{
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
case IP_PROTO_TCP: /* TCP input */
tcp_ipv4_input(dev);
break;
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
case IP_PROTO_UDP: /* UDP input */
udp_ipv4_input(dev);
break;
+3 -3
View File
@@ -197,7 +197,7 @@ int ipv6_input(FAR struct net_driver_s *dev)
* negotiating over DHCP for an address).
*/
#if defined(CONFIG_NET_BROADCAST) && defined(CONFIG_NET_UDP)
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
if (ipv6->proto == IP_PROTO_UDP &&
net_ipv6addr_cmp(ipv6->destipaddr, g_ipv6_alloneaddr))
{
@@ -253,13 +253,13 @@ int ipv6_input(FAR struct net_driver_s *dev)
switch (ipv6->proto)
{
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
case IP_PROTO_TCP: /* TCP input */
tcp_ipv6_input(dev);
break;
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
case IP_PROTO_UDP: /* UDP input */
udp_ipv6_input(dev);
break;
+9 -2
View File
@@ -57,6 +57,7 @@
#include "local/local.h"
#include "igmp/igmp.h"
#include "route/route.h"
#include "usrsock/usrsock.h"
#include "utils/utils.h"
/****************************************************************************
@@ -130,7 +131,7 @@ void net_setup(void)
local_initialize();
#endif
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
/* Initialize the listening port structures */
tcp_listen_initialize();
@@ -146,7 +147,7 @@ void net_setup(void)
#endif
#endif /* CONFIG_NET_TCP */
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
/* Initialize the UDP connection structures */
udp_initialize();
@@ -163,6 +164,12 @@ void net_setup(void)
net_initroute();
#endif
#ifdef CONFIG_NET_USRSOCK
/* Initialize the user-space socket API */
usrsock_initialize();
#endif
}
/****************************************************************************
+4 -1
View File
@@ -42,7 +42,10 @@ SOCK_CSRCS += net_dupsd2.c net_clone.c net_poll.c net_vfcntl.c
# TCP/IP support
ifeq ($(CONFIG_NET_TCP),y)
SOCK_CSRCS += listen.c accept.c net_monitor.c
SOCK_CSRCS += listen.c accept.c
ifneq ($(CONFIG_NET_TCP_NO_STACK),y)
SOCK_CSRCS += net_monitor.c
endif
# Local Unix domain support
+17
View File
@@ -54,6 +54,7 @@
#include "tcp/tcp.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
@@ -129,7 +130,9 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR socklen_t *addrlen, FAR struct socket *newsock)
{
int errcode;
#ifdef NET_TCP_HAVE_STACK
int ret;
#endif
DEBUGASSERT(psock != NULL);
@@ -141,6 +144,13 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
if (psock->s_type != SOCK_STREAM)
{
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
#warning "Missing logic"
}
#endif
errcode = EOPNOTSUPP;
goto errout;
}
@@ -238,6 +248,7 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
/* Perform the local accept operation (with the network locked) */
net_lock();
@@ -267,6 +278,10 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
}
net_unlock();
#else
errcode = EOPNOTSUPP;
goto errout;
#endif /* NET_TCP_HAVE_STACK */
}
#endif /* CONFIG_NET_TCP */
@@ -278,8 +293,10 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
leave_cancellation_point();
return OK;
#ifdef NET_TCP_HAVE_STACK
errout_after_accept:
psock_close(newsock);
#endif
errout:
set_errno(errcode);
+24
View File
@@ -46,6 +46,7 @@
#include <errno.h>
#include <string.h>
#include <debug.h>
#include <assert.h>
#ifdef CONFIG_NET_PKT
# include <netpacket/packet.h>
@@ -60,6 +61,7 @@
#include "udp/udp.h"
#include "pkt/pkt.h"
#include "local/local.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
@@ -212,6 +214,20 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
switch (psock->s_type)
{
#ifdef CONFIG_NET_USRSOCK
case SOCK_USRSOCK_TYPE:
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
DEBUGASSERT(conn);
/* Perform the usrsock bind operation */
ret = usrsock_bind(conn, addr, addrlen);
}
break;
#endif
#ifdef CONFIG_NET_PKT
case SOCK_RAW:
ret = pkt_bind(psock->s_conn, lladdr);
@@ -243,9 +259,13 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
/* Bind the TCP/IP connection structure */
ret = tcp_bind(psock->s_conn, addr);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_TCP */
@@ -284,9 +304,13 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
/* Bind the UDPP/IP connection structure */
ret = udp_bind(psock->s_conn, addr);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_UDP */
+42 -12
View File
@@ -62,12 +62,13 @@
#include "udp/udp.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
struct tcp_connect_s
{
FAR struct tcp_conn_s *tc_conn; /* Reference to TCP connection structure */
@@ -82,7 +83,7 @@ struct tcp_connect_s
* Private Function Prototypes
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int psock_setup_callbacks(FAR struct socket *psock,
FAR struct tcp_connect_s *pstate);
static void psock_teardown_callbacks(FAR struct tcp_connect_s *pstate,
@@ -92,7 +93,7 @@ static uint16_t psock_connect_interrupt(FAR struct net_driver_s *dev,
uint16_t flags);
static inline int psock_tcp_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr);
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Private Functions
@@ -101,7 +102,7 @@ static inline int psock_tcp_connect(FAR struct socket *psock,
* Name: psock_setup_callbacks
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int psock_setup_callbacks(FAR struct socket *psock,
FAR struct tcp_connect_s *pstate)
{
@@ -137,13 +138,13 @@ static inline int psock_setup_callbacks(FAR struct socket *psock,
return ret;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Name: psock_teardown_callbacks
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static void psock_teardown_callbacks(FAR struct tcp_connect_s *pstate,
int status)
{
@@ -165,7 +166,7 @@ static void psock_teardown_callbacks(FAR struct tcp_connect_s *pstate,
net_stopmonitor(conn);
}
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Name: psock_connect_interrupt
@@ -187,7 +188,7 @@ static void psock_teardown_callbacks(FAR struct tcp_connect_s *pstate,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static uint16_t psock_connect_interrupt(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags)
@@ -322,7 +323,7 @@ static uint16_t psock_connect_interrupt(FAR struct net_driver_s *dev,
return flags;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Name: psock_tcp_connect
@@ -342,7 +343,7 @@ static uint16_t psock_connect_interrupt(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int psock_tcp_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr)
{
@@ -434,7 +435,7 @@ static inline int psock_tcp_connect(FAR struct socket *psock,
net_unlock();
return ret;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Public Functions
@@ -512,7 +513,8 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
socklen_t addrlen)
{
FAR const struct sockaddr_in *inaddr = (FAR const struct sockaddr_in *)addr;
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) || \
defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_USRSOCK)
int ret;
#endif
int errcode;
@@ -570,6 +572,13 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
#endif
default:
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
break;
}
#endif
DEBUGPANIC();
errcode = EAFNOSUPPORT;
goto errout;
@@ -608,9 +617,13 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
/* Connect the TCP/IP socket */
ret = psock_tcp_connect(psock, addr);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_TCP */
@@ -642,6 +655,7 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
ret = udp_connect(psock->s_conn, addr);
if (ret < 0 || addr == NULL)
{
@@ -651,6 +665,9 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
{
psock->s_flags |= _SF_CONNECTED;
}
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_UDP */
@@ -663,6 +680,19 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
break;
#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */
#ifdef CONFIG_NET_USRSOCK
case SOCK_USRSOCK_TYPE:
{
ret = usrsock_connect(psock, addr, addrlen);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
}
break;
#endif /* CONFIG_NET_USRSOCK */
default:
errcode = EBADF;
goto errout;
+30 -8
View File
@@ -44,6 +44,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
@@ -54,6 +55,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
#ifdef CONFIG_NET
@@ -92,7 +94,7 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
{
FAR struct net_driver_s *dev;
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr;
#endif
#ifdef CONFIG_NETDEV_MULTINIC
@@ -116,7 +118,7 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
switch (psock->s_type)
{
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
case SOCK_STREAM:
{
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
@@ -129,7 +131,7 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
break;
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
case SOCK_DGRAM:
{
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
@@ -171,7 +173,7 @@ int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
/* Set the address family and the IP address */
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
outaddr->sin_family = AF_INET;
outaddr->sin_addr.s_addr = dev->d_ipaddr;
*addrlen = sizeof(struct sockaddr_in);
@@ -215,7 +217,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
FAR socklen_t *addrlen)
{
FAR struct net_driver_s *dev;
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr;
#endif
#ifdef CONFIG_NETDEV_MULTINIC
@@ -239,7 +241,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
switch (psock->s_type)
{
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
case SOCK_STREAM:
{
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
@@ -252,7 +254,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
break;
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
case SOCK_DGRAM:
{
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
@@ -294,7 +296,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
/* Set the address family and the IP address */
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
outaddr->sin6_family = AF_INET6;
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipv6addr, 16);
*addrlen = sizeof(struct sockaddr_in6);
@@ -371,6 +373,26 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
}
#endif
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
DEBUGASSERT(conn);
/* Handle usrsock getsockname */
ret = usrsock_getsockname(conn, addr, addrlen);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
return OK;
}
#endif
/* Handle by address domain */
switch (psock->s_domain)
+51
View File
@@ -43,9 +43,12 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
#include "utils/utils.h"
/****************************************************************************
@@ -106,6 +109,40 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
goto errout;
}
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
int ret;
DEBUGASSERT(conn);
/* Some of the socket options are handled from this function. */
switch (option)
{
case SO_TYPE: /* Type can be read from NuttX psock structure. */
case SO_RCVTIMEO: /* Rx timeouts can be handled at NuttX side, thus
* simplify daemon implementation. */
case SO_SNDTIMEO: /* Rx timeouts can be handled at NuttX side, thus
* simplify daemon implementation. */
break;
default: /* Other options are passed to usrsock daemon. */
{
ret = usrsock_getsockopt(conn, level, option, value, value_len);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
return OK;
}
}
}
#endif
/* Process the option */
switch (option)
@@ -159,6 +196,20 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
goto errout;
}
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
/* Return the actual socket type */
*(int*)value = conn->type;
*value_len = sizeof(int);
break;
}
#endif
/* Return the socket type */
*(FAR int *)value = psock->s_type;
+13
View File
@@ -48,6 +48,7 @@
#include "tcp/tcp.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
@@ -92,6 +93,13 @@ int psock_listen(FAR struct socket *psock, int backlog)
if (psock->s_type != SOCK_STREAM || !psock->s_conn)
{
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
#warning "Missing logic"
}
#endif
errcode = EOPNOTSUPP;
goto errout;
}
@@ -118,6 +126,7 @@ int psock_listen(FAR struct socket *psock, int backlog)
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
FAR struct tcp_conn_s *conn =
(FAR struct tcp_conn_s *)psock->s_conn;
@@ -143,6 +152,10 @@ int psock_listen(FAR struct socket *psock, int backlog)
*/
tcp_listen(conn);
#else
errcode = EOPNOTSUPP;
goto errout;
#endif /* NET_TCP_HAVE_STACK */
}
#endif /* CONFIG_NET_TCP */
+12 -2
View File
@@ -51,6 +51,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
@@ -96,7 +97,7 @@ int net_clone(FAR struct socket *psock1, FAR struct socket *psock2)
DEBUGASSERT(psock2->s_conn);
psock2->s_crefs = 1; /* One reference on the new socket itself */
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
if (psock2->s_type == SOCK_STREAM)
{
FAR struct tcp_conn_s *conn = psock2->s_conn;
@@ -105,7 +106,7 @@ int net_clone(FAR struct socket *psock1, FAR struct socket *psock2)
}
else
#endif
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
if (psock2->s_type == SOCK_DGRAM)
{
FAR struct udp_conn_s *conn = psock2->s_conn;
@@ -113,6 +114,15 @@ int net_clone(FAR struct socket *psock1, FAR struct socket *psock2)
conn->crefs++;
}
else
#endif
#ifdef CONFIG_NET_USRSOCK
if (psock2->s_type == SOCK_USRSOCK_TYPE)
{
FAR struct usrsock_conn_s *conn = psock2->s_conn;
DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255);
conn->crefs++;
}
else
#endif
{
nerr("ERROR: Unsupported type: %d\n", psock2->s_type);
+53 -10
View File
@@ -67,12 +67,13 @@
#include "pkt/pkt.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
struct tcp_close_s
{
FAR struct devif_callback_s *cl_cb; /* Reference to TCP callback instance */
@@ -106,7 +107,7 @@ struct tcp_close_s
*
****************************************************************************/
#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_SOLINGER)
#if defined(NET_TCP_HAVE_STACK) && defined(CONFIG_NET_SOLINGER)
static inline int close_timeout(FAR struct tcp_close_s *pstate)
{
FAR struct socket *psock = 0;
@@ -132,7 +133,7 @@ static inline int close_timeout(FAR struct tcp_close_s *pstate)
return FALSE;
}
#endif /* CONFIG_NET_SOCKOPTS && CONFIG_NET_SOLINGER */
#endif /* NET_TCP_HAVE_STACK && CONFIG_NET_SOLINGER */
/****************************************************************************
* Function: netclose_interrupt
@@ -151,7 +152,7 @@ static inline int close_timeout(FAR struct tcp_close_s *pstate)
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static uint16_t netclose_interrupt(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags)
@@ -256,7 +257,7 @@ end_wait:
return 0;
#endif
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: netclose_txnotify
@@ -274,7 +275,7 @@ end_wait:
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline void netclose_txnotify(FAR struct socket *psock,
FAR struct tcp_conn_s *conn)
{
@@ -313,7 +314,7 @@ static inline void netclose_txnotify(FAR struct socket *psock,
}
#endif /* CONFIG_NET_IPv6 */
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: netclose_disconnect
@@ -332,7 +333,7 @@ static inline void netclose_txnotify(FAR struct socket *psock,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline int netclose_disconnect(FAR struct socket *psock)
{
struct tcp_close_s state;
@@ -451,7 +452,7 @@ static inline int netclose_disconnect(FAR struct socket *psock)
net_unlock();
return ret;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: local_close
@@ -557,6 +558,7 @@ int psock_close(FAR struct socket *psock)
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
FAR struct tcp_conn_s *conn = psock->s_conn;
/* Is this the last reference to the connection structure
@@ -592,6 +594,7 @@ int psock_close(FAR struct socket *psock)
conn->crefs--;
}
#endif /* NET_TCP_HAVE_STACK */
}
#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL_STREAM */
}
@@ -617,6 +620,7 @@ int psock_close(FAR struct socket *psock)
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
FAR struct udp_conn_s *conn = psock->s_conn;
/* Is this the last reference to the connection structure
@@ -636,6 +640,7 @@ int psock_close(FAR struct socket *psock)
conn->crefs--;
}
#endif /* NET_UDP_HAVE_STACK */
}
#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */
}
@@ -668,6 +673,44 @@ int psock_close(FAR struct socket *psock)
break;
#endif
#ifdef CONFIG_NET_USRSOCK
case SOCK_USRSOCK_TYPE:
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
/* Is this the last reference to the connection structure (there
* could be more if the socket was dup'ed).
*/
if (conn->crefs <= 1)
{
/* Yes... inform user-space daemon of socket close. */
errcode = usrsock_close(conn);
/* Free the connection structure */
conn->crefs = 0;
usrsock_free(psock->s_conn);
if (errcode < 0)
{
/* Return with error code, but free resources. */
errcode = -errcode;
goto errout_with_psock;
}
}
else
{
/* No.. Just decrement the reference count */
conn->crefs--;
}
}
break;
#endif
default:
errcode = EBADF;
goto errout;
@@ -679,7 +722,7 @@ int psock_close(FAR struct socket *psock)
sock_release(psock);
return OK;
#ifdef CONFIG_NET_TCP
#if defined(NET_TCP_HAVE_STACK) || defined(CONFIG_NET_USRSOCK)
errout_with_psock:
sock_release(psock);
#endif
+4
View File
@@ -50,6 +50,8 @@
#include "tcp/tcp.h"
#include "socket/socket.h"
#ifdef NET_TCP_HAVE_STACK
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -345,4 +347,6 @@ void net_lostconnection(FAR struct socket *psock, uint16_t flags)
net_unlock();
}
#endif /* NET_TCP_HAVE_STACK */
#endif /* CONFIG_NET && CONFIG_NET_TCP */
+12 -1
View File
@@ -45,6 +45,7 @@
#include "udp/udp.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
#if defined(CONFIG_NET) && !defined(CONFIG_DISABLE_POLL)
@@ -57,7 +58,8 @@
*/
#undef HAVE_NET_POLL
#if defined(HAVE_TCP_POLL) || defined(HAVE_UDP_POLL) || defined(HAVE_LOCAL_POLL)
#if defined(HAVE_TCP_POLL) || defined(HAVE_UDP_POLL) || \
defined(HAVE_LOCAL_POLL) || defined(CONFIG_NET_USRSOCK)
# define HAVE_NET_POLL 1
#endif
@@ -233,6 +235,15 @@ int psock_poll(FAR struct socket *psock, FAR struct pollfd *fds, bool setup)
#else
int ret;
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
/* Perform usrsock setup/teardown. */
return usrsock_poll(psock, fds, setup);
}
#endif
/* Check if we are setting up or tearing down the poll */
if (setup)
+19
View File
@@ -72,6 +72,8 @@
#include "tcp/tcp.h"
#include "socket/socket.h"
#ifdef NET_TCP_HAVE_STACK
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -615,6 +617,21 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
goto errout;
}
#ifdef CONFIG_NET_USRSOCK
/* If this is a usrsock socket, use generic sendfile implementation. */
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
int infd;
list = sched_getfiles();
DEBUGASSERT(list != NULL);
infd = infile - list->fl_files;
return lib_sendfile(outfd, infd, offset, count);
}
#endif /* CONFIG_NET_USRSOCK */
/* If this is an un-connected socket, then return ENOTCONN */
if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
@@ -776,4 +793,6 @@ errout:
}
}
#endif /* NET_TCP_HAVE_STACK */
#endif /* CONFIG_NET && CONFIG_NET_TCP */
+25 -2
View File
@@ -49,6 +49,7 @@
#include <arch/irq.h>
#include <nuttx/net/net.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
@@ -164,6 +165,13 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
ret |= O_NONBLOCK;
}
#endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE && _SS_ISNONBLOCK(psock->s_flags))
{
ret |= O_NONBLOCK;
}
#endif
}
break;
@@ -178,7 +186,7 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
{
#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_TCP_READAHEAD) || \
defined(CONFIG_NET_UDP_READAHEAD)
defined(CONFIG_NET_UDP_READAHEAD) || defined(CONFIG_NET_USRSOCK)
/* Non-blocking is the only configurable option. And it applies
* only Unix domain sockets and to read operations on TCP/IP
* and UDP/IP sockets when read-ahead is enabled.
@@ -213,7 +221,22 @@ int net_vfcntl(int sockfd, int cmd, va_list ap)
}
else
#endif
#endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */
#if defined(CONFIG_NET_USRSOCK)
if (psock->s_type == SOCK_USRSOCK_TYPE) /* usrsock socket */
{
if ((mode & O_NONBLOCK) != 0)
{
psock->s_flags |= _SF_NONBLOCK;
}
else
{
psock->s_flags &= ~_SF_NONBLOCK;
}
}
else
#endif
#endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD ||
CONFIG_NET_UDP_READAHEAD || CONFIG_NET_USRSOCK */
{
nerr("ERROR: Non-blocking not supported for this socket\n");
}
+64 -35
View File
@@ -72,6 +72,7 @@
#include "pkt/pkt.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Pre-processor Definitions
@@ -90,7 +91,8 @@
* Private Types
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) || defined(CONFIG_NET_PKT)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK) \
|| defined(CONFIG_NET_PKT)
struct recvfrom_s
{
FAR struct socket *rf_sock; /* The parent socket structure */
@@ -106,7 +108,7 @@ struct recvfrom_s
ssize_t rf_recvlen; /* The received length */
int rf_result; /* Success:OK, failure:negated errno */
};
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK */
/****************************************************************************
* Private Functions
@@ -129,7 +131,8 @@ struct recvfrom_s
*
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) || defined(CONFIG_NET_PKT)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK) \
|| defined(CONFIG_NET_PKT)
static inline void recvfrom_add_recvlen(FAR struct recvfrom_s *pstate,
size_t recvlen)
@@ -143,7 +146,7 @@ static inline void recvfrom_add_recvlen(FAR struct recvfrom_s *pstate,
pstate->rf_buffer += recvlen;
pstate->rf_buflen -= recvlen;
}
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP || CONFIG_NET_PKT */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK || CONFIG_NET_PKT */
/****************************************************************************
* Function: recvfrom_newdata
@@ -163,7 +166,7 @@ static inline void recvfrom_add_recvlen(FAR struct recvfrom_s *pstate,
*
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK)
static size_t recvfrom_newdata(FAR struct net_driver_s *dev,
FAR struct recvfrom_s *pstate)
{
@@ -191,7 +194,7 @@ static size_t recvfrom_newdata(FAR struct net_driver_s *dev,
return recvlen;
}
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_newpktdata
@@ -255,7 +258,7 @@ static void recvfrom_newpktdata(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline void recvfrom_newtcpdata(FAR struct net_driver_s *dev,
FAR struct recvfrom_s *pstate)
{
@@ -307,7 +310,7 @@ static inline void recvfrom_newtcpdata(FAR struct net_driver_s *dev,
dev->d_len = 0;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_newudpdata
@@ -327,7 +330,7 @@ static inline void recvfrom_newtcpdata(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static inline void recvfrom_newudpdata(FAR struct net_driver_s *dev,
FAR struct recvfrom_s *pstate)
{
@@ -339,7 +342,7 @@ static inline void recvfrom_newudpdata(FAR struct net_driver_s *dev,
dev->d_len = 0;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_tcpreadahead
@@ -359,7 +362,7 @@ static inline void recvfrom_newudpdata(FAR struct net_driver_s *dev,
*
****************************************************************************/
#if defined(CONFIG_NET_TCP) && defined(CONFIG_NET_TCP_READAHEAD)
#if defined(NET_TCP_HAVE_STACK) && defined(CONFIG_NET_TCP_READAHEAD)
static inline void recvfrom_tcpreadahead(struct recvfrom_s *pstate)
{
FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pstate->rf_sock->s_conn;
@@ -419,9 +422,9 @@ static inline void recvfrom_tcpreadahead(struct recvfrom_s *pstate)
}
}
}
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK && CONFIG_NET_TCP_READAHEAD */
#if defined(CONFIG_NET_UDP) && defined(CONFIG_NET_UDP_READAHEAD)
#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_UDP_READAHEAD)
static inline void recvfrom_udpreadahead(struct recvfrom_s *pstate)
{
@@ -526,7 +529,7 @@ out:
*
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK)
#ifdef CONFIG_NET_SOCKOPTS
static int recvfrom_timeout(struct recvfrom_s *pstate)
{
@@ -581,7 +584,7 @@ static int recvfrom_timeout(struct recvfrom_s *pstate)
return FALSE;
}
#endif /* CONFIG_NET_SOCKOPTS */
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_pktsender
@@ -684,7 +687,7 @@ static uint16_t recvfrom_pktinterrupt(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static inline void recvfrom_tcpsender(FAR struct net_driver_s *dev,
FAR struct recvfrom_s *pstate)
{
@@ -735,7 +738,7 @@ static inline void recvfrom_tcpsender(FAR struct net_driver_s *dev,
}
#endif /* CONFIG_NET_IPv4 */
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_tcpinterrupt
@@ -757,7 +760,7 @@ static inline void recvfrom_tcpsender(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static uint16_t recvfrom_tcpinterrupt(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags)
@@ -958,7 +961,7 @@ static uint16_t recvfrom_tcpinterrupt(FAR struct net_driver_s *dev,
return flags;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_udpsender
@@ -978,7 +981,7 @@ static uint16_t recvfrom_tcpinterrupt(FAR struct net_driver_s *dev,
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static inline void recvfrom_udpsender(struct net_driver_s *dev, struct recvfrom_s *pstate)
{
/* Get the family from the packet type, IP address from the IP header, and
@@ -1059,7 +1062,7 @@ static inline void recvfrom_udpsender(struct net_driver_s *dev, struct recvfrom_
}
#endif /* CONFIG_NET_IPv4 */
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_udp_terminate
@@ -1076,7 +1079,7 @@ static inline void recvfrom_udpsender(struct net_driver_s *dev, struct recvfrom_
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static void recvfrom_udp_terminate(FAR struct recvfrom_s *pstate, int result)
{
/* Don't allow any further UDP call backs. */
@@ -1095,7 +1098,7 @@ static void recvfrom_udp_terminate(FAR struct recvfrom_s *pstate, int result)
sem_post(&pstate->rf_sem);
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_udp_interrupt
@@ -1117,7 +1120,7 @@ static void recvfrom_udp_terminate(FAR struct recvfrom_s *pstate, int result)
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static uint16_t recvfrom_udp_interrupt(FAR struct net_driver_s *dev,
FAR void *pvconn, FAR void *pvpriv,
uint16_t flags)
@@ -1189,7 +1192,7 @@ static uint16_t recvfrom_udp_interrupt(FAR struct net_driver_s *dev,
return flags;
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_init
@@ -1210,7 +1213,8 @@ static uint16_t recvfrom_udp_interrupt(FAR struct net_driver_s *dev,
*
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) || defined(CONFIG_NET_PKT)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK) \
|| defined(CONFIG_NET_PKT)
static void recvfrom_init(FAR struct socket *psock, FAR void *buf,
size_t len, FAR struct sockaddr *infrom,
FAR socklen_t *fromlen,
@@ -1246,7 +1250,7 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf,
#define recvfrom_uninit(s) sem_destroy(&(s)->rf_sem)
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfrom_result
@@ -1265,7 +1269,8 @@ static void recvfrom_init(FAR struct socket *psock, FAR void *buf,
*
****************************************************************************/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP) || defined(CONFIG_NET_PKT)
#if defined(NET_UDP_HAVE_STACK) || defined(NET_TCP_HAVE_STACK) \
|| defined(CONFIG_NET_PKT)
static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
{
int save_errno = get_errno(); /* In case something we do changes it */
@@ -1294,7 +1299,7 @@ static ssize_t recvfrom_result(int result, struct recvfrom_s *pstate)
return pstate->rf_recvlen;
}
#endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */
#endif /* NET_UDP_HAVE_STACK || NET_TCP_HAVE_STACK */
/****************************************************************************
* Function: recvfromo_pkt_rxnotify
@@ -1334,7 +1339,7 @@ static void recvfromo_pkt_rxnotify(FAR struct pkt_conn_s *conn)
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static inline void recvfrom_udp_rxnotify(FAR struct socket *psock,
FAR struct udp_conn_s *conn)
{
@@ -1373,7 +1378,7 @@ static inline void recvfrom_udp_rxnotify(FAR struct socket *psock,
}
#endif /* CONFIG_NET_IPv6 */
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: pkt_recvfrom
@@ -1489,7 +1494,7 @@ errout_with_state:
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR struct sockaddr *from, FAR socklen_t *fromlen)
{
@@ -1607,7 +1612,7 @@ errout_with_state:
recvfrom_uninit(&state);
return ret;
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Function: tcp_recvfrom
@@ -1629,7 +1634,7 @@ errout_with_state:
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR struct sockaddr *from, FAR socklen_t *fromlen)
{
@@ -1785,7 +1790,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
recvfrom_uninit(&state);
return (ssize_t)ret;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Public Functions
@@ -1880,6 +1885,22 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
goto errout;
}
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
/* Perform the usrsock recvfrom operation */
ret = usrsock_recvfrom(psock, buf, len, from, fromlen);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
return ret;
}
#endif
/* If a 'from' address has been provided, verify that it is large
* enough to hold this address family.
*/
@@ -1964,7 +1985,11 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
else
#endif
{
#ifdef NET_TCP_HAVE_STACK
ret = tcp_recvfrom(psock, buf, len, from, fromlen);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_TCP */
}
@@ -1989,7 +2014,11 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
ret = udp_recvfrom(psock, buf, len, from, fromlen);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_UDP */
}
+33 -1
View File
@@ -51,6 +51,7 @@
#include "sixlowpan/sixlowpan.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
@@ -168,9 +169,14 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
#ifdef CONFIG_NETDEV_MULTINIC
if (ret < 0)
{
/* UDP/IP packet send */
/* TCP/IP packet send */
ret = psock_tcp_send(psock, buf, len);
#ifdef NET_TCP_HAVE_STACK
ret = psock_tcp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NETDEV_MULTINIC */
@@ -178,7 +184,11 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
/* Only TCP/IP packet send */
#ifdef NET_TCP_HAVE_STACK
ret = psock_tcp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
#endif /* CONFIG_NET_6LOWPAN */
}
#endif /* CONFIG_NET_TCP */
@@ -216,6 +226,11 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
/* UDP/IP packet send */
ret = psock_udp_send(psock, buf, len);
#ifdef NET_UDP_HAVE_STACK
ret = psock_udp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
}
#endif /* CONFIG_NETDEV_MULTINIC */
@@ -223,7 +238,11 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
/* Only UDP/IP packet send */
#ifdef NET_UDP_HAVE_STACK
ret = psock_udp_send(psock, buf, len);
#else
ret = -ENOSYS;
#endif
#endif /* CONFIG_NET_6LOWPAN */
}
#endif /* CONFIG_NET_UDP */
@@ -231,6 +250,14 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
break;
#endif /* CONFIG_NET_UDP */
#ifdef CONFIG_NET_USRSOCK
case SOCK_USRSOCK_TYPE:
{
ret = usrsock_sendto(psock, buf, len, NULL, 0);
}
break;
#endif /*CONFIG_NET_USRSOCK*/
default:
{
/* EDESTADDRREQ. Signifies that the socket is not connection-mode
@@ -243,6 +270,11 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
}
leave_cancellation_point();
if (ret < 0)
{
set_errno(-ret);
ret = ERROR;
}
return ret;
}
+25 -2
View File
@@ -51,6 +51,7 @@
#include "udp/udp.h"
#include "local/local.h"
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
@@ -126,7 +127,8 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
socklen_t tolen)
{
socklen_t minlen;
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM)
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) || \
defined(CONFIG_NET_USRSOCK)
ssize_t nsent;
#endif
int errcode;
@@ -137,7 +139,8 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
if (!to || !tolen)
{
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM)
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) || \
defined(CONFIG_NET_USRSOCK)
return psock_send(psock, buf, len, flags);
#else
nerr("ERROR: No 'to' address\n");
@@ -146,6 +149,22 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
#endif
}
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
/* Perform the usrsock sendto operation */
nsent = usrsock_sendto(psock, buf, len, to, tolen);
if (nsent < 0)
{
errcode = -nsent;
goto errout;
}
return nsent;
}
#endif
/* Verify that a valid address has been provided */
switch (to->sa_family)
@@ -218,7 +237,11 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
else
#endif
{
#ifdef NET_UDP_HAVE_STACK
nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen);
#else
nsent = -ENOSYS;
#endif
}
#endif /* CONFIG_NET_UDP */
+36
View File
@@ -45,11 +45,14 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <arch/irq.h>
#include <nuttx/net/net.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
#include "utils/utils.h"
/****************************************************************************
@@ -115,6 +118,39 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
goto errout;
}
#ifdef CONFIG_NET_USRSOCK
if (psock->s_type == SOCK_USRSOCK_TYPE)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
int ret;
DEBUGASSERT(conn);
/* Some of the socket options are handled from this function. */
switch (option)
{
case SO_RCVTIMEO: /* Rx timeouts can be handled at NuttX side, thus
* simplify daemon implementation. */
case SO_SNDTIMEO: /* Rx timeouts can be handled at NuttX side, thus
* simplify daemon implementation. */
break;
default: /* Other options are passed to usrsock daemon. */
{
ret = usrsock_setsockopt(conn, level, option, value, value_len);
if (ret < 0)
{
errcode = -ret;
goto errout;
}
return OK;
}
}
}
#endif
/* Process the option */
switch (option)
+54 -4
View File
@@ -52,6 +52,7 @@
#include "udp/udp.h"
#include "pkt/pkt.h"
#include "local/local.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
@@ -65,7 +66,7 @@
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
static int psock_tcp_alloc(FAR struct socket *psock)
{
/* Allocate the TCP connection structure */
@@ -90,7 +91,7 @@ static int psock_tcp_alloc(FAR struct socket *psock)
psock->s_conn = conn;
return OK;
}
#endif /* CONFIG_NET_TCP */
#endif /* NET_TCP_HAVE_STACK */
/****************************************************************************
* Name: psock_udp_alloc
@@ -100,7 +101,7 @@ static int psock_tcp_alloc(FAR struct socket *psock)
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
#ifdef NET_UDP_HAVE_STACK
static int psock_udp_alloc(FAR struct socket *psock)
{
/* Allocate the UDP connection structure */
@@ -125,7 +126,7 @@ static int psock_udp_alloc(FAR struct socket *psock)
psock->s_conn = conn;
return OK;
}
#endif /* CONFIG_NET_UDP */
#endif /* NET_UDP_HAVE_STACK */
/****************************************************************************
* Name: psock_pkt_alloc
@@ -250,6 +251,47 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
int ret;
int errcode;
#ifdef CONFIG_NET_USRSOCK
switch (domain)
{
default:
break;
case PF_INET:
case PF_INET6:
{
#ifndef CONFIG_NET_USRSOCK_UDP
if (type == SOCK_DGRAM)
break;
#endif
#ifndef CONFIG_NET_USRSOCK_TCP
if (type == SOCK_STREAM)
break;
#endif
psock->s_type = 0;
psock->s_conn = NULL;
ret = usrsock_socket(domain, type, protocol, psock);
if (ret >= 0)
{
/* Successfully handled and opened by usrsock daemon. */
return OK;
}
else if (ret == -ENETDOWN)
{
/* Net down means that usrsock daemon is not running.
* Attempt to open socket with kernel networking stack. */
}
else
{
errcode = -ret;
goto errout;
}
}
}
#endif /* CONFIG_NET_USRSOCK */
/* Only PF_INET, PF_INET6 or PF_PACKET domains supported */
switch (domain)
@@ -400,9 +442,13 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
if (ipdomain)
#endif
{
#ifdef NET_TCP_HAVE_STACK
/* Allocate and attach the TCP connection structure */
ret = psock_tcp_alloc(psock);
#else
ret = -ENETDOWN;
#endif
}
#endif /* CONFIG_NET_TCP */
@@ -438,9 +484,13 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
if (ipdomain)
#endif
{
#ifdef NET_UDP_HAVE_STACK
/* Allocate and attach the UDP connection structure */
ret = psock_udp_alloc(psock);
#else
ret = -ENETDOWN;
#endif
}
#endif /* CONFIG_NET_UDP */
+5 -4
View File
@@ -49,6 +49,7 @@
#include <nuttx/clock.h>
#include <nuttx/net/net.h>
#include "tcp/tcp.h"
/****************************************************************************
* Pre-processor Definitions
@@ -152,7 +153,7 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
struct tcp_conn_s; /* Forward reference */
#endif
@@ -243,7 +244,7 @@ FAR struct socket *sockfd_socket(int sockfd);
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
int net_startmonitor(FAR struct socket *psock);
#endif
@@ -265,7 +266,7 @@ int net_startmonitor(FAR struct socket *psock);
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
void net_stopmonitor(FAR struct tcp_conn_s *conn);
#endif
@@ -287,7 +288,7 @@ void net_stopmonitor(FAR struct tcp_conn_s *conn);
*
****************************************************************************/
#ifdef CONFIG_NET_TCP
#ifdef NET_TCP_HAVE_STACK
void net_lostconnection(FAR struct socket *psock, uint16_t flags);
#endif
+10 -3
View File
@@ -9,9 +9,16 @@ config NET_TCP
bool "TCP/IP Networking"
default n
---help---
TCP support on or off
Enable or disable TCP networking support.
if NET_TCP
config NET_TCP_NO_STACK
bool "Disable TCP/IP Stack"
default n
select NET_TCP
---help---
Build without TCP/IP stack even if TCP networking support enabled.
if NET_TCP && !NET_TCP_NO_STACK
config NET_TCPURGDATA
bool "Urgent data"
@@ -184,5 +191,5 @@ config NET_SENDFILE
Support larger, higher performance sendfile() for transferring
files out a TCP connection.
endif # NET_TCP
endif # NET_TCP && !NET_TCP_NO_STACK
endmenu # TCP/IP Networking
+2
View File
@@ -36,6 +36,7 @@
# TCP/IP source files
ifeq ($(CONFIG_NET_TCP),y)
ifneq ($(CONFIG_NET_TCP_NO_STACK),y)
# Socket layer
@@ -73,4 +74,5 @@ endif
DEPPATH += --dep-path tcp
VPATH += :tcp
endif # !CONFIG_NET_TCP_NO_STACK
endif # CONFIG_NET_TCP
+5 -2
View File
@@ -48,11 +48,14 @@
#include <nuttx/net/iob.h>
#include <nuttx/net/ip.h>
#ifdef CONFIG_NET_TCP
#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NET_TCP_HAVE_STACK 1
/* Conditions for support TCP poll/select operations */
#if !defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
@@ -1306,5 +1309,5 @@ int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
}
#endif
#endif /* CONFIG_NET_TCP */
#endif /* CONFIG_NET_TCP && !CONFIG_NET_TCP_NO_STACK */
#endif /* _NET_TCP_TCP_H */
+9 -2
View File
@@ -12,7 +12,14 @@ config NET_UDP
---help---
Enable or disable UDP networking support.
if NET_UDP
config NET_UDP_NO_STACK
bool "Disable UDP/IP Stack"
default n
select NET_UDP
---help---
Build without UDP/IP stack even if UDP networking support enabled.
if NET_UDP && !NET_UDP_NO_STACK
config NET_UDP_CHECKSUMS
bool "UDP checksums"
@@ -55,5 +62,5 @@ config NET_UDP_READAHEAD
default y
select NET_IOB
endif # NET_UDP
endif # NET_UDP && !NET_UDP_NO_STACK
endmenu # UDP Networking
+2
View File
@@ -36,6 +36,7 @@
# UDP source files
ifeq ($(CONFIG_NET_UDP),y)
ifneq ($(CONFIG_NET_UDP_NO_STACK),y)
# Socket layer
@@ -57,4 +58,5 @@ NET_CSRCS += udp_callback.c udp_ipselect.c
DEPPATH += --dep-path udp
VPATH += :udp
endif # !CONFIG_NET_UDP_NO_STACK
endif # CONFIG_NET_UDP
+5 -2
View File
@@ -51,11 +51,14 @@
# include <nuttx/net/iob.h>
#endif
#ifdef CONFIG_NET_UDP
#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NET_UDP_HAVE_STACK 1
/* Conditions for support UDP poll/select operations */
#if !defined(CONFIG_DISABLE_POLL) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
@@ -510,5 +513,5 @@ int udp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds);
}
#endif
#endif /* CONFIG_NET_UDP */
#endif /* CONFIG_NET_UDP && !CONFIG_NET_UDP_NO_STACK */
#endif /* __NET_UDP_UDP_H */
+39
View File
@@ -0,0 +1,39 @@
#
# For a description of the syntax of this configuration file,
# see misc/tools/kconfig-language.txt.
#
menu "User-space networking stack API"
config NET_USRSOCK
bool "User-space networking stack API"
default n
depends on NET
---help---
Enable or disable user-space networking stack support.
if NET_USRSOCK
config NET_USRSOCK_CONNS
int "Number of usrsock connections"
default 6
---help---
Maximum number of usrsock connections (all tasks).
Note: Usrsock daemon can impose additional restrictions for
maximum number of concurrent connections supported.
config NET_USRSOCK_UDP
bool "User-space daemon provides UDP sockets"
default n
select NET_UDP
---help---
config NET_USRSOCK_TCP
bool "User-space daemon provides TCP sockets"
default n
select NET_TCP
---help---
endif # NET_USRSOCK
endmenu # User-space networking stack API
+51
View File
@@ -0,0 +1,51 @@
############################################################################
# net/usrsock/Make.defs
#
# Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
# Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
# User Socket source files
ifeq ($(CONFIG_NET_USRSOCK),y)
NET_CSRCS += usrsock_close.c usrsock_conn.c usrsock_bind.c usrsock_connect.c
NET_CSRCS += usrsock_dev.c
NET_CSRCS += usrsock_event.c usrsock_getsockname.c usrsock_getsockopt.c
NET_CSRCS += usrsock_poll.c usrsock_recvfrom.c usrsock_sendto.c
NET_CSRCS += usrsock_setsockopt.c usrsock_socket.c
# Include User Socket build support
DEPPATH += --dep-path usrsock
VPATH += :usrsock
endif # CONFIG_NET_USRSOCK
File diff suppressed because it is too large Load Diff
+221
View File
@@ -0,0 +1,221 @@
/****************************************************************************
* net/usrsock/usrsock_bind.c
*
* Copyright (C) 2015-2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t bind_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->result = -ECONNABORTED;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->result = conn->resp.result;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_bind_request
****************************************************************************/
static int do_bind_request(FAR struct usrsock_conn_s *conn,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
struct usrsock_request_bind_s req = {};
struct iovec bufs[2];
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_BIND;
req.usockid = conn->usockid;
req.addrlen = addrlen;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
bufs[1].iov_base = (FAR void *)addr;
bufs[1].iov_len = req.addrlen;
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: usrsock_bind
*
* Description:
* usrsock_bind() gives the socket 'conn' the local address 'addr'. 'addr'
* is 'addrlen' bytes long. Traditionally, this is called "assigning a name
* to a socket." When a socket is created with socket, it exists in a name
* space (address family) but has no name assigned.
*
* Parameters:
* conn usrsock socket connection structure
* addr Socket local address
* addrlen Length of 'addr'
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately
*
* EACCES
* The address is protected, and the user is not the superuser.
* EADDRINUSE
* The given address is already in use.
* EINVAL
* The socket is already bound to an address.
* ENOTSOCK
* psock is a descriptor for a file, not a socket.
*
* Assumptions:
*
****************************************************************************/
int usrsock_bind(FAR struct usrsock_conn_s *conn,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
struct usrsock_reqstate_s state = {};
ssize_t ret;
DEBUGASSERT(conn);
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_request_callback(conn, &state, bind_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Request user-space daemon to close socket. */
ret = do_bind_request(conn, addr, addrlen);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.result;
}
usrsock_teardown_request_callback(&state);
errout_unlock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+205
View File
@@ -0,0 +1,205 @@
/****************************************************************************
* net/usrsock/usrsock_close.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t close_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
conn->state = USRSOCK_CONN_STATE_ABORTED;
pstate->result = -ECONNABORTED;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->result = conn->resp.result;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_close_request
****************************************************************************/
static int do_close_request(FAR struct usrsock_conn_s *conn)
{
struct usrsock_request_close_s req = {};
struct iovec bufs[1];
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_CLOSE;
req.usockid = conn->usockid;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_close
*
* Description:
*
****************************************************************************/
int usrsock_close(FAR struct usrsock_conn_s *conn)
{
struct usrsock_reqstate_s state = {};
int ret;
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Already closed? */
ninfo("usockid=%d; already closed.\n", conn->usockid);
ret = OK;
goto close_out;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_request_callback(conn, &state, close_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout;
}
/* Request user-space daemon to close socket. */
ret = do_close_request(conn);
if (ret < 0)
{
ret = OK; /* Error? return OK for close. */
}
else
{
/* Wait for completion of request. */
while (net_lockedwait(&state.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.result;
if (ret < 0)
{
/* TODO: Error handling for close? Mark closed anyway? There is not
* much we can do if this happens.
*/
ninfo("user-space daemon reported error %d for usockid=%d\n",
state.result, conn->usockid);
ret = OK;
}
}
usrsock_teardown_request_callback(&state);
close_out:
conn->state = USRSOCK_CONN_STATE_UNINITIALIZED;
conn->usockid = -1;
errout:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+347
View File
@@ -0,0 +1,347 @@
/****************************************************************************
* net/usrsock/usrsock_conn.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/net.h>
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Data
****************************************************************************/
/* The array containing all usrsock connections. */
struct usrsock_conn_s g_usrsock_connections[CONFIG_NET_USRSOCK_CONNS];
/* A list of all free usrsock connections */
static dq_queue_t g_free_usrsock_connections;
static sem_t g_free_sem;
/* A list of all allocated usrsock connections */
static dq_queue_t g_active_usrsock_connections;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: _usrsock_semtake() and _usrsock_semgive()
*
* Description:
* Take/give semaphore
*
****************************************************************************/
static void _usrsock_semtake(FAR sem_t *sem)
{
/* Take the semaphore (perhaps waiting) */
while (net_lockedwait(sem) != 0)
{
/* The only case that an error should occur here is if
* the wait was awakened by a signal.
*/
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
}
static void _usrsock_semgive(FAR sem_t *sem)
{
(void)sem_post(sem);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: usrsock_alloc()
*
* Description:
* Allocate a new, uninitialized usrsock connection structure. This is
* normally something done by the implementation of the socket() API
*
****************************************************************************/
FAR struct usrsock_conn_s *usrsock_alloc(void)
{
FAR struct usrsock_conn_s *conn;
/* The free list is only accessed from user, non-interrupt level and
* is protected by a semaphore (that behaves like a mutex).
*/
_usrsock_semtake(&g_free_sem);
conn = (FAR struct usrsock_conn_s *)dq_remfirst(&g_free_usrsock_connections);
if (conn)
{
/* Make sure that the connection is marked as uninitialized */
memset(conn, 0, sizeof(*conn));
conn->dev = NULL;
conn->usockid = -1;
conn->state = USRSOCK_CONN_STATE_UNINITIALIZED;
conn->list = NULL;
conn->connected = false;
/* Enqueue the connection into the active list */
dq_addlast(&conn->node, &g_active_usrsock_connections);
}
_usrsock_semgive(&g_free_sem);
return conn;
}
/****************************************************************************
* Name: usrsock_free()
*
* Description:
* Free a usrsock connection structure that is no longer in use. This should
* be done by the implementation of close().
*
****************************************************************************/
void usrsock_free(FAR struct usrsock_conn_s *conn)
{
/* The free list is only accessed from user, non-interrupt level and
* is protected by a semaphore (that behaves like a mutex).
*/
DEBUGASSERT(conn->crefs == 0);
_usrsock_semtake(&g_free_sem);
/* Remove the connection from the active list */
dq_rem(&conn->node, &g_active_usrsock_connections);
/* Reset structure */
memset(conn, 0, sizeof(*conn));
conn->dev = NULL;
conn->usockid = -1;
conn->state = USRSOCK_CONN_STATE_UNINITIALIZED;
conn->list = NULL;
/* Free the connection */
dq_addlast(&conn->node, &g_free_usrsock_connections);
_usrsock_semgive(&g_free_sem);
}
/****************************************************************************
* Name: usrsock_nextconn()
*
* Description:
* Traverse the list of allocated usrsock connections
*
* Assumptions:
* This function is called from usrsock device logic.
*
****************************************************************************/
FAR struct usrsock_conn_s *usrsock_nextconn(FAR struct usrsock_conn_s *conn)
{
if (!conn)
{
return (FAR struct usrsock_conn_s *)g_active_usrsock_connections.head;
}
else
{
return (FAR struct usrsock_conn_s *)conn->node.flink;
}
}
/****************************************************************************
* Name: usrsock_connidx()
****************************************************************************/
int usrsock_connidx(FAR struct usrsock_conn_s *conn)
{
int idx = conn - g_usrsock_connections;
DEBUGASSERT(idx >= 0);
DEBUGASSERT(idx < ARRAY_SIZE(g_usrsock_connections));
return idx;
}
/****************************************************************************
* Name: usrsock_active()
*
* Description:
* Find a connection structure that is the appropriate
* connection for usrsock
*
* Assumptions:
*
****************************************************************************/
FAR struct usrsock_conn_s *usrsock_active(int16_t usockid)
{
FAR struct usrsock_conn_s *conn = NULL;
while ((conn = usrsock_nextconn(conn)) != NULL)
{
if (conn->usockid == usockid)
return conn;
}
return NULL;
}
/****************************************************************************
* Name: usrsock_setup_request_callback()
****************************************************************************/
int usrsock_setup_request_callback(FAR struct usrsock_conn_s *conn,
FAR struct usrsock_reqstate_s *pstate,
FAR devif_callback_event_t event,
uint16_t flags)
{
int ret = -EBUSY;
(void)sem_init(&pstate->recvsem, 0, 0);
pstate->conn = conn;
pstate->result = -EAGAIN;
pstate->completed = false;
/* Set up the callback in the connection */
pstate->cb = devif_callback_alloc(NULL, &conn->list);
if (pstate->cb)
{
/* Set up the connection "interrupt" handler */
pstate->cb->flags = flags;
pstate->cb->priv = (FAR void *)pstate;
pstate->cb->event = event;
ret = OK;
}
return ret;
}
/****************************************************************************
* Name: usrsock_setup_data_request_callback()
****************************************************************************/
int usrsock_setup_data_request_callback(FAR struct usrsock_conn_s *conn,
FAR struct usrsock_data_reqstate_s *pstate,
FAR devif_callback_event_t event,
uint16_t flags)
{
pstate->valuelen = 0;
pstate->valuelen_nontrunc = 0;
return usrsock_setup_request_callback(conn, &pstate->reqstate, event, flags);
}
/****************************************************************************
* Name: usrsock_teardown_request_callback()
****************************************************************************/
void usrsock_teardown_request_callback(FAR struct usrsock_reqstate_s *pstate)
{
FAR struct usrsock_conn_s *conn = pstate->conn;
/* Make sure that no further events are processed */
devif_conn_callback_free(NULL, pstate->cb, &conn->list);
pstate->cb = NULL;
}
/****************************************************************************
* Name: usrsock_initialize()
*
* Description:
* Initialize the User Socket connection structures. Called once and only
* from the networking layer.
*
****************************************************************************/
void usrsock_initialize(void)
{
int i;
/* Initialize the queues */
dq_init(&g_free_usrsock_connections);
dq_init(&g_active_usrsock_connections);
sem_init(&g_free_sem, 0, 1);
for (i = 0; i < CONFIG_NET_USRSOCK_CONNS; i++)
{
FAR struct usrsock_conn_s *conn = &g_usrsock_connections[i];
/* Mark the connection closed and move it to the free list */
memset(conn, 0, sizeof(*conn));
conn->dev = NULL;
conn->usockid = -1;
conn->state = USRSOCK_CONN_STATE_UNINITIALIZED;
conn->list = NULL;
conn->flags = 0;
dq_addlast(&conn->node, &g_free_usrsock_connections);
}
/* Register /dev/usrsock character device. */
usrsockdev_register();
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+257
View File
@@ -0,0 +1,257 @@
/****************************************************************************
* net/usrsock/usrsock_connect.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t connect_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->result = -ECONNABORTED;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->result = conn->resp.result;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_connect_request
****************************************************************************/
static int do_connect_request(FAR struct usrsock_conn_s *conn,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
struct usrsock_request_connect_s req = {};
struct iovec bufs[2];
if (addrlen > UINT16_MAX)
{
addrlen = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_CONNECT;
req.usockid = conn->usockid;
req.addrlen = addrlen;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
bufs[1].iov_base = (FAR void *)addr;
bufs[1].iov_len = addrlen;
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: usrsock_connect
*
* Description:
* Perform a usrsock connection
*
* Parameters:
* psock - A reference to the socket structure of the socket to be connected
* addr The address of the remote server to connect to
* addrlen Length of address buffer
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
int usrsock_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
struct usrsock_reqstate_s state = {};
int ret;
DEBUGASSERT(conn);
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNREFUSED;
goto errout_unlock;
}
if (conn->connected &&
(conn->type == SOCK_STREAM || conn->type == SOCK_SEQPACKET))
{
/* Already connected. */
ret = -EISCONN;
goto errout_unlock;
}
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
/* Already connecting. */
ninfo("usockid=%d; socket already connecting.\n",
conn->usockid);
ret = -EALREADY;
goto errout_unlock;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_request_callback(conn, &state, connect_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Mark conn as connecting one. */
conn->state = USRSOCK_CONN_STATE_CONNECTING;
/* Send request. */
ret = do_connect_request(conn, addr, addrlen);
if (ret < 0)
{
goto errout_teardown;
}
/* Do not block on waiting for request completion if nonblocking socket. */
if (!conn->resp.inprogress || !_SS_ISNONBLOCK(psock->s_flags))
{
/* Wait for completion of request (or signal). */
if (net_lockedwait(&state.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
/* Wait interrupted, exit early. */
ret = -EINTR;
goto errout_teardown;
}
ret = state.result;
}
else
{
/* Request not completed and socket is non-blocking. */
ret = -EINPROGRESS;
}
errout_teardown:
usrsock_teardown_request_callback(&state);
errout_unlock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
/****************************************************************************
* net/usrsock/usrsock_event.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include "devif/devif.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_event
*
* Description:
* Handler for received connection events
*
****************************************************************************/
int usrsock_event(FAR struct usrsock_conn_s *conn, uint16_t events)
{
ninfo("events: %04X\n", events);
if (!events)
{
return OK;
}
net_lock();
/* Generic state updates. */
if (events & USRSOCK_EVENT_REQ_COMPLETE)
{
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
conn->state = USRSOCK_CONN_STATE_READY;
events |= USRSOCK_EVENT_CONNECT_RESP;
if (conn->resp.result == 0)
{
conn->connected = true;
}
}
}
if (events & USRSOCK_EVENT_ABORT)
{
conn->state = USRSOCK_CONN_STATE_ABORTED;
}
if (events & USRSOCK_EVENT_REMOTE_CLOSED)
{
/* After reception of remote close event, clear input/output flags. */
conn->flags &= ~(USRSOCK_EVENT_SENDTO_READY |
USRSOCK_EVENT_RECVFROM_AVAIL);
conn->flags |= USRSOCK_EVENT_REMOTE_CLOSED;
}
if ((conn->state == USRSOCK_CONN_STATE_READY ||
conn->state == USRSOCK_CONN_STATE_CONNECTING) &&
!(conn->flags & USRSOCK_EVENT_REMOTE_CLOSED))
{
if (events & USRSOCK_EVENT_SENDTO_READY)
{
conn->flags |= USRSOCK_EVENT_SENDTO_READY;
}
if (events & USRSOCK_EVENT_RECVFROM_AVAIL)
{
conn->flags |= USRSOCK_EVENT_RECVFROM_AVAIL;
}
}
/* Send events to callbacks */
(void)devif_conn_event(NULL, conn, events, conn->list);
net_unlock();
return OK;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+265
View File
@@ -0,0 +1,265 @@
/****************************************************************************
* net/usrsock/usrsock_getsockname.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t getsockname_event(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_data_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->reqstate.result = -ECONNABORTED;
pstate->valuelen = 0;
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->reqstate.result = conn->resp.result;
if (pstate->reqstate.result < 0)
{
pstate->valuelen = 0;
pstate->valuelen_nontrunc = 0;
}
else
{
pstate->valuelen = conn->resp.valuelen;
pstate->valuelen_nontrunc = conn->resp.valuelen_nontrunc;
}
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_getsockopt_request
****************************************************************************/
static int do_getsockname_request(FAR struct usrsock_conn_s *conn,
socklen_t addrlen)
{
struct usrsock_request_getsockname_s req = {};
struct iovec bufs[1];
if (addrlen > UINT16_MAX)
{
addrlen = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_GETSOCKNAME;
req.usockid = conn->usockid;
req.max_addrlen = addrlen;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Name: setup_conn_getsockopt
****************************************************************************/
static void setup_conn_getsockname(FAR struct usrsock_conn_s *conn,
FAR struct iovec *iov,
unsigned int iovcnt)
{
unsigned int i;
conn->resp.datain.iov = iov;
conn->resp.datain.pos = 0;
conn->resp.datain.total = 0;
conn->resp.datain.iovcnt = iovcnt;
for (i = 0; i < iovcnt; i++)
{
conn->resp.datain.total += iov[i].iov_len;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_getsockname
*
* Description:
* The getsockname() function retrieves the locally-bound name of the
* specified socket, stores this address in the sockaddr structure pointed
* to by the 'addr' argument, and stores the length of this address in the
* object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
*
* If the socket has not been bound to a local name, the value stored in
* the object pointed to by address is unspecified.
*
* Parameters:
* conn usrsock socket connection structure
* addr sockaddr structure to receive data [out]
* addrlen Length of sockaddr structure [in/out]
*
****************************************************************************/
int usrsock_getsockname(FAR struct usrsock_conn_s *conn,
FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
struct usrsock_data_reqstate_s state = {};
struct iovec inbufs[1];
ssize_t ret;
socklen_t outaddrlen = 0;
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_data_request_callback(
conn, &state, getsockname_event,
USRSOCK_EVENT_ABORT | USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
inbufs[0].iov_base = (FAR void *)addr;
inbufs[0].iov_len = *addrlen;
setup_conn_getsockname(conn, inbufs, ARRAY_SIZE(inbufs));
/* Request user-space daemon to close socket. */
ret = do_getsockname_request(conn, *addrlen);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.reqstate.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.reqstate.result;
DEBUGASSERT(state.valuelen <= *addrlen);
DEBUGASSERT(state.valuelen <= state.valuelen_nontrunc);
if (ret >= 0)
{
/* Store length of data that was written to 'value' buffer. */
outaddrlen = state.valuelen_nontrunc;
}
}
setup_conn_getsockname(conn, NULL, 0);
usrsock_teardown_data_request_callback(&state);
errout_unlock:
net_unlock();
*addrlen = outaddrlen;
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+275
View File
@@ -0,0 +1,275 @@
/****************************************************************************
* net/usrsock/usrsock_getsockopt.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK) && \
defined(CONFIG_NET_SOCKOPTS)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t getsockopt_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_data_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->reqstate.result = -ECONNABORTED;
pstate->valuelen = 0;
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->reqstate.result = conn->resp.result;
if (pstate->reqstate.result < 0)
{
pstate->valuelen = 0;
}
else
{
pstate->valuelen = conn->resp.valuelen;
}
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_getsockopt_request
****************************************************************************/
static int do_getsockopt_request(FAR struct usrsock_conn_s *conn, int level,
int option, socklen_t value_len)
{
struct usrsock_request_getsockopt_s req = {};
struct iovec bufs[1];
if (level < INT16_MIN || level > INT16_MAX)
{
return -EINVAL;
}
if (option < INT16_MIN || option > INT16_MAX)
{
return -EINVAL;
}
if (value_len > UINT16_MAX)
{
value_len = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_GETSOCKOPT;
req.usockid = conn->usockid;
req.level = level;
req.option = option;
req.max_valuelen = value_len;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Name: setup_conn_getsockopt
****************************************************************************/
static void setup_conn_getsockopt(FAR struct usrsock_conn_s *conn,
FAR struct iovec *iov, unsigned int iovcnt)
{
unsigned int i;
conn->resp.datain.iov = iov;
conn->resp.datain.pos = 0;
conn->resp.datain.total = 0;
conn->resp.datain.iovcnt = iovcnt;
for (i = 0; i < iovcnt; i++)
{
conn->resp.datain.total += iov[i].iov_len;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_getsockopt
*
* Description:
* getsockopt() retrieve thse value for the option specified by the
* 'option' argument for the socket specified by the 'psock' argument. If
* the size of the option value is greater than 'value_len', the value
* stored in the object pointed to by the 'value' argument will be silently
* truncated. Otherwise, the length pointed to by the 'value_len' argument
* will be modified to indicate the actual length of the'value'.
*
* The 'level' argument specifies the protocol level of the option. To
* retrieve options at the socket level, specify the level argument as
* SOL_SOCKET.
*
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* conn usrsock socket connection structure
* level Protocol level to set the option
* option identifies the option to get
* value Points to the argument value
* value_len The length of the argument value
*
****************************************************************************/
int usrsock_getsockopt(FAR struct usrsock_conn_s *conn, int level, int option,
FAR void *value, FAR socklen_t *value_len)
{
struct usrsock_data_reqstate_s state = {};
struct iovec inbufs[1];
ssize_t ret;
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_data_request_callback(
conn, &state, getsockopt_event,
USRSOCK_EVENT_ABORT | USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
inbufs[0].iov_base = (FAR void *)value;
inbufs[0].iov_len = *value_len;
setup_conn_getsockopt(conn, inbufs, ARRAY_SIZE(inbufs));
/* Request user-space daemon to close socket. */
ret = do_getsockopt_request(conn, level, option, *value_len);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.reqstate.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.reqstate.result;
DEBUGASSERT(state.valuelen <= *value_len);
if (ret >= 0)
{
/* Store length of data that was written to 'value' buffer. */
*value_len = state.valuelen;
}
}
setup_conn_getsockopt(conn, NULL, 0);
usrsock_teardown_data_request_callback(&state);
errout_unlock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK && CONFIG_NET_SOCKOPTS */
+388
View File
@@ -0,0 +1,388 @@
/****************************************************************************
* net/usrsock/usrsock_poll.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK) && \
!defined(CONFIG_DISABLE_POLL)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Data
****************************************************************************/
struct usrsock_poll_s
{
FAR struct socket *psock; /* Needed to handle loss of connection */
struct pollfd *fds; /* Needed to handle poll events */
FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
};
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t poll_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_poll_s *info = (FAR struct usrsock_poll_s *)pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
pollevent_t eventset = 0;
DEBUGASSERT(!info || (info->psock && info->fds));
if (!info)
return flags;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
/* Socket forcefully terminated. */
eventset |= (POLLERR | POLLHUP);
}
else if ((flags & USRSOCK_EVENT_CONNECT_RESP) && !conn->connected)
{
ninfo("socket connect failed.\n");
/* Non-blocking connect failed. */
eventset |= (POLLERR | POLLHUP);
}
else if (flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("remote closed.\n");
/* Remote closed. */
eventset |= (POLLHUP | POLLIN);
}
else
{
/* Check data events. */
if (flags & USRSOCK_EVENT_RECVFROM_AVAIL)
{
ninfo("socket recv avail.\n");
eventset |= POLLIN;
}
if (flags & USRSOCK_EVENT_SENDTO_READY)
{
ninfo("socket send ready.\n");
eventset |= POLLOUT;
}
}
/* Filter I/O events depending on requested events. */
eventset &= (~(POLLOUT | POLLIN) | info->fds->events);
/* POLLOUT and PULLHUP are mutually exclusive. */
if ((eventset & POLLOUT) && (eventset & POLLHUP))
{
eventset &= ~POLLOUT;
}
/* Awaken the caller of poll() is requested event occurred. */
if (eventset)
{
info->fds->revents |= eventset;
sem_post(info->fds->sem);
}
return flags;
}
/****************************************************************************
* Function: usrsock_poll
*
* Description:
* Setup to monitor events on an usrsock socket
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* fds - The structure describing the events to be monitored.
*
* Returned Value:
* 0: Success; Negated errno on failure
*
****************************************************************************/
static int usrsock_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
FAR struct usrsock_poll_s *info;
FAR struct devif_callback_s *cb;
int ret = OK;
/* Sanity check */
#ifdef CONFIG_DEBUG
if (!conn || !fds)
{
return -EINVAL;
}
#endif
/* Allocate a container to hold the poll information */
info = (FAR struct usrsock_poll_s *)kmm_malloc(sizeof(struct usrsock_poll_s));
if (!info)
{
return -ENOMEM;
}
net_lock();
/* Allocate a usrsock callback structure */
cb = devif_callback_alloc(NULL, &conn->list);
if (!cb)
{
ret = -EBUSY;
kmm_free(info); /* fds->priv not set, so we need to free info here. */
goto errout_unlock;
}
/* Initialize the poll info container */
info->psock = psock;
info->fds = fds;
info->cb = cb;
/* Initialize the callback structure. Save the reference to the info
* structure as callback private data so that it will be available during
* callback processing.
*/
cb->flags = USRSOCK_EVENT_ABORT | USRSOCK_EVENT_CONNECT_RESP |
USRSOCK_EVENT_SENDTO_READY | USRSOCK_EVENT_RECVFROM_AVAIL |
USRSOCK_EVENT_REMOTE_CLOSED;
cb->priv = (FAR void *)info;
cb->event = poll_event;
/* Save the reference in the poll info structure as fds private as well
* for use during poll teardown as well.
*/
fds->priv = (FAR void *)info;
/* Check if socket is in error state */
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
ninfo("socket %s.\n",
conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ?
"uninitialized" : "aborted");
fds->revents |= (POLLERR | POLLHUP);
}
/* Stream sockets need to be connected or connecting (or listening). */
else if ((conn->type == SOCK_STREAM || conn->type == SOCK_SEQPACKET) &&
!(conn->connected || conn->state == USRSOCK_CONN_STATE_CONNECTING))
{
ninfo("stream socket not connected and not connecting.\n");
fds->revents |= (POLLOUT | POLLIN | POLLHUP);
}
else if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("socket remote closed.\n");
/* Remote closed. */
fds->revents |= (POLLHUP | POLLIN);
}
else
{
/* Check if daemon has room for send data or has data to receive. */
if (conn->flags & USRSOCK_EVENT_SENDTO_READY)
{
ninfo("socket send ready.\n");
fds->revents |= (POLLOUT & fds->events);
}
if (conn->flags & USRSOCK_EVENT_RECVFROM_AVAIL)
{
ninfo("socket recv avail.\n");
fds->revents |= (POLLIN & fds->events);
}
}
/* Filter I/O events depending on requested events. */
fds->revents &= (~(POLLOUT | POLLIN) | info->fds->events);
/* POLLOUT and PULLHUP are mutually exclusive. */
if ((fds->revents & POLLOUT) && (fds->revents & POLLHUP))
{
fds->revents &= ~POLLOUT;
}
/* Check if any requested events are already in effect */
if (fds->revents != 0)
{
/* Yes.. then signal the poll logic */
sem_post(fds->sem);
}
errout_unlock:
net_unlock();
return ret;
}
/****************************************************************************
* Function: usrsock_pollteardown
*
* Description:
* Teardown monitoring of events on an usrsock socket
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* fds - The structure describing the events to be stopped being monitored.
*
* Returned Value:
* 0: Success; Negated errno on failure
*
****************************************************************************/
static int usrsock_pollteardown(FAR struct socket *psock,
FAR struct pollfd *fds)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
FAR struct usrsock_poll_s *info;
/* Sanity check */
#ifdef CONFIG_DEBUG
if (!conn || !fds->priv)
{
return -EINVAL;
}
#endif
/* Recover the socket descriptor poll state info from the poll structure */
info = (FAR struct usrsock_poll_s *)fds->priv;
DEBUGASSERT(info && info->fds && info->cb);
if (info)
{
/* Release the callback */
net_lock();
devif_conn_callback_free(NULL, info->cb, &conn->list);
net_unlock();
/* Release the poll/select data slot */
info->fds->priv = NULL;
/* Then free the poll info container */
kmm_free(info);
}
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_poll
*
* Description:
* The standard poll() operation redirects operations on socket descriptors
* to this function.
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* fds - The structure describing the events to be monitored.
* setup - true: Setup up the poll; false: Teardown the poll
*
* Returned Value:
* 0: Success; Negated errno on failure
*
****************************************************************************/
int usrsock_poll(FAR struct socket *psock, FAR struct pollfd *fds, bool setup)
{
if (setup)
{
return usrsock_pollsetup(psock, fds);
}
else
{
return usrsock_pollteardown(psock, fds);
}
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK && !CONFIG_DISABLE_POLL */
+485
View File
@@ -0,0 +1,485 @@
/****************************************************************************
* net/usrsock/usrsock_recvfrom.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t recvfrom_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_data_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->reqstate.result = -ECONNABORTED;
pstate->valuelen = 0;
pstate->valuelen_nontrunc = 0;
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->reqstate.result = conn->resp.result;
if (pstate->reqstate.result < 0)
{
pstate->valuelen = 0;
pstate->valuelen_nontrunc = 0;
}
else
{
pstate->valuelen = conn->resp.valuelen;
pstate->valuelen_nontrunc = conn->resp.valuelen_nontrunc;
}
if (pstate->reqstate.result >= 0 ||
pstate->reqstate.result == -EAGAIN)
{
/* After reception of data, mark input not ready. Daemon will
* send event to restore this flag. */
conn->flags &= ~USRSOCK_EVENT_RECVFROM_AVAIL;
}
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
else if (flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("remote closed.\n");
pstate->reqstate.result = -EPIPE;
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
else if (flags & USRSOCK_EVENT_RECVFROM_AVAIL)
{
ninfo("recvfrom avail.\n");
flags &= ~USRSOCK_EVENT_RECVFROM_AVAIL;
/* Stop further callbacks */
pstate->reqstate.cb->flags = 0;
pstate->reqstate.cb->priv = NULL;
pstate->reqstate.cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->reqstate.recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_recvfrom_request
****************************************************************************/
static int do_recvfrom_request(FAR struct usrsock_conn_s *conn, size_t buflen,
socklen_t addrlen)
{
struct usrsock_request_recvfrom_s req = {};
struct iovec bufs[1];
if (addrlen > UINT16_MAX)
{
addrlen = UINT16_MAX;
}
if (buflen > UINT16_MAX)
{
buflen = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_RECVFROM;
req.usockid = conn->usockid;
req.max_addrlen = addrlen;
req.max_buflen = buflen;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Name: setup_conn_recvfrom
****************************************************************************/
static void setup_conn_recvfrom(FAR struct usrsock_conn_s *conn,
FAR struct iovec *iov, unsigned int iovcnt)
{
unsigned int i;
conn->resp.datain.iov = iov;
conn->resp.datain.pos = 0;
conn->resp.datain.total = 0;
conn->resp.datain.iovcnt = iovcnt;
for (i = 0; i < iovcnt; i++)
{
conn->resp.datain.total += iov[i].iov_len;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_recvfrom
*
* Description:
* recvfrom() receives messages from a 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.
*
* Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* from Address of source (may be NULL)
* fromlen The length of the address structure
*
****************************************************************************/
ssize_t usrsock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR struct sockaddr *from, FAR socklen_t *fromlen)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
struct usrsock_data_reqstate_s state = {};
struct iovec inbufs[2];
socklen_t addrlen = 0;
socklen_t outaddrlen = 0;
ssize_t ret;
#ifdef CONFIG_NET_SOCKOPTS
struct timespec abstime;
#endif
struct timespec *ptimeo = NULL;
DEBUGASSERT(conn);
if (fromlen)
{
if (*fromlen > 0 && from == NULL)
{
return -EINVAL;
}
addrlen = *fromlen;
}
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
if (conn->type == SOCK_STREAM || conn->type == SOCK_SEQPACKET)
{
if (!conn->connected)
{
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
/* Connecting. */
ninfo("usockid=%d; socket still connecting.\n",
conn->usockid);
ret = -EAGAIN;
goto errout_unlock;
}
else
{
/* Not connected. */
ninfo("usockid=%d; socket not connected.\n",
conn->usockid);
ret = -ENOTCONN;
goto errout_unlock;
}
}
}
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
/* Non-blocking connecting. */
ninfo("usockid=%d; socket still connecting.\n",
conn->usockid);
ret = -EAGAIN;
goto errout_unlock;
}
#ifdef CONFIG_NET_SOCKOPTS
if (psock->s_rcvtimeo != 0)
{
DEBUGVERIFY(clock_gettime(CLOCK_REALTIME, &abstime));
/* Prepare timeout value for recvfrom. */
abstime.tv_sec += psock->s_rcvtimeo / DSEC_PER_SEC;
abstime.tv_nsec += (psock->s_rcvtimeo % DSEC_PER_SEC) * NSEC_PER_DSEC;
if (abstime.tv_nsec >= NSEC_PER_SEC)
{
abstime.tv_sec++;
abstime.tv_nsec -= NSEC_PER_SEC;
}
ptimeo = &abstime;
}
#endif
do
{
/* Check if remote end has closed connection. */
if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("usockid=%d; remote closed (EOF).\n", conn->usockid);
ret = 0;
goto errout_unlock;
}
/* Check if need to wait for receive data to become available. */
if (!(conn->flags & USRSOCK_EVENT_RECVFROM_AVAIL))
{
if (_SS_ISNONBLOCK(psock->s_flags))
{
/* Nothing to receive from daemon side. */
ret = -EAGAIN;
goto errout_unlock;
}
/* Wait recv to become avail. */
ret = usrsock_setup_data_request_callback(
conn, &state, recvfrom_event,
USRSOCK_EVENT_ABORT | USRSOCK_EVENT_RECVFROM_AVAIL |
USRSOCK_EVENT_REMOTE_CLOSED);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Wait for receive-avail (or abort, or timeout, or signal). */
ret = 0;
if (net_timedwait(&state.reqstate.recvsem, ptimeo) != OK)
{
ret = *get_errno_ptr();
if (ret == ETIMEDOUT)
{
ninfo("recvfrom timedout\n");
ret = -EAGAIN;
}
else if (ret == EINTR)
{
ninfo("recvfrom interrupted\n");
ret = -EINTR;
}
else
{
nerr("net_timedwait errno: %d\n", ret);
DEBUGASSERT(false);
}
}
usrsock_teardown_data_request_callback(&state);
/* Did wait timeout or got signal? */
if (ret != 0)
{
goto errout_unlock;
}
/* Was socket aborted? */
if (conn->state == USRSOCK_CONN_STATE_ABORTED)
{
ret = -EPIPE;
goto errout_unlock;
}
/* Did remote disconnect? */
if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ret = 0;
goto errout_unlock;
}
DEBUGASSERT(conn->flags & USRSOCK_EVENT_RECVFROM_AVAIL);
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_data_request_callback(
conn, &state, recvfrom_event,
USRSOCK_EVENT_ABORT | USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
inbufs[0].iov_base = (FAR void *)from;
inbufs[0].iov_len = addrlen;
inbufs[1].iov_base = (FAR void *)buf;
inbufs[1].iov_len = len;
setup_conn_recvfrom(conn, inbufs, ARRAY_SIZE(inbufs));
/* Request user-space daemon to close socket. */
ret = do_recvfrom_request(conn, len, addrlen);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.reqstate.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.reqstate.result;
DEBUGASSERT(ret <= (ssize_t)len);
DEBUGASSERT(state.valuelen <= addrlen);
DEBUGASSERT(state.valuelen <= state.valuelen_nontrunc);
if (ret >= 0)
{
/* Store length of 'from' address that was available at
* daemon-side. */
outaddrlen = state.valuelen_nontrunc;
}
}
setup_conn_recvfrom(conn, NULL, 0);
usrsock_teardown_data_request_callback(&state);
}
while (ret == -EAGAIN);
errout_unlock:
net_unlock();
if (fromlen)
{
*fromlen = outaddrlen;
}
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+426
View File
@@ -0,0 +1,426 @@
/****************************************************************************
* net/usrsock/usrsock_sendto.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t sendto_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->result = -ECONNABORTED;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->result = conn->resp.result;
if (pstate->result >= 0 || pstate->result == -EAGAIN)
{
/* After reception of data, mark input not ready. Daemon will
* send event to restore this flag. */
conn->flags &= ~USRSOCK_EVENT_SENDTO_READY;
}
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("remote closed.\n");
pstate->result = -EPIPE;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_SENDTO_READY)
{
ninfo("sendto ready.\n");
/* Do not let other waiters to claim new data. */
flags &= ~USRSOCK_EVENT_SENDTO_READY;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_sendto_request
****************************************************************************/
static int do_sendto_request(FAR struct usrsock_conn_s *conn,
FAR const void *buf, size_t buflen,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
struct usrsock_request_sendto_s req = {};
struct iovec bufs[3];
if (addrlen > UINT16_MAX)
{
addrlen = UINT16_MAX;
}
if (buflen > UINT16_MAX)
{
buflen = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_SENDTO;
req.usockid = conn->usockid;
req.addrlen = addrlen;
req.buflen = buflen;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
bufs[1].iov_base = (FAR void *)addr;
bufs[1].iov_len = addrlen;
bufs[2].iov_base = (FAR void *)buf;
bufs[2].iov_len = buflen;
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
****************************************************************************/
ssize_t usrsock_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, FAR const struct sockaddr *to,
socklen_t tolen)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
struct usrsock_reqstate_s state = {};
ssize_t ret;
#ifdef CONFIG_NET_SOCKOPTS
struct timespec abstime;
#endif
struct timespec *ptimeo = NULL;
DEBUGASSERT(conn);
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
if (conn->type == SOCK_STREAM || conn->type == SOCK_SEQPACKET)
{
if (!conn->connected)
{
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
/* Connecting. */
ninfo("usockid=%d; socket still connecting.\n",
conn->usockid);
ret = -EAGAIN;
goto errout_unlock;
}
else
{
/* Not connected. */
ret = -ENOTCONN;
goto errout_unlock;
}
}
if (to || tolen)
{
/* Address provided for connection-mode socket */
ret = -EISCONN;
goto errout_unlock;
}
}
if (conn->state == USRSOCK_CONN_STATE_CONNECTING)
{
/* Non-blocking connecting. */
ninfo("usockid=%d; socket still connecting.\n", conn->usockid);
ret = -EAGAIN;
goto errout_unlock;
}
#ifdef CONFIG_NET_SOCKOPTS
if (psock->s_sndtimeo != 0)
{
DEBUGVERIFY(clock_gettime(CLOCK_REALTIME, &abstime));
/* Prepare timeout value for sendto. */
abstime.tv_sec += psock->s_sndtimeo / DSEC_PER_SEC;
abstime.tv_nsec += (psock->s_sndtimeo % DSEC_PER_SEC) * NSEC_PER_DSEC;
if (abstime.tv_nsec >= NSEC_PER_SEC)
{
abstime.tv_sec++;
abstime.tv_nsec -= NSEC_PER_SEC;
}
ptimeo = &abstime;
}
#endif
do
{
/* Check if remote end has closed connection. */
if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ninfo("usockid=%d; remote closed.\n", conn->usockid);
ret = -EPIPE;
goto errout_unlock;
}
/* Check if need to wait for send to become ready. */
if (!(conn->flags & USRSOCK_EVENT_SENDTO_READY))
{
if (_SS_ISNONBLOCK(psock->s_flags))
{
/* Send busy at daemon side. */
ret = -EAGAIN;
goto errout_unlock;
}
/* Wait send to become ready. */
ret = usrsock_setup_request_callback(conn, &state, sendto_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_SENDTO_READY |
USRSOCK_EVENT_REMOTE_CLOSED);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Wait for send-ready (or abort, or timeout, or signal). */
ret = 0;
if (net_timedwait(&state.recvsem, ptimeo) != OK)
{
ret = *get_errno_ptr();
if (ret == ETIMEDOUT)
{
ninfo("sendto timedout\n");
ret = -EAGAIN;
}
else if (ret == EINTR)
{
ninfo("sendto interrupted\n");
ret = -EINTR;
}
else
{
nerr("net_timedwait errno: %d\n", ret);
DEBUGASSERT(false);
}
}
usrsock_teardown_request_callback(&state);
/* Did wait timeout or got signal? */
if (ret != 0)
{
goto errout_unlock;
}
/* Was socket aborted? */
if (conn->state == USRSOCK_CONN_STATE_ABORTED)
{
ret = -EPIPE;
goto errout_unlock;
}
/* Did remote disconnect? */
if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
{
ret = -EPIPE;
goto errout_unlock;
}
DEBUGASSERT(conn->flags & USRSOCK_EVENT_SENDTO_READY);
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_request_callback(conn, &state, sendto_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Request user-space daemon to close socket. */
ret = do_sendto_request(conn, buf, len, to, tolen);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.result;
DEBUGASSERT(ret <= (ssize_t)len);
}
usrsock_teardown_request_callback(&state);
}
while (ret == -EAGAIN);
errout_unlock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK */
+230
View File
@@ -0,0 +1,230 @@
/****************************************************************************
* net/usrsock/usrsock_setsockopt.c
*
* Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
* Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK) && \
defined(CONFIG_NET_SOCKOPTS)
#include <stdint.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arch/irq.h>
#include <sys/socket.h>
#include <nuttx/net/net.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/kmalloc.h>
#include "socket/socket.h"
#include "usrsock/usrsock.h"
/****************************************************************************
* Private Functions
****************************************************************************/
static uint16_t setsockopt_event(FAR struct net_driver_s *dev, FAR void *pvconn,
FAR void *pvpriv, uint16_t flags)
{
FAR struct usrsock_reqstate_s *pstate = pvpriv;
FAR struct usrsock_conn_s *conn = pvconn;
if (flags & USRSOCK_EVENT_ABORT)
{
ninfo("socket aborted.\n");
pstate->result = -ECONNABORTED;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
else if (flags & USRSOCK_EVENT_REQ_COMPLETE)
{
ninfo("request completed.\n");
pstate->result = conn->resp.result;
/* Stop further callbacks */
pstate->cb->flags = 0;
pstate->cb->priv = NULL;
pstate->cb->event = NULL;
/* Wake up the waiting thread */
sem_post(&pstate->recvsem);
}
return flags;
}
/****************************************************************************
* Name: do_setsockopt_request
****************************************************************************/
static int do_setsockopt_request(FAR struct usrsock_conn_s *conn,
int level, int option, FAR const void *value,
socklen_t value_len)
{
struct usrsock_request_setsockopt_s req = {};
struct iovec bufs[2];
if (level < INT16_MIN || level > INT16_MAX)
{
return -EINVAL;
}
if (option < INT16_MIN || option > INT16_MAX)
{
return -EINVAL;
}
if (value_len > UINT16_MAX)
{
value_len = UINT16_MAX;
}
/* Prepare request for daemon to read. */
req.head.reqid = USRSOCK_REQUEST_SETSOCKOPT;
req.usockid = conn->usockid;
req.level = level;
req.option = option;
req.valuelen = value_len;
bufs[0].iov_base = (FAR void *)&req;
bufs[0].iov_len = sizeof(req);
bufs[1].iov_base = (FAR void *)value;
bufs[1].iov_len = req.valuelen;
return usrsockdev_do_request(conn, bufs, ARRAY_SIZE(bufs));
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Function: usrsock_setsockopt
*
* Description:
* psock_setsockopt() sets the option specified by the 'option' argument,
* at the protocol level specified by the 'level' argument, to the value
* pointed to by the 'value' argument for the socket on the 'psock' argument.
*
* The 'level' argument specifies the protocol level of the option. To set
* options at the socket level, specify the level argument as SOL_SOCKET.
*
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* conn usrsock socket connection structure
* level Protocol level to set the option
* option identifies the option to set
* value Points to the argument value
* value_len The length of the argument value
*
****************************************************************************/
int usrsock_setsockopt(FAR struct usrsock_conn_s *conn, int level, int option,
FAR const void *value, FAR socklen_t value_len)
{
struct usrsock_reqstate_s state = {};
ssize_t ret;
DEBUGASSERT(conn);
net_lock();
if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
conn->state == USRSOCK_CONN_STATE_ABORTED)
{
/* Invalid state or closed by daemon. */
ninfo("usockid=%d; connect() with uninitialized usrsock.\n",
conn->usockid);
ret = (conn->state == USRSOCK_CONN_STATE_ABORTED) ? -EPIPE : -ECONNRESET;
goto errout_unlock;
}
/* Set up event callback for usrsock. */
ret = usrsock_setup_request_callback(conn, &state, setsockopt_event,
USRSOCK_EVENT_ABORT |
USRSOCK_EVENT_REQ_COMPLETE);
if (ret < 0)
{
nwarn("usrsock_setup_request_callback failed: %d\n", ret);
goto errout_unlock;
}
/* Request user-space daemon to close socket. */
ret = do_setsockopt_request(conn, level, option, value, value_len);
if (ret >= 0)
{
/* Wait for completion of request. */
while (net_lockedwait(&state.recvsem) != OK)
{
DEBUGASSERT(*get_errno_ptr() == EINTR);
}
ret = state.result;
}
usrsock_teardown_request_callback(&state);
errout_unlock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET && CONFIG_NET_USRSOCK && CONFIG_NET_SOCKOPTS */

Some files were not shown because too many files have changed in this diff Show More