summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-01-24 15:19:50 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-01-24 15:19:50 -0600
commit72ceb9b6815c222ce08a01e22bdc97c9f474d196 (patch)
treed422f378589658e6ff71ccff2e4e0a01097adddc
parent4c3c2dd8df25d28fc4a5d6c089649041dcdba74e (diff)
downloadnuttx-72ceb9b6815c222ce08a01e22bdc97c9f474d196.tar.gz
nuttx-72ceb9b6815c222ce08a01e22bdc97c9f474d196.tar.bz2
nuttx-72ceb9b6815c222ce08a01e22bdc97c9f474d196.zip
Hook local socket functions into socket creation and close logic
-rw-r--r--nuttx/net/local/local.h242
-rw-r--r--nuttx/net/net_initialize.c7
-rw-r--r--nuttx/net/socket/net_close.c145
-rw-r--r--nuttx/net/socket/socket.c160
4 files changed, 486 insertions, 68 deletions
diff --git a/nuttx/net/local/local.h b/nuttx/net/local/local.h
new file mode 100644
index 000000000..5d8aec50b
--- /dev/null
+++ b/nuttx/net/local/local.h
@@ -0,0 +1,242 @@
+/****************************************************************************
+ * net/local/loal.h
+ *
+ * Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 __NET_LOCAL_LOCAL_H
+#define __NET_LOCAL_LOCAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <queue.h>
+#include <stdint.h>
+
+#ifdef CONFIG_NET_LOCAL
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Representation of a local connection */
+
+struct local_conn_s
+{
+ dq_entry_t node; /* Supports a doubly linked list */
+ int16_t fd; /* File descriptor of underlying file */
+ uint8_t crefs; /* Reference counts on this instance */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+# define EXTERN extern "C"
+extern "C"
+{
+#else
+# define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct sockaddr; /* Forward reference */
+struct socket; /* Forward reference */
+
+/****************************************************************************
+ * Name: local_initialize
+ *
+ * Description:
+ * Initialize the local connection structures. Called once and only from
+ * the UIP layer.
+ *
+ ****************************************************************************/
+
+void local_initialize(void);
+
+/****************************************************************************
+ * Name: local_alloc
+ *
+ * Description:
+ * Allocate a new, uninitialized local connection structure. This is
+ * normally something done by the implementation of the socket() API
+ *
+ ****************************************************************************/
+
+FAR struct local_conn_s *local_alloc(void);
+
+/****************************************************************************
+ * Name: local_free
+ *
+ * Description:
+ * Free a local connection structure that is no longer in use. This should
+ * be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void local_free(FAR struct local_conn_s *conn);
+
+/****************************************************************************
+ * Name: local_bind
+ *
+ * Description:
+ * This function implements the low-level parts of the standard local
+ * bind()operation.
+ *
+ ****************************************************************************/
+
+int local_bind(FAR struct local_conn_s *conn,
+ FAR const struct sockaddr *addr);
+
+/****************************************************************************
+ * Name: local_connect
+ *
+ * Description:
+ * This function sets up a new local connection. The function will
+ * automatically allocate an unused local port for the new
+ * connection. However, another port can be chosen by using the
+ * local_bind() call, after the local_connect() function has been
+ * called.
+ *
+ * This function is called as part of the implementation of sendto
+ * and recvfrom.
+ *
+ * Input Parameters:
+ * conn - A reference to local connection structure
+ * addr - The address of the remote host.
+ *
+ * Assumptions:
+ * This function is called user code. Interrupts may be enabled.
+ *
+ ****************************************************************************/
+
+int local_connect(FAR struct local_conn_s *conn,
+ FAR const struct sockaddr *addr);
+
+/****************************************************************************
+ * Name: psock_local_send
+ *
+ * Description:
+ * Send a local packet as a stream.
+ *
+ * Parameters:
+ * psock An instance of the internal socket structure.
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags
+ *
+ * Return:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately (see send() for the
+ * list of errno numbers).
+ *
+ ****************************************************************************/
+
+ssize_t psock_local_send(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags);
+
+/****************************************************************************
+ * Function: psock_sendto
+ *
+ * Description:
+ * Send a local packet as a datagram.
+ *
+ * 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
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error,
+ * -1 is returned, and errno is set appropriately (see sendto() for the
+ * list of errno numbers).
+ *
+ ****************************************************************************/
+
+ssize_t psock_local_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags, FAR const struct sockaddr *to,
+ socklen_t tolen);
+
+/****************************************************************************
+ * Function: psock_recvfrom
+ *
+ * Description:
+ * recvfrom() receives messages from a local socket, and may be used to
+ * receive data on a socket whether or not it is connection-oriented.
+ *
+ * If from is not NULL, and the underlying protocol provides the source
+ * address, this source address is filled in. The argument fromlen
+ * initialized to the size of the buffer associated with from, and modified
+ * on return to indicate the actual size of the address stored there.
+ *
+ * Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. If no data is
+ * available to be received and the peer has performed an orderly shutdown,
+ * recv() will return 0. Otherwise, on errors, -1 is returned, and errno
+ * is set appropriately (see receivefrom for the complete list).
+ *
+ ****************************************************************************/
+
+ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_LOCAL */
+#endif /* __NET_LOCAL_LOCAL_H */
diff --git a/nuttx/net/net_initialize.c b/nuttx/net/net_initialize.c
index 371b30987..469270577 100644
--- a/nuttx/net/net_initialize.c
+++ b/nuttx/net/net_initialize.c
@@ -53,6 +53,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
#include "igmp/igmp.h"
#include "route/route.h"
#include "utils/utils.h"
@@ -128,6 +129,12 @@ void net_initialize(void)
pkt_initialize();
#endif
+#ifdef CONFIG_NET_UDP
+ /* Initialize the local, "Unix domain" socket support */
+
+ local_initialize();
+#endif
+
#ifdef CONFIG_NET_TCP
/* Initialize the listening port structures */
diff --git a/nuttx/net/socket/net_close.c b/nuttx/net/socket/net_close.c
index a2ef7e91f..d58d42829 100644
--- a/nuttx/net/socket/net_close.c
+++ b/nuttx/net/socket/net_close.c
@@ -63,6 +63,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
@@ -452,6 +453,45 @@ static inline int netclose_disconnect(FAR struct socket *psock)
#endif /* CONFIG_NET_TCP */
/****************************************************************************
+ * Function: local_close
+ *
+ * Description:
+ * Performs the close operation on a local socket instance
+ *
+ * Parameters:
+ * psock Socket instance
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_LOCAL
+static void local_close(FAR struct socket *psock)
+{
+ FAR struct local_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)
+ {
+ conn->crefs = 0;
+ local_free(conn);
+ }
+ else
+ {
+ /* No.. Just decrement the reference count */
+
+ conn->crefs--;
+ }
+}
+#endif /* CONFIG_NET_LOCAL */
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -519,63 +559,102 @@ int psock_close(FAR struct socket *psock)
break;
#endif
-#ifdef CONFIG_NET_TCP
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
{
- FAR struct tcp_conn_s *conn = psock->s_conn;
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
+#endif
+ {
+ /* Release our reference to the local connection structure */
- /* Is this the last reference to the connection structure (there
- * could be more if the socket was dup'ed).
- */
+ local_close(psock);
+ }
+#endif /* CONFIG_NET_LOCAL */
- if (conn->crefs <= 1)
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
{
- /* Yes... then perform the disconnection now */
+ FAR struct tcp_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).
+ */
- tcp_unlisten(conn); /* No longer accepting connections */
- conn->crefs = 0; /* Discard our reference to the connection */
- err = netclose_disconnect(psock); /* Break any current connections */
- if (err < 0)
+ if (conn->crefs <= 1)
{
- /* This would normally occur only if there is a timeout
- * from a lingering close.
- */
+ /* Yes... then perform the disconnection now */
+
+ tcp_unlisten(conn); /* No longer accepting connections */
+ conn->crefs = 0; /* Discard our reference to the connection */
+
+ /* Break any current connections */
+
+ err = netclose_disconnect(psock);
+ if (err < 0)
+ {
+ /* This would normally occur only if there is a
+ * timeout from a lingering close.
+ */
- goto errout_with_psock;
+ goto errout_with_psock;
+ }
}
- }
- else
- {
- /* No.. Just decrement the reference count */
+ else
+ {
+ /* No.. Just decrement the reference count */
- conn->crefs--;
+ conn->crefs--;
+ }
}
+#endif /* CONFIG_NET_TCP */
}
break;
#endif
-#ifdef CONFIG_NET_UDP
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
case SOCK_DGRAM:
{
- FAR struct udp_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)
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ if (psock->s_domain == PF_LOCAL)
+#endif
{
- /* Yes... free the connection structure */
+ /* Release our reference to the local connection structure */
- conn->crefs = 0; /* No more references on the connection */
- udp_free(psock->s_conn); /* Free uIP resources */
+ local_close(psock);
}
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
else
+#endif
{
- /* No.. Just decrement the reference count */
+ FAR struct udp_conn_s *conn = psock->s_conn;
- conn->crefs--;
+ /* Is this the last reference to the connection structure
+ * (there could be more if the socket was dup'ed).
+ */
+
+ if (conn->crefs <= 1)
+ {
+ /* Yes... free the connection structure */
+
+ conn->crefs = 0;
+ udp_free(psock->s_conn);
+ }
+ else
+ {
+ /* No.. Just decrement the reference count */
+
+ conn->crefs--;
+ }
}
+#endif /* CONFIG_NET_UDP */
}
break;
#endif
diff --git a/nuttx/net/socket/socket.c b/nuttx/net/socket/socket.c
index 1ce2e0890..8e00143ca 100644
--- a/nuttx/net/socket/socket.c
+++ b/nuttx/net/socket/socket.c
@@ -51,6 +51,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
/****************************************************************************
* Public Functions
@@ -96,7 +97,10 @@
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
+#ifdef CONFIG_NET_LOCAL
bool ipdomain = false;
+#endif
+ bool dgramok = false;
int err;
/* Only PF_INET, PF_INET6 or PF_PACKET domains supported */
@@ -105,13 +109,25 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
#ifdef CONFIG_NET_IPv4
case PF_INET:
+#ifdef CONFIG_NET_LOCAL
ipdomain = true;
+#endif
+ dgramok = true;
break;
#endif
#ifdef CONFIG_NET_IPv6
case PF_INET6:
+#ifdef CONFIG_NET_LOCAL
ipdomain = true;
+#endif
+ dgramok = true;
+ break;
+#endif
+
+#ifdef CONFIG_NET_LOCAL
+ case PF_LOCAL:
+ dgramok = true;
break;
#endif
@@ -131,7 +147,7 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
#ifdef CONFIG_NET_TCP
case SOCK_STREAM:
- if ((protocol != 0 && protocol != IPPROTO_TCP) || !ipdomain)
+ if ((protocol != 0 && protocol != IPPROTO_TCP) || !dgramok)
{
err = EPROTONOSUPPORT;
goto errout;
@@ -142,7 +158,7 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
#ifdef CONFIG_NET_UDP
case SOCK_DGRAM:
- if ((protocol != 0 && protocol != IPPROTO_UDP) || !ipdomain)
+ if ((protocol != 0 && protocol != IPPROTO_UDP) || !dgramok)
{
err = EPROTONOSUPPORT;
goto errout;
@@ -153,7 +169,7 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
#ifdef CONFIG_NET_PKT
case SOCK_RAW:
- if (ipdomain)
+ if (dgramok)
{
err = EPROTONOSUPPORT;
goto errout;
@@ -185,56 +201,130 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
err = ENOMEM; /* Assume failure to allocate connection instance */
switch (type)
{
-#ifdef CONFIG_NET_TCP
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
{
- /* Allocate the TCP connection structure and save in the new
- * socket instance.
- */
-
- FAR struct tcp_conn_s *conn = tcp_alloc(domain);
- if (!conn)
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
+#endif
{
- /* Failed to reserve a connection structure */
+ /* Allocate the TCP connection structure */
+
+ FAR struct tcp_conn_s *conn = tcp_alloc(domain);
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ goto errout; /* With err == ENFILE or ENOMEM */
+ }
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
- goto errout; /* With err == ENFILE or ENOMEM */
+ DEBUGASSERT(conn->crefs == 0);
+ conn->crefs = 1;
+
+ /* Save the pre-allocated connection in the socket structure */
+
+ psock->s_conn = conn;
}
+#endif /* CONFIG_NET_TCP */
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ else
+#endif
+ {
+ /* Allocate the local connection structure */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ FAR struct local_conn_s *conn = local_alloc();
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ goto errout; /* With err == ENFILE or ENOMEM */
+ }
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+ conn->crefs = 1;
+
+ /* Save the pre-allocated connection in the socket structure */
+
+ psock->s_conn = conn;
+ }
+#endif /* CONFIG_NET_LOCAL */
}
break;
#endif
-#ifdef CONFIG_NET_UDP
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
case SOCK_DGRAM:
{
- /* Allocate the UDP connection structure and save in the new
- * socket instance.
- */
-
- FAR struct udp_conn_s *conn = udp_alloc(domain);
- if (!conn)
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
+#endif
{
- /* Failed to reserve a connection structure */
+ /* Allocate the UDP connection structure */
+
+ FAR struct udp_conn_s *conn = udp_alloc(domain);
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ goto errout; /* With err == ENFILE or ENOMEM */
+ }
- goto errout; /* With err == ENFILE or ENOMEM */
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+ conn->crefs = 1;
+
+ /* Save the pre-allocated connection in the socket structure */
+
+ psock->s_conn = conn;
}
+#endif /* CONFIG_NET_UDP */
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ else
+#endif
+ {
+ /* Allocate the local connection structure */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ FAR struct local_conn_s *conn = local_alloc();
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ goto errout; /* With err == ENFILE or ENOMEM */
+ }
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be increment only if the socket is
+ * dup'ed
+ */
+
+ DEBUGASSERT(conn->crefs == 0);
+ conn->crefs = 1;
+
+ /* Save the pre-allocated connection in the socket structure */
+
+ psock->s_conn = conn;
+ }
+#endif /* CONFIG_NET_LOCAL */
}
break;
#endif