changeset 5012:bbadb6605a1c

7041778: Move SCTP implementation out of sun.nio.ch and into its own package Reviewed-by: alanb
author chegar
date Sat, 04 Feb 2012 07:29:11 +0000
parents f9fb8c4b4550
children e528a64dd21b
files make/com/sun/nio/sctp/Exportedfiles.gmk make/com/sun/nio/sctp/FILES_java.gmk make/com/sun/nio/sctp/Makefile make/com/sun/nio/sctp/mapfile-vers src/share/classes/com/sun/nio/sctp/MessageInfo.java src/share/classes/com/sun/nio/sctp/SctpChannel.java src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java src/share/classes/com/sun/nio/sctp/SctpServerChannel.java src/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java src/share/classes/sun/nio/ch/IOStatus.java src/share/classes/sun/nio/ch/IOUtil.java src/share/classes/sun/nio/ch/Net.java src/share/classes/sun/nio/ch/SctpMessageInfoImpl.java src/share/classes/sun/nio/ch/SctpStdSocketOption.java src/share/classes/sun/nio/ch/SelChImpl.java src/share/classes/sun/nio/ch/SelectionKeyImpl.java src/share/classes/sun/nio/ch/SelectorImpl.java src/share/classes/sun/nio/ch/Util.java src/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java src/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java src/solaris/classes/sun/nio/ch/NativeThread.java src/solaris/classes/sun/nio/ch/PollArrayWrapper.java src/solaris/classes/sun/nio/ch/SctpAssocChange.java src/solaris/classes/sun/nio/ch/SctpAssociationImpl.java src/solaris/classes/sun/nio/ch/SctpChannelImpl.java src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java src/solaris/classes/sun/nio/ch/SctpNet.java src/solaris/classes/sun/nio/ch/SctpNotification.java src/solaris/classes/sun/nio/ch/SctpPeerAddrChange.java src/solaris/classes/sun/nio/ch/SctpResultContainer.java src/solaris/classes/sun/nio/ch/SctpSendFailed.java src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java src/solaris/classes/sun/nio/ch/SctpShutdown.java src/solaris/classes/sun/nio/ch/sctp/AssociationChange.java src/solaris/classes/sun/nio/ch/sctp/AssociationImpl.java src/solaris/classes/sun/nio/ch/sctp/PeerAddrChange.java src/solaris/classes/sun/nio/ch/sctp/ResultContainer.java src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java src/solaris/classes/sun/nio/ch/sctp/SctpNet.java src/solaris/classes/sun/nio/ch/sctp/SctpNotification.java src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java src/solaris/classes/sun/nio/ch/sctp/SendFailed.java src/solaris/classes/sun/nio/ch/sctp/Shutdown.java src/solaris/native/sun/nio/ch/Sctp.h src/solaris/native/sun/nio/ch/SctpChannelImpl.c src/solaris/native/sun/nio/ch/SctpNet.c src/solaris/native/sun/nio/ch/SctpServerChannelImpl.c src/solaris/native/sun/nio/ch/sctp/Sctp.h src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c src/solaris/native/sun/nio/ch/sctp/SctpNet.c src/solaris/native/sun/nio/ch/sctp/SctpServerChannelImpl.c src/windows/classes/sun/nio/ch/SctpChannelImpl.java src/windows/classes/sun/nio/ch/SctpMultiChannelImpl.java src/windows/classes/sun/nio/ch/SctpServerChannelImpl.java src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java src/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java src/windows/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java src/windows/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java
diffstat 63 files changed, 5971 insertions(+), 5937 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/sun/nio/sctp/Exportedfiles.gmk	Mon Jan 30 11:44:45 2012 +0000
+++ b/make/com/sun/nio/sctp/Exportedfiles.gmk	Sat Feb 04 07:29:11 2012 +0000
@@ -29,11 +29,11 @@
 
 ifneq ($(PLATFORM), windows)
 FILES_export = \
-    sun/nio/ch/SctpAssocChange.java \
-    sun/nio/ch/SctpChannelImpl.java \
-    sun/nio/ch/SctpNet.java \
-    sun/nio/ch/SctpPeerAddrChange.java \
-    sun/nio/ch/SctpResultContainer.java \
-    sun/nio/ch/SctpServerChannelImpl.java \
-    sun/nio/ch/SctpStdSocketOption.java
+    sun/nio/ch/sctp/AssociationChange.java \
+    sun/nio/ch/sctp/SctpChannelImpl.java \
+    sun/nio/ch/sctp/SctpNet.java \
+    sun/nio/ch/sctp/PeerAddrChange.java \
+    sun/nio/ch/sctp/ResultContainer.java \
+    sun/nio/ch/sctp/SctpServerChannelImpl.java \
+    sun/nio/ch/sctp/SctpStdSocketOption.java
 endif
--- a/make/com/sun/nio/sctp/FILES_java.gmk	Mon Jan 30 11:44:45 2012 +0000
+++ b/make/com/sun/nio/sctp/FILES_java.gmk	Sat Feb 04 07:29:11 2012 +0000
@@ -42,25 +42,25 @@
 	com/sun/nio/sctp/SendFailedNotification.java \
 	com/sun/nio/sctp/ShutdownNotification.java \
 	\
-	sun/nio/ch/SctpMessageInfoImpl.java \
-	sun/nio/ch/SctpStdSocketOption.java
+	sun/nio/ch/sctp/MessageInfoImpl.java \
+	sun/nio/ch/sctp/SctpStdSocketOption.java
 
 ifneq ($(PLATFORM), windows)
 FILES_java += \
-	sun/nio/ch/SctpAssocChange.java \
-	sun/nio/ch/SctpAssociationImpl.java \
-	sun/nio/ch/SctpChannelImpl.java \
-	sun/nio/ch/SctpMultiChannelImpl.java \
-	sun/nio/ch/SctpNet.java \
-	sun/nio/ch/SctpNotification.java \
-	sun/nio/ch/SctpPeerAddrChange.java \
-	sun/nio/ch/SctpResultContainer.java \
-	sun/nio/ch/SctpSendFailed.java \
-	sun/nio/ch/SctpServerChannelImpl.java \
-	sun/nio/ch/SctpShutdown.java
+	sun/nio/ch/sctp/AssociationChange.java \
+	sun/nio/ch/sctp/AssociationImpl.java \
+	sun/nio/ch/sctp/PeerAddrChange.java \
+	sun/nio/ch/sctp/ResultContainer.java \
+	sun/nio/ch/sctp/SctpChannelImpl.java \
+	sun/nio/ch/sctp/SctpMultiChannelImpl.java \
+	sun/nio/ch/sctp/SctpNet.java \
+	sun/nio/ch/sctp/SctpNotification.java \
+	sun/nio/ch/sctp/SctpServerChannelImpl.java \
+	sun/nio/ch/sctp/SendFailed.java \
+	sun/nio/ch/sctp/Shutdown.java
 else
 FILES_java += \
-	sun/nio/ch/SctpChannelImpl.java \
-	sun/nio/ch/SctpMultiChannelImpl.java \
-	sun/nio/ch/SctpServerChannelImpl.java
+	sun/nio/ch/sctp/SctpChannelImpl.java \
+	sun/nio/ch/sctp/SctpMultiChannelImpl.java \
+	sun/nio/ch/sctp/SctpServerChannelImpl.java
 endif
--- a/make/com/sun/nio/sctp/Makefile	Mon Jan 30 11:44:45 2012 +0000
+++ b/make/com/sun/nio/sctp/Makefile	Sat Feb 04 07:29:11 2012 +0000
@@ -47,14 +47,16 @@
 #
 # Find platform-specific C source files
 #
-vpath %.c $(PLATFORM_SRC)/native/sun/nio/ch
+vpath %.c $(PLATFORM_SRC)/native/sun/nio/ch/sctp
 
 #
 # Include nio.h, net_util.h, sun_nio_ch_IOStatus.h, etc
 #
 OTHER_INCLUDES += \
   -I$(SHARE_SRC)/native/sun/nio/ch \
+  -I$(SHARE_SRC)/native/sun/nio/ch/sctp \
   -I$(SHARE_SRC)/native/java/net \
+  -I$(PLATFORM_SRC)/native/sun/nio/ch \
   -I$(PLATFORM_SRC)/native/java/net \
   -I$(CLASSHDRDIR)/../../../../java/java.nio/nio/CClassHeaders
 
@@ -75,5 +77,5 @@
 
 clean clobber::
 	$(RM) -r $(CLASSDESTDIR)/com/sun/nio/sctp
-	$(RM) -r $(CLASSDESTDIR)/sun/nio/ch
+	$(RM) -r $(CLASSDESTDIR)/sun/nio/ch/sctp
 
--- a/make/com/sun/nio/sctp/mapfile-vers	Mon Jan 30 11:44:45 2012 +0000
+++ b/make/com/sun/nio/sctp/mapfile-vers	Sat Feb 04 07:29:11 2012 +0000
@@ -25,30 +25,30 @@
 
 SUNWprivate_1.1 {
 	global:
-		Java_sun_nio_ch_SctpNet_init;
-		Java_sun_nio_ch_SctpNet_socket0;
-		Java_sun_nio_ch_SctpNet_bindx;
-		Java_sun_nio_ch_SctpNet_branch0;
-		Java_sun_nio_ch_SctpNet_listen0;
-		Java_sun_nio_ch_SctpNet_connect0;
-		Java_sun_nio_ch_SctpNet_close0;
-		Java_sun_nio_ch_SctpNet_preClose0;
-		Java_sun_nio_ch_SctpNet_getLocalAddresses0;
-		Java_sun_nio_ch_SctpNet_getRemoteAddresses0;
-		Java_sun_nio_ch_SctpNet_getPrimAddrOption0;
-		Java_sun_nio_ch_SctpNet_setPrimAddrOption0;
-		Java_sun_nio_ch_SctpNet_setPeerPrimAddrOption0;
-		Java_sun_nio_ch_SctpNet_getInitMsgOption0;
-		Java_sun_nio_ch_SctpNet_setInitMsgOption0;
-		Java_sun_nio_ch_SctpNet_getIntOption0;
-		Java_sun_nio_ch_SctpNet_setIntOption0;
-		Java_sun_nio_ch_SctpNet_shutdown0;
-		Java_sun_nio_ch_SctpChannelImpl_initIDs;
-		Java_sun_nio_ch_SctpChannelImpl_checkConnect;
-		Java_sun_nio_ch_SctpChannelImpl_receive0;
-		Java_sun_nio_ch_SctpChannelImpl_send0;
-		Java_sun_nio_ch_SctpServerChannelImpl_initIDs;
-		Java_sun_nio_ch_SctpServerChannelImpl_accept0;
+		Java_sun_nio_ch_sctp_SctpNet_init;
+		Java_sun_nio_ch_sctp_SctpNet_socket0;
+		Java_sun_nio_ch_sctp_SctpNet_bindx;
+		Java_sun_nio_ch_sctp_SctpNet_branch0;
+		Java_sun_nio_ch_sctp_SctpNet_listen0;
+		Java_sun_nio_ch_sctp_SctpNet_connect0;
+		Java_sun_nio_ch_sctp_SctpNet_close0;
+		Java_sun_nio_ch_sctp_SctpNet_preClose0;
+		Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0;
+		Java_sun_nio_ch_sctp_SctpNet_getRemoteAddresses0;
+		Java_sun_nio_ch_sctp_SctpNet_getPrimAddrOption0;
+		Java_sun_nio_ch_sctp_SctpNet_setPrimAddrOption0;
+		Java_sun_nio_ch_sctp_SctpNet_setPeerPrimAddrOption0;
+		Java_sun_nio_ch_sctp_SctpNet_getInitMsgOption0;
+		Java_sun_nio_ch_sctp_SctpNet_setInitMsgOption0;
+		Java_sun_nio_ch_sctp_SctpNet_getIntOption0;
+		Java_sun_nio_ch_sctp_SctpNet_setIntOption0;
+		Java_sun_nio_ch_sctp_SctpNet_shutdown0;
+		Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs;
+		Java_sun_nio_ch_sctp_SctpChannelImpl_checkConnect;
+		Java_sun_nio_ch_sctp_SctpChannelImpl_receive0;
+		Java_sun_nio_ch_sctp_SctpChannelImpl_send0;
+		Java_sun_nio_ch_sctp_SctpServerChannelImpl_initIDs;
+		Java_sun_nio_ch_sctp_SctpServerChannelImpl_accept0;
                 JNI_OnLoad;
 	local:
 		*;
--- a/src/share/classes/com/sun/nio/sctp/MessageInfo.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/com/sun/nio/sctp/MessageInfo.java	Sat Feb 04 07:29:11 2012 +0000
@@ -94,7 +94,7 @@
         if (streamNumber < 0 || streamNumber > 65536)
             throw new IllegalArgumentException("Invalid stream number");
 
-        return new sun.nio.ch.SctpMessageInfoImpl(null, address, streamNumber);
+        return new sun.nio.ch.sctp.MessageInfoImpl(null, address, streamNumber);
     }
     /**
      * Creates a {@code MessageInfo} instance suitable for use when
@@ -133,8 +133,8 @@
         if (streamNumber < 0 || streamNumber > 65536)
             throw new IllegalArgumentException("Invalid stream number");
 
-        return new sun.nio.ch.SctpMessageInfoImpl(association, address,
-                streamNumber);
+        return new sun.nio.ch.sctp.MessageInfoImpl(association,
+                                                   address, streamNumber);
     }
 
     /**
--- a/src/share/classes/com/sun/nio/sctp/SctpChannel.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/com/sun/nio/sctp/SctpChannel.java	Sat Feb 04 07:29:11 2012 +0000
@@ -162,7 +162,7 @@
      */
     public static SctpChannel open() throws
         IOException {
-        return new sun.nio.ch.SctpChannelImpl((SelectorProvider)null);
+        return new sun.nio.ch.sctp.SctpChannelImpl((SelectorProvider)null);
     }
 
     /**
--- a/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java	Sat Feb 04 07:29:11 2012 +0000
@@ -162,7 +162,7 @@
      */
     public static SctpMultiChannel open() throws
         IOException {
-        return new sun.nio.ch.SctpMultiChannelImpl((SelectorProvider)null);
+        return new sun.nio.ch.sctp.SctpMultiChannelImpl((SelectorProvider)null);
     }
 
     /**
--- a/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java	Sat Feb 04 07:29:11 2012 +0000
@@ -98,7 +98,7 @@
      */
     public static SctpServerChannel open() throws
         IOException {
-        return new sun.nio.ch.SctpServerChannelImpl((SelectorProvider)null);
+        return new sun.nio.ch.sctp.SctpServerChannelImpl((SelectorProvider)null);
     }
 
     /**
--- a/src/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java	Sat Feb 04 07:29:11 2012 +0000
@@ -25,7 +25,7 @@
 package com.sun.nio.sctp;
 
 import java.net.SocketAddress;
-import sun.nio.ch.SctpStdSocketOption;
+import sun.nio.ch.sctp.SctpStdSocketOption;
 
 /**
  * SCTP channels supports the socket options defined by this class
@@ -50,7 +50,7 @@
      */
     public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS = new
         SctpStdSocketOption<Boolean>("SCTP_DISABLE_FRAGMENTS", Boolean.class,
-        sun.nio.ch.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
+        sun.nio.ch.sctp.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
 
     /**
      * Enables or disables explicit message completion.
@@ -69,7 +69,7 @@
      */
     public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE = new
         SctpStdSocketOption<Boolean>("SCTP_EXPLICIT_COMPLETE", Boolean.class,
-        sun.nio.ch.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
+        sun.nio.ch.sctp.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
 
     /**
      * Fragmented interleave controls how the presentation of messages occur
@@ -120,7 +120,7 @@
     public static final SctpSocketOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
             new SctpStdSocketOption<Integer>("SCTP_FRAGMENT_INTERLEAVE",
                   Integer.class,
-                  sun.nio.ch.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
+                  sun.nio.ch.sctp.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
 
     /**
      * The maximum number of streams requested by the local endpoint during
@@ -171,7 +171,7 @@
      */
     public static final SctpSocketOption<Boolean> SCTP_NODELAY =
         new SctpStdSocketOption<Boolean>("SCTP_NODELAY", Boolean.class,
-        sun.nio.ch.SctpStdSocketOption.SCTP_NODELAY);
+        sun.nio.ch.sctp.SctpStdSocketOption.SCTP_NODELAY);
 
     /**
      * Requests that the local SCTP stack use the given peer address as
@@ -246,7 +246,7 @@
      */
     public static final SctpSocketOption<Integer> SO_SNDBUF =
         new SctpStdSocketOption<Integer>("SO_SNDBUF", Integer.class,
-        sun.nio.ch.SctpStdSocketOption.SO_SNDBUF);
+        sun.nio.ch.sctp.SctpStdSocketOption.SO_SNDBUF);
 
     /**
      * The size of the socket receive buffer.
@@ -273,7 +273,7 @@
      */
     public static final SctpSocketOption<Integer> SO_RCVBUF =
         new SctpStdSocketOption<Integer>("SO_RCVBUF", Integer.class,
-        sun.nio.ch.SctpStdSocketOption.SO_RCVBUF);
+        sun.nio.ch.sctp.SctpStdSocketOption.SO_RCVBUF);
 
     /**
      * Linger on close if data is present.
@@ -304,7 +304,7 @@
      */
     public static final SctpSocketOption<Integer> SO_LINGER =
         new SctpStdSocketOption<Integer>("SO_LINGER", Integer.class,
-        sun.nio.ch.SctpStdSocketOption.SO_LINGER);
+        sun.nio.ch.sctp.SctpStdSocketOption.SO_LINGER);
 
     /**
      * This class is used to set the maximum number of inbound/outbound streams
--- a/src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Sat Feb 04 07:29:11 2012 +0000
@@ -35,15 +35,15 @@
  * @since 1.4
  */
 
-abstract class AbstractPollArrayWrapper {
+public abstract class AbstractPollArrayWrapper {
 
     // Event masks
-    static final short POLLIN       = 0x0001;
-    static final short POLLOUT      = 0x0004;
-    static final short POLLERR      = 0x0008;
-    static final short POLLHUP      = 0x0010;
-    static final short POLLNVAL     = 0x0020;
-    static final short POLLREMOVE   = 0x0800;
+    public static final short POLLIN       = 0x0001;
+    public static final short POLLOUT      = 0x0004;
+    public static final short POLLERR      = 0x0008;
+    public static final short POLLHUP      = 0x0010;
+    public static final short POLLNVAL     = 0x0020;
+    public static final short POLLREMOVE   = 0x0800;
 
     // Miscellaneous constants
     static final short SIZE_POLLFD   = 8;
--- a/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -67,7 +67,7 @@
         this.channelOffset = offset;
     }
 
-    void putEventOps(SelectionKeyImpl sk, int ops) {
+    public void putEventOps(SelectionKeyImpl sk, int ops) {
         synchronized (closeLock) {
             if (closed)
                 throw new ClosedSelectorException();
--- a/src/share/classes/sun/nio/ch/IOStatus.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/IOStatus.java	Sat Feb 04 07:29:11 2012 +0000
@@ -28,16 +28,16 @@
 
 // Constants for reporting I/O status
 
-final class IOStatus {
+public final class IOStatus {
 
     private IOStatus() { }
 
-    static final int EOF = -1;              // End of file
-    static final int UNAVAILABLE = -2;      // Nothing available (non-blocking)
-    static final int INTERRUPTED = -3;      // System call interrupted
-    static final int UNSUPPORTED = -4;      // Operation not supported
-    static final int THROWN = -5;           // Exception thrown in JNI code
-    static final int UNSUPPORTED_CASE = -6; // This case not supported
+    public static final int EOF = -1;              // End of file
+    public static final int UNAVAILABLE = -2;      // Nothing available (non-blocking)
+    public static final int INTERRUPTED = -3;      // System call interrupted
+    public static final int UNSUPPORTED = -4;      // Operation not supported
+    public static final int THROWN = -5;           // Exception thrown in JNI code
+    public static final int UNSUPPORTED_CASE = -6; // This case not supported
 
     // The following two methods are for use in try/finally blocks where a
     // status value needs to be normalized before being returned to the invoker
@@ -55,28 +55,28 @@
     //     }
     //
 
-    static int normalize(int n) {
+    public static int normalize(int n) {
         if (n == UNAVAILABLE)
             return 0;
         return n;
     }
 
-    static boolean check(int n) {
+    public static boolean check(int n) {
         return (n >= UNAVAILABLE);
     }
 
-    static long normalize(long n) {
+    public static long normalize(long n) {
         if (n == UNAVAILABLE)
             return 0;
         return n;
     }
 
-    static boolean check(long n) {
+    public static boolean check(long n) {
         return (n >= UNAVAILABLE);
     }
 
     // Return true iff n is not one of the IOStatus values
-    static boolean checkAll(long n) {
+    public static boolean checkAll(long n) {
         return ((n > EOF) || (n < UNSUPPORTED_CASE));
     }
 
--- a/src/share/classes/sun/nio/ch/IOUtil.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/IOUtil.java	Sat Feb 04 07:29:11 2012 +0000
@@ -34,7 +34,7 @@
  * File-descriptor based I/O utilities that are shared by NIO classes.
  */
 
-class IOUtil {
+public class IOUtil {
 
     private IOUtil() { }                // No instantiation
 
@@ -309,7 +309,7 @@
         }
     }
 
-    static FileDescriptor newFD(int i) {
+    public static FileDescriptor newFD(int i) {
         FileDescriptor fd = new FileDescriptor();
         setfdVal(fd, i);
         return fd;
@@ -326,10 +326,11 @@
 
     static native boolean drain(int fd) throws IOException;
 
-    static native void configureBlocking(FileDescriptor fd, boolean blocking)
+    public static native void configureBlocking(FileDescriptor fd,
+                                                boolean blocking)
         throws IOException;
 
-    static native int fdVal(FileDescriptor fd);
+    public static native int fdVal(FileDescriptor fd);
 
     static native void setfdVal(FileDescriptor fd, int value);
 
--- a/src/share/classes/sun/nio/ch/Net.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/Net.java	Sat Feb 04 07:29:11 2012 +0000
@@ -33,7 +33,7 @@
 import java.security.PrivilegedAction;
 
 
-class Net {                                             // package-private
+public class Net {
 
     private Net() { }
 
@@ -75,7 +75,7 @@
         return canJoin6WithIPv4Group0();
     }
 
-    static InetSocketAddress checkAddress(SocketAddress sa) {
+    public static InetSocketAddress checkAddress(SocketAddress sa) {
         if (sa == null)
             throw new NullPointerException();
         if (!(sa instanceof InetSocketAddress))
@@ -330,7 +330,7 @@
     // Due to oddities SO_REUSEADDR on windows reuse is ignored
     private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
 
-    static void bind(FileDescriptor fd, InetAddress addr, int port)
+    public static void bind(FileDescriptor fd, InetAddress addr, int port)
         throws IOException
     {
         bind(UNSPEC, fd, addr, port);
@@ -383,7 +383,7 @@
     private static native InetAddress localInetAddress(FileDescriptor fd)
         throws IOException;
 
-    static InetSocketAddress localAddress(FileDescriptor fd)
+    public static InetSocketAddress localAddress(FileDescriptor fd)
         throws IOException
     {
         return new InetSocketAddress(localInetAddress(fd), localPort(fd));
--- a/src/share/classes/sun/nio/ch/SctpMessageInfoImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.net.SocketAddress;
-import com.sun.nio.sctp.MessageInfo;
-import com.sun.nio.sctp.Association;
-
-/**
- * An implementation of a MessageInfo.
- */
-public class SctpMessageInfoImpl extends MessageInfo {
-    private final SocketAddress address;
-    private final int bytes;          /* 0 */
-
-    private Association association;
-    private int assocId;
-    private int streamNumber;
-    private boolean complete = true;
-    private boolean unordered;  /* false */
-    private long timeToLive;    /* 0L */
-    private int ppid;           /* 0 */
-
-    public SctpMessageInfoImpl(Association association,
-                               SocketAddress address,
-                               int streamNumber) {
-        this.association = association;
-        this.address = address;
-        this.streamNumber = streamNumber;
-        bytes = 0;
-    }
-
-    /* Invoked from native */
-    private SctpMessageInfoImpl(int assocId,
-                                SocketAddress address,
-                                int bytes,
-                                int streamNumber,
-                                boolean complete,
-                                boolean unordered,
-                                int ppid) {
-        this.assocId = assocId;
-        this.address = address;
-        this.bytes = bytes;
-        this.streamNumber = streamNumber;
-        this.complete = complete;
-        this.unordered = unordered;
-        this.ppid = ppid;
-    }
-
-    @Override
-    public Association association() {
-        return association;
-    }
-
-    /**
-     * SctpMessageInfoImpl instances created from native will need to have their
-     * association set from the channel.
-     */
-    void setAssociation(Association association) {
-        this.association = association;
-    }
-
-    int associationID() {
-        return assocId;
-    }
-
-    @Override
-    public SocketAddress address() {
-        return address;
-    }
-
-    @Override
-    public int bytes() {
-        return bytes;
-    }
-
-    @Override
-    public int streamNumber() {
-        return streamNumber;
-    }
-
-    @Override
-    public MessageInfo streamNumber(int streamNumber) {
-        if (streamNumber < 0 || streamNumber > 65536)
-            throw new IllegalArgumentException("Invalid stream number");
-
-        this.streamNumber = streamNumber;
-        return this;
-    }
-
-    @Override
-    public int payloadProtocolID() {
-        return ppid;
-    }
-
-    @Override
-    public MessageInfo payloadProtocolID(int ppid) {
-        this.ppid = ppid;
-        return this;
-    }
-
-    @Override
-    public boolean isComplete() {
-        return complete;
-    }
-
-    @Override
-    public MessageInfo complete(boolean complete) {
-        this.complete = complete;
-        return this;
-    }
-
-    @Override
-    public boolean isUnordered() {
-        return unordered;
-    }
-
-    @Override
-    public MessageInfo unordered(boolean unordered) {
-        this.unordered = unordered;
-        return this;
-    }
-
-    @Override
-    public long timeToLive() {
-        return timeToLive;
-    }
-
-    @Override
-    public MessageInfo timeToLive(long millis) {
-        timeToLive = millis;
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder(super.toString());
-        sb.append( "[Address: ").append(address)
-          .append(", Association: ").append(association)
-          .append(", Assoc ID: ").append(assocId)
-          .append(", Bytes: ").append(bytes)
-          .append(", Stream Number: ").append(streamNumber)
-          .append(", Complete: ").append(complete)
-          .append(", isUnordered: ").append(unordered)
-          .append("]");
-        return sb.toString();
-    }
-}
--- a/src/share/classes/sun/nio/ch/SctpStdSocketOption.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import com.sun.nio.sctp.SctpSocketOption;
-
-public class SctpStdSocketOption<T>
-    implements SctpSocketOption<T>
-{
-    /* for native mapping of int options */
-    public static final int SCTP_DISABLE_FRAGMENTS = 1;
-    public static final int SCTP_EXPLICIT_COMPLETE = 2;
-    public static final int SCTP_FRAGMENT_INTERLEAVE = 3;
-    public static final int SCTP_NODELAY = 4;
-    public static final int SO_SNDBUF = 5;
-    public static final int SO_RCVBUF = 6;
-    public static final int SO_LINGER = 7;
-
-    private final String name;
-    private final Class<T> type;
-
-    /* for native mapping of int options */
-    private int constValue;
-
-    public SctpStdSocketOption(String name, Class<T> type) {
-        this.name = name;
-        this.type = type;
-    }
-
-    public SctpStdSocketOption(String name, Class<T> type, int constValue) {
-        this.name = name;
-        this.type = type;
-        this.constValue = constValue;
-    }
-
-    @Override
-    public String name() {
-        return name;
-    }
-
-    @Override
-    public Class<T> type() {
-        return type;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    int constValue() {
-        return constValue;
-    }
-}
--- a/src/share/classes/sun/nio/ch/SelChImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/SelChImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -36,7 +36,7 @@
  * @since 1.4
  */
 
-interface SelChImpl extends Channel {
+public interface SelChImpl extends Channel {
 
     FileDescriptor getFD();
 
--- a/src/share/classes/sun/nio/ch/SelectionKeyImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/SelectionKeyImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -34,12 +34,12 @@
  * An implementation of SelectionKey for Solaris.
  */
 
-class SelectionKeyImpl
+public class SelectionKeyImpl
     extends AbstractSelectionKey
 {
 
     final SelChImpl channel;                            // package-private
-    final SelectorImpl selector;                        // package-private
+    public final SelectorImpl selector;
 
     // Index for a pollfd array in Selector that this key is registered with
     private int index;
@@ -91,15 +91,15 @@
     // The nio versions of these operations do not care if a key
     // has been invalidated. They are for internal use by nio code.
 
-    void nioReadyOps(int ops) {                 // package-private
+    public void nioReadyOps(int ops) {
         readyOps = ops;
     }
 
-    int nioReadyOps() {                         // package-private
+    public int nioReadyOps() {
         return readyOps;
     }
 
-    SelectionKey nioInterestOps(int ops) {      // package-private
+    public SelectionKey nioInterestOps(int ops) {
         if ((ops & ~channel().validOps()) != 0)
             throw new IllegalArgumentException();
         channel.translateAndSetInterestOps(ops, this);
@@ -107,7 +107,7 @@
         return this;
     }
 
-    int nioInterestOps() {                       // package-private
+    public int nioInterestOps() {
         return interestOps;
     }
 
--- a/src/share/classes/sun/nio/ch/SelectorImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/SelectorImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -36,7 +36,7 @@
  * Base Selector implementation class.
  */
 
-abstract class SelectorImpl
+public abstract class SelectorImpl
     extends AbstractSelector
 {
 
@@ -118,7 +118,7 @@
 
     protected abstract void implClose() throws IOException;
 
-    void putEventOps(SelectionKeyImpl sk, int ops) { }
+    public void putEventOps(SelectionKeyImpl sk, int ops) { }
 
     protected final SelectionKey register(AbstractSelectableChannel ch,
                                           int ops,
--- a/src/share/classes/sun/nio/ch/Util.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/share/classes/sun/nio/ch/Util.java	Sat Feb 04 07:29:11 2012 +0000
@@ -40,7 +40,7 @@
 import sun.security.action.GetPropertyAction;
 
 
-class Util {
+public class Util {
 
     // -- Caches --
 
@@ -158,7 +158,7 @@
     /**
      * Returns a temporary buffer of at least the given size
      */
-    static ByteBuffer getTemporaryDirectBuffer(int size) {
+    public static ByteBuffer getTemporaryDirectBuffer(int size) {
         BufferCache cache = bufferCache.get();
         ByteBuffer buf = cache.get(size);
         if (buf != null) {
@@ -178,7 +178,7 @@
     /**
      * Releases a temporary buffer by returning to the cache or freeing it.
      */
-    static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
+    public static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
         offerFirstTemporaryDirectBuffer(buf);
     }
 
@@ -467,7 +467,7 @@
 
     private static boolean loaded = false;
 
-    static void load() {
+    public static void load() {
         synchronized (Util.class) {
             if (loaded)
                 return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.net.SocketAddress;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.Association;
+
+/**
+ * An implementation of a MessageInfo.
+ */
+public class MessageInfoImpl extends MessageInfo {
+    private final SocketAddress address;
+    private final int bytes;          /* 0 */
+
+    private Association association;
+    private int assocId;
+    private int streamNumber;
+    private boolean complete = true;
+    private boolean unordered;  /* false */
+    private long timeToLive;    /* 0L */
+    private int ppid;           /* 0 */
+
+    public MessageInfoImpl(Association association,
+                           SocketAddress address,
+                           int streamNumber) {
+        this.association = association;
+        this.address = address;
+        this.streamNumber = streamNumber;
+        bytes = 0;
+    }
+
+    /* Invoked from native */
+    private MessageInfoImpl(int assocId,
+                            SocketAddress address,
+                            int bytes,
+                            int streamNumber,
+                            boolean complete,
+                            boolean unordered,
+                            int ppid) {
+        this.assocId = assocId;
+        this.address = address;
+        this.bytes = bytes;
+        this.streamNumber = streamNumber;
+        this.complete = complete;
+        this.unordered = unordered;
+        this.ppid = ppid;
+    }
+
+    @Override
+    public Association association() {
+        return association;
+    }
+
+    /**
+     * MessageInfoImpl instances created from native will need to have their
+     * association set from the channel.
+     */
+    void setAssociation(Association association) {
+        this.association = association;
+    }
+
+    int associationID() {
+        return assocId;
+    }
+
+    @Override
+    public SocketAddress address() {
+        return address;
+    }
+
+    @Override
+    public int bytes() {
+        return bytes;
+    }
+
+    @Override
+    public int streamNumber() {
+        return streamNumber;
+    }
+
+    @Override
+    public MessageInfo streamNumber(int streamNumber) {
+        if (streamNumber < 0 || streamNumber > 65536)
+            throw new IllegalArgumentException("Invalid stream number");
+
+        this.streamNumber = streamNumber;
+        return this;
+    }
+
+    @Override
+    public int payloadProtocolID() {
+        return ppid;
+    }
+
+    @Override
+    public MessageInfo payloadProtocolID(int ppid) {
+        this.ppid = ppid;
+        return this;
+    }
+
+    @Override
+    public boolean isComplete() {
+        return complete;
+    }
+
+    @Override
+    public MessageInfo complete(boolean complete) {
+        this.complete = complete;
+        return this;
+    }
+
+    @Override
+    public boolean isUnordered() {
+        return unordered;
+    }
+
+    @Override
+    public MessageInfo unordered(boolean unordered) {
+        this.unordered = unordered;
+        return this;
+    }
+
+    @Override
+    public long timeToLive() {
+        return timeToLive;
+    }
+
+    @Override
+    public MessageInfo timeToLive(long millis) {
+        timeToLive = millis;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(super.toString());
+        sb.append( "[Address: ").append(address)
+          .append(", Association: ").append(association)
+          .append(", Assoc ID: ").append(assocId)
+          .append(", Bytes: ").append(bytes)
+          .append(", Stream Number: ").append(streamNumber)
+          .append(", Complete: ").append(complete)
+          .append(", isUnordered: ").append(unordered)
+          .append("]");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import com.sun.nio.sctp.SctpSocketOption;
+
+public class SctpStdSocketOption<T>
+    implements SctpSocketOption<T>
+{
+    /* for native mapping of int options */
+    public static final int SCTP_DISABLE_FRAGMENTS = 1;
+    public static final int SCTP_EXPLICIT_COMPLETE = 2;
+    public static final int SCTP_FRAGMENT_INTERLEAVE = 3;
+    public static final int SCTP_NODELAY = 4;
+    public static final int SO_SNDBUF = 5;
+    public static final int SO_RCVBUF = 6;
+    public static final int SO_LINGER = 7;
+
+    private final String name;
+    private final Class<T> type;
+
+    /* for native mapping of int options */
+    private int constValue;
+
+    public SctpStdSocketOption(String name, Class<T> type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    public SctpStdSocketOption(String name, Class<T> type, int constValue) {
+        this.name = name;
+        this.type = type;
+        this.constValue = constValue;
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public Class<T> type() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    int constValue() {
+        return constValue;
+    }
+}
--- a/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -180,7 +180,7 @@
             ((SelChImpl)selch).kill();
     }
 
-    void putEventOps(SelectionKeyImpl sk, int ops) {
+    public void putEventOps(SelectionKeyImpl sk, int ops) {
         if (closed)
             throw new ClosedSelectorException();
         int fd = IOUtil.fdVal(sk.channel.getFD());
--- a/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -181,7 +181,7 @@
             ((SelChImpl)selch).kill();
     }
 
-    void putEventOps(SelectionKeyImpl sk, int ops) {
+    public void putEventOps(SelectionKeyImpl sk, int ops) {
         if (closed)
             throw new ClosedSelectorException();
         pollWrapper.setInterest(sk.channel, ops);
--- a/src/solaris/classes/sun/nio/ch/NativeThread.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/solaris/classes/sun/nio/ch/NativeThread.java	Sat Feb 04 07:29:11 2012 +0000
@@ -37,21 +37,21 @@
 // always returns -1 and the signal(long) method has no effect.
 
 
-class NativeThread {
+public class NativeThread {
 
     // Returns an opaque token representing the native thread underlying the
     // invoking Java thread.  On systems that do not require signalling, this
     // method always returns -1.
     //
-    static native long current();
+    public static native long current();
 
     // Signals the given native thread so as to release it from a blocking I/O
     // operation.  On systems that do not require signalling, this method has
     // no effect.
     //
-    static native void signal(long nt);
+    public static native void signal(long nt);
 
-    static native void init();
+    private static native void init();
 
     static {
         Util.load();
--- a/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java	Mon Jan 30 11:44:45 2012 +0000
+++ b/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java	Sat Feb 04 07:29:11 2012 +0000
@@ -41,9 +41,9 @@
  * @since 1.4
  */
 
-class PollArrayWrapper extends AbstractPollArrayWrapper {
+public class PollArrayWrapper extends AbstractPollArrayWrapper {
 
-    static final short POLLCONN = POLLOUT;
+    public static final short POLLCONN = POLLOUT;
 
     // File descriptor to write for interrupt
     int interruptFD;
--- a/src/solaris/classes/sun/nio/ch/SctpAssocChange.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.AssociationChangeNotification;
-
-/**
- * An implementation of AssociationChangeNotification
- */
-public class SctpAssocChange extends AssociationChangeNotification
-    implements SctpNotification
-{
-    /* static final ints so that they can be referenced from native */
-    private final static int SCTP_COMM_UP = 1;
-    private final static int SCTP_COMM_LOST = 2;
-    private final static int SCTP_RESTART = 3;
-    private final static int SCTP_SHUTDOWN = 4;
-    private final static int SCTP_CANT_START = 5;
-
-    private Association association;
-
-    /* assocId is used to lookup the association before the notification is
-     * returned to user code */
-    private int assocId;
-    private AssocChangeEvent event;
-    private int maxOutStreams;
-    private int maxInStreams;
-
-    /* Invoked from native */
-    private SctpAssocChange(int assocId,
-                            int intEvent,
-                            int maxOutStreams,
-                            int maxInStreams) {
-        switch (intEvent) {
-            case SCTP_COMM_UP :
-                this.event = AssocChangeEvent.COMM_UP;
-                break;
-            case SCTP_COMM_LOST :
-                this.event = AssocChangeEvent.COMM_LOST;
-                break;
-            case SCTP_RESTART :
-                this.event = AssocChangeEvent.RESTART;
-                break;
-            case SCTP_SHUTDOWN :
-                this.event = AssocChangeEvent.SHUTDOWN;
-                break;
-            case SCTP_CANT_START :
-                this.event = AssocChangeEvent.CANT_START;
-                break;
-            default :
-                throw new AssertionError(
-                      "Unknown Association Change Event type: " + intEvent);
-        }
-
-        this.assocId = assocId;
-        this.maxOutStreams = maxOutStreams;
-        this.maxInStreams = maxInStreams;
-    }
-
-    @Override
-    public int assocId() {
-        return assocId;
-    }
-
-    @Override
-    public void setAssociation(Association association) {
-        this.association = association;
-    }
-
-    @Override
-    public Association association() {
-        assert association != null;
-        return association;
-    }
-
-    @Override
-    public AssocChangeEvent event() {
-        return event;
-    }
-
-    int maxOutStreams() {
-        return maxOutStreams;
-    }
-
-    int maxInStreams() {
-        return maxInStreams;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(super.toString()).append(" [");
-        sb.append("Association:").append(association);
-        sb.append(", Event: ").append(event).append("]");
-        return sb.toString();
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpAssociationImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import com.sun.nio.sctp.Association;
-
-/**
- * An implementation of Association
- */
-public class SctpAssociationImpl extends Association {
-    public SctpAssociationImpl(int associationID,
-                               int maxInStreams,
-                               int maxOutStreams) {
-        super(associationID, maxInStreams, maxOutStreams);
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer sb = new StringBuffer(super.toString());
-        return sb.append("[associationID:")
-                 .append(associationID())
-                 .append(", maxIn:")
-                 .append(maxInboundStreams())
-                 .append(", maxOut:")
-                 .append(maxOutboundStreams())
-                 .append("]")
-                 .toString();
-    }
-}
-
--- a/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1097 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.net.InetAddress;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.InetSocketAddress;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Set;
-import java.util.HashSet;
-import java.nio.ByteBuffer;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.ConnectionPendingException;
-import java.nio.channels.NoConnectionPendingException;
-import java.nio.channels.AlreadyConnectedException;
-import java.nio.channels.NotYetBoundException;
-import java.nio.channels.NotYetConnectedException;
-import java.nio.channels.spi.SelectorProvider;
-import com.sun.nio.sctp.AbstractNotificationHandler;
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.AssociationChangeNotification;
-import com.sun.nio.sctp.HandlerResult;
-import com.sun.nio.sctp.IllegalReceiveException;
-import com.sun.nio.sctp.InvalidStreamException;
-import com.sun.nio.sctp.IllegalUnbindException;
-import com.sun.nio.sctp.MessageInfo;
-import com.sun.nio.sctp.NotificationHandler;
-import com.sun.nio.sctp.SctpChannel;
-import com.sun.nio.sctp.SctpSocketOption;
-import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
-import static sun.nio.ch.SctpResultContainer.SEND_FAILED;
-import static sun.nio.ch.SctpResultContainer.ASSOCIATION_CHANGED;
-import static sun.nio.ch.SctpResultContainer.PEER_ADDRESS_CHANGED;
-import static sun.nio.ch.SctpResultContainer.SHUTDOWN;
-
-/**
- * An implementation of an SctpChannel
- */
-public class SctpChannelImpl extends SctpChannel
-    implements SelChImpl
-{
-    private final FileDescriptor fd;
-
-    private final int fdVal;
-
-    /* IDs of native threads doing send and receivess, for signalling */
-    private volatile long receiverThread = 0;
-    private volatile long senderThread = 0;
-
-    /* Lock held by current receiving or connecting thread */
-    private final Object receiveLock = new Object();
-
-    /* Lock held by current sending or connecting thread */
-    private final Object sendLock = new Object();
-
-    private final ThreadLocal<Boolean> receiveInvoked =
-        new ThreadLocal<Boolean>() {
-             @Override protected Boolean initialValue() {
-                 return Boolean.FALSE;
-            }
-    };
-
-    /* Lock held by any thread that modifies the state fields declared below
-       DO NOT invoke a blocking I/O operation while holding this lock! */
-    private final Object stateLock = new Object();
-
-    private enum ChannelState {
-        UNINITIALIZED,
-        UNCONNECTED,
-        PENDING,
-        CONNECTED,
-        KILLPENDING,
-        KILLED,
-    }
-    /* -- The following fields are protected by stateLock -- */
-    private ChannelState state = ChannelState.UNINITIALIZED;
-
-    /* Binding; Once bound the port will remain constant. */
-    int port = -1;
-    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
-    /* Has the channel been bound to the wildcard address */
-    private boolean wildcard; /* false */
-    //private InetSocketAddress remoteAddress = null;
-
-    /* Input/Output open */
-    private boolean readyToConnect;
-
-    /* Shutdown */
-    private boolean isShutdown;
-
-    private Association association;
-
-    private Set<SocketAddress> remoteAddresses = Collections.emptySet();
-
-    /* -- End of fields protected by stateLock -- */
-
-    /**
-     * Constructor for normal connecting sockets
-     */
-    public SctpChannelImpl(SelectorProvider provider) throws IOException {
-        //TODO: update provider remove public modifier
-        super(provider);
-        this.fd = SctpNet.socket(true);
-        this.fdVal = IOUtil.fdVal(fd);
-        this.state = ChannelState.UNCONNECTED;
-    }
-
-    /**
-     * Constructor for sockets obtained from server sockets
-     */
-    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();
-
-        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);
-            }
-        }
-    }
-
-    /**
-     * Binds the channel's socket to a local address.
-     */
-    @Override
-    public SctpChannel bind(SocketAddress local) throws IOException {
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                synchronized (stateLock) {
-                    ensureOpenAndUnconnected();
-                    if (isBound())
-                        SctpNet.throwAlreadyBoundException();
-                    InetSocketAddress isa = (local == null) ?
-                        new InetSocketAddress(0) : Net.checkAddress(local);
-                    Net.bind(fd, isa.getAddress(), isa.getPort());
-                    InetSocketAddress boundIsa = Net.localAddress(fd);
-                    port = boundIsa.getPort();
-                    localAddresses.add(isa);
-                    if (isa.getAddress().isAnyLocalAddress())
-                        wildcard = true;
-                }
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public SctpChannel bindAddress(InetAddress address)
-            throws IOException {
-        bindUnbindAddress(address, true);
-        localAddresses.add(new InetSocketAddress(address, port));
-        return this;
-    }
-
-    @Override
-    public SctpChannel unbindAddress(InetAddress address)
-            throws IOException {
-        bindUnbindAddress(address, false);
-        localAddresses.remove(new InetSocketAddress(address, port));
-        return this;
-    }
-
-    private SctpChannel bindUnbindAddress(InetAddress address, boolean add)
-            throws IOException {
-        if (address == null)
-            throw new IllegalArgumentException();
-
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                synchronized (stateLock) {
-                    if (!isOpen())
-                        throw new ClosedChannelException();
-                    if (!isBound())
-                        throw new NotYetBoundException();
-                    if (wildcard)
-                        throw new IllegalStateException(
-                                "Cannot add or remove addresses from a channel that is bound to the wildcard address");
-                    if (address.isAnyLocalAddress())
-                        throw new IllegalArgumentException(
-                                "Cannot add or remove the wildcard address");
-                    if (add) {
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                SctpNet.throwAlreadyBoundException();
-                            }
-                        }
-                    } else { /*removing */
-                        /* Verify that there is more than one address
-                         * and that address is already bound */
-                        if (localAddresses.size() <= 1)
-                            throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
-                        boolean foundAddress = false;
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                foundAddress = true;
-                                break;
-                            }
-                        }
-                        if (!foundAddress )
-                            throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
-                    }
-
-                    SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
-
-                    /* Update our internal Set to reflect the addition/removal */
-                    if (add)
-                        localAddresses.add(new InetSocketAddress(address, port));
-                    else {
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                localAddresses.remove(addr);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return this;
-    }
-
-    private boolean isBound() {
-        synchronized (stateLock) {
-            return port == -1 ? false : true;
-        }
-    }
-
-    private boolean isConnected() {
-        synchronized (stateLock) {
-            return (state == ChannelState.CONNECTED);
-        }
-    }
-
-    private void ensureOpenAndUnconnected() throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (isConnected())
-                throw new AlreadyConnectedException();
-            if (state == ChannelState.PENDING)
-                throw new ConnectionPendingException();
-        }
-    }
-
-    private boolean ensureReceiveOpen() throws ClosedChannelException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isConnected())
-                throw new NotYetConnectedException();
-            else
-                return true;
-        }
-    }
-
-    private void ensureSendOpen() throws ClosedChannelException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (isShutdown)
-                throw new ClosedChannelException();
-            if (!isConnected())
-                throw new NotYetConnectedException();
-        }
-    }
-
-    private void receiverCleanup() throws IOException {
-        synchronized (stateLock) {
-            receiverThread = 0;
-            if (state == ChannelState.KILLPENDING)
-                kill();
-        }
-    }
-
-    private void senderCleanup() throws IOException {
-        synchronized (stateLock) {
-            senderThread = 0;
-            if (state == ChannelState.KILLPENDING)
-                kill();
-        }
-    }
-
-    @Override
-    public Association association() throws ClosedChannelException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isConnected())
-                return null;
-
-            return association;
-        }
-    }
-
-    @Override
-    public boolean connect(SocketAddress endpoint) throws IOException {
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                ensureOpenAndUnconnected();
-                InetSocketAddress isa = Net.checkAddress(endpoint);
-                SecurityManager sm = System.getSecurityManager();
-                if (sm != null)
-                    sm.checkConnect(isa.getAddress().getHostAddress(),
-                                    isa.getPort());
-                synchronized (blockingLock()) {
-                    int n = 0;
-                    try {
-                        try {
-                            begin();
-                            synchronized (stateLock) {
-                                if (!isOpen()) {
-                                    return false;
-                                }
-                                receiverThread = NativeThread.current();
-                            }
-                            for (;;) {
-                                InetAddress ia = isa.getAddress();
-                                if (ia.isAnyLocalAddress())
-                                    ia = InetAddress.getLocalHost();
-                                n = SctpNet.connect(fdVal, ia, isa.getPort());
-                                if (  (n == IOStatus.INTERRUPTED)
-                                      && isOpen())
-                                    continue;
-                                break;
-                            }
-                        } finally {
-                            receiverCleanup();
-                            end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                            assert IOStatus.check(n);
-                        }
-                    } catch (IOException x) {
-                        /* If an exception was thrown, close the channel after
-                         * invoking end() so as to avoid bogus
-                         * AsynchronousCloseExceptions */
-                        close();
-                        throw x;
-                    }
-
-                    if (n > 0) {
-                        synchronized (stateLock) {
-                            /* Connection succeeded */
-                            state = ChannelState.CONNECTED;
-                            if (!isBound()) {
-                                InetSocketAddress boundIsa =
-                                        Net.localAddress(fd);
-                                port = boundIsa.getPort();
-                            }
-
-                            /* Receive COMM_UP */
-                            ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
-                            try {
-                                receive(buf, null, null, true);
-                            } finally {
-                                Util.releaseTemporaryDirectBuffer(buf);
-                            }
-
-                            /* cache remote addresses */
-                            try {
-                                remoteAddresses = getRemoteAddresses();
-                            } catch (IOException unused) { /* swallow exception */ }
-
-                            return true;
-                        }
-                    } else  {
-                        synchronized (stateLock) {
-                            /* If nonblocking and no exception then connection
-                             * pending; disallow another invocation */
-                            if (!isBlocking())
-                                state = ChannelState.PENDING;
-                            else
-                                assert false;
-                        }
-                    }
-                }
-                return false;
-            }
-        }
-    }
-
-    @Override
-    public boolean connect(SocketAddress endpoint,
-                           int maxOutStreams,
-                           int maxInStreams)
-            throws IOException {
-        ensureOpenAndUnconnected();
-        return setOption(SCTP_INIT_MAXSTREAMS, InitMaxStreams.
-                create(maxInStreams, maxOutStreams)).connect(endpoint);
-
-    }
-
-    @Override
-    public boolean isConnectionPending() {
-        synchronized (stateLock) {
-            return (state == ChannelState.PENDING);
-        }
-    }
-
-    @Override
-    public boolean finishConnect() throws IOException {
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                synchronized (stateLock) {
-                    if (!isOpen())
-                        throw new ClosedChannelException();
-                    if (isConnected())
-                        return true;
-                    if (state != ChannelState.PENDING)
-                        throw new NoConnectionPendingException();
-                }
-                int n = 0;
-                try {
-                    try {
-                        begin();
-                        synchronized (blockingLock()) {
-                            synchronized (stateLock) {
-                                if (!isOpen()) {
-                                    return false;
-                                }
-                                receiverThread = NativeThread.current();
-                            }
-                            if (!isBlocking()) {
-                                for (;;) {
-                                    n = checkConnect(fd, false, readyToConnect);
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
-                                        continue;
-                                    break;
-                                }
-                            } else {
-                                for (;;) {
-                                    n = checkConnect(fd, true, readyToConnect);
-                                    if (n == 0) {
-                                        // Loop in case of
-                                        // spurious notifications
-                                        continue;
-                                    }
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
-                                        continue;
-                                    break;
-                                }
-                            }
-                        }
-                    } finally {
-                        synchronized (stateLock) {
-                            receiverThread = 0;
-                            if (state == ChannelState.KILLPENDING) {
-                                kill();
-                                /* poll()/getsockopt() does not report
-                                 * error (throws exception, with n = 0)
-                                 * on Linux platform after dup2 and
-                                 * signal-wakeup. Force n to 0 so the
-                                 * end() can throw appropriate exception */
-                                n = 0;
-                            }
-                        }
-                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                        assert IOStatus.check(n);
-                    }
-                } catch (IOException x) {
-                    /* If an exception was thrown, close the channel after
-                     * invoking end() so as to avoid bogus
-                     * AsynchronousCloseExceptions */
-                    close();
-                    throw x;
-                }
-
-                if (n > 0) {
-                    synchronized (stateLock) {
-                        state = ChannelState.CONNECTED;
-                        if (!isBound()) {
-                            InetSocketAddress boundIsa =
-                                    Net.localAddress(fd);
-                            port = boundIsa.getPort();
-                        }
-
-                        /* Receive COMM_UP */
-                        ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
-                        try {
-                            receive(buf, null, null, true);
-                        } finally {
-                            Util.releaseTemporaryDirectBuffer(buf);
-                        }
-
-                        /* cache remote addresses */
-                        try {
-                            remoteAddresses = getRemoteAddresses();
-                        } catch (IOException unused) { /* swallow exception */ }
-
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected void implConfigureBlocking(boolean block) throws IOException {
-        IOUtil.configureBlocking(fd, block);
-    }
-
-    @Override
-    public void implCloseSelectableChannel() throws IOException {
-        synchronized (stateLock) {
-            SctpNet.preClose(fdVal);
-
-            if (receiverThread != 0)
-                NativeThread.signal(receiverThread);
-
-            if (senderThread != 0)
-                NativeThread.signal(senderThread);
-
-            if (!isRegistered())
-                kill();
-        }
-    }
-
-    @Override
-    public FileDescriptor getFD() {
-        return fd;
-    }
-
-    @Override
-    public int getFDVal() {
-        return fdVal;
-    }
-
-    /**
-     * Translates native poll revent ops into a ready operation ops
-     */
-    private boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl sk) {
-        int intOps = sk.nioInterestOps();
-        int oldOps = sk.nioReadyOps();
-        int newOps = initialOps;
-
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
-            /* This should only happen if this channel is pre-closed while a
-             * selection operation is in progress
-             * ## Throw an error if this channel has not been pre-closed */
-            return false;
-        }
-
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
-            newOps = intOps;
-            sk.nioReadyOps(newOps);
-            /* No need to poll again in checkConnect,
-             * the error will be detected there */
-            readyToConnect = true;
-            return (newOps & ~oldOps) != 0;
-        }
-
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
-            ((intOps & SelectionKey.OP_READ) != 0) &&
-            isConnected())
-            newOps |= SelectionKey.OP_READ;
-
-        if (((ops & PollArrayWrapper.POLLCONN) != 0) &&
-            ((intOps & SelectionKey.OP_CONNECT) != 0) &&
-            ((state == ChannelState.UNCONNECTED) || (state == ChannelState.PENDING))) {
-            newOps |= SelectionKey.OP_CONNECT;
-            readyToConnect = true;
-        }
-
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
-            ((intOps & SelectionKey.OP_WRITE) != 0) &&
-            isConnected())
-            newOps |= SelectionKey.OP_WRITE;
-
-        sk.nioReadyOps(newOps);
-        return (newOps & ~oldOps) != 0;
-    }
-
-    @Override
-    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, sk.nioReadyOps(), sk);
-    }
-
-    @Override
-    @SuppressWarnings("all")
-    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, 0, sk);
-    }
-
-    @Override
-    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
-        int newOps = 0;
-        if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
-        if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
-        if ((ops & SelectionKey.OP_CONNECT) != 0)
-            newOps |= PollArrayWrapper.POLLCONN;
-        sk.selector.putEventOps(sk, newOps);
-    }
-
-    @Override
-    public void kill() throws IOException {
-        synchronized (stateLock) {
-            if (state == ChannelState.KILLED)
-                return;
-            if (state == ChannelState.UNINITIALIZED) {
-                state = ChannelState.KILLED;
-                return;
-            }
-            assert !isOpen() && !isRegistered();
-
-            /* Postpone the kill if there is a waiting reader
-             * or writer thread. */
-            if (receiverThread == 0 && senderThread == 0) {
-                SctpNet.close(fdVal);
-                state = ChannelState.KILLED;
-            } else {
-                state = ChannelState.KILLPENDING;
-            }
-        }
-    }
-
-    @Override
-    public <T> SctpChannel setOption(SctpSocketOption<T> name, T value)
-            throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!supportedOptions().contains(name))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            SctpNet.setSocketOption(fdVal, name, value, 0 /*oneToOne*/);
-        }
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getOption(SctpSocketOption<T> name) throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!supportedOptions().contains(name))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            return (T)SctpNet.getSocketOption(fdVal, name, 0 /*oneToOne*/);
-        }
-    }
-
-    private static class DefaultOptionsHolder {
-        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
-
-        private static Set<SctpSocketOption<?>> defaultOptions() {
-            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
-            set.add(SCTP_DISABLE_FRAGMENTS);
-            set.add(SCTP_EXPLICIT_COMPLETE);
-            set.add(SCTP_FRAGMENT_INTERLEAVE);
-            set.add(SCTP_INIT_MAXSTREAMS);
-            set.add(SCTP_NODELAY);
-            set.add(SCTP_PRIMARY_ADDR);
-            set.add(SCTP_SET_PEER_PRIMARY_ADDR);
-            set.add(SO_SNDBUF);
-            set.add(SO_RCVBUF);
-            set.add(SO_LINGER);
-            return Collections.unmodifiableSet(set);
-        }
-    }
-
-    @Override
-    public final Set<SctpSocketOption<?>> supportedOptions() {
-        return DefaultOptionsHolder.defaultOptions;
-    }
-
-    @Override
-    public <T> MessageInfo receive(ByteBuffer buffer,
-                                   T attachment,
-                                   NotificationHandler<T> handler)
-            throws IOException {
-        return receive(buffer, attachment, handler, false);
-    }
-
-    private <T> MessageInfo receive(ByteBuffer buffer,
-                                    T attachment,
-                                    NotificationHandler<T> handler,
-                                    boolean fromConnect)
-            throws IOException {
-        if (buffer == null)
-            throw new IllegalArgumentException("buffer cannot be null");
-
-        if (buffer.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-
-        if (receiveInvoked.get())
-            throw new IllegalReceiveException(
-                    "cannot invoke receive from handler");
-        receiveInvoked.set(Boolean.TRUE);
-
-        try {
-            SctpResultContainer resultContainer = new SctpResultContainer();
-            do {
-                resultContainer.clear();
-                synchronized (receiveLock) {
-                    if (!ensureReceiveOpen())
-                        return null;
-
-                    int n = 0;
-                    try {
-                        begin();
-
-                        synchronized (stateLock) {
-                            if(!isOpen())
-                                return null;
-                            receiverThread = NativeThread.current();
-                        }
-
-                        do {
-                            n = receive(fdVal, buffer, resultContainer, fromConnect);
-                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
-                    } finally {
-                        receiverCleanup();
-                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                        assert IOStatus.check(n);
-                    }
-
-                    if (!resultContainer.isNotification()) {
-                        /* message or nothing */
-                        if (resultContainer.hasSomething()) {
-                            /* Set the association before returning */
-                            SctpMessageInfoImpl info =
-                                    resultContainer.getMessageInfo();
-                            synchronized (stateLock) {
-                                assert association != null;
-                                info.setAssociation(association);
-                            }
-                            return info;
-                        } else
-                            /* Non-blocking may return null if nothing available*/
-                            return null;
-                    } else { /* notification */
-                        synchronized (stateLock) {
-                            handleNotificationInternal(
-                                    resultContainer);
-                        }
-                    }
-
-                    if (fromConnect)  {
-                        /* If we reach here, then it was connect that invoked
-                         * receive and received the COMM_UP. We have already
-                         * handled the COMM_UP with the internal notification
-                         * handler. Simply return. */
-                        return null;
-                    }
-                }  /* receiveLock */
-            } while (handler == null ? true :
-                (invokeNotificationHandler(resultContainer, handler, attachment)
-                 == HandlerResult.CONTINUE));
-
-            return null;
-        } finally {
-            receiveInvoked.set(Boolean.FALSE);
-        }
-    }
-
-    private int receive(int fd,
-                        ByteBuffer dst,
-                        SctpResultContainer resultContainer,
-                        boolean peek)
-            throws IOException {
-        int pos = dst.position();
-        int lim = dst.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        if (dst instanceof DirectBuffer && rem > 0)
-            return receiveIntoNativeBuffer(fd, resultContainer, dst, rem, pos, peek);
-
-        /* Substitute a native buffer */
-        int newSize = Math.max(rem, 1);
-        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
-        try {
-            int n = receiveIntoNativeBuffer(fd, resultContainer, bb, newSize, 0, peek);
-            bb.flip();
-            if (n > 0 && rem > 0)
-                dst.put(bb);
-            return n;
-        } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
-        }
-    }
-
-    private int receiveIntoNativeBuffer(int fd,
-                                        SctpResultContainer resultContainer,
-                                        ByteBuffer bb,
-                                        int rem,
-                                        int pos,
-                                        boolean peek)
-        throws IOException
-    {
-        int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek);
-
-        if (n > 0)
-            bb.position(pos + n);
-        return n;
-    }
-
-    private InternalNotificationHandler internalNotificationHandler =
-            new InternalNotificationHandler();
-
-    private void handleNotificationInternal(SctpResultContainer resultContainer)
-    {
-        invokeNotificationHandler(resultContainer,
-                internalNotificationHandler, null);
-    }
-
-    private class InternalNotificationHandler
-            extends AbstractNotificationHandler<Object>
-    {
-        @Override
-        public HandlerResult handleNotification(
-                AssociationChangeNotification not, Object unused) {
-            if (not.event().equals(
-                    AssociationChangeNotification.AssocChangeEvent.COMM_UP) &&
-                    association == null) {
-                SctpAssocChange sac = (SctpAssocChange) not;
-                association = new SctpAssociationImpl
-                       (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams());
-            }
-            return HandlerResult.CONTINUE;
-        }
-    }
-
-    private <T> HandlerResult invokeNotificationHandler
-                                 (SctpResultContainer resultContainer,
-                                  NotificationHandler<T> handler,
-                                  T attachment) {
-        SctpNotification notification = resultContainer.notification();
-        synchronized (stateLock) {
-            notification.setAssociation(association);
-        }
-
-        if (!(handler instanceof AbstractNotificationHandler)) {
-            return handler.handleNotification(notification, attachment);
-        }
-
-        /* AbstractNotificationHandler */
-        AbstractNotificationHandler<T> absHandler =
-                (AbstractNotificationHandler<T>)handler;
-        switch(resultContainer.type()) {
-            case ASSOCIATION_CHANGED :
-                return absHandler.handleNotification(
-                        resultContainer.getAssociationChanged(), attachment);
-            case PEER_ADDRESS_CHANGED :
-                return absHandler.handleNotification(
-                        resultContainer.getPeerAddressChanged(), attachment);
-            case SEND_FAILED :
-                return absHandler.handleNotification(
-                        resultContainer.getSendFailed(), attachment);
-            case SHUTDOWN :
-                return absHandler.handleNotification(
-                        resultContainer.getShutdown(), attachment);
-            default :
-                /* implementation specific handlers */
-                return absHandler.handleNotification(
-                        resultContainer.notification(), attachment);
-        }
-    }
-
-    private void checkAssociation(Association sendAssociation) {
-        synchronized (stateLock) {
-            if (sendAssociation != null && !sendAssociation.equals(association)) {
-                throw new IllegalArgumentException(
-                        "Cannot send to another association");
-            }
-        }
-    }
-
-    private void checkStreamNumber(int streamNumber) {
-        synchronized (stateLock) {
-            if (association != null) {
-                if (streamNumber < 0 ||
-                      streamNumber >= association.maxOutboundStreams())
-                    throw new InvalidStreamException();
-            }
-        }
-    }
-
-    /* TODO: Add support for ttl and isComplete to both 121 12M
-     *       SCTP_EOR not yet supported on reference platforms
-     *       TTL support limited...
-     */
-    @Override
-    public int send(ByteBuffer buffer, MessageInfo messageInfo)
-            throws IOException {
-        if (buffer == null)
-            throw new IllegalArgumentException("buffer cannot be null");
-
-        if (messageInfo == null)
-            throw new IllegalArgumentException("messageInfo cannot be null");
-
-        checkAssociation(messageInfo.association());
-        checkStreamNumber(messageInfo.streamNumber());
-
-        synchronized (sendLock) {
-            ensureSendOpen();
-
-            int n = 0;
-            try {
-                begin();
-
-                synchronized (stateLock) {
-                    if(!isOpen())
-                        return 0;
-                    senderThread = NativeThread.current();
-                }
-
-                do {
-                    n = send(fdVal, buffer, messageInfo);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
-                return IOStatus.normalize(n);
-            } finally {
-                senderCleanup();
-                end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                assert IOStatus.check(n);
-            }
-        }
-    }
-
-    private int send(int fd, ByteBuffer src, MessageInfo messageInfo)
-            throws IOException {
-        int streamNumber = messageInfo.streamNumber();
-        SocketAddress target = messageInfo.address();
-        boolean unordered = messageInfo.isUnordered();
-        int ppid = messageInfo.payloadProtocolID();
-
-        if (src instanceof DirectBuffer)
-            return sendFromNativeBuffer(fd, src, target, streamNumber,
-                    unordered, ppid);
-
-        /* Substitute a native buffer */
-        int pos = src.position();
-        int lim = src.limit();
-        assert (pos <= lim && streamNumber >= 0);
-
-        int rem = (pos <= lim ? lim - pos : 0);
-        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
-        try {
-            bb.put(src);
-            bb.flip();
-            /* Do not update src until we see how many bytes were written */
-            src.position(pos);
-
-            int n = sendFromNativeBuffer(fd, bb, target, streamNumber,
-                    unordered, ppid);
-            if (n > 0) {
-                /* now update src */
-                src.position(pos + n);
-            }
-            return n;
-        } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
-        }
-    }
-
-    private int sendFromNativeBuffer(int fd,
-                                     ByteBuffer bb,
-                                     SocketAddress target,
-                                     int streamNumber,
-                                     boolean unordered,
-                                     int ppid)
-            throws IOException {
-        int pos = bb.position();
-        int lim = bb.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        int written = send0(fd, ((DirectBuffer)bb).address() + pos,
-                            rem, target, -1 /*121*/, streamNumber, unordered, ppid);
-        if (written > 0)
-            bb.position(pos + written);
-        return written;
-    }
-
-    @Override
-    public SctpChannel shutdown() throws IOException {
-        synchronized(stateLock) {
-            if (isShutdown)
-                return this;
-
-            ensureSendOpen();
-            SctpNet.shutdown(fdVal, -1);
-            if (senderThread != 0)
-                NativeThread.signal(senderThread);
-            isShutdown = true;
-        }
-        return this;
-    }
-
-    @Override
-    public Set<SocketAddress> getAllLocalAddresses()
-            throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isBound())
-                return Collections.emptySet();
-
-            return SctpNet.getLocalAddresses(fdVal);
-        }
-    }
-
-    @Override
-    public Set<SocketAddress> getRemoteAddresses()
-            throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isConnected() || isShutdown)
-                return Collections.emptySet();
-
-            try {
-                return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
-            } catch (SocketException unused) {
-                /* an open connected channel should always have remote addresses */
-                return remoteAddresses;
-            }
-        }
-    }
-
-    /* Native */
-    private static native void initIDs();
-
-    static native int receive0(int fd, SctpResultContainer resultContainer,
-            long address, int length, boolean peek) throws IOException;
-
-    static native int send0(int fd, long address, int length,
-            SocketAddress target, int assocId, int streamNumber,
-            boolean unordered, int ppid) throws IOException;
-
-    private static native int checkConnect(FileDescriptor fd, boolean block,
-            boolean ready) throws IOException;
-
-    static {
-        Util.load();   /* loads nio & net native libraries */
-        java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
-        initIDs();
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,985 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.net.InetAddress;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.InetSocketAddress;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map.Entry;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.nio.ByteBuffer;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.NotYetBoundException;
-import java.nio.channels.spi.SelectorProvider;
-import com.sun.nio.sctp.AbstractNotificationHandler;
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.AssociationChangeNotification;
-import com.sun.nio.sctp.HandlerResult;
-import com.sun.nio.sctp.IllegalReceiveException;
-import com.sun.nio.sctp.InvalidStreamException;
-import com.sun.nio.sctp.IllegalUnbindException;
-import com.sun.nio.sctp.NotificationHandler;
-import com.sun.nio.sctp.MessageInfo;
-import com.sun.nio.sctp.SctpChannel;
-import com.sun.nio.sctp.SctpMultiChannel;
-import com.sun.nio.sctp.SctpSocketOption;
-import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
-import static sun.nio.ch.SctpResultContainer.*;
-
-/**
- * An implementation of SctpMultiChannel
- */
-public class SctpMultiChannelImpl extends SctpMultiChannel
-    implements SelChImpl
-{
-    private final FileDescriptor fd;
-
-    private final int fdVal;
-
-    /* IDs of native threads doing send and receives, for signalling */
-    private volatile long receiverThread = 0;
-    private volatile long senderThread = 0;
-
-    /* Lock held by current receiving thread */
-    private final Object receiveLock = new Object();
-
-    /* Lock held by current sending thread */
-    private final Object sendLock = new Object();
-
-    /* Lock held by any thread that modifies the state fields declared below
-     * DO NOT invoke a blocking I/O operation while holding this lock! */
-    private final Object stateLock = new Object();
-
-    private enum ChannelState {
-        UNINITIALIZED,
-        KILLPENDING,
-        KILLED,
-    }
-
-    /* -- The following fields are protected by stateLock -- */
-    private ChannelState state = ChannelState.UNINITIALIZED;
-
-    /* Binding: Once bound the port will remain constant. */
-    int port = -1;
-    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
-    /* Has the channel been bound to the wildcard address */
-    private boolean wildcard; /* false */
-
-    /* Keeps a map of addresses to association, and visa versa */
-    private HashMap<SocketAddress, Association> addressMap =
-                         new HashMap<SocketAddress, Association>();
-    private HashMap<Association, Set<SocketAddress>> associationMap =
-                         new HashMap<Association, Set<SocketAddress>>();
-
-    /* -- End of fields protected by stateLock -- */
-
-    /* If an association has been shutdown mark it for removal after
-     * the user handler has been invoked */
-    private final ThreadLocal<Association> associationToRemove =
-        new ThreadLocal<Association>() {
-             @Override protected Association initialValue() {
-                 return null;
-            }
-    };
-
-    /* A notification handler cannot invoke receive */
-    private final ThreadLocal<Boolean> receiveInvoked =
-        new ThreadLocal<Boolean>() {
-             @Override protected Boolean initialValue() {
-                 return Boolean.FALSE;
-            }
-    };
-
-    public SctpMultiChannelImpl(SelectorProvider provider)
-            throws IOException {
-        //TODO: update provider, remove public modifier
-        super(provider);
-        this.fd = SctpNet.socket(false /*one-to-many*/);
-        this.fdVal = IOUtil.fdVal(fd);
-    }
-
-    @Override
-    public SctpMultiChannel bind(SocketAddress local, int backlog)
-            throws IOException {
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                synchronized (stateLock) {
-                    ensureOpen();
-                    if (isBound())
-                        SctpNet.throwAlreadyBoundException();
-                    InetSocketAddress isa = (local == null) ?
-                        new InetSocketAddress(0) : Net.checkAddress(local);
-
-                    SecurityManager sm = System.getSecurityManager();
-                    if (sm != null)
-                        sm.checkListen(isa.getPort());
-                    Net.bind(fd, isa.getAddress(), isa.getPort());
-
-                    InetSocketAddress boundIsa = Net.localAddress(fd);
-                    port = boundIsa.getPort();
-                    localAddresses.add(isa);
-                    if (isa.getAddress().isAnyLocalAddress())
-                        wildcard = true;
-
-                    SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
-                }
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public SctpMultiChannel bindAddress(InetAddress address)
-            throws IOException {
-        return bindUnbindAddress(address, true);
-    }
-
-    @Override
-    public SctpMultiChannel unbindAddress(InetAddress address)
-            throws IOException {
-        return bindUnbindAddress(address, false);
-    }
-
-    private SctpMultiChannel bindUnbindAddress(InetAddress address,
-                                               boolean add)
-            throws IOException {
-        if (address == null)
-            throw new IllegalArgumentException();
-
-        synchronized (receiveLock) {
-            synchronized (sendLock) {
-                synchronized (stateLock) {
-                    if (!isOpen())
-                        throw new ClosedChannelException();
-                    if (!isBound())
-                        throw new NotYetBoundException();
-                    if (wildcard)
-                        throw new IllegalStateException(
-                                "Cannot add or remove addresses from a channel that is bound to the wildcard address");
-                    if (address.isAnyLocalAddress())
-                        throw new IllegalArgumentException(
-                                "Cannot add or remove the wildcard address");
-                    if (add) {
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                SctpNet.throwAlreadyBoundException();
-                            }
-                        }
-                    } else { /*removing */
-                        /* Verify that there is more than one address
-                         * and that address is already bound */
-                        if (localAddresses.size() <= 1)
-                            throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
-                        boolean foundAddress = false;
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                foundAddress = true;
-                                break;
-                            }
-                        }
-                        if (!foundAddress )
-                            throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
-                    }
-
-                    SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
-
-                    /* Update our internal Set to reflect the addition/removal */
-                    if (add)
-                        localAddresses.add(new InetSocketAddress(address, port));
-                    else {
-                        for (InetSocketAddress addr : localAddresses) {
-                            if (addr.getAddress().equals(address)) {
-                                localAddresses.remove(addr);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public Set<Association> associations()
-            throws ClosedChannelException, NotYetBoundException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isBound())
-                throw new NotYetBoundException();
-
-            return Collections.unmodifiableSet(associationMap.keySet());
-        }
-    }
-
-    private boolean isBound() {
-        synchronized (stateLock) {
-            return port == -1 ? false : true;
-        }
-    }
-
-    private void ensureOpen() throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-        }
-    }
-
-    private void receiverCleanup() throws IOException {
-        synchronized (stateLock) {
-            receiverThread = 0;
-            if (state == ChannelState.KILLPENDING)
-                kill();
-        }
-    }
-
-    private void senderCleanup() throws IOException {
-        synchronized (stateLock) {
-            senderThread = 0;
-            if (state == ChannelState.KILLPENDING)
-                kill();
-        }
-    }
-
-    @Override
-    protected void implConfigureBlocking(boolean block) throws IOException {
-        IOUtil.configureBlocking(fd, block);
-    }
-
-    @Override
-    public void implCloseSelectableChannel() throws IOException {
-        synchronized (stateLock) {
-            SctpNet.preClose(fdVal);
-
-            if (receiverThread != 0)
-                NativeThread.signal(receiverThread);
-
-            if (senderThread != 0)
-                NativeThread.signal(senderThread);
-
-            if (!isRegistered())
-                kill();
-        }
-    }
-
-    @Override
-    public FileDescriptor getFD() {
-        return fd;
-    }
-
-    @Override
-    public int getFDVal() {
-        return fdVal;
-    }
-
-    /**
-     * Translates native poll revent ops into a ready operation ops
-     */
-    private boolean translateReadyOps(int ops, int initialOps,
-                                      SelectionKeyImpl sk) {
-        int intOps = sk.nioInterestOps();
-        int oldOps = sk.nioReadyOps();
-        int newOps = initialOps;
-
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
-            /* This should only happen if this channel is pre-closed while a
-             * selection operation is in progress
-             * ## Throw an error if this channel has not been pre-closed */
-            return false;
-        }
-
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
-            newOps = intOps;
-            sk.nioReadyOps(newOps);
-            return (newOps & ~oldOps) != 0;
-        }
-
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
-            ((intOps & SelectionKey.OP_READ) != 0))
-            newOps |= SelectionKey.OP_READ;
-
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
-            ((intOps & SelectionKey.OP_WRITE) != 0))
-            newOps |= SelectionKey.OP_WRITE;
-
-        sk.nioReadyOps(newOps);
-        return (newOps & ~oldOps) != 0;
-    }
-
-    @Override
-    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, sk.nioReadyOps(), sk);
-    }
-
-    @Override
-    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, 0, sk);
-    }
-
-    @Override
-    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
-        int newOps = 0;
-        if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
-        if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
-        sk.selector.putEventOps(sk, newOps);
-    }
-
-    @Override
-    public void kill() throws IOException {
-        synchronized (stateLock) {
-            if (state == ChannelState.KILLED)
-                return;
-            if (state == ChannelState.UNINITIALIZED) {
-                state = ChannelState.KILLED;
-                return;
-            }
-            assert !isOpen() && !isRegistered();
-
-            /* Postpone the kill if there is a thread sending or receiving. */
-            if (receiverThread == 0 && senderThread == 0) {
-                SctpNet.close(fdVal);
-                state = ChannelState.KILLED;
-            } else {
-                state = ChannelState.KILLPENDING;
-            }
-        }
-    }
-
-    @Override
-    public <T> SctpMultiChannel setOption(SctpSocketOption<T> name,
-                                          T value,
-                                          Association association)
-            throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!(supportedOptions().contains(name)))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (association != null && (name.equals(SCTP_PRIMARY_ADDR) ||
-                    name.equals(SCTP_SET_PEER_PRIMARY_ADDR))) {
-                checkAssociation(association);
-            }
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            int assocId = association == null ? 0 : association.associationID();
-            SctpNet.setSocketOption(fdVal, name, value, assocId);
-        }
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getOption(SctpSocketOption<T> name, Association association)
-            throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!supportedOptions().contains(name))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (association != null && (name.equals(SCTP_PRIMARY_ADDR) ||
-                    name.equals(SCTP_SET_PEER_PRIMARY_ADDR))) {
-                checkAssociation(association);
-            }
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            int assocId = association == null ? 0 : association.associationID();
-            return (T)SctpNet.getSocketOption(fdVal, name, assocId);
-        }
-    }
-
-    private static class DefaultOptionsHolder {
-        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
-
-        private static Set<SctpSocketOption<?>> defaultOptions() {
-            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
-            set.add(SCTP_DISABLE_FRAGMENTS);
-            set.add(SCTP_EXPLICIT_COMPLETE);
-            set.add(SCTP_FRAGMENT_INTERLEAVE);
-            set.add(SCTP_INIT_MAXSTREAMS);
-            set.add(SCTP_NODELAY);
-            set.add(SCTP_PRIMARY_ADDR);
-            set.add(SCTP_SET_PEER_PRIMARY_ADDR);
-            set.add(SO_SNDBUF);
-            set.add(SO_RCVBUF);
-            set.add(SO_LINGER);
-            return Collections.unmodifiableSet(set);
-        }
-    }
-
-    @Override
-    public final Set<SctpSocketOption<?>> supportedOptions() {
-        return DefaultOptionsHolder.defaultOptions;
-    }
-
-    @Override
-    public <T> MessageInfo receive(ByteBuffer buffer,
-                                   T attachment,
-                                   NotificationHandler<T> handler)
-            throws IOException {
-        if (buffer == null)
-            throw new IllegalArgumentException("buffer cannot be null");
-
-        if (buffer.isReadOnly())
-            throw new IllegalArgumentException("Read-only buffer");
-
-        if (receiveInvoked.get())
-            throw new IllegalReceiveException(
-                    "cannot invoke receive from handler");
-        receiveInvoked.set(Boolean.TRUE);
-
-        try {
-            SctpResultContainer resultContainer = new SctpResultContainer();
-            do {
-                resultContainer.clear();
-                synchronized (receiveLock) {
-                    ensureOpen();
-                    if (!isBound())
-                        throw new NotYetBoundException();
-
-                    int n = 0;
-                    try {
-                        begin();
-
-                        synchronized (stateLock) {
-                            if(!isOpen())
-                                return null;
-                            receiverThread = NativeThread.current();
-                        }
-
-                        do {
-                            n = receive(fdVal, buffer, resultContainer);
-                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
-                    } finally {
-                        receiverCleanup();
-                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                        assert IOStatus.check(n);
-                    }
-
-                    if (!resultContainer.isNotification()) {
-                        /* message or nothing */
-                        if (resultContainer.hasSomething()) {
-                            /* Set the association before returning */
-                            SctpMessageInfoImpl info =
-                                    resultContainer.getMessageInfo();
-                            info.setAssociation(lookupAssociation(info.
-                                    associationID()));
-                            SecurityManager sm = System.getSecurityManager();
-                            if (sm != null) {
-                                InetSocketAddress isa  = (InetSocketAddress)info.address();
-                                if (!addressMap.containsKey(isa)) {
-                                    /* must be a new association */
-                                    try {
-                                        sm.checkAccept(isa.getAddress().getHostAddress(),
-                                                       isa.getPort());
-                                    } catch (SecurityException se) {
-                                        buffer.clear();
-                                        throw se;
-                                    }
-                                }
-                            }
-
-                            assert info.association() != null;
-                            return info;
-                        } else  {
-                          /* Non-blocking may return null if nothing available*/
-                            return null;
-                        }
-                    } else { /* notification */
-                        synchronized (stateLock) {
-                            handleNotificationInternal(
-                                    resultContainer);
-                        }
-                    }
-                } /* receiveLock */
-            } while (handler == null ? true :
-                (invokeNotificationHandler(resultContainer, handler, attachment)
-                 == HandlerResult.CONTINUE));
-        } finally {
-            receiveInvoked.set(Boolean.FALSE);
-        }
-
-        return null;
-    }
-
-    private int receive(int fd,
-                        ByteBuffer dst,
-                        SctpResultContainer resultContainer)
-            throws IOException {
-        int pos = dst.position();
-        int lim = dst.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-        if (dst instanceof DirectBuffer && rem > 0)
-            return receiveIntoNativeBuffer(fd, resultContainer, dst, rem, pos);
-
-        /* Substitute a native buffer. */
-        int newSize = Math.max(rem, 1);
-        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
-        try {
-            int n = receiveIntoNativeBuffer(fd, resultContainer, bb, newSize, 0);
-            bb.flip();
-            if (n > 0 && rem > 0)
-                dst.put(bb);
-            return n;
-        } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
-        }
-    }
-
-    private int receiveIntoNativeBuffer(int fd,
-                                        SctpResultContainer resultContainer,
-                                        ByteBuffer bb,
-                                        int rem,
-                                        int pos)
-            throws IOException {
-        int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem);
-        if (n > 0)
-            bb.position(pos + n);
-        return n;
-    }
-
-    private InternalNotificationHandler internalNotificationHandler =
-            new InternalNotificationHandler();
-
-    private void handleNotificationInternal(SctpResultContainer resultContainer)
-    {
-        invokeNotificationHandler(resultContainer,
-                internalNotificationHandler, null);
-    }
-
-    private class InternalNotificationHandler
-            extends AbstractNotificationHandler<Object>
-    {
-        @Override
-        public HandlerResult handleNotification(
-                AssociationChangeNotification not, Object unused) {
-            SctpAssocChange sac = (SctpAssocChange) not;
-
-            /* Update map to reflect change in association */
-            switch (not.event()) {
-                case COMM_UP :
-                    Association newAssociation = new SctpAssociationImpl
-                       (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams());
-                    addAssociation(newAssociation);
-                    break;
-                case SHUTDOWN :
-                case COMM_LOST :
-                //case RESTART: ???
-                    /* mark association for removal after user handler invoked*/
-                    associationToRemove.set(lookupAssociation(sac.assocId()));
-            }
-            return HandlerResult.CONTINUE;
-        }
-    }
-
-    private <T> HandlerResult invokeNotificationHandler(
-                                   SctpResultContainer resultContainer,
-                                   NotificationHandler<T> handler,
-                                   T attachment) {
-        HandlerResult result;
-        SctpNotification notification = resultContainer.notification();
-        notification.setAssociation(lookupAssociation(notification.assocId()));
-
-        if (!(handler instanceof AbstractNotificationHandler)) {
-            result = handler.handleNotification(notification, attachment);
-        } else { /* AbstractNotificationHandler */
-            AbstractNotificationHandler<T> absHandler =
-                    (AbstractNotificationHandler<T>)handler;
-            switch(resultContainer.type()) {
-                case ASSOCIATION_CHANGED :
-                    result = absHandler.handleNotification(
-                            resultContainer.getAssociationChanged(), attachment);
-                    break;
-                case PEER_ADDRESS_CHANGED :
-                    result = absHandler.handleNotification(
-                            resultContainer.getPeerAddressChanged(), attachment);
-                    break;
-                case SEND_FAILED :
-                    result = absHandler.handleNotification(
-                            resultContainer.getSendFailed(), attachment);
-                    break;
-                case SHUTDOWN :
-                    result =  absHandler.handleNotification(
-                            resultContainer.getShutdown(), attachment);
-                    break;
-                default :
-                    /* implementation specific handlers */
-                    result =  absHandler.handleNotification(
-                            resultContainer.notification(), attachment);
-            }
-        }
-
-        if (!(handler instanceof InternalNotificationHandler)) {
-            /* Only remove associations after user handler
-             * has finished with them */
-            Association assoc = associationToRemove.get();
-            if (assoc != null) {
-                removeAssociation(assoc);
-                associationToRemove.set(null);
-            }
-
-        }
-
-        return result;
-    }
-
-    private Association lookupAssociation(int assocId) {
-        /* Lookup the association in our internal map */
-        synchronized (stateLock) {
-            Set<Association> assocs = associationMap.keySet();
-            for (Association a : assocs) {
-                if (a.associationID() == assocId) {
-                    return a;
-                }
-            }
-        }
-        return null;
-    }
-
-    private void addAssociation(Association association) {
-        synchronized (stateLock) {
-            int assocId = association.associationID();
-            Set<SocketAddress> addresses = null;
-
-            try {
-                addresses = SctpNet.getRemoteAddresses(fdVal, assocId);
-            } catch (IOException unused) {
-                /* OK, determining connected addresses may not be possible
-                 * shutdown, connection lost, etc */
-            }
-
-            associationMap.put(association, addresses);
-            if (addresses != null) {
-                for (SocketAddress addr : addresses)
-                    addressMap.put(addr, association);
-            }
-        }
-    }
-
-    private void removeAssociation(Association association) {
-        synchronized (stateLock) {
-            int assocId = association.associationID();
-            Set<SocketAddress> addresses = null;
-
-             try {
-                addresses = SctpNet.getRemoteAddresses(fdVal, assocId);
-            } catch (IOException unused) {
-                /* OK, determining connected addresses may not be possible
-                 * shutdown, connection lost, etc */
-            }
-
-            Set<Association> assocs = associationMap.keySet();
-            for (Association a : assocs) {
-                if (a.associationID() == assocId) {
-                    associationMap.remove(a);
-                    break;
-                }
-            }
-            if (addresses != null) {
-                for (SocketAddress addr : addresses)
-                    addressMap.remove(addr);
-            } else {
-                /* We cannot determine the connected addresses */
-                Set<java.util.Map.Entry<SocketAddress, Association>> addrAssocs =
-                        addressMap.entrySet();
-                Iterator<Entry<SocketAddress, Association>> iterator = addrAssocs.iterator();
-                while (iterator.hasNext()) {
-                    Entry<SocketAddress, Association> entry = iterator.next();
-                    if (entry.getValue().equals(association)) {
-                        iterator.remove();
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * @throws  IllegalArgumentException
-     *          If the given association is not controlled by this channel
-     *
-     * @return  {@code true} if, and only if, the given association is one
-     *          of the current associations controlled by this channel
-     */
-    private boolean checkAssociation(Association messageAssoc) {
-        synchronized (stateLock) {
-            for (Association association : associationMap.keySet()) {
-                if (messageAssoc.equals(association)) {
-                    return true;
-                }
-            }
-        }
-        throw new IllegalArgumentException(
-              "Given Association is not controlled by this channel");
-    }
-
-    private void checkStreamNumber(Association assoc, int streamNumber) {
-        synchronized (stateLock) {
-            if (streamNumber < 0 || streamNumber >= assoc.maxOutboundStreams())
-                throw new InvalidStreamException();
-        }
-    }
-
-    /* TODO: Add support for ttl and isComplete to both 121 12M
-     *       SCTP_EOR not yet supported on reference platforms
-     *       TTL support limited...
-     */
-    @Override
-    public int send(ByteBuffer buffer, MessageInfo messageInfo)
-            throws IOException {
-        if (buffer == null)
-            throw new IllegalArgumentException("buffer cannot be null");
-
-        if (messageInfo == null)
-            throw new IllegalArgumentException("messageInfo cannot be null");
-
-        synchronized (sendLock) {
-            ensureOpen();
-
-            if (!isBound())
-                bind(null, 0);
-
-            int n = 0;
-            try {
-                int assocId = -1;
-                SocketAddress address = null;
-                begin();
-
-                synchronized (stateLock) {
-                    if(!isOpen())
-                        return 0;
-                    senderThread = NativeThread.current();
-
-                    /* Determine what address or association to send to */
-                    Association assoc = messageInfo.association();
-                    InetSocketAddress addr = (InetSocketAddress)messageInfo.address();
-                    if (assoc != null) {
-                        checkAssociation(assoc);
-                        checkStreamNumber(assoc, messageInfo.streamNumber());
-                        assocId = assoc.associationID();
-                        /* have we also got a preferred address */
-                        if (addr != null) {
-                            if (!assoc.equals(addressMap.get(addr)))
-                                throw new IllegalArgumentException("given preferred address is not part of this association");
-                            address = addr;
-                        }
-                    } else if (addr != null) {
-                        address = addr;
-                        Association association = addressMap.get(addr);
-                        if (association != null) {
-                            checkStreamNumber(association, messageInfo.streamNumber());
-                            assocId = association.associationID();
-
-                        } else { /* must be new association */
-                            SecurityManager sm = System.getSecurityManager();
-                            if (sm != null)
-                                sm.checkConnect(addr.getAddress().getHostAddress(),
-                                                addr.getPort());
-                        }
-                    } else {
-                        throw new AssertionError(
-                            "Both association and address cannot be null");
-                    }
-                }
-
-                do {
-                    n = send(fdVal, buffer, assocId, address, messageInfo);
-                } while ((n == IOStatus.INTERRUPTED) && isOpen());
-
-                return IOStatus.normalize(n);
-            } finally {
-                senderCleanup();
-                end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                assert IOStatus.check(n);
-            }
-        }
-    }
-
-    private int send(int fd,
-                     ByteBuffer src,
-                     int assocId,
-                     SocketAddress target,
-                     MessageInfo messageInfo)
-            throws IOException {
-        int streamNumber = messageInfo.streamNumber();
-        boolean unordered = messageInfo.isUnordered();
-        int ppid = messageInfo.payloadProtocolID();
-
-        if (src instanceof DirectBuffer)
-            return sendFromNativeBuffer(fd, src, target, assocId,
-                    streamNumber, unordered, ppid);
-
-        /* Substitute a native buffer */
-        int pos = src.position();
-        int lim = src.limit();
-        assert (pos <= lim && streamNumber >= 0);
-
-        int rem = (pos <= lim ? lim - pos : 0);
-        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
-        try {
-            bb.put(src);
-            bb.flip();
-            /* Do not update src until we see how many bytes were written */
-            src.position(pos);
-
-            int n = sendFromNativeBuffer(fd, bb, target, assocId,
-                    streamNumber, unordered, ppid);
-            if (n > 0) {
-                /* now update src */
-                src.position(pos + n);
-            }
-            return n;
-        } finally {
-            Util.releaseTemporaryDirectBuffer(bb);
-        }
-    }
-
-    private int sendFromNativeBuffer(int fd,
-                                     ByteBuffer bb,
-                                     SocketAddress target,
-                                     int assocId,
-                                     int streamNumber,
-                                     boolean unordered,
-                                     int ppid)
-            throws IOException {
-        int pos = bb.position();
-        int lim = bb.limit();
-        assert (pos <= lim);
-        int rem = (pos <= lim ? lim - pos : 0);
-
-        int written = send0(fd, ((DirectBuffer)bb).address() + pos,
-                            rem, target, assocId, streamNumber, unordered, ppid);
-        if (written > 0)
-            bb.position(pos + written);
-        return written;
-    }
-
-    @Override
-    public SctpMultiChannel shutdown(Association association)
-            throws IOException {
-        synchronized (stateLock) {
-            checkAssociation(association);
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            SctpNet.shutdown(fdVal, association.associationID());
-        }
-        return this;
-    }
-
-    @Override
-    public Set<SocketAddress> getAllLocalAddresses()
-            throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isBound())
-                return Collections.emptySet();
-
-            return SctpNet.getLocalAddresses(fdVal);
-        }
-    }
-
-    @Override
-    public Set<SocketAddress> getRemoteAddresses(Association association)
-            throws IOException {
-        synchronized (stateLock) {
-            checkAssociation(association);
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            try {
-                return SctpNet.getRemoteAddresses(fdVal, association.associationID());
-            } catch (SocketException se) {
-                /* a valid association should always have remote addresses */
-                Set<SocketAddress> addrs = associationMap.get(association);
-                return addrs != null ? addrs : Collections.<SocketAddress>emptySet();
-            }
-        }
-    }
-
-    @Override
-    public SctpChannel branch(Association association)
-            throws IOException {
-        synchronized (stateLock) {
-            checkAssociation(association);
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            FileDescriptor bFd = SctpNet.branch(fdVal,
-                                                association.associationID());
-            /* successfully branched, we can now remove it from assoc list */
-            removeAssociation(association);
-
-            return new SctpChannelImpl(provider(), bFd, association);
-        }
-    }
-
-    /* Use common native implementation shared between
-     * one-to-one and one-to-many */
-    private static int receive0(int fd,
-                                SctpResultContainer resultContainer,
-                                long address,
-                                int length)
-            throws IOException{
-        return SctpChannelImpl.receive0(fd, resultContainer, address,
-                length, false /*peek */);
-    }
-
-    private static int send0(int fd,
-                             long address,
-                             int length,
-                             SocketAddress target,
-                             int assocId,
-                             int streamNumber,
-                             boolean unordered,
-                             int ppid)
-            throws IOException {
-        return SctpChannelImpl.send0(fd, address, length, target, assocId,
-                streamNumber, unordered, ppid);
-    }
-
-    static {
-        Util.load();   /* loads nio & net native libraries */
-        java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpNet.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.nio.channels.AlreadyBoundException;
-import java.util.Set;
-import java.util.HashSet;
-import java.security.AccessController;
-import sun.security.action.GetPropertyAction;
-import com.sun.nio.sctp.SctpSocketOption;
-import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
-
-public class SctpNet {
-    static final String osName = AccessController.doPrivileged(
-                    new GetPropertyAction("os.name"));
-
-    /* -- Miscellaneous SCTP utilities -- */
-
-    private static boolean IPv4MappedAddresses() {
-        if ("SunOS".equals(osName)) {
-            /* Solaris supports IPv4Mapped Addresses with bindx */
-            return true;
-        } /* else {  //other OS/implementations  */
-
-        /* lksctp/linux requires Ipv4 addresses */
-        return false;
-    }
-
-    static boolean throwAlreadyBoundException() throws IOException {
-        throw new AlreadyBoundException();
-    }
-
-    static void listen(int fd, int backlog) throws IOException {
-        listen0(fd, backlog);
-    }
-
-    static int connect(int fd, InetAddress remote, int remotePort)
-            throws IOException {
-        return connect0(fd, remote, remotePort);
-    }
-
-    static void close(int fd) throws IOException {
-        close0(fd);
-    }
-
-    static void preClose(int fd) throws IOException {
-        preClose0(fd);
-    }
-
-    /**
-     * @param  oneToOne
-     *         if {@code true} returns a one-to-one sctp socket, otherwise
-     *         returns a one-to-many sctp socket
-     */
-    static FileDescriptor socket(boolean oneToOne) throws IOException {
-        int nativefd = socket0(oneToOne);
-        return IOUtil.newFD(nativefd);
-    }
-
-    static void bindx(int fd, InetAddress[] addrs, int port, boolean add)
-            throws IOException {
-        bindx(fd, addrs, port, addrs.length, add,
-                IPv4MappedAddresses());
-    }
-
-    static Set<SocketAddress> getLocalAddresses(int fd)
-            throws IOException {
-        HashSet<SocketAddress> set = null;
-        SocketAddress[] saa = getLocalAddresses0(fd);
-
-        if (saa != null) {
-            set = new HashSet<SocketAddress>(saa.length);
-            for (SocketAddress sa : saa)
-                set.add(sa);
-        }
-
-        return set;
-    }
-
-    static Set<SocketAddress> getRemoteAddresses(int fd, int assocId)
-            throws IOException {
-        HashSet<SocketAddress> set = null;
-        SocketAddress[] saa = getRemoteAddresses0(fd, assocId);
-
-        if (saa != null) {
-            set = new HashSet<SocketAddress>(saa.length);
-            for (SocketAddress sa : saa)
-                set.add(sa);
-        }
-
-        return set;
-    }
-
-    static <T> void setSocketOption(int fd,
-                                    SctpSocketOption<T> name,
-                                    T value,
-                                    int assocId)
-            throws IOException {
-        if (value == null)
-            throw new IllegalArgumentException("Invalid option value");
-
-        if (name.equals(SCTP_INIT_MAXSTREAMS)) {
-            InitMaxStreams maxStreamValue = (InitMaxStreams)value;
-            SctpNet.setInitMsgOption0(fd,
-                 maxStreamValue.maxInStreams(), maxStreamValue.maxOutStreams());
-        } else if (name.equals(SCTP_PRIMARY_ADDR) ||
-                   name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) {
-
-            SocketAddress addr  = (SocketAddress) value;
-            if (addr == null)
-                throw new IllegalArgumentException("Invalid option value");
-
-            Net.checkAddress(addr);
-            InetSocketAddress netAddr = (InetSocketAddress)addr;
-
-            if (name.equals(SCTP_PRIMARY_ADDR)) {
-                setPrimAddrOption0(fd,
-                                   assocId,
-                                   netAddr.getAddress(),
-                                   netAddr.getPort());
-            } else {
-                setPeerPrimAddrOption0(fd,
-                                       assocId,
-                                       netAddr.getAddress(),
-                                       netAddr.getPort(),
-                                       IPv4MappedAddresses());
-            }
-        } else if (name.equals(SCTP_DISABLE_FRAGMENTS) ||
-            name.equals(SCTP_EXPLICIT_COMPLETE) ||
-            name.equals(SCTP_FRAGMENT_INTERLEAVE) ||
-            name.equals(SCTP_NODELAY) ||
-            name.equals(SO_SNDBUF) ||
-            name.equals(SO_RCVBUF) ||
-            name.equals(SO_LINGER)) {
-            setIntOption(fd, name, value);
-        } else {
-            throw new AssertionError("Unknown socket option");
-        }
-    }
-
-    static Object getSocketOption(int fd, SctpSocketOption<?> name, int assocId)
-             throws IOException {
-         if (name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) {
-            throw new IllegalArgumentException(
-                    "SCTP_SET_PEER_PRIMARY_ADDR cannot be retrieved");
-        } else if (name.equals(SCTP_INIT_MAXSTREAMS)) {
-            /* container for holding maxIn/Out streams */
-            int[] values = new int[2];
-            SctpNet.getInitMsgOption0(fd, values);
-            return InitMaxStreams.create(values[0], values[1]);
-        } else if (name.equals(SCTP_PRIMARY_ADDR)) {
-            return getPrimAddrOption0(fd, assocId);
-        } else if (name.equals(SCTP_DISABLE_FRAGMENTS) ||
-            name.equals(SCTP_EXPLICIT_COMPLETE) ||
-            name.equals(SCTP_FRAGMENT_INTERLEAVE) ||
-            name.equals(SCTP_NODELAY) ||
-            name.equals(SO_SNDBUF) ||
-            name.equals(SO_RCVBUF) ||
-            name.equals(SO_LINGER)) {
-            return getIntOption(fd, name);
-        } else {
-            throw new AssertionError("Unknown socket option");
-        }
-    }
-
-    static void setIntOption(int fd, SctpSocketOption<?> name, Object value)
-            throws IOException {
-        if (value == null)
-            throw new IllegalArgumentException("Invalid option value");
-
-        Class<?> type = name.type();
-        if (type != Integer.class && type != Boolean.class)
-            throw new AssertionError("Should not reach here");
-
-        if (name == SO_RCVBUF ||
-            name == SO_SNDBUF)
-        {
-            int i = ((Integer)value).intValue();
-            if (i < 0)
-                throw new IllegalArgumentException(
-                        "Invalid send/receive buffer size");
-        } else if (name == SO_LINGER) {
-            int i = ((Integer)value).intValue();
-            if (i < 0)
-                value = Integer.valueOf(-1);
-            if (i > 65535)
-                value = Integer.valueOf(65535);
-        } else if (name.equals(SCTP_FRAGMENT_INTERLEAVE)) {
-            int i = ((Integer)value).intValue();
-            if (i < 0 || i > 2)
-                throw new IllegalArgumentException(
-                        "Invalid value for SCTP_FRAGMENT_INTERLEAVE");
-        }
-
-        int arg;
-        if (type == Integer.class) {
-            arg = ((Integer)value).intValue();
-        } else {
-            boolean b = ((Boolean)value).booleanValue();
-            arg = (b) ? 1 : 0;
-        }
-
-        setIntOption0(fd, ((SctpStdSocketOption)name).constValue(), arg);
-    }
-
-    static Object getIntOption(int fd, SctpSocketOption<?> name)
-            throws IOException {
-        Class<?> type = name.type();
-
-        if (type != Integer.class && type != Boolean.class)
-            throw new AssertionError("Should not reach here");
-
-        if (!(name instanceof SctpStdSocketOption))
-            throw new AssertionError("Should not reach here");
-
-        int value = getIntOption0(fd,
-                ((SctpStdSocketOption)name).constValue());
-
-        if (type == Integer.class) {
-            return Integer.valueOf(value);
-        } else {
-            return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
-        }
-    }
-
-    static void shutdown(int fd, int assocId)
-            throws IOException {
-        shutdown0(fd, assocId);
-    }
-
-    static FileDescriptor branch(int fd, int assocId) throws IOException {
-        int nativefd = branch0(fd, assocId);
-        return IOUtil.newFD(nativefd);
-    }
-
-    /* Native Methods */
-    static native int socket0(boolean oneToOne) throws IOException;
-
-    static native void listen0(int fd, int backlog) throws IOException;
-
-    static native int connect0(int fd, InetAddress remote, int remotePort)
-        throws IOException;
-
-    static native void close0(int fd) throws IOException;
-
-    static native void preClose0(int fd) throws IOException;
-
-    static native void bindx(int fd, InetAddress[] addrs, int port, int length,
-            boolean add, boolean preferIPv6) throws IOException;
-
-    static native int getIntOption0(int fd, int opt) throws IOException;
-
-    static native void setIntOption0(int fd, int opt, int arg)
-        throws IOException;
-
-    static native SocketAddress[] getLocalAddresses0(int fd) throws IOException;
-
-    static native SocketAddress[] getRemoteAddresses0(int fd, int assocId)
-            throws IOException;
-
-    static native int branch0(int fd, int assocId) throws IOException;
-
-    static native void setPrimAddrOption0(int fd, int assocId, InetAddress ia,
-            int port) throws IOException;
-
-    static native void setPeerPrimAddrOption0(int fd, int assocId,
-            InetAddress ia, int port, boolean preferIPv6) throws IOException;
-
-    static native SocketAddress getPrimAddrOption0(int fd, int assocId)
-            throws IOException;
-
-    /* retVals [0] maxInStreams, [1] maxOutStreams */
-    static native void getInitMsgOption0(int fd, int[] retVals) throws IOException;
-
-    static native void setInitMsgOption0(int fd, int arg1, int arg2)
-            throws IOException;
-
-    static native void shutdown0(int fd, int assocId);
-
-    static native void init();
-
-    static {
-        init();
-    }
-}
-
--- a/src/solaris/classes/sun/nio/ch/SctpNotification.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.Notification;
-
-/**
- * All Notification implemenations MUST implement this interface to provide
- * access to the native association identidier.
- */
-interface SctpNotification extends Notification {
-    int assocId();
-    void setAssociation(Association association);
-}
--- a/src/solaris/classes/sun/nio/ch/SctpPeerAddrChange.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.net.SocketAddress;
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.PeerAddressChangeNotification;
-
-/**
- * An implementation of PeerAddressChangeNotification
- */
-public class SctpPeerAddrChange extends PeerAddressChangeNotification
-    implements SctpNotification
-{
-    /* static final ints so that they can be referenced from native */
-    private final static int SCTP_ADDR_AVAILABLE = 1;
-    private final static int SCTP_ADDR_UNREACHABLE = 2;
-    private final static int SCTP_ADDR_REMOVED = 3;
-    private final static int SCTP_ADDR_ADDED = 4;
-    private final static int SCTP_ADDR_MADE_PRIM = 5;
-    private final static int SCTP_ADDR_CONFIRMED =6;
-
-    private Association association;
-
-    /* assocId is used to lookup the association before the notification is
-     * returned to user code */
-    private int assocId;
-    private SocketAddress address;
-    private AddressChangeEvent event;
-
-    /* Invoked from native */
-    private SctpPeerAddrChange(int assocId, SocketAddress address, int intEvent) {
-        switch (intEvent) {
-            case SCTP_ADDR_AVAILABLE :
-                this.event = AddressChangeEvent.ADDR_AVAILABLE;
-                break;
-            case SCTP_ADDR_UNREACHABLE :
-                this.event = AddressChangeEvent.ADDR_UNREACHABLE;
-                break;
-            case SCTP_ADDR_REMOVED :
-                this.event = AddressChangeEvent.ADDR_REMOVED;
-                break;
-            case SCTP_ADDR_ADDED :
-                this.event = AddressChangeEvent.ADDR_ADDED;
-                break;
-            case SCTP_ADDR_MADE_PRIM :
-                this.event = AddressChangeEvent.ADDR_MADE_PRIMARY;
-                break;
-            case SCTP_ADDR_CONFIRMED :
-                this.event = AddressChangeEvent.ADDR_CONFIRMED;
-                break;
-            default:
-                throw new AssertionError("Unknown event type");
-        }
-        this.assocId = assocId;
-        this.address = address;
-    }
-
-    @Override
-    public int assocId() {
-        return assocId;
-    }
-
-    @Override
-    public void setAssociation(Association association) {
-        this.association = association;
-    }
-
-    @Override
-    public SocketAddress address() {
-        assert address != null;
-        return address;
-    }
-
-    @Override
-    public Association association() {
-        assert association != null;
-        return association;
-    }
-
-    @Override
-    public AddressChangeEvent event() {
-        assert event != null;
-        return event;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(super.toString()).append(" [");
-        sb.append("Address: ").append(address);
-        sb.append(", Association:").append(association);
-        sb.append(", Event: ").append(event).append("]");
-        return sb.toString();
-    }
-}
-
--- a/src/solaris/classes/sun/nio/ch/SctpResultContainer.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-/**
- * Wraps the actual message or notification so that it can be
- * set and returned from the native receive implementation.
- */
-public class SctpResultContainer {
-    /* static final ints so that they can be referenced from native */
-    static final int NOTHING = 0;
-    static final int MESSAGE = 1;
-    static final int SEND_FAILED = 2;
-    static final int ASSOCIATION_CHANGED = 3;
-    static final int PEER_ADDRESS_CHANGED = 4;
-    static final int SHUTDOWN = 5;
-
-    private Object value;
-    private int type;
-
-    int type() {
-        return type;
-    }
-
-    boolean hasSomething() {
-        return type() != NOTHING;
-    }
-
-    boolean isNotification() {
-        return type() != MESSAGE && type() != NOTHING ? true : false;
-    }
-
-    void clear() {
-        type = NOTHING;
-        value = null;
-    }
-
-    SctpNotification notification() {
-        assert type() != MESSAGE && type() != NOTHING;
-
-        return (SctpNotification) value;
-    }
-
-    SctpMessageInfoImpl getMessageInfo() {
-        assert type() == MESSAGE;
-
-        if (value instanceof SctpMessageInfoImpl)
-            return (SctpMessageInfoImpl) value;
-
-        return null;
-    }
-
-    SctpSendFailed getSendFailed() {
-        assert type() == SEND_FAILED;
-
-        if (value instanceof SctpSendFailed)
-            return (SctpSendFailed) value;
-
-        return null;
-    }
-
-    SctpAssocChange getAssociationChanged() {
-        assert type() == ASSOCIATION_CHANGED;
-
-        if (value instanceof SctpAssocChange)
-            return (SctpAssocChange) value;
-
-        return null;
-    }
-
-    SctpPeerAddrChange getPeerAddressChanged() {
-        assert type() == PEER_ADDRESS_CHANGED;
-
-        if (value instanceof SctpPeerAddrChange)
-            return (SctpPeerAddrChange) value;
-
-        return null;
-    }
-
-    SctpShutdown getShutdown() {
-        assert type() == SHUTDOWN;
-
-        if (value instanceof SctpShutdown)
-            return (SctpShutdown) value;
-
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Type: ");
-        switch (type) {
-            case NOTHING:              sb.append("NOTHING");             break;
-            case MESSAGE:              sb.append("MESSAGE");             break;
-            case SEND_FAILED:          sb.append("SEND FAILED");         break;
-            case ASSOCIATION_CHANGED:  sb.append("ASSOCIATION CHANGE");  break;
-            case PEER_ADDRESS_CHANGED: sb.append("PEER ADDRESS CHANGE"); break;
-            case SHUTDOWN:             sb.append("SHUTDOWN");            break;
-            default :                  sb.append("Unknown result type");
-        }
-        sb.append(", Value: ");
-        sb.append((value == null) ? "null" : value.toString());
-        return sb.toString();
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpSendFailed.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.nio.ByteBuffer;
-import java.net.SocketAddress;
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.SendFailedNotification;
-
-/**
- * An implementation of SendFailedNotification
- */
-public class SctpSendFailed extends SendFailedNotification
-    implements SctpNotification
-{
-    private Association association;
-    /* assocId is used to lookup the association before the notification is
-     * returned to user code */
-    private int assocId;
-    private SocketAddress address;
-    private ByteBuffer buffer;
-    private int errorCode;
-    private int streamNumber;
-
-    /* Invoked from native */
-    private SctpSendFailed(int assocId,
-                           SocketAddress address,
-                           ByteBuffer buffer,
-                           int errorCode,
-                           int streamNumber) {
-        this.assocId = assocId;
-        this.errorCode = errorCode;
-        this.streamNumber = streamNumber;
-        this.address = address;
-        this.buffer = buffer;
-    }
-
-    @Override
-    public int assocId() {
-        return assocId;
-    }
-
-    @Override
-    public void setAssociation(Association association) {
-        this.association = association;
-    }
-
-    @Override
-    public Association association() {
-        /* may be null */
-        return association;
-    }
-
-    @Override
-    public SocketAddress address() {
-        assert address != null;
-        return address;
-    }
-
-    @Override
-    public ByteBuffer buffer() {
-        assert buffer != null;
-        return buffer;
-    }
-
-    @Override
-    public int errorCode() {
-        return errorCode;
-    }
-
-    @Override
-    public int streamNumber() {
-        return streamNumber;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(super.toString()).append(" [");
-        sb.append("Association:").append(association);
-        sb.append(", Address: ").append(address);
-        sb.append(", buffer: ").append(buffer);
-        sb.append(", errorCode: ").append(errorCode);
-        sb.append(", streamNumber: ").append(streamNumber);
-        sb.append("]");
-        return sb.toString();
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,425 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import java.net.SocketAddress;
-import java.net.InetSocketAddress;
-import java.net.InetAddress;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Set;
-import java.util.HashSet;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.NotYetBoundException;
-import java.nio.channels.spi.SelectorProvider;
-import com.sun.nio.sctp.IllegalUnbindException;
-import com.sun.nio.sctp.SctpChannel;
-import com.sun.nio.sctp.SctpServerChannel;
-import com.sun.nio.sctp.SctpSocketOption;
-import com.sun.nio.sctp.SctpStandardSocketOptions;
-
-/**
- * An implementation of SctpServerChannel
- */
-public class SctpServerChannelImpl extends SctpServerChannel
-    implements SelChImpl
-{
-    private final FileDescriptor fd;
-
-    private final int fdVal;
-
-    /* IDs of native thread doing accept, for signalling */
-    private volatile long thread = 0;
-
-    /* Lock held by thread currently blocked in this channel */
-    private final Object lock = new Object();
-
-    /* Lock held by any thread that modifies the state fields declared below
-     * DO NOT invoke a blocking I/O operation while holding this lock! */
-    private final Object stateLock = new Object();
-
-    private enum ChannelState {
-        UNINITIALIZED,
-        INUSE,
-        KILLPENDING,
-        KILLED,
-    }
-    /* -- The following fields are protected by stateLock -- */
-    private ChannelState state = ChannelState.UNINITIALIZED;
-
-    /* Binding: Once bound the port will remain constant. */
-    int port = -1;
-    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
-    /* Has the channel been bound to the wildcard address */
-    private boolean wildcard; /* false */
-
-    /* -- End of fields protected by stateLock -- */
-
-    /**
-     * Initializes a new instance of this class.
-     */
-    public SctpServerChannelImpl(SelectorProvider provider)
-            throws IOException {
-        //TODO: update provider remove public modifier
-        super(provider);
-        this.fd = SctpNet.socket(true);
-        this.fdVal = IOUtil.fdVal(fd);
-        this.state = ChannelState.INUSE;
-    }
-
-    @Override
-    public SctpServerChannel bind(SocketAddress local, int backlog)
-            throws IOException {
-        synchronized (lock) {
-            synchronized (stateLock) {
-                if (!isOpen())
-                    throw new ClosedChannelException();
-                if (isBound())
-                    SctpNet.throwAlreadyBoundException();
-
-                InetSocketAddress isa = (local == null) ?
-                    new InetSocketAddress(0) : Net.checkAddress(local);
-                SecurityManager sm = System.getSecurityManager();
-                if (sm != null)
-                    sm.checkListen(isa.getPort());
-                Net.bind(fd, isa.getAddress(), isa.getPort());
-
-                InetSocketAddress boundIsa = Net.localAddress(fd);
-                port = boundIsa.getPort();
-                localAddresses.add(isa);
-                    if (isa.getAddress().isAnyLocalAddress())
-                        wildcard = true;
-
-                SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public SctpServerChannel bindAddress(InetAddress address)
-            throws IOException {
-        return bindUnbindAddress(address, true);
-    }
-
-    @Override
-    public SctpServerChannel unbindAddress(InetAddress address)
-            throws IOException {
-        return bindUnbindAddress(address, false);
-    }
-
-    private SctpServerChannel bindUnbindAddress(InetAddress address, boolean add)
-            throws IOException {
-        if (address == null)
-            throw new IllegalArgumentException();
-
-        synchronized (lock) {
-            synchronized (stateLock) {
-                if (!isOpen())
-                    throw new ClosedChannelException();
-                if (!isBound())
-                    throw new NotYetBoundException();
-                if (wildcard)
-                    throw new IllegalStateException(
-                            "Cannot add or remove addresses from a channel that is bound to the wildcard address");
-                if (address.isAnyLocalAddress())
-                    throw new IllegalArgumentException(
-                            "Cannot add or remove the wildcard address");
-                if (add) {
-                    for (InetSocketAddress addr : localAddresses) {
-                        if (addr.getAddress().equals(address)) {
-                            SctpNet.throwAlreadyBoundException();
-                        }
-                    }
-                } else { /*removing */
-                    /* Verify that there is more than one address
-                     * and that address is already bound */
-                    if (localAddresses.size() <= 1)
-                        throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
-                    boolean foundAddress = false;
-                    for (InetSocketAddress addr : localAddresses) {
-                        if (addr.getAddress().equals(address)) {
-                            foundAddress = true;
-                            break;
-                        }
-                    }
-                    if (!foundAddress )
-                        throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
-                }
-
-                SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
-
-                /* Update our internal Set to reflect the addition/removal */
-                if (add)
-                    localAddresses.add(new InetSocketAddress(address, port));
-                else {
-                    for (InetSocketAddress addr : localAddresses) {
-                        if (addr.getAddress().equals(address)) {
-                            localAddresses.remove(addr);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        return this;
-    }
-
-    private boolean isBound() {
-        synchronized (stateLock) {
-            return port == -1 ? false : true;
-        }
-    }
-
-    private void acceptCleanup() throws IOException {
-        synchronized (stateLock) {
-            thread = 0;
-            if (state == ChannelState.KILLPENDING)
-                kill();
-        }
-    }
-
-    @Override
-    public SctpChannel accept() throws IOException {
-        synchronized (lock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isBound())
-                throw new NotYetBoundException();
-            SctpChannel sc = null;
-
-            int n = 0;
-            FileDescriptor newfd = new FileDescriptor();
-            InetSocketAddress[] isaa = new InetSocketAddress[1];
-
-            try {
-                begin();
-                if (!isOpen())
-                    return null;
-                thread = NativeThread.current();
-                for (;;) {
-                    n = accept0(fd, newfd, isaa);
-                    if ((n == IOStatus.INTERRUPTED) && isOpen())
-                        continue;
-                    break;
-                }
-            } finally {
-                acceptCleanup();
-                end(n > 0);
-                assert IOStatus.check(n);
-            }
-
-            if (n < 1)
-                return null;
-
-            IOUtil.configureBlocking(newfd, true);
-            InetSocketAddress isa = isaa[0];
-            sc = new SctpChannelImpl(provider(), newfd);
-
-            SecurityManager sm = System.getSecurityManager();
-            if (sm != null)
-                sm.checkAccept(isa.getAddress().getHostAddress(),
-                               isa.getPort());
-
-            return sc;
-        }
-    }
-
-    @Override
-    protected void implConfigureBlocking(boolean block) throws IOException {
-        IOUtil.configureBlocking(fd, block);
-    }
-
-    @Override
-    public void implCloseSelectableChannel() throws IOException {
-        synchronized (stateLock) {
-            SctpNet.preClose(fdVal);
-            if (thread != 0)
-                NativeThread.signal(thread);
-            if (!isRegistered())
-                kill();
-        }
-    }
-
-    @Override
-    public void kill() throws IOException {
-        synchronized (stateLock) {
-            if (state == ChannelState.KILLED)
-                return;
-            if (state == ChannelState.UNINITIALIZED) {
-                state = ChannelState.KILLED;
-                return;
-            }
-            assert !isOpen() && !isRegistered();
-
-            // Postpone the kill if there is a thread in accept
-            if (thread == 0) {
-                SctpNet.close(fdVal);
-                state = ChannelState.KILLED;
-            } else {
-                state = ChannelState.KILLPENDING;
-            }
-        }
-    }
-
-    @Override
-    public FileDescriptor getFD() {
-        return fd;
-    }
-
-    @Override
-    public int getFDVal() {
-        return fdVal;
-    }
-
-    /**
-     * Translates native poll revent ops into a ready operation ops
-     */
-    private boolean translateReadyOps(int ops, int initialOps,
-                                     SelectionKeyImpl sk) {
-        int intOps = sk.nioInterestOps();
-        int oldOps = sk.nioReadyOps();
-        int newOps = initialOps;
-
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
-            /* This should only happen if this channel is pre-closed while a
-             * selection operation is in progress
-             * ## Throw an error if this channel has not been pre-closed */
-            return false;
-        }
-
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
-            newOps = intOps;
-            sk.nioReadyOps(newOps);
-            return (newOps & ~oldOps) != 0;
-        }
-
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
-            ((intOps & SelectionKey.OP_ACCEPT) != 0))
-                newOps |= SelectionKey.OP_ACCEPT;
-
-        sk.nioReadyOps(newOps);
-        return (newOps & ~oldOps) != 0;
-    }
-
-    @Override
-    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, sk.nioReadyOps(), sk);
-    }
-
-    @Override
-    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
-        return translateReadyOps(ops, 0, sk);
-    }
-
-    @Override
-    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
-        int newOps = 0;
-
-        /* Translate ops */
-        if ((ops & SelectionKey.OP_ACCEPT) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
-        /* Place ops into pollfd array */
-        sk.selector.putEventOps(sk, newOps);
-
-    }
-
-    @Override
-    public <T> SctpServerChannel setOption(SctpSocketOption<T> name, T value)
-            throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!supportedOptions().contains(name))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            SctpNet.setSocketOption(fdVal, name, value, 0 /*oneToOne*/);
-            return this;
-        }
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T getOption(SctpSocketOption<T> name) throws IOException {
-        if (name == null)
-            throw new NullPointerException();
-        if (!supportedOptions().contains(name))
-            throw new UnsupportedOperationException("'" + name + "' not supported");
-
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-
-            return (T) SctpNet.getSocketOption(fdVal, name, 0 /*oneToOne*/);
-        }
-    }
-
-    private static class DefaultOptionsHolder {
-        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
-
-        private static Set<SctpSocketOption<?>> defaultOptions() {
-            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(1);
-            set.add(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
-            return Collections.unmodifiableSet(set);
-        }
-    }
-
-    @Override
-    public final Set<SctpSocketOption<?>> supportedOptions() {
-        return DefaultOptionsHolder.defaultOptions;
-    }
-
-    @Override
-    public Set<SocketAddress> getAllLocalAddresses()
-            throws IOException {
-        synchronized (stateLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if (!isBound())
-                return Collections.emptySet();
-
-            return SctpNet.getLocalAddresses(fdVal);
-        }
-    }
-
-    /* Native */
-    private static native void initIDs();
-
-    private static native int accept0(FileDescriptor ssfd,
-        FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException;
-
-    static {
-        Util.load();   // loads nio & net native libraries
-        java.security.AccessController.doPrivileged(
-                new sun.security.action.LoadLibraryAction("sctp"));
-        initIDs();
-    }
-}
--- a/src/solaris/classes/sun/nio/ch/SctpShutdown.java	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.nio.ch;
-
-import com.sun.nio.sctp.Association;
-import com.sun.nio.sctp.ShutdownNotification;
-
-/**
- * An implementation of ShutdownNotification
- */
-public class SctpShutdown extends ShutdownNotification
-    implements SctpNotification
-{
-    private Association association;
-    /* assocId is used to lookup the association before the notification is
-     * returned to user code */
-    private int assocId;
-
-    /* Invoked from native */
-    private SctpShutdown(int assocId) {
-        this.assocId = assocId;
-    }
-
-    @Override
-    public int assocId() {
-        return assocId;
-    }
-
-    @Override
-    public void setAssociation(Association association) {
-        this.association = association;
-    }
-
-    @Override
-    public Association association() {
-        assert association != null;
-        return association;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(super.toString()).append(" [");
-        sb.append("Association:").append(association).append("]");
-        return sb.toString();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/AssociationChange.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.AssociationChangeNotification;
+
+/**
+ * An implementation of AssociationChangeNotification
+ */
+public class AssociationChange extends AssociationChangeNotification
+    implements SctpNotification
+{
+    /* static final ints so that they can be referenced from native */
+    private final static int SCTP_COMM_UP = 1;
+    private final static int SCTP_COMM_LOST = 2;
+    private final static int SCTP_RESTART = 3;
+    private final static int SCTP_SHUTDOWN = 4;
+    private final static int SCTP_CANT_START = 5;
+
+    private Association association;
+
+    /* assocId is used to lookup the association before the notification is
+     * returned to user code */
+    private int assocId;
+    private AssocChangeEvent event;
+    private int maxOutStreams;
+    private int maxInStreams;
+
+    /* Invoked from native */
+    private AssociationChange(int assocId,
+                              int intEvent,
+                              int maxOutStreams,
+                              int maxInStreams) {
+        switch (intEvent) {
+            case SCTP_COMM_UP :
+                this.event = AssocChangeEvent.COMM_UP;
+                break;
+            case SCTP_COMM_LOST :
+                this.event = AssocChangeEvent.COMM_LOST;
+                break;
+            case SCTP_RESTART :
+                this.event = AssocChangeEvent.RESTART;
+                break;
+            case SCTP_SHUTDOWN :
+                this.event = AssocChangeEvent.SHUTDOWN;
+                break;
+            case SCTP_CANT_START :
+                this.event = AssocChangeEvent.CANT_START;
+                break;
+            default :
+                throw new AssertionError(
+                      "Unknown Association Change Event type: " + intEvent);
+        }
+
+        this.assocId = assocId;
+        this.maxOutStreams = maxOutStreams;
+        this.maxInStreams = maxInStreams;
+    }
+
+    @Override
+    public int assocId() {
+        return assocId;
+    }
+
+    @Override
+    public void setAssociation(Association association) {
+        this.association = association;
+    }
+
+    @Override
+    public Association association() {
+        assert association != null;
+        return association;
+    }
+
+    @Override
+    public AssocChangeEvent event() {
+        return event;
+    }
+
+    int maxOutStreams() {
+        return maxOutStreams;
+    }
+
+    int maxInStreams() {
+        return maxInStreams;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString()).append(" [");
+        sb.append("Association:").append(association);
+        sb.append(", Event: ").append(event).append("]");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/AssociationImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import com.sun.nio.sctp.Association;
+
+/**
+ * An implementation of Association
+ */
+public class AssociationImpl extends Association {
+    public AssociationImpl(int associationID,
+                           int maxInStreams,
+                           int maxOutStreams) {
+        super(associationID, maxInStreams, maxOutStreams);
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer(super.toString());
+        return sb.append("[associationID:")
+                 .append(associationID())
+                 .append(", maxIn:")
+                 .append(maxInboundStreams())
+                 .append(", maxOut:")
+                 .append(maxOutboundStreams())
+                 .append("]")
+                 .toString();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/PeerAddrChange.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.net.SocketAddress;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.PeerAddressChangeNotification;
+
+/**
+ * An implementation of PeerAddressChangeNotification
+ */
+public class PeerAddrChange extends PeerAddressChangeNotification
+    implements SctpNotification
+{
+    /* static final ints so that they can be referenced from native */
+    private final static int SCTP_ADDR_AVAILABLE = 1;
+    private final static int SCTP_ADDR_UNREACHABLE = 2;
+    private final static int SCTP_ADDR_REMOVED = 3;
+    private final static int SCTP_ADDR_ADDED = 4;
+    private final static int SCTP_ADDR_MADE_PRIM = 5;
+    private final static int SCTP_ADDR_CONFIRMED =6;
+
+    private Association association;
+
+    /* assocId is used to lookup the association before the notification is
+     * returned to user code */
+    private int assocId;
+    private SocketAddress address;
+    private AddressChangeEvent event;
+
+    /* Invoked from native */
+    private PeerAddrChange(int assocId, SocketAddress address, int intEvent) {
+        switch (intEvent) {
+            case SCTP_ADDR_AVAILABLE :
+                this.event = AddressChangeEvent.ADDR_AVAILABLE;
+                break;
+            case SCTP_ADDR_UNREACHABLE :
+                this.event = AddressChangeEvent.ADDR_UNREACHABLE;
+                break;
+            case SCTP_ADDR_REMOVED :
+                this.event = AddressChangeEvent.ADDR_REMOVED;
+                break;
+            case SCTP_ADDR_ADDED :
+                this.event = AddressChangeEvent.ADDR_ADDED;
+                break;
+            case SCTP_ADDR_MADE_PRIM :
+                this.event = AddressChangeEvent.ADDR_MADE_PRIMARY;
+                break;
+            case SCTP_ADDR_CONFIRMED :
+                this.event = AddressChangeEvent.ADDR_CONFIRMED;
+                break;
+            default:
+                throw new AssertionError("Unknown event type");
+        }
+        this.assocId = assocId;
+        this.address = address;
+    }
+
+    @Override
+    public int assocId() {
+        return assocId;
+    }
+
+    @Override
+    public void setAssociation(Association association) {
+        this.association = association;
+    }
+
+    @Override
+    public SocketAddress address() {
+        assert address != null;
+        return address;
+    }
+
+    @Override
+    public Association association() {
+        assert association != null;
+        return association;
+    }
+
+    @Override
+    public AddressChangeEvent event() {
+        assert event != null;
+        return event;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString()).append(" [");
+        sb.append("Address: ").append(address);
+        sb.append(", Association:").append(association);
+        sb.append(", Event: ").append(event).append("]");
+        return sb.toString();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/ResultContainer.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+/**
+ * Wraps the actual message or notification so that it can be
+ * set and returned from the native receive implementation.
+ */
+public class ResultContainer {
+    /* static final ints so that they can be referenced from native */
+    static final int NOTHING = 0;
+    static final int MESSAGE = 1;
+    static final int SEND_FAILED = 2;
+    static final int ASSOCIATION_CHANGED = 3;
+    static final int PEER_ADDRESS_CHANGED = 4;
+    static final int SHUTDOWN = 5;
+
+    private Object value;
+    private int type;
+
+    int type() {
+        return type;
+    }
+
+    boolean hasSomething() {
+        return type() != NOTHING;
+    }
+
+    boolean isNotification() {
+        return type() != MESSAGE && type() != NOTHING ? true : false;
+    }
+
+    void clear() {
+        type = NOTHING;
+        value = null;
+    }
+
+    SctpNotification notification() {
+        assert type() != MESSAGE && type() != NOTHING;
+
+        return (SctpNotification) value;
+    }
+
+    MessageInfoImpl getMessageInfo() {
+        assert type() == MESSAGE;
+
+        if (value instanceof MessageInfoImpl)
+            return (MessageInfoImpl) value;
+
+        return null;
+    }
+
+    SendFailed getSendFailed() {
+        assert type() == SEND_FAILED;
+
+        if (value instanceof SendFailed)
+            return (SendFailed) value;
+
+        return null;
+    }
+
+    AssociationChange getAssociationChanged() {
+        assert type() == ASSOCIATION_CHANGED;
+
+        if (value instanceof AssociationChange)
+            return (AssociationChange) value;
+
+        return null;
+    }
+
+    PeerAddrChange getPeerAddressChanged() {
+        assert type() == PEER_ADDRESS_CHANGED;
+
+        if (value instanceof PeerAddrChange)
+            return (PeerAddrChange) value;
+
+        return null;
+    }
+
+    Shutdown getShutdown() {
+        assert type() == SHUTDOWN;
+
+        if (value instanceof Shutdown)
+            return (Shutdown) value;
+
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Type: ");
+        switch (type) {
+            case NOTHING:              sb.append("NOTHING");             break;
+            case MESSAGE:              sb.append("MESSAGE");             break;
+            case SEND_FAILED:          sb.append("SEND FAILED");         break;
+            case ASSOCIATION_CHANGED:  sb.append("ASSOCIATION CHANGE");  break;
+            case PEER_ADDRESS_CHANGED: sb.append("PEER ADDRESS CHANGE"); break;
+            case SHUTDOWN:             sb.append("SHUTDOWN");            break;
+            default :                  sb.append("Unknown result type");
+        }
+        sb.append(", Value: ");
+        sb.append((value == null) ? "null" : value.toString());
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.InetSocketAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.spi.SelectorProvider;
+import com.sun.nio.sctp.AbstractNotificationHandler;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.AssociationChangeNotification;
+import com.sun.nio.sctp.HandlerResult;
+import com.sun.nio.sctp.IllegalReceiveException;
+import com.sun.nio.sctp.InvalidStreamException;
+import com.sun.nio.sctp.IllegalUnbindException;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.NotificationHandler;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpSocketOption;
+import sun.nio.ch.DirectBuffer;
+import sun.nio.ch.IOStatus;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.NativeThread;
+import sun.nio.ch.Net;
+import sun.nio.ch.PollArrayWrapper;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import sun.nio.ch.Util;
+import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
+import static sun.nio.ch.sctp.ResultContainer.SEND_FAILED;
+import static sun.nio.ch.sctp.ResultContainer.ASSOCIATION_CHANGED;
+import static sun.nio.ch.sctp.ResultContainer.PEER_ADDRESS_CHANGED;
+import static sun.nio.ch.sctp.ResultContainer.SHUTDOWN;
+
+/**
+ * An implementation of an SctpChannel
+ */
+public class SctpChannelImpl extends SctpChannel
+    implements SelChImpl
+{
+    private final FileDescriptor fd;
+
+    private final int fdVal;
+
+    /* IDs of native threads doing send and receivess, for signalling */
+    private volatile long receiverThread = 0;
+    private volatile long senderThread = 0;
+
+    /* Lock held by current receiving or connecting thread */
+    private final Object receiveLock = new Object();
+
+    /* Lock held by current sending or connecting thread */
+    private final Object sendLock = new Object();
+
+    private final ThreadLocal<Boolean> receiveInvoked =
+        new ThreadLocal<Boolean>() {
+             @Override protected Boolean initialValue() {
+                 return Boolean.FALSE;
+            }
+    };
+
+    /* Lock held by any thread that modifies the state fields declared below
+       DO NOT invoke a blocking I/O operation while holding this lock! */
+    private final Object stateLock = new Object();
+
+    private enum ChannelState {
+        UNINITIALIZED,
+        UNCONNECTED,
+        PENDING,
+        CONNECTED,
+        KILLPENDING,
+        KILLED,
+    }
+    /* -- The following fields are protected by stateLock -- */
+    private ChannelState state = ChannelState.UNINITIALIZED;
+
+    /* Binding; Once bound the port will remain constant. */
+    int port = -1;
+    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
+    /* Has the channel been bound to the wildcard address */
+    private boolean wildcard; /* false */
+    //private InetSocketAddress remoteAddress = null;
+
+    /* Input/Output open */
+    private boolean readyToConnect;
+
+    /* Shutdown */
+    private boolean isShutdown;
+
+    private Association association;
+
+    private Set<SocketAddress> remoteAddresses = Collections.emptySet();
+
+    /* -- End of fields protected by stateLock -- */
+
+    /**
+     * Constructor for normal connecting sockets
+     */
+    public SctpChannelImpl(SelectorProvider provider) throws IOException {
+        //TODO: update provider remove public modifier
+        super(provider);
+        this.fd = SctpNet.socket(true);
+        this.fdVal = IOUtil.fdVal(fd);
+        this.state = ChannelState.UNCONNECTED;
+    }
+
+    /**
+     * Constructor for sockets obtained from server sockets
+     */
+    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();
+
+        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);
+            }
+        }
+    }
+
+    /**
+     * Binds the channel's socket to a local address.
+     */
+    @Override
+    public SctpChannel bind(SocketAddress local) throws IOException {
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                synchronized (stateLock) {
+                    ensureOpenAndUnconnected();
+                    if (isBound())
+                        SctpNet.throwAlreadyBoundException();
+                    InetSocketAddress isa = (local == null) ?
+                        new InetSocketAddress(0) : Net.checkAddress(local);
+                    Net.bind(fd, isa.getAddress(), isa.getPort());
+                    InetSocketAddress boundIsa = Net.localAddress(fd);
+                    port = boundIsa.getPort();
+                    localAddresses.add(isa);
+                    if (isa.getAddress().isAnyLocalAddress())
+                        wildcard = true;
+                }
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public SctpChannel bindAddress(InetAddress address)
+            throws IOException {
+        bindUnbindAddress(address, true);
+        localAddresses.add(new InetSocketAddress(address, port));
+        return this;
+    }
+
+    @Override
+    public SctpChannel unbindAddress(InetAddress address)
+            throws IOException {
+        bindUnbindAddress(address, false);
+        localAddresses.remove(new InetSocketAddress(address, port));
+        return this;
+    }
+
+    private SctpChannel bindUnbindAddress(InetAddress address, boolean add)
+            throws IOException {
+        if (address == null)
+            throw new IllegalArgumentException();
+
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        throw new ClosedChannelException();
+                    if (!isBound())
+                        throw new NotYetBoundException();
+                    if (wildcard)
+                        throw new IllegalStateException(
+                                "Cannot add or remove addresses from a channel that is bound to the wildcard address");
+                    if (address.isAnyLocalAddress())
+                        throw new IllegalArgumentException(
+                                "Cannot add or remove the wildcard address");
+                    if (add) {
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                SctpNet.throwAlreadyBoundException();
+                            }
+                        }
+                    } else { /*removing */
+                        /* Verify that there is more than one address
+                         * and that address is already bound */
+                        if (localAddresses.size() <= 1)
+                            throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
+                        boolean foundAddress = false;
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                foundAddress = true;
+                                break;
+                            }
+                        }
+                        if (!foundAddress )
+                            throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
+                    }
+
+                    SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
+
+                    /* Update our internal Set to reflect the addition/removal */
+                    if (add)
+                        localAddresses.add(new InetSocketAddress(address, port));
+                    else {
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                localAddresses.remove(addr);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
+    private boolean isBound() {
+        synchronized (stateLock) {
+            return port == -1 ? false : true;
+        }
+    }
+
+    private boolean isConnected() {
+        synchronized (stateLock) {
+            return (state == ChannelState.CONNECTED);
+        }
+    }
+
+    private void ensureOpenAndUnconnected() throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (isConnected())
+                throw new AlreadyConnectedException();
+            if (state == ChannelState.PENDING)
+                throw new ConnectionPendingException();
+        }
+    }
+
+    private boolean ensureReceiveOpen() throws ClosedChannelException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isConnected())
+                throw new NotYetConnectedException();
+            else
+                return true;
+        }
+    }
+
+    private void ensureSendOpen() throws ClosedChannelException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (isShutdown)
+                throw new ClosedChannelException();
+            if (!isConnected())
+                throw new NotYetConnectedException();
+        }
+    }
+
+    private void receiverCleanup() throws IOException {
+        synchronized (stateLock) {
+            receiverThread = 0;
+            if (state == ChannelState.KILLPENDING)
+                kill();
+        }
+    }
+
+    private void senderCleanup() throws IOException {
+        synchronized (stateLock) {
+            senderThread = 0;
+            if (state == ChannelState.KILLPENDING)
+                kill();
+        }
+    }
+
+    @Override
+    public Association association() throws ClosedChannelException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isConnected())
+                return null;
+
+            return association;
+        }
+    }
+
+    @Override
+    public boolean connect(SocketAddress endpoint) throws IOException {
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                ensureOpenAndUnconnected();
+                InetSocketAddress isa = Net.checkAddress(endpoint);
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkConnect(isa.getAddress().getHostAddress(),
+                                    isa.getPort());
+                synchronized (blockingLock()) {
+                    int n = 0;
+                    try {
+                        try {
+                            begin();
+                            synchronized (stateLock) {
+                                if (!isOpen()) {
+                                    return false;
+                                }
+                                receiverThread = NativeThread.current();
+                            }
+                            for (;;) {
+                                InetAddress ia = isa.getAddress();
+                                if (ia.isAnyLocalAddress())
+                                    ia = InetAddress.getLocalHost();
+                                n = SctpNet.connect(fdVal, ia, isa.getPort());
+                                if (  (n == IOStatus.INTERRUPTED)
+                                      && isOpen())
+                                    continue;
+                                break;
+                            }
+                        } finally {
+                            receiverCleanup();
+                            end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                            assert IOStatus.check(n);
+                        }
+                    } catch (IOException x) {
+                        /* If an exception was thrown, close the channel after
+                         * invoking end() so as to avoid bogus
+                         * AsynchronousCloseExceptions */
+                        close();
+                        throw x;
+                    }
+
+                    if (n > 0) {
+                        synchronized (stateLock) {
+                            /* Connection succeeded */
+                            state = ChannelState.CONNECTED;
+                            if (!isBound()) {
+                                InetSocketAddress boundIsa =
+                                        Net.localAddress(fd);
+                                port = boundIsa.getPort();
+                            }
+
+                            /* Receive COMM_UP */
+                            ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
+                            try {
+                                receive(buf, null, null, true);
+                            } finally {
+                                Util.releaseTemporaryDirectBuffer(buf);
+                            }
+
+                            /* cache remote addresses */
+                            try {
+                                remoteAddresses = getRemoteAddresses();
+                            } catch (IOException unused) { /* swallow exception */ }
+
+                            return true;
+                        }
+                    } else  {
+                        synchronized (stateLock) {
+                            /* If nonblocking and no exception then connection
+                             * pending; disallow another invocation */
+                            if (!isBlocking())
+                                state = ChannelState.PENDING;
+                            else
+                                assert false;
+                        }
+                    }
+                }
+                return false;
+            }
+        }
+    }
+
+    @Override
+    public boolean connect(SocketAddress endpoint,
+                           int maxOutStreams,
+                           int maxInStreams)
+            throws IOException {
+        ensureOpenAndUnconnected();
+        return setOption(SCTP_INIT_MAXSTREAMS, InitMaxStreams.
+                create(maxInStreams, maxOutStreams)).connect(endpoint);
+
+    }
+
+    @Override
+    public boolean isConnectionPending() {
+        synchronized (stateLock) {
+            return (state == ChannelState.PENDING);
+        }
+    }
+
+    @Override
+    public boolean finishConnect() throws IOException {
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        throw new ClosedChannelException();
+                    if (isConnected())
+                        return true;
+                    if (state != ChannelState.PENDING)
+                        throw new NoConnectionPendingException();
+                }
+                int n = 0;
+                try {
+                    try {
+                        begin();
+                        synchronized (blockingLock()) {
+                            synchronized (stateLock) {
+                                if (!isOpen()) {
+                                    return false;
+                                }
+                                receiverThread = NativeThread.current();
+                            }
+                            if (!isBlocking()) {
+                                for (;;) {
+                                    n = checkConnect(fd, false, readyToConnect);
+                                    if (  (n == IOStatus.INTERRUPTED)
+                                          && isOpen())
+                                        continue;
+                                    break;
+                                }
+                            } else {
+                                for (;;) {
+                                    n = checkConnect(fd, true, readyToConnect);
+                                    if (n == 0) {
+                                        // Loop in case of
+                                        // spurious notifications
+                                        continue;
+                                    }
+                                    if (  (n == IOStatus.INTERRUPTED)
+                                          && isOpen())
+                                        continue;
+                                    break;
+                                }
+                            }
+                        }
+                    } finally {
+                        synchronized (stateLock) {
+                            receiverThread = 0;
+                            if (state == ChannelState.KILLPENDING) {
+                                kill();
+                                /* poll()/getsockopt() does not report
+                                 * error (throws exception, with n = 0)
+                                 * on Linux platform after dup2 and
+                                 * signal-wakeup. Force n to 0 so the
+                                 * end() can throw appropriate exception */
+                                n = 0;
+                            }
+                        }
+                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                        assert IOStatus.check(n);
+                    }
+                } catch (IOException x) {
+                    /* If an exception was thrown, close the channel after
+                     * invoking end() so as to avoid bogus
+                     * AsynchronousCloseExceptions */
+                    close();
+                    throw x;
+                }
+
+                if (n > 0) {
+                    synchronized (stateLock) {
+                        state = ChannelState.CONNECTED;
+                        if (!isBound()) {
+                            InetSocketAddress boundIsa =
+                                    Net.localAddress(fd);
+                            port = boundIsa.getPort();
+                        }
+
+                        /* Receive COMM_UP */
+                        ByteBuffer buf = Util.getTemporaryDirectBuffer(50);
+                        try {
+                            receive(buf, null, null, true);
+                        } finally {
+                            Util.releaseTemporaryDirectBuffer(buf);
+                        }
+
+                        /* cache remote addresses */
+                        try {
+                            remoteAddresses = getRemoteAddresses();
+                        } catch (IOException unused) { /* swallow exception */ }
+
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected void implConfigureBlocking(boolean block) throws IOException {
+        IOUtil.configureBlocking(fd, block);
+    }
+
+    @Override
+    public void implCloseSelectableChannel() throws IOException {
+        synchronized (stateLock) {
+            SctpNet.preClose(fdVal);
+
+            if (receiverThread != 0)
+                NativeThread.signal(receiverThread);
+
+            if (senderThread != 0)
+                NativeThread.signal(senderThread);
+
+            if (!isRegistered())
+                kill();
+        }
+    }
+
+    @Override
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    @Override
+    public int getFDVal() {
+        return fdVal;
+    }
+
+    /**
+     * Translates native poll revent ops into a ready operation ops
+     */
+    private boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl sk) {
+        int intOps = sk.nioInterestOps();
+        int oldOps = sk.nioReadyOps();
+        int newOps = initialOps;
+
+        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+            /* This should only happen if this channel is pre-closed while a
+             * selection operation is in progress
+             * ## Throw an error if this channel has not been pre-closed */
+            return false;
+        }
+
+        if ((ops & (PollArrayWrapper.POLLERR
+                    | PollArrayWrapper.POLLHUP)) != 0) {
+            newOps = intOps;
+            sk.nioReadyOps(newOps);
+            /* No need to poll again in checkConnect,
+             * the error will be detected there */
+            readyToConnect = true;
+            return (newOps & ~oldOps) != 0;
+        }
+
+        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+            ((intOps & SelectionKey.OP_READ) != 0) &&
+            isConnected())
+            newOps |= SelectionKey.OP_READ;
+
+        if (((ops & PollArrayWrapper.POLLCONN) != 0) &&
+            ((intOps & SelectionKey.OP_CONNECT) != 0) &&
+            ((state == ChannelState.UNCONNECTED) || (state == ChannelState.PENDING))) {
+            newOps |= SelectionKey.OP_CONNECT;
+            readyToConnect = true;
+        }
+
+        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+            ((intOps & SelectionKey.OP_WRITE) != 0) &&
+            isConnected())
+            newOps |= SelectionKey.OP_WRITE;
+
+        sk.nioReadyOps(newOps);
+        return (newOps & ~oldOps) != 0;
+    }
+
+    @Override
+    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, sk.nioReadyOps(), sk);
+    }
+
+    @Override
+    @SuppressWarnings("all")
+    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, 0, sk);
+    }
+
+    @Override
+    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
+        int newOps = 0;
+        if ((ops & SelectionKey.OP_READ) != 0)
+            newOps |= PollArrayWrapper.POLLIN;
+        if ((ops & SelectionKey.OP_WRITE) != 0)
+            newOps |= PollArrayWrapper.POLLOUT;
+        if ((ops & SelectionKey.OP_CONNECT) != 0)
+            newOps |= PollArrayWrapper.POLLCONN;
+        sk.selector.putEventOps(sk, newOps);
+    }
+
+    @Override
+    public void kill() throws IOException {
+        synchronized (stateLock) {
+            if (state == ChannelState.KILLED)
+                return;
+            if (state == ChannelState.UNINITIALIZED) {
+                state = ChannelState.KILLED;
+                return;
+            }
+            assert !isOpen() && !isRegistered();
+
+            /* Postpone the kill if there is a waiting reader
+             * or writer thread. */
+            if (receiverThread == 0 && senderThread == 0) {
+                SctpNet.close(fdVal);
+                state = ChannelState.KILLED;
+            } else {
+                state = ChannelState.KILLPENDING;
+            }
+        }
+    }
+
+    @Override
+    public <T> SctpChannel setOption(SctpSocketOption<T> name, T value)
+            throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            SctpNet.setSocketOption(fdVal, name, value, 0 /*oneToOne*/);
+        }
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SctpSocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            return (T)SctpNet.getSocketOption(fdVal, name, 0 /*oneToOne*/);
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SctpSocketOption<?>> defaultOptions() {
+            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
+            set.add(SCTP_DISABLE_FRAGMENTS);
+            set.add(SCTP_EXPLICIT_COMPLETE);
+            set.add(SCTP_FRAGMENT_INTERLEAVE);
+            set.add(SCTP_INIT_MAXSTREAMS);
+            set.add(SCTP_NODELAY);
+            set.add(SCTP_PRIMARY_ADDR);
+            set.add(SCTP_SET_PEER_PRIMARY_ADDR);
+            set.add(SO_SNDBUF);
+            set.add(SO_RCVBUF);
+            set.add(SO_LINGER);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    @Override
+    public final Set<SctpSocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    @Override
+    public <T> MessageInfo receive(ByteBuffer buffer,
+                                   T attachment,
+                                   NotificationHandler<T> handler)
+            throws IOException {
+        return receive(buffer, attachment, handler, false);
+    }
+
+    private <T> MessageInfo receive(ByteBuffer buffer,
+                                    T attachment,
+                                    NotificationHandler<T> handler,
+                                    boolean fromConnect)
+            throws IOException {
+        if (buffer == null)
+            throw new IllegalArgumentException("buffer cannot be null");
+
+        if (buffer.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+
+        if (receiveInvoked.get())
+            throw new IllegalReceiveException(
+                    "cannot invoke receive from handler");
+        receiveInvoked.set(Boolean.TRUE);
+
+        try {
+            ResultContainer resultContainer = new ResultContainer();
+            do {
+                resultContainer.clear();
+                synchronized (receiveLock) {
+                    if (!ensureReceiveOpen())
+                        return null;
+
+                    int n = 0;
+                    try {
+                        begin();
+
+                        synchronized (stateLock) {
+                            if(!isOpen())
+                                return null;
+                            receiverThread = NativeThread.current();
+                        }
+
+                        do {
+                            n = receive(fdVal, buffer, resultContainer, fromConnect);
+                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
+                    } finally {
+                        receiverCleanup();
+                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                        assert IOStatus.check(n);
+                    }
+
+                    if (!resultContainer.isNotification()) {
+                        /* message or nothing */
+                        if (resultContainer.hasSomething()) {
+                            /* Set the association before returning */
+                            MessageInfoImpl info =
+                                    resultContainer.getMessageInfo();
+                            synchronized (stateLock) {
+                                assert association != null;
+                                info.setAssociation(association);
+                            }
+                            return info;
+                        } else
+                            /* Non-blocking may return null if nothing available*/
+                            return null;
+                    } else { /* notification */
+                        synchronized (stateLock) {
+                            handleNotificationInternal(
+                                    resultContainer);
+                        }
+                    }
+
+                    if (fromConnect)  {
+                        /* If we reach here, then it was connect that invoked
+                         * receive and received the COMM_UP. We have already
+                         * handled the COMM_UP with the internal notification
+                         * handler. Simply return. */
+                        return null;
+                    }
+                }  /* receiveLock */
+            } while (handler == null ? true :
+                (invokeNotificationHandler(resultContainer, handler, attachment)
+                 == HandlerResult.CONTINUE));
+
+            return null;
+        } finally {
+            receiveInvoked.set(Boolean.FALSE);
+        }
+    }
+
+    private int receive(int fd,
+                        ByteBuffer dst,
+                        ResultContainer resultContainer,
+                        boolean peek)
+            throws IOException {
+        int pos = dst.position();
+        int lim = dst.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        if (dst instanceof DirectBuffer && rem > 0)
+            return receiveIntoNativeBuffer(fd, resultContainer, dst, rem, pos, peek);
+
+        /* Substitute a native buffer */
+        int newSize = Math.max(rem, 1);
+        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
+        try {
+            int n = receiveIntoNativeBuffer(fd, resultContainer, bb, newSize, 0, peek);
+            bb.flip();
+            if (n > 0 && rem > 0)
+                dst.put(bb);
+            return n;
+        } finally {
+            Util.releaseTemporaryDirectBuffer(bb);
+        }
+    }
+
+    private int receiveIntoNativeBuffer(int fd,
+                                        ResultContainer resultContainer,
+                                        ByteBuffer bb,
+                                        int rem,
+                                        int pos,
+                                        boolean peek)
+        throws IOException
+    {
+        int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek);
+
+        if (n > 0)
+            bb.position(pos + n);
+        return n;
+    }
+
+    private InternalNotificationHandler internalNotificationHandler =
+            new InternalNotificationHandler();
+
+    private void handleNotificationInternal(ResultContainer resultContainer)
+    {
+        invokeNotificationHandler(resultContainer,
+                internalNotificationHandler, null);
+    }
+
+    private class InternalNotificationHandler
+            extends AbstractNotificationHandler<Object>
+    {
+        @Override
+        public HandlerResult handleNotification(
+                AssociationChangeNotification not, Object unused) {
+            if (not.event().equals(
+                    AssociationChangeNotification.AssocChangeEvent.COMM_UP) &&
+                    association == null) {
+                AssociationChange sac = (AssociationChange) not;
+                association = new AssociationImpl
+                       (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams());
+            }
+            return HandlerResult.CONTINUE;
+        }
+    }
+
+    private <T> HandlerResult invokeNotificationHandler
+                                 (ResultContainer resultContainer,
+                                  NotificationHandler<T> handler,
+                                  T attachment) {
+        SctpNotification notification = resultContainer.notification();
+        synchronized (stateLock) {
+            notification.setAssociation(association);
+        }
+
+        if (!(handler instanceof AbstractNotificationHandler)) {
+            return handler.handleNotification(notification, attachment);
+        }
+
+        /* AbstractNotificationHandler */
+        AbstractNotificationHandler<T> absHandler =
+                (AbstractNotificationHandler<T>)handler;
+        switch(resultContainer.type()) {
+            case ASSOCIATION_CHANGED :
+                return absHandler.handleNotification(
+                        resultContainer.getAssociationChanged(), attachment);
+            case PEER_ADDRESS_CHANGED :
+                return absHandler.handleNotification(
+                        resultContainer.getPeerAddressChanged(), attachment);
+            case SEND_FAILED :
+                return absHandler.handleNotification(
+                        resultContainer.getSendFailed(), attachment);
+            case SHUTDOWN :
+                return absHandler.handleNotification(
+                        resultContainer.getShutdown(), attachment);
+            default :
+                /* implementation specific handlers */
+                return absHandler.handleNotification(
+                        resultContainer.notification(), attachment);
+        }
+    }
+
+    private void checkAssociation(Association sendAssociation) {
+        synchronized (stateLock) {
+            if (sendAssociation != null && !sendAssociation.equals(association)) {
+                throw new IllegalArgumentException(
+                        "Cannot send to another association");
+            }
+        }
+    }
+
+    private void checkStreamNumber(int streamNumber) {
+        synchronized (stateLock) {
+            if (association != null) {
+                if (streamNumber < 0 ||
+                      streamNumber >= association.maxOutboundStreams())
+                    throw new InvalidStreamException();
+            }
+        }
+    }
+
+    /* TODO: Add support for ttl and isComplete to both 121 12M
+     *       SCTP_EOR not yet supported on reference platforms
+     *       TTL support limited...
+     */
+    @Override
+    public int send(ByteBuffer buffer, MessageInfo messageInfo)
+            throws IOException {
+        if (buffer == null)
+            throw new IllegalArgumentException("buffer cannot be null");
+
+        if (messageInfo == null)
+            throw new IllegalArgumentException("messageInfo cannot be null");
+
+        checkAssociation(messageInfo.association());
+        checkStreamNumber(messageInfo.streamNumber());
+
+        synchronized (sendLock) {
+            ensureSendOpen();
+
+            int n = 0;
+            try {
+                begin();
+
+                synchronized (stateLock) {
+                    if(!isOpen())
+                        return 0;
+                    senderThread = NativeThread.current();
+                }
+
+                do {
+                    n = send(fdVal, buffer, messageInfo);
+                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+
+                return IOStatus.normalize(n);
+            } finally {
+                senderCleanup();
+                end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                assert IOStatus.check(n);
+            }
+        }
+    }
+
+    private int send(int fd, ByteBuffer src, MessageInfo messageInfo)
+            throws IOException {
+        int streamNumber = messageInfo.streamNumber();
+        SocketAddress target = messageInfo.address();
+        boolean unordered = messageInfo.isUnordered();
+        int ppid = messageInfo.payloadProtocolID();
+
+        if (src instanceof DirectBuffer)
+            return sendFromNativeBuffer(fd, src, target, streamNumber,
+                    unordered, ppid);
+
+        /* Substitute a native buffer */
+        int pos = src.position();
+        int lim = src.limit();
+        assert (pos <= lim && streamNumber >= 0);
+
+        int rem = (pos <= lim ? lim - pos : 0);
+        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
+        try {
+            bb.put(src);
+            bb.flip();
+            /* Do not update src until we see how many bytes were written */
+            src.position(pos);
+
+            int n = sendFromNativeBuffer(fd, bb, target, streamNumber,
+                    unordered, ppid);
+            if (n > 0) {
+                /* now update src */
+                src.position(pos + n);
+            }
+            return n;
+        } finally {
+            Util.releaseTemporaryDirectBuffer(bb);
+        }
+    }
+
+    private int sendFromNativeBuffer(int fd,
+                                     ByteBuffer bb,
+                                     SocketAddress target,
+                                     int streamNumber,
+                                     boolean unordered,
+                                     int ppid)
+            throws IOException {
+        int pos = bb.position();
+        int lim = bb.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        int written = send0(fd, ((DirectBuffer)bb).address() + pos,
+                            rem, target, -1 /*121*/, streamNumber, unordered, ppid);
+        if (written > 0)
+            bb.position(pos + written);
+        return written;
+    }
+
+    @Override
+    public SctpChannel shutdown() throws IOException {
+        synchronized(stateLock) {
+            if (isShutdown)
+                return this;
+
+            ensureSendOpen();
+            SctpNet.shutdown(fdVal, -1);
+            if (senderThread != 0)
+                NativeThread.signal(senderThread);
+            isShutdown = true;
+        }
+        return this;
+    }
+
+    @Override
+    public Set<SocketAddress> getAllLocalAddresses()
+            throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isBound())
+                return Collections.emptySet();
+
+            return SctpNet.getLocalAddresses(fdVal);
+        }
+    }
+
+    @Override
+    public Set<SocketAddress> getRemoteAddresses()
+            throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isConnected() || isShutdown)
+                return Collections.emptySet();
+
+            try {
+                return SctpNet.getRemoteAddresses(fdVal, 0/*unused*/);
+            } catch (SocketException unused) {
+                /* an open connected channel should always have remote addresses */
+                return remoteAddresses;
+            }
+        }
+    }
+
+    /* Native */
+    private static native void initIDs();
+
+    static native int receive0(int fd, ResultContainer resultContainer,
+            long address, int length, boolean peek) throws IOException;
+
+    static native int send0(int fd, long address, int length,
+            SocketAddress target, int assocId, int streamNumber,
+            boolean unordered, int ppid) throws IOException;
+
+    private static native int checkConnect(FileDescriptor fd, boolean block,
+            boolean ready) throws IOException;
+
+    static {
+        Util.load();   /* loads nio & net native libraries */
+        java.security.AccessController.doPrivileged(
+                new sun.security.action.LoadLibraryAction("sctp"));
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,994 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.InetSocketAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.spi.SelectorProvider;
+import com.sun.nio.sctp.AbstractNotificationHandler;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.AssociationChangeNotification;
+import com.sun.nio.sctp.HandlerResult;
+import com.sun.nio.sctp.IllegalReceiveException;
+import com.sun.nio.sctp.InvalidStreamException;
+import com.sun.nio.sctp.IllegalUnbindException;
+import com.sun.nio.sctp.NotificationHandler;
+import com.sun.nio.sctp.MessageInfo;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpMultiChannel;
+import com.sun.nio.sctp.SctpSocketOption;
+import sun.nio.ch.DirectBuffer;
+import sun.nio.ch.NativeThread;
+import sun.nio.ch.IOStatus;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.Net;
+import sun.nio.ch.PollArrayWrapper;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import sun.nio.ch.Util;
+import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
+import static sun.nio.ch.sctp.ResultContainer.*;
+
+/**
+ * An implementation of SctpMultiChannel
+ */
+public class SctpMultiChannelImpl extends SctpMultiChannel
+    implements SelChImpl
+{
+    private final FileDescriptor fd;
+
+    private final int fdVal;
+
+    /* IDs of native threads doing send and receives, for signalling */
+    private volatile long receiverThread = 0;
+    private volatile long senderThread = 0;
+
+    /* Lock held by current receiving thread */
+    private final Object receiveLock = new Object();
+
+    /* Lock held by current sending thread */
+    private final Object sendLock = new Object();
+
+    /* Lock held by any thread that modifies the state fields declared below
+     * DO NOT invoke a blocking I/O operation while holding this lock! */
+    private final Object stateLock = new Object();
+
+    private enum ChannelState {
+        UNINITIALIZED,
+        KILLPENDING,
+        KILLED,
+    }
+
+    /* -- The following fields are protected by stateLock -- */
+    private ChannelState state = ChannelState.UNINITIALIZED;
+
+    /* Binding: Once bound the port will remain constant. */
+    int port = -1;
+    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
+    /* Has the channel been bound to the wildcard address */
+    private boolean wildcard; /* false */
+
+    /* Keeps a map of addresses to association, and visa versa */
+    private HashMap<SocketAddress, Association> addressMap =
+                         new HashMap<SocketAddress, Association>();
+    private HashMap<Association, Set<SocketAddress>> associationMap =
+                         new HashMap<Association, Set<SocketAddress>>();
+
+    /* -- End of fields protected by stateLock -- */
+
+    /* If an association has been shutdown mark it for removal after
+     * the user handler has been invoked */
+    private final ThreadLocal<Association> associationToRemove =
+        new ThreadLocal<Association>() {
+             @Override protected Association initialValue() {
+                 return null;
+            }
+    };
+
+    /* A notification handler cannot invoke receive */
+    private final ThreadLocal<Boolean> receiveInvoked =
+        new ThreadLocal<Boolean>() {
+             @Override protected Boolean initialValue() {
+                 return Boolean.FALSE;
+            }
+    };
+
+    public SctpMultiChannelImpl(SelectorProvider provider)
+            throws IOException {
+        //TODO: update provider, remove public modifier
+        super(provider);
+        this.fd = SctpNet.socket(false /*one-to-many*/);
+        this.fdVal = IOUtil.fdVal(fd);
+    }
+
+    @Override
+    public SctpMultiChannel bind(SocketAddress local, int backlog)
+            throws IOException {
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                synchronized (stateLock) {
+                    ensureOpen();
+                    if (isBound())
+                        SctpNet.throwAlreadyBoundException();
+                    InetSocketAddress isa = (local == null) ?
+                        new InetSocketAddress(0) : Net.checkAddress(local);
+
+                    SecurityManager sm = System.getSecurityManager();
+                    if (sm != null)
+                        sm.checkListen(isa.getPort());
+                    Net.bind(fd, isa.getAddress(), isa.getPort());
+
+                    InetSocketAddress boundIsa = Net.localAddress(fd);
+                    port = boundIsa.getPort();
+                    localAddresses.add(isa);
+                    if (isa.getAddress().isAnyLocalAddress())
+                        wildcard = true;
+
+                    SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
+                }
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public SctpMultiChannel bindAddress(InetAddress address)
+            throws IOException {
+        return bindUnbindAddress(address, true);
+    }
+
+    @Override
+    public SctpMultiChannel unbindAddress(InetAddress address)
+            throws IOException {
+        return bindUnbindAddress(address, false);
+    }
+
+    private SctpMultiChannel bindUnbindAddress(InetAddress address,
+                                               boolean add)
+            throws IOException {
+        if (address == null)
+            throw new IllegalArgumentException();
+
+        synchronized (receiveLock) {
+            synchronized (sendLock) {
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        throw new ClosedChannelException();
+                    if (!isBound())
+                        throw new NotYetBoundException();
+                    if (wildcard)
+                        throw new IllegalStateException(
+                                "Cannot add or remove addresses from a channel that is bound to the wildcard address");
+                    if (address.isAnyLocalAddress())
+                        throw new IllegalArgumentException(
+                                "Cannot add or remove the wildcard address");
+                    if (add) {
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                SctpNet.throwAlreadyBoundException();
+                            }
+                        }
+                    } else { /*removing */
+                        /* Verify that there is more than one address
+                         * and that address is already bound */
+                        if (localAddresses.size() <= 1)
+                            throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
+                        boolean foundAddress = false;
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                foundAddress = true;
+                                break;
+                            }
+                        }
+                        if (!foundAddress )
+                            throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
+                    }
+
+                    SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
+
+                    /* Update our internal Set to reflect the addition/removal */
+                    if (add)
+                        localAddresses.add(new InetSocketAddress(address, port));
+                    else {
+                        for (InetSocketAddress addr : localAddresses) {
+                            if (addr.getAddress().equals(address)) {
+                                localAddresses.remove(addr);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public Set<Association> associations()
+            throws ClosedChannelException, NotYetBoundException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isBound())
+                throw new NotYetBoundException();
+
+            return Collections.unmodifiableSet(associationMap.keySet());
+        }
+    }
+
+    private boolean isBound() {
+        synchronized (stateLock) {
+            return port == -1 ? false : true;
+        }
+    }
+
+    private void ensureOpen() throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+        }
+    }
+
+    private void receiverCleanup() throws IOException {
+        synchronized (stateLock) {
+            receiverThread = 0;
+            if (state == ChannelState.KILLPENDING)
+                kill();
+        }
+    }
+
+    private void senderCleanup() throws IOException {
+        synchronized (stateLock) {
+            senderThread = 0;
+            if (state == ChannelState.KILLPENDING)
+                kill();
+        }
+    }
+
+    @Override
+    protected void implConfigureBlocking(boolean block) throws IOException {
+        IOUtil.configureBlocking(fd, block);
+    }
+
+    @Override
+    public void implCloseSelectableChannel() throws IOException {
+        synchronized (stateLock) {
+            SctpNet.preClose(fdVal);
+
+            if (receiverThread != 0)
+                NativeThread.signal(receiverThread);
+
+            if (senderThread != 0)
+                NativeThread.signal(senderThread);
+
+            if (!isRegistered())
+                kill();
+        }
+    }
+
+    @Override
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    @Override
+    public int getFDVal() {
+        return fdVal;
+    }
+
+    /**
+     * Translates native poll revent ops into a ready operation ops
+     */
+    private boolean translateReadyOps(int ops, int initialOps,
+                                      SelectionKeyImpl sk) {
+        int intOps = sk.nioInterestOps();
+        int oldOps = sk.nioReadyOps();
+        int newOps = initialOps;
+
+        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+            /* This should only happen if this channel is pre-closed while a
+             * selection operation is in progress
+             * ## Throw an error if this channel has not been pre-closed */
+            return false;
+        }
+
+        if ((ops & (PollArrayWrapper.POLLERR
+                    | PollArrayWrapper.POLLHUP)) != 0) {
+            newOps = intOps;
+            sk.nioReadyOps(newOps);
+            return (newOps & ~oldOps) != 0;
+        }
+
+        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+            ((intOps & SelectionKey.OP_READ) != 0))
+            newOps |= SelectionKey.OP_READ;
+
+        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+            ((intOps & SelectionKey.OP_WRITE) != 0))
+            newOps |= SelectionKey.OP_WRITE;
+
+        sk.nioReadyOps(newOps);
+        return (newOps & ~oldOps) != 0;
+    }
+
+    @Override
+    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, sk.nioReadyOps(), sk);
+    }
+
+    @Override
+    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, 0, sk);
+    }
+
+    @Override
+    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
+        int newOps = 0;
+        if ((ops & SelectionKey.OP_READ) != 0)
+            newOps |= PollArrayWrapper.POLLIN;
+        if ((ops & SelectionKey.OP_WRITE) != 0)
+            newOps |= PollArrayWrapper.POLLOUT;
+        sk.selector.putEventOps(sk, newOps);
+    }
+
+    @Override
+    public void kill() throws IOException {
+        synchronized (stateLock) {
+            if (state == ChannelState.KILLED)
+                return;
+            if (state == ChannelState.UNINITIALIZED) {
+                state = ChannelState.KILLED;
+                return;
+            }
+            assert !isOpen() && !isRegistered();
+
+            /* Postpone the kill if there is a thread sending or receiving. */
+            if (receiverThread == 0 && senderThread == 0) {
+                SctpNet.close(fdVal);
+                state = ChannelState.KILLED;
+            } else {
+                state = ChannelState.KILLPENDING;
+            }
+        }
+    }
+
+    @Override
+    public <T> SctpMultiChannel setOption(SctpSocketOption<T> name,
+                                          T value,
+                                          Association association)
+            throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!(supportedOptions().contains(name)))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (association != null && (name.equals(SCTP_PRIMARY_ADDR) ||
+                    name.equals(SCTP_SET_PEER_PRIMARY_ADDR))) {
+                checkAssociation(association);
+            }
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            int assocId = association == null ? 0 : association.associationID();
+            SctpNet.setSocketOption(fdVal, name, value, assocId);
+        }
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SctpSocketOption<T> name, Association association)
+            throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (association != null && (name.equals(SCTP_PRIMARY_ADDR) ||
+                    name.equals(SCTP_SET_PEER_PRIMARY_ADDR))) {
+                checkAssociation(association);
+            }
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            int assocId = association == null ? 0 : association.associationID();
+            return (T)SctpNet.getSocketOption(fdVal, name, assocId);
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SctpSocketOption<?>> defaultOptions() {
+            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(10);
+            set.add(SCTP_DISABLE_FRAGMENTS);
+            set.add(SCTP_EXPLICIT_COMPLETE);
+            set.add(SCTP_FRAGMENT_INTERLEAVE);
+            set.add(SCTP_INIT_MAXSTREAMS);
+            set.add(SCTP_NODELAY);
+            set.add(SCTP_PRIMARY_ADDR);
+            set.add(SCTP_SET_PEER_PRIMARY_ADDR);
+            set.add(SO_SNDBUF);
+            set.add(SO_RCVBUF);
+            set.add(SO_LINGER);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    @Override
+    public final Set<SctpSocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    @Override
+    public <T> MessageInfo receive(ByteBuffer buffer,
+                                   T attachment,
+                                   NotificationHandler<T> handler)
+            throws IOException {
+        if (buffer == null)
+            throw new IllegalArgumentException("buffer cannot be null");
+
+        if (buffer.isReadOnly())
+            throw new IllegalArgumentException("Read-only buffer");
+
+        if (receiveInvoked.get())
+            throw new IllegalReceiveException(
+                    "cannot invoke receive from handler");
+        receiveInvoked.set(Boolean.TRUE);
+
+        try {
+            ResultContainer resultContainer = new ResultContainer();
+            do {
+                resultContainer.clear();
+                synchronized (receiveLock) {
+                    ensureOpen();
+                    if (!isBound())
+                        throw new NotYetBoundException();
+
+                    int n = 0;
+                    try {
+                        begin();
+
+                        synchronized (stateLock) {
+                            if(!isOpen())
+                                return null;
+                            receiverThread = NativeThread.current();
+                        }
+
+                        do {
+                            n = receive(fdVal, buffer, resultContainer);
+                        } while ((n == IOStatus.INTERRUPTED) && isOpen());
+
+                    } finally {
+                        receiverCleanup();
+                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                        assert IOStatus.check(n);
+                    }
+
+                    if (!resultContainer.isNotification()) {
+                        /* message or nothing */
+                        if (resultContainer.hasSomething()) {
+                            /* Set the association before returning */
+                            MessageInfoImpl info =
+                                    resultContainer.getMessageInfo();
+                            info.setAssociation(lookupAssociation(info.
+                                    associationID()));
+                            SecurityManager sm = System.getSecurityManager();
+                            if (sm != null) {
+                                InetSocketAddress isa  = (InetSocketAddress)info.address();
+                                if (!addressMap.containsKey(isa)) {
+                                    /* must be a new association */
+                                    try {
+                                        sm.checkAccept(isa.getAddress().getHostAddress(),
+                                                       isa.getPort());
+                                    } catch (SecurityException se) {
+                                        buffer.clear();
+                                        throw se;
+                                    }
+                                }
+                            }
+
+                            assert info.association() != null;
+                            return info;
+                        } else  {
+                          /* Non-blocking may return null if nothing available*/
+                            return null;
+                        }
+                    } else { /* notification */
+                        synchronized (stateLock) {
+                            handleNotificationInternal(
+                                    resultContainer);
+                        }
+                    }
+                } /* receiveLock */
+            } while (handler == null ? true :
+                (invokeNotificationHandler(resultContainer, handler, attachment)
+                 == HandlerResult.CONTINUE));
+        } finally {
+            receiveInvoked.set(Boolean.FALSE);
+        }
+
+        return null;
+    }
+
+    private int receive(int fd,
+                        ByteBuffer dst,
+                        ResultContainer resultContainer)
+            throws IOException {
+        int pos = dst.position();
+        int lim = dst.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        if (dst instanceof DirectBuffer && rem > 0)
+            return receiveIntoNativeBuffer(fd, resultContainer, dst, rem, pos);
+
+        /* Substitute a native buffer. */
+        int newSize = Math.max(rem, 1);
+        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
+        try {
+            int n = receiveIntoNativeBuffer(fd, resultContainer, bb, newSize, 0);
+            bb.flip();
+            if (n > 0 && rem > 0)
+                dst.put(bb);
+            return n;
+        } finally {
+            Util.releaseTemporaryDirectBuffer(bb);
+        }
+    }
+
+    private int receiveIntoNativeBuffer(int fd,
+                                        ResultContainer resultContainer,
+                                        ByteBuffer bb,
+                                        int rem,
+                                        int pos)
+            throws IOException {
+        int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem);
+        if (n > 0)
+            bb.position(pos + n);
+        return n;
+    }
+
+    private InternalNotificationHandler internalNotificationHandler =
+            new InternalNotificationHandler();
+
+    private void handleNotificationInternal(ResultContainer resultContainer)
+    {
+        invokeNotificationHandler(resultContainer,
+                internalNotificationHandler, null);
+    }
+
+    private class InternalNotificationHandler
+            extends AbstractNotificationHandler<Object>
+    {
+        @Override
+        public HandlerResult handleNotification(
+                AssociationChangeNotification not, Object unused) {
+            AssociationChange sac = (AssociationChange) not;
+
+            /* Update map to reflect change in association */
+            switch (not.event()) {
+                case COMM_UP :
+                    Association newAssociation = new AssociationImpl
+                       (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams());
+                    addAssociation(newAssociation);
+                    break;
+                case SHUTDOWN :
+                case COMM_LOST :
+                //case RESTART: ???
+                    /* mark association for removal after user handler invoked*/
+                    associationToRemove.set(lookupAssociation(sac.assocId()));
+            }
+            return HandlerResult.CONTINUE;
+        }
+    }
+
+    private <T> HandlerResult invokeNotificationHandler(
+                                   ResultContainer resultContainer,
+                                   NotificationHandler<T> handler,
+                                   T attachment) {
+        HandlerResult result;
+        SctpNotification notification = resultContainer.notification();
+        notification.setAssociation(lookupAssociation(notification.assocId()));
+
+        if (!(handler instanceof AbstractNotificationHandler)) {
+            result = handler.handleNotification(notification, attachment);
+        } else { /* AbstractNotificationHandler */
+            AbstractNotificationHandler<T> absHandler =
+                    (AbstractNotificationHandler<T>)handler;
+            switch(resultContainer.type()) {
+                case ASSOCIATION_CHANGED :
+                    result = absHandler.handleNotification(
+                            resultContainer.getAssociationChanged(), attachment);
+                    break;
+                case PEER_ADDRESS_CHANGED :
+                    result = absHandler.handleNotification(
+                            resultContainer.getPeerAddressChanged(), attachment);
+                    break;
+                case SEND_FAILED :
+                    result = absHandler.handleNotification(
+                            resultContainer.getSendFailed(), attachment);
+                    break;
+                case SHUTDOWN :
+                    result =  absHandler.handleNotification(
+                            resultContainer.getShutdown(), attachment);
+                    break;
+                default :
+                    /* implementation specific handlers */
+                    result =  absHandler.handleNotification(
+                            resultContainer.notification(), attachment);
+            }
+        }
+
+        if (!(handler instanceof InternalNotificationHandler)) {
+            /* Only remove associations after user handler
+             * has finished with them */
+            Association assoc = associationToRemove.get();
+            if (assoc != null) {
+                removeAssociation(assoc);
+                associationToRemove.set(null);
+            }
+
+        }
+
+        return result;
+    }
+
+    private Association lookupAssociation(int assocId) {
+        /* Lookup the association in our internal map */
+        synchronized (stateLock) {
+            Set<Association> assocs = associationMap.keySet();
+            for (Association a : assocs) {
+                if (a.associationID() == assocId) {
+                    return a;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void addAssociation(Association association) {
+        synchronized (stateLock) {
+            int assocId = association.associationID();
+            Set<SocketAddress> addresses = null;
+
+            try {
+                addresses = SctpNet.getRemoteAddresses(fdVal, assocId);
+            } catch (IOException unused) {
+                /* OK, determining connected addresses may not be possible
+                 * shutdown, connection lost, etc */
+            }
+
+            associationMap.put(association, addresses);
+            if (addresses != null) {
+                for (SocketAddress addr : addresses)
+                    addressMap.put(addr, association);
+            }
+        }
+    }
+
+    private void removeAssociation(Association association) {
+        synchronized (stateLock) {
+            int assocId = association.associationID();
+            Set<SocketAddress> addresses = null;
+
+             try {
+                addresses = SctpNet.getRemoteAddresses(fdVal, assocId);
+            } catch (IOException unused) {
+                /* OK, determining connected addresses may not be possible
+                 * shutdown, connection lost, etc */
+            }
+
+            Set<Association> assocs = associationMap.keySet();
+            for (Association a : assocs) {
+                if (a.associationID() == assocId) {
+                    associationMap.remove(a);
+                    break;
+                }
+            }
+            if (addresses != null) {
+                for (SocketAddress addr : addresses)
+                    addressMap.remove(addr);
+            } else {
+                /* We cannot determine the connected addresses */
+                Set<java.util.Map.Entry<SocketAddress, Association>> addrAssocs =
+                        addressMap.entrySet();
+                Iterator<Entry<SocketAddress, Association>> iterator = addrAssocs.iterator();
+                while (iterator.hasNext()) {
+                    Entry<SocketAddress, Association> entry = iterator.next();
+                    if (entry.getValue().equals(association)) {
+                        iterator.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @throws  IllegalArgumentException
+     *          If the given association is not controlled by this channel
+     *
+     * @return  {@code true} if, and only if, the given association is one
+     *          of the current associations controlled by this channel
+     */
+    private boolean checkAssociation(Association messageAssoc) {
+        synchronized (stateLock) {
+            for (Association association : associationMap.keySet()) {
+                if (messageAssoc.equals(association)) {
+                    return true;
+                }
+            }
+        }
+        throw new IllegalArgumentException(
+              "Given Association is not controlled by this channel");
+    }
+
+    private void checkStreamNumber(Association assoc, int streamNumber) {
+        synchronized (stateLock) {
+            if (streamNumber < 0 || streamNumber >= assoc.maxOutboundStreams())
+                throw new InvalidStreamException();
+        }
+    }
+
+    /* TODO: Add support for ttl and isComplete to both 121 12M
+     *       SCTP_EOR not yet supported on reference platforms
+     *       TTL support limited...
+     */
+    @Override
+    public int send(ByteBuffer buffer, MessageInfo messageInfo)
+            throws IOException {
+        if (buffer == null)
+            throw new IllegalArgumentException("buffer cannot be null");
+
+        if (messageInfo == null)
+            throw new IllegalArgumentException("messageInfo cannot be null");
+
+        synchronized (sendLock) {
+            ensureOpen();
+
+            if (!isBound())
+                bind(null, 0);
+
+            int n = 0;
+            try {
+                int assocId = -1;
+                SocketAddress address = null;
+                begin();
+
+                synchronized (stateLock) {
+                    if(!isOpen())
+                        return 0;
+                    senderThread = NativeThread.current();
+
+                    /* Determine what address or association to send to */
+                    Association assoc = messageInfo.association();
+                    InetSocketAddress addr = (InetSocketAddress)messageInfo.address();
+                    if (assoc != null) {
+                        checkAssociation(assoc);
+                        checkStreamNumber(assoc, messageInfo.streamNumber());
+                        assocId = assoc.associationID();
+                        /* have we also got a preferred address */
+                        if (addr != null) {
+                            if (!assoc.equals(addressMap.get(addr)))
+                                throw new IllegalArgumentException("given preferred address is not part of this association");
+                            address = addr;
+                        }
+                    } else if (addr != null) {
+                        address = addr;
+                        Association association = addressMap.get(addr);
+                        if (association != null) {
+                            checkStreamNumber(association, messageInfo.streamNumber());
+                            assocId = association.associationID();
+
+                        } else { /* must be new association */
+                            SecurityManager sm = System.getSecurityManager();
+                            if (sm != null)
+                                sm.checkConnect(addr.getAddress().getHostAddress(),
+                                                addr.getPort());
+                        }
+                    } else {
+                        throw new AssertionError(
+                            "Both association and address cannot be null");
+                    }
+                }
+
+                do {
+                    n = send(fdVal, buffer, assocId, address, messageInfo);
+                } while ((n == IOStatus.INTERRUPTED) && isOpen());
+
+                return IOStatus.normalize(n);
+            } finally {
+                senderCleanup();
+                end((n > 0) || (n == IOStatus.UNAVAILABLE));
+                assert IOStatus.check(n);
+            }
+        }
+    }
+
+    private int send(int fd,
+                     ByteBuffer src,
+                     int assocId,
+                     SocketAddress target,
+                     MessageInfo messageInfo)
+            throws IOException {
+        int streamNumber = messageInfo.streamNumber();
+        boolean unordered = messageInfo.isUnordered();
+        int ppid = messageInfo.payloadProtocolID();
+
+        if (src instanceof DirectBuffer)
+            return sendFromNativeBuffer(fd, src, target, assocId,
+                    streamNumber, unordered, ppid);
+
+        /* Substitute a native buffer */
+        int pos = src.position();
+        int lim = src.limit();
+        assert (pos <= lim && streamNumber >= 0);
+
+        int rem = (pos <= lim ? lim - pos : 0);
+        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
+        try {
+            bb.put(src);
+            bb.flip();
+            /* Do not update src until we see how many bytes were written */
+            src.position(pos);
+
+            int n = sendFromNativeBuffer(fd, bb, target, assocId,
+                    streamNumber, unordered, ppid);
+            if (n > 0) {
+                /* now update src */
+                src.position(pos + n);
+            }
+            return n;
+        } finally {
+            Util.releaseTemporaryDirectBuffer(bb);
+        }
+    }
+
+    private int sendFromNativeBuffer(int fd,
+                                     ByteBuffer bb,
+                                     SocketAddress target,
+                                     int assocId,
+                                     int streamNumber,
+                                     boolean unordered,
+                                     int ppid)
+            throws IOException {
+        int pos = bb.position();
+        int lim = bb.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        int written = send0(fd, ((DirectBuffer)bb).address() + pos,
+                            rem, target, assocId, streamNumber, unordered, ppid);
+        if (written > 0)
+            bb.position(pos + written);
+        return written;
+    }
+
+    @Override
+    public SctpMultiChannel shutdown(Association association)
+            throws IOException {
+        synchronized (stateLock) {
+            checkAssociation(association);
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            SctpNet.shutdown(fdVal, association.associationID());
+        }
+        return this;
+    }
+
+    @Override
+    public Set<SocketAddress> getAllLocalAddresses()
+            throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isBound())
+                return Collections.emptySet();
+
+            return SctpNet.getLocalAddresses(fdVal);
+        }
+    }
+
+    @Override
+    public Set<SocketAddress> getRemoteAddresses(Association association)
+            throws IOException {
+        synchronized (stateLock) {
+            checkAssociation(association);
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            try {
+                return SctpNet.getRemoteAddresses(fdVal, association.associationID());
+            } catch (SocketException se) {
+                /* a valid association should always have remote addresses */
+                Set<SocketAddress> addrs = associationMap.get(association);
+                return addrs != null ? addrs : Collections.<SocketAddress>emptySet();
+            }
+        }
+    }
+
+    @Override
+    public SctpChannel branch(Association association)
+            throws IOException {
+        synchronized (stateLock) {
+            checkAssociation(association);
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            FileDescriptor bFd = SctpNet.branch(fdVal,
+                                                association.associationID());
+            /* successfully branched, we can now remove it from assoc list */
+            removeAssociation(association);
+
+            return new SctpChannelImpl(provider(), bFd, association);
+        }
+    }
+
+    /* Use common native implementation shared between
+     * one-to-one and one-to-many */
+    private static int receive0(int fd,
+                                ResultContainer resultContainer,
+                                long address,
+                                int length)
+            throws IOException{
+        return SctpChannelImpl.receive0(fd, resultContainer, address,
+                length, false /*peek */);
+    }
+
+    private static int send0(int fd,
+                             long address,
+                             int length,
+                             SocketAddress target,
+                             int assocId,
+                             int streamNumber,
+                             boolean unordered,
+                             int ppid)
+            throws IOException {
+        return SctpChannelImpl.send0(fd, address, length, target, assocId,
+                streamNumber, unordered, ppid);
+    }
+
+    static {
+        Util.load();   /* loads nio & net native libraries */
+        java.security.AccessController.doPrivileged(
+                new sun.security.action.LoadLibraryAction("sctp"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SctpNet.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.AlreadyBoundException;
+import java.util.Set;
+import java.util.HashSet;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.Net;
+import com.sun.nio.sctp.SctpSocketOption;
+import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
+
+public class SctpNet {
+    static final String osName = AccessController.doPrivileged(
+                    new GetPropertyAction("os.name"));
+
+    /* -- Miscellaneous SCTP utilities -- */
+
+    private static boolean IPv4MappedAddresses() {
+        if ("SunOS".equals(osName)) {
+            /* Solaris supports IPv4Mapped Addresses with bindx */
+            return true;
+        } /* else {  //other OS/implementations  */
+
+        /* lksctp/linux requires Ipv4 addresses */
+        return false;
+    }
+
+    static boolean throwAlreadyBoundException() throws IOException {
+        throw new AlreadyBoundException();
+    }
+
+    static void listen(int fd, int backlog) throws IOException {
+        listen0(fd, backlog);
+    }
+
+    static int connect(int fd, InetAddress remote, int remotePort)
+            throws IOException {
+        return connect0(fd, remote, remotePort);
+    }
+
+    static void close(int fd) throws IOException {
+        close0(fd);
+    }
+
+    static void preClose(int fd) throws IOException {
+        preClose0(fd);
+    }
+
+    /**
+     * @param  oneToOne
+     *         if {@code true} returns a one-to-one sctp socket, otherwise
+     *         returns a one-to-many sctp socket
+     */
+    static FileDescriptor socket(boolean oneToOne) throws IOException {
+        int nativefd = socket0(oneToOne);
+        return IOUtil.newFD(nativefd);
+    }
+
+    static void bindx(int fd, InetAddress[] addrs, int port, boolean add)
+            throws IOException {
+        bindx(fd, addrs, port, addrs.length, add,
+                IPv4MappedAddresses());
+    }
+
+    static Set<SocketAddress> getLocalAddresses(int fd)
+            throws IOException {
+        HashSet<SocketAddress> set = null;
+        SocketAddress[] saa = getLocalAddresses0(fd);
+
+        if (saa != null) {
+            set = new HashSet<SocketAddress>(saa.length);
+            for (SocketAddress sa : saa)
+                set.add(sa);
+        }
+
+        return set;
+    }
+
+    static Set<SocketAddress> getRemoteAddresses(int fd, int assocId)
+            throws IOException {
+        HashSet<SocketAddress> set = null;
+        SocketAddress[] saa = getRemoteAddresses0(fd, assocId);
+
+        if (saa != null) {
+            set = new HashSet<SocketAddress>(saa.length);
+            for (SocketAddress sa : saa)
+                set.add(sa);
+        }
+
+        return set;
+    }
+
+    static <T> void setSocketOption(int fd,
+                                    SctpSocketOption<T> name,
+                                    T value,
+                                    int assocId)
+            throws IOException {
+        if (value == null)
+            throw new IllegalArgumentException("Invalid option value");
+
+        if (name.equals(SCTP_INIT_MAXSTREAMS)) {
+            InitMaxStreams maxStreamValue = (InitMaxStreams)value;
+            SctpNet.setInitMsgOption0(fd,
+                 maxStreamValue.maxInStreams(), maxStreamValue.maxOutStreams());
+        } else if (name.equals(SCTP_PRIMARY_ADDR) ||
+                   name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) {
+
+            SocketAddress addr  = (SocketAddress) value;
+            if (addr == null)
+                throw new IllegalArgumentException("Invalid option value");
+
+            Net.checkAddress(addr);
+            InetSocketAddress netAddr = (InetSocketAddress)addr;
+
+            if (name.equals(SCTP_PRIMARY_ADDR)) {
+                setPrimAddrOption0(fd,
+                                   assocId,
+                                   netAddr.getAddress(),
+                                   netAddr.getPort());
+            } else {
+                setPeerPrimAddrOption0(fd,
+                                       assocId,
+                                       netAddr.getAddress(),
+                                       netAddr.getPort(),
+                                       IPv4MappedAddresses());
+            }
+        } else if (name.equals(SCTP_DISABLE_FRAGMENTS) ||
+            name.equals(SCTP_EXPLICIT_COMPLETE) ||
+            name.equals(SCTP_FRAGMENT_INTERLEAVE) ||
+            name.equals(SCTP_NODELAY) ||
+            name.equals(SO_SNDBUF) ||
+            name.equals(SO_RCVBUF) ||
+            name.equals(SO_LINGER)) {
+            setIntOption(fd, name, value);
+        } else {
+            throw new AssertionError("Unknown socket option");
+        }
+    }
+
+    static Object getSocketOption(int fd, SctpSocketOption<?> name, int assocId)
+             throws IOException {
+         if (name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) {
+            throw new IllegalArgumentException(
+                    "SCTP_SET_PEER_PRIMARY_ADDR cannot be retrieved");
+        } else if (name.equals(SCTP_INIT_MAXSTREAMS)) {
+            /* container for holding maxIn/Out streams */
+            int[] values = new int[2];
+            SctpNet.getInitMsgOption0(fd, values);
+            return InitMaxStreams.create(values[0], values[1]);
+        } else if (name.equals(SCTP_PRIMARY_ADDR)) {
+            return getPrimAddrOption0(fd, assocId);
+        } else if (name.equals(SCTP_DISABLE_FRAGMENTS) ||
+            name.equals(SCTP_EXPLICIT_COMPLETE) ||
+            name.equals(SCTP_FRAGMENT_INTERLEAVE) ||
+            name.equals(SCTP_NODELAY) ||
+            name.equals(SO_SNDBUF) ||
+            name.equals(SO_RCVBUF) ||
+            name.equals(SO_LINGER)) {
+            return getIntOption(fd, name);
+        } else {
+            throw new AssertionError("Unknown socket option");
+        }
+    }
+
+    static void setIntOption(int fd, SctpSocketOption<?> name, Object value)
+            throws IOException {
+        if (value == null)
+            throw new IllegalArgumentException("Invalid option value");
+
+        Class<?> type = name.type();
+        if (type != Integer.class && type != Boolean.class)
+            throw new AssertionError("Should not reach here");
+
+        if (name == SO_RCVBUF ||
+            name == SO_SNDBUF)
+        {
+            int i = ((Integer)value).intValue();
+            if (i < 0)
+                throw new IllegalArgumentException(
+                        "Invalid send/receive buffer size");
+        } else if (name == SO_LINGER) {
+            int i = ((Integer)value).intValue();
+            if (i < 0)
+                value = Integer.valueOf(-1);
+            if (i > 65535)
+                value = Integer.valueOf(65535);
+        } else if (name.equals(SCTP_FRAGMENT_INTERLEAVE)) {
+            int i = ((Integer)value).intValue();
+            if (i < 0 || i > 2)
+                throw new IllegalArgumentException(
+                        "Invalid value for SCTP_FRAGMENT_INTERLEAVE");
+        }
+
+        int arg;
+        if (type == Integer.class) {
+            arg = ((Integer)value).intValue();
+        } else {
+            boolean b = ((Boolean)value).booleanValue();
+            arg = (b) ? 1 : 0;
+        }
+
+        setIntOption0(fd, ((SctpStdSocketOption)name).constValue(), arg);
+    }
+
+    static Object getIntOption(int fd, SctpSocketOption<?> name)
+            throws IOException {
+        Class<?> type = name.type();
+
+        if (type != Integer.class && type != Boolean.class)
+            throw new AssertionError("Should not reach here");
+
+        if (!(name instanceof SctpStdSocketOption))
+            throw new AssertionError("Should not reach here");
+
+        int value = getIntOption0(fd,
+                ((SctpStdSocketOption)name).constValue());
+
+        if (type == Integer.class) {
+            return Integer.valueOf(value);
+        } else {
+            return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
+        }
+    }
+
+    static void shutdown(int fd, int assocId)
+            throws IOException {
+        shutdown0(fd, assocId);
+    }
+
+    static FileDescriptor branch(int fd, int assocId) throws IOException {
+        int nativefd = branch0(fd, assocId);
+        return IOUtil.newFD(nativefd);
+    }
+
+    /* Native Methods */
+    static native int socket0(boolean oneToOne) throws IOException;
+
+    static native void listen0(int fd, int backlog) throws IOException;
+
+    static native int connect0(int fd, InetAddress remote, int remotePort)
+        throws IOException;
+
+    static native void close0(int fd) throws IOException;
+
+    static native void preClose0(int fd) throws IOException;
+
+    static native void bindx(int fd, InetAddress[] addrs, int port, int length,
+            boolean add, boolean preferIPv6) throws IOException;
+
+    static native int getIntOption0(int fd, int opt) throws IOException;
+
+    static native void setIntOption0(int fd, int opt, int arg)
+        throws IOException;
+
+    static native SocketAddress[] getLocalAddresses0(int fd) throws IOException;
+
+    static native SocketAddress[] getRemoteAddresses0(int fd, int assocId)
+            throws IOException;
+
+    static native int branch0(int fd, int assocId) throws IOException;
+
+    static native void setPrimAddrOption0(int fd, int assocId, InetAddress ia,
+            int port) throws IOException;
+
+    static native void setPeerPrimAddrOption0(int fd, int assocId,
+            InetAddress ia, int port, boolean preferIPv6) throws IOException;
+
+    static native SocketAddress getPrimAddrOption0(int fd, int assocId)
+            throws IOException;
+
+    /* retVals [0] maxInStreams, [1] maxOutStreams */
+    static native void getInitMsgOption0(int fd, int[] retVals) throws IOException;
+
+    static native void setInitMsgOption0(int fd, int arg1, int arg2)
+            throws IOException;
+
+    static native void shutdown0(int fd, int assocId);
+
+    static native void init();
+
+    static {
+        init();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SctpNotification.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.Notification;
+
+/**
+ * All Notification implemenations MUST implement this interface to provide
+ * access to the native association identidier.
+ */
+interface SctpNotification extends Notification {
+    int assocId();
+    void setAssociation(Association association);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.net.InetAddress;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.spi.SelectorProvider;
+import com.sun.nio.sctp.IllegalUnbindException;
+import com.sun.nio.sctp.SctpChannel;
+import com.sun.nio.sctp.SctpServerChannel;
+import com.sun.nio.sctp.SctpSocketOption;
+import com.sun.nio.sctp.SctpStandardSocketOptions;
+import sun.nio.ch.DirectBuffer;
+import sun.nio.ch.NativeThread;
+import sun.nio.ch.IOStatus;
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.Net;
+import sun.nio.ch.PollArrayWrapper;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import sun.nio.ch.Util;
+
+/**
+ * An implementation of SctpServerChannel
+ */
+public class SctpServerChannelImpl extends SctpServerChannel
+    implements SelChImpl
+{
+    private final FileDescriptor fd;
+
+    private final int fdVal;
+
+    /* IDs of native thread doing accept, for signalling */
+    private volatile long thread = 0;
+
+    /* Lock held by thread currently blocked in this channel */
+    private final Object lock = new Object();
+
+    /* Lock held by any thread that modifies the state fields declared below
+     * DO NOT invoke a blocking I/O operation while holding this lock! */
+    private final Object stateLock = new Object();
+
+    private enum ChannelState {
+        UNINITIALIZED,
+        INUSE,
+        KILLPENDING,
+        KILLED,
+    }
+    /* -- The following fields are protected by stateLock -- */
+    private ChannelState state = ChannelState.UNINITIALIZED;
+
+    /* Binding: Once bound the port will remain constant. */
+    int port = -1;
+    private HashSet<InetSocketAddress> localAddresses = new HashSet<InetSocketAddress>();
+    /* Has the channel been bound to the wildcard address */
+    private boolean wildcard; /* false */
+
+    /* -- End of fields protected by stateLock -- */
+
+    /**
+     * Initializes a new instance of this class.
+     */
+    public SctpServerChannelImpl(SelectorProvider provider)
+            throws IOException {
+        //TODO: update provider remove public modifier
+        super(provider);
+        this.fd = SctpNet.socket(true);
+        this.fdVal = IOUtil.fdVal(fd);
+        this.state = ChannelState.INUSE;
+    }
+
+    @Override
+    public SctpServerChannel bind(SocketAddress local, int backlog)
+            throws IOException {
+        synchronized (lock) {
+            synchronized (stateLock) {
+                if (!isOpen())
+                    throw new ClosedChannelException();
+                if (isBound())
+                    SctpNet.throwAlreadyBoundException();
+
+                InetSocketAddress isa = (local == null) ?
+                    new InetSocketAddress(0) : Net.checkAddress(local);
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkListen(isa.getPort());
+                Net.bind(fd, isa.getAddress(), isa.getPort());
+
+                InetSocketAddress boundIsa = Net.localAddress(fd);
+                port = boundIsa.getPort();
+                localAddresses.add(isa);
+                    if (isa.getAddress().isAnyLocalAddress())
+                        wildcard = true;
+
+                SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public SctpServerChannel bindAddress(InetAddress address)
+            throws IOException {
+        return bindUnbindAddress(address, true);
+    }
+
+    @Override
+    public SctpServerChannel unbindAddress(InetAddress address)
+            throws IOException {
+        return bindUnbindAddress(address, false);
+    }
+
+    private SctpServerChannel bindUnbindAddress(InetAddress address, boolean add)
+            throws IOException {
+        if (address == null)
+            throw new IllegalArgumentException();
+
+        synchronized (lock) {
+            synchronized (stateLock) {
+                if (!isOpen())
+                    throw new ClosedChannelException();
+                if (!isBound())
+                    throw new NotYetBoundException();
+                if (wildcard)
+                    throw new IllegalStateException(
+                            "Cannot add or remove addresses from a channel that is bound to the wildcard address");
+                if (address.isAnyLocalAddress())
+                    throw new IllegalArgumentException(
+                            "Cannot add or remove the wildcard address");
+                if (add) {
+                    for (InetSocketAddress addr : localAddresses) {
+                        if (addr.getAddress().equals(address)) {
+                            SctpNet.throwAlreadyBoundException();
+                        }
+                    }
+                } else { /*removing */
+                    /* Verify that there is more than one address
+                     * and that address is already bound */
+                    if (localAddresses.size() <= 1)
+                        throw new IllegalUnbindException("Cannot remove address from a channel with only one address bound");
+                    boolean foundAddress = false;
+                    for (InetSocketAddress addr : localAddresses) {
+                        if (addr.getAddress().equals(address)) {
+                            foundAddress = true;
+                            break;
+                        }
+                    }
+                    if (!foundAddress )
+                        throw new IllegalUnbindException("Cannot remove address from a channel that is not bound to that address");
+                }
+
+                SctpNet.bindx(fdVal, new InetAddress[]{address}, port, add);
+
+                /* Update our internal Set to reflect the addition/removal */
+                if (add)
+                    localAddresses.add(new InetSocketAddress(address, port));
+                else {
+                    for (InetSocketAddress addr : localAddresses) {
+                        if (addr.getAddress().equals(address)) {
+                            localAddresses.remove(addr);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
+    private boolean isBound() {
+        synchronized (stateLock) {
+            return port == -1 ? false : true;
+        }
+    }
+
+    private void acceptCleanup() throws IOException {
+        synchronized (stateLock) {
+            thread = 0;
+            if (state == ChannelState.KILLPENDING)
+                kill();
+        }
+    }
+
+    @Override
+    public SctpChannel accept() throws IOException {
+        synchronized (lock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isBound())
+                throw new NotYetBoundException();
+            SctpChannel sc = null;
+
+            int n = 0;
+            FileDescriptor newfd = new FileDescriptor();
+            InetSocketAddress[] isaa = new InetSocketAddress[1];
+
+            try {
+                begin();
+                if (!isOpen())
+                    return null;
+                thread = NativeThread.current();
+                for (;;) {
+                    n = accept0(fd, newfd, isaa);
+                    if ((n == IOStatus.INTERRUPTED) && isOpen())
+                        continue;
+                    break;
+                }
+            } finally {
+                acceptCleanup();
+                end(n > 0);
+                assert IOStatus.check(n);
+            }
+
+            if (n < 1)
+                return null;
+
+            IOUtil.configureBlocking(newfd, true);
+            InetSocketAddress isa = isaa[0];
+            sc = new SctpChannelImpl(provider(), newfd);
+
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null)
+                sm.checkAccept(isa.getAddress().getHostAddress(),
+                               isa.getPort());
+
+            return sc;
+        }
+    }
+
+    @Override
+    protected void implConfigureBlocking(boolean block) throws IOException {
+        IOUtil.configureBlocking(fd, block);
+    }
+
+    @Override
+    public void implCloseSelectableChannel() throws IOException {
+        synchronized (stateLock) {
+            SctpNet.preClose(fdVal);
+            if (thread != 0)
+                NativeThread.signal(thread);
+            if (!isRegistered())
+                kill();
+        }
+    }
+
+    @Override
+    public void kill() throws IOException {
+        synchronized (stateLock) {
+            if (state == ChannelState.KILLED)
+                return;
+            if (state == ChannelState.UNINITIALIZED) {
+                state = ChannelState.KILLED;
+                return;
+            }
+            assert !isOpen() && !isRegistered();
+
+            // Postpone the kill if there is a thread in accept
+            if (thread == 0) {
+                SctpNet.close(fdVal);
+                state = ChannelState.KILLED;
+            } else {
+                state = ChannelState.KILLPENDING;
+            }
+        }
+    }
+
+    @Override
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    @Override
+    public int getFDVal() {
+        return fdVal;
+    }
+
+    /**
+     * Translates native poll revent ops into a ready operation ops
+     */
+    private boolean translateReadyOps(int ops, int initialOps,
+                                     SelectionKeyImpl sk) {
+        int intOps = sk.nioInterestOps();
+        int oldOps = sk.nioReadyOps();
+        int newOps = initialOps;
+
+        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+            /* This should only happen if this channel is pre-closed while a
+             * selection operation is in progress
+             * ## Throw an error if this channel has not been pre-closed */
+            return false;
+        }
+
+        if ((ops & (PollArrayWrapper.POLLERR
+                    | PollArrayWrapper.POLLHUP)) != 0) {
+            newOps = intOps;
+            sk.nioReadyOps(newOps);
+            return (newOps & ~oldOps) != 0;
+        }
+
+        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+            ((intOps & SelectionKey.OP_ACCEPT) != 0))
+                newOps |= SelectionKey.OP_ACCEPT;
+
+        sk.nioReadyOps(newOps);
+        return (newOps & ~oldOps) != 0;
+    }
+
+    @Override
+    public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, sk.nioReadyOps(), sk);
+    }
+
+    @Override
+    public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
+        return translateReadyOps(ops, 0, sk);
+    }
+
+    @Override
+    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
+        int newOps = 0;
+
+        /* Translate ops */
+        if ((ops & SelectionKey.OP_ACCEPT) != 0)
+            newOps |= PollArrayWrapper.POLLIN;
+        /* Place ops into pollfd array */
+        sk.selector.putEventOps(sk, newOps);
+
+    }
+
+    @Override
+    public <T> SctpServerChannel setOption(SctpSocketOption<T> name, T value)
+            throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            SctpNet.setSocketOption(fdVal, name, value, 0 /*oneToOne*/);
+            return this;
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SctpSocketOption<T> name) throws IOException {
+        if (name == null)
+            throw new NullPointerException();
+        if (!supportedOptions().contains(name))
+            throw new UnsupportedOperationException("'" + name + "' not supported");
+
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+
+            return (T) SctpNet.getSocketOption(fdVal, name, 0 /*oneToOne*/);
+        }
+    }
+
+    private static class DefaultOptionsHolder {
+        static final Set<SctpSocketOption<?>> defaultOptions = defaultOptions();
+
+        private static Set<SctpSocketOption<?>> defaultOptions() {
+            HashSet<SctpSocketOption<?>> set = new HashSet<SctpSocketOption<?>>(1);
+            set.add(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS);
+            return Collections.unmodifiableSet(set);
+        }
+    }
+
+    @Override
+    public final Set<SctpSocketOption<?>> supportedOptions() {
+        return DefaultOptionsHolder.defaultOptions;
+    }
+
+    @Override
+    public Set<SocketAddress> getAllLocalAddresses()
+            throws IOException {
+        synchronized (stateLock) {
+            if (!isOpen())
+                throw new ClosedChannelException();
+            if (!isBound())
+                return Collections.emptySet();
+
+            return SctpNet.getLocalAddresses(fdVal);
+        }
+    }
+
+    /* Native */
+    private static native void initIDs();
+
+    private static native int accept0(FileDescriptor ssfd,
+        FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException;
+
+    static {
+        Util.load();   // loads nio & net native libraries
+        java.security.AccessController.doPrivileged(
+                new sun.security.action.LoadLibraryAction("sctp"));
+        initIDs();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/SendFailed.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import java.nio.ByteBuffer;
+import java.net.SocketAddress;
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.SendFailedNotification;
+
+/**
+ * An implementation of SendFailedNotification
+ */
+public class SendFailed extends SendFailedNotification
+    implements SctpNotification
+{
+    private Association association;
+    /* assocId is used to lookup the association before the notification is
+     * returned to user code */
+    private int assocId;
+    private SocketAddress address;
+    private ByteBuffer buffer;
+    private int errorCode;
+    private int streamNumber;
+
+    /* Invoked from native */
+    private SendFailed(int assocId,
+                       SocketAddress address,
+                       ByteBuffer buffer,
+                       int errorCode,
+                       int streamNumber) {
+        this.assocId = assocId;
+        this.errorCode = errorCode;
+        this.streamNumber = streamNumber;
+        this.address = address;
+        this.buffer = buffer;
+    }
+
+    @Override
+    public int assocId() {
+        return assocId;
+    }
+
+    @Override
+    public void setAssociation(Association association) {
+        this.association = association;
+    }
+
+    @Override
+    public Association association() {
+        /* may be null */
+        return association;
+    }
+
+    @Override
+    public SocketAddress address() {
+        assert address != null;
+        return address;
+    }
+
+    @Override
+    public ByteBuffer buffer() {
+        assert buffer != null;
+        return buffer;
+    }
+
+    @Override
+    public int errorCode() {
+        return errorCode;
+    }
+
+    @Override
+    public int streamNumber() {
+        return streamNumber;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString()).append(" [");
+        sb.append("Association:").append(association);
+        sb.append(", Address: ").append(address);
+        sb.append(", buffer: ").append(buffer);
+        sb.append(", errorCode: ").append(errorCode);
+        sb.append(", streamNumber: ").append(streamNumber);
+        sb.append("]");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/nio/ch/sctp/Shutdown.java	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.nio.ch.sctp;
+
+import com.sun.nio.sctp.Association;
+import com.sun.nio.sctp.ShutdownNotification;
+
+/**
+ * An implementation of ShutdownNotification
+ */
+public class Shutdown extends ShutdownNotification
+    implements SctpNotification
+{
+    private Association association;
+    /* assocId is used to lookup the association before the notification is
+     * returned to user code */
+    private int assocId;
+
+    /* Invoked from native */
+    private Shutdown(int assocId) {
+        this.assocId = assocId;
+    }
+
+    @Override
+    public int assocId() {
+        return assocId;
+    }
+
+    @Override
+    public void setAssociation(Association association) {
+        this.association = association;
+    }
+
+    @Override
+    public Association association() {
+        assert association != null;
+        return association;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString()).append(" [");
+        sb.append("Association:").append(association).append("]");
+        return sb.toString();
+    }
+}
--- a/src/solaris/native/sun/nio/ch/Sctp.h	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SUN_NIO_CH_SCTP_H
-#define SUN_NIO_CH_SCTP_H
-
-#ifdef __solaris__
-
-#define _XPG4_2
-#define __EXTENSIONS__
-#include <sys/socket.h>
-#include <netinet/sctp.h>
-#include "jni.h"
-
-/* Current Solaris headers don't comply with draft rfc */
-#ifndef SCTP_EOF
-#define SCTP_EOF MSG_EOF
-#endif
-
-#ifndef SCTP_UNORDERED
-#define SCTP_UNORDERED MSG_UNORDERED
-#endif
-
-/* The current version of the socket API extension shipped with Solaris does
- * not define the following options that the Java API (optionally) supports */
-#ifndef SCTP_EXPLICIT_EOR
-#define SCTP_EXPLICIT_EOR -1
-#endif
-#ifndef SCTP_FRAGMENT_INTERLEAVE
-#define SCTP_FRAGMENT_INTERLEAVE -1
-#endif
-#ifndef SCTP_SET_PEER_PRIMARY_ADDR
-#define SCTP_SET_PEER_PRIMARY_ADDR -1
-#endif
-
-/* Function types to support dynamic linking of socket API extension functions
- * for SCTP. This is so that there is no linkage depandancy during build or
- * runtime for libsctp.*/
-typedef int sctp_getladdrs_func(int sock, sctp_assoc_t id, void **addrs);
-typedef int sctp_freeladdrs_func(void* addrs);
-typedef int sctp_getpaddrs_func(int sock, sctp_assoc_t id, void **addrs);
-typedef int sctp_freepaddrs_func(void *addrs);
-typedef int sctp_bindx_func(int sock, void *addrs, int addrcnt, int flags);
-typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
-
-
-
-#else /* __linux__ */
-#include <stdint.h>
-#include <linux/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include "jni.h"
-
-//Causes compiler error if not found, should make warning and uncomment
-/*#include <netinet/sctp.h>*/
-
-#ifndef IPPROTO_SCTP
-#define IPPROTO_SCTP    132
-#endif
-
-/* The current version of lksctp does
- * not define the following option that the Java API (optionally) supports */
-#ifndef SCTP_EXPLICIT_EOR
-#define SCTP_EXPLICIT_EOR -1
-#endif
-
-/* Definitions taken from lksctp-tools-1.0.8/src/include/netinet/sctp.h */
-#ifndef SCTP_INITMSG
-
-enum sctp_optname {
-        SCTP_RTOINFO,
-#define SCTP_RTOINFO SCTP_RTOINFO
-        SCTP_ASSOCINFO,
-#define SCTP_ASSOCINFO SCTP_ASSOCINFO
-        SCTP_INITMSG,
-#define SCTP_INITMSG SCTP_INITMSG
-        SCTP_NODELAY,   /* Get/set nodelay option. */
-#define SCTP_NODELAY    SCTP_NODELAY
-        SCTP_AUTOCLOSE,
-#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE
-        SCTP_SET_PEER_PRIMARY_ADDR,
-#define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR
-        SCTP_PRIMARY_ADDR,
-#define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR
-        SCTP_ADAPTATION_LAYER,
-#define SCTP_ADAPTATION_LAYER SCTP_ADAPTATION_LAYER
-        SCTP_DISABLE_FRAGMENTS,
-#define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS
-        SCTP_PEER_ADDR_PARAMS,
-#define SCTP_PEER_ADDR_PARAMS SCTP_PEER_ADDR_PARAMS
-        SCTP_DEFAULT_SEND_PARAM,
-#define SCTP_DEFAULT_SEND_PARAM SCTP_DEFAULT_SEND_PARAM
-        SCTP_EVENTS,
-#define SCTP_EVENTS SCTP_EVENTS
-        SCTP_I_WANT_MAPPED_V4_ADDR,  /* Turn on/off mapped v4 addresses  */
-#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
-        SCTP_MAXSEG,    /* Get/set maximum fragment. */
-#define SCTP_MAXSEG     SCTP_MAXSEG
-        SCTP_STATUS,
-#define SCTP_STATUS SCTP_STATUS
-        SCTP_GET_PEER_ADDR_INFO,
-#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
-        SCTP_DELAYED_ACK_TIME,
-#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME
-        SCTP_CONTEXT,   /* Receive Context */
-#define SCTP_CONTEXT SCTP_CONTEXT
-        SCTP_FRAGMENT_INTERLEAVE,
-#define SCTP_FRAGMENT_INTERLEAVE SCTP_FRAGMENT_INTERLEAVE
-        SCTP_PARTIAL_DELIVERY_POINT,    /* Set/Get partial delivery point */
-#define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT
-        SCTP_MAX_BURST,         /* Set/Get max burst */
-#define SCTP_MAX_BURST SCTP_MAX_BURST
-};
-
-enum sctp_sac_state {
-        SCTP_COMM_UP,
-        SCTP_COMM_LOST,
-        SCTP_RESTART,
-        SCTP_SHUTDOWN_COMP,
-        SCTP_CANT_STR_ASSOC,
-};
-
-enum sctp_spc_state {
-        SCTP_ADDR_AVAILABLE,
-        SCTP_ADDR_UNREACHABLE,
-        SCTP_ADDR_REMOVED,
-        SCTP_ADDR_ADDED,
-        SCTP_ADDR_MADE_PRIM,
-        SCTP_ADDR_CONFIRMED,
-};
-
-enum sctp_sinfo_flags {
-        SCTP_UNORDERED = 1,  /* Send/receive message unordered. */
-        SCTP_ADDR_OVER = 2,  /* Override the primary destination. */
-        SCTP_ABORT=4,        /* Send an ABORT message to the peer. */
-        SCTP_EOF=MSG_FIN,    /* Initiate graceful shutdown process. */
-};
-
-enum sctp_sn_type {
-        SCTP_SN_TYPE_BASE     = (1<<15),
-        SCTP_ASSOC_CHANGE,
-        SCTP_PEER_ADDR_CHANGE,
-        SCTP_SEND_FAILED,
-        SCTP_REMOTE_ERROR,
-        SCTP_SHUTDOWN_EVENT,
-        SCTP_PARTIAL_DELIVERY_EVENT,
-        SCTP_ADAPTATION_INDICATION,
-};
-
-typedef enum sctp_cmsg_type {
-        SCTP_INIT,              /* 5.2.1 SCTP Initiation Structure */
-#define SCTP_INIT SCTP_INIT
-        SCTP_SNDRCV,            /* 5.2.2 SCTP Header Information Structure */
-#define SCTP_SNDRCV SCTP_SNDRCV
-} sctp_cmsg_t;
-
-enum sctp_msg_flags {
-        MSG_NOTIFICATION = 0x8000,
-#define MSG_NOTIFICATION MSG_NOTIFICATION
-};
-
-#define SCTP_BINDX_ADD_ADDR 0x01
-#define SCTP_BINDX_REM_ADDR 0x02
-
-typedef __s32 sctp_assoc_t;
-
-struct sctp_initmsg {
-        __u16 sinit_num_ostreams;
-        __u16 sinit_max_instreams;
-        __u16 sinit_max_attempts;
-        __u16 sinit_max_init_timeo;
-};
-
-struct sctp_sndrcvinfo {
-        __u16 sinfo_stream;
-        __u16 sinfo_ssn;
-        __u16 sinfo_flags;
-        __u32 sinfo_ppid;
-        __u32 sinfo_context;
-        __u32 sinfo_timetolive;
-        __u32 sinfo_tsn;
-        __u32 sinfo_cumtsn;
-        sctp_assoc_t sinfo_assoc_id;
-};
-
-struct sctp_event_subscribe {
-        __u8 sctp_data_io_event;
-        __u8 sctp_association_event;
-        __u8 sctp_address_event;
-        __u8 sctp_send_failure_event;
-        __u8 sctp_peer_error_event;
-        __u8 sctp_shutdown_event;
-        __u8 sctp_partial_delivery_event;
-        __u8 sctp_adaptation_layer_event;
-};
-
-struct sctp_send_failed {
-        __u16 ssf_type;
-        __u16 ssf_flags;
-        __u32 ssf_length;
-        __u32 ssf_error;
-        struct sctp_sndrcvinfo ssf_info;
-        sctp_assoc_t ssf_assoc_id;
-        __u8 ssf_data[0];
-};
-
-struct sctp_assoc_change {
-        __u16 sac_type;
-        __u16 sac_flags;
-        __u32 sac_length;
-        __u16 sac_state;
-        __u16 sac_error;
-        __u16 sac_outbound_streams;
-        __u16 sac_inbound_streams;
-        sctp_assoc_t sac_assoc_id;
-        __u8 sac_info[0];
-};
-
-struct sctp_shutdown_event {
-        __u16 sse_type;
-        __u16 sse_flags;
-        __u32 sse_length;
-        sctp_assoc_t sse_assoc_id;
-};
-
-struct sctp_paddr_change {
-        __u16 spc_type;
-        __u16 spc_flags;
-        __u32 spc_length;
-        struct sockaddr_storage spc_aaddr;
-        int spc_state;
-        int spc_error;
-        sctp_assoc_t spc_assoc_id;
-} __attribute__((packed, aligned(4)));
-
-struct sctp_remote_error {
-        __u16 sre_type;
-        __u16 sre_flags;
-        __u32 sre_length;
-        __u16 sre_error;
-        sctp_assoc_t sre_assoc_id;
-        __u8 sre_data[0];
-};
-
-struct sctp_adaptation_event {
-        __u16 sai_type;
-        __u16 sai_flags;
-        __u32 sai_length;
-        __u32 sai_adaptation_ind;
-        sctp_assoc_t sai_assoc_id;
-};
-
-struct sctp_setprim {
-        sctp_assoc_t            ssp_assoc_id;
-        struct sockaddr_storage ssp_addr;
-} __attribute__((packed, aligned(4)));
-
-struct sctp_setpeerprim {
-        sctp_assoc_t            sspp_assoc_id;
-        struct sockaddr_storage sspp_addr;
-} __attribute__((packed, aligned(4)));
-
-
-struct sctp_pdapi_event {
-        __u16 pdapi_type;
-        __u16 pdapi_flags;
-        __u32 pdapi_length;
-        __u32 pdapi_indication;
-        sctp_assoc_t pdapi_assoc_id;
-};
-
-union sctp_notification {
-        struct {
-                __u16 sn_type;             /* Notification type. */
-                __u16 sn_flags;
-                __u32 sn_length;
-        } sn_header;
-        struct sctp_assoc_change sn_assoc_change;
-        struct sctp_paddr_change sn_paddr_change;
-        struct sctp_remote_error sn_remote_error;
-        struct sctp_send_failed sn_send_failed;
-        struct sctp_shutdown_event sn_shutdown_event;
-        struct sctp_adaptation_event sn_adaptation_event;
-        struct sctp_pdapi_event sn_pdapi_event;
-};
-
-#endif /* SCTP_INITMSG */
-
-/* Function types to support dynamic linking of socket API extension functions
- * for SCTP. This is so that there is no linkage depandancy during build or
- * runtime for libsctp.*/
-typedef int sctp_getladdrs_func(int sd, sctp_assoc_t id, struct sockaddr **addrs);
-typedef int sctp_freeladdrs_func(struct sockaddr *addrs);
-typedef int sctp_getpaddrs_func(int sd, sctp_assoc_t id, struct sockaddr **addrs);
-typedef int sctp_freepaddrs_func(struct sockaddr *addrs);
-typedef int sctp_bindx_func(int sd, struct sockaddr *addrs, int addrcnt, int flags);
-typedef int sctp_peeloff_func(int sock, sctp_assoc_t id);
-
-
-#endif /* __linux__ */
-
-sctp_getladdrs_func* nio_sctp_getladdrs;
-sctp_freeladdrs_func* nio_sctp_freeladdrs;
-sctp_getpaddrs_func* nio_sctp_getpaddrs;
-sctp_freepaddrs_func* nio_sctp_freepaddrs;
-sctp_bindx_func* nio_sctp_bindx;
-sctp_peeloff_func* nio_sctp_peeloff;
-
-jboolean loadSocketExtensionFuncs(JNIEnv* env);
-
-#endif /* !SUN_NIO_CH_SCTP_H */
--- a/src/solaris/native/sun/nio/ch/SctpChannelImpl.c	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,594 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "Sctp.h"
-
-#include "jni.h"
-#include "nio_util.h"
-#include "nio.h"
-#include "net_util.h"
-#include "net_util_md.h"
-#include "sun_nio_ch_SctpNet.h"
-#include "sun_nio_ch_SctpChannelImpl.h"
-#include "sun_nio_ch_SctpAssocChange.h"
-#include "sun_nio_ch_SctpResultContainer.h"
-#include "sun_nio_ch_SctpPeerAddrChange.h"
-
-/* sizeof(union sctp_notification */
-#define NOTIFICATION_BUFFER_SIZE 280
-
-#define MESSAGE_IMPL_CLASS              "sun/nio/ch/SctpMessageInfoImpl"
-#define RESULT_CONTAINER_CLASS          "sun/nio/ch/SctpResultContainer"
-#define SEND_FAILED_CLASS               "sun/nio/ch/SctpSendFailed"
-#define ASSOC_CHANGE_CLASS              "sun/nio/ch/SctpAssocChange"
-#define PEER_CHANGE_CLASS               "sun/nio/ch/SctpPeerAddrChange"
-#define SHUTDOWN_CLASS                  "sun/nio/ch/SctpShutdown"
-
-struct controlData {
-    int assocId;
-    unsigned short streamNumber;
-    jboolean unordered;
-    unsigned int ppid;
-};
-
-static jclass    smi_class;    /* sun.nio.ch.SctpMessageInfoImpl            */
-static jmethodID smi_ctrID;    /* sun.nio.ch.SctpMessageInfoImpl.<init>     */
-static jfieldID  src_valueID;  /* sun.nio.ch.SctpResultContainer.value      */
-static jfieldID  src_typeID;   /* sun.nio.ch.SctpResultContainer.type       */
-static jclass    ssf_class;    /* sun.nio.ch.SctpSendFailed                 */
-static jmethodID ssf_ctrID;    /* sun.nio.ch.SctpSendFailed.<init>          */
-static jclass    sac_class;    /* sun.nio.ch.SctpAssociationChanged         */
-static jmethodID sac_ctrID;    /* sun.nio.ch.SctpAssociationChanged.<init>  */
-static jclass    spc_class;    /* sun.nio.ch.SctpPeerAddressChanged         */
-static jmethodID spc_ctrID;    /* sun.nio.ch.SctpPeerAddressChanged.<init>  */
-static jclass    ss_class;     /* sun.nio.ch.SctpShutdown                   */
-static jmethodID ss_ctrID;     /* sun.nio.ch.SctpShutdown.<init>            */
-static jfieldID  isa_addrID;   /* java.net.InetSocketAddress.addr           */
-static jfieldID  isa_portID;   /* java.net.InetSocketAddress.port           */
-
-/* defined in SctpNet.c */
-jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr);
-
-/* use SocketChannelImpl's checkConnect implementation */
-extern jint Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv* env,
-    jobject this, jobject fdo, jboolean block, jboolean ready);
-
-/*
- * Class:     sun_nio_ch_SctpChannelImpl
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpChannelImpl_initIDs
-  (JNIEnv *env, jclass klass) {
-    jclass cls;
-
-    /* SctpMessageInfoImpl */
-    cls = (*env)->FindClass(env, MESSAGE_IMPL_CLASS);
-    CHECK_NULL(cls);
-    smi_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(smi_class);
-    smi_ctrID = (*env)->GetMethodID(env, cls, "<init>",
-            "(ILjava/net/SocketAddress;IIZZI)V");
-    CHECK_NULL(smi_ctrID);
-
-    /* SctpResultContainer */
-    cls = (*env)->FindClass(env, RESULT_CONTAINER_CLASS);
-    CHECK_NULL(cls);
-    src_valueID = (*env)->GetFieldID(env, cls, "value", "Ljava/lang/Object;");
-    CHECK_NULL(src_valueID);
-    src_typeID = (*env)->GetFieldID(env, cls, "type", "I");
-    CHECK_NULL(src_typeID);
-
-    /* SctpSendFailed */
-    cls = (*env)->FindClass(env, SEND_FAILED_CLASS);
-    CHECK_NULL(cls);
-    ssf_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(ssf_class);
-    ssf_ctrID = (*env)->GetMethodID(env, cls, "<init>",
-        "(ILjava/net/SocketAddress;Ljava/nio/ByteBuffer;II)V");
-    CHECK_NULL(ssf_ctrID);
-
-    /* SctpAssocChange */
-    cls = (*env)->FindClass(env, ASSOC_CHANGE_CLASS);
-    CHECK_NULL(cls);
-    sac_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(sac_class);
-    sac_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(IIII)V");
-    CHECK_NULL(sac_ctrID);
-
-    /* SctpPeerAddrChange */
-    cls = (*env)->FindClass(env, PEER_CHANGE_CLASS);
-    CHECK_NULL(cls);
-    spc_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(spc_class);
-    spc_ctrID = (*env)->GetMethodID(env, cls, "<init>",
-            "(ILjava/net/SocketAddress;I)V");
-    CHECK_NULL(spc_ctrID);
-
-    /* sun.nio.ch.SctpShutdown */
-    cls = (*env)->FindClass(env, SHUTDOWN_CLASS);
-    CHECK_NULL(cls);
-    ss_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(ss_class);
-    ss_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(I)V");
-    CHECK_NULL(ss_ctrID);
-
-    /* InetSocketAddress */
-    cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
-    CHECK_NULL(cls);
-    isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;");
-    CHECK_NULL(isa_addrID);
-    isa_portID = (*env)->GetFieldID(env, cls, "port", "I");
-}
-
-void getControlData
-  (struct msghdr* msg, struct controlData* cdata) {
-    struct cmsghdr* cmsg;
-
-    for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
-        if (cmsg->cmsg_level == IPPROTO_SCTP && cmsg->cmsg_type == SCTP_SNDRCV) {
-            struct sctp_sndrcvinfo *sri;
-
-            sri = (struct sctp_sndrcvinfo *) CMSG_DATA(cmsg);
-            cdata->assocId = sri->sinfo_assoc_id;
-            cdata->streamNumber = sri->sinfo_stream;
-            cdata->unordered = (sri->sinfo_flags & SCTP_UNORDERED) ? JNI_TRUE :
-                JNI_FALSE;
-            cdata->ppid = ntohl(sri->sinfo_ppid);
-
-            return;
-        }
-    }
-    return;
-}
-
-void setControlData
-  (struct msghdr* msg, struct controlData* cdata) {
-    struct cmsghdr* cmsg;
-    struct sctp_sndrcvinfo *sri;
-
-    cmsg = CMSG_FIRSTHDR(msg);
-    cmsg->cmsg_level = IPPROTO_SCTP;
-    cmsg->cmsg_type = SCTP_SNDRCV;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-
-    /* Initialize the payload */
-    sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg);
-    memset(sri, 0, sizeof (*sri));
-
-    if (cdata->streamNumber > 0) {
-        sri->sinfo_stream = cdata->streamNumber;
-    }
-    if (cdata->assocId > 0) {
-        sri->sinfo_assoc_id = cdata->assocId;
-    }
-    if (cdata->unordered == JNI_TRUE) {
-        sri->sinfo_flags = sri->sinfo_flags | SCTP_UNORDERED;
-    }
-
-    if (cdata->ppid > 0) {
-        sri->sinfo_ppid = htonl(cdata->ppid);
-    }
-
-    /* Sum of the length of all control messages in the buffer. */
-    msg->msg_controllen = cmsg->cmsg_len;
-}
-
-// TODO: test: can create send failed without any data? if so need to
-// update API so that buffer can be null if no data.
-void handleSendFailed
-  (JNIEnv* env, int fd, jobject resultContainerObj, struct sctp_send_failed *ssf,
-   int read, jboolean isEOR, struct sockaddr* sap) {
-    jobject bufferObj = NULL, resultObj, isaObj;
-    char *addressP;
-    struct sctp_sndrcvinfo *sri;
-    int remaining, dataLength;
-
-    /* the actual undelivered message data is directly after the ssf */
-    int dataOffset = sizeof(struct sctp_send_failed);
-
-    sri = (struct sctp_sndrcvinfo*) &ssf->ssf_info;
-
-    /* the number of bytes remaining to be read in the sctp_send_failed notif*/
-    remaining = ssf->ssf_length - read;
-
-    /* the size of the actual undelivered message */
-    dataLength = ssf->ssf_length - dataOffset;
-
-    /* retrieved address from sockaddr */
-    isaObj = SockAddrToInetSocketAddress(env, sap);
-
-    /* data retrieved from sff_data */
-    if (dataLength > 0) {
-        struct iovec iov[1];
-        struct msghdr msg[1];
-        int rv, alreadyRead;
-        char *dataP = (char*) ssf;
-        dataP += dataOffset;
-
-        if ((addressP = malloc(dataLength)) == NULL) {
-            JNU_ThrowOutOfMemoryError(env, "handleSendFailed");
-            return;
-        }
-
-        memset(msg, 0, sizeof (*msg));
-        msg->msg_iov = iov;
-        msg->msg_iovlen = 1;
-
-        bufferObj = (*env)->NewDirectByteBuffer(env, addressP, dataLength);
-        CHECK_NULL(bufferObj);
-
-        alreadyRead = read - dataOffset;
-        if (alreadyRead > 0) {
-            memcpy(addressP, /*ssf->ssf_data*/ dataP, alreadyRead);
-            iov->iov_base = addressP + alreadyRead;
-            iov->iov_len = dataLength - alreadyRead;
-        } else {
-            iov->iov_base = addressP;
-            iov->iov_len = dataLength;
-        }
-
-        if (remaining > 0) {
-            if ((rv = recvmsg(fd, msg, 0)) < 0) {
-                handleSocketError(env, errno);
-                return;
-            }
-
-            if (rv != (dataLength - alreadyRead) || !(msg->msg_flags & MSG_EOR)) {
-                //TODO: assert false: "should not reach here";
-                return;
-            }
-            // TODO: Set and document (in API) buffers position.
-        }
-    }
-
-    /* create SctpSendFailed */
-    resultObj = (*env)->NewObject(env, ssf_class, ssf_ctrID, ssf->ssf_assoc_id,
-            isaObj, bufferObj, ssf->ssf_error, sri->sinfo_stream);
-    CHECK_NULL(resultObj);
-    (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
-    (*env)->SetIntField(env, resultContainerObj, src_typeID,
-            sun_nio_ch_SctpResultContainer_SEND_FAILED);
-}
-
-void handleAssocChange
-  (JNIEnv* env, jobject resultContainerObj, struct sctp_assoc_change *sac) {
-    jobject resultObj;
-    int state = 0;
-
-    switch (sac->sac_state) {
-        case SCTP_COMM_UP :
-            state = sun_nio_ch_SctpAssocChange_SCTP_COMM_UP;
-            break;
-        case SCTP_COMM_LOST :
-            state = sun_nio_ch_SctpAssocChange_SCTP_COMM_LOST;
-            break;
-        case SCTP_RESTART :
-            state = sun_nio_ch_SctpAssocChange_SCTP_RESTART;
-            break;
-        case SCTP_SHUTDOWN_COMP :
-            state = sun_nio_ch_SctpAssocChange_SCTP_SHUTDOWN;
-            break;
-        case SCTP_CANT_STR_ASSOC :
-            state = sun_nio_ch_SctpAssocChange_SCTP_CANT_START;
-    }
-
-    /* create SctpAssociationChanged */
-    resultObj = (*env)->NewObject(env, sac_class, sac_ctrID, sac->sac_assoc_id,
-        state, sac->sac_outbound_streams, sac->sac_inbound_streams);
-    CHECK_NULL(resultObj);
-    (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
-    (*env)->SetIntField(env, resultContainerObj, src_typeID,
-            sun_nio_ch_SctpResultContainer_ASSOCIATION_CHANGED);
-}
-
-void handleShutdown
-  (JNIEnv* env, jobject resultContainerObj, struct sctp_shutdown_event* sse) {
-    /* create SctpShutdown */
-    jobject resultObj = (*env)->NewObject(env, ss_class, ss_ctrID, sse->sse_assoc_id);
-    CHECK_NULL(resultObj);
-    (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
-    (*env)->SetIntField(env, resultContainerObj, src_typeID,
-            sun_nio_ch_SctpResultContainer_SHUTDOWN);
-}
-
-void handlePeerAddrChange
-  (JNIEnv* env, jobject resultContainerObj, struct sctp_paddr_change* spc) {
-    int event = 0;
-    jobject addressObj, resultObj;
-    unsigned int state = spc->spc_state;
-
-    switch (state) {
-        case SCTP_ADDR_AVAILABLE :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_AVAILABLE;
-            break;
-        case SCTP_ADDR_UNREACHABLE :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_UNREACHABLE;
-            break;
-        case SCTP_ADDR_REMOVED :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_REMOVED;
-            break;
-        case SCTP_ADDR_ADDED :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_ADDED;
-            break;
-        case SCTP_ADDR_MADE_PRIM :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_MADE_PRIM;
-#ifdef __linux__  /* Solaris currently doesn't support SCTP_ADDR_CONFIRMED */
-            break;
-        case SCTP_ADDR_CONFIRMED :
-            event = sun_nio_ch_SctpPeerAddrChange_SCTP_ADDR_CONFIRMED;
-#endif  /* __linux__ */
-    }
-
-    addressObj = SockAddrToInetSocketAddress(env, (struct sockaddr*)&spc->spc_aaddr);
-
-    /* create SctpPeerAddressChanged */
-    resultObj = (*env)->NewObject(env, spc_class, spc_ctrID, spc->spc_assoc_id,
-            addressObj, event);
-    CHECK_NULL(resultObj);
-    (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
-    (*env)->SetIntField(env, resultContainerObj, src_typeID,
-            sun_nio_ch_SctpResultContainer_PEER_ADDRESS_CHANGED);
-}
-
-void handleUninteresting
-  (union sctp_notification *snp) {
-    //fprintf(stdout,"\nNative: handleUninterestingNotification: Receive notification type [%u]", snp->sn_header.sn_type);
-}
-
-/**
- * Handle notifications from the SCTP stack.
- * Returns JNI_TRUE if the notification is one that is of interest to the
- * Java API, otherwise JNI_FALSE.
- */
-jboolean handleNotification
-  (JNIEnv* env, int fd, jobject resultContainerObj, union sctp_notification* snp,
-   int read, jboolean isEOR, struct sockaddr* sap) {
-    switch (snp->sn_header.sn_type) {
-        case SCTP_SEND_FAILED:
-            handleSendFailed(env, fd, resultContainerObj, &snp->sn_send_failed,
-                    read, isEOR, sap);
-            return JNI_TRUE;
-        case SCTP_ASSOC_CHANGE:
-            handleAssocChange(env, resultContainerObj, &snp->sn_assoc_change);
-            return JNI_TRUE;
-        case SCTP_SHUTDOWN_EVENT:
-            handleShutdown(env, resultContainerObj, &snp->sn_shutdown_event);
-            return JNI_TRUE;
-        case SCTP_PEER_ADDR_CHANGE:
-            handlePeerAddrChange(env, resultContainerObj, &snp->sn_paddr_change);
-            return JNI_TRUE;
-        default :
-            /* the Java API is not interested in this event, maybe we are? */
-            handleUninteresting(snp);
-    }
-    return JNI_FALSE;
-}
-
-void handleMessage
-  (JNIEnv* env, jobject resultContainerObj, struct msghdr* msg,int read,
-   jboolean isEOR, struct sockaddr* sap) {
-    jobject isa, resultObj;
-    struct controlData cdata[1];
-
-    if (read == 0) {
-        /* we reached EOF */
-        read = -1;
-    }
-
-    isa = SockAddrToInetSocketAddress(env, sap);
-    getControlData(msg, cdata);
-
-    /* create SctpMessageInfoImpl */
-    resultObj = (*env)->NewObject(env, smi_class, smi_ctrID, cdata->assocId,
-                                  isa, read, cdata->streamNumber,
-                                  isEOR ? JNI_TRUE : JNI_FALSE,
-                                  cdata->unordered, cdata->ppid);
-    CHECK_NULL(resultObj);
-    (*env)->SetObjectField(env, resultContainerObj, src_valueID, resultObj);
-    (*env)->SetIntField(env, resultContainerObj, src_typeID,
-                        sun_nio_ch_SctpResultContainer_MESSAGE);
-}
-
-/*
- * Class:     sun_nio_ch_SctpChannelImpl
- * Method:    receive0
- * Signature: (ILsun/nio/ch/SctpResultContainer;JIZ)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpChannelImpl_receive0
-  (JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj,
-   jlong address, jint length, jboolean peek) {
-    SOCKADDR sa;
-    int sa_len = sizeof(sa);
-    ssize_t rv = 0;
-    jlong *addr = jlong_to_ptr(address);
-    struct iovec iov[1];
-    struct msghdr msg[1];
-    char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
-    int flags = peek == JNI_TRUE ? MSG_PEEK : 0;
-
-    /* Set up the msghdr structure for receiving */
-    memset(msg, 0, sizeof (*msg));
-    msg->msg_name = &sa;
-    msg->msg_namelen = sa_len;
-    iov->iov_base = addr;
-    iov->iov_len = length;
-    msg->msg_iov = iov;
-    msg->msg_iovlen = 1;
-    msg->msg_control = cbuf;
-    msg->msg_controllen = sizeof(cbuf);
-    msg->msg_flags = 0;
-
-    do {
-        if ((rv = recvmsg(fd, msg, flags)) < 0) {
-            if (errno == EWOULDBLOCK) {
-                return IOS_UNAVAILABLE;
-            } else if (errno == EINTR) {
-                return IOS_INTERRUPTED;
-
-#ifdef __linux__
-            } else if (errno == ENOTCONN) {
-                /* ENOTCONN when EOF reached */
-                rv = 0;
-                /* there will be no control data */
-                msg->msg_controllen = 0;
-#endif /* __linux__ */
-
-            } else {
-                handleSocketError(env, errno);
-                return 0;
-            }
-        }
-
-        if (msg->msg_flags & MSG_NOTIFICATION) {
-            char *bufp = (char*)addr;
-            union sctp_notification *snp;
-
-            if (!(msg->msg_flags & MSG_EOR) && length < NOTIFICATION_BUFFER_SIZE) {
-                char buf[NOTIFICATION_BUFFER_SIZE];
-                int rvSAVE = rv;
-                memcpy(buf, addr, rv);
-                iov->iov_base = buf + rv;
-                iov->iov_len = NOTIFICATION_BUFFER_SIZE - rv;
-                if ((rv = recvmsg(fd, msg, flags)) < 0) {
-                    handleSocketError(env, errno);
-                    return 0;
-                }
-                bufp = buf;
-                rv += rvSAVE;
-            }
-            snp = (union sctp_notification *) bufp;
-            if (handleNotification(env, fd, resultContainerObj, snp, rv,
-                                   (msg->msg_flags & MSG_EOR),
-                                   (struct sockaddr*)&sa ) == JNI_TRUE) {
-                /* We have received a notification that is of interest to
-                   to the Java API. The appropriate notification will be
-                   set in the result container. */
-                return 0;
-            }
-
-            // set iov back to addr, and reset msg_controllen
-            iov->iov_base = addr;
-            iov->iov_len = length;
-            msg->msg_control = cbuf;
-            msg->msg_controllen = sizeof(cbuf);
-        }
-    } while (msg->msg_flags & MSG_NOTIFICATION);
-
-    handleMessage(env, resultContainerObj, msg, rv,
-            (msg->msg_flags & MSG_EOR), (struct sockaddr*)&sa);
-    return rv;
-}
-
-/*
- * Class:     sun_nio_ch_SctpChannelImpl
- * Method:    send0
- * Signature: (IJILjava/net/SocketAddress;IIZI)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpChannelImpl_send0
-  (JNIEnv *env, jclass klass, jint fd, jlong address, jint length,
-   jobject saTarget, jint assocId, jint streamNumber, jboolean unordered,
-   jint ppid) {
-    SOCKADDR sa;
-    int sa_len = sizeof(sa);
-    ssize_t rv = 0;
-    jlong *addr = jlong_to_ptr(address);
-    struct iovec iov[1];
-    struct msghdr msg[1];
-    int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo));
-    char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
-    struct controlData cdata[1];
-
-    /* SctpChannel:
-     *    saTarget may contain the preferred address or NULL to use primary,
-     *    assocId will always be -1
-     * SctpMultiChannell:
-     *    Setup new association, saTarget will contain address, assocId = -1
-     *    Association already existing, assocId != -1, saTarget = preferred addr
-     */
-    if (saTarget != NULL /*&& assocId <= 0*/) {
-
-        jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID);
-        jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID);
-
-        if (NET_InetAddressToSockaddr(env, targetAddress, targetPort,
-                                      (struct sockaddr *)&sa,
-                                      &sa_len, JNI_TRUE) != 0) {
-            return IOS_THROWN;
-        }
-    } else {
-        memset(&sa, '\x0', sa_len);
-        sa_len = 0;
-    }
-
-    /* Set up the msghdr structure for sending */
-    memset(msg, 0, sizeof (*msg));
-    memset(cbuf, 0, cbuf_size);
-    msg->msg_name = &sa;
-    msg->msg_namelen = sa_len;
-    iov->iov_base = addr;
-    iov->iov_len = length;
-    msg->msg_iov = iov;
-    msg->msg_iovlen = 1;
-    msg->msg_control = cbuf;
-    msg->msg_controllen = cbuf_size;
-    msg->msg_flags = 0;
-
-    cdata->streamNumber = streamNumber;
-    cdata->assocId = assocId;
-    cdata->unordered = unordered;
-    cdata->ppid = ppid;
-    setControlData(msg, cdata);
-
-    if ((rv = sendmsg(fd, msg, 0)) < 0) {
-        if (errno == EWOULDBLOCK) {
-            return IOS_UNAVAILABLE;
-        } else if (errno == EINTR) {
-            return IOS_INTERRUPTED;
-        } else if (errno == EPIPE) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                            "Socket is shutdown for writing");
-        } else {
-            handleSocketError(env, errno);
-            return 0;
-        }
-    }
-
-    return rv;
-}
-
-/*
- * Class:     sun_nio_ch_SctpChannelImpl
- * Method:    checkConnect
- * Signature: (Ljava/io/FileDescriptor;ZZ)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpChannelImpl_checkConnect
-  (JNIEnv* env, jobject this, jobject fdo, jboolean block, jboolean ready) {
-    return Java_sun_nio_ch_SocketChannelImpl_checkConnect(env, this,
-                                                          fdo, block, ready);
-}
-
--- a/src/solaris/native/sun/nio/ch/SctpNet.c	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,753 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <dlfcn.h>
-
-#include "Sctp.h"
-#include "jni.h"
-#include "jni_util.h"
-#include "nio_util.h"
-#include "nio.h"
-#include "net_util.h"
-#include "net_util_md.h"
-#include "sun_nio_ch_SctpNet.h"
-#include "sun_nio_ch_SctpStdSocketOption.h"
-
-static jclass isaCls = 0;
-static jmethodID isaCtrID = 0;
-
-static const char* nativeSctpLib = "libsctp.so.1";
-static jboolean funcsLoaded = JNI_FALSE;
-
-JNIEXPORT jint JNICALL JNI_OnLoad
-  (JavaVM *vm, void *reserved) {
-    return JNI_VERSION_1_2;
-}
-
-static int preCloseFD = -1;     /* File descriptor to which we dup other fd's
-                                   before closing them for real */
-
-/**
- * Loads the native sctp library that contains the socket extension
- * functions, as well as locating the individual functions.
- * There will be a pending exception if this method returns false.
- */
-jboolean loadSocketExtensionFuncs
-  (JNIEnv* env) {
-    if (dlopen(nativeSctpLib, RTLD_GLOBAL | RTLD_LAZY) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_getladdrs = (sctp_getladdrs_func*)
-            dlsym(RTLD_DEFAULT, "sctp_getladdrs")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_freeladdrs = (sctp_freeladdrs_func*)
-            dlsym(RTLD_DEFAULT, "sctp_freeladdrs")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_getpaddrs = (sctp_getpaddrs_func*)
-            dlsym(RTLD_DEFAULT, "sctp_getpaddrs")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_freepaddrs = (sctp_freepaddrs_func*)
-            dlsym(RTLD_DEFAULT, "sctp_freepaddrs")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_bindx = (sctp_bindx_func*)
-            dlsym(RTLD_DEFAULT, "sctp_bindx")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    if ((nio_sctp_peeloff = (sctp_peeloff_func*)
-            dlsym(RTLD_DEFAULT, "sctp_peeloff")) == NULL) {
-        JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-              dlerror());
-        return JNI_FALSE;
-    }
-
-    funcsLoaded = JNI_TRUE;
-    return JNI_TRUE;
-}
-
-jint
-handleSocketError(JNIEnv *env, jint errorValue)
-{
-    char *xn;
-    switch (errorValue) {
-        case EINPROGRESS:     /* Non-blocking connect */
-            return 0;
-        case EPROTO:
-            xn= JNU_JAVANETPKG "ProtocolException";
-            break;
-        case ECONNREFUSED:
-            xn = JNU_JAVANETPKG "ConnectException";
-            break;
-        case ETIMEDOUT:
-            xn = JNU_JAVANETPKG "ConnectException";
-            break;
-        case EHOSTUNREACH:
-            xn = JNU_JAVANETPKG "NoRouteToHostException";
-            break;
-        case EADDRINUSE:  /* Fall through */
-        case EADDRNOTAVAIL:
-            xn = JNU_JAVANETPKG "BindException";
-            break;
-        default:
-            xn = JNU_JAVANETPKG "SocketException";
-            break;
-    }
-    errno = errorValue;
-    JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
-    return IOS_THROWN;
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    init
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_SctpNet_init
-  (JNIEnv *env, jclass cl) {
-    int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
-        return;
-    }
-    preCloseFD = sp[0];
-    close(sp[1]);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    socket0
- * Signature: (Z)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpNet_socket0
-  (JNIEnv *env, jclass klass, jboolean oneToOne) {
-    int fd;
-    struct sctp_event_subscribe event;
-#ifdef AF_INET6
-    int domain = ipv6_available() ? AF_INET6 : AF_INET;
-#else
-    int domain = AF_INET;
-#endif
-
-    /* Try to load the socket API extension functions */
-    if (!funcsLoaded && !loadSocketExtensionFuncs(env)) {
-        return 0;
-    }
-
-    fd = socket(domain, (oneToOne ? SOCK_STREAM : SOCK_SEQPACKET), IPPROTO_SCTP);
-
-    if (fd < 0) {
-        return handleSocketError(env, errno);
-    }
-
-    /* Enable events */
-    memset(&event, 0, sizeof(event));
-    event.sctp_data_io_event = 1;
-    event.sctp_association_event = 1;
-    event.sctp_address_event = 1;
-    event.sctp_send_failure_event = 1;
-    //event.sctp_peer_error_event = 1;
-    event.sctp_shutdown_event = 1;
-    //event.sctp_partial_delivery_event = 1;
-    //event.sctp_adaptation_layer_event = 1;
-    if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) {
-       handleSocketError(env, errno);
-    }
-    return fd;
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    bindx
- * Signature: (I[Ljava/net/InetAddress;IIZ)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_bindx
-  (JNIEnv *env, jclass klass, jint fd, jobjectArray addrs, jint port,
-   jint addrsLength, jboolean add, jboolean preferIPv6) {
-    SOCKADDR *sap, *tmpSap;
-    int i, sa_len = sizeof(SOCKADDR);
-    jobject ia;
-
-    if (addrsLength < 1)
-        return;
-
-    if ((sap = calloc(addrsLength,  sa_len)) == NULL) {
-          JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
-        return;
-    }
-
-    tmpSap = sap;
-    for (i=0; i<addrsLength; i++) {
-        ia = (*env)->GetObjectArrayElement(env, addrs, i);
-        if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr*)tmpSap,
-                                      &sa_len, preferIPv6) != 0) {
-            free(sap);
-            return;
-        }
-        tmpSap++;
-    }
-
-    if (nio_sctp_bindx(fd, (void*)sap, addrsLength, add ? SCTP_BINDX_ADD_ADDR :
-                       SCTP_BINDX_REM_ADDR) != 0) {
-        handleSocketError(env, errno);
-    }
-
-    free(sap);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    listen0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_SctpNet_listen0
-  (JNIEnv *env, jclass cl, jint fd, jint backlog) {
-    if (listen(fd, backlog) < 0)
-        handleSocketError(env, errno);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    connect0
- * Signature: (ILjava/net/InetAddress;I)I
- */
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_SctpNet_connect0
-  (JNIEnv *env, jclass clazz, int fd, jobject iao, jint port) {
-    SOCKADDR sa;
-    int sa_len = SOCKADDR_LEN;
-    int rv;
-
-    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
-                                  &sa_len, JNI_TRUE) != 0) {
-        return IOS_THROWN;
-    }
-
-    rv = connect(fd, (struct sockaddr *)&sa, sa_len);
-    if (rv != 0) {
-        if (errno == EINPROGRESS) {
-            return IOS_UNAVAILABLE;
-        } else if (errno == EINTR) {
-            return IOS_INTERRUPTED;
-        }
-        return handleSocketError(env, errno);
-    }
-    return 1;
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_SctpNet_close0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    if (fd != -1) {
-        int rv = close(fd);
-        if (rv < 0)
-            JNU_ThrowIOExceptionWithLastError(env, "Close failed");
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    preClose0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_SctpNet_preClose0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    if (preCloseFD >= 0) {
-        if (dup2(preCloseFD, fd) < 0)
-            JNU_ThrowIOExceptionWithLastError(env, "dup2 failed");
-    }
-}
-
-void initializeISA
-  (JNIEnv* env) {
-    if (isaCls == 0) {
-        jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
-        CHECK_NULL(c);
-        isaCls = (*env)->NewGlobalRef(env, c);
-        CHECK_NULL(isaCls);
-        (*env)->DeleteLocalRef(env, c);
-        isaCtrID = (*env)->GetMethodID(env, isaCls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
-    }
-}
-
-jobject SockAddrToInetSocketAddress
-  (JNIEnv *env, struct sockaddr* sap) {
-    int port = 0;
-
-    jobject ia = NET_SockaddrToInetAddress(env, sap, &port);
-    if (ia == NULL)
-        return NULL;
-
-    if (isaCls == 0) {
-        initializeISA(env);
-        CHECK_NULL_RETURN(isaCls, NULL);
-    }
-
-    return (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    getLocalAddresses0
- * Signature: (I)[Ljava/net/SocketAddress;
- */
-JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_SctpNet_getLocalAddresses0
-  (JNIEnv *env, jclass klass, jint fd) {
-    void *addr_buf, *laddr;
-    struct sockaddr* sap;
-    int i, addrCount;
-    jobjectArray isaa;
-
-#ifdef __solaris__
-    if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
-#else /* __linux__ */
-    if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
-#endif
-        handleSocketError(env, errno);
-        return NULL;
-    }
-
-    if (addrCount < 1)
-        return NULL;
-
-    if (isaCls == 0) {
-        initializeISA(env);
-        CHECK_NULL_RETURN(isaCls, NULL);
-    }
-
-    isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
-    if (isaa == NULL) {
-        nio_sctp_freeladdrs(addr_buf);
-        return NULL;
-    }
-
-    laddr = addr_buf;
-    for (i=0; i<addrCount; i++) {
-        int port = 0;
-        jobject isa = NULL, ia;
-        sap = (struct sockaddr*)addr_buf;
-        ia = NET_SockaddrToInetAddress(env, sap, &port);
-        if (ia != NULL)
-            isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
-        if (isa != NULL)
-            (*env)->SetObjectArrayElement(env, isaa, i, isa);
-
-        if (sap->sa_family == AF_INET)
-            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
-        else
-            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
-    }
-
-    nio_sctp_freeladdrs(laddr);
-    return isaa;
-}
-
-jobjectArray getRemoteAddresses
-  (JNIEnv *env, jint fd, sctp_assoc_t id) {
-    void *addr_buf, *paddr;
-    struct sockaddr* sap;
-    int i, addrCount;
-    jobjectArray isaa;
-
-#if __solaris__
-    if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
-#else /* __linux__ */
-    if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) {
-#endif
-        handleSocketError(env, errno);
-        return NULL;
-    }
-
-    if (addrCount < 1)
-        return NULL;
-
-    if (isaCls == 0) {
-        initializeISA(env);
-        CHECK_NULL_RETURN(isaCls, NULL);
-    }
-
-    isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
-    if (isaa == NULL) {
-        nio_sctp_freepaddrs(addr_buf);
-        return NULL;
-    }
-
-    paddr = addr_buf;
-    for (i=0; i<addrCount; i++) {
-        jobject ia, isa = NULL;
-        int port;
-        sap = (struct sockaddr*)addr_buf;
-        ia = NET_SockaddrToInetAddress(env, sap, &port);
-        if (ia != NULL)
-            isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
-        if (isa != NULL)
-            (*env)->SetObjectArrayElement(env, isaa, i, isa);
-
-        if (sap->sa_family == AF_INET)
-            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
-        else
-            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
-    }
-
-    nio_sctp_freepaddrs(paddr);
-
-    return isaa;
-}
-
- /*
- * Class:     sun_nio_ch_SctpNet
- * Method:    getRemoteAddresses0
- * Signature: (II)[Ljava/net/SocketAddress;
- */
-JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_SctpNet_getRemoteAddresses0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
-    return getRemoteAddresses(env, fd, assocId);
-}
-
-/* Map the Java level option to the native level */
-int mapSocketOption
-  (jint cmd, int *level, int *optname) {
-    static struct {
-        jint cmd;
-        int level;
-        int optname;
-    } const opts[] = {
-        { sun_nio_ch_SctpStdSocketOption_SCTP_DISABLE_FRAGMENTS,   IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS },
-        { sun_nio_ch_SctpStdSocketOption_SCTP_EXPLICIT_COMPLETE,   IPPROTO_SCTP, SCTP_EXPLICIT_EOR },
-        { sun_nio_ch_SctpStdSocketOption_SCTP_FRAGMENT_INTERLEAVE, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE },
-        { sun_nio_ch_SctpStdSocketOption_SCTP_NODELAY,             IPPROTO_SCTP, SCTP_NODELAY },
-        { sun_nio_ch_SctpStdSocketOption_SO_SNDBUF,                SOL_SOCKET,   SO_SNDBUF },
-        { sun_nio_ch_SctpStdSocketOption_SO_RCVBUF,                SOL_SOCKET,   SO_RCVBUF },
-        { sun_nio_ch_SctpStdSocketOption_SO_LINGER,                SOL_SOCKET,   SO_LINGER } };
-
-    int i;
-    for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
-        if (cmd == opts[i].cmd) {
-            *level = opts[i].level;
-            *optname = opts[i].optname;
-            return 0;
-        }
-    }
-
-    /* not found */
-    return -1;
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    setIntOption0
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_setIntOption0
-  (JNIEnv *env, jclass klass, jint fd, jint opt, int arg) {
-    int klevel, kopt;
-    int result;
-    struct linger linger;
-    void *parg;
-    int arglen;
-
-    if (mapSocketOption(opt, &klevel, &kopt) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Unsupported socket option");
-        return;
-    }
-
-    if (opt == sun_nio_ch_SctpStdSocketOption_SO_LINGER) {
-        parg = (void *)&linger;
-        arglen = sizeof(linger);
-        if (arg >= 0) {
-            linger.l_onoff = 1;
-            linger.l_linger = arg;
-        } else {
-            linger.l_onoff = 0;
-            linger.l_linger = 0;
-        }
-    } else {
-        parg = (void *)&arg;
-        arglen = sizeof(arg);
-    }
-
-    if (NET_SetSockOpt(fd, klevel, kopt, parg, arglen) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun_nio_ch_SctpNet.setIntOption0");
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    getIntOption0
- * Signature: (II)I
- */
-JNIEXPORT int JNICALL Java_sun_nio_ch_SctpNet_getIntOption0
-  (JNIEnv *env, jclass klass, jint fd, jint opt) {
-    int klevel, kopt;
-    int result;
-    struct linger linger;
-    void *arg;
-    int arglen;
-
-    if (mapSocketOption(opt, &klevel, &kopt) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "Unsupported socket option");
-        return -1;
-    }
-
-    if (opt == sun_nio_ch_SctpStdSocketOption_SO_LINGER) {
-        arg = (void *)&linger;
-        arglen = sizeof(linger);
-    } else {
-        arg = (void *)&result;
-        arglen = sizeof(result);
-    }
-
-    if (NET_GetSockOpt(fd, klevel, kopt, arg, &arglen) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.Net.getIntOption");
-        return -1;
-    }
-
-    if (opt == sun_nio_ch_SctpStdSocketOption_SO_LINGER)
-        return linger.l_onoff ? linger.l_linger : -1;
-    else
-        return result;
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    getPrimAddrOption0
- * Signature: (II)Ljava/net/SocketAddress;
- */
-JNIEXPORT jobject JNICALL Java_sun_nio_ch_SctpNet_getPrimAddrOption0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
-    struct sctp_setprim prim;
-    unsigned int prim_len = sizeof(prim);
-    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
-
-    prim.ssp_assoc_id = assocId;
-
-    if (getsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, &prim_len) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.SctpNet.getPrimAddrOption0");
-        return NULL;
-    }
-
-    return SockAddrToInetSocketAddress(env, sap);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    setPrimAddrOption0
- * Signature: (IILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_setPrimAddrOption0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) {
-    struct sctp_setprim prim;
-    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
-    int sap_len;
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
-                                  &sap_len, JNI_TRUE) != 0) {
-        return;
-    }
-
-    prim.ssp_assoc_id = assocId;
-
-    if (setsockopt(fd, IPPROTO_SCTP, SCTP_PRIMARY_ADDR, &prim, sizeof(prim)) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.SctpNet.setPrimAddrOption0");
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    setPeerPrimAddrOption0
- * Signature: (IILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_setPeerPrimAddrOption0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId,
-   jobject iaObj, jint port, jboolean preferIPv6) {
-    struct sctp_setpeerprim prim;
-    struct sockaddr* sap = (struct sockaddr*)&prim.sspp_addr;
-    int sap_len;
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
-                                  &sap_len, preferIPv6) != 0) {
-        return;
-    }
-
-    prim.sspp_assoc_id = assocId;
-
-    if (setsockopt(fd, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, &prim,
-            sizeof(prim)) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.SctpNet.setPeerPrimAddrOption0");
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    getInitMsgOption0
- * Signature: (I[I)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_getInitMsgOption0
-  (JNIEnv *env, jclass klass, jint fd, jintArray retVal) {
-    struct sctp_initmsg sctp_initmsg;
-    unsigned int sim_len = sizeof(sctp_initmsg);
-    int vals[2];
-
-    if (getsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_initmsg,
-            &sim_len) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.SctpNet.getInitMsgOption0");
-        return;
-    }
-
-    vals[0] = sctp_initmsg.sinit_max_instreams;
-    vals[1] = sctp_initmsg.sinit_num_ostreams;
-    (*env)->SetIntArrayRegion(env, retVal, 0, 2, vals);
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    setInitMsgOption0
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_setInitMsgOption0
-  (JNIEnv *env, jclass klass, jint fd, jint inArg, jint outArg) {
-    struct sctp_initmsg sctp_initmsg;
-
-    sctp_initmsg.sinit_max_instreams = (unsigned int)inArg;
-    sctp_initmsg.sinit_num_ostreams = (unsigned int)outArg;
-    sctp_initmsg.sinit_max_attempts = 0;  // default
-    sctp_initmsg.sinit_max_init_timeo = 0;  // default
-
-    if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &sctp_initmsg,
-          sizeof(sctp_initmsg)) < 0) {
-        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                     "sun.nio.ch.SctpNet.setInitMsgOption0");
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    shutdown0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_shutdown0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
-    int rv;
-    struct msghdr msg[1];
-    struct iovec iov[1];
-    int cbuf_size = CMSG_SPACE(sizeof (struct sctp_sndrcvinfo));
-    char cbuf[CMSG_SPACE(sizeof (struct sctp_sndrcvinfo))];
-    struct cmsghdr* cmsg;
-    struct sctp_sndrcvinfo *sri;
-
-    /* SctpSocketChannel */
-    if (assocId < 0) {
-        shutdown(fd, SHUT_WR);
-        return;
-    }
-
-    memset(msg, 0, sizeof (*msg));
-    memset(cbuf, 0, cbuf_size);
-    msg->msg_name = NULL;
-    msg->msg_namelen = 0;
-    iov->iov_base = NULL;
-    iov->iov_len = 0;
-    msg->msg_iov = iov;
-    msg->msg_iovlen = 1;
-    msg->msg_control = cbuf;
-    msg->msg_controllen = cbuf_size;
-    msg->msg_flags = 0;
-
-    cmsg = CMSG_FIRSTHDR(msg);
-    cmsg->cmsg_level = IPPROTO_SCTP;
-    cmsg->cmsg_type = SCTP_SNDRCV;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
-
-    /* Initialize the payload: */
-    sri = (struct sctp_sndrcvinfo*) CMSG_DATA(cmsg);
-    memset(sri, 0, sizeof (*sri));
-
-    if (assocId > 0) {
-        sri->sinfo_assoc_id = assocId;
-    }
-
-    sri->sinfo_flags = sri->sinfo_flags | SCTP_EOF;
-
-    /* Sum of the length of all control messages in the buffer. */
-    msg->msg_controllen = cmsg->cmsg_len;
-
-    if ((rv = sendmsg(fd, msg, 0)) < 0) {
-        handleSocketError(env, errno);
-    }
-}
-
-/*
- * Class:     sun_nio_ch_SctpNet
- * Method:    branch
- * Signature: (II)I
- */
-JNIEXPORT int JNICALL Java_sun_nio_ch_SctpNet_branch0
-  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
-    int newfd = 0;
-    if ((newfd = nio_sctp_peeloff(fd, assocId)) < 0) {
-        handleSocketError(env, errno);
-    }
-
-    return newfd;
-}
--- a/src/solaris/native/sun/nio/ch/SctpServerChannelImpl.c	Mon Jan 30 11:44:45 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "sun_nio_ch_SctpServerChannelImpl.h"
-
-extern void Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv* env,
-    jclass c);
-
-extern jint Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv* env,
-    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa);
-
-/*
- * Class:     sun_nio_ch_SctpServerChannelImpl
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_SctpServerChannelImpl_initIDs
-  (JNIEnv* env, jclass c) {
-    Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(env, c);
-}
-
-/*
- * Class:     sun_nio_ch_SctpServerChannelImpl
- * Method:    accept0
- * Signature: (Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpServerChannelImpl_accept0
-  (JNIEnv* env, jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa) {
-    return Java_sun_nio_ch_ServerSocketChannelImpl_accept0(env, this,
-                                                           ssfdo, newfdo, isaa);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/native/sun/nio/ch/sctp/Sctp.h	Sat Feb 04 07:29:11 2012 +0000
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.