diff options
author | Mohan Embar <gnustuff@thisiscool.com> | 2003-08-29 04:21:01 +0000 |
---|---|---|
committer | Mohan Embar <membar@gcc.gnu.org> | 2003-08-29 04:21:01 +0000 |
commit | 5c14415811b48f1b486be91ea41661381f08a3fe (patch) | |
tree | 236d99541a3b4c358a6a326abd76276ce8557c33 /libjava/java/net | |
parent | a1d6cdc2d7a48f9b584e2323b173176055adc53a (diff) | |
download | gcc-5c14415811b48f1b486be91ea41661381f08a3fe.zip gcc-5c14415811b48f1b486be91ea41661381f08a3fe.tar.gz gcc-5c14415811b48f1b486be91ea41661381f08a3fe.tar.bz2 |
win32.cc: fixed tab...
* win32.cc: fixed tab, indentation and whitespace
inconsistencies
removed jvm.h include
added includes java/lang/UnsupportedOperationException.h,
java/io/IOException.h, java/net/SocketException.h
(WSAEventWrapper): class implementation
(_Jv_WinStrError): implemented both overloads
(_Jv_ThrowIOException): implemented both overloads
(_Jv_ThrowSocketException): implemented both overloads
(_Jv_select): implemented
* include/win32.h: fixed tab, indentation and whitespace
inconsistencies
wrapped <windows.h> include with #define WIN32_LEAN_AND_MEAN
added jvm.h include
(WSAEventWrapper): added class declaration
(_Jv_WinStrError): added both overload declarations
(_Jv_ThrowIOException): added both overload declarations
(_Jv_ThrowSocketException): added both overload declarations
removed ENOTCONN, ECONNRESET and ENOPROTOOPT defines
(_Jv_select): added declaration
(_Jv_socket): removed
(_Jv_connect): removed
(_Jv_close): removed
(_Jv_bind): removed
(_Jv_accept): removed
(_Jv_listen): removed
(_Jv_write): removed
(_Jv_read): removed
* java/io/natFileDescriptorWin32.cc: fixed tab, indentation and
whitespace inconsistencies
replaced <windows.h> #include with <platform.h>
removed jvm.h include
(testCanUseGetHandleInfo): new function which tests whether Win32
GetHandleInformation() call can be used with console buffer handles
(only supported on >=WinNT 5.0)
(winerr): removed (superseded by _Jv_WinStrError in include/win32.h)
(valid): rewrote implementation using GetHandleInformation()
(sync): changed exception throwing to use error string and exception
helper methods declared in include/win32.h
(open): likewise
(write): likewise
(setLength): likewise
(close): likewise
(seek): likewise
(getFilePointer): likewise
(read): likewise
* java/io/natFileWin32.cc: fixed tab, indentation and
whitespace inconsistencies
replaced <windows.h> #include with <platform.h>
removed jvm.h include
(_access): use JV_TEMP_UTF_STRING
(_stat): likewise
(performMkDir): use JV_TEMP_UTF_STRING
(performRenameTo): likewise
(performDelete): likewise
(performCreate): likewise
(performSetReadOnly): likewise
(performSetLastModified): likewise
* java/lang/natWin32Process.cc: fixed tab, indentation and
whitespace inconsistencies
replaced <windows.h> #include with <platform.h>
removed includes gcj/cni.h, jvm.h
(new_string): removed
(startProcess): use JV_TEMP_UTF_STRING,
changed exception throwing to use error string and exception
helper methods declared in include/win32.h
* java/net/natInetAddressWin32.cc: fixed tab, indentation and
whitespace inconsistencies
replaced <windows.h> #include with <platform.h>
removed jvm.h include
removed DISABLE_JAVA_NET conditional code
removed POSIX conditional code not relevant to Win32
(aton): use JV_TEMP_UTF_STRING
removed POSIX conditional code not relevant to Win32
(lookup): likewise
(getLocalHostName): likewise
* java/net/natNetworkInterfaceWin32.cc: fixed tab, indentation and
whitespace inconsistencies
removed unnecessary windows.h, winsock.h and gcj/cni.h includes
removed DISABLE_JAVA_NET conditional code
removed POSIX conditional code not relevant to Win32
(winsock2GetRealNetworkInterfaces): new function to compute network
interfaces via Winsock2 API
(determineGetRealNetworkInterfacesFN): new function for returning
a function pointer to the function used to compute network interfaces.
(getRealNetworkInterfaces): implemented
* java/net/natPlainDatagramSocketImplWin32.cc: fixed tab, indentation and
whitespace inconsistencies
removed gcj/cni.h include
removed DISABLE_JAVA_NET conditional code
removed POSIX conditional code not relevant to Win32
changed net POSIXisms to Win32isms
replaced _Jv socket-related calls with their real Win32 equivalents
changed exception throwing to use error string and exception
helper methods declared in include/win32.h
(peekData): implemented timeout support
(receive): likewise
* java/net/natPlainSocketImplWin32.cc: fixed tab, indentation and
whitespace inconsistencies
removed gcj/cni.h and gcj/javaprims.h includes
removed DISABLE_JAVA_NET conditional code
removed POSIX conditional code not relevant to Win32
changed net POSIXisms to Win32isms
replaced _Jv socket-related calls with their real Win32
equivalents
changed exception throwing to use error string and exception
helper methods declared in include/win32.h
(throwConnectException): helper function for connect()
(connect): implemented timeout support
(accept): likewise
(doRead): new helper function common to both read() method overloads,
includes timeout support
(read): implemented both overloads in terms of doRead()
(available): implemented using ioctlsocket()
From-SVN: r70904
Diffstat (limited to 'libjava/java/net')
-rw-r--r-- | libjava/java/net/natInetAddressWin32.cc | 265 | ||||
-rw-r--r-- | libjava/java/net/natNetworkInterfaceWin32.cc | 210 | ||||
-rw-r--r-- | libjava/java/net/natPlainDatagramSocketImplWin32.cc | 536 | ||||
-rw-r--r-- | libjava/java/net/natPlainSocketImplWin32.cc | 707 |
4 files changed, 560 insertions, 1158 deletions
diff --git a/libjava/java/net/natInetAddressWin32.cc b/libjava/java/net/natInetAddressWin32.cc index f6748fd..42c7d7d 100644 --- a/libjava/java/net/natInetAddressWin32.cc +++ b/libjava/java/net/natInetAddressWin32.cc @@ -7,124 +7,26 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ #include <config.h> +#include <platform.h> -#ifdef WIN32 - -#include <windows.h> -#include <winsock.h> #undef STRICT -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif /* MAXHOSTNAMELEN */ - -#else /* WIN32 */ - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <string.h> -#include <errno.h> - -#include <sys/param.h> -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif - -#endif /* WIN32 */ - -#include <gcj/cni.h> -#include <jvm.h> #include <java/net/InetAddress.h> #include <java/net/UnknownHostException.h> #include <java/lang/SecurityException.h> -#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME) -#include <sys/utsname.h> -#endif - -#ifndef HAVE_GETHOSTNAME_DECL -extern "C" int gethostname (char *name, int namelen); -#endif - -#ifdef DISABLE_JAVA_NET - -jbyteArray -java::net::InetAddress::aton (jstring) -{ - return NULL; -} - -jint -java::net::InetAddress::getFamily (jbyteArray bytes) -{ - return 0; -} - -JArray<java::net::InetAddress*> * -java::net::InetAddress::lookup (jstring, java::net::InetAddress *, jboolean) -{ - return NULL; -} - -jstring -java::net::InetAddress::getLocalHostname () -{ - return NULL; -} - -#else /* DISABLE_JAVA_NET */ - jbyteArray java::net::InetAddress::aton (jstring host) { - char *hostname; - char buf[100]; - int len = JvGetStringUTFLength(host); - if (len < 100) - hostname = buf; - else - hostname = (char*) _Jv_AllocBytes (len+1); - JvGetStringUTFRegion (host, 0, host->length(), hostname); - buf[len] = '\0'; + JV_TEMP_UTF_STRING (hostname, host); char* bytes = NULL; int blen = 0; -#ifdef HAVE_INET_ATON - struct in_addr laddr; - if (inet_aton (hostname, &laddr)) + unsigned long laddr = inet_addr (hostname); + if (laddr != INADDR_NONE) { bytes = (char*) &laddr; blen = 4; } -#elif defined(HAVE_INET_ADDR) -#if ! HAVE_IN_ADDR_T - typedef jint in_addr_t; -#endif - in_addr_t laddr = inet_addr (hostname); - if (laddr != (in_addr_t)(-1)) - { - bytes = (char*) &laddr; - blen = 4; - } -#endif -#if defined (HAVE_INET_PTON) && defined (HAVE_INET6) - char inet6_addr[16]; - if (len != 0 && inet_pton (AF_INET6, hostname, inet6_addr) > 0) - { - bytes = inet6_addr; - blen = 16; - } -#endif if (blen == 0) return NULL; jbyteArray result = JvNewByteArray (blen); @@ -149,69 +51,17 @@ java::net::InetAddress::getFamily (jbyteArray bytes) JArray<java::net::InetAddress*> * java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, - jboolean all) + jboolean all) { struct hostent *hptr = NULL; -#if defined (HAVE_GETHOSTBYNAME_R) || defined (HAVE_GETHOSTBYADDR_R) - struct hostent hent_r; -#if HAVE_STRUCT_HOSTENT_DATA - struct hostent_data fixed_buffer, *buffer_r = &fixed_buffer; -#else -#if defined (__GLIBC__) - // FIXME: in glibc, gethostbyname_r returns NETDB_INTERNAL to herr and - // ERANGE to errno if the buffer size is too small, rather than what is - // expected here. We work around this by setting a bigger buffer size and - // hoping that it is big enough. - char fixed_buffer[1024]; -#else - char fixed_buffer[200]; -#endif - char *buffer_r = fixed_buffer; - int size_r = sizeof (fixed_buffer); -#endif -#endif - if (host != NULL) { - char *hostname; - char buf[100]; - int len = JvGetStringUTFLength(host); - if (len < 100) - hostname = buf; - else - hostname = (char*) _Jv_AllocBytes (len+1); - JvGetStringUTFRegion (host, 0, host->length(), hostname); - buf[len] = '\0'; -#ifdef HAVE_GETHOSTBYNAME_R - while (true) - { - int ok; -#if HAVE_STRUCT_HOSTENT_DATA - ok = ! gethostbyname_r (hostname, &hent_r, buffer_r); -#else - int herr = 0; -#ifdef GETHOSTBYNAME_R_RETURNS_INT - ok = ! gethostbyname_r (hostname, &hent_r, buffer_r, size_r, - &hptr, &herr); -#else - hptr = gethostbyname_r (hostname, &hent_r, buffer_r, size_r, &herr); - ok = hptr != NULL; -#endif /* GETHOSTNAME_R_RETURNS_INT */ - if (! ok && herr == ERANGE) - { - size_r *= 2; - buffer_r = (char *) _Jv_AllocBytes (size_r); - } - else -#endif /* HAVE_STRUCT_HOSTENT_DATA */ - break; - } -#else + JV_TEMP_UTF_STRING (hostname, host); + // FIXME: this is insufficient if some other piece of code calls // this gethostbyname. JvSynchronize sync (java::net::InetAddress::localhostAddress); hptr = gethostbyname (hostname); -#endif /* HAVE_GETHOSTBYNAME_R */ } else { @@ -221,51 +71,24 @@ java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, int type; char *val; if (len == 4) - { - val = chars; - type = iaddr->family = AF_INET; - } + { + val = chars; + type = iaddr->family = AF_INET; + } #ifdef HAVE_INET6 else if (len == 16) - { - val = (char *) &chars; - type = iaddr->family = AF_INET6; - } + { + val = (char *) &chars; + type = iaddr->family = AF_INET6; + } #endif /* HAVE_INET6 */ else - JvFail ("unrecognized size"); + JvFail ("unrecognized size"); -#ifdef HAVE_GETHOSTBYADDR_R - while (true) - { - int ok; -#if HAVE_STRUCT_HOSTENT_DATA - ok = ! gethostbyaddr_r (val, len, type, &hent_r, buffer_r); -#else - int herr = 0; -#ifdef GETHOSTBYADDR_R_RETURNS_INT - ok = ! gethostbyaddr_r (val, len, type, &hent_r, - buffer_r, size_r, &hptr, &herr); -#else - hptr = gethostbyaddr_r (val, len, type, &hent_r, - buffer_r, size_r, &herr); - ok = hptr != NULL; -#endif /* GETHOSTBYADDR_R_RETURNS_INT */ - if (! ok && herr == ERANGE) - { - size_r *= 2; - buffer_r = (char *) _Jv_AllocBytes (size_r); - } - else -#endif /* HAVE_STRUCT_HOSTENT_DATA */ - break; - } -#else /* HAVE_GETHOSTBYADDR_R */ // FIXME: this is insufficient if some other piece of code calls // this gethostbyaddr. JvSynchronize sync (java::net::InetAddress::localhostAddress); hptr = gethostbyaddr (val, len, type); -#endif /* HAVE_GETHOSTBYADDR_R */ } if (hptr != NULL) { @@ -273,22 +96,23 @@ java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, host = JvNewStringUTF (hptr->h_name); java::lang::SecurityException *ex = checkConnect (host); if (ex != NULL) - { - if (iaddr == NULL || iaddr->addr == NULL) - throw ex; - hptr = NULL; - } + { + if (iaddr == NULL || iaddr->addr == NULL) + throw ex; + hptr = NULL; + } } if (hptr == NULL) { if (iaddr != NULL && iaddr->addr != NULL) - { - iaddr->hostName = iaddr->getHostAddress(); - return NULL; - } + { + iaddr->hostName = iaddr->getHostAddress(); + return NULL; + } else - throw new java::net::UnknownHostException(host); + throw new java::net::UnknownHostException(host); } + int count; if (all) { @@ -298,6 +122,7 @@ java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, } else count = 1; + JArray<java::net::InetAddress*> *result; java::net::InetAddress** iaddrs; if (all) @@ -314,42 +139,30 @@ java::net::InetAddress::lookup (jstring host, java::net::InetAddress* iaddr, for (int i = 0; i < count; i++) { if (iaddrs[i] == NULL) - iaddrs[i] = new java::net::InetAddress (NULL, NULL); + iaddrs[i] = new java::net::InetAddress (NULL, NULL); if (iaddrs[i]->hostName == NULL) iaddrs[i]->hostName = host; if (iaddrs[i]->addr == NULL) - { - char *bytes = hptr->h_addr_list[i]; - iaddrs[i]->addr = JvNewByteArray (hptr->h_length); - iaddrs[i]->family = getFamily (iaddrs[i]->addr); - memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length); - } + { + char *bytes = hptr->h_addr_list[i]; + iaddrs[i]->addr = JvNewByteArray (hptr->h_length); + iaddrs[i]->family = getFamily (iaddrs[i]->addr); + memcpy (elements (iaddrs[i]->addr), bytes, hptr->h_length); + } } + return result; } jstring java::net::InetAddress::getLocalHostname () { - char *chars; -#ifdef HAVE_GETHOSTNAME - char buffer[MAXHOSTNAMELEN]; - if (gethostname (buffer, MAXHOSTNAMELEN)) + char buffer[400]; + if (gethostname (buffer, sizeof(buffer))) return NULL; - chars = buffer; -#elif HAVE_UNAME - struct utsname stuff; - if (uname (&stuff) != 0) - return NULL; - chars = stuff.nodename; -#else - return NULL; -#endif // It is admittedly non-optimal to convert the hostname to Unicode // only to convert it back in getByName, but simplicity wins. Note // that unless there is a SecurityManager, we only get called once // anyway, thanks to the InetAddress.localhost cache. - return JvNewStringUTF (chars); + return JvNewStringUTF (buffer); } - -#endif /* DISABLE_JAVA_NET */ diff --git a/libjava/java/net/natNetworkInterfaceWin32.cc b/libjava/java/net/natNetworkInterfaceWin32.cc index 47d68b5..20c9a9b 100644 --- a/libjava/java/net/natNetworkInterfaceWin32.cc +++ b/libjava/java/net/natNetworkInterfaceWin32.cc @@ -9,134 +9,126 @@ details. */ #include <config.h> #include <platform.h> -#ifdef WIN32 - -#include <windows.h> -#include <winsock.h> #undef STRICT -#else /* WIN32 */ - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -#include <sys/param.h> -#include <sys/types.h> -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -#define BSD_COMP /* Get FIONREAD on Solaris2. */ -#include <sys/ioctl.h> -#endif -#ifdef HAVE_NET_IF_H -#include <net/if.h> -#endif - -#endif /* WIN32 */ - -#include <gcj/cni.h> -#include <jvm.h> #include <java/net/NetworkInterface.h> #include <java/net/Inet4Address.h> #include <java/net/SocketException.h> #include <java/util/Vector.h> -#ifdef DISABLE_JAVA_NET +/* As of this writing, NetworkInterface.java has + getName() == getDisplayName() and only one IP address + per interface. If this changes, we'll need to use + iphlpapi (not supported on Win95) to retrieve richer + adapter information via GetAdaptersInfo(). In this + module, we provide the necessary hooks to detect the + presence of iphlpapi and use it if necessary, but + comment things out for now to avoid compiler warnings. */ -::java::util::Vector* -java::net::NetworkInterface::getRealNetworkInterfaces () -{ - ::java::util::Vector* ht = new ::java::util::Vector(); - return ht; -} +enum {MAX_INTERFACES = 50}; -#else /* DISABLE_JAVA_NET */ +typedef int +(*PfnGetRealNetworkInterfaces) (jstring* pjstrName, + java::net::InetAddress** ppAddress); -::java::util::Vector* -java::net::NetworkInterface::getRealNetworkInterfaces () +static int +winsock2GetRealNetworkInterfaces (jstring* pjstrName, + java::net::InetAddress** ppAddress) { -#ifdef WIN32 - throw new ::java::net::SocketException; -#else - int fd; - int num_interfaces = 0; - struct ifconf if_data; - struct ifreq* if_record; - ::java::util::Vector* ht = new ::java::util::Vector (); - - if_data.ifc_len = 0; - if_data.ifc_buf = NULL; - - // Open a (random) socket to have a file descriptor for the ioctl calls. - fd = _Jv_socket (PF_INET, SOCK_DGRAM, htons (IPPROTO_IP)); - - if (fd < 0) - throw new ::java::net::SocketException; - - // Get all interfaces. If not enough buffers are available try it - // with a bigger buffer size. - do - { - num_interfaces += 16; - - if_data.ifc_len = sizeof (struct ifreq) * num_interfaces; - if_data.ifc_buf = - (char*) _Jv_Realloc (if_data.ifc_buf, if_data.ifc_len); - - // Try to get all local interfaces. - if (::ioctl (fd, SIOCGIFCONF, &if_data) < 0) - throw new java::net::SocketException; - } - while (if_data.ifc_len >= (sizeof (struct ifreq) * num_interfaces)); - + // FIXME: Add IPv6 support. + + INTERFACE_INFO arInterfaceInfo[MAX_INTERFACES]; + + // Open a (random) socket to have a file descriptor for the WSAIoctl call. + SOCKET skt = ::socket (AF_INET, SOCK_DGRAM, 0); + if (skt == INVALID_SOCKET) + _Jv_ThrowSocketException (); + + DWORD dwOutBufSize; + int nRetCode = ::WSAIoctl (skt, SIO_GET_INTERFACE_LIST, + NULL, 0, &arInterfaceInfo, sizeof(arInterfaceInfo), + &dwOutBufSize, NULL, NULL); + + if (nRetCode == SOCKET_ERROR) + { + DWORD dwLastErrorCode = WSAGetLastError (); + ::closesocket (skt); + _Jv_ThrowSocketException (dwLastErrorCode); + } + // Get addresses of all interfaces. - if_record = if_data.ifc_req; - - for (int n = 0; n < if_data.ifc_len; n += sizeof (struct ifreq)) + int nNbInterfaces = dwOutBufSize / sizeof(INTERFACE_INFO); + int nCurETHInterface = 0; + for (int i=0; i < nNbInterfaces; ++i) { - struct ifreq ifr; - - memset (&ifr, 0, sizeof (ifr)); - strcpy (ifr.ifr_name, if_record->ifr_name); - - // Try to get the IPv4-address of the local interface - if (::ioctl (fd, SIOCGIFADDR, &ifr) < 0) - throw new java::net::SocketException; - int len = 4; - struct sockaddr_in sa = *((sockaddr_in*) &(ifr.ifr_addr)); - jbyteArray baddr = JvNewByteArray (len); - memcpy (elements (baddr), &(sa.sin_addr), len); - jstring if_name = JvNewStringLatin1 (if_record->ifr_name); - Inet4Address* address = + SOCKADDR_IN* pAddr = (SOCKADDR_IN*) &arInterfaceInfo[i].iiAddress; + memcpy (elements (baddr), &(pAddr->sin_addr), len); + + // Concoct a name for this interface. Since we don't + // have access to the real name under Winsock 2, we use + // "lo" for the loopback interface and ethX for the + // real ones. + char szName[30]; + u_long lFlags = arInterfaceInfo[i].iiFlags; + + if (lFlags & IFF_LOOPBACK) + strcpy (szName, "lo"); + else + { + strcpy (szName, "eth"); + wsprintf(szName+3, "%d", nCurETHInterface++); + } + + jstring if_name = JvNewStringLatin1 (szName); + java::net::Inet4Address* address = new java::net::Inet4Address (baddr, JvNewStringLatin1 ("")); - ht->add (new NetworkInterface (if_name, address)); - if_record++; + pjstrName[i] = if_name; + ppAddress[i] = address; } -#ifdef HAVE_INET6 - // FIXME: read /proc/net/if_inet6 (on Linux 2.4) -#endif - - _Jv_Free (if_data.ifc_buf); + ::closesocket (skt); - if (fd >= 0) - _Jv_close (fd); + return nNbInterfaces; +} + +/* +static int +iphlpapiGetRealNetworkInterfaces (jstring* pjstrName, + java::net::InetAddress** ppAddress) +{ + return 0; +} +*/ + +static PfnGetRealNetworkInterfaces +determineGetRealNetworkInterfacesFN () +{ + /* FIXME: Try to dynamically load iphlpapi.dll and + detect the presence of GetAdaptersInfo() using + GetProcAddress(). If successful, return + iphlpapiGetRealNetworkInterfaces; if not, + return winsock2GetRealNetworkInterfaces */ + return &winsock2GetRealNetworkInterfaces; +} + +::java::util::Vector* +java::net::NetworkInterface::getRealNetworkInterfaces () +{ + static PfnGetRealNetworkInterfaces pfn = + determineGetRealNetworkInterfacesFN (); + + jstring arIFName[MAX_INTERFACES]; + InetAddress* arpInetAddress[MAX_INTERFACES]; + ::java::util::Vector* ht = new ::java::util::Vector (); + int nNbInterfaces = (*pfn) (arIFName, arpInetAddress); + for (int i=0; i < nNbInterfaces; ++i) + { + ht->add (new java::net::NetworkInterface (arIFName[i], + arpInetAddress[i])); + } + return ht; -#endif /* WIN32 */ } - -#endif // DISABLE_JAVA_NET // diff --git a/libjava/java/net/natPlainDatagramSocketImplWin32.cc b/libjava/java/net/natPlainDatagramSocketImplWin32.cc index d0d006d..53927de 100644 --- a/libjava/java/net/natPlainDatagramSocketImplWin32.cc +++ b/libjava/java/net/natPlainDatagramSocketImplWin32.cc @@ -8,31 +8,13 @@ details. */ #include <config.h> #include <platform.h> - -#ifdef WIN32 - -#include <errno.h> #include <string.h> -#else /* WIN32 */ - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#include <errno.h> -#include <string.h> - -#endif /* WIN32 */ - #if HAVE_BSTRING_H -// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 +// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 #include <bstring.h> #endif -#include <gcj/cni.h> #include <java/io/IOException.h> #include <java/io/InterruptedIOException.h> #include <java/net/BindException.h> @@ -42,116 +24,12 @@ details. */ #include <java/net/NetworkInterface.h> #include <java/net/DatagramPacket.h> #include <java/net/PortUnreachableException.h> +#include <java/net/SocketTimeoutException.h> #include <java/lang/InternalError.h> #include <java/lang/Object.h> #include <java/lang/Boolean.h> #include <java/lang/Integer.h> -#ifdef DISABLE_JAVA_NET - -void -java::net::PlainDatagramSocketImpl::create () -{ - throw new SocketException ( - JvNewStringLatin1 ("DatagramSocketImpl.create: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::bind (jint, java::net::InetAddress *) -{ - throw new BindException ( - JvNewStringLatin1 ("DatagramSocketImpl.bind: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint) -{ - throw new SocketException ( - JvNewStringLatin1 ("DatagramSocketImpl.connect: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::disconnect () -{ - throw new SocketException ( - JvNewStringLatin1 ("DatagramSocketImpl.disconnect: unimplemented")); -} - -jint -java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.peek: unimplemented")); -} - -jint -java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.peekData: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::close () -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.close: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.send: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.receive: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::setTimeToLive (jint) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.setTimeToLive: unimplemented")); -} - -jint -java::net::PlainDatagramSocketImpl::getTimeToLive () -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.getTimeToLive: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *, - java::net::NetworkInterface *, - jboolean) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("DatagramSocketImpl.mcastGrp: unimplemented")); -} - -void -java::net::PlainDatagramSocketImpl::setOption (jint, java::lang::Object *) -{ - throw new SocketException ( - JvNewStringLatin1 ("DatagramSocketImpl.setOption: unimplemented")); -} - -java::lang::Object * -java::net::PlainDatagramSocketImpl::getOption (jint) -{ - throw new SocketException ( - JvNewStringLatin1 ("DatagramSocketImpl.getOption: unimplemented")); -} - -#else /* DISABLE_JAVA_NET */ - - union SockAddr { struct sockaddr_in address; @@ -178,31 +56,29 @@ union InAddr #endif }; - // FIXME: routines here and/or in natPlainSocketImpl.cc could throw // NoRouteToHostException; also consider UnknownHostException, ConnectException. void java::net::PlainDatagramSocketImpl::create () { - int sock = _Jv_socket (AF_INET, SOCK_DGRAM, 0); + SOCKET sock = ::socket (AF_INET, SOCK_DGRAM, 0); - if (sock < 0) + if (sock == INVALID_SOCKET) { - char* strerr = strerror (errno); - throw new java::net::SocketException (JvNewStringUTF (strerr)); + _Jv_ThrowSocketException (); } _Jv_platform_close_on_exec (sock); // We use fnum in place of fd here. From leaving fd null we avoid // the double close problem in FileDescriptor.finalize. - fnum = sock; + fnum = (int) sock; } void java::net::PlainDatagramSocketImpl::bind (jint lport, - java::net::InetAddress *host) + java::net::InetAddress *host) { union SockAddr u; struct sockaddr *ptr = (struct sockaddr *) &u.address; @@ -235,7 +111,7 @@ java::net::PlainDatagramSocketImpl::bind (jint lport, else throw new java::net::SocketException (JvNewStringUTF ("invalid length")); - if (_Jv_bind (fnum, ptr, len) == 0) + if (::bind (fnum, ptr, len) == 0) { socklen_t addrlen = sizeof(u); @@ -248,30 +124,30 @@ java::net::PlainDatagramSocketImpl::bind (jint lport, /* Allow broadcast by default. */ int broadcast = 1; - if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast, + if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast, sizeof (broadcast)) != 0) goto error; return; } - error: - char* strerr = strerror (errno); - throw new java::net::BindException (JvNewStringUTF (strerr)); +error: + DWORD dwErrorCode = WSAGetLastError (); + throw new java::net::BindException (_Jv_WinStrError (dwErrorCode)); } void java::net::PlainDatagramSocketImpl::connect (java::net::InetAddress *, jint) -{ +{ throw new ::java::lang::InternalError (JvNewStringLatin1 ( - "PlainDatagramSocketImpl::connect: not implemented yet")); + "PlainDatagramSocketImpl::connect: not implemented yet")); } void java::net::PlainDatagramSocketImpl::disconnect () { throw new ::java::lang::InternalError (JvNewStringLatin1 ( - "PlainDatagramSocketImpl::disconnect: not implemented yet")); + "PlainDatagramSocketImpl::disconnect: not implemented yet")); } jint @@ -307,13 +183,14 @@ java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i) i->addr = raddr; return rport; - error: - char* strerr = strerror (errno); - - if (errno == ECONNREFUSED) - throw new PortUnreachableException (JvNewStringUTF (strerr)); - - throw new java::io::IOException (JvNewStringUTF (strerr)); +error: + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + + _Jv_ThrowIOException (); + return -1; + // we should never get here } jint @@ -325,29 +202,18 @@ java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p) jbyte *dbytes = elements (p->getData()); ssize_t retlen = 0; -// FIXME: implement timeout support for Win32 -#ifndef WIN32 - // Do timeouts via select since SO_RCVTIMEO is not always available. - if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE) + if (timeout > 0) { - fd_set rset; - struct timeval tv; - FD_ZERO(&rset); - FD_SET(fnum, &rset); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - int retval; - if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0) + int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) goto error; - else if (retval == 0) - throw new java::io::InterruptedIOException (); } -#endif /* WIN32 */ retlen = ::recvfrom (fnum, (char *) dbytes, p->getLength(), MSG_PEEK, (sockaddr*) &u, &addrlen); - if (retlen < 0) + if (retlen == SOCKET_ERROR) goto error; // FIXME: Deal with Multicast addressing and if the socket is connected. jbyteArray raddr; @@ -374,13 +240,17 @@ java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p) p->setLength ((jint) retlen); return rport; - error: - char* strerr = strerror (errno); - - if (errno == ECONNREFUSED) - throw new PortUnreachableException (JvNewStringUTF (strerr)); +error: + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + else if (dwErrorCode == WSAETIMEDOUT) + throw new java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode)); + else + _Jv_ThrowIOException (); - throw new java::io::IOException (JvNewStringUTF (strerr)); + return -1; + // we should never get here } // Close(shutdown) the socket. @@ -392,7 +262,7 @@ java::net::PlainDatagramSocketImpl::close () // The method isn't declared to throw anything, so we disregard // the return value. - _Jv_close (fnum); + ::closesocket (fnum); fnum = -1; timeout = 0; } @@ -430,12 +300,11 @@ java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p) if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0) return; - char* strerr = strerror (errno); - - if (errno == ECONNREFUSED) - throw new PortUnreachableException (JvNewStringUTF (strerr)); + DWORD dwErrorCode = WSAGetLastError (); + if (dwErrorCode == WSAECONNRESET) + throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode)); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } void @@ -447,24 +316,16 @@ java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p) jbyte *dbytes = elements (p->getData()); ssize_t retlen = 0; -// FIXME: implement timeout support for Win32 -#ifndef WIN32 - // Do timeouts via select since SO_RCVTIMEO is not always available. - if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE) + if (timeout > 0) { - fd_set rset; - struct timeval tv; - FD_ZERO(&rset); - FD_SET(fnum, &rset); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - int retval; - if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0) + // This implementation doesn't allow specifying an infinite + // timeout after specifying a finite one, but Sun's JDK 1.4.1 + // didn't seem to allow this either.... + int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) goto error; - else if (retval == 0) - throw new java::io::InterruptedIOException (); } -#endif /* WIN32 */ retlen = ::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (sockaddr*) &u, @@ -497,12 +358,13 @@ java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p) return; error: - char* strerr = strerror (errno); - - if (errno == ECONNREFUSED) - throw new PortUnreachableException (JvNewStringUTF (strerr)); - - throw new java::io::IOException (JvNewStringUTF (strerr)); + DWORD dwErrorCode = WSAGetLastError(); + if (dwErrorCode == WSAECONNRESET) + throw new PortUnreachableException (_Jv_WinStrError (dwErrorCode)); + else if (dwErrorCode == WSAETIMEDOUT) + throw new java::net::SocketTimeoutException (_Jv_WinStrError (dwErrorCode)); + else + throw new java::io::IOException (_Jv_WinStrError (dwErrorCode)); } void @@ -515,8 +377,7 @@ java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl) if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0) return; - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } jint @@ -529,20 +390,19 @@ java::net::PlainDatagramSocketImpl::getTimeToLive () if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0) return ((int) val) & 0xFF; - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); + + return -1; + // we should never get here } void java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr, java::net::NetworkInterface *, - jboolean join) + jboolean) { // FIXME: implement use of NetworkInterface - - union McastReq u; jbyteArray haddress = inetaddr->addr; - jbyte *bytes = elements (haddress); int len = haddress->length; int level, opname; const char *ptr; @@ -556,7 +416,7 @@ java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr, memcpy (&u.mreq.imr_multiaddr, bytes, len); // FIXME: If a non-default interface is set, use it; see Stevens p. 501. // Maybe not, see note in last paragraph at bottom of Stevens p. 497. - u.mreq.imr_interface.s_addr = htonl (INADDR_ANY); + u.mreq.imr_interface.s_addr = htonl (INADDR_ANY); len = sizeof (struct ip_mreq); ptr = (const char *) &u.mreq; } @@ -589,13 +449,12 @@ java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr, if (::setsockopt (fnum, level, opname, ptr, len) == 0) return; - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } void java::net::PlainDatagramSocketImpl::setOption (jint optID, - java::lang::Object *value) + java::lang::Object *value) { int val; socklen_t val_len = sizeof (val); @@ -605,19 +464,19 @@ java::net::PlainDatagramSocketImpl::setOption (jint optID, if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$)) { - java::lang::Boolean *boolobj = + java::lang::Boolean *boolobj = static_cast<java::lang::Boolean *> (value); val = boolobj->booleanValue() ? 1 : 0; } else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$)) { - java::lang::Integer *intobj = - static_cast<java::lang::Integer *> (value); + java::lang::Integer *intobj = + static_cast<java::lang::Integer *> (value); val = (int) intobj->intValue(); } // Else assume value to be an InetAddress for use with IP_MULTICAST_IF. - switch (optID) + switch (optID) { case _Jv_TCP_NODELAY_ : throw new java::net::SocketException ( @@ -636,103 +495,92 @@ java::net::PlainDatagramSocketImpl::setOption (jint optID, if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val, val_len) != 0) goto error; - break; - + break; + case _Jv_SO_OOBINLINE_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_OOBINLINE: not valid for UDP")); break; - + case _Jv_SO_SNDBUF_ : case _Jv_SO_RCVBUF_ : -#if defined(SO_SNDBUF) && defined(SO_RCVBUF) int opt; optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0) - goto error; -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")); -#endif + goto error; return; case _Jv_SO_REUSEADDR_ : -#if defined(SO_REUSEADDR) - if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val, - val_len) != 0) - goto error; -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_REUSEADDR not supported")); -#endif - return; + if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val, + val_len) != 0) + goto error; + return; case _Jv_SO_BINDADDR_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_BINDADDR: read only option")); return; case _Jv_IP_MULTICAST_IF_ : - union InAddr u; + union InAddr u; jbyteArray haddress; - jbyte *bytes; - int len; - int level, opname; - const char *ptr; - - haddress = ((java::net::InetAddress *) value)->addr; - bytes = elements (haddress); - len = haddress->length; - if (len == 4) - { - level = IPPROTO_IP; - opname = IP_MULTICAST_IF; - memcpy (&u.addr, bytes, len); - len = sizeof (struct in_addr); - ptr = (const char *) &u.addr; - } + jbyte *bytes; + int len; + int level, opname; + const char *ptr; + + haddress = ((java::net::InetAddress *) value)->addr; + bytes = elements (haddress); + len = haddress->length; + if (len == 4) + { + level = IPPROTO_IP; + opname = IP_MULTICAST_IF; + memcpy (&u.addr, bytes, len); + len = sizeof (struct in_addr); + ptr = (const char *) &u.addr; + } // Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF) - else if (len == 16) - { - level = IPPROTO_IPV6; - opname = IPV6_MULTICAST_IF; - memcpy (&u.addr6, bytes, len); - len = sizeof (struct in6_addr); - ptr = (const char *) &u.addr6; - } + else if (len == 16) + { + level = IPPROTO_IPV6; + opname = IPV6_MULTICAST_IF; + memcpy (&u.addr6, bytes, len); + len = sizeof (struct in6_addr); + ptr = (const char *) &u.addr6; + } #endif - else - throw - new java::net::SocketException (JvNewStringUTF ("invalid length")); + else + throw + new java::net::SocketException (JvNewStringUTF ("invalid length")); - if (::setsockopt (fnum, level, opname, ptr, len) != 0) - goto error; + if (::setsockopt (fnum, level, opname, ptr, len) != 0) + goto error; return; - + case _Jv_IP_MULTICAST_IF2_ : throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented")); break; - + case _Jv_IP_MULTICAST_LOOP_ : throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented")); break; - + case _Jv_IP_TOS_ : if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val, - val_len) != 0) - goto error; - return; - + val_len) != 0) + goto error; + return; + case _Jv_SO_TIMEOUT_ : - timeout = val; + timeout = val; return; default : - errno = ENOPROTOOPT; + WSASetLastError (WSAENOPROTOOPT); } error: - char* strerr = strerror (errno); - throw new java::net::SocketException (JvNewStringUTF (strerr)); + _Jv_ThrowSocketException (); } java::lang::Object * @@ -752,121 +600,105 @@ java::net::PlainDatagramSocketImpl::getOption (jint optID) case _Jv_SO_LINGER_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_LINGER not valid for UDP")); - break; + break; case _Jv_SO_KEEPALIVE_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_KEEPALIVE not valid for UDP")); break; - + case _Jv_SO_BROADCAST_ : - if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val, - &val_len) != 0) - goto error; - return new java::lang::Boolean (val != 0); - + if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val, + &val_len) != 0) + goto error; + return new java::lang::Boolean (val != 0); + case _Jv_SO_OOBINLINE_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_OOBINLINE not valid for UDP")); break; - + case _Jv_SO_RCVBUF_ : case _Jv_SO_SNDBUF_ : -#if defined(SO_SNDBUF) && defined(SO_RCVBUF) int opt; optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0) - goto error; + goto error; else - return new java::lang::Integer (val); -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")); -#endif - break; + return new java::lang::Integer (val); + break; case _Jv_SO_BINDADDR_: - // cache the local address - if (localAddress == NULL) - { - jbyteArray laddr; - if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0) - goto error; - if (u.address.sin_family == AF_INET) - { - laddr = JvNewByteArray (4); - memcpy (elements (laddr), &u.address.sin_addr, 4); - } + // cache the local address + if (localAddress == NULL) + { + jbyteArray laddr; + if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0) + goto error; + if (u.address.sin_family == AF_INET) + { + laddr = JvNewByteArray (4); + memcpy (elements (laddr), &u.address.sin_addr, 4); + } #ifdef HAVE_INET6 else if (u.address.sin_family == AF_INET6) - { - laddr = JvNewByteArray (16); - memcpy (elements (laddr), &u.address6.sin6_addr, 16); - } + { + laddr = JvNewByteArray (16); + memcpy (elements (laddr), &u.address6.sin6_addr, 16); + } #endif - else - throw new java::net::SocketException ( - JvNewStringUTF ("invalid family")); - localAddress = new java::net::InetAddress (laddr, NULL); - } - return localAddress; - break; + else + throw new java::net::SocketException ( + JvNewStringUTF ("invalid family")); + localAddress = new java::net::InetAddress (laddr, NULL); + } + return localAddress; + break; case _Jv_SO_REUSEADDR_ : -#if defined(SO_REUSEADDR) - if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val, - &val_len) != 0) - goto error; - return new java::lang::Boolean (val != 0); -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_REUSEADDR not supported")); -#endif - break; + if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val, + &val_len) != 0) + goto error; + return new java::lang::Boolean (val != 0); + break; case _Jv_IP_MULTICAST_IF_ : -#ifdef HAVE_INET_NTOA - struct in_addr inaddr; - socklen_t inaddr_len; - char *bytes; - - inaddr_len = sizeof(inaddr); - if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr, - &inaddr_len) != 0) - goto error; - - bytes = inet_ntoa (inaddr); - - return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes)); -#else - throw new java::net::SocketException ( - JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()")); -#endif - break; + struct in_addr inaddr; + socklen_t inaddr_len; + char *bytes; + + inaddr_len = sizeof(inaddr); + if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr, + &inaddr_len) != 0) + goto error; + + bytes = inet_ntoa (inaddr); + + return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes)); + break; case _Jv_SO_TIMEOUT_ : - return new java::lang::Integer (timeout); - break; - + return new java::lang::Integer (timeout); + break; + case _Jv_IP_MULTICAST_IF2_ : throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented")); break; - + case _Jv_IP_MULTICAST_LOOP_ : - if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val, - &val_len) != 0) - goto error; - return new java::lang::Boolean (val != 0); - + if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val, + &val_len) != 0) + goto error; + return new java::lang::Boolean (val != 0); + case _Jv_IP_TOS_ : if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val, &val_len) != 0) goto error; return new java::lang::Integer (val); - + default : - errno = ENOPROTOOPT; + WSASetLastError (WSAENOPROTOOPT); } - error: - char* strerr = strerror (errno); - throw new java::net::SocketException (JvNewStringUTF (strerr)); +error: + _Jv_ThrowSocketException (); + return 0; + // we should never get here } - -#endif /* DISABLE_JAVA_NET */ diff --git a/libjava/java/net/natPlainSocketImplWin32.cc b/libjava/java/net/natPlainSocketImplWin32.cc index 1485ea8..d43ad23 100644 --- a/libjava/java/net/natPlainSocketImplWin32.cc +++ b/libjava/java/net/natPlainSocketImplWin32.cc @@ -9,61 +9,10 @@ details. */ #include <config.h> #include <platform.h> -#ifndef DISABLE_JAVA_NET - -#ifdef WIN32 - -#include <windows.h> -#include <winsock.h> -#include <errno.h> -#include <string.h> #undef STRICT #undef MAX_PRIORITY #undef MIN_PRIORITY -#undef FIONREAD - -// These functions make the Win32 socket API look more POSIXy -static inline int -write(int s, void *buf, int len) -{ - return send(s, (char*)buf, len, 0); -} - -static inline int -read(int s, void *buf, int len) -{ - return recv(s, (char*)buf, len, 0); -} - -// these errors cannot occur on Win32 -#else /* WIN32 */ - -#ifdef HAVE_SYS_IOCTL_H -#define BSD_COMP /* Get FIONREAD on Solaris2. */ -#include <sys/ioctl.h> -#endif - -// Pick up FIONREAD on Solaris 2.5. -#ifdef HAVE_SYS_FILIO_H -#include <sys/filio.h> -#endif - -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <errno.h> -#include <string.h> -#endif /* WIN32 */ -#endif /* DISABLE_JAVA_NET */ - -#if HAVE_BSTRING_H -// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 -#include <bstring.h> -#endif - - -#include <gcj/cni.h> -#include <gcj/javaprims.h> #include <java/io/IOException.h> #include <java/io/InterruptedIOException.h> #include <java/net/BindException.h> @@ -83,122 +32,6 @@ read(int s, void *buf, int len) #include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/IllegalArgumentException.h> -#ifdef DISABLE_JAVA_NET - -void -java::net::PlainSocketImpl::create (jboolean) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("SocketImpl.create: unimplemented")); -} - -void -java::net::PlainSocketImpl::bind (java::net::InetAddress *, jint) -{ - throw new BindException ( - JvNewStringLatin1 ("SocketImpl.bind: unimplemented")); -} - -void -java::net::PlainSocketImpl::connect (java::net::SocketAddress *, jint) -{ - throw new ConnectException ( - JvNewStringLatin1 ("SocketImpl.connect: unimplemented")); -} - -void -java::net::PlainSocketImpl::listen (jint) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("SocketImpl.listen: unimplemented")); -} - -void -java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *) -{ - throw new java::io::IOException ( - JvNewStringLatin1 ("SocketImpl.accept: unimplemented")); -} - -void -java::net::PlainSocketImpl::setOption (jint, java::lang::Object *) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.setOption: unimplemented")); -} - -java::lang::Object * -java::net::PlainSocketImpl::getOption (jint) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.getOption: unimplemented")); -} - -jint -java::net::PlainSocketImpl::read(void) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.read: unimplemented")); -} - -jint -java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.read: unimplemented")); -} - -void -java::net::PlainSocketImpl::write(jint b) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.write: unimplemented")); -} - -void -java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.write: unimplemented")); -} - -void -java::net::PlainSocketImpl::sendUrgentData(jint data) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented")); -} - -jint -java::net::PlainSocketImpl::available(void) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.available: unimplemented")); -} - -void -java::net::PlainSocketImpl::close(void) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.close: unimplemented")); -} - -void -java::net::PlainSocketImpl::shutdownInput (void) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented")); -} - -void -java::net::PlainSocketImpl::shutdownOutput (void) -{ - throw new SocketException ( - JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented")); -} - -#else /* DISABLE_JAVA_NET */ - union SockAddr { struct sockaddr_in address; @@ -210,12 +43,11 @@ union SockAddr void java::net::PlainSocketImpl::create (jboolean stream) { - int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); + int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); - if (sock < 0) + if (sock == int(INVALID_SOCKET)) { - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } _Jv_platform_close_on_exec (sock); @@ -261,15 +93,15 @@ java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport) // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT. ::setsockopt(fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i)); - - if (_Jv_bind (fnum, ptr, len) == 0) + + if (::bind (fnum, ptr, len) != SOCKET_ERROR) { address = host; socklen_t addrlen = sizeof(u); if (lport != 0) localport = lport; - else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0) + else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != SOCKET_ERROR) localport = ntohs (u.address.sin_port); else goto error; @@ -277,9 +109,21 @@ java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport) return; } - error: - char* strerr = strerror (errno); - throw new java::net::BindException (JvNewStringUTF (strerr)); +error: + DWORD dwErrorCode = WSAGetLastError (); + throw new java::net::BindException (_Jv_WinStrError (dwErrorCode)); +} + +static void +throwConnectException (DWORD dwErrorCode) +{ + throw new java::net::ConnectException (_Jv_WinStrError (dwErrorCode)); +} + +static void +throwConnectException () +{ + throwConnectException (WSAGetLastError ()); } void @@ -289,13 +133,14 @@ java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr, java::net::InetSocketAddress *tmp = (java::net::InetSocketAddress*) addr; java::net::InetAddress *host = tmp->getAddress(); jint rport = tmp->getPort(); - + union SockAddr u; socklen_t addrlen = sizeof(u); jbyteArray haddress = host->addr; jbyte *bytes = elements (haddress); int len = haddress->length; struct sockaddr *ptr = (struct sockaddr *) &u.address; + if (len == 4) { u.address.sin_family = AF_INET; @@ -315,35 +160,49 @@ java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr, else throw new java::net::SocketException (JvNewStringUTF ("invalid length")); -// FIXME: implement timeout support for Win32 -#ifndef WIN32 if (timeout > 0) { - int flags = ::fcntl (fnum, F_GETFL); - ::fcntl (fnum, F_SETFL, flags | O_NONBLOCK); - - if ((_Jv_connect (fnum, ptr, len) != 0) && (errno != EINPROGRESS)) - goto error; + // FIXME: we're creating a fresh WSAEVENT for each connect(). + WSAEventWrapper aWSAEventWrapper(fnum, FD_CONNECT); + WSAEVENT hEvent = aWSAEventWrapper.getEventHandle (); - fd_set rset; - struct timeval tv; - FD_ZERO(&rset); - FD_SET(fnum, &rset); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - int retval; - - if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0) - goto error; - else if (retval == 0) - throw new java::net::SocketTimeoutException - (JvNewStringUTF ("Connect timed out")); + if (::connect (fnum, ptr, len) == SOCKET_ERROR) + { + if (WSAGetLastError () != WSAEWOULDBLOCK) + throwConnectException (); + + DWORD dwRet = + WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false); + // use true, false instead of TRUE, FALSE because the + // MS constants got undefined + + if (dwRet == WSA_WAIT_FAILED) + throwConnectException (); + + else if (dwRet == WSA_WAIT_TIMEOUT) + throw new java::net::SocketTimeoutException + (JvNewStringUTF ("connect timed out")); + + // If we get here, we still need to check whether the actual + // connect() succeeded. Use any socket-specific error code + // instead of the thread-based one. + int nErrCode; int nErrLen=sizeof(nErrCode); + if (::getsockopt(fnum, SOL_SOCKET, SO_ERROR, (char*) &nErrCode, + &nErrLen) == SOCKET_ERROR) + { + throwConnectException (); + } + + if (nErrCode != NO_ERROR) + { + throwConnectException (nErrCode); + } + } } else -#endif { - if (_Jv_connect (fnum, ptr, len) != 0) - goto error; + if (::connect (fnum, ptr, len) == SOCKET_ERROR) + throwConnectException(); } address = host; @@ -352,26 +211,19 @@ java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr, // A bind may not have been done on this socket; if so, set localport now. if (localport == 0) { - if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0) + if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != SOCKET_ERROR) localport = ntohs (u.address.sin_port); else - goto error; + throwConnectException(); } - - return; - - error: - char* strerr = strerror (errno); - throw new java::net::ConnectException (JvNewStringUTF (strerr)); } void java::net::PlainSocketImpl::listen (jint backlog) { - if (::listen (fnum, backlog) != 0) + if (::listen (fnum, backlog) == SOCKET_ERROR) { - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } } @@ -380,31 +232,61 @@ java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s) { union SockAddr u; socklen_t addrlen = sizeof(u); - int new_socket = 0; + int new_socket = 0; -// FIXME: implement timeout support for Win32 -#ifndef WIN32 - // Do timeouts via select since SO_RCVTIMEO is not always available. - if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE) + if (timeout > 0) { - fd_set rset; - struct timeval tv; - FD_ZERO(&rset); - FD_SET(fnum, &rset); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - int retval; - if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0) - goto error; - else if (retval == 0) - throw new java::io::InterruptedIOException ( - JvNewStringUTF("Accept timed out")); - } -#endif /* WIN32 */ + // FIXME: we're creating a fresh WSAEVENT for each accept(). + // One possible alternative would be that fnum really points + // to an extended structure consisting of the SOCKET, its + // associated WSAEVENT, etc. + WSAEventWrapper aWSAEventWrapper(fnum, FD_ACCEPT); + WSAEVENT hEvent = aWSAEventWrapper.getEventHandle (); + + for (;;) + { + new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen); + + if (new_socket != int(INVALID_SOCKET)) + { + // This new child socket is nonblocking because the parent + // socket became nonblocking via the WSAEventSelect() call, + // so we set its mode back to blocking. + WSAEventSelect (new_socket, hEvent, 0); + // undo the hEvent <-> FD_ACCEPT association inherited + // inherited from our parent socket + + unsigned long lSockOpt = 0L; + // blocking mode + if (ioctlsocket(new_socket, FIONBIO, &lSockOpt) == SOCKET_ERROR) + { + goto error; + } + break; + } + else if (WSAGetLastError () != WSAEWOULDBLOCK) + { + goto error; + } - new_socket = _Jv_accept (fnum, (sockaddr*) &u, &addrlen); + DWORD dwRet = + WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false); + // use true, false instead of TRUE, FALSE because the + // MS constants got undefined + + if (dwRet == WSA_WAIT_FAILED) + goto error; + else if (dwRet == WSA_WAIT_TIMEOUT) + throw new java::net::SocketTimeoutException + (JvNewStringUTF ("accept timed out")); + } + } + else + { + new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen); + } - if (new_socket < 0) + if (new_socket == int(INVALID_SOCKET)) goto error; _Jv_platform_close_on_exec (new_socket); @@ -435,8 +317,7 @@ java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s) return; error: - char* strerr = strerror (errno); - throw new java::io::IOException (JvNewStringUTF (strerr)); + _Jv_ThrowIOException (); } // Close(shutdown) the socket. @@ -447,14 +328,16 @@ java::net::PlainSocketImpl::close() JvSynchronize sync (this); // should we use shutdown here? how would that effect so_linger? - int res = _Jv_close (fnum); + int res = ::closesocket (fnum); if (res == -1) { // These three errors are not errors according to tests performed // on the reference implementation. - if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF) - throw new java::io::IOException (JvNewStringUTF (strerror (errno))); + DWORD dwErr = WSAGetLastError(); + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); } // Safe place to reset the file pointer. fnum = -1; @@ -470,20 +353,22 @@ java::net::PlainSocketImpl::write(jint b) while (r != 1) { - r = _Jv_write (fnum, &d, 1); + r = ::send (fnum, (char*) &d, 1, 0); if (r == -1) { + DWORD dwErr = WSAGetLastError(); if (java::lang::Thread::interrupted()) { java::io::InterruptedIOException *iioe - = new java::io::InterruptedIOException - (JvNewStringLatin1 (strerror (errno))); + = new java::io::InterruptedIOException + (_Jv_WinStrError (dwErr)); iioe->bytesTransferred = 0; throw iioe; } // Some errors should not cause exceptions. - if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF) - throw new java::io::IOException (JvNewStringUTF (strerror (errno))); + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); break; } } @@ -500,24 +385,25 @@ java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len) jbyte *bytes = elements (b) + offset; int written = 0; - while (len > 0) { - int r = _Jv_write (fnum, bytes, len); + int r = ::send (fnum, (char*) bytes, len, 0); if (r == -1) { + DWORD dwErr = WSAGetLastError(); if (java::lang::Thread::interrupted()) { java::io::InterruptedIOException *iioe = new java::io::InterruptedIOException - (JvNewStringLatin1 (strerror (errno))); + (_Jv_WinStrError (dwErr)); iioe->bytesTransferred = written; throw iioe; } // Some errors should not cause exceptions. - if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF) - throw new java::io::IOException (JvNewStringUTF (strerror (errno))); + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); break; } @@ -534,43 +420,37 @@ java::net::PlainSocketImpl::sendUrgentData (jint) "PlainSocketImpl: sending of urgent data not supported by this socket")); } -// Read a single byte from the socket. -jint -java::net::PlainSocketImpl::read(void) +// read() helper +static jint +doRead(int fnum, void* buf, int count, int timeout) { - jbyte b; - -// FIXME: implement timeout support for Win32 -#ifndef WIN32 - // Do timeouts via select. - if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE) - { - // Create the file descriptor set. - fd_set read_fds; - FD_ZERO (&read_fds); - FD_SET (fnum,&read_fds); - // Create the timeout struct based on our internal timeout value. - struct timeval timeout_value; - timeout_value.tv_sec = timeout / 1000; - timeout_value.tv_usec = (timeout % 1000) * 1000; - // Select on the fds. - int sel_retval = - _Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value); - // If select returns 0 we've waited without getting data... - // that means we've timed out. - if (sel_retval == 0) - throw new java::io::InterruptedIOException - (JvNewStringUTF ("read timed out") ); - // If select returns ok we know we either got signalled or read some data... - // either way we need to try to read. - } -#endif /* WIN32 */ - - int r = _Jv_read (fnum, &b, 1); + int r = 0; + DWORD dwErrorCode = 0; + // we are forced to declare this here because + // a call to Thread::interrupted() blanks out + // WSAGetLastError(). + + // FIXME: we unconditionally set SO_RCVTIMEO here + // because we can't detect whether someone has + // gone from a non-zero to zero timeout. What we'd + // really need is a member state variable in addition + // to timeout + int nRet= ::setsockopt(fnum, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) + { + dwErrorCode = WSAGetLastError (); + goto error; + } + + r = ::recv (fnum, (char*) buf, count, 0); if (r == 0) return -1; + dwErrorCode = WSAGetLastError (); + // save WSAGetLastError() before calling Thread.interrupted() + if (java::lang::Thread::interrupted()) { java::io::InterruptedIOException *iioe = @@ -581,14 +461,28 @@ java::net::PlainSocketImpl::read(void) } else if (r == -1) { +error: // Some errors cause us to return end of stream... - if (errno == ENOTCONN) + if (dwErrorCode == WSAENOTCONN) return -1; // Other errors need to be signalled. - throw new java::io::IOException (JvNewStringUTF (strerror (errno))); + if (dwErrorCode == WSAETIMEDOUT) + throw new java::net::SocketTimeoutException + (JvNewStringUTF ("read timed out") ); + else + _Jv_ThrowIOException (dwErrorCode); } + + return r; +} +// Read a single byte from the socket. +jint +java::net::PlainSocketImpl::read(void) +{ + jbyte b; + doRead(fnum, &b, 1, timeout); return b & 0xFF; } @@ -606,120 +500,20 @@ java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count) jbyte *bytes = elements (buffer) + offset; -// FIXME: implement timeout support for Win32 -#ifndef WIN32 - // Do timeouts via select. - if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE) - { - // Create the file descriptor set. - fd_set read_fds; - FD_ZERO (&read_fds); - FD_SET (fnum, &read_fds); - // Create the timeout struct based on our internal timeout value. - struct timeval timeout_value; - timeout_value.tv_sec = timeout / 1000; - timeout_value.tv_usec =(timeout % 1000) * 1000; - // Select on the fds. - int sel_retval = - _Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value); - // We're only interested in the 0 return. - // error returns still require us to try to read - // the socket to see what happened. - if (sel_retval == 0) - { - java::io::InterruptedIOException *iioe = - new java::io::InterruptedIOException - (JvNewStringUTF ("read interrupted")); - iioe->bytesTransferred = 0; - throw iioe; - } - } -#endif - // Read the socket. - int r = ::recv (fnum, (char *) bytes, count, 0); - - if (r == 0) - return -1; - - if (java::lang::Thread::interrupted()) - { - java::io::InterruptedIOException *iioe = - new java::io::InterruptedIOException - (JvNewStringUTF ("read interrupted")); - iioe->bytesTransferred = r == -1 ? 0 : r; - throw iioe; - } - else if (r == -1) - { - // Some errors cause us to return end of stream... - if (errno == ENOTCONN) - return -1; - - // Other errors need to be signalled. - throw new java::io::IOException (JvNewStringUTF (strerror (errno))); - } - - return r; + return doRead(fnum, bytes, count, timeout); } // How many bytes are available? jint java::net::PlainSocketImpl::available(void) { -#if defined(FIONREAD) || defined(HAVE_SELECT) - long num = 0; - int r = 0; - bool num_set = false; - -#if defined(FIONREAD) - r = ::ioctl (fnum, FIONREAD, &num); - - if (r == -1 && errno == ENOTTY) - { - // If the ioctl doesn't work, we don't care. - r = 0; - num = 0; - } - else - num_set = true; -#elif defined(HAVE_SELECT) - if (fnum < 0) - { - errno = EBADF; - r = -1; - } -#endif + unsigned long num = 0; - if (r == -1) - { - posix_error: - throw new java::io::IOException(JvNewStringUTF(strerror(errno))); - } - - // If we didn't get anything we can use select. - -#if defined(HAVE_SELECT) - if (! num_set) - if (! num_set && fnum >= 0 && fnum < FD_SETSIZE) - { - fd_set rd; - FD_ZERO (&rd); - FD_SET (fnum, &rd); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - r = _Jv_select (fnum + 1, &rd, NULL, NULL, &tv); - if(r == -1) - goto posix_error; - num = r == 0 ? 0 : 1; - } -#endif /* HAVE_SELECT */ + if (::ioctlsocket (fnum, FIONREAD, &num) == SOCKET_ERROR) + _Jv_ThrowIOException (); return (jint) num; -#else - throw new java::io::IOException (JvNewStringUTF ("unimplemented")); -#endif } void @@ -733,11 +527,11 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$)) { - java::lang::Boolean *boolobj = + java::lang::Boolean *boolobj = static_cast<java::lang::Boolean *> (value); if (boolobj->booleanValue()) - val = 1; - else + val = 1; + else { if (optID == _Jv_SO_LINGER_) val = -1; @@ -747,8 +541,8 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) } else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$)) { - java::lang::Integer *intobj = - static_cast<java::lang::Integer *> (value); + java::lang::Integer *intobj = + static_cast<java::lang::Integer *> (value); val = (int) intobj->intValue(); } else @@ -757,62 +551,48 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) JvNewStringLatin1 ("`value' must be Boolean or Integer")); } - switch (optID) + switch (optID) { case _Jv_TCP_NODELAY_ : -#ifdef TCP_NODELAY if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val, - val_len) != 0) + val_len) == SOCKET_ERROR) goto error; -#else - throw new java::lang::InternalError - (JvNewStringUTF ("TCP_NODELAY not supported")); -#endif /* TCP_NODELAY */ return; case _Jv_SO_KEEPALIVE_ : if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, - val_len) != 0) + val_len) == SOCKET_ERROR) goto error; break; - + case _Jv_SO_BROADCAST_ : throw new java::net::SocketException (JvNewStringUTF ("SO_BROADCAST not valid for TCP")); break; - + case _Jv_SO_OOBINLINE_ : if (::setsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val, - val_len) != 0) + val_len) == SOCKET_ERROR) goto error; break; case _Jv_SO_LINGER_ : -#ifdef SO_LINGER struct linger l_val; l_val.l_onoff = (val != -1); l_val.l_linger = val; if (::setsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val, - sizeof(l_val)) != 0) - goto error; -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_LINGER not supported")); -#endif /* SO_LINGER */ + sizeof(l_val)) == SOCKET_ERROR) + goto error; return; case _Jv_SO_SNDBUF_ : case _Jv_SO_RCVBUF_ : -#if defined(SO_SNDBUF) && defined(SO_RCVBUF) int opt; optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; - if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0) - goto error; -#else - throw new java::lang::InternalError ( - JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")); -#endif + if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, + val_len) == SOCKET_ERROR) + goto error; return; case _Jv_SO_BINDADDR_ : @@ -824,23 +604,23 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")); return; - + case _Jv_IP_MULTICAST_IF2_ : throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP")); break; - + case _Jv_IP_MULTICAST_LOOP_ : throw new java::net::SocketException ( JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP")); break; - + case _Jv_IP_TOS_ : if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val, - val_len) != 0) - goto error; + val_len) == SOCKET_ERROR) + goto error; break; - + case _Jv_SO_REUSEADDR_ : throw new java::net::SocketException ( JvNewStringUTF ("SO_REUSEADDR: not valid for TCP")); @@ -851,12 +631,11 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) return; default : - errno = ENOPROTOOPT; + WSASetLastError (WSAENOPROTOOPT); } - error: - char* strerr = strerror (errno); - throw new java::net::SocketException (JvNewStringUTF (strerr)); +error: + _Jv_ThrowSocketException (); } java::lang::Object * @@ -871,75 +650,62 @@ java::net::PlainSocketImpl::getOption (jint optID) switch (optID) { -#ifdef TCP_NODELAY case _Jv_TCP_NODELAY_ : if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val, - &val_len) != 0) + &val_len) == SOCKET_ERROR) goto error; else return new java::lang::Boolean (val != 0); -#else - throw new java::lang::InternalError - (JvNewStringUTF ("TCP_NODELAY not supported")); -#endif break; - + case _Jv_SO_LINGER_ : -#ifdef SO_LINGER if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val, - &l_val_len) != 0) - goto error; - + &l_val_len) == SOCKET_ERROR) + goto error; + if (l_val.l_onoff) return new java::lang::Integer (l_val.l_linger); else return new java::lang::Boolean ((jboolean)false); -#else - throw new java::lang::InternalError - (JvNewStringUTF ("SO_LINGER not supported")); -#endif - break; + break; case _Jv_SO_KEEPALIVE_ : if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, - &val_len) != 0) + &val_len) == SOCKET_ERROR) goto error; else return new java::lang::Boolean (val != 0); case _Jv_SO_BROADCAST_ : if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val, - &val_len) != 0) - goto error; + &val_len) == SOCKET_ERROR) + goto error; return new java::lang::Boolean ((jboolean)val); - + case _Jv_SO_OOBINLINE_ : if (::getsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val, - &val_len) != 0) - goto error; + &val_len) == SOCKET_ERROR) + goto error; return new java::lang::Boolean ((jboolean)val); - + case _Jv_SO_RCVBUF_ : case _Jv_SO_SNDBUF_ : -#if defined(SO_SNDBUF) && defined(SO_RCVBUF) int opt; optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; - if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0) - goto error; + if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; else return new java::lang::Integer (val); -#else - throw new java::lang::InternalError - (JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")); -#endif break; case _Jv_SO_BINDADDR_: - // cache the local address + // cache the local address if (localAddress == NULL) { jbyteArray laddr; - if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0) + if (::getsockname (fnum, (sockaddr*) &u, + &addrlen) == SOCKET_ERROR) goto error; if (u.address.sin_family == AF_INET) @@ -966,24 +732,24 @@ java::net::PlainSocketImpl::getOption (jint optID) throw new java::net::SocketException (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")); break; - + case _Jv_IP_MULTICAST_IF2_ : throw new java::net::SocketException (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP")); break; - + case _Jv_IP_MULTICAST_LOOP_ : throw new java::net::SocketException (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP")); break; - + case _Jv_IP_TOS_ : if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val, - &val_len) != 0) + &val_len) == SOCKET_ERROR) goto error; return new java::lang::Integer (val); break; - + case _Jv_SO_REUSEADDR_ : throw new java::net::SocketException (JvNewStringUTF ("SO_REUSEADDR: not valid for TCP")); @@ -994,26 +760,25 @@ java::net::PlainSocketImpl::getOption (jint optID) break; default : - errno = ENOPROTOOPT; + WSASetLastError (WSAENOPROTOOPT); } - error: - char* strerr = strerror (errno); - throw new java::net::SocketException (JvNewStringUTF (strerr)); +error: + _Jv_ThrowSocketException (); + return 0; + // we should never get here } void java::net::PlainSocketImpl::shutdownInput (void) { if (::shutdown (fnum, 0)) - throw new SocketException (JvNewStringUTF (strerror (errno))); + _Jv_ThrowSocketException (); } void java::net::PlainSocketImpl::shutdownOutput (void) { if (::shutdown (fnum, 1)) - throw new SocketException (JvNewStringUTF (strerror (errno))); + _Jv_ThrowSocketException (); } - -#endif /* DISABLE_JAVA_NET */ |