You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2019/12/24 14:10:57 UTC

[incubator-nuttx] branch master updated: This change implements the SO_ERROR socket option that is used to obtain the last error reported by the network.

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new ce63457  This change implements the SO_ERROR socket option that is used to obtain the last error reported by the network.
ce63457 is described below

commit ce634578ddbdcc1f847eb74fa1efcb69ad3de6e6
Author: liuhuahang <li...@xiaomi.com>
AuthorDate: Tue Dec 24 08:09:55 2019 -0600

    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 <gn...@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 <li...@xiaomi.com>
    
        Implement SO_ERROR for getsockopt()
---
 include/nuttx/net/net.h   |  3 ++-
 net/socket/accept.c       |  2 +-
 net/socket/bind.c         |  2 +-
 net/socket/connect.c      |  2 +-
 net/socket/getpeername.c  |  2 +-
 net/socket/getsockname.c  |  2 +-
 net/socket/getsockopt.c   | 15 +++++++++++++--
 net/socket/listen.c       |  4 ++--
 net/socket/net_sendfile.c |  4 ++--
 net/socket/recvfrom.c     | 15 ++++++++++-----
 net/socket/send.c         | 11 ++++++++---
 net/socket/sendto.c       |  2 +-
 net/socket/socket.h       | 17 +++++++++++++++++
 13 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index 325bb8b..5ad141b 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -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 <gn...@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) */
diff --git a/net/socket/accept.c b/net/socket/accept.c
index bcfc368..39ed7a8 100644
--- a/net/socket/accept.c
+++ b/net/socket/accept.c
@@ -302,7 +302,7 @@ errout_with_socket:
 errout:
   leave_cancellation_point();
 
-  set_errno(errcode);
+  _SO_SETERRNO(psock, errcode);
   return ERROR;
 }
 
diff --git a/net/socket/bind.c b/net/socket/bind.c
index 13c6e19..00e0796 100644
--- a/net/socket/bind.c
+++ b/net/socket/bind.c
@@ -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;
     }
 
diff --git a/net/socket/connect.c b/net/socket/connect.c
index 9e2c9aa..3fdaac8 100644
--- a/net/socket/connect.c
+++ b/net/socket/connect.c
@@ -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;
     }
 
diff --git a/net/socket/getpeername.c b/net/socket/getpeername.c
index 0988032..4181117 100644
--- a/net/socket/getpeername.c
+++ b/net/socket/getpeername.c
@@ -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;
     }
 
diff --git a/net/socket/getsockname.c b/net/socket/getsockname.c
index d267278..bed6217 100644
--- a/net/socket/getsockname.c
+++ b/net/socket/getsockname.c
@@ -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;
     }
 
diff --git a/net/socket/getsockopt.c b/net/socket/getsockopt.c
index d027da2..487642c 100644
--- a/net/socket/getsockopt.c
+++ b/net/socket/getsockopt.c
@@ -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 <gn...@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 */
diff --git a/net/socket/listen.c b/net/socket/listen.c
index 0b3f117..d267b38 100644
--- a/net/socket/listen.c
+++ b/net/socket/listen.c
@@ -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;
     }
 
diff --git a/net/socket/net_sendfile.c b/net/socket/net_sendfile.c
index faf715e..a499504 100644
--- a/net/socket/net_sendfile.c
+++ b/net/socket/net_sendfile.c
@@ -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;
     }
 
diff --git a/net/socket/recvfrom.c b/net/socket/recvfrom.c
index 4396255..79944c2 100644
--- a/net/socket/recvfrom.c
+++ b/net/socket/recvfrom.c
@@ -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 <gn...@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 */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Let psock_recvfrom() do all of the work */
 
-  ret = nx_recvfrom(sockfd, buf, len, flags, from, fromlen);
+  ret = psock_recvfrom(psock, buf, len, flags, from, fromlen);
   if (ret < 0)
     {
-      set_errno(-ret);
+      _SO_SETERRNO(psock, -ret);
       ret = ERROR;
     }
 
diff --git a/net/socket/send.c b/net/socket/send.c
index 7d95a6f..f75fdc3 100644
--- a/net/socket/send.c
+++ b/net/socket/send.c
@@ -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 */
+
+  psock = sockfd_socket(sockfd);
+
+  /* Let psock_send() do all of the work */
 
-  ret = nx_send(sockfd, buf, len, flags);
+  ret = psock_send(psock, buf, len, flags);
   if (ret < 0)
     {
-      set_errno((int)-ret);
+      _SO_SETERRNO(psock, -ret);
       ret = ERROR;
     }
 
diff --git a/net/socket/sendto.c b/net/socket/sendto.c
index dbbe701..417afb9 100644
--- a/net/socket/sendto.c
+++ b/net/socket/sendto.c
@@ -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;
     }
 
diff --git a/net/socket/socket.h b/net/socket/socket.h
index 608e44a..f826337 100644
--- a/net/socket/socket.h
+++ b/net/socket/socket.h
@@ -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
  ****************************************************************************/