changeset 2052:fc5578368a0c

6915313: Reorganize implementation to make it more feasible to port to JDK6 Summary: This makes the SCTP implementation easier to run with Suns JDK6. Reviewed-by: alanb
author chegar
date Mon, 11 Jan 2010 16:04:05 +0000
parents 0f0aee89e282
children 9d38ab65acff
files make/com/sun/nio/sctp/FILES_java.gmk make/com/sun/nio/sctp/mapfile-vers 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/SctpServerChannelImpl.java src/solaris/classes/sun/nio/ch/SctpSocketDispatcher.java src/solaris/native/sun/nio/ch/SctpNet.c
diffstat 8 files changed, 149 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/sun/nio/sctp/FILES_java.gmk	Sun Jan 10 12:29:19 2010 +0000
+++ b/make/com/sun/nio/sctp/FILES_java.gmk	Mon Jan 11 16:04:05 2010 +0000
@@ -57,8 +57,7 @@
 	sun/nio/ch/SctpResultContainer.java \
 	sun/nio/ch/SctpSendFailed.java \
 	sun/nio/ch/SctpServerChannelImpl.java \
-	sun/nio/ch/SctpShutdown.java \
-	sun/nio/ch/SctpSocketDispatcher.java
+	sun/nio/ch/SctpShutdown.java
 else
 FILES_java += \
 	sun/nio/ch/SctpChannelImpl.java \
--- a/make/com/sun/nio/sctp/mapfile-vers	Sun Jan 10 12:29:19 2010 +0000
+++ b/make/com/sun/nio/sctp/mapfile-vers	Mon Jan 11 16:04:05 2010 +0000
@@ -25,9 +25,14 @@
 
 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;
--- a/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Sun Jan 10 12:29:19 2010 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Mon Jan 11 16:04:05 2010 +0000
@@ -38,7 +38,6 @@
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ConnectionPendingException;
 import java.nio.channels.NoConnectionPendingException;
-import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.AlreadyConnectedException;
 import java.nio.channels.NotYetBoundException;
 import java.nio.channels.NotYetConnectedException;
@@ -54,7 +53,6 @@
 import com.sun.nio.sctp.NotificationHandler;
 import com.sun.nio.sctp.SctpChannel;
 import com.sun.nio.sctp.SctpSocketOption;
-import sun.nio.ch.NativeDispatcher;
 import sun.nio.ch.PollArrayWrapper;
 import sun.nio.ch.SelChImpl;
 import static com.sun.nio.sctp.SctpStandardSocketOption.*;
@@ -69,9 +67,6 @@
 public class SctpChannelImpl extends SctpChannel
     implements SelChImpl
 {
-    /* Used to make native close and preClose calls */
-    private static NativeDispatcher nd;
-
     private final FileDescriptor fd;
 
     private final int fdVal;
@@ -182,7 +177,7 @@
                 synchronized (stateLock) {
                     ensureOpenAndUnconnected();
                     if (isBound())
-                        throw new AlreadyBoundException();
+                        SctpNet.throwAlreadyBoundException();
                     InetSocketAddress isa = (local == null) ?
                         new InetSocketAddress(0) : Net.checkAddress(local);
                     Net.bind(fd, isa.getAddress(), isa.getPort());
@@ -234,7 +229,7 @@
                     if (add) {
                         for (InetSocketAddress addr : localAddresses) {
                             if (addr.getAddress().equals(address)) {
-                                throw new AlreadyBoundException();
+                                SctpNet.throwAlreadyBoundException();
                             }
                         }
                     } else { /*removing */
@@ -370,7 +365,7 @@
                                 InetAddress ia = isa.getAddress();
                                 if (ia.isAnyLocalAddress())
                                     ia = InetAddress.getLocalHost();
-                                n = Net.connect(fd, ia, isa.getPort());
+                                n = SctpNet.connect(fdVal, ia, isa.getPort());
                                 if (  (n == IOStatus.INTERRUPTED)
                                       && isOpen())
                                     continue;
@@ -556,7 +551,7 @@
     @Override
     public void implCloseSelectableChannel() throws IOException {
         synchronized (stateLock) {
-            nd.preClose(fd);
+            SctpNet.preClose(fdVal);
 
             if (receiverThread != 0)
                 NativeThread.signal(receiverThread);
@@ -662,7 +657,7 @@
             /* Postpone the kill if there is a waiting reader
              * or writer thread. */
             if (receiverThread == 0 && senderThread == 0) {
-                nd.close(fd);
+                SctpNet.close(fdVal);
                 state = ChannelState.KILLED;
             } else {
                 state = ChannelState.KILLPENDING;
@@ -1097,6 +1092,5 @@
         java.security.AccessController.doPrivileged(
                 new sun.security.action.LoadLibraryAction("sctp"));
         initIDs();
-        nd = new SctpSocketDispatcher();
     }
 }
--- a/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Sun Jan 10 12:29:19 2010 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Mon Jan 11 16:04:05 2010 +0000
@@ -38,7 +38,6 @@
 import java.util.HashMap;
 import java.nio.ByteBuffer;
 import java.nio.channels.SelectionKey;
-import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.NotYetBoundException;
 import java.nio.channels.spi.SelectorProvider;
@@ -63,9 +62,6 @@
 public class SctpMultiChannelImpl extends SctpMultiChannel
     implements SelChImpl
 {
-    /* Used to make native close and preClose calls */
-    private static NativeDispatcher nd;
-
     private final FileDescriptor fd;
 
     private final int fdVal;
@@ -140,7 +136,7 @@
                 synchronized (stateLock) {
                     ensureOpen();
                     if (isBound())
-                        throw new AlreadyBoundException();
+                        SctpNet.throwAlreadyBoundException();
                     InetSocketAddress isa = (local == null) ?
                         new InetSocketAddress(0) : Net.checkAddress(local);
 
@@ -155,7 +151,7 @@
                     if (isa.getAddress().isAnyLocalAddress())
                         wildcard = true;
 
-                    Net.listen(fd, backlog < 1 ? 50 : backlog);
+                    SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
                 }
             }
         }
@@ -196,7 +192,7 @@
                     if (add) {
                         for (InetSocketAddress addr : localAddresses) {
                             if (addr.getAddress().equals(address)) {
-                                throw new AlreadyBoundException();
+                                SctpNet.throwAlreadyBoundException();
                             }
                         }
                     } else { /*removing */
@@ -284,7 +280,7 @@
     @Override
     public void implCloseSelectableChannel() throws IOException {
         synchronized (stateLock) {
-            nd.preClose(fd);
+            SctpNet.preClose(fdVal);
 
             if (receiverThread != 0)
                 NativeThread.signal(receiverThread);
@@ -375,7 +371,7 @@
 
             /* Postpone the kill if there is a thread sending or receiving. */
             if (receiverThread == 0 && senderThread == 0) {
-                nd.close(fd);
+                SctpNet.close(fdVal);
                 state = ChannelState.KILLED;
             } else {
                 state = ChannelState.KILLPENDING;
@@ -981,6 +977,5 @@
         Util.load();   /* loads nio & net native libraries */
         java.security.AccessController.doPrivileged(
                 new sun.security.action.LoadLibraryAction("sctp"));
-        nd = new SctpSocketDispatcher();
     }
 }
--- a/src/solaris/classes/sun/nio/ch/SctpNet.java	Sun Jan 10 12:29:19 2010 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpNet.java	Mon Jan 11 16:04:05 2010 +0000
@@ -29,6 +29,7 @@
 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;
@@ -52,8 +53,29 @@
         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
+     * @param  oneToOne
      *         if {@code true} returns a one-to-one sctp socket, otherwise
      *         returns a one-to-many sctp socket
      */
@@ -240,6 +262,15 @@
     /* 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;
 
@@ -271,5 +302,11 @@
             throws IOException;
 
     static native void shutdown0(int fd, int assocId);
+
+    static native void init();
+
+    static {
+        init();
+    }
 }
 
--- a/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Sun Jan 10 12:29:19 2010 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Mon Jan 11 16:04:05 2010 +0000
@@ -33,7 +33,6 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.nio.channels.SelectionKey;
-import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.NotYetBoundException;
 import java.nio.channels.spi.SelectorProvider;
@@ -49,9 +48,6 @@
 public class SctpServerChannelImpl extends SctpServerChannel
     implements SelChImpl
 {
-    /* Used to make native close and preClose calls */
-    private static NativeDispatcher nd;
-
     private final FileDescriptor fd;
 
     private final int fdVal;
@@ -103,7 +99,7 @@
                 if (!isOpen())
                     throw new ClosedChannelException();
                 if (isBound())
-                    throw new AlreadyBoundException();
+                    SctpNet.throwAlreadyBoundException();
 
                 InetSocketAddress isa = (local == null) ?
                     new InetSocketAddress(0) : Net.checkAddress(local);
@@ -118,7 +114,7 @@
                     if (isa.getAddress().isAnyLocalAddress())
                         wildcard = true;
 
-                Net.listen(fd, backlog < 1 ? 50 : backlog);
+                SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
             }
         }
         return this;
@@ -156,7 +152,7 @@
                 if (add) {
                     for (InetSocketAddress addr : localAddresses) {
                         if (addr.getAddress().equals(address)) {
-                            throw new AlreadyBoundException();
+                            SctpNet.throwAlreadyBoundException();
                         }
                     }
                 } else { /*removing */
@@ -261,7 +257,7 @@
     @Override
     public void implCloseSelectableChannel() throws IOException {
         synchronized (stateLock) {
-            nd.preClose(fd);
+            SctpNet.preClose(fdVal);
             if (thread != 0)
                 NativeThread.signal(thread);
             if (!isRegistered())
@@ -282,7 +278,7 @@
 
             // Postpone the kill if there is a thread in accept
             if (thread == 0) {
-                nd.close(fd);
+                SctpNet.close(fdVal);
                 state = ChannelState.KILLED;
             } else {
                 state = ChannelState.KILLPENDING;
@@ -423,7 +419,6 @@
         Util.load();   // loads nio & net native libraries
         java.security.AccessController.doPrivileged(
                 new sun.security.action.LoadLibraryAction("sctp"));
-        nd = new SctpSocketDispatcher();
         initIDs();
     }
 }
--- a/src/solaris/classes/sun/nio/ch/SctpSocketDispatcher.java	Sun Jan 10 12:29:19 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2009 Sun Microsystems, Inc.  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.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-package sun.nio.ch;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-
-/**
- * Only used for {@code close} and {@code preclose}. All other methods
- * throw {@code IOException}.
- */
-class SctpSocketDispatcher extends NativeDispatcher {
-    @Override
-    @SuppressWarnings("unused")
-    int read(FileDescriptor fd, long address, int len) throws IOException {
-         throw new IOException("Operation Unsupported");
-    }
-
-    @Override
-    @SuppressWarnings("unused")
-    long readv(FileDescriptor fd, long address, int len) throws IOException {
-         throw new IOException("Operation Unsupported");
-    }
-
-    @Override
-    @SuppressWarnings("unused")
-    int write(FileDescriptor fd, long address, int len) throws IOException {
-         throw new IOException("Operation Unsupported");
-    }
-
-    @Override
-    @SuppressWarnings("unused")
-    long writev(FileDescriptor fd, long address, int len) throws IOException {
-         throw new IOException("Operation Unsupported");
-    }
-
-    @Override
-    void close(FileDescriptor fd) throws IOException {
-        FileDispatcherImpl.close0(fd);
-    }
-
-    @Override
-    void preClose(FileDescriptor fd) throws IOException {
-        FileDispatcherImpl.preClose0(fd);
-    }
-}
--- a/src/solaris/native/sun/nio/ch/SctpNet.c	Sun Jan 10 12:29:19 2010 +0000
+++ b/src/solaris/native/sun/nio/ch/SctpNet.c	Mon Jan 11 16:04:05 2010 +0000
@@ -48,6 +48,9 @@
     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.
@@ -109,6 +112,23 @@
 
 /*
  * 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
  */
@@ -184,6 +204,76 @@
     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) {