aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorWarren Levy <warrenl@gcc.gnu.org>1999-05-26 17:00:06 +0000
committerWarren Levy <warrenl@gcc.gnu.org>1999-05-26 17:00:06 +0000
commitf2ed9e9656a375cf80b11dfb3a264a7551654ecd (patch)
treea946b25d980c088ac8a79fbfeefceff665041269 /libjava
parentde4abb91d1a9f13baceb3e50f73829c0f21b830c (diff)
downloadgcc-f2ed9e9656a375cf80b11dfb3a264a7551654ecd.zip
gcc-f2ed9e9656a375cf80b11dfb3a264a7551654ecd.tar.gz
gcc-f2ed9e9656a375cf80b11dfb3a264a7551654ecd.tar.bz2
[multiple changes]
1999-05-26 Bryce McKinlay <bryce@albatross.co.nz> * 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 <warrenl@cygnus.com> * 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
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog71
-rw-r--r--libjava/java/net/DatagramSocket.java22
-rw-r--r--libjava/java/net/DatagramSocketImpl.java8
-rw-r--r--libjava/java/net/MulticastSocket.java49
-rw-r--r--libjava/java/net/PlainDatagramSocketImpl.java47
-rw-r--r--libjava/java/net/PlainSocketImpl.java15
-rw-r--r--libjava/java/net/ServerSocket.java25
-rw-r--r--libjava/java/net/Socket.java81
-rw-r--r--libjava/java/net/SocketImpl.java14
-rw-r--r--libjava/java/net/SocketOptions.java4
-rw-r--r--libjava/java/net/natInetAddress.cc2
-rw-r--r--libjava/java/net/natPlainDatagramSocketImpl.cc147
-rw-r--r--libjava/java/net/natPlainSocketImpl.cc211
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 <bryce@albatross.co.nz>
+
+ * 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 <warrenl@cygnus.com>
+
+ * 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 <tromey@cygnus.com>
* 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 7628c508..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 <java/net/PlainDatagramSocketImpl.h>
#include <java/net/InetAddress.h>
#include <java/net/DatagramPacket.h>
+#include <java/lang/Boolean.h>
#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 <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <cni.h>
+#include <javaprims.h>
#include <java/io/IOException.h>
#include <java/io/FileDescriptor.h>
#include <java/net/BindException.h>
#include <java/net/ConnectException.h>
#include <java/net/PlainSocketImpl.h>
#include <java/net/InetAddress.h>
+#include <java/net/SocketException.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>
#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<java::lang::Boolean *> (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<java::lang::Integer *> (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)));
+}