mirror of
https://github.com/apache/nuttx.git
synced 2026-09-26 09:54:24 +08:00
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:
committed by
Gregory Nutt
parent
c999519bf2
commit
cd3c9634c8
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
Reference in New Issue
Block a user