--- /home/cpdev/src/classpath/gnu/java/net/PlainDatagramSocketImpl.java	2005-07-02 21:03:03.000000000 +0000
+++ gnu/java/net/PlainDatagramSocketImpl.java	2005-06-30 05:34:09.000000000 +0000
@@ -44,9 +44,11 @@
 import java.net.DatagramPacket;
 import java.net.DatagramSocketImpl;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.SocketAddress;
 import java.net.SocketException;
+import java.net.SocketOptions;
 
 /**
  * Written using on-line Java Platform 1.2 API Specification, as well
@@ -73,10 +75,22 @@
       }
   }
   
-  /**
-   * Option id for the IP_TTL (time to live) value.
-   */
-  private static final int IP_TTL = 0x1E61; // 7777
+  // 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_SO_BROADCAST_ = SocketOptions.SO_BROADCAST,
+                   _Jv_SO_OOBINLINE_ = SocketOptions.SO_OOBINLINE,
+                   _Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
+                   _Jv_IP_MULTICAST_IF2_ = SocketOptions.IP_MULTICAST_IF2,
+                   _Jv_IP_MULTICAST_LOOP_ = SocketOptions.IP_MULTICAST_LOOP,
+                   _Jv_IP_TOS_ = SocketOptions.IP_TOS,
+                   _Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
+                   _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
+                   _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
+                   _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF,
+                   _Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE;
 
   /**
    * This is the actual underlying file descriptor
@@ -93,6 +107,15 @@
    */
   private final Object SEND_LOCK = new Object();
 
+  // FIXME: Is this necessary?  Could it help w/ DatagramSocket.getLocalAddress?
+  // InetAddress address;
+  
+  // localAddress cache  
+  InetAddress localAddress;
+
+  // 'timeout' is set/read by setOption/getOption.
+  int timeout = 0;
+
   /**
    * Default do nothing constructor
    */
@@ -123,15 +146,24 @@
    *
    * @exception SocketException If an error occurs
    */
-  protected synchronized native void bind(int port, InetAddress addr)
+  protected native void bind(int port, InetAddress addr)
     throws SocketException;
 
+  protected native void connect(InetAddress addr, int port)
+    throws SocketException;
+  
+  protected native void disconnect();
+  
   /**
    * Creates a new datagram socket
    *
    * @exception SocketException If an error occurs
    */
-  protected synchronized native void create() throws SocketException;
+  protected native void create() throws SocketException;
+  
+  protected native int peek(InetAddress addr) throws IOException;
+  
+  protected native int peekData(DatagramPacket packet) throws IOException;
 
   /**
    * Sets the Time to Live value for the socket
@@ -140,10 +172,7 @@
    *
    * @exception IOException If an error occurs
    */
-  protected synchronized void setTimeToLive(int ttl) throws IOException
-  {
-    setOption(IP_TTL, new Integer(ttl));
-  }
+  protected native void setTimeToLive(int ttl) throws IOException;
 
   /**
    * Gets the Time to Live value for the socket
@@ -152,30 +181,7 @@
    *
    * @exception IOException If an error occurs
    */
-  protected synchronized int getTimeToLive() throws IOException
-  {
-    Object obj = getOption(IP_TTL);
-
-    if (! (obj instanceof Integer))
-      throw new IOException("Internal Error");
-
-    return ((Integer) obj).intValue();
-  }
-
-  /**
-   * Sends a packet of data to a remote host
-   *
-   * @param addr The address to send to
-   * @param port The port to send to 
-   * @param buf The buffer to send
-   * @param offset The offset of the data in the buffer to send
-   * @param len The length of the data to send
-   *
-   * @exception IOException If an error occurs
-   */
-  private native void sendto (InetAddress addr, int port,
-                              byte[] buf, int offset, int len)
-    throws IOException;
+  protected native int getTimeToLive() throws IOException;
 
   /**
    * Sends a packet of data to a remote host
@@ -184,15 +190,7 @@
    *
    * @exception IOException If an error occurs
    */
-  protected void send(DatagramPacket packet) throws IOException
-  {
-    synchronized(SEND_LOCK)
-      {
-      sendto(packet.getAddress(), packet.getPort(), packet.getData(), 
-             packet.getOffset(), packet.getLength());
-      }
-    
-  }
+  protected native void send(DatagramPacket packet) throws IOException;
 
   /**
    * Receives a UDP packet from the network
@@ -201,23 +199,7 @@
    *
    * @exception IOException IOException If an error occurs
    */
-  protected void receive(DatagramPacket packet)
-    throws IOException
-  {
-      synchronized(RECEIVE_LOCK)
-        {
-        receive0(packet);		
-        }
-  }
-
-  /**
-   * Native call to receive a UDP packet from the network
-   * 
-   * @param packet The packet to fill in with the data received
-   *
-   * @exception IOException IOException If an error occurs
-   */
-  private native void receive0(DatagramPacket packet) throws IOException;
+  protected native void receive(DatagramPacket packet) throws IOException;
 
   /**
    * Sets the value of an option on the socket
@@ -227,7 +209,7 @@
    *
    * @exception SocketException If an error occurs
    */
-  public synchronized native void setOption(int option_id, Object val)
+  public native void setOption(int option_id, Object val)
     throws SocketException;
 
   /**
@@ -239,13 +221,28 @@
    *
    * @exception SocketException If an error occurs
    */
-  public synchronized native Object getOption(int option_id)
+  public native Object getOption(int option_id)
     throws SocketException;
 
   /**
+   * Joins or leaves a broadcasting group on a given network interface.
+   * If the network interface is <code>null</code> the group is join/left on
+   * all locale network interfaces.
+   * 
+   * @param inetAddr The broadcast address.
+   * @param netIf The network interface to join the group on.
+   * @param join True to join a broadcasting group, fals to leave it.
+   *
+   * @exception IOException If an error occurs.
+   */
+  private native void mcastGrp(InetAddress inetAddr, NetworkInterface netIf,
+		               boolean join)
+    throws IOException;
+
+  /**
    * Closes the socket
    */
-  protected synchronized native void close();
+  protected native void close();
 
   /**
    * Gets the Time to Live value for the socket
@@ -256,7 +253,7 @@
    *
    * @deprecated 1.2
    */
-  protected synchronized byte getTTL() throws IOException
+  protected byte getTTL() throws IOException
   {
     return (byte) getTimeToLive();
   }
@@ -270,7 +267,7 @@
    *
    * @deprecated 1.2
    */
-  protected synchronized void setTTL(byte ttl) throws IOException
+  protected void setTTL(byte ttl) throws IOException
   {
     setTimeToLive(((int) ttl) & 0xFF);
   }
@@ -282,7 +279,10 @@
    *
    * @exception IOException If an error occurs
    */
-  protected synchronized native void join(InetAddress addr) throws IOException;
+  protected void join(InetAddress addr) throws IOException
+  {
+    mcastGrp(addr, null, true);
+  }
 
   /**
    * Leaves a multicast group
@@ -291,31 +291,20 @@
    *
    * @exception IOException If an error occurs
    */
-  protected synchronized native void leave(InetAddress addr) throws IOException;
-
-  /**
-   * What does this method really do?
-   */
-  protected synchronized int peek(InetAddress addr) throws IOException
-  {
-    throw new IOException("Not Implemented Yet");
-  }
-
-  public int peekData(DatagramPacket packet)
+  protected void leave(InetAddress addr) throws IOException
   {
-    throw new InternalError
-      ("PlainDatagramSocketImpl::peekData is not implemented");
+    mcastGrp(addr, null, false);
   }
 
-  public void joinGroup(SocketAddress address, NetworkInterface netIf)
+  protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+    throws IOException
   {
-    throw new InternalError
-      ("PlainDatagramSocketImpl::joinGroup is not implemented");
+    mcastGrp(((InetSocketAddress) mcastaddr).getAddress(), netIf, true);
   }
 
-  public void leaveGroup(SocketAddress address, NetworkInterface netIf)
+  protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
+    throws IOException
   {
-    throw new InternalError
-      ("PlainDatagramSocketImpl::leaveGroup is not implemented");
+    mcastGrp(((InetSocketAddress) mcastaddr).getAddress(), netIf, false);
   }
 }
