1999-05-26 Bryce McKinlay <bryce@albatross.co.nz>
authorwarrenl <warrenl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 May 1999 17:00:06 +0000 (17:00 +0000)
committerwarrenl <warrenl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 May 1999 17:00:06 +0000 (17:00 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27184 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
libjava/ChangeLog
libjava/java/net/DatagramSocket.java
libjava/java/net/DatagramSocketImpl.java
libjava/java/net/MulticastSocket.java
libjava/java/net/PlainDatagramSocketImpl.java
libjava/java/net/PlainSocketImpl.java
libjava/java/net/ServerSocket.java
libjava/java/net/Socket.java
libjava/java/net/SocketImpl.java
libjava/java/net/SocketOptions.java
libjava/java/net/natInetAddress.cc
libjava/java/net/natPlainDatagramSocketImpl.cc
libjava/java/net/natPlainSocketImpl.cc

index 576f7d3..030da4d 100644 (file)
@@ -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
index e82681a..3bfb032 100644 (file)
@@ -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
index 2ab8c2a..9ae61cf 100644 (file)
@@ -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;
index 1cb01c1..03a6e6b 100644 (file)
@@ -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);
   }
 }
index 7628c50..2a06371 100644 (file)
@@ -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);
+  }
 }
index 19a6439..b8e10ad 100644 (file)
@@ -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
index 4dcd9d6..ae1e113 100644 (file)
@@ -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;
   }
-
 }
index 8446b22..e4ef2d7 100644 (file)
@@ -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;
index c10ffcc..b764e8e 100644 (file)
@@ -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) + "]";
   }
 }
index 40f7649..397db64 100644 (file)
@@ -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;
index c591ea6..da3a1fb 100644 (file)
@@ -1,4 +1,4 @@
-// natClass.cc - Implementation of java.lang.Class native methods.
+// natInetAddress.cc
 
 /* Copyright (C) 1998, 1999  Cygnus Solutions
 
index 1bdcdd5..42abbe1 100644 (file)
@@ -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)));
 }
index 5926ab6..feaaa77 100644 (file)
@@ -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)));
+}