[Patch for Review] "errno" in networking code and Win32

Ranjit Mathew rmathew@hotmail.com
Sat Jan 4 19:54:00 GMT 2003


Hi,

     The following patch proposes to clean up the networking
code a little bit with respect to checking for errors during
socket operations.

The background information for the need for such a patch can
be found in the following message I posted to the GCJ list:

     http://gcc.gnu.org/ml/java/2002-12/msg00218.html

I would especially request Adam and Michael (Koch) to review
these proposals since code written by them would be the most
affected by these changes.

In summary, the normal UNIX "errno" variable cannot be used on
Win32 to check for errors in calls to socket functions - the
Win32 WinSock 2 API mandates the use of the WSAGetLastError( ) and
WSASetLastError( ) functions to get and set the error code for
WinSock 2 functions. Moreover, the normal socket error code
definitions like ECONNREFUSED, etc. are instead defined as
WSAECONNREFUSED, etc.

To accommodate this limitation, I propose defining macros
"_Jv_platform_getsockerr()" and "_Jv_platform_setsockerr()"
instead of directly manipulating the errno variable for
networking code. I also provide mappings for the normal
socket error codes to their WinSock2 counterparts. For Posix
these macros directly manipulate "errno" while on Win32
these macros call WSAGetLastError( ) and WSASetLastError( )
respectively.

IMPORTANT: If these changes are acceptable, from now on we should
use these macros in our networking code instead of using "errno"
directly.

NOTE: I must point out that even after making these changes,
the networking code would still be lacking on Win32 because you
just cannot use the strerror( ) function to get the error
message for a socket error - you must use the FormatMessage( )
Win32 function to do it. This is a bit involved and I will
attempt it a bit later - in the mean time strerror( ) will
return messages like "Unknown Error" for socket errors instead
of the "real" error message.

I have had to replace the "winsock.h" header with "ws2tcpip.h"
in win32.h. I have also removed the original pseudo definitions
of ENOTCONN and ECONNRESET in win32.h as well as that of
ENOPROTOPT.


ChangeLog:

2003-01-04  Ranjit Mathew  <rmathew@hotmail.com>

	* include/win32.h: Use "ws2tcpip.h" instead of "winsock.h".
	Map socket error codes like EFOOBAR to WinSock WSAFOOBAR
	error codes.
         (ENOTCONN, ECONNRESET, ENOPROTOOPT): Remove old definitions.
         (_Jv_platform_getsockerr): Define.
         (_Jv_platform_setsockerr): Define.

	* include/posix.h (_Jv_platform_getsockerr): Define.
         (_Jv_platform_setsockerr): Define.

	* java/net/natPlainDatagramSocketImpl.cc: Use
	_Jv_platform_getsockerr and _Jv_platform_setsockerr instead
	of directly using "errno".

	* java/net/natPlainDatagramSocketImpl.cc: Ditto.

-------------------------------- 8< --------------------------------
--- include/win32.h	2002-12-18 23:28:14.000000000 +0530
+++ include/win32.h	2003-01-05 00:12:45.000000000 +0530
@@ -15,6 +15,5 @@
  #undef STRICT

-#undef __INSIDE_CYGWIN__
-#include <winsock.h>
+#include <ws2tcpip.h>
  #define IP_TOS 3
  #include <gcj/cni.h>
@@ -29,13 +28,40 @@
  #ifndef DISABLE_JAVA_NET

-// these errors cannot occur on Win32
-#define ENOTCONN 0
-#define ECONNRESET 0
-
-#ifndef ENOPROTOOPT
-#define ENOPROTOOPT 109
-#endif
+#define _Jv_platform_getsockerr() WSAGetLastError( )
+#define _Jv_platform_setsockerr(x) WSASetLastError(x)

-#endif // DISABLE_JAVA_NET
+#define EUSERS                   WSAEUSERS
+#define ENOTSOCK                 WSAENOTSOCK
+#define EDESTADDRREQ             WSAEDESTADDRREQ
+#define EMSGSIZE                 WSAEMSGSIZE
+#define EPROTOTYPE               WSAEPROTOTYPE
+#define ENOPROTOOPT              WSAENOPROTOOPT
+#define EPROTONOSUPPORT          WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT          WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP               WSAEOPNOTSUPP
+#define EPFNOSUPPORT             WSAEPFNOSUPPORT
+#define EAFNOSUPPORT             WSAEAFNOSUPPORT
+#define EADDRINUSE               WSAEADDRINUSE
+#define EADDRNOTAVAIL            WSAEADDRNOTAVAIL
+#define ENETDOWN                 WSAENETDOWN
+#define ENETUNREACH              WSAENETUNREACH
+#define ENETRESET                WSAENETRESET
+#define ECONNABORTED             WSAECONNABORTED
+#define ECONNRESET               WSAECONNRESET
+#define ENOBUFS                  WSAENOBUFS
+#define EISCONN                  WSAEISCONN
+#define ENOTCONN                 WSAENOTCONN
+#define ESHUTDOWN                WSAESHUTDOWN
+#define ETOOMANYREFS             WSAETOOMANYREFS
+#define ETIMEDOUT                WSAETIMEDOUT
+#define ECONNREFUSED             WSAECONNREFUSED
+#define EHOSTDOWN                WSAEHOSTDOWN
+#define EHOSTUNREACH             WSAEHOSTUNREACH
+#define EALREADY                 WSAEALREADY
+#define EINPROGRESS              WSAEINPROGRESS
+#define ESTALE                   WSAESTALE
+#define EDQUOT                   WSAEDQUOT
+
+#endif /* !DISABLE_JAVA_NET */

  extern void _Jv_platform_initialize (void);
--- include/posix.h	2003-01-04 20:56:53.000000000 +0530
+++ include/posix.h	2003-01-05 00:01:53.000000000 +0530
@@ -67,4 +67,7 @@
  #endif

+#define _Jv_platform_getsockerr()  (errno)
+#define _Jv_platform_setsockerr(x) (errno = (x))
+
  static inline int
  _Jv_socket (int domain, int type, int protocol)
--- java/net/natPlainDatagramSocketImpl.cc	2002-12-18 23:47:26.000000000 +0530
+++ java/net/natPlainDatagramSocketImpl.cc	2003-01-05 00:18:39.000000000 +0530
@@ -311,5 +311,5 @@
    char* strerr = strerror (errno);

-  if (errno == ECONNREFUSED)
+  if (_Jv_platform_getsockerr () == ECONNREFUSED)
      throw new PortUnreachableException (JvNewStringUTF (strerr));

@@ -378,5 +378,5 @@
    char* strerr = strerror (errno);

-  if (errno == ECONNREFUSED)
+  if (_Jv_platform_getsockerr () == ECONNREFUSED)
      throw new PortUnreachableException (JvNewStringUTF (strerr));

@@ -433,5 +433,5 @@
    char* strerr = strerror (errno);

-  if (errno == ECONNREFUSED)
+  if (_Jv_platform_getsockerr () == ECONNREFUSED)
      throw new PortUnreachableException (JvNewStringUTF (strerr));

@@ -500,5 +500,5 @@
    char* strerr = strerror (errno);

-  if (errno == ECONNREFUSED)
+  if (_Jv_platform_getsockerr () == ECONNREFUSED)
      throw new PortUnreachableException (JvNewStringUTF (strerr));

@@ -728,5 +728,5 @@
          return;
        default :
-        errno = ENOPROTOOPT;
+        _Jv_platform_setsockerr (ENOPROTOOPT);
      }

@@ -862,5 +862,5 @@
  	
        default :
-	errno = ENOPROTOOPT;
+	_Jv_platform_setsockerr (ENOPROTOOPT);
      }

--- java/net/natPlainSocketImpl.cc	2003-01-05 00:03:33.000000000 +0530
+++ java/net/natPlainSocketImpl.cc	2003-01-05 00:09:09.000000000 +0530
@@ -323,5 +323,6 @@
        ::fcntl (fnum, F_SETFL, flags | O_NONBLOCK);

-      if ((_Jv_connect (fnum, ptr, len) != 0) && (errno != EINPROGRESS))
+      if ((_Jv_connect (fnum, ptr, len) != 0) &&
+          (_Jv_platform_getsockerr () != EINPROGRESS))
          goto error;

@@ -454,5 +455,7 @@
        // These three errors are not errors according to tests performed
        // on the reference implementation.
-      if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
+      if (_Jv_platform_getsockerr () != ENOTCONN &&
+          _Jv_platform_getsockerr () != ECONNRESET &&
+          _Jv_platform_getsockerr () != EBADF)
          throw new java::io::IOException  (JvNewStringUTF (strerror (errno)));
      }
@@ -483,5 +486,7 @@
              }
            // Some errors should not cause exceptions.
-          if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
+          if (_Jv_platform_getsockerr () != ENOTCONN &&
+              _Jv_platform_getsockerr () != ECONNRESET &&
+              _Jv_platform_getsockerr () != EBADF)
              throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
            break;
@@ -517,5 +522,7 @@
              }
            // Some errors should not cause exceptions.
-          if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
+          if (_Jv_platform_getsockerr () != ENOTCONN &&
+              _Jv_platform_getsockerr () != ECONNRESET &&
+              _Jv_platform_getsockerr () != EBADF)
              throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
            break;
@@ -583,5 +590,5 @@
      {
        // Some errors cause us to return end of stream...
-      if (errno == ENOTCONN)
+      if (_Jv_platform_getsockerr () == ENOTCONN)
          return -1;

@@ -654,5 +661,5 @@
      {
        // Some errors cause us to return end of stream...
-      if (errno == ENOTCONN)
+      if (_Jv_platform_getsockerr () == ENOTCONN)
          return -1;

@@ -676,5 +683,5 @@
    r = ::ioctl (fnum, FIONREAD, &num);

-  if (r == -1 && errno == ENOTTY)
+  if (r == -1 && _Jv_platform_getsockerr () == ENOTTY)
      {
        // If the ioctl doesn't work, we don't care.
@@ -687,5 +694,5 @@
    if (fnum < 0)
      {
-      errno = EBADF;
+      _Jv_platform_setsockerr (EBADF);
        r = -1;
      }
@@ -852,5 +859,5 @@

        default :
-        errno = ENOPROTOOPT;
+        _Jv_platform_setsockerr (ENOPROTOOPT);
      }

@@ -995,5 +1002,5 @@

      default :
-      errno = ENOPROTOOPT;
+      _Jv_platform_setsockerr (ENOPROTOOPT);
      }

-------------------------------- 8< --------------------------------

Sincerely Yours,
Ranjit.

-- 
Ranjit Mathew        Email: rmathew AT hotmail DOT com
Bangalore,
INDIA.               Web: http://ranjitmathew.tripod.com/





More information about the Java-patches mailing list