net/sockopt: Try usrsock further if the protocol not available
fallback to usrsock if the features are not implemented locally Change-Id: I46e2d6452d7edd3fa5b3d508945511cd48f22ebb Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
parent
51efe468b9
commit
316cdccf82
@ -103,37 +103,47 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_USRSOCK
|
||||
if (psock->s_type == SOCK_USRSOCK_TYPE)
|
||||
{
|
||||
FAR struct usrsock_conn_s *conn = psock->s_conn;
|
||||
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
/* Some of the socket options are handled from this function. */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case SO_TYPE: /* Type can be read from NuttX psock structure. */
|
||||
case SO_RCVTIMEO: /* Rx timeouts can be handled at NuttX side, thus
|
||||
* simplify daemon implementation. */
|
||||
case SO_SNDTIMEO: /* Rx timeouts can be handled at NuttX side, thus
|
||||
* simplify daemon implementation. */
|
||||
break;
|
||||
|
||||
default: /* Other options are passed to usrsock daemon. */
|
||||
{
|
||||
return usrsock_getsockopt(conn, SOL_SOCKET,
|
||||
option, value, value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Process the option */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
/* The following are valid only if the OS CLOCK feature is enabled */
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
case SO_SNDTIMEO:
|
||||
{
|
||||
socktimeo_t timeo;
|
||||
|
||||
/* Verify that option is the size of an 'int'. Should also check
|
||||
* that 'value' is properly aligned for an 'int'
|
||||
*/
|
||||
|
||||
if (*value_len < sizeof(struct timeval))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the timeout value. This is a atomic operation and should
|
||||
* require no special operation.
|
||||
*/
|
||||
|
||||
if (option == SO_RCVTIMEO)
|
||||
{
|
||||
timeo = psock->s_rcvtimeo;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeo = psock->s_sndtimeo;
|
||||
}
|
||||
|
||||
/* Then return the timeout value to the caller */
|
||||
|
||||
net_dsec2timeval(timeo, (struct timeval *)value);
|
||||
*value_len = sizeof(struct timeval);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_NET_USRSOCK
|
||||
case SO_ACCEPTCONN: /* Reports whether socket listening is enabled */
|
||||
if (*value_len < sizeof(int))
|
||||
{
|
||||
@ -231,42 +241,6 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
}
|
||||
break;
|
||||
|
||||
/* The following are valid only if the OS CLOCK feature is enabled */
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
case SO_SNDTIMEO:
|
||||
{
|
||||
socktimeo_t timeo;
|
||||
|
||||
/* Verify that option is the size of an 'int'. Should also check
|
||||
* that 'value' is properly aligned for an 'int'
|
||||
*/
|
||||
|
||||
if (*value_len < sizeof(struct timeval))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the timeout value. This is a atomic operation and should
|
||||
* require no special operation.
|
||||
*/
|
||||
|
||||
if (option == SO_RCVTIMEO)
|
||||
{
|
||||
timeo = psock->s_rcvtimeo;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeo = psock->s_sndtimeo;
|
||||
}
|
||||
|
||||
/* Then return the timeout value to the caller */
|
||||
|
||||
net_dsec2timeval(timeo, (struct timeval *)value);
|
||||
*value_len = sizeof(struct timeval);
|
||||
}
|
||||
break;
|
||||
|
||||
case SO_ERROR: /* Reports and clears error status. */
|
||||
{
|
||||
if (*value_len != sizeof(int))
|
||||
@ -301,6 +275,7 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
case SO_RCVLOWAT: /* Sets the minimum number of bytes to input */
|
||||
case SO_SNDBUF: /* Sets send buffer size */
|
||||
case SO_SNDLOWAT: /* Sets the minimum number of bytes to output */
|
||||
#endif
|
||||
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
@ -360,7 +335,7 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
int ret = OK;
|
||||
int ret;
|
||||
|
||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||
|
||||
@ -403,6 +378,16 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_USRSOCK
|
||||
/* Try usrsock further if the protocol not available */
|
||||
|
||||
if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
|
||||
{
|
||||
ret = usrsock_getsockopt(psock->s_conn, level,
|
||||
option, value, value_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -98,32 +98,6 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_USRSOCK
|
||||
if (psock->s_type == SOCK_USRSOCK_TYPE)
|
||||
{
|
||||
FAR struct usrsock_conn_s *conn = psock->s_conn;
|
||||
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
/* Some of the socket options are handled from this function. */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case SO_RCVTIMEO: /* Rx timeouts can be handled at NuttX side, thus
|
||||
* simplify daemon implementation. */
|
||||
case SO_SNDTIMEO: /* Rx timeouts can be handled at NuttX side, thus
|
||||
* simplify daemon implementation. */
|
||||
break;
|
||||
|
||||
default: /* Other options are passed to usrsock daemon. */
|
||||
{
|
||||
return usrsock_setsockopt(conn, SOL_SOCKET, option, value,
|
||||
value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Process the option */
|
||||
|
||||
switch (option)
|
||||
@ -133,6 +107,51 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
* is outside of the scope of setsockopt.
|
||||
*/
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
case SO_SNDTIMEO:
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
socktimeo_t timeo;
|
||||
|
||||
/* Verify that option is the size of an 'struct timeval'. */
|
||||
|
||||
if (tv == NULL || value_len != sizeof(struct timeval))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the timeout value. Any microsecond remainder will be
|
||||
* forced to the next larger, whole decisecond value.
|
||||
*/
|
||||
|
||||
timeo = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
|
||||
|
||||
/* Save the timeout value */
|
||||
|
||||
if (option == SO_RCVTIMEO)
|
||||
{
|
||||
psock->s_rcvtimeo = timeo;
|
||||
}
|
||||
else
|
||||
{
|
||||
psock->s_sndtimeo = timeo;
|
||||
}
|
||||
|
||||
/* Set/clear the corresponding enable/disable bit */
|
||||
|
||||
if (timeo)
|
||||
{
|
||||
_SO_CLROPT(psock->s_options, option);
|
||||
}
|
||||
else
|
||||
{
|
||||
_SO_SETOPT(psock->s_options, option);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_NET_USRSOCK
|
||||
|
||||
case SO_BROADCAST: /* Permits sending of broadcast messages */
|
||||
case SO_DEBUG: /* Enables recording of debugging information */
|
||||
case SO_DONTROUTE: /* Requests outgoing messages bypass standard routing */
|
||||
@ -196,49 +215,6 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
return tcp_setsockopt(psock, option, value, value_len);
|
||||
#endif
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
case SO_SNDTIMEO:
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
socktimeo_t timeo;
|
||||
|
||||
/* Verify that option is the size of an 'struct timeval'. */
|
||||
|
||||
if (tv == NULL || value_len != sizeof(struct timeval))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the timeout value. Any microsecond remainder will be
|
||||
* forced to the next larger, whole decisecond value.
|
||||
*/
|
||||
|
||||
timeo = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
|
||||
|
||||
/* Save the timeout value */
|
||||
|
||||
if (option == SO_RCVTIMEO)
|
||||
{
|
||||
psock->s_rcvtimeo = timeo;
|
||||
}
|
||||
else
|
||||
{
|
||||
psock->s_sndtimeo = timeo;
|
||||
}
|
||||
|
||||
/* Set/clear the corresponding enable/disable bit */
|
||||
|
||||
if (timeo)
|
||||
{
|
||||
_SO_CLROPT(psock->s_options, option);
|
||||
}
|
||||
else
|
||||
{
|
||||
_SO_SETOPT(psock->s_options, option);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NET_SOLINGER
|
||||
case SO_LINGER: /* Lingers on a close() if data is present */
|
||||
{
|
||||
@ -316,6 +292,7 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
case SO_ERROR: /* Reports and clears error status. */
|
||||
case SO_TYPE: /* Reports the socket type */
|
||||
|
||||
#endif
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
@ -434,6 +411,16 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_USRSOCK
|
||||
/* Try usrsock further if the protocol not available */
|
||||
|
||||
if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
|
||||
{
|
||||
ret = usrsock_setsockopt(psock->s_conn, level,
|
||||
option, value, value_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user