From f2ed9e9656a375cf80b11dfb3a264a7551654ecd Mon Sep 17 00:00:00 2001 From: Warren Levy Date: Wed, 26 May 1999 17:00:06 +0000 Subject: [multiple changes] 1999-05-26 Bryce McKinlay * java/net/DatagramSocket.java (getSoTimeout): Verify class type. * java/net/DatagramSocketImpl.java (getOption): Made abstract. (setOption): Made abstract. * java/net/PlainDatagramSocketImpl.java: Mirror SocketOptions fields to avoid cpp conflicts in native code. * java/net/PlainSocketImpl.java: Mirror SocketOptions fields to avoid cpp conflicts in native code. * java/net/ServerSocket.java (toString): Prepended "ServerSocket". * java/net/Socket.java (getLocalAddress): Implemented. (setTcpNoDelay): Implemented. (getTcpNoDelay): Implemented. (setSoLinger): Implemented. (getSoLinger): Implemented. (getSoTimeout): Verify class type. (setSendBufferSize): Implemented. (getSendBufferSize): Implemented. (setReceiveBufferSize): Implemented. (getReceiveBufferSize): Implemented. (toString): Prepended "Socket". * java/net/SocketImpl.java (toString): Rewritten. (getOption): Made abstract. (setOption): Made abstract. * java/net/natPlainSocketImpl.cc (connect): Set localport properly. (setOption): Implemented. (getOption): Implemented. 1999-05-26 Warren Levy * java/net/DatagramSocket.java (DatagramSocket): Get local host address when null. Set SO_REUSEADDR for multicasts. (getSoTimeout): Implemented. (setSoTimeout): Implemented. * java/net/DatagramSocketImpl.java: Implement SocketOptions interface. * java/net/MulticastSocket.java (getInterface): Implemented. (setInterface): Implemented. (setTimeToLive): Check for invalid ttl. (joinGroup): Verify multicast address and security. (leaveGroup): Verify multicast address and security. (send): Implemented. * java/net/PlainDatagramSocketImpl.java (timeout): Added. (iface): Added. (ttl): Added. (setOption): Added. (getOption): Added. (mcastGrp): Added. (getTTL): Implemented as non-native. (setTTL): ditto. (join): ditto. (leave): ditto. * java/net/ServerSocket.java (setSoTimeout): Implemented. (getSoTimeout): Implemented. (setSocketFactory): Made synchronized. * java/net/Socket.java (setSoTimeout): Implemented. (getSoTimeout): Implemented. (close): Made synchronized. (setSocketImplFactory): Made synchronized. * java/net/SocketImpl.java: Implement SocketOptions interface. * java/net/natInetAddress.cc: Corrected module name at top of file. * java/net/natPlainDatagramSocketImpl.cc (McastReq): Added union. (bind): Added FIXME. (peek): Implemented. (setTTL): Removed. (getTTL): Removed. (join): Removed. (leave): Removed. (mcastGrp): Added. (setOption): Implemented for SO_REUSEADDR. (getOption): Implemented for SO_REUSEADDR. From-SVN: r27184 --- libjava/java/net/natPlainSocketImpl.cc | 211 ++++++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 6 deletions(-) (limited to 'libjava/java/net/natPlainSocketImpl.cc') diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc index 5926ab6..feaaa77 100644 --- a/libjava/java/net/natPlainSocketImpl.cc +++ b/libjava/java/net/natPlainSocketImpl.cc @@ -11,17 +11,25 @@ details. */ #include #include #include +#include #include #include #include #include +#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #ifndef HAVE_SOCKLEN_T typedef int socklen_t; @@ -93,6 +101,7 @@ void java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport) { union SockAddr u; + socklen_t addrlen = sizeof(u); jbyteArray haddress = host->address; jbyte *bytes = elements (haddress); int len = haddress->length; @@ -115,12 +124,14 @@ java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport) #endif else goto error; - if (::connect (fnum, ptr, len) == 0) - { - address = host; - port = rport; - return; - } + if (::connect (fnum, ptr, len) != 0) + goto error; + address = host; + port = rport; + if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0) + goto error; + localport = ntohs (u.address.sin_port); + return; error: char msg[100]; char* strerr = strerror (errno); @@ -178,3 +189,191 @@ java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s) sprintf (msg, "SocketImpl.accept: %.*s", 80, strerr); JvThrow (new java::io::IOException (JvNewStringUTF (msg))); } + +void +java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value) +{ + int val; + socklen_t val_len = sizeof (val); + + if ( _Jv_IsInstanceOf(value, + java::lang::Class::forName(JvNewStringUTF("java.lang.Boolean")))) + { + java::lang::Boolean *boolobj = + static_cast (value); + if (boolobj->booleanValue()) + val = 1; + else + { + if (optID == _Jv_SO_LINGER_) + val = -1; + else + val = 0; + } + } + else // assume value is an Integer + { + java::lang::Integer *intobj = + static_cast (value); + val = (int) intobj->intValue(); + } + + switch (optID) + { + case _Jv_TCP_NODELAY_ : +#ifdef TCP_NODELAY + if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val, + val_len) != 0) + goto error; +#else + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("TCP_NODELAY not supported"))); +#endif /* TCP_NODELAY */ + return; + 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 + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_LINGER not supported"))); +#endif /* SO_LINGER */ + 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 + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"))); +#endif + return; + case _Jv_SO_BINDADDR_ : + JvThrow (new java::net::SocketException ( + JvNewStringUTF ("SO_BINDADDR: read only option"))); + return; + case _Jv_IP_MULTICAST_IF_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"))); + return; + case _Jv_SO_REUSEADDR_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_REUSEADDR: option not implemented"))); + return; + case _Jv_SO_TIMEOUT_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_TIMEOUT: option not implemented"))); + return; + default : + errno = ENOPROTOOPT; + } + + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.setOption: %.*s", 80, strerr); + JvThrow (new java::net::SocketException (JvNewStringUTF (msg))); +} + +java::lang::Object * +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) + { +#ifdef TCP_NODELAY + case _Jv_TCP_NODELAY_ : + if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val, + &val_len) != 0) + goto error; + else + return new java::lang::Boolean (val != 0); +#else + JvThrow (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; + if (l_val.l_onoff) + return new java::lang::Integer (l_val.l_linger); + else + return new java::lang::Boolean (false); +#else + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_LINGER not supported"))); +#endif + 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; + else + return new java::lang::Integer (val); +#else + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"))); +#endif + break; + case _Jv_SO_BINDADDR_: + 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); + } +#endif + else + goto error; + return new java::net::InetAddress (laddr, NULL); + break; + case _Jv_IP_MULTICAST_IF_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("IP_MULTICAST_IF: option not implemented"))); + break; + case _Jv_SO_REUSEADDR_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_REUSEADDR: option not implemented"))); + break; + case _Jv_SO_TIMEOUT_ : + JvThrow (new java::lang::InternalError ( + JvNewStringUTF ("SO_TIMEOUT: option not implemented"))); + break; + default : + errno = ENOPROTOOPT; + } + + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "SocketImpl.getOption: %.*s", 80, strerr); + JvThrow (new java::net::SocketException (JvNewStringUTF (msg))); +} -- cgit v1.1