aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/net/natPlainSocketImpl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/net/natPlainSocketImpl.cc')
-rw-r--r--libjava/java/net/natPlainSocketImpl.cc187
1 files changed, 169 insertions, 18 deletions
diff --git a/libjava/java/net/natPlainSocketImpl.cc b/libjava/java/net/natPlainSocketImpl.cc
index 4a75e980073..a1e967eb8b3 100644
--- a/libjava/java/net/natPlainSocketImpl.cc
+++ b/libjava/java/net/natPlainSocketImpl.cc
@@ -20,13 +20,9 @@ details. */
#undef MIN_PRIORITY
#undef FIONREAD
-// These functions make the Win32 socket API look more POSIXy
-static inline int
-close(int s)
-{
- return closesocket(s);
-}
+#define NATIVE_CLOSE(s) closesocket (s)
+// These functions make the Win32 socket API look more POSIXy
static inline int
write(int s, void *buf, int len)
{
@@ -63,6 +59,8 @@ read(int s, void *buf, int len)
#include <errno.h>
#include <string.h>
+#define NATIVE_CLOSE(s) ::close (s)
+
#endif /* WIN32 */
#endif /* DISABLE_JAVA_NET */
@@ -120,7 +118,9 @@ _Jv_accept (int fd, struct sockaddr *addr, socklen_t *addrlen)
#include <java/net/ConnectException.h>
#include <java/net/PlainSocketImpl.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>
@@ -148,7 +148,7 @@ java::net::PlainSocketImpl::bind (java::net::InetAddress *, jint)
}
void
-java::net::PlainSocketImpl::connect (java::net::InetAddress *, jint)
+java::net::PlainSocketImpl::connect (java::net::SocketAddress *, jint)
{
throw new ConnectException (
JvNewStringLatin1 ("SocketImpl.connect: unimplemented"));
@@ -210,6 +210,13 @@ java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
}
+void
+java::net::PlainSocketImpl::sendUrgentData(jint data)
+{
+ throw new SocketException (
+ JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented"));
+}
+
jint
java::net::PlainSocketImpl::available(void)
{
@@ -224,6 +231,20 @@ java::net::PlainSocketImpl::close(void)
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
@@ -304,8 +325,13 @@ java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
}
void
-java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
+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();
+
union SockAddr u;
socklen_t addrlen = sizeof(u);
jbyteArray haddress = host->addr;
@@ -331,8 +357,37 @@ java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
else
throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
- if (_Jv_connect (fnum, ptr, len) != 0)
- goto error;
+// 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;
+
+ 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"));
+ }
+ else
+#endif
+ {
+ if (_Jv_connect (fnum, ptr, len) != 0)
+ goto error;
+ }
+
address = host;
port = rport;
// A bind may not have been done on this socket; if so, set localport now.
@@ -429,7 +484,7 @@ java::net::PlainSocketImpl::close()
JvSynchronize sync (this);
// should we use shutdown here? how would that effect so_linger?
- int res = ::close (fnum);
+ int res = NATIVE_CLOSE (fnum);
if (res == -1)
{
@@ -506,6 +561,12 @@ java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
}
}
+void
+java::net::PlainSocketImpl::sendUrgentData (jint)
+{
+ throw new SocketException (JvNewStringLatin1 (
+ "PlainSocketImpl: sending of urgent data not supported by this socket"));
+}
// Read a single byte from the socket.
jint
@@ -527,7 +588,8 @@ java::net::PlainSocketImpl::read(void)
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);
+ 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)
@@ -586,7 +648,8 @@ java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
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);
+ 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.
@@ -715,7 +778,8 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
}
else
{
- throw new java::lang::IllegalArgumentException (JvNewStringLatin1 ("`value' must be Boolean or Integer"));
+ throw new java::lang::IllegalArgumentException (
+ JvNewStringLatin1 ("`value' must be Boolean or Integer"));
}
switch (optID)
@@ -724,12 +788,30 @@ java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
#ifdef TCP_NODELAY
if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
val_len) != 0)
- goto 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)
+ 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)
+ goto error;
+ break;
+
case _Jv_SO_LINGER_ :
#ifdef SO_LINGER
struct linger l_val;
@@ -763,6 +845,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;
+ break;
+
case _Jv_SO_REUSEADDR_ :
throw new java::net::SocketException (
JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
@@ -812,12 +911,32 @@ java::net::PlainSocketImpl::getOption (jint optID)
if (l_val.l_onoff)
return new java::lang::Integer (l_val.l_linger);
else
- return new java::lang::Boolean ((__java_boolean)false);
+ return new java::lang::Boolean ((jboolean)false);
#else
throw new java::lang::InternalError (
JvNewStringUTF ("SO_LINGER not supported"));
#endif
break;
+
+ case _Jv_SO_KEEPALIVE_ :
+ if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
+ &val_len) != 0)
+ 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;
+ 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;
+ return new java::lang::Boolean ((jboolean)val);
+
case _Jv_SO_RCVBUF_ :
case _Jv_SO_SNDBUF_ :
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
@@ -852,8 +971,8 @@ java::net::PlainSocketImpl::getOption (jint optID)
}
#endif
else
- throw
- new java::net::SocketException (JvNewStringUTF ("invalid family"));
+ throw new java::net::SocketException (
+ JvNewStringUTF ("invalid family"));
localAddress = new java::net::InetAddress (laddr, NULL);
}
return localAddress;
@@ -862,6 +981,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)
+ 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"));
@@ -878,4 +1015,18 @@ java::net::PlainSocketImpl::getOption (jint optID)
throw new java::net::SocketException (JvNewStringUTF (strerr));
}
+void
+java::net::PlainSocketImpl::shutdownInput (void)
+{
+ if (::shutdown (fnum, 0))
+ throw new SocketException (JvNewStringUTF (strerror (errno)));
+}
+
+void
+java::net::PlainSocketImpl::shutdownOutput (void)
+{
+ if (::shutdown (fnum, 1))
+ throw new SocketException (JvNewStringUTF (strerror (errno)));
+}
+
#endif /* DISABLE_JAVA_NET */