From 9378f999718203e09ed4e030ad6ef70f9d666322 Mon Sep 17 00:00:00 2001 From: warrenl Date: Wed, 26 May 1999 17:00:06 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27184 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 71 +++++++++ libjava/java/net/DatagramSocket.java | 22 ++- libjava/java/net/DatagramSocketImpl.java | 8 +- libjava/java/net/MulticastSocket.java | 49 +++++- libjava/java/net/PlainDatagramSocketImpl.java | 47 +++++- libjava/java/net/PlainSocketImpl.java | 15 ++ libjava/java/net/ServerSocket.java | 25 +-- libjava/java/net/Socket.java | 81 +++++++--- libjava/java/net/SocketImpl.java | 14 +- libjava/java/net/SocketOptions.java | 4 +- libjava/java/net/natInetAddress.cc | 2 +- libjava/java/net/natPlainDatagramSocketImpl.cc | 147 ++++++++++++++--- libjava/java/net/natPlainSocketImpl.cc | 211 ++++++++++++++++++++++++- 13 files changed, 608 insertions(+), 88 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 576f7d3..030da4d 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,74 @@ +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. + 1999-05-24 Tom Tromey * java/util/ResourceBundle.java (getBundle): Throw diff --git a/libjava/java/net/DatagramSocket.java b/libjava/java/net/DatagramSocket.java index e82681a..3bfb032 100644 --- a/libjava/java/net/DatagramSocket.java +++ b/libjava/java/net/DatagramSocket.java @@ -56,12 +56,19 @@ public class DatagramSocket // TBD: if this is right then the same should be done in Socket(). try { - impl.bind(port, laddr == null ? InetAddress.getLocalHost() : laddr); + if (laddr == null) + laddr = InetAddress.getLocalHost(); } catch (UnknownHostException e) { throw new BindException(e.getMessage()); } + + // For multicasting, set the socket to be reused (Stevens pp. 195-6). + if (this instanceof MulticastSocket) + impl.setOption(SocketOptions.SO_REUSEADDR, new Boolean(true)); + + impl.bind(port, laddr); this.laddr = laddr; } @@ -82,8 +89,11 @@ public class DatagramSocket public synchronized int getSoTimeout() throws SocketException { - // FIXME: TODO - DatagramSocket.getSoTimeout - throw new SocketException("DatagramSocket.getSoTimeout - not yet implemented"); + Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); + if (timeout instanceof Integer) + return ((Integer)timeout).intValue(); + else + return 0; } public synchronized void receive(DatagramPacket p) throws IOException @@ -114,8 +124,10 @@ public class DatagramSocket public synchronized void setSoTimeout(int timeout) throws SocketException { - // FIXME: TODO - DatagramSocket.setSoTimeout - throw new SocketException("DatagramSocket.setSoTimeout - not yet implemented"); + if (timeout < 0) + throw new IllegalArgumentException("Invalid timeout: " + timeout); + + impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); } // JDK1.2 diff --git a/libjava/java/net/DatagramSocketImpl.java b/libjava/java/net/DatagramSocketImpl.java index 2ab8c2a..9ae61cf 100644 --- a/libjava/java/net/DatagramSocketImpl.java +++ b/libjava/java/net/DatagramSocketImpl.java @@ -23,9 +23,7 @@ import java.io.FileDescriptor; * Status: Believed complete and correct. */ -// JDK1.2: needs to implement SocketOptions. -// JDK1.2: public abstract class DatagramSocketImpl implements SocketOptions -public abstract class DatagramSocketImpl +public abstract class DatagramSocketImpl implements SocketOptions { protected int localport; protected FileDescriptor fd; @@ -48,6 +46,10 @@ public abstract class DatagramSocketImpl protected abstract void join(InetAddress inetaddr) throws IOException; protected abstract void leave(InetAddress inetaddr) throws IOException; + public abstract Object getOption(int optID) throws SocketException; + public abstract void setOption(int optID, Object value) + throws SocketException; + protected FileDescriptor getFileDescriptor() { return fd; diff --git a/libjava/java/net/MulticastSocket.java b/libjava/java/net/MulticastSocket.java index 1cb01c1..03a6e6b 100644 --- a/libjava/java/net/MulticastSocket.java +++ b/libjava/java/net/MulticastSocket.java @@ -25,7 +25,8 @@ import java.io.IOException; public class MulticastSocket extends DatagramSocket { // FIXME: the local addr bound to the multicast socket can be reused; - // unlike unicast sockets. see p.1159 JCL book. + // unlike unicast sockets. It binds to any available network interface. + // See p.1159 JCL book. public MulticastSocket() throws IOException { @@ -39,13 +40,16 @@ public class MulticastSocket extends DatagramSocket public InetAddress getInterface() throws SocketException { - // FIXME: TODO - MulticastSocket.getInterface - throw new SocketException("MulticastSocket.getInterface - not yet implemented"); + // FIXME: Is it possible that an InetAddress wasn't returned from getOption? + return (InetAddress) impl.getOption(SocketOptions.IP_MULTICAST_IF); } // Deprecated in JDK1.2 public byte getTTL() throws IOException { + // Use getTTL here rather than getTimeToLive in case we're using an impl + // other than the default PlainDatagramSocketImpl and it doesn't have + // getTimeToLive yet. return impl.getTTL(); } @@ -57,35 +61,66 @@ public class MulticastSocket extends DatagramSocket public void setInterface(InetAddress inf) throws SocketException { - // FIXME: TODO - MulticastSocket.setInterface - throw new SocketException("MulticastSocket.setInterface - not yet implemented"); + impl.setOption(SocketOptions.IP_MULTICAST_IF, inf); } // Deprecated in JDK1.2 public void setTTL(byte ttl) throws IOException { + // Use setTTL here rather than setTimeToLive in case we're using an impl + // other than the default PlainDatagramSocketImpl and it doesn't have + // setTimeToLive yet. impl.setTTL(ttl); } // JDK1.2 public void setTimeToLive(int ttl) throws IOException { + if (ttl < 0 || ttl > 255) + throw new IllegalArgumentException("Invalid ttl: " + ttl); + impl.setTimeToLive(ttl); } public void joinGroup(InetAddress mcastaddr) throws IOException { + if (! mcastaddr.isMulticastAddress()) + throw new IOException("Not a Multicast address"); + + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkMulticast(mcastaddr); + impl.join(mcastaddr); } public void leaveGroup(InetAddress mcastaddr) throws IOException { + if (! mcastaddr.isMulticastAddress()) + throw new IOException("Not a Multicast address"); + + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkMulticast(mcastaddr); + impl.leave(mcastaddr); } - public void send(DatagramPacket p, byte ttl) throws IOException + public synchronized void send(DatagramPacket p, byte ttl) throws IOException { - // FIXME: use ttl instead of getTTL() for time to live. + SecurityManager s = System.getSecurityManager(); + if (s != null) + { + InetAddress addr = p.getAddress(); + if (addr.isMulticastAddress()) + s.checkMulticast(addr, ttl); + else + s.checkConnect(addr.getHostAddress(), p.getPort()); + } + + int oldttl = impl.getTimeToLive(); + impl.setTimeToLive(((int) ttl) & 0xFF); impl.send(p); + impl.setTimeToLive(oldttl); } } diff --git a/libjava/java/net/PlainDatagramSocketImpl.java b/libjava/java/net/PlainDatagramSocketImpl.java index 7628c50..2a06371 100644 --- a/libjava/java/net/PlainDatagramSocketImpl.java +++ b/libjava/java/net/PlainDatagramSocketImpl.java @@ -24,13 +24,28 @@ import java.io.IOException; class PlainDatagramSocketImpl extends DatagramSocketImpl { + // These fields are mirrored for use in native code to avoid cpp conflicts + // when the #defines in system header files are the same as the public fields. + static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY, + _Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR, + _Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR, + _Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF, + _Jv_SO_LINGER_ = SocketOptions.SO_LINGER, + _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT, + _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF, + _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF; + int fnum = -1; InetAddress address; // TBD: DatagramSocket.getLocalAddress()? + // FIXME: These values are set/read by setOption/getOption. + int timeout = 0; + InetAddress iface = null; + int ttl = -1; // FIXME: Probably should have bind (and create?) calls from DatagramSocket // constuctor. If so, then same change should be made to the corresponding // Socket (non-datagram) classes. This allows the implementation more - // compleete control over how the socket is set up and used (e.g. connect, + // complete control over how the socket is set up and used (e.g. connect, // setting options, etc.). public PlainDatagramSocketImpl() { @@ -40,17 +55,39 @@ class PlainDatagramSocketImpl extends DatagramSocketImpl throws SocketException; protected native void create() throws SocketException; protected native int peek(InetAddress i) throws IOException; - protected native void setTTL(byte ttl) throws IOException; - protected native byte getTTL() throws IOException; protected native void setTimeToLive(int ttl) throws IOException; protected native int getTimeToLive() throws IOException; - protected native void join(InetAddress inetaddr) throws IOException; - protected native void leave(InetAddress inetaddr) throws IOException; protected native void send(DatagramPacket p) throws IOException; protected native void receive(DatagramPacket p) throws IOException; + public native void setOption(int optID, Object value) throws SocketException; + public native Object getOption(int optID) throws SocketException; + private native void mcastGrp(InetAddress inetaddr, boolean join) + throws IOException; protected void close() throws IOException { fd.close(); } + + // Deprecated in JDK 1.2. + protected byte getTTL() throws IOException + { + return (byte) getTimeToLive(); + } + + // Deprecated in JDK 1.2. + protected void setTTL(byte ttl) throws IOException + { + setTimeToLive(((int) ttl) & 0xFF); + } + + protected void join(InetAddress inetaddr) throws IOException + { + mcastGrp(inetaddr, true); + } + + protected void leave(InetAddress inetaddr) throws IOException + { + mcastGrp(inetaddr, false); + } } diff --git a/libjava/java/net/PlainSocketImpl.java b/libjava/java/net/PlainSocketImpl.java index 19a6439..b8e10ad 100644 --- a/libjava/java/net/PlainSocketImpl.java +++ b/libjava/java/net/PlainSocketImpl.java @@ -24,8 +24,23 @@ import java.io.*; class PlainSocketImpl extends SocketImpl { + // These fields are mirrored for use in native code to avoid cpp conflicts + // when the #defines in system header files are the same as the public fields. + static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY, + _Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR, + _Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR, + _Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF, + _Jv_SO_LINGER_ = SocketOptions.SO_LINGER, + _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT, + _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF, + _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF; + int fnum = -1; + public native void setOption(int optID, Object value) throws SocketException; + + public native Object getOption(int optID) throws SocketException; + protected native void create (boolean stream) throws IOException; protected void connect (String host, int port) throws IOException diff --git a/libjava/java/net/ServerSocket.java b/libjava/java/net/ServerSocket.java index 4dcd9d6..ae1e113 100644 --- a/libjava/java/net/ServerSocket.java +++ b/libjava/java/net/ServerSocket.java @@ -1,4 +1,4 @@ -// Socket.java +// ServerSocket.java /* Copyright (C) 1999 Cygnus Solutions @@ -14,8 +14,7 @@ details. */ */ /** Written using on-line Java Platform 1.2 API Specification. - * Status: I believe all methods are implemented, but many - * of them just throw an exception. + * Status: I believe all methods are implemented. */ package java.net; @@ -81,25 +80,31 @@ public class ServerSocket impl.close(); } - public void setSoTimeout (int timeout) throws SocketException + public synchronized void setSoTimeout (int timeout) throws SocketException { - throw new InternalError("ServerSocket.setSoTimeout not implemented"); + if (timeout < 0) + throw new IllegalArgumentException("Invalid timeout: " + timeout); + + impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); } - public int getSoTimeout () throws SocketException + public synchronized int getSoTimeout () throws SocketException { - throw new InternalError("ServerSocket.getSoTimeout not implemented"); + Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); + if (timeout instanceof Integer) + return ((Integer)timeout).intValue(); + else + return 0; } public String toString () { - return impl.toString(); + return "ServerSocket" + impl.toString(); } - public static void setSocketFactory (SocketImplFactory fac) + public static synchronized void setSocketFactory (SocketImplFactory fac) throws IOException { factory = fac; } - } diff --git a/libjava/java/net/Socket.java b/libjava/java/net/Socket.java index 8446b22..e4ef2d7 100644 --- a/libjava/java/net/Socket.java +++ b/libjava/java/net/Socket.java @@ -14,8 +14,7 @@ details. */ */ /** Written using on-line Java Platform 1.2 API Specification. - * Status: I believe all methods are implemented, but many - * of them just throw an exception. + * Status: I believe all methods are implemented. */ package java.net; @@ -116,9 +115,18 @@ public class Socket public InetAddress getLocalAddress () { - // There doesn't seem to be any way to implement this - // using a (generic) SocketImpl ... What am I missing? - throw new InternalError("Socket.getLocalAddres not implemented"); + InetAddress localAddress; + try + { + localAddress = (InetAddress)impl.getOption(SocketOptions.SO_BINDADDR); + } + catch (SocketException x) + { + // (hopefully) shouldn't happen + System.err.println(x); + throw new java.lang.InternalError("Error in PlainSocketImpl.getOption"); + } + return localAddress; } public int getPort () @@ -143,65 +151,98 @@ public class Socket public void setTcpNoDelay (boolean on) throws SocketException { - throw new InternalError("Socket.setTcpNoDelay not implemented"); + impl.setOption( SocketOptions.TCP_NODELAY, new Boolean(on) ); } public boolean getTcpNoDelay() throws SocketException { - throw new InternalError("Socket.getTcpNoDelay not implemented"); + Boolean bool = (Boolean)impl.getOption( SocketOptions.TCP_NODELAY ); + return bool.booleanValue(); } public void setSoLinger(boolean on, int linger) throws SocketException { - throw new InternalError("Socket.setSoLinger not implemented"); + if ( on && (linger >= 0) ) + { + if (linger > 65535) + linger = 65535; + impl.setOption( SocketOptions.SO_LINGER, new Integer(linger) ); + } + else if ( on && (linger < 0) ) + throw new IllegalArgumentException("SO_LINGER must be >= 0"); + else + impl.setOption( SocketOptions.SO_LINGER, new Boolean(false) ); } public int getSoLinger() throws SocketException { - throw new InternalError("Socket.getSoLinger not implemented"); + Object linger = impl.getOption(SocketOptions.SO_LINGER); + if (linger instanceof Integer) + return ((Integer)linger).intValue(); + else + return -1; } - public void setSoTimeout (int timeout) throws SocketException + public synchronized void setSoTimeout (int timeout) throws SocketException { - throw new InternalError("Socket.setSoTimeout not implemented"); + if (timeout < 0) + throw new IllegalArgumentException("Invalid timeout: " + timeout); + + impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); } - public int getSoTimeout () throws SocketException + public synchronized int getSoTimeout () throws SocketException { - throw new InternalError("Socket.getSoTimeout not implemented"); + Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); + if (timeout instanceof Integer) + return ((Integer)timeout).intValue(); + else + return 0; } + // JDK1.2 public void setSendBufferSize (int size) throws SocketException { - throw new InternalError("Socket.setSendBufferSize not implemented"); + if (size <= 0) + throw new IllegalArgumentException("Invalid buffer size: " + size); + + impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size)); } + // JDK1.2 public int getSendBufferSize () throws SocketException { - throw new InternalError("Socket.getSendBufferSize not implemented"); + Integer buf = (Integer)impl.getOption(SocketOptions.SO_SNDBUF); + return buf.intValue(); } + // JDK1.2 public void setReceiveBufferSize (int size) throws SocketException { - throw new InternalError("Socket.setReceiveBufferSize not implemented"); + if (size <= 0) + throw new IllegalArgumentException("Invalid buffer size: " + size); + + impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size)); } + // JDK1.2 public int getReceiveBufferSize () throws SocketException { - throw new InternalError("Socket.getReceiveBufferSize not implemented"); + Integer buf = (Integer)impl.getOption(SocketOptions.SO_RCVBUF); + return buf.intValue(); } - public void close () throws IOException + public synchronized void close () throws IOException { impl.close(); } public String toString () { - return impl.toString(); + return "Socket" + impl.toString(); } - public static void setSocketImplFactory (SocketImplFactory fac) + public static synchronized void setSocketImplFactory (SocketImplFactory fac) throws IOException { factory = fac; diff --git a/libjava/java/net/SocketImpl.java b/libjava/java/net/SocketImpl.java index c10ffcc..b764e8e 100644 --- a/libjava/java/net/SocketImpl.java +++ b/libjava/java/net/SocketImpl.java @@ -17,12 +17,10 @@ import java.io.*; */ /** Written using on-line Java Platform 1.2 API Specification. - * Believed complete and correct, except for implementation of toString. + * Believed complete and correct. */ -// JDK1.2: needs to implement SocketOptions. -// JDK1.2: public abstract class SocketImpl implements SocketOptions -public abstract class SocketImpl +public abstract class SocketImpl implements SocketOptions { protected InetAddress address; @@ -65,8 +63,14 @@ public abstract class SocketImpl protected int getLocalPort () { return localport; } + public abstract Object getOption(int optID) throws SocketException; + + public abstract void setOption(int optID, Object value) + throws SocketException; + public String toString () { - return super.toString(); // FIXME + return "[addr=" + address.toString() + ",port=" + Integer.toString(port) + + ",localport=" + Integer.toString(localport) + "]"; } } diff --git a/libjava/java/net/SocketOptions.java b/libjava/java/net/SocketOptions.java index 40f7649..397db64 100644 --- a/libjava/java/net/SocketOptions.java +++ b/libjava/java/net/SocketOptions.java @@ -29,10 +29,10 @@ public abstract interface SocketOptions public static final int SO_LINGER = 0x80; public static final int SO_TIMEOUT = 0x1006; -// JDK1.2 + // JDK1.2 public static final int SO_SNDBUF = 0x1001; -// JDK1.2 + // JDK1.2 public static final int SO_RCVBUF = 0x1002; public void setOption(int optID, Object value) throws SocketException; diff --git a/libjava/java/net/natInetAddress.cc b/libjava/java/net/natInetAddress.cc index c591ea6..da3a1fb 100644 --- a/libjava/java/net/natInetAddress.cc +++ b/libjava/java/net/natInetAddress.cc @@ -1,4 +1,4 @@ -// natClass.cc - Implementation of java.lang.Class native methods. +// natInetAddress.cc /* Copyright (C) 1998, 1999 Cygnus Solutions diff --git a/libjava/java/net/natPlainDatagramSocketImpl.cc b/libjava/java/net/natPlainDatagramSocketImpl.cc index 1bdcdd5..42abbe1 100644 --- a/libjava/java/net/natPlainDatagramSocketImpl.cc +++ b/libjava/java/net/natPlainDatagramSocketImpl.cc @@ -23,6 +23,7 @@ details. */ #include #include #include +#include #ifndef HAVE_SOCKLEN_T typedef int socklen_t; @@ -36,6 +37,15 @@ union SockAddr #endif }; +union McastReq +{ + struct ip_mreq mreq; +#ifdef HAVE_INET6 + struct ipv6_mreq mreq6; +#endif +}; + + // FIXME: routines here and/or in natPlainSocketImpl.cc could throw // NoRouteToHostException; also consider UnknownHostException, ConnectException. @@ -58,6 +68,7 @@ void java::net::PlainDatagramSocketImpl::bind (jint lport, java::net::InetAddress *host) { + // FIXME: prob. need to do a setsockopt with SO_BROADCAST to allow multicast. union SockAddr u; jbyteArray haddress = host->address; jbyte *bytes = elements (haddress); @@ -97,9 +108,41 @@ java::net::PlainDatagramSocketImpl::bind (jint lport, jint java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i) { - // FIXME: TODO - PlainDatagramSocketImpl::peek - // throws IOException; - return 0; + // FIXME: Deal with Multicast and if the socket is connected. + union SockAddr u; + socklen_t addrlen = sizeof(u); + ssize_t retlen = + ::recvfrom (fnum, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u, + &addrlen); + if (retlen < 0) + goto error; + // FIXME: Deal with Multicast addressing and if the socket is connected. + 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 + goto error; + // FIXME: Multicast: s->address = new InetAddress (raddr, NULL); + i->address = raddr; + return rport; + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "DatagramSocketImpl.peek: %.*s", 80, strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); } void @@ -183,21 +226,6 @@ java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p) } void -java::net::PlainDatagramSocketImpl::setTTL (jbyte ttl) -{ - // FIXME: TODO - :PlainDatagramSocketImpl::setTTL - // throws IOException; -} - -jbyte -java::net::PlainDatagramSocketImpl::getTTL () -{ - // FIXME: TODO - PlainDatagramSocketImpl::getTTL - // throws IOException; - return 0; -} - -void java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl) { // throws IOException; @@ -213,15 +241,86 @@ java::net::PlainDatagramSocketImpl::getTimeToLive () } void -java::net::PlainDatagramSocketImpl::join (java::net::InetAddress *inetaddr) +java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr, + jboolean join) { - // throws IOException; - // FIXME: TODO - PlainDatagramSocketImpl::join + union McastReq u; + jbyteArray haddress = inetaddr->address; + jbyte *bytes = elements (haddress); + int len = haddress->length; + int level, opname; + const char *ptr; + if (len == 4) + { + level = IPPROTO_IP; + opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; + memcpy (&u.mreq.imr_multiaddr, bytes, len); + // FIXME: If a non-default interface is set, use it; see Stevens p. 501. + u.mreq.imr_interface.s_addr = htonl (INADDR_ANY); + len = sizeof (struct ip_mreq); + ptr = (const char *) &u.mreq; + } +#ifdef HAVE_INET6 + else if (len == 16) + { + level = IPPROTO_IPV6; + opname = join ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP; + memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len); + // FIXME: If a non-default interface is set, use it; see Stevens p. 501. + u.mreq6.ipv6mr_interface = 0; + len = sizeof (struct ipv6_mreq); + ptr = (const char *) &u.mreq6; + } +#endif + else + goto error; + if (::setsockopt (fnum, level, opname, ptr, len) == 0) + return; + error: + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "DatagramSocketImpl.%s: %.*s", join ? "join" : "leave", 80, + strerr); + JvThrow (new java::io::IOException (JvNewStringUTF (msg))); } void -java::net::PlainDatagramSocketImpl::leave (java::net::InetAddress *inetaddr) +java::net::PlainDatagramSocketImpl::setOption (jint optID, + java::lang::Object *value) { - // throws IOException; - // FIXME: TODO - PlainDatagramSocketImpl::leave + if (optID == _Jv_SO_REUSEADDR_) + { + // FIXME: Is it possible that a Boolean wasn't passed in? + const int on = (((java::lang::Boolean *) value)->booleanValue()) ? 1 : 0; + if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &on, + sizeof (int)) == 0) + return; + } + else + errno = ENOPROTOOPT; + + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "DatagramSocketImpl.setOption: %.*s", 80, strerr); + JvThrow (new java::net::SocketException (JvNewStringUTF (msg))); +} + +java::lang::Object * +java::net::PlainDatagramSocketImpl::getOption (jint optID) +{ + if (optID == _Jv_SO_REUSEADDR_) + { + int on; + socklen_t len; + if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &on, + (socklen_t *) &len) == 0) + return new java::lang::Boolean (on == 1); + } + else + errno = ENOPROTOOPT; + + char msg[100]; + char* strerr = strerror (errno); + sprintf (msg, "DatagramSocketImpl.getOption: %.*s", 80, strerr); + JvThrow (new java::net::SocketException (JvNewStringUTF (msg))); } 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))); +} -- 2.7.4