From d291d8b244efc66333a228e5013a5afd80c87f6d Mon Sep 17 00:00:00 2001 From: membar Date: Fri, 29 Aug 2003 04:21:01 +0000 Subject: [PATCH] * 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 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 #include with 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 #include with 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 #include with 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 #include with 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() git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70904 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 117 ++++ libjava/include/win32.h | 108 ++-- libjava/java/io/natFileDescriptorWin32.cc | 141 ++-- libjava/java/io/natFileWin32.cc | 118 ++-- libjava/java/lang/natWin32Process.cc | 54 +- libjava/java/net/natInetAddressWin32.cc | 265 ++------ libjava/java/net/natNetworkInterfaceWin32.cc | 210 +++--- .../java/net/natPlainDatagramSocketImplWin32.cc | 536 ++++++---------- libjava/java/net/natPlainSocketImplWin32.cc | 707 +++++++-------------- libjava/win32.cc | 135 +++- 10 files changed, 978 insertions(+), 1413 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 62b0413..d0c28f8 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,122 @@ 2003-08-28 Mohan Embar + * 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 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 #include with + 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 #include with + 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 #include with + 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 #include with + 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() + +2003-08-28 Mohan Embar + * java/net/natInetAddressWin32.cc, java/net/natNetworkInterfaceWin32.cc, java/net/natPlainDatagramSocketImplWin32.cc, diff --git a/libjava/include/win32.h b/libjava/include/win32.h index 320273a..6da0eaf 100644 --- a/libjava/include/win32.h +++ b/libjava/include/win32.h @@ -11,11 +11,14 @@ details. */ #ifndef __JV_WIN32_H__ #define __JV_WIN32_H__ +#define WIN32_LEAN_AND_MEAN #include +#undef WIN32_LEAN_AND_MEAN #undef STRICT #include #include +#include #include #include @@ -40,21 +43,58 @@ details. */ // with the JNICALL definition in jni.h #define _Jv_platform_ffi_abi FFI_STDCALL -#ifndef DISABLE_JAVA_NET +/* Useful helper classes and methods. */ -// these errors cannot occur on Win32 -#define ENOTCONN 0 -#define ECONNRESET 0 +/* A C++ wrapper around a WSAEVENT which closes the event + in its destructor. If dwSelFlags is non-zero, we also + issue an WSAEventSelect on the socket descriptor with + the given flags; this is undone by a corresponding call + to WSAEventSelect(fd, 0, 0) in our destructor. */ +class WSAEventWrapper +{ +public: + WSAEventWrapper(int fd, DWORD dwSelFlags); + ~WSAEventWrapper(); + + WSAEVENT getEventHandle() + { + return m_hEvent; + } + +private: + WSAEVENT m_hEvent; + int m_fd; + DWORD m_dwSelFlags; +}; + +// Error string text. The int argument is compatible +// with both int WSAGetLastError() and DWORD GetLastError() +// I tried avoiding having to pass the error explicitly, but +// it didn't work this was invoked with say +// throw new SomeException(_Jv_WinStrError()). +extern jstring +_Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode); + +extern jstring +_Jv_WinStrError (int nErrorCode); -#ifndef ENOPROTOOPT -#define ENOPROTOOPT 109 -#endif +extern void +_Jv_ThrowIOException (DWORD dwErrorCode); -#endif // DISABLE_JAVA_NET +extern void +_Jv_ThrowIOException (); +extern void +_Jv_ThrowSocketException (DWORD dwErrorCode); + +extern void +_Jv_ThrowSocketException (); + +// Platform implementation extern void _Jv_platform_initialize (void); extern void _Jv_platform_initProperties (java::util::Properties*); extern jlong _Jv_platform_gettimeofday (); +extern int _Jv_select (int n, fd_set *, fd_set *, fd_set *, struct timeval *); inline void _Jv_platform_close_on_exec (jint) @@ -77,58 +117,6 @@ _Jv_platform_usleep (unsigned long usecs) } #endif /* JV_HASH_SYNCHRONIZATION */ -#ifndef DISABLE_JAVA_NET - -static inline int -_Jv_socket (int domain, int type, int protocol) -{ - return ::socket (domain, type, protocol); -} - -inline int -_Jv_connect (jint fd, sockaddr *ptr, int len) -{ - return ::connect (fd, ptr, len); -} - -inline int -_Jv_close (jint fd) -{ - return ::closesocket (fd); -} - -inline int -_Jv_bind (int fd, struct sockaddr *addr, int addrlen) -{ - return ::bind (fd, addr, addrlen); -} - -inline int -_Jv_accept (int fd, struct sockaddr *addr, socklen_t *addrlen) -{ - return ::accept (fd, addr, addrlen); -} - -inline int -_Jv_listen (int fd, int backlog) -{ - return ::listen (fd, backlog); -} - -inline int -_Jv_write(int s, void *buf, int len) -{ - return ::send (s, (char*) buf, len, 0); -} - -inline int -_Jv_read(int s, void *buf, int len) -{ - return ::recv (s, (char*) buf, len, 0); -} - -#endif /* DISABLE_JAVA_NET */ - /* Store up to SIZE return address of the current program state in ARRAY and return the exact number of values stored. */ extern int backtrace (void **__array, int __size); diff --git a/libjava/java/io/natFileDescriptorWin32.cc b/libjava/java/io/natFileDescriptorWin32.cc index 5066987..1891bf7 100644 --- a/libjava/java/io/natFileDescriptorWin32.cc +++ b/libjava/java/io/natFileDescriptorWin32.cc @@ -13,15 +13,13 @@ details. */ // need to change to use the windows asynchronous IO functions #include +#include #include #include -#include #undef STRICT -#include -#include #include #include #include @@ -33,6 +31,16 @@ details. */ #include #include +static bool testCanUseGetHandleInfo() +{ + /* Test to see whether GetHandleInformation can be used + for console input or screen buffers. This is better + a kludgy OS version check. */ + DWORD dwFlags; + return GetHandleInformation (GetStdHandle (STD_INPUT_HANDLE), + &dwFlags) != 0; +} + // FIXME: casting a FILE (pointer) to a jint will not work on Win64 -- // we should be using gnu.gcj.RawData's. @@ -44,41 +52,32 @@ java::io::FileDescriptor::init(void) err = new java::io::FileDescriptor((jint)(GetStdHandle (STD_ERROR_HANDLE))); } -static char * -winerr (void) -{ - static LPVOID last = NULL; - LPVOID old = NULL; - - if (last) - old = last; - - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &last, - 0, - NULL); - - if (old) - LocalFree (old); - - return (char *)last; -} - jboolean java::io::FileDescriptor::valid (void) { - BY_HANDLE_FILE_INFORMATION info; - return GetFileInformationByHandle ((HANDLE)fd, &info) != 0; + static bool bCanUseGetHandleInfo = testCanUseGetHandleInfo(); + if (bCanUseGetHandleInfo) + { + /* As with UNIX, a "file" descriptor can be one of + a gazillion possible underlying things like a pipe + or socket, so we can't get too fancy here. */ + DWORD dwFlags; + HANDLE h = (HANDLE) fd; + return GetHandleInformation (h, &dwFlags) != 0; + } + else + { + /* Can't use GetHandleInformation() for console handles on < WinNT 5. */ + return true; + } } void java::io::FileDescriptor::sync (void) { if (! FlushFileBuffers ((HANDLE)fd)) - throw new SyncFailedException (JvNewStringLatin1 (winerr ())); + { + DWORD dwErrorCode = GetLastError (); + throw new SyncFailedException (_Jv_WinStrError (dwErrorCode)); + } } jint @@ -87,10 +86,8 @@ java::io::FileDescriptor::open (jstring path, jint jflags) { HANDLE handle = NULL; DWORD access = 0; DWORD create = OPEN_EXISTING; - char buf[MAX_PATH] = ""; - - jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf); - buf[total] = '\0'; + + JV_TEMP_UTF_STRING(cpath, path) JvAssert((jflags & READ) || (jflags & WRITE)); @@ -98,9 +95,9 @@ java::io::FileDescriptor::open (jstring path, jint jflags) { { access = GENERIC_READ | GENERIC_WRITE; if (jflags & EXCL) - create = CREATE_NEW; // this will raise error if file exists. + create = CREATE_NEW; // this will raise error if file exists. else - create = OPEN_ALWAYS; // equivalent to O_CREAT + create = OPEN_ALWAYS; // equivalent to O_CREAT } else if (jflags & READ) { @@ -111,20 +108,19 @@ java::io::FileDescriptor::open (jstring path, jint jflags) { { access = GENERIC_WRITE; if (jflags & EXCL) - create = CREATE_NEW; + create = CREATE_NEW; else if (jflags & APPEND) - create = OPEN_ALWAYS; + create = OPEN_ALWAYS; else - create = CREATE_ALWAYS; + create = CREATE_ALWAYS; } - handle = CreateFile(buf, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create, 0, NULL); + handle = CreateFile(cpath, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create, 0, NULL); if (handle == INVALID_HANDLE_VALUE) { - char msg[MAX_PATH + 1000]; - sprintf (msg, "%s: %s", buf, winerr ()); - throw new FileNotFoundException (JvNewStringLatin1 (msg)); + DWORD dwErrorCode = GetLastError (); + throw new FileNotFoundException (_Jv_WinStrError (cpath, dwErrorCode)); } // For APPEND mode, move the file pointer to the end of the file. @@ -132,7 +128,10 @@ java::io::FileDescriptor::open (jstring path, jint jflags) { { DWORD low = SetFilePointer (handle, 0, NULL, FILE_END); if ((low == 0xffffffff) && (GetLastError () != NO_ERROR)) - throw new FileNotFoundException (JvNewStringLatin1 (winerr ())); + { + DWORD dwErrorCode = GetLastError (); + throw new FileNotFoundException (_Jv_WinStrError (cpath, dwErrorCode)); + } } return (jint)handle; } @@ -149,13 +148,13 @@ java::io::FileDescriptor::write (jint b) { InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted")); iioe->bytesTransferred = bytesWritten; - throw iioe; + throw iioe; } if (bytesWritten != 1) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); } else - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); // FIXME: loop until bytesWritten == 1 } @@ -175,11 +174,11 @@ java::io::FileDescriptor::write(jbyteArray b, jint offset, jint len) { InterruptedIOException *iioe = new InterruptedIOException (JvNewStringLatin1 ("write interrupted")); iioe->bytesTransferred = bytesWritten; - throw iioe; + throw iioe; } } else - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); // FIXME: loop until bytesWritten == len } @@ -189,7 +188,7 @@ java::io::FileDescriptor::close (void) HANDLE save = (HANDLE)fd; fd = (jint)INVALID_HANDLE_VALUE; if (! CloseHandle (save)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); } void @@ -201,46 +200,46 @@ java::io::FileDescriptor::setLength(jlong pos) // Get the original file pointer. if (SetFilePointer((HANDLE) fd, (LONG) 0, &liOrigFilePointer, - FILE_CURRENT) != (BOOL) 0 + FILE_CURRENT) != (BOOL) 0 && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); // Get the length of the file. if (SetFilePointer((HANDLE) fd, (LONG) 0, &liEndFilePointer, - FILE_END) != (BOOL) 0 + FILE_END) != (BOOL) 0 && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); if ((jlong)liEndFilePointer == pos) { // Restore the file pointer. if (liOrigFilePointer != liEndFilePointer) - { - if (SetFilePointer((HANDLE) fd, liOrigFilePointer, &liNewFilePointer, - FILE_BEGIN) != (BOOL) 0 - && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); - } + { + if (SetFilePointer((HANDLE) fd, liOrigFilePointer, &liNewFilePointer, + FILE_BEGIN) != (BOOL) 0 + && (GetLastError() != NO_ERROR)) + _Jv_ThrowIOException (); + } return; } // Seek to the new end of file. if (SetFilePointer((HANDLE) fd, (LONG) pos, &liNewFilePointer, - FILE_BEGIN) != (BOOL) 0 + FILE_BEGIN) != (BOOL) 0 && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); // Truncate the file at this point. if (SetEndOfFile((HANDLE) fd) != (BOOL) 0 && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); if (liOrigFilePointer < liNewFilePointer) { // Restore the file pointer. if (SetFilePointer((HANDLE) fd, liOrigFilePointer, &liNewFilePointer, - FILE_BEGIN) != (BOOL) 0 - && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + FILE_BEGIN) != (BOOL) 0 + && (GetLastError() != NO_ERROR)) + _Jv_ThrowIOException (); } } @@ -262,7 +261,7 @@ java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc) LONG high = pos >> 32; DWORD low = SetFilePointer ((HANDLE)fd, (DWORD)(0xffffffff & pos), &high, whence == SET ? FILE_BEGIN : FILE_CURRENT); if ((low == 0xffffffff) && (GetLastError () != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); return low; } @@ -272,7 +271,7 @@ java::io::FileDescriptor::getFilePointer(void) LONG high = 0; DWORD low = SetFilePointer ((HANDLE)fd, 0, &high, FILE_CURRENT); if ((low == 0xffffffff) && (GetLastError() != NO_ERROR)) - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); return (((jlong)high) << 32L) | (jlong)low; } @@ -298,7 +297,7 @@ java::io::FileDescriptor::read(void) if (GetLastError () == ERROR_BROKEN_PIPE) return -1; else - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); } if (! read) @@ -329,7 +328,7 @@ java::io::FileDescriptor::read(jbyteArray buffer, jint offset, jint count) if (GetLastError () == ERROR_BROKEN_PIPE) return -1; else - throw new IOException (JvNewStringLatin1 (winerr ())); + _Jv_ThrowIOException (); } if (read == 0) return -1; diff --git a/libjava/java/io/natFileWin32.cc b/libjava/java/io/natFileWin32.cc index 1e06832..cee6b00 100644 --- a/libjava/java/io/natFileWin32.cc +++ b/libjava/java/io/natFileWin32.cc @@ -9,15 +9,13 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ #include +#include #include #include -#include #undef STRICT -#include -#include #include #include #include @@ -42,12 +40,9 @@ details. */ jboolean java::io::File::_access (jint query) { - jstring canon = getCanonicalPath(); - if (! canon) + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) return false; - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf); - buf[total] = '\0'; JvAssert (query == READ || query == WRITE || query == EXISTS); @@ -55,7 +50,7 @@ java::io::File::_access (jint query) // If the file exists but cannot be read because of the secuirty attributes // on an NTFS disk this wont work (it reports it can be read but cant) // Could we use something from the security API? - DWORD attributes = GetFileAttributes (buf); + DWORD attributes = GetFileAttributes (canon); if ((query == EXISTS) || (query == READ)) return (attributes == 0xffffffff) ? false : true; else @@ -65,16 +60,13 @@ java::io::File::_access (jint query) jboolean java::io::File::_stat (jint query) { - jstring canon = getCanonicalPath(); - if (! canon) + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) return false; - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf); - buf[total] = '\0'; JvAssert (query == DIRECTORY || query == ISFILE); - DWORD attributes = GetFileAttributes (buf); + DWORD attributes = GetFileAttributes (canon); if (attributes == 0xffffffff) return false; @@ -87,18 +79,15 @@ java::io::File::_stat (jint query) jlong java::io::File::attr (jint query) { - jstring canon = getCanonicalPath(); - if (! canon) + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) return false; - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length(), buf); - buf[total] = '\0'; JvAssert (query == MODIFIED || query == LENGTH); WIN32_FIND_DATA info; HANDLE sHandle; - if ( ( sHandle = FindFirstFile( buf, &info)) == INVALID_HANDLE_VALUE) + if ( ( sHandle = FindFirstFile( canon, &info)) == INVALID_HANDLE_VALUE) return 0; FindClose( sHandle); @@ -119,13 +108,11 @@ java::io::File::attr (jint query) jstring java::io::File::getCanonicalPath (void) { - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); - jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); - buf[total] = '\0'; + JV_TEMP_UTF_STRING (cpath, path); LPTSTR unused; char buf2[MAX_PATH]; - if(!GetFullPathName(buf, MAX_PATH, buf2, &unused)) + if(!GetFullPathName(cpath, MAX_PATH, buf2, &unused)) throw new IOException (JvNewStringLatin1 ("GetFullPathName failed")); // FIXME: what encoding to assume for file names? This affects many @@ -152,7 +139,7 @@ java::io::File::isAbsolute (void) && (path->charAt(0) < 'A' || path->charAt(0) > 'Z')) return false; return (path->charAt(1) == ':' - && (path->charAt(2) == '/' || path->charAt(2) == '\\')); + && (path->charAt(2) == '/' || path->charAt(2) == '\\')); } void java::io::File::init_native () @@ -163,8 +150,8 @@ void java::io::File::init_native () jobjectArray java::io::File::performList (java::io::FilenameFilter *filter, - java::io::FileFilter *fileFilter, - java::lang::Class *clazz) + java::io::FileFilter *fileFilter, + java::lang::Class *clazz) { jstring canon = getCanonicalPath(); if (! canon) @@ -190,16 +177,16 @@ java::io::File::performList (java::io::FilenameFilter *filter, jstring name = JvNewStringUTF (data.cFileName); if (filter && !filter->accept(this, name)) - continue; + continue; if (clazz == &java::io::File::class$) - { + { java::io::File *file = new java::io::File (this, name); if (fileFilter && !fileFilter->accept(file)) - continue; - vec->addElement (file); - } - else - vec->addElement (name); + continue; + vec->addElement (file); + } + else + vec->addElement (name); } } while (FindNextFile (handle, &data)); @@ -217,53 +204,42 @@ java::io::File::performList (java::io::FilenameFilter *filter, jboolean java::io::File::performMkdir (void) { - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); - jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf); - buf[total] = '\0'; - - return (CreateDirectory(buf, NULL)) ? true : false; + JV_TEMP_UTF_STRING (cpath, path); + return (CreateDirectory(cpath, NULL)) ? true : false; } jboolean java::io::File::performRenameTo (File *dest) { - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); - jsize total = JvGetStringUTFRegion(path, 0, path->length(), buf); - buf[total] = '\0'; - char *buf2 = (char *) __builtin_alloca (JvGetStringUTFLength (dest->path) - + 1); - total = JvGetStringUTFRegion(dest->path, 0, dest->path->length(), buf2); - buf2[total] = '\0'; - - return (MoveFile(buf, buf2)) ? true : false; + JV_TEMP_UTF_STRING (pathFrom, path); + JV_TEMP_UTF_STRING (pathTo, dest->path); + return (MoveFile(pathFrom, pathTo)) ? true : false; } jboolean java::io::File::performDelete () { - jstring canon = getCanonicalPath(); - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion(canon, 0, canon->length(), buf); - buf[total] = '\0'; + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) + return false; - DWORD attributes = GetFileAttributes (buf); + DWORD attributes = GetFileAttributes (canon); if (attributes == 0xffffffff) return false; if (attributes & FILE_ATTRIBUTE_DIRECTORY) - return (RemoveDirectory (buf)) ? true : false; + return (RemoveDirectory (canon)) ? true : false; else - return (DeleteFile (buf)) ? true : false; + return (DeleteFile (canon)) ? true : false; } jboolean java::io::File::performCreate (void) { - jstring canon = getCanonicalPath (); - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf); - buf[total] = '\0'; + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) + return false; - HANDLE h = CreateFile (buf, 0, 0, NULL, CREATE_NEW, + HANDLE h = CreateFile (canon, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { @@ -281,15 +257,14 @@ jboolean java::io::File::performCreate (void) jboolean java::io::File::performSetReadOnly () { - jstring canon = getCanonicalPath (); - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf); - buf[total] = '\0'; + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) + return false; - DWORD attrs = GetFileAttributes (buf); + DWORD attrs = GetFileAttributes (canon); if (attrs != INVALID_FILE_ATTRIBUTES) { - if (SetFileAttributes (buf, attrs | FILE_ATTRIBUTE_READONLY) != 0) + if (SetFileAttributes (canon, attrs | FILE_ATTRIBUTE_READONLY) != 0) return true; else return false; @@ -300,10 +275,9 @@ jboolean java::io::File::performSetReadOnly () jboolean java::io::File::performSetLastModified (jlong time) { - jstring canon = getCanonicalPath (); - char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (canon) + 1); - jsize total = JvGetStringUTFRegion (canon, 0, canon->length (), buf); - buf[total] = '\0'; + JV_TEMP_UTF_STRING (canon, getCanonicalPath()); + if (!canon) + return false; FILETIME modTime; long long mTime100ns = ((long long) time /* Ha! */ @@ -313,7 +287,7 @@ jboolean java::io::File::performSetLastModified (jlong time) modTime.dwHighDateTime = (DWORD) (mTime100ns >> 32); jboolean retVal = false; - HANDLE h = CreateFile (buf, FILE_WRITE_ATTRIBUTES, + HANDLE h = CreateFile (canon, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); diff --git a/libjava/java/lang/natWin32Process.cc b/libjava/java/lang/natWin32Process.cc index 710753e..86fd5b3 100644 --- a/libjava/java/lang/natWin32Process.cc +++ b/libjava/java/lang/natWin32Process.cc @@ -9,18 +9,11 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ #include - -#include - -#define WIN32_LEAN_AND_MEAN -#include +#include // Conflicts with the definition in "java/lang/reflect/Modifier.h" #undef STRICT -#include -#include - #include #include #include @@ -111,16 +104,6 @@ java::lang::ConcreteProcess::waitFor (void) return exitCode; } -static char * -new_string (jstring string) -{ - jsize s = _Jv_GetStringUTFLength (string); - char *buf = (char *) _Jv_Malloc (s + 1); - _Jv_GetStringUTFRegion (string, 0, s, buf); - buf[s] = '\0'; - return buf; -} - void java::lang::ConcreteProcess::startProcess (jstringArray progarray, jstringArray envp, @@ -177,9 +160,7 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, } // Get the working directory path, if specified. - char *wdir = NULL; - if (dir != NULL) - wdir = new_string (dir->getPath ()); + JV_TEMP_UTF_STRING (wdir, dir ? dir->getPath () : 0); errorStream = NULL; inputStream = NULL; @@ -204,29 +185,25 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, sAttrs.lpSecurityDescriptor = NULL; - char tmpBuff[64]; if (CreatePipe (&cldStdInRd, &cldStdInWr, &sAttrs, 0) == 0) { - sprintf (tmpBuff, - "Error creating stdin pipe (Win32 Error Code: %lu)", - GetLastError ()); - throw new IOException (JvNewStringLatin1 (tmpBuff)); + DWORD dwErrorCode = GetLastError (); + throw new IOException (_Jv_WinStrError ("Error creating stdin pipe", + dwErrorCode)); } if (CreatePipe (&cldStdOutRd, &cldStdOutWr, &sAttrs, 0) == 0) { - sprintf (tmpBuff, - "Error creating stdout pipe (Win32 Error Code: %lu)", - GetLastError ()); - throw new IOException (JvNewStringLatin1 (tmpBuff)); + DWORD dwErrorCode = GetLastError (); + throw new IOException (_Jv_WinStrError ("Error creating stdout pipe", + dwErrorCode)); } if (CreatePipe (&cldStdErrRd, &cldStdErrWr, &sAttrs, 0) == 0) { - sprintf (tmpBuff, - "Error creating stderr pipe (Win32 Error Code: %lu)", - GetLastError ()); - throw new IOException (JvNewStringLatin1 (tmpBuff)); + DWORD dwErrorCode = GetLastError (); + throw new IOException (_Jv_WinStrError ("Error creating stderr pipe", + dwErrorCode)); } outputStream = new FileOutputStream @@ -263,10 +240,9 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, &si, &pi) == 0) { - sprintf (tmpBuff, - "Error creating child process (Win32 Error Code: %lu)", - GetLastError ()); - throw new IOException (JvNewStringLatin1 (tmpBuff)); + DWORD dwErrorCode = GetLastError (); + throw new IOException ( + _Jv_WinStrError ("Error creating child process", dwErrorCode)); } procHandle = (jint ) pi.hProcess; @@ -279,8 +255,6 @@ java::lang::ConcreteProcess::startProcess (jstringArray progarray, _Jv_Free (cmdLine); if (env != NULL) _Jv_Free (env); - if (wdir != NULL) - _Jv_Free (wdir); } catch (java::lang::Throwable *thrown) { 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 +#include -#ifdef WIN32 - -#include -#include #undef STRICT -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif /* MAXHOSTNAMELEN */ - -#else /* WIN32 */ - -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#include -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif - -#endif /* WIN32 */ - -#include -#include #include #include #include -#if defined(HAVE_UNAME) && ! defined(HAVE_GETHOSTNAME) -#include -#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::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::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 *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 #include -#ifdef WIN32 - -#include -#include #undef STRICT -#else /* WIN32 */ - -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include - -#include -#include -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#define BSD_COMP /* Get FIONREAD on Solaris2. */ -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif - -#endif /* WIN32 */ - -#include -#include #include #include #include #include -#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 #include - -#ifdef WIN32 - -#include #include -#else /* WIN32 */ - -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_ARPA_INET_H -#include -#endif -#include -#include - -#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 #endif -#include #include #include #include @@ -42,116 +24,12 @@ details. */ #include #include #include +#include #include #include #include #include -#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 (value); val = boolobj->booleanValue() ? 1 : 0; } else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$)) { - java::lang::Integer *intobj = - static_cast (value); + java::lang::Integer *intobj = + static_cast (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 #include -#ifndef DISABLE_JAVA_NET - -#ifdef WIN32 - -#include -#include -#include -#include #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 -#endif - -// Pick up FIONREAD on Solaris 2.5. -#ifdef HAVE_SYS_FILIO_H -#include -#endif - -#include -#include -#include -#include -#endif /* WIN32 */ -#endif /* DISABLE_JAVA_NET */ - -#if HAVE_BSTRING_H -// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 -#include -#endif - - -#include -#include #include #include #include @@ -83,122 +32,6 @@ read(int s, void *buf, int len) #include #include -#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 (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 (value); + java::lang::Integer *intobj = + static_cast (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 */ diff --git a/libjava/win32.cc b/libjava/win32.cc index 9597dc8..abe768a 100644 --- a/libjava/win32.cc +++ b/libjava/win32.cc @@ -10,11 +10,13 @@ details. */ #include #include -#include #include #include #include +#include +#include +#include #include static LONG CALLBACK @@ -37,6 +39,102 @@ const char *_Jv_ThisExecutable (void) return exec_name; } +// Helper classes and methods implementation + +// class WSAEventWrapper +WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags): + m_hEvent(0), + m_fd(fd), + m_dwSelFlags(dwSelFlags) +{ + m_hEvent = WSACreateEvent (); + if (dwSelFlags) + WSAEventSelect(fd, m_hEvent, dwSelFlags); +} + +WSAEventWrapper::~WSAEventWrapper () +{ + if (m_dwSelFlags) + { + WSAEventSelect(m_fd, m_hEvent, 0); + if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT)) + { + // Set the socket back to non-blocking mode. + // Ignore any error since we're in a destructor. + unsigned long lSockOpt = 0L; + // blocking mode + ::ioctlsocket (m_fd, FIONBIO, &lSockOpt); + } + } + WSACloseEvent (m_hEvent); +} + +// Error string text. +jstring +_Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode) +{ + LPTSTR lpMsgBuf = 0; + + DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + + FormatMessage (dwFlags, + NULL, + (DWORD) nErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + jstring ret; + if (lpszPrologue) + { + LPTSTR lpszTemp = + (LPTSTR) _Jv_Malloc (strlen (lpszPrologue) + + strlen (lpMsgBuf) + 3); + strcpy (lpszTemp, lpszPrologue); + strcat (lpszTemp, ": "); + strcat (lpszTemp, lpMsgBuf); + ret = JvNewStringLatin1 (lpszTemp); + } + else + { + ret = JvNewStringLatin1 (lpMsgBuf); + } + + LocalFree(lpMsgBuf); + return ret; +} + +jstring +_Jv_WinStrError (int nErrorCode) +{ + return _Jv_WinStrError (0, nErrorCode); +} + +void _Jv_ThrowIOException (DWORD dwErrorCode) +{ + throw new java::io::IOException (_Jv_WinStrError (dwErrorCode)); +} + +void _Jv_ThrowIOException() +{ + DWORD dwErrorCode = WSAGetLastError (); + _Jv_ThrowIOException (dwErrorCode); +} + +void _Jv_ThrowSocketException (DWORD dwErrorCode) +{ + throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode)); +} + +void _Jv_ThrowSocketException() +{ + DWORD dwErrorCode = WSAGetLastError (); + _Jv_ThrowSocketException (dwErrorCode); +} + // Platform-specific VM initialization. void _Jv_platform_initialize (void) @@ -45,11 +143,11 @@ _Jv_platform_initialize (void) WSADATA data; if (WSAStartup (MAKEWORD (1, 1), &data)) MessageBox (NULL, "Error initialising winsock library.", "Error", - MB_OK | MB_ICONEXCLAMATION); - + MB_OK | MB_ICONEXCLAMATION); + // Install exception handler SetUnhandledExceptionFilter (win32_exception_handler); - + // Initialize our executable name GetModuleFileName(NULL, exec_name, sizeof(exec_name)); } @@ -96,14 +194,14 @@ _Jv_platform_initProperties (java::util::Properties* newprops) if (buffer != NULL) { if (GetCurrentDirectory (buflen, buffer)) - SET ("user.dir", buffer); + SET ("user.dir", buffer); if (GetTempPath (buflen, buffer)) - SET ("java.io.tmpdir", buffer); + SET ("java.io.tmpdir", buffer); _Jv_Free (buffer); } - + // Use GetUserName to set 'user.name'. buflen = 257; // UNLEN + 1 buffer = (char *) _Jv_MallocUnchecked (buflen); @@ -114,8 +212,8 @@ _Jv_platform_initProperties (java::util::Properties* newprops) _Jv_Free (buffer); } - // According to the api documentation for 'GetWindowsDirectory()', the - // environmental variable HOMEPATH always specifies the user's home + // According to the api documentation for 'GetWindowsDirectory()', the + // environmental variable HOMEPATH always specifies the user's home // directory or a default directory. On the 3 windows machines I checked // only 1 had it set. If it's not set, JDK1.3.1 seems to set it to // the windows directory, so we'll do the same. @@ -130,7 +228,7 @@ _Jv_platform_initProperties (java::util::Properties* newprops) if (winHome != NULL) { if (GetWindowsDirectory (winHome, MAX_PATH)) - SET ("user.home", winHome); + SET ("user.home", winHome); _Jv_Free (winHome); } } @@ -148,7 +246,7 @@ _Jv_platform_initProperties (java::util::Properties* newprops) if (buffer != NULL) { sprintf (buffer, "%d.%d", (int) osvi.dwMajorVersion, - (int) osvi.dwMinorVersion); + (int) osvi.dwMinorVersion); SET ("os.version", buffer); _Jv_Free (buffer); } @@ -163,7 +261,7 @@ _Jv_platform_initProperties (java::util::Properties* newprops) else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) SET ("os.name", "Windows Me"); else - SET ("os.name", "Windows ??"); + SET ("os.name", "Windows ??"); break; case VER_PLATFORM_WIN32_NT: @@ -231,3 +329,16 @@ backtrace (void **__array, int __size) } return i; } + +int +_Jv_select (int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) +{ + int r = ::select (n, readfds, writefds, exceptfds, timeout); + if (r == SOCKET_ERROR) + { + DWORD dwErrorCode = WSAGetLastError (); + throw new java::io::IOException (_Jv_WinStrError (dwErrorCode)); + } + return r; +} -- 2.7.4