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
+5
View File
@@ -2522,3 +2522,8 @@
* include/nuttx/arch.h, configs/stm3240g-eval/src/up_cxxinitialize.c, and * include/nuttx/arch.h, configs/stm3240g-eval/src/up_cxxinitialize.c, and
configs/stm3240g-eval/src/up_cxxinitialize.c: Add support for C++ static configs/stm3240g-eval/src/up_cxxinitialize.c: Add support for C++ static
initializers. 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.
+72 -91
View File
@@ -300,7 +300,6 @@
# define bdtdbg(x...) # define bdtdbg(x...)
# define bdtvdbg(x...) # define bdtvdbg(x...)
# define pic32mx_ep0bdtdump(msg)
#endif #endif
@@ -467,9 +466,6 @@ static inline void
static inline bool static inline bool
pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno); pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno);
static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv); static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv);
#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG
static void pic32mx_ep0bdtdump(const char *msg);
#endif
/* Endpoint operations ******************************************************/ /* 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_reset(struct pic32mx_usbdev_s *priv);
static void pic32mx_attach(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_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_hwreset(struct pic32mx_usbdev_s *priv);
static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv); static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv);
static void pic32mx_hwshutdown(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); 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" pic32mx_swreset(priv);
#if 0 /* If there is no pull-up, then this will just cause another reset */
pic32mx_reset(priv);
pic32mx_attach(priv);
#endif
priv->devstate = DEVSTATE_DEFAULT; priv->devstate = DEVSTATE_DEFAULT;
#ifdef CONFIG_USBOTG #ifdef CONFIG_USBOTG
/* Disable and deactivate HNP */ /* Disable and deactivate HNP */
#warning Missing Logic #warning Missing Logic
#endif #endif
pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR); /* Acknowlege the reset interrupt */
goto interrupt_exit;
pic32mx_putreg(USB_INT_URST, PIC32MX_USB_IR);
goto interrupt_exit;
} }
/* Service IDLE interrupts */ /* Service IDLE interrupts */
@@ -2630,28 +2628,6 @@ static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv)
bdt->addr = 0; 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 * 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) 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 pic32mx_swreset(priv);
* 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;
}
/* Re-configure the USB controller in its initial, unconnected state */ /* 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 */ /* Configure EP0 */
pic32mx_ep0configure(priv); pic32mx_ep0configure(priv);
pic32mx_ep0bdtdump("Attached");
/* Flush any pending transactions */ /* Flush any pending transactions */
@@ -3554,6 +3494,65 @@ static void pic32mx_detach(struct pic32mx_usbdev_s *priv)
#endif #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 * Name: pic32mx_hwreset
****************************************************************************/ ****************************************************************************/
@@ -3562,7 +3561,6 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
{ {
uint32_t physaddr; uint32_t physaddr;
uint16_t regval; uint16_t regval;
int i;
/* Power down the USB module. This will reset all USB registers. */ /* 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; regval |= USB_PWRC_USBPWR;
pic32mx_putreg(regval, PIC32MX_USB_PWRC); 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) /* Set the address of the buffer descriptor table (BDT)
* *
* BDTP1: Bit 1-7: Bits 9-15 of the BDT base address * 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 >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2);
pic32mx_putreg((uint16_t)((physaddr >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1); 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 /* Assert reset request to all of the Ping Pong buffer pointers. This
* will reset all Even/Odd buffer pointers to the EVEN BD banks. * 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 */ /* Setup the USB controller in it initial unconnected state */
DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED); 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 /* 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 * pic32mx_attach() were called before we got here, the the attach
+24
View File
@@ -150,6 +150,12 @@ EXTERN int net_releaselist(FAR struct socketlist *list);
EXTERN FAR struct socket *sockfd_socket(int sockfd); 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 ***************************************************************/ /* net_close.c ***************************************************************/
/* The standard close() operation redirects operations on socket descriptors /* The standard close() operation redirects operations on socket descriptors
* to this function. * to this function.
@@ -161,6 +167,12 @@ EXTERN int net_close(int sockfd);
EXTERN int psock_close(FAR struct socket *psock); 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.c ********************************************************************/
/* Send using underlying socket structure */ /* 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) #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 ***************************************************************/ /* net_ioctl.c ***************************************************************/
/* The standard ioctl() operation redirects operations on socket descriptors /* The standard ioctl() operation redirects operations on socket descriptors
* to this function. * to this function.
+53 -13
View File
@@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* net/bind.c * net/bind.c
* *
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -51,16 +51,16 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Function: bind * Function: psock_bind
* *
* Description: * 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 * '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 * a socket." When a socket is created with socket, it exists in a name
* space (address family) but has no name assigned. * space (address family) but has no name assigned.
* *
* Parameters: * Parameters:
* sockfd Socket descriptor from socket * psock Socket structure of the socket to bind
* addr Socket local address * addr Socket local address
* addrlen Length of 'addr' * addrlen Length of 'addr'
* *
@@ -71,21 +71,18 @@
* The address is protected, and the user is not the superuser. * The address is protected, and the user is not the superuser.
* EADDRINUSE * EADDRINUSE
* The given address is already in use. * The given address is already in use.
* EBADF
* sockfd is not a valid descriptor.
* EINVAL * EINVAL
* The socket is already bound to an address. * The socket is already bound to an address.
* ENOTSOCK * ENOTSOCK
* sockfd is a descriptor for a file, not a socket. * psock is a descriptor for a file, not a socket.
* *
* Assumptions: * 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) #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; 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 err;
int ret; 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) if (!psock || psock->s_crefs <= 0)
{ {
err = EBADF; err = ENOTSOCK;
goto errout; goto errout;
} }
@@ -154,4 +151,47 @@ errout:
return ERROR; 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 */ #endif /* CONFIG_NET */
+72 -21
View File
@@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* net/getsockopt.c * net/getsockopt.c
* *
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -51,11 +51,11 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Function: getsockopt * Function: psock_getsockopt
* *
* Description: * Description:
* getsockopt() retrieve thse value for the option specified by the * 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 * 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 * stored in the object pointed to by the 'value' argument will be silently
* truncated. Otherwise, the length pointed to by the 'value_len' argument * 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. * See <sys/socket.h> a complete list of values for the 'option' argument.
* *
* Parameters: * Parameters:
* sockfd Socket descriptor of socket * psock Socket structure of the socket to query
* level Protocol level to set the option * level Protocol level to set the option
* option identifies the option to get * option identifies the option to get
* value Points to the argument value * value Points to the argument value
@@ -76,15 +76,13 @@
* *
* Returned Value: * Returned Value:
* *
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EINVAL * EINVAL
* The specified option is invalid at the specified socket 'level' or the * The specified option is invalid at the specified socket 'level' or the
* socket has been shutdown. * socket has been shutdown.
* ENOPROTOOPT * ENOPROTOOPT
* The 'option' is not supported by the protocol. * The 'option' is not supported by the protocol.
* ENOTSOCK * ENOTSOCK
* The 'sockfd' argument does not refer to a socket. * The 'psock' argument does not refer to a socket.
* ENOBUFS * ENOBUFS
* Insufficient resources are available in the system to complete the * Insufficient resources are available in the system to complete the
* call. * 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; 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 ) */ /* Verify that the socket option if valid (but might not be supported ) */
if (!_SO_GETVALID(option) || !value || !value_len) 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 */ /* Process the option */
switch (option) switch (option)
{ {
/* The following options take a point to an integer boolean value. /* 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; return OK;
errout: errout:
*get_errno_ptr() = err; set_errno(err);
return ERROR; 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 */ #endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */
+1
View File
@@ -242,6 +242,7 @@ int sockfd_allocate(int minsd)
} }
_net_semgive(list); _net_semgive(list);
} }
return ERROR; return ERROR;
} }
+77 -22
View File
@@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* net/setsockopt.c * net/setsockopt.c
* *
* Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -52,13 +52,12 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Function: setsockopt * Function: psock_setsockopt
* *
* Description: * 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 * at the protocol level specified by the 'level' argument, to the value
* pointed to by the 'value' argument for the socket associated with the * pointed to by the 'value' argument for the socket on the 'psock' argument.
* file descriptor specified by the 'sockfd' argument.
* *
* The 'level' argument specifies the protocol level of the option. To set * The 'level' argument specifies the protocol level of the option. To set
* options at the socket level, specify the level argument as SOL_SOCKET. * 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. * See <sys/socket.h> a complete list of values for the 'option' argument.
* *
* Parameters: * Parameters:
* sockfd Socket descriptor of socket * psock Socket structure of socket to operate on
* level Protocol level to set the option * level Protocol level to set the option
* option identifies the option to set * option identifies the option to set
* value Points to the argument value * value Points to the argument value
@@ -75,8 +74,6 @@
* Returned Value: * Returned Value:
* 0 on success; -1 on failure * 0 on success; -1 on failure
* *
* EBADF
* The 'sockfd' argument is not a valid socket descriptor.
* EDOM * EDOM
* The send and receive timeout values are too big to fit into the * The send and receive timeout values are too big to fit into the
* timeout fields in the socket structure. * 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; uip_lock_t flags;
int err; 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 ) */ /* Verify that the socket option if valid (but might not be supported ) */
if (!_SO_SETVALID(option) || !value) 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; return OK;
errout: errout:
*get_errno_ptr() = err; set_errno(err);
return ERROR; 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 */ #endif /* CONFIG_NET && CONFIG_NET_SOCKOPTS */
+87 -26
View File
@@ -1,8 +1,8 @@
/**************************************************************************** /****************************************************************************
* net/socket.c * net/socket.c
* *
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -52,15 +52,17 @@
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Function: socket * Function: psock_socket
* *
* Description: * Description:
* socket() creates an endpoint for communication and returns a descriptor. * socket() creates an endpoint for communication and returns a socket
* structure.
* *
* Parameters: * Parameters:
* domain (see sys/socket.h) * domain (see sys/socket.h)
* type (see sys/socket.h) * type (see sys/socket.h)
* protocol (see sys/socket.h) * protocol (see sys/socket.h)
* psock A pointer to a user allocated socket structure to be initialized.
* *
* Returned Value: * Returned Value:
* 0 on success; -1 on error with errno set appropriately * 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; int err = ENFILE;
/* Only PF_INET or PF_INET6 domains supported */ /* Only PF_INET or PF_INET6 domains supported */
@@ -123,23 +123,7 @@ int socket(int domain, int type, int protocol)
goto errout; goto errout;
} }
/* Everything looks good. Allocate a socket descriptor */ /* Everything looks good. Initialize the socket structure */
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;
}
/* Save the protocol type */ /* Save the protocol type */
psock->s_type = type; psock->s_type = type;
@@ -209,17 +193,94 @@ int socket(int domain, int type, int protocol)
{ {
/* Failed to reserve a connection structure */ /* Failed to reserve a connection structure */
sockfd_release(sockfd);
goto errout; /* With err == ENFILE or ENOMEM */ goto errout; /* With err == ENFILE or ENOMEM */
} }
return sockfd; return OK;
errout: errout:
errno = err; errno = err;
return ERROR; 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 */ #endif /* CONFIG_NET */