jdk/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java
changeset 3072 a801b122142f
parent 2542 d859108aea12
child 3320 a7c037dd2e14
--- a/jdk/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jun 29 13:29:05 2009 +0100
+++ b/jdk/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jun 29 14:53:10 2009 +0100
@@ -26,6 +26,7 @@
 
 import java.net.InetAddress;
 import java.net.SocketAddress;
+import java.net.SocketException;
 import java.net.InetSocketAddress;
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -122,6 +123,8 @@
 
     private Association association;
 
+    private Set<SocketAddress> remoteAddresses = Collections.EMPTY_SET;
+
     /* -- End of fields protected by stateLock -- */
 
     private SctpResultContainer commUpResultContainer;  /* null */
@@ -142,18 +145,32 @@
      */
     public SctpChannelImpl(SelectorProvider provider, FileDescriptor fd)
          throws IOException {
+        this(provider, fd, null);
+    }
+
+    /**
+     * Constructor for sockets obtained from branching
+     */
+    public SctpChannelImpl(SelectorProvider provider,
+                           FileDescriptor fd,
+                           Association association)
+            throws IOException {
         super(provider);
         this.fd = fd;
         this.fdVal = IOUtil.fdVal(fd);
         this.state = ChannelState.CONNECTED;
         port = (Net.localAddress(fd)).getPort();
 
-        /* Receive COMM_UP */
-        ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
-        try {
-            receive(buf, null, null, true);
-        } finally {
-            Util.releaseTemporaryDirectBuffer(buf);
+        if (association != null) { /* branched */
+            this.association = association;
+        } else { /* obtained from server channel */
+            /* Receive COMM_UP */
+            ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
+            try {
+                receive(buf, null, null, true);
+            } finally {
+                Util.releaseTemporaryDirectBuffer(buf);
+            }
         }
     }
 
@@ -391,6 +408,12 @@
                             } finally {
                                 Util.releaseTemporaryDirectBuffer(buf);
                             }
+
+                            /* cache remote addresses */
+                            try {
+                                remoteAddresses = getRemoteAddresses();
+                            } catch (IOException unused) { /* swallow exception */ }
+
                             return true;
                         }
                     } else  {
@@ -414,6 +437,7 @@
                            int maxOutStreams,
                            int maxInStreams)
             throws IOException {
+        ensureOpenAndUnconnected();
         return setOption(SCTP_INIT_MAXSTREAMS, InitMaxStreams.
                 create(maxInStreams, maxOutStreams)).connect(endpoint);
 
@@ -512,6 +536,12 @@
                         } finally {
                             Util.releaseTemporaryDirectBuffer(buf);
                         }
+
+                        /* cache remote addresses */
+                        try {
+                            remoteAddresses = getRemoteAddresses();
+                        } catch (IOException unused) { /* swallow exception */ }
+
                         return true;
                     }
                 }
@@ -966,7 +996,7 @@
         int pos = src.position();
         int lim = src.limit();
 
-        assert (pos <= lim && streamNumber > 0);
+        assert (pos <= lim && streamNumber >= 0);
         int rem = (pos <= lim ? lim - pos : 0);
 
         if (src instanceof DirectBuffer)
@@ -1043,10 +1073,15 @@
         synchronized (stateLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            if (!isConnected())
+            if (!isConnected() || isShutdown)
                 return Collections.EMPTY_SET;
 
-            return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
+            try {
+                return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
+            } catch (SocketException unused) {
+                /* an open connected channel should always have remote addresses */
+                return remoteAddresses;
+            }
         }
     }