6915313: Reorganize implementation to make it more feasible to port to JDK6

This makes the SCTP implementation easier to run with Suns JDK6.

Reviewed-by: alanb
This commit is contained in:
Chris Hegarty 2010-01-11 16:04:05 +00:00
parent 30d2fd5f41
commit 1d92211cb6
8 changed files with 149 additions and 102 deletions

View File

@ -57,8 +57,7 @@ FILES_java += \
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 \

View File

@ -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;

View File

@ -38,7 +38,6 @@ import java.nio.channels.SelectionKey;
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.MessageInfo;
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 @@ import static sun.nio.ch.SctpResultContainer.SHUTDOWN;
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 @@ public class SctpChannelImpl extends SctpChannel
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 @@ public class SctpChannelImpl extends SctpChannel
if (add) {
for (InetSocketAddress addr : localAddresses) {
if (addr.getAddress().equals(address)) {
throw new AlreadyBoundException();
SctpNet.throwAlreadyBoundException();
}
}
} else { /*removing */
@ -370,7 +365,7 @@ public class SctpChannelImpl extends SctpChannel
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 @@ public class SctpChannelImpl extends SctpChannel
@Override
public void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
SctpNet.preClose(fdVal);
if (receiverThread != 0)
NativeThread.signal(receiverThread);
@ -662,7 +657,7 @@ public class SctpChannelImpl extends SctpChannel
/* 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 @@ public class SctpChannelImpl extends SctpChannel
java.security.AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("sctp"));
initIDs();
nd = new SctpSocketDispatcher();
}
}

View File

@ -38,7 +38,6 @@ import java.util.HashSet;
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 @@ import static sun.nio.ch.SctpResultContainer.*;
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 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
synchronized (stateLock) {
ensureOpen();
if (isBound())
throw new AlreadyBoundException();
SctpNet.throwAlreadyBoundException();
InetSocketAddress isa = (local == null) ?
new InetSocketAddress(0) : Net.checkAddress(local);
@ -155,7 +151,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
if (isa.getAddress().isAnyLocalAddress())
wildcard = true;
Net.listen(fd, backlog < 1 ? 50 : backlog);
SctpNet.listen(fdVal, backlog < 1 ? 50 : backlog);
}
}
}
@ -196,7 +192,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
if (add) {
for (InetSocketAddress addr : localAddresses) {
if (addr.getAddress().equals(address)) {
throw new AlreadyBoundException();
SctpNet.throwAlreadyBoundException();
}
}
} else { /*removing */
@ -284,7 +280,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
@Override
public void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
SctpNet.preClose(fdVal);
if (receiverThread != 0)
NativeThread.signal(receiverThread);
@ -375,7 +371,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
/* 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 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
Util.load(); /* loads nio & net native libraries */
java.security.AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("sctp"));
nd = new SctpSocketDispatcher();
}
}

View File

@ -29,6 +29,7 @@ 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;
@ -52,8 +53,29 @@ public class SctpNet {
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 @@ public class SctpNet {
/* 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 @@ public class SctpNet {
throws IOException;
static native void shutdown0(int fd, int assocId);
static native void init();
static {
init();
}
}

View File

@ -33,7 +33,6 @@ import java.util.Collections;
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 @@ import com.sun.nio.sctp.SctpStandardSocketOption;
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 @@ public class SctpServerChannelImpl extends SctpServerChannel
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 @@ public class SctpServerChannelImpl extends SctpServerChannel
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 @@ public class SctpServerChannelImpl extends SctpServerChannel
if (add) {
for (InetSocketAddress addr : localAddresses) {
if (addr.getAddress().equals(address)) {
throw new AlreadyBoundException();
SctpNet.throwAlreadyBoundException();
}
}
} else { /*removing */
@ -261,7 +257,7 @@ public class SctpServerChannelImpl extends SctpServerChannel
@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 @@ public class SctpServerChannelImpl extends SctpServerChannel
// 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 @@ public class SctpServerChannelImpl extends SctpServerChannel
Util.load(); // loads nio & net native libraries
java.security.AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("sctp"));
nd = new SctpSocketDispatcher();
initIDs();
}
}

View File

@ -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);
}
}

View File

@ -48,6 +48,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad
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.
@ -107,6 +110,23 @@ jboolean loadSocketExtensionFuncs
return JNI_TRUE;
}
/*
* 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
@ -184,6 +204,76 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_SctpNet_bindx
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) {