Add more low-level, thread-independent socket interfaces

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4445 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-03-02 19:57:52 +00:00
parent e39ef0a587
commit 696285d84d
8 changed files with 391 additions and 173 deletions

View File

@ -2522,3 +2522,8 @@
* include/nuttx/arch.h, configs/stm3240g-eval/src/up_cxxinitialize.c, and
configs/stm3240g-eval/src/up_cxxinitialize.c: Add support for C++ static
initializers.
* net/setsockopt.c, net/getsockopt.c, net/bind.c, net/socket.c: Add more
low level, thread-independent socket interfaces for use within the OS.
Some of these are currently used by the FTP controlling terminal. More will
be used to support the NFS file system currenly underwork.

View File

@ -300,7 +300,6 @@
# define bdtdbg(x...)
# define bdtvdbg(x...)
# define pic32mx_ep0bdtdump(msg)
#endif
@ -467,9 +466,6 @@ static inline void
static inline bool
pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno);
static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv);
#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG
static void pic32mx_ep0bdtdump(const char *msg);
#endif
/* Endpoint operations ******************************************************/
@ -504,6 +500,7 @@ static int pic32mx_selfpowered(struct usbdev_s *dev, bool selfpowered);
static void pic32mx_reset(struct pic32mx_usbdev_s *priv);
static void pic32mx_attach(struct pic32mx_usbdev_s *priv);
static void pic32mx_detach(struct pic32mx_usbdev_s *priv);
static void pic32mx_swreset(struct pic32mx_usbdev_s *priv);
static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv);
static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv);
static void pic32mx_hwshutdown(struct pic32mx_usbdev_s *priv);
@ -2292,21 +2289,22 @@ static int pic32mx_interrupt(int irq, void *context)
{
usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_RESET), usbir);
/* Reset interrupt received. Restore our power-up state */
/* Reset interrupt received. Restore our initial state. NOTE: the
* hardware automatically resets the USB address, so we just need
* reset any existing configuration/transfer states.
*/
#warning "Broken Logic"
#if 0 /* If there is no pull-up, then this will just cause another reset */
pic32mx_reset(priv);
pic32mx_attach(priv);
#endif
pic32mx_swreset(priv);
priv->devstate = DEVSTATE_DEFAULT;
#ifdef CONFIG_USBOTG
/* Disable and deactivate HNP */
#warning Missing Logic
#endif
pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR);
goto interrupt_exit;
/* Acknowlege the reset interrupt */
pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR);
goto interrupt_exit;
}
/* Service IDLE interrupts */
@ -2630,28 +2628,6 @@ static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv)
bdt->addr = 0;
}
/****************************************************************************
* Name: pic32mx_ep0bdtdump
****************************************************************************/
#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG
static void pic32mx_ep0bdtdump(const char *msg)
{
volatile struct usbotg_bdtentry_s *bdt;
bdtdbg("EP0 BDT: %s\n", msg);
bdt = &g_bdt[EP0_OUT_EVEN] ;
bdtdbg(" OUT EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
bdt = &g_bdt[EP0_OUT_ODD];
bdtdbg(" OUT ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
bdt = &g_bdt[EP0_IN_EVEN];
bdtdbg(" IN EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
bdt = &g_bdt[EP0_IN_ODD];
bdtdbg(" IN ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
}
#endif
/****************************************************************************
* Endpoint operations
****************************************************************************/
@ -3372,44 +3348,9 @@ static int pic32mx_selfpowered(struct usbdev_s *dev, bool selfpowered)
static void pic32mx_reset(struct pic32mx_usbdev_s *priv)
{
int epno;
/* Reset the software configuration */
/* Tell the class driver that we are disconnected. The class driver
* should then accept any new configurations.
*/
if (priv->driver)
{
CLASS_DISCONNECT(priv->driver, &priv->usbdev);
}
/* Reset the device state structure */
priv->ctrlstate = CTRLSTATE_WAITSETUP;
/* Reset endpoints */
for (epno = 0; epno < PIC32MX_NENDPOINTS; epno++)
{
struct pic32mx_ep_s *privep = &priv->eplist[epno];
/* Cancel any queued requests. Since they are canceled
* with status -ESHUTDOWN, then will not be requeued
* until the configuration is reset. NOTE: This should
* not be necessary... the CLASS_DISCONNECT above should
* result in the class implementation calling pic32mx_epdisable
* for each of its configured endpoints.
*/
pic32mx_cancelrequests(privep);
/* Reset endpoint status */
privep->stalled = false;
privep->halted = false;
privep->txbusy = false;
privep->txnullpkt = false;
}
pic32mx_swreset(priv);
/* Re-configure the USB controller in its initial, unconnected state */
@ -3450,7 +3391,6 @@ static void pic32mx_attach(struct pic32mx_usbdev_s *priv)
/* Configure EP0 */
pic32mx_ep0configure(priv);
pic32mx_ep0bdtdump("Attached");
/* Flush any pending transactions */
@ -3554,6 +3494,65 @@ static void pic32mx_detach(struct pic32mx_usbdev_s *priv)
#endif
}
/****************************************************************************
* Name: pic32mx_swreset
****************************************************************************/
static void pic32mx_swreset(struct pic32mx_usbdev_s *priv)
{
int epno;
/* Tell the class driver that we are disconnected. The class driver
* should then accept any new configurations.
*/
if (priv->driver)
{
CLASS_DISCONNECT(priv->driver, &priv->usbdev);
}
/* Flush and reset endpoint states (except EP0) */
for (epno = 1; epno < PIC32MX_NENDPOINTS; epno++)
{
struct pic32mx_ep_s *privep = &priv->eplist[epno];
/* Cancel any queued requests. Since they are canceled
* with status -ESHUTDOWN, then will not be requeued
* until the configuration is reset. NOTE: This should
* not be necessary... the CLASS_DISCONNECT above should
* result in the class implementation calling pic32mx_epdisable
* for each of its configured endpoints.
*/
pic32mx_cancelrequests(privep);
/* Reset endpoint status */
privep->stalled = false;
privep->halted = false;
privep->txbusy = false;
privep->txnullpkt = false;
}
/* Reset to the default address */
pic32mx_putreg(0, PIC32MX_USB_ADDR);
/* Unconfigure each endpoint by clearing the endpoint control registers
* (except EP0)
*/
for (epno = 1; epno < PIC32MX_NENDPOINTS; epno++)
{
pic32mx_putreg(0, PIC32MX_USB_EP(epno));
}
/* Reset the control state */
priv->ctrlstate = CTRLSTATE_WAITSETUP;
}
/****************************************************************************
* Name: pic32mx_hwreset
****************************************************************************/
@ -3562,7 +3561,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
{
uint32_t physaddr;
uint16_t regval;
int i;
/* Power down the USB module. This will reset all USB registers. */
@ -3578,12 +3576,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
regval |= USB_PWRC_USBPWR;
pic32mx_putreg(regval, PIC32MX_USB_PWRC);
/* Reset configuration and disable interrrupts at the USB controller */
pic32mx_putreg(0, PIC32MX_USB_CNFG1);
pic32mx_putreg(0, PIC32MX_USB_EIE);
pic32mx_putreg(0, PIC32MX_USB_IE);
/* Set the address of the buffer descriptor table (BDT)
*
* BDTP1: Bit 1-7: Bits 9-15 of the BDT base address
@ -3596,17 +3588,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
pic32mx_putreg((uint16_t)((physaddr >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2);
pic32mx_putreg((uint16_t)((physaddr >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1);
/* Reset to then default address */
pic32mx_putreg(0, PIC32MX_USB_ADDR);
/* Clear all of the endpoint control registers */
for (i = 0; i < PIC32MX_NENDPOINTS; i++)
{
pic32mx_putreg(0, PIC32MX_USB_EP(i));
}
/* Assert reset request to all of the Ping Pong buffer pointers. This
* will reset all Even/Odd buffer pointers to the EVEN BD banks.
*/
@ -3860,7 +3841,7 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
/* Setup the USB controller in it initial unconnected state */
DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED);
pic32mx_hwreset(priv);
pic32mx_reset(priv);
/* We do not know the order in which the user will call APIs. If
* pic32mx_attach() were called before we got here, the the attach

View File

@ -150,6 +150,12 @@ EXTERN int net_releaselist(FAR struct socketlist *list);
EXTERN FAR struct socket *sockfd_socket(int sockfd);
/* socket.c ******************************************************************/
/* socket using underlying socket structure */
EXTERN int psock_socket(int domain, int type, int protocol,
FAR struct socket *psock);
/* net_close.c ***************************************************************/
/* The standard close() operation redirects operations on socket descriptors
* to this function.
@ -161,6 +167,12 @@ EXTERN int net_close(int sockfd);
EXTERN int psock_close(FAR struct socket *psock);
/* net_close.c ***************************************************************/
/* Performs the bind operation of a socket instance */
EXTERN int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
socklen_t addrlen);
/* send.c ********************************************************************/
/* Send using underlying socket structure */
@ -185,6 +197,18 @@ EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf,
#define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0)
/* getsockopt.c **************************************************************/
/* getsockopt using the underlying socket structure */
EXTERN int psock_getsockopt(FAR struct socket *psock, int level, int option,
FAR void *value, FAR socklen_t *value_len);
/* setsockopt.c **************************************************************/
/* setsockopt using the underlying socket structure */
EXTERN int psock_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len);
/* net_ioctl.c ***************************************************************/
/* The standard ioctl() operation redirects operations on socket descriptors
* to this function.

View File

@ -1,8 +1,8 @@
/****************************************************************************
* net/bind.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2012 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
@ -51,16 +51,16 @@
****************************************************************************/
/****************************************************************************
* Function: bind
* Function: psock_bind
*
* Description:
* bind() gives the socket 'sockfd' the local address 'addr'. 'addr' is
* 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
* space (address family) but has no name assigned.
*
* Parameters:
* sockfd Socket descriptor from socket
* psock Socket structure of the socket to bind
* addr Socket local address
* addrlen Length of 'addr'
*
@ -71,21 +71,18 @@
* The address is protected, and the user is not the superuser.
* EADDRINUSE
* The given address is already in use.
* EBADF
* sockfd is not a valid descriptor.
* EINVAL
* The socket is already bound to an address.
* ENOTSOCK
* sockfd is a descriptor for a file, not a socket.
* psock is a descriptor for a file, not a socket.
*
* Assumptions:
*
****************************************************************************/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
socklen_t addrlen)
{
FAR struct socket *psock = sockfd_socket(sockfd);
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#ifdef CONFIG_NET_IPv6
FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr;
@ -97,11 +94,11 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
int err;
int ret;
/* Verify that the sockfd corresponds to valid, allocated socket */
/* Verify that the psock corresponds to valid, allocated socket */
if (!psock || psock->s_crefs <= 0)
{
err = EBADF;
err = ENOTSOCK;
goto errout;
}
@ -154,4 +151,47 @@ errout:
return ERROR;
}
/****************************************************************************
* Function: bind
*
* Description:
* bind() gives the socket 'sockfd' the local address 'addr'. 'addr' is
* 'addrlen' bytes long. Traditionally, this is called "assigning a name to
* a socket." When a socket is created with socket, it exists in a name
* space (address family) but has no name assigned.
*
* Parameters:
* sockfd Socket descriptor of the socket to bind
* addr Socket local address
* addrlen Length of 'addr'
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately
*
* EACCES
* The address is protected, and the user is not the superuser.
* EADDRINUSE
* The given address is already in use.
* EBADF
* sockfd is not a valid descriptor.
* EINVAL
* The socket is already bound to an address.
* ENOTSOCK
* sockfd is a descriptor for a file, not a socket.
*
* Assumptions:
*
****************************************************************************/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
/* Make the socket descriptor to the underlying socket structure */
FAR struct socket *psock = sockfd_socket(sockfd);
/* Then let psock_bind do all of the work */
return psock_bind(psock, addr, addrlen);
}
#endif /* CONFIG_NET */

View File

@ -1,8 +1,8 @@
/****************************************************************************
* net/getsockopt.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2012 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
@ -51,11 +51,11 @@
****************************************************************************/
/****************************************************************************
* Function: getsockopt
* Function: psock_getsockopt
*
* Description:
* getsockopt() retrieve thse value for the option specified by the
* 'option' argument for the socket specified by the 'sockfd' argument. If
* 'option' argument for the socket specified by the 'psock' argument. If
* the size of the option value is greater than 'value_len', the value
* stored in the object pointed to by the 'value' argument will be silently
* truncated. Otherwise, the length pointed to by the 'value_len' argument
@ -68,7 +68,7 @@
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* sockfd Socket descriptor of socket
* psock Socket structure of the socket to query
* level Protocol level to set the option
* option identifies the option to get
* value Points to the argument value
@ -76,15 +76,13 @@
*
* Returned Value:
*
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EINVAL
* The specified option is invalid at the specified socket 'level' or the
* socket has been shutdown.
* ENOPROTOOPT
* The 'option' is not supported by the protocol.
* ENOTSOCK
* The 'sockfd' argument does not refer to a socket.
* The 'psock' argument does not refer to a socket.
* ENOBUFS
* Insufficient resources are available in the system to complete the
* call.
@ -93,21 +91,11 @@
*
****************************************************************************/
int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len)
int psock_getsockopt(FAR struct socket *psock, int level, int option,
FAR void *value, FAR socklen_t *value_len)
{
FAR struct socket *psock;
int err;
/* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
err = EBADF;
goto errout;
}
/* Verify that the socket option if valid (but might not be supported ) */
if (!_SO_GETVALID(option) || !value || !value_len)
@ -117,6 +105,7 @@ int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_
}
/* Process the option */
switch (option)
{
/* The following options take a point to an integer boolean value.
@ -231,8 +220,70 @@ int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_
return OK;
errout:
*get_errno_ptr() = err;
set_errno(err);
return ERROR;
}
/****************************************************************************
* Function: getsockopt
*
* Description:
* getsockopt() retrieve thse value for the option specified by the
* 'option' argument for the socket specified by the 'sockfd' argument. If
* the size of the option value is greater than 'value_len', the value
* stored in the object pointed to by the 'value' argument will be silently
* truncated. Otherwise, the length pointed to by the 'value_len' argument
* will be modified to indicate the actual length of the'value'.
*
* The 'level' argument specifies the protocol level of the option. To
* retrieve options at the socket level, specify the level argument as
* SOL_SOCKET.
*
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* sockfd Socket descriptor of socket
* level Protocol level to set the option
* option identifies the option to get
* value Points to the argument value
* value_len The length of the argument value
*
* Returned Value:
*
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EINVAL
* The specified option is invalid at the specified socket 'level' or the
* socket has been shutdown.
* ENOPROTOOPT
* The 'option' is not supported by the protocol.
* ENOTSOCK
* The 'sockfd' argument does not refer to a socket.
* ENOBUFS
* Insufficient resources are available in the system to complete the
* call.
*
* Assumptions:
*
****************************************************************************/
int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len)
{
FAR struct socket *psock;
/* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
set_errno(EBADF);
return ERROR;
}
/* Then let psock_getsockopt() do all of the work */
return psock_getsockopt(psock, level, option, value, value_len);
}
#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */

View File

@ -242,6 +242,7 @@ int sockfd_allocate(int minsd)
}
_net_semgive(list);
}
return ERROR;
}

View File

@ -1,8 +1,8 @@
/****************************************************************************
* net/setsockopt.c
*
* Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007, 2008, 2011-2012 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
@ -52,13 +52,12 @@
****************************************************************************/
/****************************************************************************
* Function: setsockopt
* Function: psock_setsockopt
*
* Description:
* setsockopt() sets the option specified by the 'option' argument,
* psock_setsockopt() sets the option specified by the 'option' argument,
* at the protocol level specified by the 'level' argument, to the value
* pointed to by the 'value' argument for the socket associated with the
* file descriptor specified by the 'sockfd' argument.
* pointed to by the 'value' argument for the socket on the 'psock' argument.
*
* The 'level' argument specifies the protocol level of the option. To set
* options at the socket level, specify the level argument as SOL_SOCKET.
@ -66,7 +65,7 @@
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* sockfd Socket descriptor of socket
* psock Socket structure of socket to operate on
* level Protocol level to set the option
* option identifies the option to set
* value Points to the argument value
@ -75,8 +74,6 @@
* Returned Value:
* 0 on success; -1 on failure
*
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EDOM
* The send and receive timeout values are too big to fit into the
* timeout fields in the socket structure.
@ -100,22 +97,12 @@
*
****************************************************************************/
int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len)
int psock_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len)
{
FAR struct socket *psock;
uip_lock_t flags;
int err;
/* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
err = EBADF;
goto errout;
}
/* Verify that the socket option if valid (but might not be supported ) */
if (!_SO_SETVALID(option) || !value)
@ -242,8 +229,76 @@ int setsockopt(int sockfd, int level, int option, const void *value, socklen_t v
return OK;
errout:
*get_errno_ptr() = err;
set_errno(err);
return ERROR;
}
/****************************************************************************
* Function: setsockopt
*
* Description:
* setsockopt() sets the option specified by the 'option' argument,
* at the protocol level specified by the 'level' argument, to the value
* pointed to by the 'value' argument for the socket associated with the
* file descriptor specified by the 'sockfd' argument.
*
* The 'level' argument specifies the protocol level of the option. To set
* options at the socket level, specify the level argument as SOL_SOCKET.
*
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Parameters:
* sockfd Socket descriptor of socket
* level Protocol level to set the option
* option identifies the option to set
* value Points to the argument value
* value_len The length of the argument value
*
* Returned Value:
* 0 on success; -1 on failure
*
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EDOM
* The send and receive timeout values are too big to fit into the
* timeout fields in the socket structure.
* EINVAL
* The specified option is invalid at the specified socket 'level' or the
* socket has been shut down.
* EISCONN
* The socket is already connected, and a specified option cannot be set
* while the socket is connected.
* ENOPROTOOPT
* The 'option' is not supported by the protocol.
* ENOTSOCK
* The 'sockfd' argument does not refer to a socket.
* ENOMEM
* There was insufficient memory available for the operation to complete.
* ENOBUFS
* Insufficient resources are available in the system to complete the
* call.
*
* Assumptions:
*
****************************************************************************/
int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len)
{
FAR struct socket *psock;
/* Get the underlying socket structure */
/* Verify that the sockfd corresponds to valid, allocated socket */
psock = sockfd_socket(sockfd);
if (!psock || psock->s_crefs <= 0)
{
set_errno(EBADF);
return ERROR;
}
/* Then let psock_setockopt() do all of the work */
return psock_setsockopt(psock, level, option, value, value_len);
}
#endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */

View File

@ -1,8 +1,8 @@
/****************************************************************************
* net/socket.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2009, 2012 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
@ -52,15 +52,17 @@
****************************************************************************/
/****************************************************************************
* Function: socket
* Function: psock_socket
*
* Description:
* socket() creates an endpoint for communication and returns a descriptor.
* socket() creates an endpoint for communication and returns a socket
* structure.
*
* Parameters:
* domain (see sys/socket.h)
* type (see sys/socket.h)
* protocol (see sys/socket.h)
* psock A pointer to a user allocated socket structure to be initialized.
*
* Returned Value:
* 0 on success; -1 on error with errno set appropriately
@ -87,10 +89,8 @@
*
****************************************************************************/
int socket(int domain, int type, int protocol)
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
FAR struct socket *psock;
int sockfd;
int err = ENFILE;
/* Only PF_INET or PF_INET6 domains supported */
@ -123,23 +123,7 @@ int socket(int domain, int type, int protocol)
goto errout;
}
/* Everything looks good. Allocate a socket descriptor */
sockfd = sockfd_allocate(0);
if (sockfd < 0)
{
goto errout; /* with err == ENFILE */
}
/* Initialize the socket structure */
psock = sockfd_socket(sockfd);
if (!psock)
{
err = ENOSYS; /* should not happen */
goto errout;
}
/* Everything looks good. Initialize the socket structure */
/* Save the protocol type */
psock->s_type = type;
@ -209,17 +193,94 @@ int socket(int domain, int type, int protocol)
{
/* Failed to reserve a connection structure */
sockfd_release(sockfd);
goto errout; /* With err == ENFILE or ENOMEM */
}
return sockfd;
return OK;
errout:
errno = err;
return ERROR;
}
/****************************************************************************
* Function: socket
*
* Description:
* socket() creates an endpoint for communication and returns a descriptor.
*
* Parameters:
* domain (see sys/socket.h)
* type (see sys/socket.h)
* protocol (see sys/socket.h)
*
* Returned Value:
* A non-negative socket descriptor on success; -1 on error with errno set
* appropriately.
*
* EACCES
* Permission to create a socket of the specified type and/or protocol
* is denied.
* EAFNOSUPPORT
* The implementation does not support the specified address family.
* EINVAL
* Unknown protocol, or protocol family not available.
* EMFILE
* Process file table overflow.
* ENFILE
* The system limit on the total number of open files has been reached.
* ENOBUFS or ENOMEM
* Insufficient memory is available. The socket cannot be created until
* sufficient resources are freed.
* EPROTONOSUPPORT
* The protocol type or the specified protocol is not supported within
* this domain.
*
* Assumptions:
*
****************************************************************************/
int socket(int domain, int type, int protocol)
{
FAR struct socket *psock;
int sockfd;
int ret;
/* Allocate a socket descriptor */
sockfd = sockfd_allocate(0);
if (sockfd < 0)
{
set_errno(ENFILE);
return ERROR;
}
/* Get the underlying socket structure */
psock = sockfd_socket(sockfd);
if (!psock)
{
set_errno(ENOSYS); /* should not happen */
goto errout;
}
/* Initialize the socket structure */
ret = psock_socket(domain, type, protocol, psock);
if (ret < 0)
{
/* Error already set by psock_socket() */
goto errout;
}
return sockfd;
errout:
sockfd_release(sockfd);
return ERROR;
}
#endif /* CONFIG_NET */