diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/gnu/java/net/natPlainSocketImplWin32.cc | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/gnu/java/net/natPlainSocketImplWin32.cc')
-rw-r--r-- | libjava/gnu/java/net/natPlainSocketImplWin32.cc | 796 |
1 files changed, 796 insertions, 0 deletions
diff --git a/libjava/gnu/java/net/natPlainSocketImplWin32.cc b/libjava/gnu/java/net/natPlainSocketImplWin32.cc new file mode 100644 index 000000000..9377998f5 --- /dev/null +++ b/libjava/gnu/java/net/natPlainSocketImplWin32.cc @@ -0,0 +1,796 @@ +/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> +#include <platform.h> + +#undef STRICT +#undef MAX_PRIORITY +#undef MIN_PRIORITY + +#include <gnu/java/net/PlainSocketImpl.h> +#include <gnu/java/net/PlainSocketImpl$SocketInputStream.h> +#include <gnu/java/net/PlainSocketImpl$SocketOutputStream.h> +#include <java/io/IOException.h> +#include <java/net/BindException.h> +#include <java/net/ConnectException.h> +#include <java/net/InetAddress.h> +#include <java/net/InetSocketAddress.h> +#include <java/net/SocketException.h> +#include <java/net/SocketTimeoutException.h> +#include <java/lang/InternalError.h> +#include <java/lang/Object.h> +#include <java/lang/Boolean.h> +#include <java/lang/Class.h> +#include <java/lang/Integer.h> +#include <java/lang/Thread.h> +#include <java/lang/NullPointerException.h> +#include <java/lang/ArrayIndexOutOfBoundsException.h> +#include <java/lang/IllegalArgumentException.h> + +union SockAddr +{ + struct sockaddr_in address; +#ifdef HAVE_INET6 + struct sockaddr_in6 address6; +#endif +}; + +void +gnu::java::net::PlainSocketImpl::create (jboolean stream) +{ + SOCKET sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); + + if (sock == INVALID_SOCKET) + { + _Jv_ThrowIOException (); + } + + // Cast this to a HANDLE so we can make + // it non-inheritable via _Jv_platform_close_on_exec. + HANDLE hSocket = (HANDLE) sock; + _Jv_platform_close_on_exec (hSocket); + + // We use native_fd in place of fd here. From leaving fd null we avoid + // the double close problem in FileDescriptor.finalize. + native_fd = (jint) hSocket; +} + +void +gnu::java::net::PlainSocketImpl::bind (::java::net::InetAddress *host, jint lport) +{ + union SockAddr u; + struct sockaddr *ptr = (struct sockaddr *) &u.address; + jbyteArray haddress = host->addr; + jbyte *bytes = elements (haddress); + int len = haddress->length; + + if (len == 4) + { + u.address.sin_family = AF_INET; + + if (host != NULL) + memcpy (&u.address.sin_addr, bytes, len); + else + u.address.sin_addr.s_addr = htonl (INADDR_ANY); + + len = sizeof (struct sockaddr_in); + u.address.sin_port = htons (lport); + } +#ifdef HAVE_INET6 + else if (len == 16) + { + u.address6.sin6_family = AF_INET6; + memcpy (&u.address6.sin6_addr, bytes, len); + len = sizeof (struct sockaddr_in6); + u.address6.sin6_port = htons (lport); + } +#endif + else + throw new ::java::net::SocketException (JvNewStringUTF ("invalid length")); + + if (::bind (native_fd, ptr, len) != SOCKET_ERROR) + { + socklen_t addrlen = sizeof(u); + + if (lport != 0) + localport = lport; + else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != SOCKET_ERROR) + localport = ntohs (u.address.sin_port); + else + goto error; + + return; + } + +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 +gnu::java::net::PlainSocketImpl::connect (::java::net::SocketAddress *addr, + jint timeout) +{ + ::java::net::InetSocketAddress *tmp = (::java::net::InetSocketAddress*) addr; + ::java::net::InetAddress *host = tmp->getAddress(); + jint rport = tmp->getPort(); + + // Set the SocketImpl's address and port fields before we try to + // connect. Note that the fact that these are set doesn't imply + // that we're actually connected to anything. We need to record + // this data before we attempt the connect, since non-blocking + // SocketChannels will use this and almost certainly throw timeout + // exceptions. + address = host; + port = rport; + + 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; + memcpy (&u.address.sin_addr, bytes, len); + len = sizeof (struct sockaddr_in); + u.address.sin_port = htons (rport); + } +#ifdef HAVE_INET6 + else if (len == 16) + { + u.address6.sin6_family = AF_INET6; + memcpy (&u.address6.sin6_addr, bytes, len); + len = sizeof (struct sockaddr_in6); + u.address6.sin6_port = htons (rport); + } +#endif + else + throw new ::java::net::SocketException (JvNewStringUTF ("invalid length")); + + if (timeout > 0) + { + // FIXME: we're creating a fresh WSAEVENT for each connect(). + WSAEventWrapper aWSAEventWrapper(native_fd, FD_CONNECT); + WSAEVENT hEvent = aWSAEventWrapper.getEventHandle (); + + if (::connect (native_fd, 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 + + // Reset and ignore our thread's interrupted flag. + // It's not possible to interrupt these sort of + // operations on Win32 anyway. + ::java::lang::Thread::interrupted(); + + 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(native_fd, SOL_SOCKET, SO_ERROR, (char*) &nErrCode, + &nErrLen) == SOCKET_ERROR) + { + throwConnectException (); + } + + if (nErrCode != NO_ERROR) + { + throwConnectException (nErrCode); + } + } + } + else + { + if (::connect (native_fd, ptr, len) == SOCKET_ERROR) + throwConnectException(); + } + + // A bind may not have been done on this socket; if so, set localport now. + if (localport == 0) + { + if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != SOCKET_ERROR) + localport = ntohs (u.address.sin_port); + else + throwConnectException(); + } +} + +void +gnu::java::net::PlainSocketImpl::listen (jint backlog) +{ + if (::listen (native_fd, backlog) == SOCKET_ERROR) + { + _Jv_ThrowIOException (); + } +} + +void +gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s) +{ + union SockAddr u; + socklen_t addrlen = sizeof(u); + HANDLE hSocket = 0; + SOCKET new_socket = 0; + + if (timeout > 0) + { + // FIXME: we're creating a fresh WSAEVENT for each accept(). + // One possible alternative would be that native_fd really points + // to an extended structure consisting of the SOCKET, its + // associated WSAEVENT, etc. + WSAEventWrapper aWSAEventWrapper(native_fd, FD_ACCEPT); + WSAEVENT hEvent = aWSAEventWrapper.getEventHandle (); + + for (;;) + { + new_socket = ::accept (native_fd, (sockaddr*) &u, &addrlen); + + if (new_socket != 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; + } + + DWORD dwRet = + WSAWaitForMultipleEvents (1, &hEvent, true, timeout, false); + // use true, false instead of TRUE, FALSE because the + // MS constants got undefined + + // Reset and ignore our thread's interrupted flag. + ::java::lang::Thread::interrupted(); + + 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 (native_fd, (sockaddr*) &u, &addrlen); + } + + if (new_socket == INVALID_SOCKET) + goto error; + + // Cast this to a HANDLE so we can make + // it non-inheritable via _Jv_platform_close_on_exec. + hSocket = (HANDLE) new_socket; + _Jv_platform_close_on_exec (hSocket); + + jbyteArray raddr; + jint rport; + if (u.address.sin_family == AF_INET) + { + raddr = JvNewByteArray (4); + memcpy (elements (raddr), &u.address.sin_addr, 4); + rport = ntohs (u.address.sin_port); + } +#ifdef HAVE_INET6 + else if (u.address.sin_family == AF_INET6) + { + raddr = JvNewByteArray (16); + memcpy (elements (raddr), &u.address6.sin6_addr, 16); + rport = ntohs (u.address6.sin6_port); + } +#endif + else + throw new ::java::net::SocketException (JvNewStringUTF ("invalid family")); + + s->native_fd = (jint) hSocket; + s->localport = localport; + s->address = ::java::net::InetAddress::getByAddress (raddr); + s->port = rport; + return; + + error: + _Jv_ThrowIOException (); +} + +// Close(shutdown) the socket. +void +gnu::java::net::PlainSocketImpl::close() +{ + // Avoid races from asynchronous finalization. + JvSynchronize sync (this); + + // should we use shutdown here? how would that effect so_linger? + int res = ::closesocket (native_fd); + + if (res == -1) + { + // These three errors are not errors according to tests performed + // on the reference implementation. + DWORD dwErr = WSAGetLastError(); + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); + } + // Safe place to reset the file pointer. + native_fd = -1; + timeout = 0; +} + +// Write a byte to the socket. +void +gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jint b) +{ + jbyte d =(jbyte) b; + int r = 0; + + while (r != 1) + { + r = ::send (this$0->native_fd, (char*) &d, 1, 0); + if (r == -1) + { + DWORD dwErr = WSAGetLastError(); + + // Reset and ignore our thread's interrupted flag. + // It's not possible to interrupt these sort of + // operations on Win32 anyway. + ::java::lang::Thread::interrupted(); + + // Some errors should not cause exceptions. + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); + break; + } + } +} + +// Write some bytes to the socket. +void +gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jbyteArray b, + jint offset, jint len) +{ + if (! b) + throw new ::java::lang::NullPointerException; + if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b)) + throw new ::java::lang::ArrayIndexOutOfBoundsException; + + jbyte *bytes = elements (b) + offset; + int written = 0; + while (len > 0) + { + int r = ::send (this$0->native_fd, (char*) bytes, len, 0); + + if (r == -1) + { + DWORD dwErr = WSAGetLastError(); + + // Reset and ignore our thread's interrupted flag. + ::java::lang::Thread::interrupted(); + + // Some errors should not cause exceptions. + if (dwErr != WSAENOTCONN && dwErr != WSAECONNRESET + && dwErr != WSAENOTSOCK) + _Jv_ThrowIOException (); + break; + } + + written += r; + len -= r; + bytes += r; + } +} + +void +gnu::java::net::PlainSocketImpl::sendUrgentData (jint) +{ + throw new ::java::net::SocketException (JvNewStringLatin1 ( + "PlainSocketImpl: sending of urgent data not supported by this socket")); +} + +// read() helper +static jint +doRead(int native_fd, void* buf, int count, int timeout) +{ + 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(native_fd, SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (nRet != NO_ERROR) + { + dwErrorCode = WSAGetLastError (); + goto error; + } + + r = ::recv (native_fd, (char*) buf, count, 0); + + if (r == 0) + return -1; + + dwErrorCode = WSAGetLastError (); + // save WSAGetLastError() before calling Thread.interrupted() + + // Reset and ignore our thread's interrupted flag. + ::java::lang::Thread::interrupted(); + + if (r == -1) + { +error: + // Some errors cause us to return end of stream... + if (dwErrorCode == WSAENOTCONN) + return -1; + + // Other errors need to be signalled. + 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 +gnu::java::net::PlainSocketImpl$SocketInputStream::read(void) +{ + jbyte b; + doRead(this$0->native_fd, &b, 1, this$0->timeout); + return b & 0xFF; +} + +// Read count bytes into the buffer, starting at offset. +jint +gnu::java::net::PlainSocketImpl$SocketInputStream::read(jbyteArray buffer, + jint offset, jint count) +{ + // If zero bytes were requested, short circuit so that recv + // doesn't signal EOF. + if (count == 0) + return 0; + + if (! buffer) + throw new ::java::lang::NullPointerException; + + jsize bsize = JvGetArrayLength (buffer); + + if (offset < 0 || count < 0 || offset + count > bsize) + throw new ::java::lang::ArrayIndexOutOfBoundsException; + + jbyte *bytes = elements (buffer) + offset; + + // Read the socket. + return doRead(this$0->native_fd, bytes, count, this$0->timeout); +} + +// How many bytes are available? +jint +gnu::java::net::PlainSocketImpl::available(void) +{ + unsigned long num = 0; + + if (::ioctlsocket (native_fd, FIONREAD, &num) == SOCKET_ERROR) + _Jv_ThrowIOException (); + + return (jint) num; +} + +void +gnu::java::net::PlainSocketImpl::setOption (jint optID, ::java::lang::Object *value) +{ + int val; + socklen_t val_len = sizeof (val); + + if (native_fd < 0) + throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed")); + + if (_Jv_IsInstanceOf (value, &::java::lang::Boolean::class$)) + { + ::java::lang::Boolean *boolobj = + static_cast< ::java::lang::Boolean *> (value); + if (boolobj->booleanValue()) + val = 1; + else + { + if (optID == _Jv_SO_LINGER_) + val = -1; + else + val = 0; + } + } + else if (_Jv_IsInstanceOf (value, &::java::lang::Integer::class$)) + { + ::java::lang::Integer *intobj = + static_cast< ::java::lang::Integer *> (value); + val = (int) intobj->intValue(); + } + else + { + throw new ::java::lang::IllegalArgumentException ( + JvNewStringLatin1 ("`value' must be Boolean or Integer")); + } + + switch (optID) + { + case _Jv_TCP_NODELAY_ : + if (::setsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val, + val_len) == SOCKET_ERROR) + goto error; + return; + + case _Jv_SO_KEEPALIVE_ : + if (::setsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, + 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 (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val, + val_len) == SOCKET_ERROR) + goto error; + break; + + case _Jv_SO_LINGER_ : + struct linger l_val; + l_val.l_onoff = (val != -1); + l_val.l_linger = val; + + if (::setsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val, + sizeof(l_val)) == SOCKET_ERROR) + goto error; + return; + + case _Jv_SO_SNDBUF_ : + case _Jv_SO_RCVBUF_ : + int opt; + optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; + if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, + val_len) == SOCKET_ERROR) + goto error; + return; + + case _Jv_SO_BINDADDR_ : + throw new ::java::net::SocketException ( + JvNewStringUTF ("SO_BINDADDR: read only option")); + return; + + case _Jv_IP_MULTICAST_IF_ : + 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 (native_fd, SOL_SOCKET, IP_TOS, (char *) &val, + val_len) == SOCKET_ERROR) + goto error; + break; + + case _Jv_SO_REUSEADDR_ : + throw new ::java::net::SocketException ( + JvNewStringUTF ("SO_REUSEADDR: not valid for TCP")); + return; + + case _Jv_SO_TIMEOUT_ : + timeout = val; + return; + + default : + WSASetLastError (WSAENOPROTOOPT); + } + +error: + _Jv_ThrowSocketException (); +} + +::java::lang::Object * +gnu::java::net::PlainSocketImpl::getOption (jint optID) +{ + int val; + socklen_t val_len = sizeof(val); + union SockAddr u; + socklen_t addrlen = sizeof(u); + struct linger l_val; + socklen_t l_val_len = sizeof(l_val); + + switch (optID) + { + case _Jv_TCP_NODELAY_ : + if (::getsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; + else + return new ::java::lang::Boolean (val != 0); + break; + + case _Jv_SO_LINGER_ : + if (::getsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val, + &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); + break; + + case _Jv_SO_KEEPALIVE_ : + if (::getsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; + else + return new ::java::lang::Boolean (val != 0); + + case _Jv_SO_BROADCAST_ : + if (::getsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; + return new ::java::lang::Boolean ((jboolean)val); + + case _Jv_SO_OOBINLINE_ : + if (::getsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; + return new ::java::lang::Boolean ((jboolean)val); + + case _Jv_SO_RCVBUF_ : + case _Jv_SO_SNDBUF_ : + int opt; + optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF; + if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, + &val_len) == SOCKET_ERROR) + goto error; + else + return new ::java::lang::Integer (val); + break; + case _Jv_SO_BINDADDR_: + // cache the local address + if (localAddress == NULL) + { + jbyteArray laddr; + + if (::getsockname (native_fd, (sockaddr*) &u, + &addrlen) == SOCKET_ERROR) + 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); + } +#endif + else + throw new ::java::net::SocketException + (JvNewStringUTF ("invalid family")); + localAddress = ::java::net::InetAddress::getByAddress (laddr); + } + + return localAddress; + break; + case _Jv_IP_MULTICAST_IF_ : + 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 (native_fd, SOL_SOCKET, IP_TOS, (char *) &val, + &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")); + break; + + case _Jv_SO_TIMEOUT_ : + return new ::java::lang::Integer (timeout); + break; + + default : + WSASetLastError (WSAENOPROTOOPT); + } + +error: + _Jv_ThrowSocketException (); + return 0; + // we should never get here +} + +void +gnu::java::net::PlainSocketImpl::shutdownInput (void) +{ + if (::shutdown (native_fd, 0)) + _Jv_ThrowSocketException (); +} + +void +gnu::java::net::PlainSocketImpl::shutdownOutput (void) +{ + if (::shutdown (native_fd, 1)) + _Jv_ThrowSocketException (); +} |