summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/ChangeLog.txt3
-rw-r--r--apps/examples/Kconfig1
-rw-r--r--apps/examples/Make.defs4
-rw-r--r--apps/examples/Makefile4
-rw-r--r--apps/examples/README.txt14
-rw-r--r--apps/examples/ustream/.gitignore14
-rw-r--r--apps/examples/ustream/Kconfig19
-rw-r--r--apps/examples/ustream/Makefile173
-rw-r--r--apps/examples/ustream/ustream.h53
-rw-r--r--apps/examples/ustream/ustream_client.c191
-rw-r--r--apps/examples/ustream/ustream_server.c212
-rw-r--r--apps/nshlib/nsh.h16
-rw-r--r--apps/nshlib/nsh_netinit.c5
-rwxr-xr-xnuttx/ChangeLog3
-rw-r--r--nuttx/arch/sim/src/Makefile2
-rw-r--r--nuttx/arch/sim/src/nuttx-names.dat2
-rw-r--r--nuttx/arch/sim/src/up_idle.c2
-rw-r--r--nuttx/arch/sim/src/up_initialize.c2
-rw-r--r--nuttx/include/nuttx/net/netconfig.h10
-rw-r--r--nuttx/net/Kconfig1
-rw-r--r--nuttx/net/Makefile3
-rw-r--r--nuttx/net/README.txt1
-rw-r--r--nuttx/net/devif/devif_poll.c4
-rw-r--r--nuttx/net/local/Kconfig19
-rw-r--r--nuttx/net/local/Make.defs49
-rw-r--r--nuttx/net/local/local.h549
-rw-r--r--nuttx/net/local/local_accept.c224
-rw-r--r--nuttx/net/local/local_bind.c119
-rw-r--r--nuttx/net/local/local_conn.c136
-rw-r--r--nuttx/net/local/local_connect.c305
-rw-r--r--nuttx/net/local/local_fifo.c407
-rw-r--r--nuttx/net/local/local_listen.c149
-rw-r--r--nuttx/net/local/local_recvfrom.c256
-rw-r--r--nuttx/net/local/local_recvutils.c248
-rw-r--r--nuttx/net/local/local_release.c129
-rw-r--r--nuttx/net/local/local_send.c97
-rw-r--r--nuttx/net/local/local_sendpacket.c166
-rw-r--r--nuttx/net/local/local_sendto.c84
-rw-r--r--nuttx/net/net_initialize.c7
-rw-r--r--nuttx/net/netdev/netdev_register.c2
-rw-r--r--nuttx/net/pkt/pkt.h2
-rw-r--r--nuttx/net/pkt/pkt_conn.c3
-rw-r--r--nuttx/net/socket/Make.defs7
-rw-r--r--nuttx/net/socket/accept.c310
-rw-r--r--nuttx/net/socket/bind.c95
-rw-r--r--nuttx/net/socket/connect.c72
-rw-r--r--nuttx/net/socket/listen.c66
-rw-r--r--nuttx/net/socket/net_close.c157
-rw-r--r--nuttx/net/socket/recvfrom.c121
-rw-r--r--nuttx/net/socket/send.c25
-rw-r--r--nuttx/net/socket/sendto.c12
-rw-r--r--nuttx/net/socket/socket.c323
-rw-r--r--nuttx/net/tcp/Make.defs2
-rw-r--r--nuttx/net/tcp/tcp.h43
-rw-r--r--nuttx/net/tcp/tcp_accept.c359
55 files changed, 4833 insertions, 449 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 9be1899a3..4f8ed9288 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -1199,3 +1199,6 @@
* apps/interpreters/micropython: Add math library defines for nan(),
copysign(), and trunc() functions. From Brennan Ashton (2015-01-26).
+ * apps/examples/ustreadm: Add a simple test of Unix domain sockets
+ (2014-01-27).
+
diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig
index 6714e6351..329077071 100644
--- a/apps/examples/Kconfig
+++ b/apps/examples/Kconfig
@@ -75,6 +75,7 @@ source "$APPSDIR/examples/discover/Kconfig"
source "$APPSDIR/examples/webserver/Kconfig"
source "$APPSDIR/examples/usbserial/Kconfig"
source "$APPSDIR/examples/usbterm/Kconfig"
+source "$APPSDIR/examples/ustream/Kconfig"
source "$APPSDIR/examples/watchdog/Kconfig"
source "$APPSDIR/examples/wget/Kconfig"
source "$APPSDIR/examples/wgetjson/Kconfig"
diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs
index 2c23a68e6..520ba8cc0 100644
--- a/apps/examples/Make.defs
+++ b/apps/examples/Make.defs
@@ -318,6 +318,10 @@ ifeq ($(CONFIG_EXAMPLES_USBTERM),y)
CONFIGURED_APPS += examples/usbterm
endif
+ifeq ($(CONFIG_EXAMPLES_USTREAM),y)
+CONFIGURED_APPS += examples/ustream
+endif
+
ifeq ($(CONFIG_EXAMPLES_WATCHDOG),y)
CONFIGURED_APPS += examples/watchdog
endif
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index 8d39c1a5f..ddcea687c 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -45,7 +45,7 @@ SUBDIRS += nxffs nxflat nxhello nximage nxlines nxtext ostest pashello pipe
SUBDIRS += poll posix_spawn pwm qencoder random relays rgmp romfs sendmail
SUBDIRS += serialblaster serloop serialrx slcd smart smart_test tcpecho
SUBDIRS += telnetd thttpd tiff timer touchscreen udp usbserial usbterm
-SUBDIRS += watchdog webserver wget wgetjson xmlrpc
+SUBDIRS += ustream watchdog webserver wget wgetjson xmlrpc
# Sub-directories that might need context setup. Directories may need
# context setup for a variety of reasons, but the most common is because
@@ -59,7 +59,7 @@ CNTXTDIRS += djoystick flash_test ftpd hello helloxx i2schar json keypadtest
CNTXTDIRS += ltdc modbus lcdrw mtdpart mtdrwb netpkt nettest nx nxhello
CNTXTDIRS += nximage nxlines nxtext nrf24l01_term ostest random relays
CNTXTDIRS += qencoder serialblasters lcd serialrx smart_test tcpecho telnetd
-CNTXTDIRS += tiff timer touchscreen usbterm watchdog wgetjson
+CNTXTDIRS += tiff timer touchscreen usbterm ustream watchdog wgetjson
endif
all: nothing
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index 13586419b..c9436df91 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -1976,6 +1976,20 @@ examples/usbterm
Prolifics emulation (not defined) and the CDC serial implementation
(when defined). CONFIG_USBDEV_TRACE_INITIALIDSET.
+examples/ustream
+^^^^^^^^^^^^^^^^
+
+ This is the same test as examples/nettest, but using Unix domain
+ sockets.
+
+ Dependencies:
+ CONFIG_NET_LOCAL - Depends on support for Unix domain sockets
+
+ Configuration:
+ CONFIG_EXAMPLES_USTREAM - Enables the Unix domain socket example.
+ CONFIG_EXAMPLES_USTREAM_ADDR - Specifics the Unix domain address.
+ Default "/var/fifo/fifo".
+
examples/watchdog
^^^^^^^^^^^^^^^^^
diff --git a/apps/examples/ustream/.gitignore b/apps/examples/ustream/.gitignore
new file mode 100644
index 000000000..52ae9aa90
--- /dev/null
+++ b/apps/examples/ustream/.gitignore
@@ -0,0 +1,14 @@
+/Make.dep
+/.depend
+/.built
+/*.asm
+/*.obj
+/*.rel
+/*.lst
+/*.sym
+/*.adb
+/*.lib
+/*.src
+/*.hobj
+/*.exe
+/*.dSYM
diff --git a/apps/examples/ustream/Kconfig b/apps/examples/ustream/Kconfig
new file mode 100644
index 000000000..5731a7c5a
--- /dev/null
+++ b/apps/examples/ustream/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config EXAMPLES_USTREAM
+ bool "Unix domain socket example"
+ default n
+ depends on NET_LOCAL
+ ---help---
+ Enable the Unix domain SOCK_STREAM test example
+
+if EXAMPLES_USTREAM
+
+config EXAMPLES_USTREAM_ADDR
+ string "Unix domain address"
+ default "/var/fifo/fifo"
+
+endif # EXAMPLES_USTREAM
diff --git a/apps/examples/ustream/Makefile b/apps/examples/ustream/Makefile
new file mode 100644
index 000000000..b5570cbe3
--- /dev/null
+++ b/apps/examples/ustream/Makefile
@@ -0,0 +1,173 @@
+############################################################################
+# examples/ustream/Makefile
+#
+# 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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# Basic Unix domain networking test
+
+SERVER_ASRCS =
+SERVER_AOBJS = $(SERVER_ASRCS:.S=$(OBJEXT))
+
+SERVER_CSRCS =
+SERVER_COBJS = $(SERVER_CSRCS:.c=$(OBJEXT))
+
+SERVER_MAINSRC = ustream_server.c
+SERVER_MAINOBJ = $(SERVER_MAINSRC:.c=$(OBJEXT))
+
+SERVER_SRCS = $(SERVER_ASRCS) $(SERVER_CSRCS) $(SERVER_MAINSRC)
+SERVER_OBJS = $(SERVER_AOBJS) $(SERVER_COBJS)
+
+SERVER_PROGNAME = server$(EXEEXT)
+
+SERVER_APPNAME = server
+SERVER_PRIORITY = SCHED_PRIORITY_DEFAULT
+SERVER_STACKSIZE = 2048
+
+CLIENT_ASRCS =
+CLIENT_AOBJS = $(CLIENT_ASRCS:.S=$(OBJEXT))
+
+CLIENT_CSRCS =
+CLIENT_COBJS = $(CLIENT_CSRCS:.c=$(OBJEXT))
+
+CLIENT_MAINSRC = ustream_client.c
+CLIENT_MAINOBJ = $(CLIENT_MAINSRC:.c=$(OBJEXT))
+
+CLIENT_SRCS = $(CLIENT_ASRCS) $(CLIENT_CSRCS) $(CLIENT_MAINSRC)
+CLIENT_OBJS = $(CLIENT_AOBJS) $(CLIENT_COBJS)
+
+CLIENT_PROGNAME = server$(EXEEXT)
+
+CLIENT_APPNAME = client
+CLIENT_PRIORITY = SCHED_PRIORITY_DEFAULT
+CLIENT_STACKSIZE = 2048
+
+AOBJS = $(CLIENT_AOBJS) $(SERVER_AOBJS)
+COBJS = $(CLIENT_COBJS) $(CLIENT_MAINOBJ) $(SERVER_COBJS) $(SERVER_MAINOBJ)
+
+SRCS = $(CLIENT_SRCS) $(SERVER_SRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifneq ($(CONFIG_BUILD_KERNEL),y)
+ SERVER_OBJS += $(SERVER_MAINOBJ)
+ CLIENT_OBJS += $(CLIENT_MAINOBJ)
+endif
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ USTREAM_BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ USTREAM_BIN = ..\\..\\libapps$(LIBEXT)
+else
+ USTREAM_BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ifeq ($(WINTOOL),y)
+ INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
+else
+ INSTALL_DIR = $(BIN_DIR)
+endif
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ $(call ARCHIVE, $(USTREAM_BIN), $(OBJS))
+ $(Q) touch .built
+
+ifeq ($(CONFIG_BUILD_KERNEL),y)
+
+$(BIN_DIR)$(DELIM)$(CLIENT_PROGNAME): $(CLIENT_OBJS)
+ @echo "LD: $(CLIENT_PROGNAME)"
+ $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(CLIENT_PROGNAME) $(ARCHCRT0OBJ) $(CLIENT_MAINOBJ) $(LDLIBS)
+ $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(CLIENT_PROGNAME)
+
+$(BIN_DIR)$(DELIM)$(SERVER_PROGNAME): $(OBJS) $(SERVER_MAINOBJ)
+ @echo "LD: $(SERVER_PROGNAME)"
+ $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(SERVER_PROGNAME) $(ARCHCRT0OBJ) $(SERVER_MAINOBJ) $(LDLIBS)
+ $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(SERVER_PROGNAME)
+
+install: $(BIN_DIR)$(DELIM)$(CLIENT_PROGNAME) $(BIN_DIR)$(DELIM)$(SERVER_PROGNAME)
+
+else
+install:
+
+endif
+
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+
+$(BUILTIN_REGISTRY)$(DELIM)$(CLIENT_APPNAME)_main.bdat: $(DEPCONFIG) Makefile
+ $(call REGISTER,$(CLIENT_APPNAME),$(CLIENT_PRIORITY),$(CLIENT_STACKSIZE),$(CLIENT_APPNAME)_main)
+
+$(BUILTIN_REGISTRY)$(DELIM)$(SERVER_APPNAME)_main.bdat: $(DEPCONFIG) Makefile
+ $(call REGISTER,$(SERVER_APPNAME),$(SERVER_PRIORITY),$(SERVER_STACKSIZE),$(SERVER_APPNAME)_main)
+
+context: $(BUILTIN_REGISTRY)$(DELIM)$(CLIENT_APPNAME)_main.bdat $(BUILTIN_REGISTRY)$(DELIM)$(SERVER_APPNAME)_main.bdat
+
+else
+
+context:
+
+endif
+
+.depend: Makefile $(SERVER_SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SERVER_SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ $(call DELFILE, .built)
+ $(call DELFILE, *.dSYM)
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+-include Make.dep
+
diff --git a/apps/examples/ustream/ustream.h b/apps/examples/ustream/ustream.h
new file mode 100644
index 000000000..2d4533c05
--- /dev/null
+++ b/apps/examples/ustream/ustream.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ * examples/ustream/ustream.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 __APPS_EXAMPLES_USTREAM_H
+#define __APPS_EXAMPLES_USTREAM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SENDSIZE 4096
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __APPS_EXAMPLES_USTREAM_H */
diff --git a/apps/examples/ustream/ustream_client.c b/apps/examples/ustream/ustream_client.c
new file mode 100644
index 000000000..797a5a18c
--- /dev/null
+++ b/apps/examples/ustream/ustream_client.c
@@ -0,0 +1,191 @@
+/****************************************************************************
+ * examples/ustream/ustream_client.c
+ *
+ * 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 Gregory Nutt 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>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ustream.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_KERNEL
+int main(int argc, FAR char *argv[])
+#else
+int client_main(int argc, char *argv[])
+#endif
+{
+ struct sockaddr_un myaddr;
+ socklen_t addrlen;
+ FAR char *outbuf;
+ FAR char *inbuf;
+ int sockfd;
+ int nbytessent;
+ int nbytesrecvd;
+ int totalbytesrecvd;
+ int ch;
+ int ret;
+ int i;
+
+ /* Allocate buffers */
+
+ outbuf = (char*)malloc(SENDSIZE);
+ inbuf = (char*)malloc(SENDSIZE);
+ if (!outbuf || !inbuf)
+ {
+ printf("client: failed to allocate buffers\n");
+ exit(1);
+ }
+
+ /* Create a new Unix domain socket */
+
+ sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+ printf("client socket failure %d\n", errno);
+ goto errout_with_buffers;
+ }
+
+ /* Connect the socket to the server */
+
+ addrlen = strlen(CONFIG_EXAMPLES_USTREAM_ADDR);
+ if (addrlen > UNIX_PATH_MAX - 1)
+ {
+ addrlen = UNIX_PATH_MAX - 1;
+ }
+
+ myaddr.sun_family = AF_LOCAL;
+ strncpy(myaddr.sun_path, CONFIG_EXAMPLES_USTREAM_ADDR, addrlen);
+ myaddr.sun_path[addrlen] = '\0';
+
+ printf("client: Connecting...\n");
+ addrlen += sizeof(sa_family_t) + 1;
+ ret = connect( sockfd, (struct sockaddr *)&myaddr, addrlen);
+ if (ret < 0)
+ {
+ printf("client: connect failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ printf("client: Connected\n");
+
+ /* Initialize the buffer */
+
+ ch = 0x20;
+ for (i = 0; i < SENDSIZE; i++ )
+ {
+ outbuf[i] = ch;
+ if (++ch > 0x7e)
+ {
+ ch = 0x20;
+ }
+ }
+
+ /* Then send and receive one message */
+
+ printf("client: Sending %d bytes\n", SENDSIZE);
+ nbytessent = send(sockfd, outbuf, SENDSIZE, 0);
+ printf("client: Sent %d bytes\n", nbytessent);
+
+ if (nbytessent < 0)
+ {
+ printf("client: send failed: %d\n", errno);
+ goto errout_with_socket;
+ }
+ else if (nbytessent != SENDSIZE)
+ {
+ printf("client: Bad send length: %d Expected: %d\n", nbytessent, SENDSIZE);
+ goto errout_with_socket;
+ }
+
+ totalbytesrecvd = 0;
+ do
+ {
+ printf("client: Receiving...\n");
+ nbytesrecvd = recv(sockfd, &inbuf[totalbytesrecvd], SENDSIZE - totalbytesrecvd, 0);
+
+ if (nbytesrecvd < 0)
+ {
+ printf("client: recv failed: %d\n", errno);
+ goto errout_with_socket;
+ }
+ else if (nbytesrecvd == 0)
+ {
+ printf("client: The server closed the connection\n");
+ goto errout_with_socket;
+ }
+
+ totalbytesrecvd += nbytesrecvd;
+ printf("client: Received %d of %d bytes\n", totalbytesrecvd, SENDSIZE);
+ }
+ while (totalbytesrecvd < SENDSIZE);
+
+ if (totalbytesrecvd != SENDSIZE)
+ {
+ printf("client: Bad recv length: %d Expected: %d\n", totalbytesrecvd, SENDSIZE);
+ goto errout_with_socket;
+ }
+ else if (memcmp(inbuf, outbuf, SENDSIZE) != 0)
+ {
+ printf("client: Received buffer does not match sent buffer\n");
+ goto errout_with_socket;
+ }
+
+ close(sockfd);
+ free(outbuf);
+ free(inbuf);
+ return 0;
+
+errout_with_socket:
+ close(sockfd);
+
+errout_with_buffers:
+ free(outbuf);
+ free(inbuf);
+ return 1;
+}
diff --git a/apps/examples/ustream/ustream_server.c b/apps/examples/ustream/ustream_server.c
new file mode 100644
index 000000000..4432019a4
--- /dev/null
+++ b/apps/examples/ustream/ustream_server.c
@@ -0,0 +1,212 @@
+/****************************************************************************
+ * examples/ustream/ustream_server.c
+ *
+ * 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 Gregory Nutt 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>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "ustream.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_KERNEL
+int main(int argc, FAR char *argv[])
+#else
+int server_main(int argc, char *argv[])
+#endif
+{
+ struct sockaddr_un myaddr;
+ socklen_t addrlen;
+ FAR char *buffer;
+ int listensd;
+ int acceptsd;
+ int nbytesread;
+ int totalbytesread;
+ int nbytessent;
+ int ch;
+ int ret;
+ int i;
+
+ /* Allocate a BIG buffer */
+
+ buffer = (char*)malloc(2*SENDSIZE);
+ if (!buffer)
+ {
+ printf("server: failed to allocate buffer\n");
+ exit(1);
+ }
+
+ /* Create a new Unix domain socket */
+
+ listensd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (listensd < 0)
+ {
+ printf("server: socket failure: %d\n", errno);
+ goto errout_with_buffer;
+ }
+
+ /* Bind the socket to a local address */
+
+ addrlen = strlen(CONFIG_EXAMPLES_USTREAM_ADDR);
+ if (addrlen > UNIX_PATH_MAX - 1)
+ {
+ addrlen = UNIX_PATH_MAX - 1;
+ }
+
+ myaddr.sun_family = AF_LOCAL;
+ strncpy(myaddr.sun_path, CONFIG_EXAMPLES_USTREAM_ADDR, addrlen);
+ myaddr.sun_path[addrlen] = '\0';
+
+ addrlen += sizeof(sa_family_t) + 1;
+ ret = bind(listensd, (struct sockaddr*)&myaddr, addrlen);
+ if (ret < 0)
+ {
+ printf("server: bind failure: %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ /* Listen for connections on the bound socket */
+
+ if (listen(listensd, 5) < 0)
+ {
+ printf("server: listen failure %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ /* Accept only one connection */
+
+ printf("server: Accepting connections on %s\n", CONFIG_EXAMPLES_USTREAM_ADDR);
+ acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen);
+ if (acceptsd < 0)
+ {
+ printf("server: accept failure: %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ printf("server: Connection accepted -- receiving\n");
+
+ /* Receive canned message */
+
+ totalbytesread = 0;
+ while (totalbytesread < SENDSIZE)
+ {
+ printf("server: Reading...\n");
+ nbytesread = recv(acceptsd, &buffer[totalbytesread], 2*SENDSIZE - totalbytesread, 0);
+ if (nbytesread < 0)
+ {
+ printf("server: recv failed: %d\n", errno);
+ goto errout_with_acceptsd;
+ }
+ else if (nbytesread == 0)
+ {
+ printf("server: The client broke the connection\n");
+ goto errout_with_acceptsd;
+ }
+
+ totalbytesread += nbytesread;
+ printf("server: Received %d of %d bytes\n", totalbytesread, SENDSIZE);
+ }
+
+ /* Verify the message */
+
+ if (totalbytesread != SENDSIZE)
+ {
+ printf("server: Received %d / Expected %d bytes\n", totalbytesread, SENDSIZE);
+ goto errout_with_acceptsd;
+ }
+
+ ch = 0x20;
+ for (i = 0; i < SENDSIZE; i++ )
+ {
+ if (buffer[i] != ch)
+ {
+ printf("server: Byte %d is %02x / Expected %02x\n", i, buffer[i], ch);
+ goto errout_with_acceptsd;
+ }
+
+ if (++ch > 0x7e)
+ {
+ ch = 0x20;
+ }
+ }
+
+ /* Then send the same data back to the client */
+
+ printf("server: Sending %d bytes\n", totalbytesread);
+ nbytessent = send(acceptsd, buffer, totalbytesread, 0);
+ if (nbytessent <= 0)
+ {
+ printf("server: send failed: %d\n", errno);
+ goto errout_with_acceptsd;
+ }
+
+ printf("server: Sent %d bytes\n", nbytessent);
+
+ /* If this platform only does abortive disconnects, then wait a bit to get the
+ * client side a change to receive the data.
+ */
+
+ printf("server: Wait before closing\n");
+ sleep(60);
+
+ close(listensd);
+ close(acceptsd);
+ free(buffer);
+ return 0;
+
+errout_with_acceptsd:
+ close(acceptsd);
+
+errout_with_listensd:
+ close(listensd);
+
+errout_with_buffer:
+ free(buffer);
+ return 1;
+}
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index 1bd41f319..eccf5c23d 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -154,6 +154,22 @@
# define CONFIG_NSH_NETINIT_THREAD_PRIORITY 100
#endif
+/* Some networking commands do not make sense unless there is a network
+ * device. There might not be a network device if, for example, only Unix
+ * domain sockets were enable.
+ */
+
+#if !defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_SLIP)
+ /* No link layer protocol is a good indication that there is no network
+ * device.
+ */
+
+# undef CONFIG_NSH_DISABLE_IFUPDOWN
+# undef CONFIG_NSH_DISABLE_IFCONFIG
+# define CONFIG_NSH_DISABLE_IFUPDOWN 1
+# define CONFIG_NSH_DISABLE_IFCONFIG 1
+#endif
+
/* Telnetd requires networking support */
#ifndef CONFIG_NET
diff --git a/apps/nshlib/nsh_netinit.c b/apps/nshlib/nsh_netinit.c
index ed42bb9ba..d2ea3520f 100644
--- a/apps/nshlib/nsh_netinit.c
+++ b/apps/nshlib/nsh_netinit.c
@@ -107,7 +107,7 @@
# ifndef CONFIG_NSH_NOMAC
# error "CONFIG_NSH_NOMAC must be defined for SLIP"
# endif
-#else
+#elif !defined(CONFIG_NET_LOCAL)
# error ERROR: No link layer protocol defined
#endif
@@ -235,7 +235,8 @@ static void nsh_netinit_configure(void)
/* Set the MAC address */
netlib_setmacaddr(NET_DEVNAME, mac);
-#endif
+
+#endif /* CONFIG_NSH_NOMAC && CONFIG_NET_ETHERNET */
#ifdef CONFIG_NET_IPv4
/* Set up our host address */
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index d1e6eea6b..3ea6bd3fc 100755
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -9535,6 +9535,9 @@
* arch/arm/src/stm32/stm32_rtcc.c and Kconfig: Recent changes to
stm32_rtcc.c do not compile with STM32L15XX configurations. From
Jussi Kivilinna (2015-01-27).
+ * net/local: Add initial support for local, Unix domain sockets.
+ Initial support is limited to SOCK_STREAM and is untested on
+ initial commit (2014-01-27).
* net/iob, net/tcp/tcp_callback.c, and include/nuttx/net/iob.h: There
were issues with the TCP write-ahead buffering if CONFIG_NET_NOINTS was
enabled: There is a possibility of deadlocks in certain timing conditions.
diff --git a/nuttx/arch/sim/src/Makefile b/nuttx/arch/sim/src/Makefile
index 4507ce60d..0fd5bfea9 100644
--- a/nuttx/arch/sim/src/Makefile
+++ b/nuttx/arch/sim/src/Makefile
@@ -98,7 +98,7 @@ ifeq ($(CONFIG_ARCH_ROMGETC),y)
CSRCS += up_romgetc.c
endif
-ifeq ($(CONFIG_NET),y)
+ifeq ($(CONFIG_NET_ETHERNET),y)
CSRCS += up_netdriver.c
HOSTCFLAGS += -DNETDEV_BUFSIZE=$(CONFIG_NET_ETH_MTU)
ifneq ($(HOSTOS),Cygwin)
diff --git a/nuttx/arch/sim/src/nuttx-names.dat b/nuttx/arch/sim/src/nuttx-names.dat
index 9658cf644..bfd3c051c 100644
--- a/nuttx/arch/sim/src/nuttx-names.dat
+++ b/nuttx/arch/sim/src/nuttx-names.dat
@@ -1,3 +1,4 @@
+accept NXaccept
calloc NXcalloc
clock_gettime NXclock_gettime
close NXclose
@@ -13,6 +14,7 @@ fsync NXfsync
gettimeofday NXgettimeofday
ioctl NXioctl
isatty NXisatty
+listen NXlisten
lseek NXlseek
malloc NXmalloc
malloc_init NXmalloc_init
diff --git a/nuttx/arch/sim/src/up_idle.c b/nuttx/arch/sim/src/up_idle.c
index ae7c2d704..3cc7875b9 100644
--- a/nuttx/arch/sim/src/up_idle.c
+++ b/nuttx/arch/sim/src/up_idle.c
@@ -117,7 +117,7 @@ void up_idle(void)
#endif
-#ifdef CONFIG_NET
+#ifdef CONFIG_NET_ETHERNET
/* Run the network if enabled */
netdriver_loop();
diff --git a/nuttx/arch/sim/src/up_initialize.c b/nuttx/arch/sim/src/up_initialize.c
index 6ae39f94a..82eb32d1c 100644
--- a/nuttx/arch/sim/src/up_initialize.c
+++ b/nuttx/arch/sim/src/up_initialize.c
@@ -158,7 +158,7 @@ void up_initialize(void)
up_registerblockdevice(); /* Our FAT ramdisk at /dev/ram0 */
#endif
-#ifdef CONFIG_NET
+#ifdef CONFIG_NET_ETHERNET
netdriver_init(); /* Our "real" network driver */
#endif
diff --git a/nuttx/include/nuttx/net/netconfig.h b/nuttx/include/nuttx/net/netconfig.h
index fed4f4ada..58e285b5f 100644
--- a/nuttx/include/nuttx/net/netconfig.h
+++ b/nuttx/include/nuttx/net/netconfig.h
@@ -148,7 +148,7 @@
# define MIN_NET_DEV_MTU CONFIG_NET_SLIP_MTU
# define MAX_NET_DEV_MTU CONFIG_NET_SLIP_MTU
-#else /* if defined(CONFIG_NET_ETHERNET) */
+#elif defined(CONFIG_NET_ETHERNET)
/* Assume standard Ethernet link layer header */
# define NET_LL_HDRLEN(d) 14
@@ -156,6 +156,14 @@
# define MIN_NET_DEV_MTU CONFIG_NET_ETH_MTU
# define MAX_NET_DEV_MTU CONFIG_NET_ETH_MTU
+#else
+ /* Perhaps only Unix domain sockets */
+
+# define NET_LL_HDRLEN(d) 0
+# define NET_DEV_MTU(d) 0
+# define MIN_NET_DEV_MTU 0
+# define MAX_NET_DEV_MTU 0
+
#endif /* MULTILINK or SLIP or ETHERNET */
/* Layer 3/4 Configuration Options ******************************************/
diff --git a/nuttx/net/Kconfig b/nuttx/net/Kconfig
index 2c2eabef6..272743d2b 100644
--- a/nuttx/net/Kconfig
+++ b/nuttx/net/Kconfig
@@ -202,6 +202,7 @@ endmenu # Internet Protocol Selection
source "net/socket/Kconfig"
source "net/pkt/Kconfig"
+source "net/local/Kconfig"
source "net/tcp/Kconfig"
source "net/udp/Kconfig"
source "net/icmp/Kconfig"
diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile
index 7a9cf03d5..ce3faf0f3 100644
--- a/nuttx/net/Makefile
+++ b/nuttx/net/Makefile
@@ -63,9 +63,10 @@ include icmp/Make.defs
include icmpv6/Make.defs
include neighbor/Make.defs
include igmp/Make.defs
+include pkt/Make.defs
+include local/Make.defs
include tcp/Make.defs
include udp/Make.defs
-include pkt/Make.defs
include devif/Make.defs
include route/Make.defs
include utils/Make.defs
diff --git a/nuttx/net/README.txt b/nuttx/net/README.txt
index bbbccc0db..db0a59452 100644
--- a/nuttx/net/README.txt
+++ b/nuttx/net/README.txt
@@ -13,6 +13,7 @@ Directory Structure
+- icmp - Internet Control Message Protocol (IPv4)
+- icmpv6 - Internet Control Message Protocol (IPv6)
+- iob - I/O buffering logic
+ +- local - Unix domain (local) sockets
+- neighbor - Neighbor Discovery Protocol (IPv6)
+- netdev - Socket network device interface
+- pkt - "Raw" packet socket support
diff --git a/nuttx/net/devif/devif_poll.c b/nuttx/net/devif/devif_poll.c
index 3070584b6..c942ea266 100644
--- a/nuttx/net/devif/devif_poll.c
+++ b/nuttx/net/devif/devif_poll.c
@@ -313,7 +313,7 @@ static inline int devif_poll_tcp_timer(FAR struct net_driver_s *dev,
int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
{
- int bstop;
+ int bstop = false;
/* Traverse all of the active packet connections and perform the poll
* action.
@@ -417,7 +417,7 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
int devif_timer(FAR struct net_driver_s *dev, devif_poll_callback_t callback,
int hsec)
{
- int bstop;
+ int bstop = false;
/* Increment the timer used by the IP reassembly logic */
diff --git a/nuttx/net/local/Kconfig b/nuttx/net/local/Kconfig
new file mode 100644
index 000000000..2f720c348
--- /dev/null
+++ b/nuttx/net/local/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+menu "Unix Domain Socket Support"
+ depends on NET && EXPERIMENTAL
+
+config NET_LOCAL
+ bool "Unix domain (local) sockets"
+ default n
+ ---help---
+ Enable or disable Unix domain (aka Local) sockets.
+
+if NET_LOCAL
+
+endif # NET_LOCAL
+
+endmenu # Unix Domain Sockets
diff --git a/nuttx/net/local/Make.defs b/nuttx/net/local/Make.defs
new file mode 100644
index 000000000..6b101cd7a
--- /dev/null
+++ b/nuttx/net/local/Make.defs
@@ -0,0 +1,49 @@
+############################################################################
+# net/local/Make.defs
+#
+# 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.
+#
+############################################################################
+
+# UDP source files
+
+ifeq ($(CONFIG_NET_LOCAL),y)
+
+NET_CSRCS += local_conn.c local_connect.c local_release.c local_bind.c
+NET_CSRCS += local_listen.c local_accept.c local_fifo.c local_recvfrom.c
+NET_CSRCS += local_send.c local_sendto.c local_sendpacket.c local_recvutils.c
+
+# Include UDP build support
+
+DEPPATH += --dep-path local
+VPATH += :local
+
+endif # CONFIG_NET_LOCAL
diff --git a/nuttx/net/local/local.h b/nuttx/net/local/local.h
new file mode 100644
index 000000000..23a4ed8fe
--- /dev/null
+++ b/nuttx/net/local/local.h
@@ -0,0 +1,549 @@
+/****************************************************************************
+ * 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 <sys/un.h>
+#include <semaphore.h>
+#include <queue.h>
+#include <stdint.h>
+
+#ifdef CONFIG_NET_LOCAL
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Packet format in FIFO:
+ *
+ * 1. Sync bytes (7 at most)
+ * 2. End/Start byte
+ * 3. 16-bit packet length (in host order)
+ * 4. Packet data (in host order)
+ */
+
+#define LOCAL_SYNC_BYTE 0x42 /* Byte in sync sequence */
+#define LOCAL_END_BYTE 0xbd /* End of sync seqence */
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+/* Local, Unix domain socket types */
+
+enum local_type_e
+{
+ LOCAL_TYPE_UNTYPED = 0, /* Type is not determined until the socket is bound */
+ LOCAL_TYPE_UNNAMED, /* A Unix socket that is not bound to any name */
+ LOCAL_TYPE_PATHNAME, /* lc_path holds a null terminated string */
+ LOCAL_TYPE_ABSTRACT /* lc_path is length zero */
+};
+
+/* The state of a Unix socket */
+
+enum local_state_s
+{
+ /* Common states */
+
+ LOCAL_STATE_UNBOUND = 0, /* Created by socket, but not bound */
+ LOCAL_STATE_BOUND, /* Bound to an path */
+
+ /* SOCK_STREAM server only */
+
+ LOCAL_STATE_LISTENING, /* Server listening for connections */
+
+ /* SOCK_STREAM peers only */
+
+ LOCAL_STATE_ACCEPT, /* Client waiting for a connection */
+ LOCAL_STATE_CONNECTED, /* Peer connected */
+ LOCAL_STATE_DISCONNECTED /* Peer disconnected */
+};
+
+/* Representation of a local connection. There are four types of
+ * connection structures:
+ *
+ * 1. Server. A SOCK_STREAM that only listens for and accepts
+ * connections from server.
+ * 2. Client. A SOCK_STREAM peer that connects via the server.
+ * 3. Peer. A connected SOCK_STREAM that sends() and recvs() packets.
+ * May either be the client that connect with the server of the
+ * new peer connect generated with the connection was accepted by
+ * the server.
+ *
+ * And
+ *
+ * 4. Connectionless. Like a peer but using a connectionless datagram
+ * style of communication. SOCK_DRAM support has not yet been
+ * implemented.
+ */
+
+struct local_conn_s
+{
+ /* lc_node supports a doubly linked list: Listening SOCK_STREAM servers
+ * will be linked into a list of listeners; SOCK_STREAM clients will be
+ * linked to the lc_waiters and lc_conn lists.
+ */
+
+ dq_entry_t lc_node; /* Supports a doubly linked list */
+
+ /* Fields common to SOCK_STREAM and SOCK_DGRAM */
+
+ uint8_t lc_crefs; /* Reference counts on this instance */
+ uint8_t lc_proto; /* SOCK_STREAM or SOCK_DGRAM */
+ uint8_t lc_type; /* See enum local_type_e */
+ uint8_t lc_state; /* See enum local_state_e */
+ int16_t lc_infd; /* File descriptor of read-only FIFO (peers) */
+ int16_t lc_outfd; /* File descriptor of write-only FIFO (peers) */
+ char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */
+
+ /* SOCK_STREAM fields common to both client and server */
+
+ sem_t lc_waitsem; /* Use to wait for a connection to be accepted */
+
+ /* Union of fields unique to SOCK_STREAM client, server, and connected
+ * peers.
+ */
+
+ union
+ {
+ /* Fields unique to the SOCK_STREAM server side */
+
+ struct
+ {
+ uint8_t lc_pending; /* Number of pending connections */
+ uint8_t lc_backlog; /* Maximum number of pending connections */
+ dq_queue_t lc_waiters; /* List of connections waiting to be accepted */
+ } server;
+
+ /* Fields unique to the connecting client side */
+
+ struct
+ {
+ uint16_t lc_remaining; /* (For binary compatibility with peer) */
+ volatile int lc_result; /* Result of the connection operation (client)*/
+ } client;
+
+ /* Fields common to connected peers (connected or accepted) */
+
+ struct
+ {
+ uint16_t lc_remaining; /* Bytes remaining in the incoming stream */
+ } peer;
+ } u;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+# define EXTERN extern "C"
+extern "C"
+{
+#else
+# define EXTERN extern
+#endif
+
+/* A list of all SOCK_STREAM listener connections */
+
+EXTERN dq_queue_t g_local_listeners;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct sockaddr; /* Forward reference */
+struct socket; /* Forward reference */
+
+/****************************************************************************
+ * Name: local_initialize
+ *
+ * Description:
+ * Initialize the local, Unix domain connection structures. Called once
+ * and only from the common network initialization logic.
+ *
+ ****************************************************************************/
+
+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: psock_local_bind
+ *
+ * Description:
+ * This function implements the low-level parts of the standard local
+ * bind()operation.
+ *
+ ****************************************************************************/
+
+int psock_local_bind(FAR struct socket *psock,
+ FAR const struct sockaddr *addr, socklen_t addrlen);
+
+/****************************************************************************
+ * 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
+ * psock_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:
+ * client - A reference to the client-side local connection structure
+ * addr - The address of the remote host.
+ *
+ ****************************************************************************/
+
+int local_connect(FAR struct local_conn_s *client,
+ FAR const struct sockaddr *addr);
+
+/****************************************************************************
+ * Name: local_release
+ *
+ * Description:
+ * If the local, Unix domain socket is in the connected state, then
+ * disconnect it. Release the local connection structure in any event
+ *
+ * Input Parameters:
+ * conn - A reference to local connection structure
+ *
+ ****************************************************************************/
+
+int local_release(FAR struct local_conn_s *conn);
+
+/****************************************************************************
+ * Name: local_listen
+ *
+ * Description:
+ * Listen for a new connection of a SOCK_STREAM Unix domain socket.
+ *
+ * This function is called as part of the implementation of listen();
+ *
+ * Input Parameters:
+ * server - A reference to the server-side local connection structure
+ * backlog - Maximum number of pending connections.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * The network is NOT locked
+ *
+ ****************************************************************************/
+
+int local_listen(FAR struct local_conn_s *server, int backlog);
+
+/****************************************************************************
+ * Function: psock_local_accept
+ *
+ * Description:
+ * This function implements accept() for Unix domain sockets. See the
+ * description of accept() for further information.
+ *
+ * Parameters:
+ * psock The listening Unix domain socket structure
+ * addr Receives the address of the connecting client
+ * addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
+ * newconn The new, accepted Unix domain connection structure
+ *
+ * Returned Value:
+ * Returns zero (OK) on success or a negated errno value on failure.
+ * See the description of accept of the possible errno values in the
+ * description of accept().
+ *
+ * Assumptions:
+ * Network is NOT locked.
+ *
+ ****************************************************************************/
+
+int psock_local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR void **newconn);
+
+/****************************************************************************
+ * 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 (ignored for now)
+ *
+ * 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 (ignored for now)
+ * 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);
+
+/****************************************************************************
+ * Name: local_send_packet
+ *
+ * Description:
+ * Send a packet on the write-only FIFO.
+ *
+ * Parameters:
+ * fd File descriptor of write-only FIFO.
+ * buf Data to send
+ * len Length of data to send
+ *
+ * Return:
+ * Zero is returned on success; a negated errno value is returned on any
+ * failure.
+ *
+ ****************************************************************************/
+
+int local_send_packet(int fd, FAR const uint8_t *buf, size_t len);
+
+/****************************************************************************
+ * 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 (ignored for now)
+ * 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);
+
+/****************************************************************************
+ * Name: local_fifo_read
+ *
+ * Description:
+ * Read a data from the read-only FIFO.
+ *
+ * Parameters:
+ * fd - File descriptor of read-only FIFO.
+ * buf - Local to store the received data
+ * len - Length of data to receive [in]
+ * Length of data actually received [out]
+ *
+ * Return:
+ * Zero is returned on success; a negated errno value is returned on any
+ * failure. If -ECONNRESET is received, then the sending side has closed
+ * the FIFO. In this case, the returned data may still be valid (if the
+ * returned len > 0).
+ *
+ ****************************************************************************/
+
+int local_fifo_read(int fd, FAR uint8_t *buf, size_t *len);
+
+/****************************************************************************
+ * Name: local_getaddr
+ *
+ * Description:
+ * Return the Unix domain address of a connection.
+ *
+ * Parameters:
+ * conn - The connection
+ * addr - The location to return the address
+ * addrlen - The size of the memory allocat by the caller to receive the
+ * address.
+ *
+ * Return:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int local_getaddr(FAR struct local_conn_s *conn, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen);
+
+/****************************************************************************
+ * Name: local_sync
+ *
+ * Description:
+ * Read a sync bytes until the start of the packet is found.
+ *
+ * Parameters:
+ * fd - File descriptor of read-only FIFO.
+ *
+ * Return:
+ * The non-zero size of the following packet is returned on success; a
+ * negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int local_sync(int fd);
+
+/****************************************************************************
+ * Name: local_create_fifos
+ *
+ * Description:
+ * Create the FIFO pair needed for a connection.
+ *
+ ****************************************************************************/
+
+int local_create_fifos(FAR struct local_conn_s *client);
+
+/****************************************************************************
+ * Name: local_destroy_fifos
+ *
+ * Description:
+ * Destroy the FIFO pair used for a connection.
+ *
+ ****************************************************************************/
+
+int local_destroy_fifos(FAR struct local_conn_s *client);
+
+/****************************************************************************
+ * Name: local_open_client_rx
+ *
+ * Description:
+ * Only the client-side Rx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_client_rx(FAR struct local_conn_s *client);
+
+/****************************************************************************
+ * Name: local_open_client_tx
+ *
+ * Description:
+ * Only the client-side Tx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_client_tx(FAR struct local_conn_s *client);
+
+/****************************************************************************
+ * Name: local_open_server_rx
+ *
+ * Description:
+ * Only the server-side Rx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_server_rx(FAR struct local_conn_s *server);
+
+/****************************************************************************
+ * Name: local_open_server_tx
+ *
+ * Description:
+ * Only the server-side Tx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_server_tx(FAR struct local_conn_s *server);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_LOCAL */
+#endif /* __NET_LOCAL_LOCAL_H */
diff --git a/nuttx/net/local/local_accept.c b/nuttx/net/local/local_accept.c
new file mode 100644
index 000000000..2fd1b92d3
--- /dev/null
+++ b/nuttx/net/local/local_accept.c
@@ -0,0 +1,224 @@
+/****************************************************************************
+ * net/local/local_accept.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/net/net.h>
+
+#include "socket/socket.h"
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: psock_local_accept
+ *
+ * Description:
+ * This function implements accept() for Unix domain sockets. See the
+ * description of accept() for further information.
+ *
+ * Parameters:
+ * psock The listening Unix domain socket structure
+ * addr Receives the address of the connecting client
+ * addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
+ * newconn The new, accepted Unix domain connection structure
+ *
+ * Returned Value:
+ * Returns zero (OK) on success or a negated errno value on failure.
+ * See the description of accept of the possible errno values in the
+ * description of accept().
+ *
+ * Assumptions:
+ * Network is NOT locked.
+ *
+ ****************************************************************************/
+
+int psock_local_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR void **newconn)
+
+{
+ FAR struct local_conn_s *server;
+ FAR struct local_conn_s *client;
+ FAR struct local_conn_s *conn;
+ int ret;
+
+ /* Some sanity checks */
+
+ DEBUGASSERT(psock && psock->s_conn);
+ server = (FAR struct local_conn_s *)psock->s_conn;
+
+ if (server->lc_proto != SOCK_STREAM ||
+ server->lc_state != LOCAL_STATE_LISTENING ||
+ server->lc_type != LOCAL_TYPE_PATHNAME)
+ {
+ return -EOPNOTSUPP;
+ }
+
+ /* Loop as necessary if we have to wait for a connection */
+
+ for (;;)
+ {
+ /* Are there pending connections. Remove the client from the
+ * head of the waiting list.
+ */
+
+ client = (FAR struct local_conn_s *)
+ dq_remfirst(&server->u.server.lc_waiters);
+
+ if (client)
+ {
+ /* Decrement the number of pending clients */
+
+ DEBUGASSERT(server->u.server.lc_pending > 0);
+ server->u.server.lc_pending--;
+
+ /* Create a new connection structure for the server side of the
+ * connection.
+ */
+
+ conn = local_alloc();
+ if (!conn)
+ {
+ ndbg("ERROR: Failed to allocate new connection structure\n");
+ ret = -ENOMEM;
+ }
+ else
+ {
+ /* Initialize the new connection structure */
+
+ conn->lc_crefs = 1;
+ conn->lc_proto = SOCK_STREAM;
+ conn->lc_type = LOCAL_TYPE_PATHNAME;
+ conn->lc_state = LOCAL_STATE_CONNECTED;
+
+ strncpy(conn->lc_path, client->lc_path, UNIX_PATH_MAX-1);
+ conn->lc_path[UNIX_PATH_MAX-1] = '\0';
+
+ /* Open the server-side write-only FIFO. This should not
+ * block.
+ */
+
+ ret = local_open_server_tx(conn);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to open write-only FIFOs for %s: %d\n",
+ conn->lc_path, ret);
+ }
+ }
+
+ /* Do we have a connection? Is the write-side FIFO opened? */
+
+ if (ret == OK)
+ {
+ DEBUGASSERT(conn->lc_outfd >= 0);
+
+ /* Open the server-side read-only FIFO. This should not
+ * block because the client side has already opening it
+ * for writing.
+ */
+
+ ret = local_open_server_rx(conn);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to open read-only FIFOs for %s: %d\n",
+ conn->lc_path, ret);
+ }
+ }
+
+ /* Do we have a connection? Are the FIFOs opened? */
+
+ if (ret == OK)
+ {
+ DEBUGASSERT(conn->lc_infd >= 0);
+
+ /* Return the address family */
+
+ if (addr)
+ {
+ ret = local_getaddr(client, addr, addrlen);
+ }
+ }
+
+ if (ret == OK)
+ {
+ /* Return the client connection structure */
+
+ *newconn = (FAR void *)conn;
+ }
+
+ /* Signal the client with the result of the connection */
+
+ client->u.client.lc_result = ret;
+ sem_post(&client->lc_waitsem);
+ return ret;
+ }
+
+ /* No.. then there should be no pending connections */
+
+ DEBUGASSERT(server->u.server.lc_pending == 0);
+
+ /* Was the socket opened non-blocking? */
+
+ if (_SS_ISNONBLOCK(psock->s_flags))
+ {
+ /* Yes.. return EAGAIN */
+
+ return -EAGAIN;
+ }
+
+ /* Otherwise, listen for a connection and try again. */
+
+ ret = local_listen(server, server->u.server.lc_backlog);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_bind.c b/nuttx/net/local/local_bind.c
new file mode 100644
index 000000000..675b49516
--- /dev/null
+++ b/nuttx/net/local/local_bind.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+ * net/local/local_bind.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/socket.h>
+#include <string.h>
+#include <assert.h>
+
+#include <nuttx/net/net.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_bind
+ *
+ * Description:
+ * This function implements the low-level parts of the standard local
+ * bind()operation.
+ *
+ ****************************************************************************/
+
+int psock_local_bind(FAR struct socket *psock,
+ FAR const struct sockaddr *addr, socklen_t addrlen)
+{
+ FAR struct local_conn_s *conn;
+ FAR const struct sockaddr_un *unaddr =
+ (FAR const struct sockaddr_un *)addr;
+ int namelen;
+
+ DEBUGASSERT(psock && psock->s_conn && unaddr &&
+ unaddr->sun_family == AF_LOCAL &&
+ addrlen >= sizeof(sa_family_t));
+
+ conn = (FAR struct local_conn_s *)psock->s_conn;
+
+ /* Save the address family */
+
+ conn->lc_proto = psock->s_type;
+
+ /* No determine the type of the Unix domain socket by comparing the size
+ * of the address description.
+ */
+
+ if (addrlen == sizeof(sa_family_t))
+ {
+ /* No sun_path... This is an un-named Unix domain socket */
+
+ conn->lc_type = LOCAL_TYPE_UNNAMED;
+ }
+ else
+ {
+ namelen = strnlen(unaddr->sun_path, UNIX_PATH_MAX-1);
+ if (namelen <= 0)
+ {
+ /* Zero-length sun_path... This is an abstract Unix domain socket */
+
+ conn->lc_type = LOCAL_TYPE_ABSTRACT;
+ conn->lc_path[0] = '\0';
+ }
+ else
+ {
+ /* This is an normal, pathname Unix domain socket */
+
+ conn->lc_type = LOCAL_TYPE_PATHNAME;
+
+ /* Copy the path into the connection structure */
+
+ (void)strncpy(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1);
+ conn->lc_path[UNIX_PATH_MAX-1] = '\0';
+ }
+ }
+
+ conn->lc_state = LOCAL_STATE_BOUND;
+ return OK;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_conn.c b/nuttx/net/local/local_conn.c
new file mode 100644
index 000000000..171313b29
--- /dev/null
+++ b/nuttx/net/local/local_conn.c
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * net/local/local_conn.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <semaphore.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_initialize
+ *
+ * Description:
+ * Initialize the local, Unix domain connection structures. Called once
+ * and only from the common network initialization logic.
+ *
+ ****************************************************************************/
+
+ void local_initialize(void)
+{
+ dq_init(&g_local_listeners);
+}
+
+/****************************************************************************
+ * Name: local_alloc()
+ *
+ * Description:
+ * Allocate a new, uninitialized Unix domain socket connection structure.
+ * This is normally something done by the implementation of the socket()
+ * API
+ *
+ ****************************************************************************/
+
+FAR struct local_conn_s *local_alloc(void)
+{
+ FAR struct local_conn_s *conn =
+ (FAR struct local_conn_s *)kmm_zalloc(sizeof(struct local_conn_s));
+
+ if (conn)
+ {
+ /* Initialize non-zero elements the new connection structure */
+
+ conn->lc_infd = -1;
+ conn->lc_outfd = -1;
+ sem_init(&conn->lc_waitsem, 0, 0);
+ }
+
+ return conn;
+}
+
+/****************************************************************************
+ * Name: local_free()
+ *
+ * Description:
+ * Free a packet Unix domain 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)
+{
+ DEBUGASSERT(conn != NULL);
+
+ /* Make sure that the read-only FIFO is closed */
+
+ if (conn->lc_infd >= 0)
+ {
+ close(conn->lc_infd);
+ }
+
+ /* Make sure that the write-only FIFO is closed */
+
+ if (conn->lc_outfd >= 0)
+ {
+ close(conn->lc_outfd);
+ }
+
+ /* Destroy all FIFOs associted with the connection */
+
+ local_destroy_fifos(conn);
+ sem_destroy(&conn->lc_waitsem);
+
+ /* And free the connection structure */
+
+ kmm_free(conn);
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_connect.c b/nuttx/net/local/local_connect.c
new file mode 100644
index 000000000..c10de214a
--- /dev/null
+++ b/nuttx/net/local/local_connect.c
@@ -0,0 +1,305 @@
+/****************************************************************************
+ * net/local/local_connnect.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <queue.h>
+#include <debug.h>
+
+#include <nuttx/net/net.h>
+
+#include "utils/utils.h"
+#include "local/local.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _local_semtake() and _local_semgive()
+ *
+ * Description:
+ * Take/give semaphore
+ *
+ ****************************************************************************/
+
+static inline void _local_semtake(sem_t *sem)
+{
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(sem) != 0)
+ {
+ /* The only case that an error should occur here is if
+ * the wait was awakened by a signal.
+ */
+
+ ASSERT(*get_errno_ptr() == EINTR);
+ }
+}
+
+#define _local_semgive(sem) sem_post(sem)
+
+/****************************************************************************
+ * Name: local_stream_connect
+ *
+ * Description:
+ * Find a local connection structure that is the appropriate "server"
+ * connection to be used with the provided "client" connection.
+ *
+ * Returned Values:
+ * Zero (OK) returned on success; A negated errno value is returned on a
+ * failure. Possible failures include:
+ *
+ * Assumptions:
+ * The network is locked on entry, unlocked on return. This logic is
+ * an integral part of the lock_connect() implementation and was
+ * separated out only to improve readability.
+ *
+ ****************************************************************************/
+
+int inline local_stream_connect(FAR struct local_conn_s *client,
+ FAR struct local_conn_s *server,
+ net_lock_t state)
+{
+ int ret;
+
+ /* Has server backlog been reached?
+ * NOTE: The backlog will be zero if listen() has never been called by the
+ * server.
+ */
+
+ if (server->lc_state != LOCAL_STATE_LISTENING ||
+ server->u.server.lc_pending >= server->u.server.lc_backlog)
+ {
+ net_unlock(state);
+ ndbg("ERROR: Server is not listening: lc_state=%d\n",
+ server->lc_state);
+ ndbg(" OR: The backlog limit was reached: %d or %d\n",
+ server->u.server.lc_pending, server->u.server.lc_backlog);
+ return -ECONNREFUSED;
+ }
+
+ /* Increment the number of pending server connection s*/
+
+ server->u.server.lc_pending++;
+ DEBUGASSERT(server->u.server.lc_pending != 0);
+
+ /* Create the FIFOs needed for the connection */
+
+ ret = local_create_fifos(client);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to create FIFOs for %s: %d\n",
+ client->lc_path, ret);
+ return ret;
+ }
+
+ /* Open the client-side write-only FIFO. This should not block and should
+ * prevent the server-side from blocking as well.
+ */
+
+ ret = local_open_client_tx(client);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to open write-only FIFOs for %s: %d\n",
+ client->lc_path, ret);
+ goto errout_with_fifos;
+ }
+
+ DEBUGASSERT(client->lc_outfd >= 0);
+
+ /* Add ourself to the list of waiting connections and notify the server. */
+
+ dq_addlast(&client->lc_node, &server->u.server.lc_waiters);
+ client->lc_state = LOCAL_STATE_ACCEPT;
+ _local_semgive(&server->lc_waitsem);
+ net_unlock(state);
+
+ /* Wait for the server to accept the connections */
+
+ client->u.client.lc_result = -EBUSY;
+ do
+ {
+ _local_semtake(&client->lc_waitsem);
+ ret = client->u.client.lc_result;
+ }
+ while (ret == -EBUSY);
+
+ /* Did we successfully connect? */
+
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to connect: %d\n", ret);
+ goto errout_with_outfd;
+ }
+
+ /* Yes.. open the read-only FIFO */
+
+ ret = local_open_client_tx(client);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to open write-only FIFOs for %s: %d\n",
+ client->lc_path, ret);
+ goto errout_with_outfd;
+ }
+
+ DEBUGASSERT(client->lc_infd >= 0);
+ client->lc_state = LOCAL_STATE_CONNECTED;
+ return OK;
+
+errout_with_outfd:
+ (void)close(client->lc_outfd);
+
+errout_with_fifos:
+ (void)local_destroy_fifos(client);
+ client->lc_state = LOCAL_STATE_BOUND;
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_connect
+ *
+ * Description:
+ * Find a local connection structure that is the appropriate "server"
+ * connection to be used with the provided "client" connection.
+ *
+ * Returned Values:
+ * Zero (OK) returned on success; A negated errno value is returned on a
+ * failure. Possible failures include:
+ *
+ * EISCONN - The specified socket is connection-mode and is already
+ * connected.
+ * EADDRNOTAVAIL - The specified address is not available from the
+ * local machine.
+ * ECONNREFUSED - The target address was not listening for connections or
+ * refused the connection request because the connection backlog has
+ * been exceeded.
+ *
+ ****************************************************************************/
+
+int local_connect(FAR struct local_conn_s *client,
+ FAR const struct sockaddr *addr)
+{
+ FAR struct sockaddr_un *unaddr = (FAR struct sockaddr_un *)addr;
+ FAR struct local_conn_s *conn;
+ net_lock_t state;
+
+ DEBUGASSERT(client);
+
+ if (client->lc_state == LOCAL_STATE_ACCEPT ||
+ client->lc_state == LOCAL_STATE_CONNECTED)
+ {
+ return -EISCONN;
+ }
+
+ /* Find the matching server connection */
+
+ state = net_lock();
+ for(conn = (FAR struct local_conn_s *)g_local_listeners.head;
+ conn;
+ conn = (FAR struct local_conn_s *)dq_next(&conn->lc_node))
+ {
+ /* Anything in the listener list should be a stream socket in the
+ * istening state
+ */
+
+ DEBUGASSERT(conn->lc_state == LOCAL_STATE_LISTENING &&
+ conn->lc_proto == SOCK_STREAM);
+
+ /* Handle according to the server connection type */
+
+ switch (conn->lc_type)
+ {
+ case LOCAL_TYPE_UNNAMED: /* A Unix socket that is not bound to any name */
+ case LOCAL_TYPE_ABSTRACT: /* lc_path is length zero */
+ {
+#warning Missing logic
+ net_unlock(state);
+ return OK;
+ }
+ break;
+
+ case LOCAL_TYPE_PATHNAME: /* lc_path holds a null terminated string */
+ {
+ if (strncmp(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1) == 0)
+ {
+ /* Bind the address and protocol */
+
+ client->lc_proto = conn->lc_proto;
+ strncpy(client->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1);
+ client->lc_path[UNIX_PATH_MAX-1] = '\0';
+
+ /* We have to do more for the SOCK_STREAM family */
+
+ if (conn->lc_proto == SOCK_STREAM)
+ {
+ return local_stream_connect(client, conn, state);
+ }
+
+ net_unlock(state);
+ return OK;
+ }
+ }
+ break;
+
+ default: /* Bad, memory must be corrupted */
+ DEBUGPANIC(); /* PANIC if debug on, else fall through */
+
+ case LOCAL_TYPE_UNTYPED: /* Type is not determined until the socket is bound */
+ {
+ net_unlock(state);
+ return -EINVAL;
+ }
+ }
+ }
+
+ net_unlock(state);
+ return -EADDRNOTAVAIL;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_fifo.c b/nuttx/net/local/local_fifo.c
new file mode 100644
index 000000000..15ded2932
--- /dev/null
+++ b/nuttx/net/local/local_fifo.c
@@ -0,0 +1,407 @@
+/****************************************************************************
+ * net/local/local_fifo.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#define LOCAL_RX_SUFFIX "RX"
+#define LOCAL_TX_SUFFIX "TX"
+#define LOCAL_SUFFIX_LEN 2
+
+#define LOCAL_FULLPATH_LEN (UNIX_PATH_MAX + LOCAL_SUFFIX_LEN)
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_rx_name
+ *
+ * Description:
+ * Create the name of the RX (client-to-server) FIFO name.
+ *
+ ****************************************************************************/
+
+static inline void local_rx_name(FAR struct local_conn_s *conn,
+ FAR char *path)
+{
+ (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_RX_SUFFIX,
+ conn->lc_path);
+ path[LOCAL_FULLPATH_LEN-1] = '\0';
+}
+
+/****************************************************************************
+ * Name: local_tx_name
+ *
+ * Description:
+ * Create the name of the TX (server-to-client) FIFO name.
+ *
+ ****************************************************************************/
+
+static inline void local_tx_name(FAR struct local_conn_s *conn,
+ FAR char *path)
+{
+ (void)snprintf(path, LOCAL_FULLPATH_LEN-1, "%s" LOCAL_TX_SUFFIX,
+ conn->lc_path);
+ path[LOCAL_FULLPATH_LEN-1] = '\0';
+}
+
+/****************************************************************************
+ * Name: local_fifo_exists
+ *
+ * Description:
+ * Check if a FIFO exists.
+ *
+ ****************************************************************************/
+
+static bool local_fifo_exists(FAR const char *path)
+{
+ struct stat buf;
+ int ret;
+
+ /* Create the client-to-server FIFO */
+
+ ret = stat(path, &buf);
+ if (ret < 0)
+ {
+ return false;
+ }
+
+ /* FIFOs are character devices in NuttX. Return true if what we found
+ * is a FIFO. What if it is something else? In that case, we will
+ * return false and mkfifo() will fail.
+ */
+
+ return (bool)S_ISCHR(buf.st_mode);
+}
+
+/****************************************************************************
+ * Name: local_create_fifo
+ *
+ * Description:
+ * Create the one of FIFOs needed for a connection.
+ *
+ ****************************************************************************/
+
+static int local_create_fifo(FAR const char *path)
+{
+ int ret;
+
+ /* Create the client-to-server FIFO if it does not already exist. */
+
+ if (!local_fifo_exists(path))
+ {
+ ret = mkfifo(path, 0644);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ ndbg("ERROR: Failed to create FIFO %s: %d\n", path, errcode);
+ return -errcode;
+ }
+ }
+
+ /* The FIFO (or some character driver) exists at PATH or we successfully
+ * created the FIFO at that location.
+ */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: local_destroy_fifo
+ *
+ * Description:
+ * Destroy one of the FIFOs used in a connection.
+ *
+ ****************************************************************************/
+
+static int local_destroy_fifo(FAR const char *path)
+{
+ int ret;
+
+ /* Unlink the client-to-server FIFO if it exists. */
+
+ if (local_fifo_exists(path))
+ {
+ ret = unlink(path);
+ if (ret < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ ndbg("ERROR: Failed to unlink FIFO %s: %d\n", path, errcode);
+ return -errcode;
+ }
+ }
+
+ /* The FIFO does not exist or we successfully unlinked it. */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: local_rx_open
+ *
+ * Description:
+ * Open a FIFO for read-only access.
+ *
+ ****************************************************************************/
+
+static inline int local_rx_open(FAR struct local_conn_s *conn,
+ FAR const char *path)
+{
+ conn->lc_infd = open(path, O_RDONLY);
+ if (conn->lc_infd < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ ndbg("ERROR: Failed on open %s for reading: %d\n",
+ path, errcode);
+
+ /* Map the errcode to something consistent with the return
+ * error codes from connect():
+ *
+ * If errcode is ENOENT, meaning that the FIFO does exist,
+ * return EFAULT meaning that the socket structure address is
+ * outside the user's address space.
+ */
+
+ return errcode == ENOENT ? -EFAULT : -errcode;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: local_tx_open
+ *
+ * Description:
+ * Open a FIFO for write-only access.
+ *
+ ****************************************************************************/
+
+static inline int local_tx_open(FAR struct local_conn_s *conn,
+ FAR const char *path)
+{
+ conn->lc_infd = open(path, O_WRONLY);
+ if (conn->lc_infd < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ ndbg("ERROR: Failed on open %s for writing: %d\n",
+ path, errcode);
+
+ /* Map the errcode to something consistent with the return
+ * error codes from connect():
+ *
+ * If errcode is ENOENT, meaning that the FIFO does exist,
+ * return EFAULT meaning that the socket structure address is
+ * outside the user's address space.
+ */
+
+ return errcode == ENOENT ? -EFAULT : -errcode;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_create_fifos
+ *
+ * Description:
+ * Create the FIFO pair needed for a connection.
+ *
+ ****************************************************************************/
+
+int local_create_fifos(FAR struct local_conn_s *client)
+{
+ char path[LOCAL_FULLPATH_LEN];
+ int ret;
+
+ /* Create the client-to-server FIFO if it does not already exist. */
+
+ local_tx_name(client, path);
+ ret = local_create_fifo(path);
+ if (ret >= 0)
+ {
+ /* Create the server-to-client FIFO if it does not already exist. */
+
+ local_rx_name(client, path);
+ ret = local_create_fifo(path);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: local_destroy_fifos
+ *
+ * Description:
+ * Destroy the FIFO pair used for a connection.
+ *
+ ****************************************************************************/
+
+int local_destroy_fifos(FAR struct local_conn_s *client)
+{
+ char path[LOCAL_FULLPATH_LEN];
+ int ret1;
+ int ret2;
+
+ /* Destroy the client-to-server FIFO if it exists. */
+
+ local_tx_name(client, path);
+ ret1 = local_destroy_fifo(path);
+
+ /* Destroy the server-to-client FIFO if it exists. */
+
+ local_rx_name(client, path);
+ ret2 = local_create_fifo(path);
+
+ /* Return a failure if one occurred. */
+
+ return ret1 < 0 ? ret1 : ret2;
+}
+
+/****************************************************************************
+ * Name: local_open_client_rx
+ *
+ * Description:
+ * Only the client-side Rx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_client_rx(FAR struct local_conn_s *client)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the server-to-client path name */
+
+ local_tx_name(client, path);
+
+ /* Then open the file for read-only access */
+
+ return local_rx_open(client, path);
+}
+
+/****************************************************************************
+ * Name: local_open_client_tx
+ *
+ * Description:
+ * Only the client-side Tx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_client_tx(FAR struct local_conn_s *client)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the client-to-server path name */
+
+ local_rx_name(client, path);
+
+ /* Then open the file for write-only access */
+
+ return local_tx_open(client, path);
+}
+
+/****************************************************************************
+ * Name: local_open_server_rx
+ *
+ * Description:
+ * Only the server-side Rx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_server_rx(FAR struct local_conn_s *server)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the client-to-server path name */
+
+ local_rx_name(server, path);
+
+ /* Then open the file for write-only access */
+
+ return local_rx_open(server, path);
+}
+
+/****************************************************************************
+ * Name: local_open_server_tx
+ *
+ * Description:
+ * Only the server-side Tx FIFO.
+ *
+ ****************************************************************************/
+
+int local_open_server_tx(FAR struct local_conn_s *server)
+{
+ char path[LOCAL_FULLPATH_LEN];
+
+ /* Get the server-to-client path name */
+
+ local_tx_name(server, path);
+
+ /* Then open the file for read-only access */
+
+ return local_tx_open(server, path);
+}
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_listen.c b/nuttx/net/local/local_listen.c
new file mode 100644
index 000000000..5de0d1232
--- /dev/null
+++ b/nuttx/net/local/local_listen.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+ * net/local/local_listen.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <assert.h>
+#include <queue.h>
+#include <errno.h>
+
+#include <nuttx/net/net.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* A list of all allocated packet socket connections */
+
+dq_queue_t g_local_listeners;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_listen
+ *
+ * Description:
+ * Listen for a new connection of a SOCK_STREAM Unix domain socket.
+ *
+ * This function is called as part of the implementation of listen();
+ *
+ * Input Parameters:
+ * server - A reference to the server-side local connection structure
+ * backlog - Maximum number of pending connections.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * The network is NOT locked
+ *
+ ****************************************************************************/
+
+int local_listen(FAR struct local_conn_s *server, int backlog)
+{
+ net_lock_t state;
+ int ret;
+
+ /* Some sanity checks */
+
+ DEBUGASSERT(server);
+
+ if (server->lc_proto != SOCK_STREAM ||
+ server->lc_state == LOCAL_STATE_UNBOUND ||
+ server->lc_type != LOCAL_TYPE_PATHNAME)
+ {
+ return -EOPNOTSUPP;
+ }
+
+ DEBUGASSERT(server->lc_state == LOCAL_STATE_BOUND ||
+ server->lc_state == LOCAL_STATE_LISTENING);
+
+ /* Set the backlog value */
+
+ DEBUGASSERT((unsigned)backlog < 256);
+ server->u.server.lc_backlog = backlog;
+
+ /* Is this the first time since being bound to an address and that
+ * listen() was called? If so, the state should be LOCAL_STATE_BOUND.
+ */
+
+ if (server->lc_state == LOCAL_STATE_BOUND)
+ {
+ /* The connection should not reside in any other list */
+
+ DEBUGASSERT(server->lc_node.flink == NULL &&
+ server->lc_node.flink == NULL);
+
+ /* Add the connection structure to the list of listeners */
+
+ state = net_lock();
+ dq_addlast(&server->lc_node, &g_local_listeners);
+ net_unlock(state);
+
+ /* And change the server state to listing */
+
+ server->lc_state = LOCAL_STATE_LISTENING;
+ }
+
+ /* Loop until a connection is requested or we receive a signal */
+
+ while (dq_empty(&server->u.server.lc_waiters))
+ {
+ /* No.. wait for a connection or a signal */
+
+ ret = sem_wait(&server->lc_waitsem);
+ if (ret < 0)
+ {
+ int errval = errno;
+ DEBUGASSERT(errval == EINTR);
+ return -errval;
+ }
+ }
+
+ /* There is a client waiting for the connection */
+
+ return OK;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_recvfrom.c b/nuttx/net/local/local_recvfrom.c
new file mode 100644
index 000000000..c4c9e6a6c
--- /dev/null
+++ b/nuttx/net/local/local_recvfrom.c
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * net/local/local_recvfrom.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/net/net.h>
+
+#include "socket/socket.h"
+#include "local/local.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+/****************************************************************************
+ * Name: psock_fifo_read
+ *
+ * Description:
+ * A thin layer aroudn local_fifo_read that handles socket-related loss-of-
+ * connection events.
+ *
+ ****************************************************************************/
+
+static int psock_fifo_read(FAR struct socket *psock, FAR void *buf,
+ FAR size_t *readlen)
+{
+ FAR struct local_conn_s *conn = (FAR struct local_conn_s *)psock->s_conn;
+ int ret;
+
+ ret = local_fifo_read(conn->lc_infd, buf, readlen);
+ if (ret < 0)
+ {
+ /* -ECONNRESET is a special case. We may or not have received
+ * data, then the peer closed the connection.
+ */
+
+ if (ret == -ECONNRESET)
+ {
+ ndbg("ERROR: Lost connection: %d\n", ret);
+
+ /* Report an ungraceful loss of connection. This should
+ * eventually be reported as ENOTCONN.
+ */
+
+ psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
+ conn->lc_state = LOCAL_STATE_DISCONNECTED;
+
+ /* Did we receive any data? */
+
+ if (*readlen <= 0)
+ {
+ /* No.. return the ECONNRESET error now. Otherwise,
+ * process the received data and return ENOTCONN the
+ * next time that psock_recvfrom() is calle.
+ */
+
+ return ret;
+ }
+ }
+ else
+ {
+ ndbg("ERROR: Failed to read packet: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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 receive from for the complete list).
+ *
+ ****************************************************************************/
+
+ssize_t psock_local_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
+{
+ FAR struct local_conn_s *conn;
+ size_t readlen;
+ int ret;
+
+ DEBUGASSERT(psock && psock->s_conn && buf);
+ conn = (FAR struct local_conn_s *)psock->s_conn;
+
+ /* Verify that this is a connected peer socket and that it has opened the
+ * incoming FIFO for read-only access.
+ */
+
+ if (conn->lc_state != LOCAL_STATE_CONNECTED ||
+ conn->lc_infd < 0)
+ {
+ ndbg("ERROR: not connected\n");
+ return -ENOTCONN;
+ }
+
+ /* Are there still bytes in the FIFO from the last packet? */
+
+ if (conn->u.peer.lc_remaining == 0)
+ {
+ /* No.. Sync to the start of the next packet in the stream and get
+ * the size of the next packet.
+ */
+
+ ret = local_sync(conn->lc_infd);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to get packet length: %d\n", ret);
+ return ret;
+ }
+ else if (ret > 0xffff)
+ {
+ ndbg("ERROR: Packet is too big: %d\n", ret);
+ return -E2BIG;
+ }
+
+ conn->u.peer.lc_remaining = (uint16_t)ret;
+ }
+
+ /* Read the packet */
+ /* REVISIT: Does this make sense if the socket is SOCK_DGRAM? */
+
+ readlen = MIN(conn->u.peer.lc_remaining, len);
+ ret = psock_fifo_read(psock, buf, &readlen);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Adjust the number of bytes remaining to be read from the packet */
+
+ DEBUGASSERT(readlen <= conn->u.peer.lc_remaining);
+ conn->u.peer.lc_remaining -= readlen;
+
+ /* If this is a SOCK_STREAM socket and there are unread bytes remaining
+ * in the packet, we will get those bytes the next time recv is called.
+ * What if this is a SOCK_DRAM? REVISIT: Here we flush the remainder of
+ * the packet to the bit bucket.
+ */
+
+ if (psock->s_type == SOCK_DGRAM && conn->u.peer.lc_remaining > 0)
+ {
+ uint8_t bitbucket[32];
+ size_t tmplen;
+
+ do
+ {
+ /* Read 32 bytes into the bit bucket */
+
+ tmplen = MIN(conn->u.peer.lc_remaining, 32);
+ ret = psock_fifo_read(psock, bitbucket, &tmplen);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Adjust the number of bytes remaining to be read from the packet */
+
+ DEBUGASSERT(tmplen <= conn->u.peer.lc_remaining);
+ conn->u.peer.lc_remaining -= tmplen;
+ }
+ while (conn->u.peer.lc_remaining > 0);
+ }
+
+ /* Return the address family */
+
+ if (from)
+ {
+ ret = local_getaddr(conn, from, fromlen);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+
+ return readlen;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_recvutils.c b/nuttx/net/local/local_recvutils.c
new file mode 100644
index 000000000..a7eee1c4a
--- /dev/null
+++ b/nuttx/net/local/local_recvutils.c
@@ -0,0 +1,248 @@
+/****************************************************************************
+ * net/local/local_recvpacket.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_fifo_read
+ *
+ * Description:
+ * Read a data from the read-only FIFO.
+ *
+ * Parameters:
+ * fd - File descriptor of read-only FIFO.
+ * buf - Local to store the received data
+ * len - Length of data to receive [in]
+ * Length of data actually received [out]
+ *
+ * Return:
+ * Zero is returned on success; a negated errno value is returned on any
+ * failure. If -ECONNRESET is received, then the sending side has closed
+ * the FIFO. In this case, the returned data may still be valid (if the
+ * returned len > 0).
+ *
+ ****************************************************************************/
+
+int local_fifo_read(int fd, FAR uint8_t *buf, size_t *len)
+{
+ ssize_t total;
+ ssize_t nread;
+ int ret;
+
+ DEBUGASSERT(buf && len);
+
+ total = 0;
+ while (len > 0)
+ {
+ nread = read(fd, buf, *len);
+ if (nread < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ if (errcode != EINTR)
+ {
+ ndbg("ERROR: Read failed: %d\n", errcode);
+ ret = -errcode;
+ goto errout;
+ }
+
+ nvdbg("Ignoring signal\n");
+ }
+ else if (nread == 0)
+ {
+ /* The FIFO returns zero if the sending side of the connection
+ * has closed the FIFO.
+ */
+
+ ret = -ECONNRESET;
+ goto errout;
+ }
+ else
+ {
+ DEBUGASSERT(nread <= len);
+ len -= nread;
+ buf += nread;
+ }
+ }
+
+ ret = OK;
+
+errout:
+ *len = total;
+ return ret;
+}
+
+/****************************************************************************
+ * Name: local_sync
+ *
+ * Description:
+ * Read a sync bytes until the start of the packet is found.
+ *
+ * Parameters:
+ * fd - File descriptor of read-only FIFO.
+ *
+ * Return:
+ * The non-zero size of the following packet is returned on success; a
+ * negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int local_sync(int fd)
+{
+ size_t readlen;
+ uint16_t pktlen;
+ uint8_t sync;
+ int ret;
+
+ /* Loop until a valid pre-amble is encountered: SYNC bytes followed
+ * by one END byte.
+ */
+
+ do
+ {
+ /* Read until we encounter a sync byte */
+
+ do
+ {
+ readlen = sizeof(uint8_t);
+ ret = local_fifo_read(fd, &sync, &readlen);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to read sync bytes: %d\n", ret);
+ return ret;
+ }
+ }
+ while (sync != LOCAL_SYNC_BYTE);
+
+ /* Then read to the end of the SYNC sequence */
+
+ do
+ {
+ readlen = sizeof(uint8_t);
+ ret = local_fifo_read(fd, &sync, &readlen);
+ if (ret < 0)
+ {
+ ndbg("ERROR: Failed to read sync bytes: %d\n", ret);
+ return ret;
+ }
+ }
+ while (sync == LOCAL_SYNC_BYTE);
+ }
+ while (sync != LOCAL_END_BYTE);
+
+ /* Then read the packet length */
+
+ readlen = sizeof(uint16_t);
+ ret = local_fifo_read(fd, (FAR uint8_t *)&pktlen, &readlen);
+ return ret < 0 ? ret : pktlen;
+}
+
+/****************************************************************************
+ * Name: local_getaddr
+ *
+ * Description:
+ * Return the Unix domain address of a connection.
+ *
+ * Parameters:
+ * conn - The connection
+ * addr - The location to return the address
+ * addrlen - The size of the memory allocated by the caller to receive the
+ * address.
+ *
+ * Return:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int local_getaddr(FAR struct local_conn_s *conn, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen)
+{
+ FAR struct sockaddr_un *unaddr;
+ int totlen;
+ int pathlen;
+
+ DEBUGASSERT(conn && addr && addrlen && *addrlen >= sizeof(sa_family_t));
+
+ /* Get the length of the path (minus the NUL terminator) and the length
+ * of the whole Unix domain address.
+ */
+
+ pathlen = strnlen(conn->lc_path, UNIX_PATH_MAX-1);
+ totlen = sizeof(sa_family_t) + pathlen + 1;
+
+ /* If the length of the whole Unix domain address is larger than the
+ * buffer provided by the caller, then truncate the address to fit.
+ */
+
+ if (totlen > *addrlen)
+ {
+ pathlen -= (totlen - *addrlen);
+ totlen = *addrlen;
+ }
+
+ /* Copy the Unix domain address */
+
+ unaddr = (FAR struct sockaddr_un *)addr;
+ unaddr->sun_family = AF_LOCAL;
+ memcpy(unaddr->sun_path, conn->lc_path, pathlen);
+ unaddr->sun_path[pathlen] = '\0';
+
+ /* Return the Unix domain address size */
+
+ *addrlen = totlen;
+ return OK;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_release.c b/nuttx/net/local/local_release.c
new file mode 100644
index 000000000..e9b9d0c76
--- /dev/null
+++ b/nuttx/net/local/local_release.c
@@ -0,0 +1,129 @@
+/****************************************************************************
+ * net/local/local_release.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <semaphore.h>
+#include <errno.h>
+#include <queue.h>
+#include <assert.h>
+
+#include <nuttx/net/net.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_release
+ *
+ * Description:
+ * If the local, Unix domain socket is in the connected state, then
+ * disconnect it. Release the local connection structure in any event
+ *
+ * Input Parameters:
+ * conn - A reference to local connection structure
+ *
+ ****************************************************************************/
+
+int local_release(FAR struct local_conn_s *conn)
+{
+ net_lock_t state;
+
+ /* There should be no references on this structure */
+
+ DEBUGASSERT(conn->lc_crefs == 0);
+ state = net_lock();
+
+ /* We should not bet here with state LOCAL_STATE_ACCEPT. That is an
+ * internal state that should be atomic with respect to socket operations.
+ */
+
+ DEBUGASSERT(conn->lc_state != LOCAL_STATE_ACCEPT);
+
+ /* If the socket is connected (SOCK_STREAM client), then disconnect it */
+
+ if (conn->lc_state == LOCAL_STATE_CONNECTED ||
+ conn->lc_state == LOCAL_STATE_DISCONNECTED)
+ {
+ DEBUGASSERT(conn->lc_proto == SOCK_STREAM);
+
+ /* Just free the connection structure */
+ }
+
+ /* Is the socket is listening socket (SOCK_STREAM server) */
+
+ else if (conn->lc_state == LOCAL_STATE_LISTENING)
+ {
+ FAR struct local_conn_s *client;
+
+ DEBUGASSERT(conn->lc_proto == SOCK_STREAM);
+
+ /* Are there still clients waiting for a connection to the server? */
+
+ for (client = (FAR struct local_conn_s *)conn->u.server.lc_waiters.head;
+ client;
+ client = (FAR struct local_conn_s *)dq_next(&client->lc_node))
+ {
+ client->u.client.lc_result = -ENOTCONN;
+ sem_post(&client->lc_waitsem);
+ }
+
+ conn->u.server.lc_pending = 0;
+
+ /* Remove the server from the list of listeners. */
+
+ dq_rem(&conn->lc_node, &g_local_listeners);
+ }
+
+ /* For the remaining states (LOCAL_STATE_UNBOUND and LOCAL_STATE_UNBOUND),
+ * we simply free the connection structure.
+ */
+
+ /* Free the connection structure */
+
+ local_free(conn);
+ net_unlock(state);
+ return OK;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_send.c b/nuttx/net/local/local_send.c
new file mode 100644
index 000000000..74bf7f0a4
--- /dev/null
+++ b/nuttx/net/local/local_send.c
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * net/local/local_send.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/types.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/net/net.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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 (ignored for now)
+ *
+ * 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)
+{
+ FAR struct local_conn_s *peer;
+
+ DEBUGASSERT(psock && psock->s_conn && buf);
+ peer = (FAR struct local_conn_s *)psock->s_conn;
+
+ /* Verify that this is a connected peer socket and that it has opened the
+ * outgoing FIFO for write-only access.
+ */
+
+ if (peer->lc_type != LOCAL_STATE_CONNECTED ||
+ peer->lc_outfd < 0)
+ {
+ ndbg("ERROR: not connected\n");
+ return -ENOTCONN;
+ }
+
+ return local_send_packet(peer->lc_outfd, (FAR uint8_t *)buf, len);
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_sendpacket.c b/nuttx/net/local/local_sendpacket.c
new file mode 100644
index 000000000..3658175d6
--- /dev/null
+++ b/nuttx/net/local/local_sendpacket.c
@@ -0,0 +1,166 @@
+/****************************************************************************
+ * net/local/local_sendpacket.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define LOCAL_PREAMBLE_SIZE 8
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const uint8_t g_preamble[LOCAL_PREAMBLE_SIZE] =
+{
+ LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE,
+ LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_SYNC_BYTE, LOCAL_END_BYTE
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_fifo_write
+ *
+ * Description:
+ * Write a data on the write-only FIFO.
+ *
+ * Parameters:
+ * fd File descriptor of write-only FIFO.
+ * buf Data to send
+ * len Length of data to send
+ *
+ * Return:
+ * Zero is returned on success; a negated errno value is returned on any
+ * failure.
+ *
+ ****************************************************************************/
+
+static int local_fifo_write(int fd, FAR const uint8_t *buf, size_t len)
+{
+ ssize_t nwritten;
+
+ while (len > 0)
+ {
+ nwritten = write(fd, buf, len);
+ if (nwritten < 0)
+ {
+ int errcode = errno;
+ DEBUGASSERT(errcode > 0);
+
+ if (errcode != EINTR)
+ {
+ ndbg("ERROR: Write failed: %d\n", errcode);
+ return -errcode;
+ }
+
+ nvdbg("Ignoring signal\n");
+ }
+ else
+ {
+ DEBUGASSERT(nwritten > 0 && nwritten <= len);
+ len -= nwritten;
+ buf += nwritten;
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: local_send_packet
+ *
+ * Description:
+ * Send a packet on the write-only FIFO.
+ *
+ * Parameters:
+ * fd File descriptor of write-only FIFO.
+ * buf Data to send
+ * len Length of data to send
+ *
+ * Return:
+ * Zero is returned on success; a negated errno value is returned on any
+ * failure.
+ *
+ ****************************************************************************/
+
+int local_send_packet(int fd, FAR const uint8_t *buf, size_t len)
+{
+ uint16_t len16;
+ int ret;
+
+ /* Send the packet preamble */
+
+ ret = local_fifo_write(fd, g_preamble, LOCAL_PREAMBLE_SIZE);
+ if (ret == OK)
+ {
+ /* Send the packet length */
+
+ len16 = len;
+ ret = local_fifo_write(fd, (FAR const uint8_t *)&len16, sizeof(uint16_t));
+ if(ret == OK)
+ {
+ /* Send the packet data */
+
+ ret = local_fifo_write(fd, buf, len);
+ }
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
diff --git a/nuttx/net/local/local_sendto.c b/nuttx/net/local/local_sendto.c
new file mode 100644
index 000000000..a44333d6f
--- /dev/null
+++ b/nuttx/net/local/local_sendto.c
@@ -0,0 +1,84 @@
+/****************************************************************************
+ * net/local/local_sendto.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <nuttx/net/net.h>
+
+#include "local/local.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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)
+{
+#warning Missing logic
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_NET && CONFIG_NET_LOCAL */
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/netdev/netdev_register.c b/nuttx/net/netdev/netdev_register.c
index 1f9ff501e..a1f5c1251 100644
--- a/nuttx/net/netdev/netdev_register.c
+++ b/nuttx/net/netdev/netdev_register.c
@@ -65,7 +65,7 @@
#if defined(CONFIG_NET_SLIP)
# define NETDEV_DEFAULT_FORMAT NETDEV_SLIP_FORMAT
-#elif defined(CONFIG_NET_ETHERNET)
+#else /* if defined(CONFIG_NET_ETHERNET) */
# define NETDEV_DEFAULT_FORMAT NETDEV_ETH_FORMAT
#endif
diff --git a/nuttx/net/pkt/pkt.h b/nuttx/net/pkt/pkt.h
index 61fd45387..bf50889d5 100644
--- a/nuttx/net/pkt/pkt.h
+++ b/nuttx/net/pkt/pkt.h
@@ -100,7 +100,7 @@ extern "C"
*
* Description:
* Initialize the packet socket connection structures. Called once and
- * only from the UIP layer.
+ * only from the network initialization logic.
*
****************************************************************************/
diff --git a/nuttx/net/pkt/pkt_conn.c b/nuttx/net/pkt/pkt_conn.c
index 50a71c0c8..c47eea2d1 100644
--- a/nuttx/net/pkt/pkt_conn.c
+++ b/nuttx/net/pkt/pkt_conn.c
@@ -71,7 +71,7 @@ static struct pkt_conn_s g_pkt_connections[CONFIG_NET_PKT_CONNS];
static dq_queue_t g_free_pkt_connections;
static sem_t g_free_sem;
-/* A list of all allocated packet scoket connections */
+/* A list of all allocated packet socket connections */
static dq_queue_t g_active_pkt_connections;
@@ -129,6 +129,7 @@ void pkt_initialize(void)
for (i = 0; i < CONFIG_NET_PKT_CONNS; i++)
{
/* Mark the connection closed and move it to the free list */
+
g_pkt_connections[i].ifindex = 0;
dq_addlast(&g_pkt_connections[i].node, &g_free_pkt_connections);
}
diff --git a/nuttx/net/socket/Make.defs b/nuttx/net/socket/Make.defs
index 44645261a..0859d28a8 100644
--- a/nuttx/net/socket/Make.defs
+++ b/nuttx/net/socket/Make.defs
@@ -43,6 +43,13 @@ SOCK_CSRCS += net_clone.c net_poll.c net_vfcntl.c
ifeq ($(CONFIG_NET_TCP),y)
SOCK_CSRCS += send.c listen.c accept.c net_monitor.c
+else
+
+# Local Unix domain support
+
+ifeq ($(CONFIG_NET_LOCAL),y)
+SOCK_CSRCS += send.c listen.c accept.c
+endif
endif
# Socket options
diff --git a/nuttx/net/socket/accept.c b/nuttx/net/socket/accept.c
index 1a4dbd04c..65a164434 100644
--- a/nuttx/net/socket/accept.c
+++ b/nuttx/net/socket/accept.c
@@ -38,166 +38,25 @@
****************************************************************************/
#include <nuttx/config.h>
-#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP)
+#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
+ (defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL))
#include <sys/types.h>
#include <sys/socket.h>
-#include <semaphore.h>
-#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
-#include <arch/irq.h>
-
-#include <nuttx/net/net.h>
-#include <nuttx/net/ip.h>
-
#include "tcp/tcp.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-struct accept_s
-{
- FAR struct socket *acpt_sock; /* The accepting socket */
- sem_t acpt_sem; /* Wait for interrupt event */
- FAR struct sockaddr *acpt_addr; /* Return connection address */
- FAR struct tcp_conn_s *acpt_newconn; /* The accepted connection */
- int acpt_result; /* The result of the wait */
-};
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
- * Function: accept_tcpsender
- *
- * Description:
- * Get the sender's address from the UDP packet
- *
- * Parameters:
- * psock - The state structure of the accepting socket
- * conn - The newly accepted TCP connection
- * pstate - the recvfrom state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Running at the interrupt level
-*
- ****************************************************************************/
-
-#ifdef CONFIG_NET_TCP
-static inline void accept_tcpsender(FAR struct socket *psock,
- FAR struct tcp_conn_s *conn,
- FAR struct sockaddr *addr)
-{
- if (addr)
- {
-#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- /* If both IPv4 and IPv6 support are enabled, then we will need to
- * select which one to use when obtaining the sender's IP address.
- */
-
- if (psock->s_domain == PF_INET)
-#endif /* CONFIG_NET_IPv6 */
- {
- FAR struct sockaddr_in *inaddr = (FAR struct sockaddr_in *)addr;
-
- inaddr->sin_family = AF_INET;
- inaddr->sin_port = conn->rport;
- net_ipv4addr_copy(inaddr->sin_addr.s_addr, conn->u.ipv4.raddr);
- }
-#endif /* CONFIG_NET_IPv4 */
-
-#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- /* Otherwise, this the IPv6 address is needed */
-
- else
-#endif /* CONFIG_NET_IPv4 */
- {
- FAR struct sockaddr_in6 *inaddr = (FAR struct sockaddr_in6 *)addr;
-
- DEBUGASSERT(psock->s_domain == PF_INET6);
- inaddr->sin6_family = AF_INET6;
- inaddr->sin6_port = conn->rport;
- net_ipv6addr_copy(inaddr->sin6_addr.s6_addr, conn->u.ipv6.raddr);
- }
-#endif /* CONFIG_NET_IPv6 */
- }
-}
-#endif /* CONFIG_NET_TCP */
-
-/****************************************************************************
- * Function: accept_interrupt
- *
- * Description:
- * Receive interrupt level callbacks when connections occur
- *
- * Parameters:
- * listener The conection stucture of the listener
- * conn The connection stucture that was just accepted
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Running at the interrupt level
- *
- ****************************************************************************/
-
-static int accept_interrupt(FAR struct tcp_conn_s *listener,
- FAR struct tcp_conn_s *conn)
-{
- struct accept_s *pstate = (struct accept_s *)listener->accept_private;
- int ret = -EINVAL;
-
- if (pstate)
- {
- /* Get the connection address */
-
- accept_tcpsender(pstate->acpt_sock, conn, pstate->acpt_addr);
-
- /* Save the connection structure */
-
- pstate->acpt_newconn = conn;
- pstate->acpt_result = OK;
-
- /* There should be a reference of one on the new connection */
-
- DEBUGASSERT(conn->crefs == 1);
-
- /* Wake-up the waiting caller thread */
-
- sem_post(&pstate->acpt_sem);
-
- /* Stop any further callbacks */
-
- listener->accept_private = NULL;
- listener->accept = NULL;
- ret = OK;
- }
-
- return ret;
-}
-
-/****************************************************************************
* Public Functions
****************************************************************************/
@@ -229,7 +88,7 @@ static int accept_interrupt(FAR struct tcp_conn_s *listener,
* connections are present on the queue, accept returns EAGAIN.
*
* Parameters:
- * sockfd The listening socket descriptior
+ * sockfd The listening socket descriptor
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
*
@@ -275,9 +134,6 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
FAR struct socket *psock = sockfd_socket(sockfd);
FAR struct socket *pnewsock;
- FAR struct tcp_conn_s *conn;
- struct accept_s state;
- net_lock_t save;
int newfd;
int err;
int ret;
@@ -327,6 +183,12 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
if (addr)
{
+ /* If an address is provided, then the lenght must also be provided. */
+
+ DEBUGASSERT(addrlen);
+
+ /* A valid length depends on the address domain */
+
switch (psock->s_domain)
{
#ifdef CONFIG_NET_IPv4
@@ -353,6 +215,18 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
break;
#endif /* CONFIG_NET_IPv6 */
+#ifdef CONFIG_NET_LOCAL
+ case PF_LOCAL:
+ {
+ if (*addrlen < sizeof(sa_family_t))
+ {
+ err = EBADF;
+ goto errout;
+ }
+ }
+ break;
+#endif /* CONFIG_NET_IPv6 */
+
default:
DEBUGPANIC();
err = EINVAL;
@@ -378,132 +252,60 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
goto errout_with_socket;
}
- /* Check the backlog to see if there is a connection already pending for
- * this listener.
- */
+ /* Initialize the socket structure and mark the socket as connected. */
- save = net_lock();
- conn = (struct tcp_conn_s *)psock->s_conn;
-
-#ifdef CONFIG_NET_TCPBACKLOG
- state.acpt_newconn = tcp_backlogremove(conn);
- if (state.acpt_newconn)
- {
- /* Yes... get the address of the connected client */
-
- nvdbg("Pending conn=%p\n", state.acpt_newconn);
- accept_tcpsender(psock, state.acpt_newconn, addr);
- }
+ pnewsock->s_domain = psock->s_domain;
+ pnewsock->s_type = SOCK_STREAM;
+ pnewsock->s_flags |= _SF_CONNECTED;
+ pnewsock->s_flags &= ~_SF_CLOSED;
- /* In general, this uIP-based implementation will not support non-blocking
- * socket operations... except in a few cases: Here for TCP accept with backlog
- * enabled. If this socket is configured as non-blocking then return EAGAIN
- * if there is no pending connection in the backlog.
- */
+ /* Perform the correct accept operation for this address domain */
- else if (_SS_ISNONBLOCK(psock->s_flags))
- {
- err = EAGAIN;
- goto errout_with_lock;
- }
- else
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
#endif
{
- /* Set the socket state to accepting */
-
- psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);
-
- /* Perform the TCP accept operation */
-
- /* Initialize the state structure. This is done with interrupts
- * disabled because we don't want anything to happen until we
- * are ready.
- */
+ /* Perform the local accept operation (with the network unlocked) */
- state.acpt_sock = psock;
- state.acpt_addr = addr;
- state.acpt_newconn = NULL;
- state.acpt_result = OK;
- sem_init(&state.acpt_sem, 0, 0);
-
- /* Set up the callback in the connection */
-
- conn->accept_private = (void*)&state;
- conn->accept = accept_interrupt;
-
- /* Wait for the send to complete or an error to occur: NOTES: (1)
- * net_lockedwait will also terminate if a signal is received, (2)
- * interrupts may be disabled! They will be re-enabled while the
- * task sleeps and automatically re-enabled when the task restarts.
- */
-
- ret = net_lockedwait(&state.acpt_sem);
+ ret = psock_local_accept(psock, addr, addrlen, &pnewsock->s_conn);
if (ret < 0)
{
- /* The value returned by net_lockedwait() the same as the value
- * returned by sem_wait(): Zero (OK) is returned on success; -1
- * (ERROR) is returned on a failure with the errno value set
- * appropriately.
- *
- * We have to preserve the errno value here because it may be
- * altered by intervening operations.
- */
-
- err = get_errno();
+ err = -ret;
+ goto errout_with_socket;
}
+ }
+#endif /* CONFIG_NET_LOCAL */
- /* Make sure that no further interrupts are processed */
-
- conn->accept_private = NULL;
- conn->accept = NULL;
-
- sem_destroy(&state. acpt_sem);
-
- /* Set the socket state to idle */
-
- psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ net_lock_t state;
- /* Check for a errors. Errors are signalled by negative errno values
- * for the send length.
- */
+ /* Perform the local accept operation (with the network locked) */
- if (state.acpt_result != 0)
+ state = net_lock();
+ ret = psock_tcp_accept(psock, addr, addrlen, &pnewsock->s_conn);
+ if (ret < 0)
{
- err = state.acpt_result;
- goto errout_with_lock;
+ net_unlock(state);
+ err = -ret;
+ goto errout_with_socket;
}
- /* If net_lockedwait failed, then we were probably reawakened by a
- * signal. In this case, logic above will have set 'err' to the
- * ernno value returned by net_lockedwait().
+ /* Begin monitoring for TCP connection events on the newly connected
+ * socket
*/
- if (ret < 0)
- {
- goto errout_with_lock;
- }
+ net_startmonitor(pnewsock);
+ net_unlock(state);
}
+#endif /* CONFIG_NET_TCP */
- /* Initialize the socket structure and mark the socket as connected.
- * (The reference count on the new connection structure was set in the
- * interrupt handler).
- */
-
- pnewsock->s_domain = psock->s_domain;
- pnewsock->s_type = SOCK_STREAM;
- pnewsock->s_conn = state.acpt_newconn;
- pnewsock->s_flags |= _SF_CONNECTED;
- pnewsock->s_flags &= ~_SF_CLOSED;
-
- /* Begin monitoring for TCP connection events on the newly connected socket */
-
- net_startmonitor(pnewsock);
- net_unlock(save);
return newfd;
-errout_with_lock:
- net_unlock(save);
-
errout_with_socket:
sockfd_release(newfd);
@@ -512,4 +314,4 @@ errout:
return ERROR;
}
-#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */
+#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && (CONFIG_NET_TCP || CONFIG_NET_LOCAL) */
diff --git a/nuttx/net/socket/bind.c b/nuttx/net/socket/bind.c
index d905e5aaf..6407c0add 100644
--- a/nuttx/net/socket/bind.c
+++ b/nuttx/net/socket/bind.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/bind.c
*
- * Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <errno.h>
#include <string.h>
#include <debug.h>
@@ -58,6 +59,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
/****************************************************************************
* Private Functions
@@ -116,8 +118,8 @@ static int pkt_bind(FAR struct pkt_conn_s *conn,
*
* Description:
* bind() gives the socket 'psock' 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
+ * '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:
@@ -175,6 +177,12 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
break;
#endif
+#ifdef CONFIG_NET_LOCAL
+ case AF_LOCAL:
+ minlen = sizeof(sa_family_t);
+ break;
+#endif
+
#ifdef CONFIG_NET_PKT
case AF_PACKET:
minlen = sizeof(struct sockaddr_ll);
@@ -204,18 +212,87 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
break;
#endif
-#ifdef CONFIG_NET_TCP
+ /* Bind a stream socket which may either be TCP/IP or a local, Unix
+ * domain socket.
+ */
+
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
- ret = tcp_bind(psock->s_conn, addr);
- psock->s_flags |= _SF_BOUND;
+ {
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ /* Is this a Unix domain socket? */
+
+ if (psock->s_domain == PF_LOCAL)
+#endif
+ {
+ /* Bind the Unix domain connection structure */
+
+ ret = psock_local_bind(psock, addr, addrlen);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ /* Bind the TCP/IP connection structure */
+
+ ret = tcp_bind(psock->s_conn, addr);
+ }
+#endif /* CONFIG_NET_TCP */
+
+ /* Mark the socket bound */
+
+ if (ret >= 0)
+ {
+ psock->s_flags |= _SF_BOUND;
+ }
+ }
break;
+#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL */
+
+ /* Bind a datagram socket which may either be TCP/IP or a local, Unix
+ * domain socket.
+ */
+
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_DGRAM:
+ {
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ /* Is this a Unix domain socket? */
+
+ if (psock->s_domain == PF_LOCAL)
#endif
+ {
+ /* Bind the Unix domain connection structure */
+
+ ret = psock_local_bind(psock, addr, addrlen);
+ }
+#endif /* CONFIG_NET_LOCAL */
#ifdef CONFIG_NET_UDP
- case SOCK_DGRAM:
- ret = udp_bind(psock->s_conn, addr);
- break;
+#ifdef CONFIG_NET_LOCAL
+ else
#endif
+ {
+ /* Bind the UDPP/IP connection structure */
+
+ ret = udp_bind(psock->s_conn, addr);
+ }
+#endif /* CONFIG_NET_UDP */
+
+ /* Mark the socket bound */
+
+ if (ret >= 0)
+ {
+ psock->s_flags |= _SF_BOUND;
+ }
+ }
+ break;
+#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL */
default:
err = EBADF;
diff --git a/nuttx/net/socket/connect.c b/nuttx/net/socket/connect.c
index e152df888..9830fa55e 100644
--- a/nuttx/net/socket/connect.c
+++ b/nuttx/net/socket/connect.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/connect.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2012, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#include <stdint.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
#include <arch/irq.h>
@@ -56,6 +57,7 @@
#include "devif/devif.h"
#include "tcp/tcp.h"
#include "udp/udp.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
@@ -460,7 +462,7 @@ 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)
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
int ret;
#endif
int err;
@@ -501,6 +503,18 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
break;
#endif
+#ifdef CONFIG_NET_LOCAL
+ case AF_LOCAL:
+ {
+ if (addrlen < sizeof(sa_family_t))
+ {
+ err = EBADF;
+ goto errout;
+ }
+ }
+ break;
+#endif
+
default:
DEBUGPANIC();
err = EAFNOSUPPORT;
@@ -511,7 +525,7 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
switch (psock->s_type)
{
-#ifdef CONFIG_NET_TCP
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
{
/* Verify that the socket is not already connected */
@@ -522,9 +536,30 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
goto errout;
}
- /* Its not ... connect it */
+ /* It's not ... connect it */
+
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
+#endif
+ {
+ /* Connect to the local Unix domain server */
+
+ ret = local_connect(psock->s_conn, addr);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ /* Connect the TCP/IP socket */
+
+ ret = psock_tcp_connect(psock, addr);
+ }
+#endif /* CONFIG_NET_TCP */
- ret = psock_tcp_connect(psock, addr);
if (ret < 0)
{
err = -ret;
@@ -532,12 +567,31 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
}
}
break;
-#endif
+#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL */
-#ifdef CONFIG_NET_UDP
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
case SOCK_DGRAM:
{
- ret = udp_connect(psock->s_conn, addr);
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ if (psock->s_domain == PF_LOCAL)
+#endif
+ {
+ /* Perform the datagram connection logic */
+
+ ret = local_connect(psock->s_conn, addr);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ ret = udp_connect(psock->s_conn, addr);
+ }
+#endif /* CONFIG_NET_UDP */
+
if (ret < 0)
{
err = -ret;
@@ -545,7 +599,7 @@ int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
}
}
break;
-#endif
+#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL */
default:
err = EBADF;
diff --git a/nuttx/net/socket/listen.c b/nuttx/net/socket/listen.c
index b9b8d1d5b..cdfc4d9d8 100644
--- a/nuttx/net/socket/listen.c
+++ b/nuttx/net/socket/listen.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/listen.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,7 @@
#include <debug.h>
#include "tcp/tcp.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
@@ -89,7 +90,6 @@
int listen(int sockfd, int backlog)
{
FAR struct socket *psock = sockfd_socket(sockfd);
- struct tcp_conn_s *conn;
int err;
/* Verify that the sockfd corresponds to valid, allocated socket */
@@ -111,39 +111,73 @@ int listen(int sockfd, int backlog)
{
err = EBADF;
}
+
goto errout;
}
/* Verify that the sockfd corresponds to a connected SOCK_STREAM */
- conn = (FAR struct tcp_conn_s *)psock->s_conn;
- if (psock->s_type != SOCK_STREAM || !psock->s_conn || conn->lport <= 0)
+ if (psock->s_type != SOCK_STREAM || !psock->s_conn)
{
err = EOPNOTSUPP;
goto errout;
}
- /* Set up the backlog for this connection */
-
-#ifdef CONFIG_NET_TCPBACKLOG
- err = tcp_backlogcreate(conn, backlog);
- if (err < 0)
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
+#endif
{
- err = -err;
- goto errout;
+ FAR struct local_conn_s *conn =
+ (FAR struct local_conn_s *)psock->s_conn;
+
+ err = local_listen(conn, backlog);
+ if (err < 0)
+ {
+ err = -err;
+ goto errout;
+ }
}
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ FAR struct tcp_conn_s *conn =
+ (FAR struct tcp_conn_s *)psock->s_conn;
+
+ if (conn->lport <= 0)
+ {
+ err = EOPNOTSUPP;
+ goto errout;
+ }
+
+ /* Set up the backlog for this connection */
+
+#ifdef CONFIG_NET_TCPBACKLOG
+ err = tcp_backlogcreate(conn, backlog);
+ if (err < 0)
+ {
+ err = -err;
+ goto errout;
+ }
#endif
- /* Start listening to the bound port. This enables callbacks when accept()
- * is called and enables poll()/select() logic.
- */
+ /* Start listening to the bound port. This enables callbacks when
+ * accept() is called and enables poll()/select() logic.
+ */
+
+ tcp_listen(conn);
+ }
+#endif /* CONFIG_NET_TCP */
- tcp_listen(conn);
psock->s_flags |= _SF_LISTENING;
return OK;
errout:
- errno = err;
+ set_errno(err);
return ERROR;
}
diff --git a/nuttx/net/socket/net_close.c b/nuttx/net/socket/net_close.c
index a2ef7e91f..e33853fa7 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->lc_crefs <= 1)
+ {
+ conn->lc_crefs = 0;
+ local_release(conn);
+ }
+ else
+ {
+ /* No.. Just decrement the reference count */
+
+ conn->lc_crefs--;
+ }
+}
+#endif /* CONFIG_NET_LOCAL */
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -493,71 +533,110 @@ int psock_close(FAR struct socket *psock)
switch (psock->s_type)
{
-#ifdef CONFIG_NET_PKT
- case SOCK_RAW:
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_STREAM:
{
- FAR struct pkt_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_TCP
+ 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 */
- pkt_free(psock->s_conn); /* Free uIP resources */
+ local_close(psock);
}
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
else
+#endif
{
- /* No.. Just decrement the reference count */
+ FAR struct tcp_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... 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;
+ }
+ }
+ else
+ {
+ /* No.. Just decrement the reference count */
+
+ conn->crefs--;
+ }
}
+#endif /* CONFIG_NET_TCP */
}
break;
#endif
-#ifdef CONFIG_NET_TCP
- case SOCK_STREAM:
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_DGRAM:
{
- FAR struct tcp_conn_s *conn = psock->s_conn;
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ 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_UDP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
{
- /* Yes... then perform the disconnection now */
+ 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).
+ */
- 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... free the connection structure */
- goto errout_with_psock;
+ conn->crefs = 0;
+ udp_free(psock->s_conn);
}
- }
- else
- {
- /* No.. Just decrement the reference count */
+ else
+ {
+ /* No.. Just decrement the reference count */
- conn->crefs--;
+ conn->crefs--;
+ }
}
+#endif /* CONFIG_NET_UDP */
}
break;
#endif
-#ifdef CONFIG_NET_UDP
- case SOCK_DGRAM:
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
{
- FAR struct udp_conn_s *conn = psock->s_conn;
+ FAR struct pkt_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).
@@ -568,7 +647,7 @@ int psock_close(FAR struct socket *psock)
/* Yes... free the connection structure */
conn->crefs = 0; /* No more references on the connection */
- udp_free(psock->s_conn); /* Free uIP resources */
+ pkt_free(psock->s_conn); /* Free uIP resources */
}
else
{
diff --git a/nuttx/net/socket/recvfrom.c b/nuttx/net/socket/recvfrom.c
index e8994ff01..8e38d7881 100644
--- a/nuttx/net/socket/recvfrom.c
+++ b/nuttx/net/socket/recvfrom.c
@@ -68,6 +68,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
@@ -1580,7 +1581,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
****************************************************************************/
ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
- int flags,FAR struct sockaddr *from,
+ int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen)
{
ssize_t ret;
@@ -1614,23 +1615,37 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Get the minimum socket length */
+ switch (psock->s_domain)
+ {
#ifdef CONFIG_NET_IPv4
-#ifdef CONFIG_NET_IPv6
- if (psock->s_domain == PF_INET)
+ case PF_INET:
+ {
+ minlen = sizeof(struct sockaddr_in);
+ }
+ break;
#endif
- {
- minlen = sizeof(struct sockaddr_in);
- }
-#endif /*CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6
-#ifdef CONFIG_NET_IPv4
- else
+ case PF_INET6:
+ {
+ minlen = sizeof(struct sockaddr_in6);
+ }
+ break;
#endif
- {
- minlen = sizeof(struct sockaddr_in6);
+
+#ifdef CONFIG_NET_LOCAL
+ case PF_LOCAL:
+ {
+ minlen = sizeof(sa_family_t);
+ }
+ break;
+#endif
+
+ default:
+ DEBUGPANIC();
+ err = EINVAL;
+ goto errout;
}
-#endif /*CONFIG_NET_IPv6 */
if (*fromlen < minlen)
{
@@ -1646,30 +1661,72 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
/* Read from the network interface driver buffer */
/* Or perform the TCP/IP or UDP recv() operation */
-#if defined(CONFIG_NET_PKT)
- if (psock->s_type == SOCK_RAW)
+ switch (psock->s_type)
{
- ret = pkt_recvfrom(psock, buf, len, from);
- }
- else
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
+ {
+ ret = pkt_recvfrom(psock, buf, len, from);
+ }
+ break;
+#endif /* CONFIG_NET_PKT */
+
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_STREAM:
+ {
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
#endif
-#if defined(CONFIG_NET_TCP)
- if (psock->s_type == SOCK_STREAM)
- {
- ret = tcp_recvfrom(psock, buf, len, from);
- }
- else
+ {
+ ret = psock_local_recvfrom(psock, buf, len, flags,
+ from, fromlen);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
#endif
-#if defined(CONFIG_NET_UDP)
- if (psock->s_type == SOCK_DGRAM)
- {
- ret = udp_recvfrom(psock, buf, len, from);
- }
- else
+ {
+ ret = tcp_recvfrom(psock, buf, len, from);
+ }
+#endif /* CONFIG_NET_TCP */
+ }
+ break;
+#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL */
+
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_DGRAM:
+ {
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ if (psock->s_domain == PF_LOCAL)
#endif
- {
- ndbg("ERROR: Unsupported socket type: %d\n", psock->s_type);
- ret = -ENOSYS;
+ {
+ ret = psock_local_recvfrom(psock, buf, len, flags,
+ from, fromlen);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
+ else
+#endif
+ {
+ ret = udp_recvfrom(psock, buf, len, from);
+ }
+#endif /* CONFIG_NET_UDP */
+ }
+ break;
+#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL */
+
+ default:
+ {
+ ndbg("ERROR: Unsupported socket type: %d\n", psock->s_type);
+ ret = -ENOSYS;
+ }
+ break;
}
/* Set the socket state to idle */
diff --git a/nuttx/net/socket/send.c b/nuttx/net/socket/send.c
index 1b7358481..ddcc97ea3 100644
--- a/nuttx/net/socket/send.c
+++ b/nuttx/net/socket/send.c
@@ -45,6 +45,7 @@
#include "tcp/tcp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
#include "socket/socket.h"
/****************************************************************************
@@ -138,17 +139,31 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
case SOCK_RAW:
{
ret = psock_pkt_send(psock, buf, len);
- break;
}
+ break;
#endif
-#if defined(CONFIG_NET_TCP)
case SOCK_STREAM:
{
- ret = psock_tcp_send(psock, buf, len);
- break;
- }
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ if (psock->s_domain == PF_LOCAL)
+#endif
+ {
+ ret = psock_local_send(psock, buf, len, flags);
+ }
+#endif /* CONFIG_NET_LOCAL */
+
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ else
#endif
+ {
+ ret = psock_tcp_send(psock, buf, len);
+ }
+#endif /* CONFIG_NET_TCP */
+ }
+ break;
default:
{
diff --git a/nuttx/net/socket/sendto.c b/nuttx/net/socket/sendto.c
index 0134bde3c..85ce83f31 100644
--- a/nuttx/net/socket/sendto.c
+++ b/nuttx/net/socket/sendto.c
@@ -467,6 +467,12 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
break;
#endif
+#ifdef CONFIG_NET_IPv6
+ case AF_LOCAL:
+ minlen = sizeof(sa_family_t);
+ break;
+#endif
+
default:
ndbg("ERROR: Unrecognized address family: %d\n", to->sa_family);
err = EAFNOSUPPORT;
@@ -511,9 +517,13 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
}
#endif
- /* Perform the UDP sendto operation */
+#ifdef CONFIG_NET_LOCAL
+ /* Perform the Unix domain sendto operation */
+# warning Missing logic
+#endif
#ifdef CONFIG_NET_UDP
+ /* Perform the UDP sendto operation */
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
diff --git a/nuttx/net/socket/socket.c b/nuttx/net/socket/socket.c
index 1ce2e0890..7cec99427 100644
--- a/nuttx/net/socket/socket.c
+++ b/nuttx/net/socket/socket.c
@@ -51,6 +51,153 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
+#include "local/local.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: psock_tcp_alloc
+ *
+ * Description:
+ * Allocate and attach a TCP connection structure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP
+static int psock_tcp_alloc(FAR struct socket *psock)
+{
+ /* Allocate the TCP connection structure */
+
+ FAR struct tcp_conn_s *conn = tcp_alloc(psock->s_domain);
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ return -ENOMEM;
+ }
+
+ /* Set the reference count on the connection structure. This reference
+ * count will be incremented 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;
+ return OK;
+}
+#endif /* CONFIG_NET_TCP */
+
+/****************************************************************************
+ * Name: psock_udp_alloc
+ *
+ * Description:
+ * Allocate and attach a UDP connection structure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_UDP
+static int psock_udp_alloc(FAR struct socket *psock)
+{
+ /* Allocate the UDP connection structure */
+
+ FAR struct udp_conn_s *conn = udp_alloc(psock->s_domain);
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ return -ENOMEM;
+ }
+
+ /* Set the reference count on the connection structure. This reference
+ * count will be incremented 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;
+ return OK;
+}
+#endif /* CONFIG_NET_UDP */
+
+/****************************************************************************
+ * Name: psock_pkt_alloc
+ *
+ * Description:
+ * Allocate and attach a raw packet connection structure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_PKT
+static int psock_pkt_alloc(FAR struct socket *psock)
+{
+ /* Allocate the packet socket connection structure and save in the new
+ * socket instance.
+ */
+
+ FAR struct pkt_conn_s *conn = pkt_alloc();
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ return -ENOMEM;
+ }
+
+ /* Set the reference count on the connection structure. This reference
+ * count will be incremented 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;
+ return OK;
+}
+#endif /* CONFIG_NET_PKT */
+
+/****************************************************************************
+ * Name: psock_local_alloc
+ *
+ * Description:
+ * Allocate and attach a local, Unix domain connection structure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_LOCAL
+static int psock_local_alloc(FAR struct socket *psock)
+{
+ /* Allocate the local connection structure */
+
+ FAR struct local_conn_s *conn = local_alloc();
+ if (!conn)
+ {
+ /* Failed to reserve a connection structure */
+
+ return -ENOMEM;
+ }
+
+ /* Set the reference count on the connection structure. This reference
+ * count will be incremented only if the socket is dup'ed
+ */
+
+ DEBUGASSERT(conn->lc_crefs == 0);
+ conn->lc_crefs = 1;
+
+ /* Save the pre-allocated connection in the socket structure */
+
+ psock->s_conn = conn;
+ return OK;
+}
+#endif /* CONFIG_NET_LOCAL */
/****************************************************************************
* Public Functions
@@ -96,7 +243,11 @@
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 ret;
int err;
/* Only PF_INET, PF_INET6 or PF_PACKET domains supported */
@@ -105,13 +256,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
@@ -129,31 +292,71 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
switch (type)
{
-#ifdef CONFIG_NET_TCP
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
- if ((protocol != 0 && protocol != IPPROTO_TCP) || !ipdomain)
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
+#endif
{
- err = EPROTONOSUPPORT;
- goto errout;
+ if ((protocol != 0 && protocol != IPPROTO_TCP) || !dgramok)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
+ }
+#endif /* CONFIG_NET_TCP */
+
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ else
+#endif
+ {
+ if (protocol != 0 || !dgramok)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
}
+#endif /* CONFIG_NET_LOCAL */
break;
+#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL */
+
+#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
+ case SOCK_DGRAM:
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
#endif
+ {
+ if ((protocol != 0 && protocol != IPPROTO_UDP) || !dgramok)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
+ }
+#endif /* CONFIG_NET_UDP */
+#ifdef CONFIG_NET_LOCAL
#ifdef CONFIG_NET_UDP
- case SOCK_DGRAM:
- if ((protocol != 0 && protocol != IPPROTO_UDP) || !ipdomain)
+ else
+#endif
{
- err = EPROTONOSUPPORT;
- goto errout;
+ if (protocol != 0 || !dgramok)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
}
+#endif /* CONFIG_NET_LOCAL */
break;
-#endif
+#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL */
#ifdef CONFIG_NET_PKT
case SOCK_RAW:
- if (ipdomain)
+ if (dgramok)
{
err = EPROTONOSUPPORT;
goto errout;
@@ -185,56 +388,78 @@ 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.
- */
+#ifdef CONFIG_NET_TCP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
+#endif
+ {
+ /* Allocate and attach the TCP connection structure */
+
+ ret = psock_tcp_alloc(psock);
+ }
+#endif /* CONFIG_NET_TCP */
- FAR struct tcp_conn_s *conn = tcp_alloc(domain);
- if (!conn)
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_TCP
+ else
+#endif
{
- /* Failed to reserve a connection structure */
+ /* Allocate and attach the local connection structure */
- goto errout; /* With err == ENFILE or ENOMEM */
+ ret = psock_local_alloc(psock);
}
+#endif /* CONFIG_NET_LOCAL */
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+ /* Check for failures to allocate the connection structure. */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ if (ret < 0)
+ {
+ /* Failed to reserve a connection structure */
+
+ err = -ret;
+ goto errout;
+ }
}
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.
- */
+#ifdef CONFIG_NET_UDP
+#ifdef CONFIG_NET_LOCAL
+ if (ipdomain)
+#endif
+ {
+ /* Allocate and attach the UDP connection structure */
- FAR struct udp_conn_s *conn = udp_alloc(domain);
- if (!conn)
+ ret = psock_udp_alloc(psock);
+ }
+#endif /* CONFIG_NET_UDP */
+
+#ifdef CONFIG_NET_LOCAL
+#ifdef CONFIG_NET_UDP
+ else
+#endif
{
- /* Failed to reserve a connection structure */
+ /* Allocate and attach the local connection structure */
- goto errout; /* With err == ENFILE or ENOMEM */
+ ret = psock_local_alloc(psock);
}
+#endif /* CONFIG_NET_LOCAL */
- /* Set the reference count on the connection structure. This
- * reference count will be increment only if the socket is
- * dup'ed
- */
+ /* Check for failures to allocate the connection structure. */
- DEBUGASSERT(conn->crefs == 0);
- psock->s_conn = conn;
- conn->crefs = 1;
+ if (ret < 0)
+ {
+ /* Failed to reserve a connection structure */
+
+ err = -ret;
+ goto errout;
+ }
}
break;
#endif
@@ -242,26 +467,14 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
#ifdef CONFIG_NET_PKT
case SOCK_RAW:
{
- /* Allocate the packet socket connection structure and save
- * in the new socket instance.
- */
-
- FAR struct pkt_conn_s *conn = pkt_alloc();
- if (!conn)
+ ret = psock_pkt_alloc(FAR struct socket *psock)
+ if (ret < 0)
{
/* Failed to reserve a connection structure */
+ err = -ret;
goto errout;
}
-
- /* 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);
- psock->s_conn = conn;
- conn->crefs = 1;
}
break;
#endif
diff --git a/nuttx/net/tcp/Make.defs b/nuttx/net/tcp/Make.defs
index d213960b7..41a03469e 100644
--- a/nuttx/net/tcp/Make.defs
+++ b/nuttx/net/tcp/Make.defs
@@ -39,6 +39,8 @@ ifeq ($(CONFIG_NET_TCP),y)
# Socket layer
+SOCK_CSRCS += tcp_accept.c
+
ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y)
SOCK_CSRCS += tcp_send_buffered.c
else
diff --git a/nuttx/net/tcp/tcp.h b/nuttx/net/tcp/tcp.h
index 1d6e78e8c..010b00989 100644
--- a/nuttx/net/tcp/tcp.h
+++ b/nuttx/net/tcp/tcp.h
@@ -267,9 +267,8 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
-/* Defined in tcp_conn.c ****************************************************/
-
-struct sockaddr; /* Forward reference */
+struct sockaddr; /* Forward reference */
+struct socket; /* Forward reference */
/****************************************************************************
* Name: tcp_initialize
@@ -389,7 +388,6 @@ int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr);
int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr);
-/* Defined in tcp_ipselect.c ************************************************/
/****************************************************************************
* Function: tcp_ipv4_select
*
@@ -414,7 +412,6 @@ void tcp_ipv4_select(FAR struct net_driver_s *dev);
void tcp_ipv6_select(FAR struct net_driver_s *dev);
#endif
-/* Defined in tcp_seqno.c ***************************************************/
/****************************************************************************
* Name: tcp_setsequence
*
@@ -481,7 +478,6 @@ void tcp_initsequence(FAR uint8_t *seqno);
void tcp_nextsequence(void);
-/* Defined in tcp_poll.c ****************************************************/
/****************************************************************************
* Name: tcp_poll
*
@@ -502,7 +498,6 @@ void tcp_nextsequence(void);
void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn);
-/* Defined in tcp_timer.c ***************************************************/
/****************************************************************************
* Name: tcp_timer
*
@@ -525,7 +520,6 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn);
void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
int hsec);
-/* Defined in tcp_listen.c **************************************************/
/****************************************************************************
* Function: tcp_listen_initialize
*
@@ -593,7 +587,6 @@ bool tcp_islistener(uint16_t portno);
int tcp_accept_connection(FAR struct net_driver_s *dev,
FAR struct tcp_conn_s *conn, uint16_t portno);
-/* Defined in tcp_send.c ****************************************************/
/****************************************************************************
* Name: tcp_send
*
@@ -658,7 +651,6 @@ void tcp_reset(FAR struct net_driver_s *dev);
void tcp_ack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint8_t ack);
-/* Defined in tcp_appsend.c *************************************************/
/****************************************************************************
* Name: tcp_appsend
*
@@ -705,7 +697,6 @@ void tcp_appsend(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
void tcp_rexmit(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
uint16_t result);
-/* Defined in tcp_input.c ***************************************************/
/****************************************************************************
* Name: tcp_ipv4_input
*
@@ -748,7 +739,6 @@ void tcp_ipv4_input(FAR struct net_driver_s *dev);
void tcp_ipv6_input(FAR struct net_driver_s *dev);
#endif
-/* Defined in tcp_callback.c ************************************************/
/****************************************************************************
* Function: tcp_callback
*
@@ -794,7 +784,6 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
uint16_t nbytes);
#endif
-/* Defined in tcp_backlog.c *************************************************/
/****************************************************************************
* Function: tcp_backlogcreate
*
@@ -910,7 +899,32 @@ int tcp_backlogdelete(FAR struct tcp_conn_s *conn,
# define tcp_backlogdelete(c,b) (-ENOSYS)
#endif
-/* Defined in tcp_send_buffered.c or tcp_send_unbuffered.c ******************/
+/****************************************************************************
+ * Function: tcp_accept
+ *
+ * Description:
+ * This function implements accept() for TCP/IP sockets. See the
+ * description of accept() for further information.
+ *
+ * Parameters:
+ * psock The listening TCP socket structure
+ * addr Receives the address of the connecting client
+ * addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
+ * newconn The new, accepted TCP connection structure
+ *
+ * Returned Value:
+ * Returns zero (OK) on success or a negated errno value on failure.
+ * See the description of accept of the possible errno values in the
+ * description of accept().
+ *
+ * Assumptions:
+ * Network is locked.
+ *
+ ****************************************************************************/
+
+int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR void **newconn);
+
/****************************************************************************
* Function: psock_tcp_send
*
@@ -972,7 +986,6 @@ struct socket;
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
size_t len);
-/* Defined in tcp_wrbuffer.c ************************************************/
/****************************************************************************
* Function: tcp_wrbuffer_initialize
*
diff --git a/nuttx/net/tcp/tcp_accept.c b/nuttx/net/tcp/tcp_accept.c
new file mode 100644
index 000000000..86e4e8bc0
--- /dev/null
+++ b/nuttx/net/tcp/tcp_accept.c
@@ -0,0 +1,359 @@
+/****************************************************************************
+ * net/tcp/tcp_accept.c
+ *
+ * Copyright (C) 2007-2012, 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/net/net.h>
+
+#include "socket/socket.h"
+#include "tcp/tcp.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct accept_s
+{
+ FAR struct socket *acpt_sock; /* The accepting socket */
+ sem_t acpt_sem; /* Wait for interrupt event */
+ FAR struct sockaddr *acpt_addr; /* Return connection address */
+ FAR socklen_t *acpt_addrlen; /* Return length of address */
+ FAR struct tcp_conn_s *acpt_newconn; /* The accepted connection */
+ int acpt_result; /* The result of the wait */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: accept_tcpsender
+ *
+ * Description:
+ * Get the sender's address from the UDP packet
+ *
+ * Parameters:
+ * psock - The state structure of the accepting socket
+ * conn - The newly accepted TCP connection
+ * pstate - the recvfrom state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+*
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP
+static inline void accept_tcpsender(FAR struct socket *psock,
+ FAR struct tcp_conn_s *conn,
+ FAR struct sockaddr *addr,
+ socklen_t *addrlen)
+{
+ if (addr)
+ {
+ /* If an address is provided, then the length must also be provided. */
+
+ DEBUGASSERT(addrlen);
+
+#ifdef CONFIG_NET_IPv4
+#ifdef CONFIG_NET_IPv6
+ /* If both IPv4 and IPv6 support are enabled, then we will need to
+ * select which one to use when obtaining the sender's IP address.
+ */
+
+ if (psock->s_domain == PF_INET)
+#endif /* CONFIG_NET_IPv6 */
+ {
+ FAR struct sockaddr_in *inaddr = (FAR struct sockaddr_in *)addr;
+
+ inaddr->sin_family = AF_INET;
+ inaddr->sin_port = conn->rport;
+ net_ipv4addr_copy(inaddr->sin_addr.s_addr, conn->u.ipv4.raddr);
+
+ *addrlen = sizeof(struct sockaddr_in);
+ }
+#endif /* CONFIG_NET_IPv4 */
+
+#ifdef CONFIG_NET_IPv6
+#ifdef CONFIG_NET_IPv4
+ /* Otherwise, this the IPv6 address is needed */
+
+ else
+#endif /* CONFIG_NET_IPv4 */
+ {
+ FAR struct sockaddr_in6 *inaddr = (FAR struct sockaddr_in6 *)addr;
+
+ DEBUGASSERT(psock->s_domain == PF_INET6);
+ inaddr->sin6_family = AF_INET6;
+ inaddr->sin6_port = conn->rport;
+ net_ipv6addr_copy(inaddr->sin6_addr.s6_addr, conn->u.ipv6.raddr);
+
+ *addrlen = sizeof(struct sockaddr_in6);
+ }
+#endif /* CONFIG_NET_IPv6 */
+ }
+}
+#endif /* CONFIG_NET_TCP */
+
+/****************************************************************************
+ * Function: accept_interrupt
+ *
+ * Description:
+ * Receive interrupt level callbacks when connections occur
+ *
+ * Parameters:
+ * listener The connection structure of the listener
+ * conn The connection structure that was just accepted
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+static int accept_interrupt(FAR struct tcp_conn_s *listener,
+ FAR struct tcp_conn_s *conn)
+{
+ struct accept_s *pstate = (struct accept_s *)listener->accept_private;
+ int ret = -EINVAL;
+
+ if (pstate)
+ {
+ /* Get the connection address */
+
+ accept_tcpsender(pstate->acpt_sock, conn, pstate->acpt_addr,
+ pstate->acpt_addrlen);
+
+ /* Save the connection structure */
+
+ pstate->acpt_newconn = conn;
+ pstate->acpt_result = OK;
+
+ /* There should be a reference of one on the new connection */
+
+ DEBUGASSERT(conn->crefs == 1);
+
+ /* Wake-up the waiting caller thread */
+
+ sem_post(&pstate->acpt_sem);
+
+ /* Stop any further callbacks */
+
+ listener->accept_private = NULL;
+ listener->accept = NULL;
+ ret = OK;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: tcp_accept
+ *
+ * Description:
+ * This function implements accept() for TCP/IP sockets. See the
+ * description of accept() for further information.
+ *
+ * Parameters:
+ * psock The listening TCP socket structure
+ * addr Receives the address of the connecting client
+ * addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
+ * newconn The new, accepted TCP connection structure
+ *
+ * Returned Value:
+ * Returns zero (OK) on success or a negated errno value on failure.
+ * See the description of accept of the possible errno values in the
+ * description of accept().
+ *
+ * Assumptions:
+ * Network is locked.
+ *
+ ****************************************************************************/
+
+int psock_tcp_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR void **newconn)
+{
+ FAR struct tcp_conn_s *conn;
+ struct accept_s state;
+ int err;
+ int ret;
+
+ DEBUGASSERT(psock && newconn);
+
+ /* Check the backlog to see if there is a connection already pending for
+ * this listener.
+ */
+
+ conn = (FAR struct tcp_conn_s *)psock->s_conn;
+
+#ifdef CONFIG_NET_TCPBACKLOG
+ state.acpt_newconn = tcp_backlogremove(conn);
+ if (state.acpt_newconn)
+ {
+ /* Yes... get the address of the connected client */
+
+ nvdbg("Pending conn=%p\n", state.acpt_newconn);
+ accept_tcpsender(psock, state.acpt_newconn, addr, addrlen);
+ }
+
+ /* In general, this uIP-based implementation will not support non-blocking
+ * socket operations... except in a few cases: Here for TCP accept with backlog
+ * enabled. If this socket is configured as non-blocking then return EAGAIN
+ * if there is no pending connection in the backlog.
+ */
+
+ else if (_SS_ISNONBLOCK(psock->s_flags))
+ {
+ err = EAGAIN;
+ goto errout;
+ }
+ else
+#endif
+ {
+ /* Set the socket state to accepting */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);
+
+ /* Perform the TCP accept operation */
+
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
+
+ state.acpt_sock = psock;
+ state.acpt_addr = addr;
+ state.acpt_addrlen = addrlen;
+ state.acpt_newconn = NULL;
+ state.acpt_result = OK;
+ sem_init(&state.acpt_sem, 0, 0);
+
+ /* Set up the callback in the connection */
+
+ conn->accept_private = (void*)&state;
+ conn->accept = accept_interrupt;
+
+ /* Wait for the send to complete or an error to occur: NOTES: (1)
+ * net_lockedwait will also terminate if a signal is received, (2)
+ * interrupts may be disabled! They will be re-enabled while the
+ * task sleeps and automatically re-enabled when the task restarts.
+ */
+
+ ret = net_lockedwait(&state.acpt_sem);
+ if (ret < 0)
+ {
+ /* The value returned by net_lockedwait() the same as the value
+ * returned by sem_wait(): Zero (OK) is returned on success; -1
+ * (ERROR) is returned on a failure with the errno value set
+ * appropriately.
+ *
+ * We have to preserve the errno value here because it may be
+ * altered by intervening operations.
+ */
+
+ err = get_errno();
+ }
+
+ /* Make sure that no further interrupts are processed */
+
+ conn->accept_private = NULL;
+ conn->accept = NULL;
+
+ sem_destroy(&state. acpt_sem);
+
+ /* Set the socket state to idle */
+
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+
+ /* Check for a errors. Errors are signalled by negative errno values
+ * for the send length.
+ */
+
+ if (state.acpt_result != 0)
+ {
+ err = state.acpt_result;
+ goto errout;
+ }
+
+ /* If net_lockedwait failed, then we were probably reawakened by a
+ * signal. In this case, logic above will have set 'err' to the
+ * ernno value returned by net_lockedwait().
+ */
+
+ if (ret < 0)
+ {
+ goto errout;
+ }
+ }
+
+ *newconn = (FAR void *)state.acpt_newconn;
+ return OK;
+
+errout:
+ set_errno(err);
+ return ERROR;
+}
+
+#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */