This change implements the SO_ERROR socket option that is used to obtain the last error reported by the network.
Squashed commit of the following: Author: Gregory Nutt <gnutt@nuttx.org> net/: Trivial changes to PR from review. Biggest difference: type of s_error changed to int16_t to save a byte or two. Author: liuhuahang <liuhuahang@xiaomi.com> Implement SO_ERROR for getsockopt()
This commit is contained in:
parent
10c4aff6ca
commit
ce634578dd
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/net/net.h
|
||||
*
|
||||
* Copyright (C) 2007, 2009-2014, 2016-2018 Gregory Nutt. All rights
|
||||
* Copyright (C) 2007, 2009-2014, 2016-2019 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
|
@ -234,6 +234,7 @@ struct socket
|
|||
/* Socket options */
|
||||
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
int16_t s_error; /* Last error that occurred on this socket */
|
||||
sockopt_t s_options; /* Selected socket options */
|
||||
socktimeo_t s_rcvtimeo; /* Receive timeout value (in deciseconds) */
|
||||
socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */
|
||||
|
|
|
@ -302,7 +302,7 @@ errout_with_socket:
|
|||
errout:
|
||||
leave_cancellation_point();
|
||||
|
||||
set_errno(errcode);
|
||||
_SO_SETERRNO(psock, errcode);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
|||
ret = psock_bind(psock, addr, addrlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
|
|||
ret = psock_connect(psock, addr, addrlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ int getpeername(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||
ret = psock_getpeername(psock, addr, addrlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||
ret = psock_getsockname(psock, addr, addrlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/socket/getsockopt.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2012, 2014, 2017-2018 Gregory Nutt. All rights
|
||||
* Copyright (C) 2007-2009, 2012, 2014, 2017-2019 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
|
@ -261,10 +261,21 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
|||
}
|
||||
break;
|
||||
|
||||
case SO_ERROR: /* Reports and clears error status. */
|
||||
{
|
||||
if (*value_len != sizeof(int))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*(FAR int *)value = (int)psock->s_error;
|
||||
psock->s_error = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* The following are not yet implemented (return values other than {0,1) */
|
||||
|
||||
case SO_ACCEPTCONN: /* Reports whether socket listening is enabled */
|
||||
case SO_ERROR: /* Reports and clears error status. */
|
||||
case SO_LINGER: /* Lingers on a close() if data is present */
|
||||
case SO_RCVBUF: /* Sets receive buffer size */
|
||||
case SO_RCVLOWAT: /* Sets the minimum number of bytes to input */
|
||||
|
|
|
@ -164,7 +164,7 @@ int listen(int sockfd, int backlog)
|
|||
errcode = EBADF;
|
||||
}
|
||||
|
||||
set_errno(errcode);
|
||||
_SO_SETERRNO(psock, errcode);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ int listen(int sockfd, int backlog)
|
|||
ret = psock_listen(psock, backlog);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ ssize_t net_sendfile(int outfd, FAR struct file *infile, FAR off_t *offset,
|
|||
if (psock != NULL || psock->s_crefs <= 0)
|
||||
{
|
||||
nerr("ERROR: Invalid socket\n");
|
||||
set_errno(EBADF);
|
||||
_SO_SETERRNO(psock, EBADF);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ ssize_t net_sendfile(int outfd, FAR struct file *infile, FAR off_t *offset,
|
|||
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* net/socket/recvfrom.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -93,7 +93,7 @@ ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
/* Verify that non-NULL pointers were passed */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!buf)
|
||||
if (buf == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -226,18 +226,23 @@ ssize_t nx_recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
|||
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
||||
FAR struct sockaddr *from, FAR socklen_t *fromlen)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
ssize_t ret;
|
||||
|
||||
/* recvfrom() is a cancellation point */
|
||||
|
||||
(void)enter_cancellation_point();
|
||||
|
||||
/* Let nx_recvfrom and psock_recvfrom() do all of the work */
|
||||
/* Get the underlying socket structure */
|
||||
|
||||
ret = nx_recvfrom(sockfd, buf, len, flags, from, fromlen);
|
||||
psock = sockfd_socket(sockfd);
|
||||
|
||||
/* Let psock_recvfrom() do all of the work */
|
||||
|
||||
ret = psock_recvfrom(psock, buf, len, flags, from, fromlen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno(-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,18 +225,23 @@ ssize_t nx_send(int sockfd, FAR const void *buf, size_t len, int flags)
|
|||
|
||||
ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
ssize_t ret;
|
||||
|
||||
/* send() is a cancellation point */
|
||||
|
||||
(void)enter_cancellation_point();
|
||||
|
||||
/* Let nx_send() and psock_send() do all of the work */
|
||||
/* Get the underlying socket structure */
|
||||
|
||||
ret = nx_send(sockfd, buf, len, flags);
|
||||
psock = sockfd_socket(sockfd);
|
||||
|
||||
/* Let psock_send() do all of the work */
|
||||
|
||||
ret = psock_send(psock, buf, len, flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno((int)-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
|
|||
ret = psock_sendto(psock, buf, len, flags, to, tolen);
|
||||
if (ret < 0)
|
||||
{
|
||||
set_errno((int)-ret);
|
||||
_SO_SETERRNO(psock, -ret);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,23 @@
|
|||
#define _SO_GETVALID(o) (((unsigned int)(o)) <= _SO_MAXOPT)
|
||||
#define _SO_SETVALID(o) ((((unsigned int)(o)) <= _SO_MAXOPT) && !_SO_GETONLY(o))
|
||||
|
||||
/* Macro to set socket errors */
|
||||
|
||||
#ifdef CONFIG_NET_SOCKOPTS
|
||||
# define _SO_SETERRNO(s,e) \
|
||||
do \
|
||||
{ \
|
||||
if (s != NULL) \
|
||||
{ \
|
||||
s->s_error = (int16_t)e; \
|
||||
} \
|
||||
set_errno(e); \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define _SO_SETERRNO(s,e) set_errno(e)
|
||||
#endif /* CONFIG_NET_SOCKOPTS */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
|
Loading…
Reference in New Issue