4927640: Implementation of the sctp protocol
An implementation-specific API for the Stream Control Transmission Protocol Reviewed-by: alanb, michaelm, jccollet
This commit is contained in:
parent
6e1d4b9a47
commit
26ae13fe80
@ -41,7 +41,7 @@ endif
|
||||
# Omit mirror since it's built with the apt tool.
|
||||
SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \
|
||||
java inputmethods org xml rowset net/httpserver net/ssl demo \
|
||||
tools jarsigner tracing servicetag
|
||||
tools jarsigner tracing servicetag nio
|
||||
|
||||
all build clean clobber::
|
||||
$(SUBDIRS-loop)
|
||||
|
38
jdk/make/com/sun/nio/Makefile
Normal file
38
jdk/make/com/sun/nio/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for com.sun.nio packages.
|
||||
#
|
||||
|
||||
BUILDDIR = ../../..
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
SUBDIRS = sctp
|
||||
all build clean clobber::
|
||||
$(SUBDIRS-loop)
|
||||
|
||||
clean clobber::
|
||||
$(RM) -r $(CLASSDESTDIR)/com/sun/nio
|
39
jdk/make/com/sun/nio/sctp/Exportedfiles.gmk
Normal file
39
jdk/make/com/sun/nio/sctp/Exportedfiles.gmk
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# These are the names of Java classes for which we will make .h files.
|
||||
#
|
||||
|
||||
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
|
||||
endif
|
31
jdk/make/com/sun/nio/sctp/FILES_c.gmk
Normal file
31
jdk/make/com/sun/nio/sctp/FILES_c.gmk
Normal file
@ -0,0 +1,31 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
ifneq ($(PLATFORM),windows)
|
||||
FILES_c = \
|
||||
SctpNet.c \
|
||||
SctpChannelImpl.c \
|
||||
SctpServerChannelImpl.c
|
||||
endif
|
67
jdk/make/com/sun/nio/sctp/FILES_java.gmk
Normal file
67
jdk/make/com/sun/nio/sctp/FILES_java.gmk
Normal file
@ -0,0 +1,67 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
FILES_java = \
|
||||
com/sun/nio/sctp/AbstractNotificationHandler.java \
|
||||
com/sun/nio/sctp/Association.java \
|
||||
com/sun/nio/sctp/AssociationChangeNotification.java \
|
||||
com/sun/nio/sctp/HandlerResult.java \
|
||||
com/sun/nio/sctp/IllegalReceiveException.java \
|
||||
com/sun/nio/sctp/IllegalUnbindException.java \
|
||||
com/sun/nio/sctp/InvalidStreamException.java \
|
||||
com/sun/nio/sctp/MessageInfo.java \
|
||||
com/sun/nio/sctp/Notification.java \
|
||||
com/sun/nio/sctp/NotificationHandler.java \
|
||||
com/sun/nio/sctp/PeerAddressChangeNotification.java \
|
||||
com/sun/nio/sctp/SctpChannel.java \
|
||||
com/sun/nio/sctp/SctpMultiChannel.java \
|
||||
com/sun/nio/sctp/SctpServerChannel.java \
|
||||
com/sun/nio/sctp/SctpSocketOption.java \
|
||||
com/sun/nio/sctp/SctpStandardSocketOption.java \
|
||||
com/sun/nio/sctp/SendFailedNotification.java \
|
||||
com/sun/nio/sctp/ShutdownNotification.java \
|
||||
\
|
||||
sun/nio/ch/SctpMessageInfoImpl.java \
|
||||
sun/nio/ch/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/SctpSocketDispatcher.java
|
||||
else
|
||||
FILES_java += \
|
||||
sun/nio/ch/SctpChannelImpl.java \
|
||||
sun/nio/ch/SctpMultiChannelImpl.java \
|
||||
sun/nio/ch/SctpServerChannelImpl.java
|
||||
endif
|
80
jdk/make/com/sun/nio/sctp/Makefile
Normal file
80
jdk/make/com/sun/nio/sctp/Makefile
Normal file
@ -0,0 +1,80 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# Makefile for com.sun.nio.sctp
|
||||
#
|
||||
|
||||
BUILDDIR = ../../../..
|
||||
PACKAGE = com.sun.nio.sctp
|
||||
LIBRARY = sctp
|
||||
PRODUCT = sun
|
||||
#OTHER_JAVACFLAGS += -Xmaxwarns 1000 -Xlint
|
||||
include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
#
|
||||
# Files to compile
|
||||
#
|
||||
include FILES_c.gmk
|
||||
include FILES_java.gmk
|
||||
include Exportedfiles.gmk
|
||||
|
||||
ifneq ($(PLATFORM), windows)
|
||||
include $(BUILDDIR)/common/Mapfile-vers.gmk
|
||||
include $(BUILDDIR)/common/Library.gmk
|
||||
|
||||
#
|
||||
# Find platform-specific C source files
|
||||
#
|
||||
vpath %.c $(PLATFORM_SRC)/native/sun/nio/ch
|
||||
|
||||
#
|
||||
# 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/java/net \
|
||||
-I$(PLATFORM_SRC)/native/java/net \
|
||||
-I$(CLASSHDRDIR)/../../../../java/java.nio/nio/CClassHeaders
|
||||
|
||||
ifeq ($(PLATFORM), linux)
|
||||
COMPILER_WARNINGS_FATAL=true
|
||||
#OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl
|
||||
OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -lnio -lnet -lpthread -ldl
|
||||
endif
|
||||
ifeq ($(PLATFORM), solaris)
|
||||
#LIBSCTP = -lsctp
|
||||
OTHER_LDLIBS += $(LIBSOCKET) -L$(LIBDIR)/$(LIBARCH) -lnet -lnio
|
||||
endif # PLATFORM
|
||||
|
||||
else # windows
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
endif # ifneq windows
|
||||
|
||||
|
||||
clean clobber::
|
||||
$(RM) -r $(CLASSDESTDIR)/com/sun/nio/sctp
|
||||
$(RM) -r $(CLASSDESTDIR)/sun/nio/ch
|
||||
|
49
jdk/make/com/sun/nio/sctp/mapfile-vers
Normal file
49
jdk/make/com/sun/nio/sctp/mapfile-vers
Normal file
@ -0,0 +1,49 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
Java_sun_nio_ch_SctpNet_socket0;
|
||||
Java_sun_nio_ch_SctpNet_bindx;
|
||||
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;
|
||||
JNI_OnLoad;
|
||||
local:
|
||||
*;
|
||||
};
|
@ -86,6 +86,8 @@ TREEAPI_PKGS = com.sun.source.tree \
|
||||
|
||||
SMARTCARDIO_PKGS = javax.smartcardio
|
||||
|
||||
SCTPAPI_PKGS = com.sun.nio.sctp
|
||||
|
||||
TRACING_PKGS = com.sun.tracing \
|
||||
com.sun.tracing.dtrace
|
||||
|
||||
@ -98,4 +100,6 @@ NON_CORE_PKGS = $(DOMAPI_PKGS) \
|
||||
$(OLD_JSSE_PKGS) \
|
||||
$(HTTPSERVER_PKGS) \
|
||||
$(SMARTCARDIO_PKGS) \
|
||||
$(TRACING_PKGS)
|
||||
$(TRACING_PKGS) \
|
||||
$(SCTPAPI_PKGS)
|
||||
|
||||
|
@ -189,6 +189,7 @@ SUNWprivate_1.1 {
|
||||
Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
|
||||
Java_sun_nio_fs_UnixNativeDispatcher_getextmntent;
|
||||
Java_sun_nio_fs_UnixCopyFile_transfer;
|
||||
handleSocketError;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -175,6 +175,7 @@ SUNWprivate_1.1 {
|
||||
Java_sun_nio_fs_SolarisWatchService_portDissociate;
|
||||
Java_sun_nio_fs_SolarisWatchService_portSend;
|
||||
Java_sun_nio_fs_SolarisWatchService_portGetn;
|
||||
handleSocketError;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* A skeletal handler that consumes notifications and continues.
|
||||
*
|
||||
* <P> This class trivially implements the {@code handleNotification} methods to
|
||||
* return {@link HandlerResult#CONTINUE CONTINUE} so that all notifications are
|
||||
* consumed and the channel continues to try and receive a message.
|
||||
*
|
||||
* <P> It also provides overloaded versions of the {@code handleNotification}
|
||||
* methods, one for each of the required supported notification types, {@link
|
||||
* AssociationChangeNotification}, {@link PeerAddressChangeNotification},
|
||||
* {@link SendFailedNotification}, and {@link ShutdownNotification}. The
|
||||
* appropriate method will be invoked when the notification is received.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class AbstractNotificationHandler<T>
|
||||
implements NotificationHandler<T>
|
||||
{
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected AbstractNotificationHandler() {}
|
||||
|
||||
/**
|
||||
* Invoked when an implementation specific notification is received from the
|
||||
* SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the {@code receive} operation when it was
|
||||
* initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
@Override
|
||||
public HandlerResult handleNotification(Notification notification,
|
||||
T attachment) {
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an {@link AssociationChangeNotification} is received from
|
||||
* the SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the {@code receive} operation when it was
|
||||
* initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
public HandlerResult handleNotification(AssociationChangeNotification notification,
|
||||
T attachment) {
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an {@link PeerAddressChangeNotification} is received from
|
||||
* the SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the {@code receive} operation when it was
|
||||
* initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
public HandlerResult handleNotification(PeerAddressChangeNotification notification,
|
||||
T attachment) {
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an {@link SendFailedNotification} is received from
|
||||
* the SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the {@code receive} operation when it was
|
||||
* initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
public HandlerResult handleNotification(SendFailedNotification notification,
|
||||
T attachment) {
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an {@link ShutdownNotification} is received from
|
||||
* the SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the {@code receive} operation when it was
|
||||
* initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
public HandlerResult handleNotification(ShutdownNotification notification,
|
||||
T attachment) {
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
}
|
104
jdk/src/share/classes/com/sun/nio/sctp/Association.java
Normal file
104
jdk/src/share/classes/com/sun/nio/sctp/Association.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* A class that represents an SCTP association.
|
||||
*
|
||||
* <P> An association exists between two SCTP endpoints. Each endpoint is
|
||||
* represented by a list of transport addresses through which that endpoint can
|
||||
* be reached and from which it will originate SCTP messages. The association
|
||||
* spans over all of the possible source/destination combinations which may be
|
||||
* generated from each endpoint's lists of addresses.
|
||||
*
|
||||
* <P> Associations are identified by their Association ID.
|
||||
* Association ID's are guaranteed to be unique for the lifetime of the
|
||||
* association. An association ID may be reused after the association has been
|
||||
* shutdown. An association ID is not unique across multiple SCTP channels.
|
||||
* An Association's local and remote addresses may change if the SCTP
|
||||
* implementation supports <I>Dynamic Address Reconfiguration</I> as defined by
|
||||
* <A HREF="http://tools.ietf.org/html/rfc5061">RFC5061</A>, see the
|
||||
* {@code bindAddress} and {@code unbindAddress} methods of {@link SctpChannel},
|
||||
* {@link SctpServerChannel}, and {@link SctpMultiChannel}.
|
||||
*
|
||||
* <P> An {@code Association} is returned from an {@link
|
||||
* SctpChannel#association SctpChannel} or an {@link
|
||||
* SctpMultiChannel#associations SctpMultiChannel}, as well
|
||||
* as being given as a parameter to {@link NotificationHandler
|
||||
* NotificationHandler} methods.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class Association {
|
||||
private final int associationID;
|
||||
private final int maxInStreams;
|
||||
private final int maxOutStreams;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected Association(int associationID,
|
||||
int maxInStreams,
|
||||
int maxOutStreams) {
|
||||
this.associationID = associationID;
|
||||
this.maxInStreams = maxInStreams;
|
||||
this.maxOutStreams = maxOutStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associationID.
|
||||
*
|
||||
* @return The association ID
|
||||
*/
|
||||
public final int associationID() {
|
||||
return associationID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the maximum number of inbound streams that this association
|
||||
* supports.
|
||||
*
|
||||
* <P> Data received on this association will be on stream number
|
||||
* {@code s}, where {@code 0 <= s < maxInboundStreams()}.
|
||||
*
|
||||
* @return The maximum number of inbound streams
|
||||
*/
|
||||
public final int maxInboundStreams() {
|
||||
return maxInStreams;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the maximum number of outbound streams that this association
|
||||
* supports.
|
||||
*
|
||||
* <P> Data sent on this association must be on stream number
|
||||
* {@code s}, where {@code 0 <= s < maxOutboundStreams()}.
|
||||
*
|
||||
* @return The maximum number of outbound streams
|
||||
*/
|
||||
public final int maxOutboundStreams() {
|
||||
return maxOutStreams;
|
||||
};
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Notification emitted when an association has either opened or closed.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class AssociationChangeNotification
|
||||
implements Notification
|
||||
{
|
||||
/**
|
||||
* Defines the type of change event that happened to the association.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public enum AssocChangeEvent
|
||||
{
|
||||
/**
|
||||
* A new association is now ready and data may be exchanged with this peer.
|
||||
*/
|
||||
COMM_UP,
|
||||
|
||||
/**
|
||||
* The association has failed. A series of SCTP send failed notifications
|
||||
* will follow this notification, one for each outstanding message.
|
||||
*/
|
||||
COMM_LOST,
|
||||
|
||||
/**
|
||||
* SCTP has detected that the peer has restarted.
|
||||
*/
|
||||
RESTART,
|
||||
|
||||
/**
|
||||
* The association has gracefully closed.
|
||||
*/
|
||||
SHUTDOWN,
|
||||
|
||||
/**
|
||||
* The association failed to setup. If a message was sent on a {@link
|
||||
* SctpMultiChannel} in non-blocking mode, an
|
||||
* SCTP send failed notification will follow this notification for the
|
||||
* outstanding message.
|
||||
*/
|
||||
CANT_START
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected AssociationChangeNotification() {}
|
||||
|
||||
/**
|
||||
* Returns the association that this notification is applicable to.
|
||||
*
|
||||
* @return The association whose state has changed, or {@code null} if
|
||||
* there is no association, that is {@linkplain
|
||||
* AssocChangeEvent#CANT_START CANT_START}
|
||||
*/
|
||||
public abstract Association association();
|
||||
|
||||
/**
|
||||
* Returns the type of change event.
|
||||
*
|
||||
* @return The event
|
||||
*/
|
||||
public abstract AssocChangeEvent event();
|
||||
}
|
47
jdk/src/share/classes/com/sun/nio/sctp/HandlerResult.java
Normal file
47
jdk/src/share/classes/com/sun/nio/sctp/HandlerResult.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Defines notification handler results.
|
||||
*
|
||||
* <P> The {@code HandlerResult} is used to determine the behavior of the
|
||||
* channel after it handles a notification from the SCTP stack. Essentially its
|
||||
* value determines if the channel should try to receive another notificaiton or
|
||||
* a message before returning.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public enum HandlerResult {
|
||||
/**
|
||||
* Try to receieve another message or notification.
|
||||
*/
|
||||
CONTINUE,
|
||||
|
||||
/**
|
||||
* Return without trying to receive any more data.
|
||||
*/
|
||||
RETURN;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Unchecked exception thrown when an attempt is made to invoke the
|
||||
* {@code receive} method of {@link SctpChannel} or {@link SctpMultiChannel}
|
||||
* from a notification handler.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class IllegalReceiveException extends IllegalStateException {
|
||||
private static final long serialVersionUID = 2296619040988576224L;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*/
|
||||
public IllegalReceiveException() { }
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class with the specified message.
|
||||
*/
|
||||
public IllegalReceiveException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Unchecked exception thrown when an attempt is made to remove an
|
||||
* address that is not bound to the channel, or remove an address from a
|
||||
* channel that has only one address bound to it.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class IllegalUnbindException extends IllegalStateException {
|
||||
private static final long serialVersionUID = -310540883995532224L;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*/
|
||||
public IllegalUnbindException() { }
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class with the specified detailed message.
|
||||
*/
|
||||
public IllegalUnbindException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Unchecked exception thrown when an attempt is made to send a
|
||||
* message to an invalid stream.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class InvalidStreamException extends IllegalArgumentException {
|
||||
private static final long serialVersionUID = -9172703378046665558L;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*/
|
||||
public InvalidStreamException() { }
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class with the specified detailed message.
|
||||
*/
|
||||
public InvalidStreamException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
303
jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java
Normal file
303
jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* The {@code MessageInfo} class provides additional ancillary information about
|
||||
* messages.
|
||||
*
|
||||
* <P> Received SCTP messages, returned by
|
||||
* {@link SctpChannel#receive SctpChannel.receive} and {@link
|
||||
* SctpMultiChannel#receive SctpMultiChannel.receive},
|
||||
* return a {@code MessageInfo} instance that can be queried to determine
|
||||
* ancillary information about the received message. Messages being sent should
|
||||
* use one of the {@link #createOutgoing(java.net.SocketAddress,int)
|
||||
* createOutgoing} methods to provide ancillary data for the message being
|
||||
* sent, and may use the appropriate setter methods to override the default
|
||||
* values provided for {@link #isUnordered() unordered}, {@link #timeToLive()
|
||||
* timeToLive}, {@link #isComplete() complete} and {@link #payloadProtocolID()
|
||||
* payloadProtocolID}, before sending the message.
|
||||
*
|
||||
* <P> For out going messages the {@code timeToLive} parameter is a time period
|
||||
* that the sending side SCTP stack may expire the message if it has not been
|
||||
* sent. This time period is an indication to the stack that the message is no
|
||||
* longer required to be sent after the time period expires. It is not a hard
|
||||
* timeout and may be influenced by whether the association supports the partial
|
||||
* reliability extension, <a href=http://www.ietf.org/rfc/rfc3758.txt>RFC 3758
|
||||
* <a>
|
||||
*
|
||||
* <P> {@code MessageInfo} instances are not safe for use by multiple concurrent
|
||||
* threads. If a MessageInfo is to be used by more than one thread then access
|
||||
* to the MessageInfo should be controlled by appropriate synchronization.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class MessageInfo {
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected MessageInfo() {}
|
||||
|
||||
/**
|
||||
* Creates a {@code MessageInfo} instance suitable for use when
|
||||
* sending a message.
|
||||
*
|
||||
* <P> The returned instance will have its {@link #isUnordered() unordered}
|
||||
* value set to {@code false}, its {@link #timeToLive() timeToLive} value
|
||||
* set to {@code 0}, its {@link #isComplete() complete} value set
|
||||
* to {@code true}, and its {@link #payloadProtocolID() payloadProtocolID}
|
||||
* value set to {@code 0}. These values, if required, can be set through
|
||||
* the appropriate setter method before sending the message.
|
||||
*
|
||||
* @param address
|
||||
* For a connected {@code SctpChannel} the address is the
|
||||
* preferred peer address of the association to send the message
|
||||
* to, or {@code null} to use the peer primary address. For an
|
||||
* {@code SctpMultiChannel} the address is used to determine
|
||||
* the association, or if no association exists with a peer of that
|
||||
* address then one is setup.
|
||||
*
|
||||
* @param streamNumber
|
||||
* The stream number that the message will be sent on
|
||||
*
|
||||
* @return The outgoing message info
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the streamNumber is negative or greater than {@code 65536}
|
||||
*/
|
||||
public static MessageInfo createOutgoing(SocketAddress address,
|
||||
int streamNumber) {
|
||||
if (streamNumber < 0 || streamNumber > 65536)
|
||||
throw new IllegalArgumentException("Invalid stream number");
|
||||
|
||||
return new sun.nio.ch.SctpMessageInfoImpl(null, address, streamNumber);
|
||||
}
|
||||
/**
|
||||
* Creates a {@code MessageInfo} instance suitable for use when
|
||||
* sending a message to a given association. Typically used for
|
||||
* {@code SctpMultiChannel} when an association has already been setup.
|
||||
*
|
||||
* <P> The returned instance will have its {@link #isUnordered() unordered}
|
||||
* value set to {@code false}, its {@link #timeToLive() timeToLive} value
|
||||
* set to {@code 0}, its {@link #isComplete() complete} value set
|
||||
* to {@code true}, and its {@link #payloadProtocolID() payloadProtocolID}
|
||||
* value set to {@code 0}. These values, if required, can be set through
|
||||
* the appropriate setter method before sending the message.
|
||||
*
|
||||
* @param association
|
||||
* The association to send the message on
|
||||
*
|
||||
* @param address
|
||||
* The preferred peer address of the association to send the message
|
||||
* to, or {@code null} to use the peer primary address
|
||||
*
|
||||
* @param streamNumber
|
||||
* The stream number that the message will be sent on.
|
||||
*
|
||||
* @return The outgoing message info
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If {@code association} is {@code null}, or the streamNumber is
|
||||
* negative or greater than {@code 65536}
|
||||
*/
|
||||
public static MessageInfo createOutgoing(Association association,
|
||||
SocketAddress address,
|
||||
int streamNumber) {
|
||||
if (association == null)
|
||||
throw new IllegalArgumentException("association cannot be null");
|
||||
|
||||
if (streamNumber < 0 || streamNumber > 65536)
|
||||
throw new IllegalArgumentException("Invalid stream number");
|
||||
|
||||
return new sun.nio.ch.SctpMessageInfoImpl(association, address,
|
||||
streamNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source socket address if the message has been received,
|
||||
* otherwise the preferred destination of the message to be sent.
|
||||
*
|
||||
* @return The socket address, or {@code null} if this instance is to be
|
||||
* used for sending a message and has been construced without
|
||||
* specifying a preferred destination address
|
||||
*
|
||||
*/
|
||||
public abstract SocketAddress address();
|
||||
|
||||
/**
|
||||
* Returns the association that the message was received on, if the message
|
||||
* has been received, otherwise the association that the message is to be
|
||||
* sent on.
|
||||
*
|
||||
* @return The association, or {@code null} if this instance is to be
|
||||
* used for sending a message and has been construced using the
|
||||
* the {@link #createOutgoing(SocketAddress,int)
|
||||
* createOutgoing(SocketAddress,int)} static factory method
|
||||
*/
|
||||
public abstract Association association();
|
||||
|
||||
/**
|
||||
* Returns the number of bytes read for the received message.
|
||||
*
|
||||
* <P> This method is only appicable for received messages, it has no
|
||||
* meaning for messages being sent.
|
||||
*
|
||||
* @return The number of bytes read, {@code -1} if the channel is an {@link
|
||||
* SctpChannel} that has reached end-of-stream, otherwise
|
||||
* {@code 0}
|
||||
*/
|
||||
public abstract int bytes();
|
||||
|
||||
/**
|
||||
* Tells whether or not the message is complete.
|
||||
*
|
||||
* <P> For received messages {@code true} indicates that the message was
|
||||
* completely received. For messages being sent {@code true} indicates that
|
||||
* the message is complete, {@code false} indicates that the message is not
|
||||
* complete. How the send channel interprets this value depends on the value
|
||||
* of its {@link SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE
|
||||
* SCTP_EXPLICIT_COMPLETE} socket option.
|
||||
*
|
||||
* @return {@code true} if, and only if, the message is complete
|
||||
*/
|
||||
public abstract boolean isComplete();
|
||||
|
||||
/**
|
||||
* Sets whether or not the message is complete.
|
||||
*
|
||||
* <P> For messages being sent {@code true} indicates that
|
||||
* the message is complete, {@code false} indicates that the message is not
|
||||
* complete. How the send channel interprets this value depends on the value
|
||||
* of its {@link SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE
|
||||
* SCTP_EXPLICIT_COMPLETE} socket option.
|
||||
*
|
||||
* @param complete
|
||||
* {@code true} if, and only if, the message is complete
|
||||
*
|
||||
* @return This MessageInfo
|
||||
*
|
||||
* @see MessageInfo#isComplete()
|
||||
*/
|
||||
public abstract MessageInfo complete(boolean complete);
|
||||
|
||||
/**
|
||||
* Tells whether or not the message is unordered. For received messages
|
||||
* {@code true} indicates that the message was sent non-ordered. For
|
||||
* messages being sent {@code true} requests the un-ordered delivery of the
|
||||
* message, {@code false} indicates that the message is ordered.
|
||||
*
|
||||
* @return {@code true} if the message is unordered, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public abstract boolean isUnordered();
|
||||
|
||||
/**
|
||||
* Sets whether or not the message is unordered.
|
||||
*
|
||||
* @param unordered
|
||||
* {@code true} requests the un-ordered delivery of the message,
|
||||
* {@code false} indicates that the message is ordered.
|
||||
*
|
||||
* @return This MessageInfo
|
||||
*
|
||||
* @see MessageInfo#isUnordered()
|
||||
*/
|
||||
public abstract MessageInfo unordered(boolean unordered);
|
||||
|
||||
/**
|
||||
* Returns the payload protocol Identifier.
|
||||
*
|
||||
* <P> A value indicating the type of payload protocol data being
|
||||
* transmitted/received. This value is passed as opaque data by SCTP.
|
||||
* {@code 0} indicates an unspecified payload protocol identifier.
|
||||
*
|
||||
* @return The Payload Protocol Identifier
|
||||
*/
|
||||
public abstract int payloadProtocolID();
|
||||
|
||||
/**
|
||||
* Sets the payload protocol Identifier.
|
||||
*
|
||||
* <P> A value indicating the type of payload protocol data being
|
||||
* transmitted. This value is passed as opaque data by SCTP.
|
||||
*
|
||||
* @param ppid
|
||||
* The Payload Protocol Identifier, or {@code 0} indicate an
|
||||
* unspecified payload protocol identifier.
|
||||
*
|
||||
* @return This MessageInfo
|
||||
*
|
||||
* @see MessageInfo#payloadProtocolID()
|
||||
*/
|
||||
public abstract MessageInfo payloadProtocolID(int ppid);
|
||||
|
||||
/**
|
||||
* Returns the stream number that the message was received on, if the
|
||||
* message has been received, otherwise the stream number that the message
|
||||
* is to be sent on.
|
||||
*
|
||||
* @return The stream number
|
||||
*/
|
||||
public abstract int streamNumber();
|
||||
|
||||
/**
|
||||
* Sets the stream number that the message is to be sent on.
|
||||
*
|
||||
* @param streamNumber
|
||||
* The stream number
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the streamNumber is negative or greater than {@code 65536}
|
||||
*
|
||||
* @return This MessageInfo
|
||||
*/
|
||||
public abstract MessageInfo streamNumber(int streamNumber);
|
||||
|
||||
/**
|
||||
* The time period that the sending side may expire the message if it has
|
||||
* not been sent, or {@code 0} to indicate that no timeout should occur. This
|
||||
* value is only applicable for messages being sent, it has no meaning for
|
||||
* received messages.
|
||||
*
|
||||
* @return The time period in milliseconds, or {@code 0}
|
||||
*/
|
||||
public abstract long timeToLive();
|
||||
|
||||
/**
|
||||
* Sets the time period that the sending side may expire the message if it
|
||||
* has not been sent.
|
||||
*
|
||||
* @param millis
|
||||
* The time period in milliseconds, or {@code 0} to indicate that no
|
||||
* timeout should occur
|
||||
*
|
||||
* @return This MessageInfo
|
||||
*
|
||||
* @see MessageInfo#timeToLive()
|
||||
*/
|
||||
public abstract MessageInfo timeToLive(long millis);
|
||||
}
|
45
jdk/src/share/classes/com/sun/nio/sctp/Notification.java
Normal file
45
jdk/src/share/classes/com/sun/nio/sctp/Notification.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* A notification from the SCTP stack.
|
||||
*
|
||||
* <P> Objects of this type are passed to the {@link NotificationHandler} when
|
||||
* a notification is received.
|
||||
*
|
||||
* <P> An SCTP channel supports the following notifications: {@link
|
||||
* AssociationChangeNotification}, {@link PeerAddressChangeNotification},
|
||||
* {@link SendFailedNotification}, {@link ShutdownNotification}, and may support
|
||||
* additional implementation specific notifications.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface Notification {
|
||||
/**
|
||||
* Returns the association that this notification is applicable to.
|
||||
*/
|
||||
public Association association();
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* A handler for consuming notifications from the SCTP stack.
|
||||
*
|
||||
* <P> The SCTP channels defined in this package allow a notification handler to
|
||||
* be specified to consume notifications from the SCTP stack. When a
|
||||
* notification is received the {@linkplain #handleNotification
|
||||
* handleNotification} method of the handler is invoked to handle that
|
||||
* notification.
|
||||
*
|
||||
* <P> Additionally, an attachment object can be attached to the {@code receive}
|
||||
* operation to provide context when consuming the notification. The
|
||||
* attachment is important for cases where a <i>state-less</i> {@code
|
||||
* NotificationHandler} is used to consume the result of many {@code receive}
|
||||
* operations.
|
||||
*
|
||||
* <P> Handler implementations are encouraged to extend the {@link
|
||||
* AbstractNotificationHandler} class which implements this interface and
|
||||
* provide notification specific methods. However, an API should generally use
|
||||
* this handler interface as the type for parameters, return type, etc. rather
|
||||
* than the abstract class.
|
||||
*
|
||||
* @param T The type of the object attached to the receive operation
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public interface NotificationHandler<T> {
|
||||
/**
|
||||
* Invoked when a notification is received from the SCTP stack.
|
||||
*
|
||||
* @param notification
|
||||
* The notification
|
||||
*
|
||||
* @param attachment
|
||||
* The object attached to the receive operation when it was initiated.
|
||||
*
|
||||
* @return The handler result
|
||||
*/
|
||||
HandlerResult handleNotification(Notification notification, T attachment);
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* Notification emitted when a destination address on a multi-homed peer
|
||||
* encounters a change.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class PeerAddressChangeNotification
|
||||
implements Notification
|
||||
{
|
||||
/**
|
||||
* Defines the type of address change event that occurred to the destination
|
||||
* address on a multi-homed peer when it encounters a change of interface
|
||||
* details.
|
||||
*
|
||||
* <P> Some of these events types are only generated when the association
|
||||
* supports dynamic address reconfiguration, e.g. {@code SCTP_ADDR_ADDED},
|
||||
* {@code SCTP_ADDR_REMOVED}, etc.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public enum AddressChangeEvent {
|
||||
/**
|
||||
* This address is now reachable.
|
||||
*/
|
||||
ADDR_AVAILABLE,
|
||||
|
||||
/**
|
||||
* The address specified can no longer be reached. Any data sent to this
|
||||
* address is rerouted to an alternate until this address becomes reachable.
|
||||
*/
|
||||
ADDR_UNREACHABLE,
|
||||
|
||||
/**
|
||||
* The address is no longer part of the association.
|
||||
*/
|
||||
ADDR_REMOVED,
|
||||
|
||||
/**
|
||||
* The address is now part of the association.
|
||||
*/
|
||||
ADDR_ADDED,
|
||||
|
||||
/**
|
||||
* This address has now been made to be the primary destination address.
|
||||
*/
|
||||
ADDR_MADE_PRIMARY,
|
||||
|
||||
/**
|
||||
* This address has now been confirmed as a valid address.
|
||||
*/
|
||||
ADDR_CONFIRMED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected PeerAddressChangeNotification() {}
|
||||
|
||||
/**
|
||||
* Returns the peer address.
|
||||
*
|
||||
* @return The peer address
|
||||
*/
|
||||
public abstract SocketAddress address();
|
||||
|
||||
/**
|
||||
* Returns the association that this notification is applicable to.
|
||||
*
|
||||
* @return The association whose peer address changed
|
||||
*/
|
||||
public abstract Association association();
|
||||
|
||||
/**
|
||||
* Returns the type of change event.
|
||||
*
|
||||
* @return The event
|
||||
*/
|
||||
public abstract AddressChangeEvent event();
|
||||
}
|
859
jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java
Normal file
859
jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java
Normal file
@ -0,0 +1,859 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
|
||||
/**
|
||||
* A selectable channel for message-oriented connected SCTP sockets.
|
||||
*
|
||||
* <P> An SCTP channel can only control one SCTP association.
|
||||
* An {@code SCTPChannel} is created by invoking one of the
|
||||
* {@link #open open} methods of this class. A newly-created channel is open but
|
||||
* not yet connected, that is, there is no association setup with a remote peer.
|
||||
* An attempt to invoke an I/O operation upon an unconnected
|
||||
* channel will cause a {@link java.nio.channels.NotYetConnectedException} to be
|
||||
* thrown. An association can be setup by connecting the channel using one of
|
||||
* its {@link #connect connect} methods. Once connected, the channel remains
|
||||
* connected until it is closed. Whether or not a channel is connected may be
|
||||
* determined by invoking {@link #getRemoteAddresses getRemoteAddresses}.
|
||||
*
|
||||
* <p> SCTP channels support <i>non-blocking connection:</i> A
|
||||
* channel may be created and the process of establishing the link to
|
||||
* the remote socket may be initiated via the {@link #connect connect} method
|
||||
* for later completion by the {@link #finishConnect finishConnect} method.
|
||||
* Whether or not a connection operation is in progress may be determined by
|
||||
* invoking the {@link #isConnectionPending isConnectionPending} method.
|
||||
*
|
||||
* <p> Socket options are configured using the
|
||||
* {@link #setOption(SctpSocketOption,Object) setOption} method. An SCTP
|
||||
* channel support the following options:
|
||||
* <blockquote>
|
||||
* <table border>
|
||||
* <tr>
|
||||
* <th>Option Name</th>
|
||||
* <th>Description</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_DISABLE_FRAGMENTS
|
||||
* SCTP_DISABLE_FRAGMENTS} </td>
|
||||
* <td> Enables or disables message fragmentation </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE
|
||||
* SCTP_EXPLICIT_COMPLETE} </td>
|
||||
* <td> Enables or disables explicit message completion </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_FRAGMENT_INTERLEAVE
|
||||
* SCTP_FRAGMENT_INTERLEAVE} </td>
|
||||
* <td> Controls how the presentation of messages occur for the message
|
||||
* receiver </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_INIT_MAXSTREAMS
|
||||
* SCTP_INIT_MAXSTREAMS} </td>
|
||||
* <td> The maximum number of streams requested by the local endpoint during
|
||||
* association initialization </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_NODELAY SCTP_NODELAY} </td>
|
||||
* <td> Enables or disable a Nagle-like algorithm </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_PRIMARY_ADDR
|
||||
* SCTP_PRIMARY_ADDR} </td>
|
||||
* <td> Requests that the local SCTP stack use the given peer address as the
|
||||
* association primary </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_SET_PEER_PRIMARY_ADDR
|
||||
* SCTP_SET_PEER_PRIMARY_ADDR} </td>
|
||||
* <td> Requests that the peer mark the enclosed address as the association
|
||||
* primary </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_SNDBUF
|
||||
* SO_SNDBUF} </td>
|
||||
* <td> The size of the socket send buffer </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_RCVBUF
|
||||
* SO_RCVBUF} </td>
|
||||
* <td> The size of the socket receive buffer </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_LINGER
|
||||
* SO_LINGER} </td>
|
||||
* <td> Linger on close if data is present (when configured in blocking mode
|
||||
* only) </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* Additional (implementation specific) options may also be supported. The list
|
||||
* of options supported is obtained by invoking the {@link #supportedOptions()
|
||||
* supportedOptions} method.
|
||||
*
|
||||
* <p> SCTP channels are safe for use by multiple concurrent threads.
|
||||
* They support concurrent reading and writing, though at most one thread may be
|
||||
* reading and at most one thread may be writing at any given time. The
|
||||
* {@link #connect connect} and {@link #finishConnect
|
||||
* finishConnect} methods are mutually synchronized against each other, and
|
||||
* an attempt to initiate a send or receive operation while an invocation of one
|
||||
* of these methods is in progress will block until that invocation is complete.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class SctpChannel
|
||||
extends AbstractSelectableChannel
|
||||
{
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*
|
||||
* @param provider
|
||||
* The selector provider for this channel
|
||||
*/
|
||||
protected SctpChannel(SelectorProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an SCTP channel.
|
||||
*
|
||||
* <P> The new channel is unbound and unconnected.
|
||||
*
|
||||
* @return A new SCTP channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the SCTP protocol is not supported
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public static SctpChannel open() throws
|
||||
IOException {
|
||||
return new sun.nio.ch.SctpChannelImpl((SelectorProvider)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an SCTP channel and connects it to a remote address.
|
||||
*
|
||||
* <P> This is a convenience method and is equivalent to evaluating the
|
||||
* following expression:
|
||||
* <blockquote><pre>
|
||||
* open().connect(remote, maxOutStreams, maxInStreams);
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param remote
|
||||
* The remote address to which the new channel is to be connected
|
||||
*
|
||||
* @param maxOutStreams
|
||||
* The number of streams that the application wishes to be able
|
||||
* to send to. Must be non negative and no larger than {@code 65536}.
|
||||
* {@code 0} to use the endpoints default value.
|
||||
*
|
||||
* @param maxInStreams
|
||||
* The maximum number of inbound streams the application is prepared
|
||||
* to support. Must be non negative and no larger than {@code 65536}.
|
||||
* {@code 0} to use the endpoints default value.
|
||||
*
|
||||
* @return A new SCTP channel connected to the given address
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the connect operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the connect operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.UnresolvedAddressException
|
||||
* If the given remote address is not fully resolved
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given remote address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed
|
||||
* and it does not permit access to the given remote peer
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the SCTP protocol is not supported
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public static SctpChannel open(SocketAddress remote, int maxOutStreams,
|
||||
int maxInStreams) throws IOException {
|
||||
SctpChannel ssc = SctpChannel.open();
|
||||
ssc.connect(remote, maxOutStreams, maxInStreams);
|
||||
return ssc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the association on this channel's socket.
|
||||
*
|
||||
* @return the association, or {@code null} if the channel's socket is not
|
||||
* connected.
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract Association association() throws IOException;
|
||||
|
||||
/**
|
||||
* Binds the channel's socket to a local address.
|
||||
*
|
||||
* <P> This method is used to establish a relationship between the socket
|
||||
* and the local addresses. Once a relationship is established then
|
||||
* the socket remains bound until the channel is closed. This relationship
|
||||
* may not necesssarily be with the address {@code local} as it may be removed
|
||||
* by {@link #unbindAddress unbindAddress}, but there will always be at least
|
||||
* one local address bound to the channel's socket once an invocation of
|
||||
* this method successfully completes.
|
||||
*
|
||||
* <P> Once the channel's socket has been successfully bound to a specific
|
||||
* address, that is not automatically assigned, more addresses
|
||||
* may be bound to it using {@link #bindAddress bindAddress}, or removed
|
||||
* using {@link #unbindAddress unbindAddress}.
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or {@code null} to
|
||||
* bind the socket to an automatically assigned socket address
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyConnectedException
|
||||
* If this channel is already connected
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.ConnectionPendingException
|
||||
* If a non-blocking connection operation is already in progress on this channel
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given address is not supported
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel bind(SocketAddress local)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Adds the given address to the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise {@link
|
||||
* java.nio.channels.NotYetBoundException} is thrown. The {@link #bind bind}
|
||||
* method takes a {@code SocketAddress} as its argument which typically
|
||||
* contains a port number as well as an address. Addresses subquently bound
|
||||
* using this method are simply addresses as the SCTP port number remains
|
||||
* the same for the lifetime of the channel.
|
||||
*
|
||||
* <P> Adding addresses to a connected association is optional functionality.
|
||||
* If the endpoint supports dynamic address reconfiguration then it may
|
||||
* send the appropriate message to the peer to change the peers address
|
||||
* lists.
|
||||
*
|
||||
* @param address
|
||||
* The address to add to the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.ConnectionPendingException
|
||||
* If a non-blocking connection operation is already in progress on
|
||||
* this channel
|
||||
*
|
||||
* @throws java.nio.channels.NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound to the given address
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel bindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Removes the given address from the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise {@link java.nio.channels.NotYetBoundException}
|
||||
* is thrown. If this method is invoked on a channel that does not have
|
||||
* {@code address} as one of its bound addresses or that has only one
|
||||
* local address bound to it, then this method throws
|
||||
* {@link IllegalUnbindException}.
|
||||
* The initial address that the channel's socket is bound to using {@link
|
||||
* #bind bind} may be removed from the bound addresses for the channel's socket.
|
||||
*
|
||||
* <P> Removing addresses from a connected association is optional
|
||||
* functionality. If the endpoint supports dynamic address reconfiguration
|
||||
* then it may send the appropriate message to the peer to change the peers
|
||||
* address lists.
|
||||
*
|
||||
* @param address
|
||||
* The address to remove from the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.ConnectionPendingException
|
||||
* If a non-blocking connection operation is already in progress on
|
||||
* this channel
|
||||
*
|
||||
* @throws java.nio.channels.NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IllegalUnbindException
|
||||
* If {@code address} is not bound to the channel's socket. or
|
||||
* the channel has only one address bound to it
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel unbindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Connects this channel's socket.
|
||||
*
|
||||
* <P> If this channel is in non-blocking mode then an invocation of this
|
||||
* method initiates a non-blocking connection operation. If the connection
|
||||
* is established immediately, as can happen with a local connection, then
|
||||
* this method returns {@code true}. Otherwise this method returns
|
||||
* {@code false} and the connection operation must later be completed by
|
||||
* invoking the {@link #finishConnect finishConnect} method.
|
||||
*
|
||||
* <P> If this channel is in blocking mode then an invocation of this
|
||||
* method will block until the connection is established or an I/O error
|
||||
* occurs.
|
||||
*
|
||||
* <P> If a security manager has been installed then this method verifies
|
||||
* that its {@link java.lang.SecurityManager#checkConnect checkConnect}
|
||||
* method permits connecting to the address and port number of the given
|
||||
* remote peer.
|
||||
*
|
||||
* <p> This method may be invoked at any time. If a {@link #send send} or
|
||||
* {@link #receive receive} operation upon this channel is invoked while an
|
||||
* invocation of this method is in progress then that operation will first
|
||||
* block until this invocation is complete. If a connection attempt is
|
||||
* initiated but fails, that is, if an invocation of this method throws a
|
||||
* checked exception, then the channel will be closed.
|
||||
*
|
||||
* @param remote
|
||||
* The remote peer to which this channel is to be connected
|
||||
*
|
||||
* @return {@code true} if a connection was established, {@code false} if
|
||||
* this channel is in non-blocking mode and the connection
|
||||
* operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyConnectedException
|
||||
* If this channel is already connected
|
||||
*
|
||||
* @throws java.nio.channels.ConnectionPendingException
|
||||
* If a non-blocking connection operation is already in progress on
|
||||
* this channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the connect operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the connect operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.UnresolvedAddressException
|
||||
* If the given remote address is not fully resolved
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given remote address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed
|
||||
* and it does not permit access to the given remote peer
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract boolean connect(SocketAddress remote) throws IOException;
|
||||
|
||||
/**
|
||||
* Connects this channel's socket.
|
||||
*
|
||||
* <P> This is a convience method and is equivalent to evaluating the
|
||||
* following expression:
|
||||
* <blockquote><pre>
|
||||
* setOption(SctpStandardSocketOption.SCTP_INIT_MAXSTREAMS, SctpStandardSocketOption.InitMaxStreams.create(maxInStreams, maxOutStreams))
|
||||
* .connect(remote);
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* <P> The {@code maxOutStreams} and {@code maxInStreams} parameters
|
||||
* represent the maximum number of streams that the application wishes to be
|
||||
* able to send to and receive from. They are negotiated with the remote
|
||||
* peer and may be limited by the operating system.
|
||||
*
|
||||
* @param remote
|
||||
* The remote peer to which this channel is to be connected
|
||||
*
|
||||
* @param maxOutStreams
|
||||
* Must be non negative and no larger than {@code 65536}.
|
||||
* {@code 0} to use the endpoints default value.
|
||||
*
|
||||
* @param maxInStreams
|
||||
* Must be non negative and no larger than {@code 65536}.
|
||||
* {@code 0} to use the endpoints default value.
|
||||
*
|
||||
* @return {@code true} if a connection was established, {@code false} if
|
||||
* this channel is in non-blocking mode and the connection operation
|
||||
* is in progress
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyConnectedException
|
||||
* If this channel is already connected
|
||||
*
|
||||
* @throws java.nio.channels.ConnectionPendingException
|
||||
* If a non-blocking connection operation is already in progress on
|
||||
* this channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the connect operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the connect operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.UnresolvedAddressException
|
||||
* If the given remote address is not fully resolved
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given remote address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed
|
||||
* and it does not permit access to the given remote peer
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract boolean connect(SocketAddress remote,
|
||||
int maxOutStreams,
|
||||
int maxInStreams)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Tells whether or not a connection operation is in progress on this channel.
|
||||
*
|
||||
* @return {@code true} if, and only if, a connection operation has been initiated
|
||||
* on this channel but not yet completed by invoking the
|
||||
* {@link #finishConnect} method
|
||||
*/
|
||||
public abstract boolean isConnectionPending();
|
||||
|
||||
/**
|
||||
* Finishes the process of connecting an SCTP channel.
|
||||
*
|
||||
* <P> A non-blocking connection operation is initiated by placing a socket
|
||||
* channel in non-blocking mode and then invoking one of its {@link #connect
|
||||
* connect} methods. Once the connection is established, or the attempt has
|
||||
* failed, the channel will become connectable and this method may
|
||||
* be invoked to complete the connection sequence. If the connection
|
||||
* operation failed then invoking this method will cause an appropriate
|
||||
* {@link java.io.IOException} to be thrown.
|
||||
*
|
||||
* <P> If this channel is already connected then this method will not block
|
||||
* and will immediately return <tt>true</tt>. If this channel is in
|
||||
* non-blocking mode then this method will return <tt>false</tt> if the
|
||||
* connection process is not yet complete. If this channel is in blocking
|
||||
* mode then this method will block until the connection either completes
|
||||
* or fails, and will always either return <tt>true</tt> or throw a checked
|
||||
* exception describing the failure.
|
||||
*
|
||||
* <P> This method may be invoked at any time. If a {@link #send send} or {@link #receive receive}
|
||||
* operation upon this channel is invoked while an invocation of this
|
||||
* method is in progress then that operation will first block until this
|
||||
* invocation is complete. If a connection attempt fails, that is, if an
|
||||
* invocation of this method throws a checked exception, then the channel
|
||||
* will be closed.
|
||||
*
|
||||
* @return {@code true} if, and only if, this channel's socket is now
|
||||
* connected
|
||||
*
|
||||
* @throws java.nio.channels.NoConnectionPendingException
|
||||
* If this channel is not connected and a connection operation
|
||||
* has not been initiated
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the connect operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the connect operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract boolean finishConnect() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns all of the socket addresses to which this channel's socket is
|
||||
* bound.
|
||||
*
|
||||
* @return All the socket addresses that this channel's socket is
|
||||
* bound to, or an empty {@code Set} if the channel's socket is not
|
||||
* bound
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public abstract Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns all of the remote addresses to which this channel's socket
|
||||
* is connected.
|
||||
*
|
||||
* <P> If the channel is connected to a remote peer that is bound to
|
||||
* multiple addresses then it is these addresses that the channel's socket
|
||||
* is connected.
|
||||
*
|
||||
* @return All of the remote addresses to which this channel's socket
|
||||
* is connected, or an empty {@code Set} if the channel's socket is
|
||||
* not connected
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public abstract Set<SocketAddress> getRemoteAddresses()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Shutdown a connection without closing the channel.
|
||||
*
|
||||
* <P> Sends a shutdown command to the remote peer, effectively preventing
|
||||
* any new data from being written to the socket by either peer. Further
|
||||
* sends will throw {@link java.nio.channels.ClosedChannelException}. The
|
||||
* channel remains open to allow the for any data (and notifications) to be
|
||||
* received that may have been sent by the peer before it received the
|
||||
* shutdown command. If the channel is already shutdown then invoking this
|
||||
* method has no effect.
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.NotYetConnectedException
|
||||
* If this channel is not yet connected
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel shutdown() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @return The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> T getOption(SctpSocketOption<T> name)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @param value
|
||||
* The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the value is not a valid value for this socket option
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> SctpChannel setOption(SctpSocketOption<T> name, T value)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this channel.
|
||||
*
|
||||
* <P> This method will continue to return the set of options even after the
|
||||
* channel has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this channel
|
||||
*/
|
||||
public abstract Set<SctpSocketOption<?>> supportedOptions();
|
||||
|
||||
/**
|
||||
* Returns an operation set identifying this channel's supported operations.
|
||||
*
|
||||
* <P> SCTP channels support connecting, reading, and writing, so this
|
||||
* method returns <tt>(</tt>{@link SelectionKey#OP_CONNECT}
|
||||
* <tt>|</tt> {@link SelectionKey#OP_READ} <tt>|</tt> {@link
|
||||
* SelectionKey#OP_WRITE}<tt>)</tt>. </p>
|
||||
*
|
||||
* @return The valid-operation set
|
||||
*/
|
||||
@Override
|
||||
public final int validOps() {
|
||||
return (SelectionKey.OP_READ |
|
||||
SelectionKey.OP_WRITE |
|
||||
SelectionKey.OP_CONNECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a message into the given buffer and/or handles a notification.
|
||||
*
|
||||
* <P> If a message or notification is immediately available, or if this
|
||||
* channel is in blocking mode and one eventually becomes available, then
|
||||
* the message or notification is returned or handled, respectively. If this
|
||||
* channel is in non-blocking mode and a message or notification is not
|
||||
* immediately available then this method immediately returns {@code null}.
|
||||
*
|
||||
* <P> If this method receives a message it is copied into the given byte
|
||||
* buffer. The message is transferred into the given byte buffer starting at
|
||||
* its current position and the buffers position is incremented by the
|
||||
* number of bytes read. If there are fewer bytes remaining in the buffer
|
||||
* than are required to hold the message, or the underlying input buffer
|
||||
* does not contain the complete message, then an invocation of {@link
|
||||
* MessageInfo#isComplete isComplete} on the returned {@code
|
||||
* MessageInfo} will return {@code false}, and more invocations of this
|
||||
* method will be necessary to completely consume the messgae. Only
|
||||
* one message at a time will be partially delivered in any stream. The
|
||||
* socket option {@link SctpStandardSocketOption#SCTP_FRAGMENT_INTERLEAVE
|
||||
* SCTP_FRAGMENT_INTERLEAVE} controls various aspects of what interlacing of
|
||||
* messages occurs.
|
||||
*
|
||||
* <P> If this method receives a notification then the appropriate method of
|
||||
* the given handler, if there is one, is invoked. If the handler returns
|
||||
* {@link HandlerResult#CONTINUE CONTINUE} then this method will try to
|
||||
* receive another message/notification, otherwise, if {@link
|
||||
* HandlerResult#RETURN RETURN} is returned this method will return {@code
|
||||
* null}. If an uncaught exception is thrown by the handler it will be
|
||||
* propagated up the stack through this method.
|
||||
*
|
||||
* <P> This method may be invoked at any time. If another thread has
|
||||
* already initiated a receive operation upon this channel, then an
|
||||
* invocation of this method will block until the first operation is
|
||||
* complete. The given handler is invoked without holding any locks used
|
||||
* to enforce the above synchronization policy, that way handlers
|
||||
* will not stall other threads from receiving. A handler should not invoke
|
||||
* the {@code receive} method of this channel, if it does an
|
||||
* {@link IllegalReceiveException} will be thrown.
|
||||
*
|
||||
* @param dst
|
||||
* The buffer into which message bytes are to be transferred
|
||||
*
|
||||
* @param attachment
|
||||
* The object to attach to the receive operation; can be
|
||||
* {@code null}
|
||||
*
|
||||
* @param handler
|
||||
* A handler to handle notifications from the SCTP stack, or {@code
|
||||
* null} to ignore any notifications.
|
||||
*
|
||||
* @return The {@code MessageInfo}, {@code null} if this channel is in
|
||||
* non-blocking mode and no messages are immediately available or
|
||||
* the notification handler returns {@link HandlerResult#RETURN
|
||||
* RETURN} after handling a notification
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the read operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the read operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.NotYetConnectedException
|
||||
* If this channel is not yet connected
|
||||
*
|
||||
* @throws IllegalReceiveException
|
||||
* If the given handler invokes the {@code receive} method of this
|
||||
* channel
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract <T> MessageInfo receive(ByteBuffer dst,
|
||||
T attachment,
|
||||
NotificationHandler<T> handler)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sends a message via this channel.
|
||||
*
|
||||
* <P> If this channel is in non-blocking mode and there is sufficient room
|
||||
* in the underlying output buffer, or if this channel is in blocking mode
|
||||
* and sufficient room becomes available, then the remaining bytes in the
|
||||
* given byte buffer are transmitted as a single message. Sending a message
|
||||
* is atomic unless explicit message completion {@link
|
||||
* SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE SCTP_EXPLICIT_COMPLETE}
|
||||
* socket option is enabled on this channel's socket.
|
||||
*
|
||||
* <P> The message is transferred from the byte buffer as if by a regular
|
||||
* {@link java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
|
||||
* write} operation.
|
||||
*
|
||||
* <P> The bytes will be written to the stream number that is specified by
|
||||
* {@link MessageInfo#streamNumber streamNumber} in the given {@code
|
||||
* messageInfo}.
|
||||
*
|
||||
* <P> This method may be invoked at any time. If another thread has already
|
||||
* initiated a send operation upon this channel, then an invocation of
|
||||
* this method will block until the first operation is complete.
|
||||
*
|
||||
* @param src
|
||||
* The buffer containing the message to be sent
|
||||
*
|
||||
* @param messageInfo
|
||||
* Ancillary data about the message to be sent
|
||||
*
|
||||
* @return The number of bytes sent, which will be either the number of
|
||||
* bytes that were remaining in the messages buffer when this method
|
||||
* was invoked or, if this channel is non-blocking, may be zero if
|
||||
* there was insufficient room for the message in the underlying
|
||||
* output buffer
|
||||
*
|
||||
* @throws InvalidStreamExcepton
|
||||
* If {@code streamNumner} is negative or greater than or equal to
|
||||
* the maximum number of outgoing streams
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the read operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the read operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.NotYetConnectedException
|
||||
* If this channel is not yet connected
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract int send(ByteBuffer src, MessageInfo messageInfo)
|
||||
throws IOException;
|
||||
}
|
731
jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java
Normal file
731
jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java
Normal file
@ -0,0 +1,731 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetBoundException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
|
||||
/**
|
||||
* A selectable channel for message-oriented SCTP sockets.
|
||||
*
|
||||
* <P> An SCTP multi channel supports many associations on a single socket.
|
||||
* An {@code SctpMultiChannel} is created by invoking the
|
||||
* {@link #open open} method of this class. A newly-created channel is open but
|
||||
* not yet bound. An attempt to invoke the {@link #receive receive} method of an
|
||||
* unbound channel will cause the {@link NotYetBoundException}
|
||||
* to be thrown. An attempt to invoke the {@link #send send} method of an
|
||||
* unbound channel will cause it to first invoke the {@link #bind bind} method.
|
||||
* The address(es) that the channel's socket is bound to can be retrieved by
|
||||
* calling {@link #getAllLocalAddresses getAllLocalAddresses}.
|
||||
*
|
||||
* <P> Messages may be sent and received without explicitly setting up an
|
||||
* association with the remote peer. The channel will implicitly setup
|
||||
* a new association whenever it sends or receives a message from a remote
|
||||
* peer if there is not already an association with that peer. Upon successful
|
||||
* association setup, an {@link AssociationChangeNotification
|
||||
* association changed} notification will be put to the SCTP stack with its
|
||||
* {@code event} parameter set to {@link
|
||||
* AssociationChangeNotification.AssocChangeEvent#COMM_UP
|
||||
* COMM_UP}. This notification can be received by invoking {@link #receive
|
||||
* receive}.
|
||||
*
|
||||
* <P> Socket options are configured using the
|
||||
* {@link #setOption(SctpSocketOption,Object,Association) setOption} method. An
|
||||
* {@code SctpMultiChannel} supports the following options:
|
||||
* <blockquote>
|
||||
* <table border>
|
||||
* <tr>
|
||||
* <th>Option Name</th>
|
||||
* <th>Description</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_DISABLE_FRAGMENTS
|
||||
* SCTP_DISABLE_FRAGMENTS} </td>
|
||||
* <td> Enables or disables message fragmentation </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE
|
||||
* SCTP_EXPLICIT_COMPLETE} </td>
|
||||
* <td> Enables or disables explicit message completion </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_FRAGMENT_INTERLEAVE
|
||||
* SCTP_FRAGMENT_INTERLEAVE} </td>
|
||||
* <td> Controls how the presentation of messages occur for the message
|
||||
* receiver </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_INIT_MAXSTREAMS
|
||||
* SCTP_INIT_MAXSTREAMS} </td>
|
||||
* <td> The maximum number of streams requested by the local endpoint during
|
||||
* association initialization </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_NODELAY SCTP_NODELAY} </td>
|
||||
* <td> Enables or disable a Nagle-like algorithm </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_PRIMARY_ADDR
|
||||
* SCTP_PRIMARY_ADDR} </td>
|
||||
* <td> Requests that the local SCTP stack use the given peer address as the
|
||||
* association primary </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_SET_PEER_PRIMARY_ADDR
|
||||
* SCTP_SET_PEER_PRIMARY_ADDR} </td>
|
||||
* <td> Requests that the peer mark the enclosed address as the association
|
||||
* primary </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_SNDBUF
|
||||
* SO_SNDBUF} </td>
|
||||
* <td> The size of the socket send buffer </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_RCVBUF
|
||||
* SO_RCVBUF} </td>
|
||||
* <td> The size of the socket receive buffer </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SO_LINGER
|
||||
* SO_LINGER} </td>
|
||||
* <td> Linger on close if data is present (when configured in blocking mode
|
||||
* only) </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* Additional (implementation specific) options may also be supported. The list
|
||||
* of options supported is obtained by invoking the {@link #supportedOptions()
|
||||
* supportedOptions} method.
|
||||
*
|
||||
* <p> SCTP multi channels are safe for use by multiple concurrent threads.
|
||||
* They support concurrent sending and receiving, though at most one thread may be
|
||||
* sending and at most one thread may be receiving at any given time.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class SctpMultiChannel
|
||||
extends AbstractSelectableChannel
|
||||
{
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*
|
||||
* @param provider
|
||||
* The selector provider for this channel
|
||||
*/
|
||||
protected SctpMultiChannel(SelectorProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an SCTP multi channel.
|
||||
*
|
||||
* <P> The new channel is unbound.
|
||||
*
|
||||
* @return A new SCTP multi channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the SCTP protocol is not supported
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public static SctpMultiChannel open() throws
|
||||
IOException {
|
||||
return new sun.nio.ch.SctpMultiChannelImpl((SelectorProvider)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the open associations on this channel's socket.
|
||||
*
|
||||
* <P> Only associations whose {@link AssociationChangeNotification.AssocChangeEvent#COMM_UP
|
||||
* COMM_UP} association change event has been received are included
|
||||
* in the returned set of associations. Associations for which a
|
||||
* {@link AssociationChangeNotification.AssocChangeEvent#COMM_LOST COMM_LOST} or {@link
|
||||
* AssociationChangeNotification.AssocChangeEvent#SHUTDOWN SHUTDOWN} association change
|
||||
* event have been receive are removed from the set of associations.
|
||||
*
|
||||
* <P> The returned set of associations is a snapshot of the open
|
||||
* associations at the time that this method is invoked.
|
||||
*
|
||||
* @return A {@code Set} containing the open associations, or an empty
|
||||
* {@code Set} if there are none.
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract Set<Association> associations()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Binds the channel's socket to a local address and configures the socket
|
||||
* to listen for connections.
|
||||
*
|
||||
* <P> This method is used to establish a relationship between the socket
|
||||
* and the local address. Once a relationship is established then
|
||||
* the socket remains bound until the channel is closed. This relationship
|
||||
* may not necesssarily be with the address {@code local} as it may be removed
|
||||
* by {@link #unbindAddress unbindAddress}, but there will always be at least one local
|
||||
* address bound to the channel's socket once an invocation of this method
|
||||
* successfully completes.
|
||||
*
|
||||
* <P> Once the channel's socket has been successfully bound to a specific
|
||||
* address, that is not automatically assigned, more addresses
|
||||
* may be bound to it using {@link #bindAddress bindAddress}, or removed
|
||||
* using {@link #unbindAddress unbindAddress}.
|
||||
*
|
||||
* <P> The backlog parameter is the maximum number of pending connections on
|
||||
* the socket. Its exact semantics are implementation specific. An implementation
|
||||
* may impose an implementation specific maximum length or may choose to ignore
|
||||
* the parameter. If the backlog parameter has the value {@code 0}, or a negative
|
||||
* value, then an implementation specific default is used.
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or {@code null} to
|
||||
* bind the socket to an automatically assigned socket address
|
||||
*
|
||||
* @param backlog
|
||||
* The maximum number number of pending connections
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and its {@link
|
||||
* java.lang.SecurityManager#checkListen(int) checkListen} method
|
||||
* denies the operation
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpMultiChannel bind(SocketAddress local,
|
||||
int backlog)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Binds the channel's socket to a local address and configures the socket
|
||||
* to listen for connections.
|
||||
*
|
||||
* <P> This method works as if invoking it were equivalent to evaluating the
|
||||
* expression:
|
||||
* <blockquote><pre>
|
||||
* bind(local, 0);
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or {@code null} to
|
||||
* bind the socket to an automatically assigned socket address
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and its {@link
|
||||
* java.lang.SecurityManager#checkListen(int) checkListen} method
|
||||
* denies the operation
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public final SctpMultiChannel bind(SocketAddress local)
|
||||
throws IOException {
|
||||
return bind(local, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given address to the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise {@link NotYetBoundException} is thrown.
|
||||
* The {@link #bind bind} method takes a {@code SocketAddress} as its
|
||||
* argument which typically contains a port number as well as an address.
|
||||
* Addresses subquently bound using this method are simply addresses as the
|
||||
* SCTP port number remains the same for the lifetime of the channel.
|
||||
*
|
||||
* <P> New associations setup after this method successfully completes
|
||||
* will be associated with the given address. Adding addresses to existing
|
||||
* associations is optional functionality. If the endpoint supports
|
||||
* dynamic address reconfiguration then it may send the appropriate message
|
||||
* to the peer to change the peers address lists.
|
||||
*
|
||||
* @param address
|
||||
* The address to add to the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound to the given address
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpMultiChannel bindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Removes the given address from the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise {@link NotYetBoundException} is thrown.
|
||||
*
|
||||
* <P> If this method is invoked on a channel that does
|
||||
* not have {@code address} as one of its bound addresses, or that has only
|
||||
* one local address bound to it, then this method throws
|
||||
* {@link IllegalUnbindException}.
|
||||
*
|
||||
* <P> The initial address that the channel's socket is bound to using
|
||||
* {@link #bind bind} may be removed from the bound addresses for the
|
||||
* channel's socket.
|
||||
*
|
||||
* <P> New associations setup after this method successfully completes
|
||||
* will not be associated with the given address. Removing addresses from
|
||||
* existing associations is optional functionality. If the endpoint supports
|
||||
* dynamic address reconfiguration then it may send the appropriate message
|
||||
* to the peer to change the peers address lists.
|
||||
*
|
||||
* @param address
|
||||
* The address to remove from the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws IllegalUnbindException
|
||||
* {@code address} is not bound to the channel's socket, or the
|
||||
* channel has only one address bound to it
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpMultiChannel unbindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns all of the socket addresses to which this channel's socket is
|
||||
* bound.
|
||||
*
|
||||
* @return All the socket addresses that this channel's socket is
|
||||
* bound to, or an empty {@code Set} if the channel's socket is not
|
||||
* bound
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public abstract Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns all of the remote addresses to which the given association on
|
||||
* this channel's socket is connected.
|
||||
*
|
||||
* @return All of the remote addresses for the given association, or
|
||||
* an empty {@code Set} if the association has been shutdown
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public abstract Set<SocketAddress> getRemoteAddresses(Association association)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Shutdown an association without closing the channel.
|
||||
*
|
||||
* @param association
|
||||
* The association to shutdown
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpMultiChannel shutdown(Association association)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* <P> Note that some options are retrieved on the channel's socket,
|
||||
* therefore the {@code association} parameter is not applicable and will be
|
||||
* ignored if given. However, if the option is association specific then the
|
||||
* association must be given.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @param association
|
||||
* The association whose option should be retrieved, or {@code null}
|
||||
* if this option should be retrieved at the channel's socket level.
|
||||
*
|
||||
* @return The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> T getOption(SctpSocketOption<T> name,
|
||||
Association association)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* <P> Note that some options are retrieved on the channel's socket,
|
||||
* therefore the {@code association} parameter is not applicable and will be
|
||||
* ignored if given. However, if the option is association specific then the
|
||||
* association must be given.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @param association
|
||||
* The association whose option should be set, or {@code null}
|
||||
* if this option should be set at the channel's socket level.
|
||||
*
|
||||
* @param value
|
||||
* The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the value is not a valid value for this socket option
|
||||
*
|
||||
* @throws ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> SctpMultiChannel setOption(SctpSocketOption<T> name,
|
||||
T value,
|
||||
Association association)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this channel.
|
||||
*
|
||||
* <P> This method will continue to return the set of options even after the
|
||||
* channel has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this channel
|
||||
*/
|
||||
public abstract Set<SctpSocketOption<?>> supportedOptions();
|
||||
|
||||
/**
|
||||
* Returns an operation set identifying this channel's supported operations.
|
||||
*
|
||||
* <P> SCTP multi channels support reading, and writing, so this
|
||||
* method returns
|
||||
* {@code (}{@link SelectionKey#OP_READ} {@code |} {@link
|
||||
* SelectionKey#OP_WRITE}{@code )}. </p>
|
||||
*
|
||||
* @return The valid-operation set
|
||||
*/
|
||||
@Override
|
||||
public final int validOps() {
|
||||
return (SelectionKey.OP_READ |
|
||||
SelectionKey.OP_WRITE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a message and/or handles a notification via this channel.
|
||||
*
|
||||
* <P> If a message or notification is immediately available, or if this
|
||||
* channel is in blocking mode and one eventually becomes available, then
|
||||
* the message or notification is returned or handled, respectively. If this
|
||||
* channel is in non-blocking mode and a message or notification is not
|
||||
* immediately available then this method immediately returns {@code null}.
|
||||
*
|
||||
* <P> If this method receives a message it is copied into the given byte
|
||||
* buffer and an {@link MessageInfo} is returned.
|
||||
* The message is transferred into the given byte buffer starting at its
|
||||
* current position and the buffers position is incremented by the number of
|
||||
* bytes read. If there are fewer bytes remaining in the buffer than are
|
||||
* required to hold the message, or the underlying input buffer does not
|
||||
* contain the complete message, then an invocation of {@link
|
||||
* MessageInfo#isComplete isComplete} on the returned {@code
|
||||
* MessageInfo} will return {@code false}, and more invocations of this
|
||||
* method will be necessary to completely consume the messgae. Only
|
||||
* one message at a time will be partially delivered in any stream. The
|
||||
* socket option {@link SctpStandardSocketOption#SCTP_FRAGMENT_INTERLEAVE
|
||||
* SCTP_FRAGMENT_INTERLEAVE} controls various aspects of what interlacing of
|
||||
* messages occurs.
|
||||
*
|
||||
* <P> If this method receives a notification then the appropriate method of
|
||||
* the given handler, if there is one, is invoked. If the handler returns {@link
|
||||
* HandlerResult#CONTINUE CONTINUE} then this method will try to receive another
|
||||
* message/notification, otherwise, if {@link HandlerResult#RETURN RETURN} is returned
|
||||
* this method will return {@code null}. If an uncaught exception is thrown by the
|
||||
* handler it will be propagated up the stack through this method.
|
||||
*
|
||||
* <P> If a security manager has been installed then for each new association
|
||||
* setup this method verifies that the associations source address and port
|
||||
* number are permitted by the security manager's {@link
|
||||
* java.lang.SecurityManager#checkAccept(String,int) checkAccept} method.
|
||||
*
|
||||
* <P> This method may be invoked at any time. If another thread has
|
||||
* already initiated a receive operation upon this channel, then an
|
||||
* invocation of this method will block until the first operation is
|
||||
* complete. The given handler is invoked without holding any locks used
|
||||
* to enforce the above synchronization policy, that way handlers
|
||||
* will not stall other threads from receiving. A handler should not invoke
|
||||
* the {@code receive} method of this channel, if it does an
|
||||
* {@link IllegalReceiveException} will be thrown.
|
||||
*
|
||||
* @param buffer
|
||||
* The buffer into which bytes are to be transferred
|
||||
*
|
||||
* @param attachment
|
||||
* The object to attach to the receive operation; can be
|
||||
* {@code null}
|
||||
*
|
||||
* @param handler
|
||||
* A handler to handle notifications from the SCTP stack, or
|
||||
* {@code null} to ignore any notifications.
|
||||
*
|
||||
* @return The {@code MessageInfo}, {@code null} if this channel is in
|
||||
* non-blocking mode and no messages are immediately available or
|
||||
* the notification handler returns {@code RETURN} after handling
|
||||
* a notification
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the read operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the read operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws IllegalReceiveException
|
||||
* If the given handler invokes the {@code receive} method of this
|
||||
* channel
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and it does not permit
|
||||
* new associations to be accepted from the message's sender
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract <T> MessageInfo receive(ByteBuffer buffer,
|
||||
T attachment,
|
||||
NotificationHandler<T> handler)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sends a message via this channel.
|
||||
*
|
||||
* <P> If this channel is unbound then this method will invoke {@link
|
||||
* #bind(SocketAddress, int) bind(null, 0)} before sending any data.
|
||||
*
|
||||
* <P> If there is no association existing between this channel's socket
|
||||
* and the intended receiver, identified by the address in the given messageInfo, then one
|
||||
* will be automatically setup to the intended receiver. This is considered
|
||||
* to be Implicit Association Setup. Upon successful association setup, an
|
||||
* {@link AssociationChangeNotification association changed}
|
||||
* notification will be put to the SCTP stack with its {@code event} parameter set
|
||||
* to {@link AssociationChangeNotification.AssocChangeEvent#COMM_UP COMM_UP}
|
||||
* . This notification can be received by invoking {@link #receive
|
||||
* receive}.
|
||||
*
|
||||
* <P> If this channel is in blocking mode, there is sufficient room in the
|
||||
* underlying output buffer, then the remaining bytes in the given byte
|
||||
* buffer are transmitted as a single message. Sending a message
|
||||
* is atomic unless explicit message completion {@link
|
||||
* SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE SCTP_EXPLICIT_COMPLETE}
|
||||
* socket option is enabled on this channel's socket.
|
||||
*
|
||||
* <P> If this channel is in non-blocking mode, there is sufficient room
|
||||
* in the underlying output buffer, and an implicit association setup is
|
||||
* required, then the remaining bytes in the given byte buffer are
|
||||
* transmitted as a single message, subject to {@link
|
||||
* SctpStandardSocketOption#SCTP_EXPLICIT_COMPLETE SCTP_EXPLICIT_COMPLETE}.
|
||||
* If for any reason the message cannot
|
||||
* be delivered an {@link AssociationChangeNotification association
|
||||
* changed} notification is put on the SCTP stack with its {@code event} parameter set
|
||||
* to {@link AssociationChangeNotification.AssocChangeEvent#CANT_START CANT_START}.
|
||||
*
|
||||
* <P> The message is transferred from the byte buffer as if by a regular
|
||||
* {@link java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
|
||||
* write} operation.
|
||||
*
|
||||
* <P> If a security manager has been installed then for each new association
|
||||
* setup this method verifies that the given remote peers address and port
|
||||
* number are permitted by the security manager's {@link
|
||||
* java.lang.SecurityManager#checkConnect(String,int) checkConnect} method.
|
||||
*
|
||||
* <P> This method may be invoked at any time. If another thread has already
|
||||
* initiated a send operation upon this channel, then an invocation of
|
||||
* this method will block until the first operation is complete.
|
||||
*
|
||||
* @param buffer
|
||||
* The buffer containing the message to be sent
|
||||
*
|
||||
* @param messageInfo
|
||||
* Ancillary data about the message to be sent
|
||||
*
|
||||
* @return The number of bytes sent, which will be either the number of
|
||||
* bytes that were remaining in the messages buffer when this method
|
||||
* was invoked or, if this channel is non-blocking, may be zero if
|
||||
* there was insufficient room for the message in the underlying
|
||||
* output buffer
|
||||
*
|
||||
* @throws InvalidStreamExcepton
|
||||
* If {@code streamNumber} is negative, or if an association already
|
||||
* exists and {@code streamNumber} is greater than the maximum number
|
||||
* of outgoing streams
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the read operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the read operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and it does not permit
|
||||
* new associations to be setup with the the messages's address
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract int send(ByteBuffer buffer, MessageInfo messageInfo)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Branches off an association.
|
||||
*
|
||||
* <P> An application can invoke this method to branch off an association
|
||||
* into a separate channel. The new bound and connected {@link SctpChannel}
|
||||
* will be created for the association. The branched off association will no
|
||||
* longer be part of this channel.
|
||||
*
|
||||
* <P> This is particularly useful when, for instance, the application
|
||||
* wishes to have a number of sporadic message senders/receivers remain
|
||||
* under the original SCTP multi channel but branch off those
|
||||
* associations carrying high volume data traffic into their own
|
||||
* separate SCTP channels.
|
||||
*
|
||||
* @param association
|
||||
* The association to branch off
|
||||
*
|
||||
* @return The {@code SctpChannel}
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel branch(Association association)
|
||||
throws IOException;
|
||||
}
|
421
jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java
Normal file
421
jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java
Normal file
@ -0,0 +1,421 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
|
||||
/**
|
||||
* A selectable channel for message-oriented listening SCTP sockets.
|
||||
*
|
||||
* <p> An {@code SCTPServerChannel} is created by invoking the
|
||||
* {@link #open open} method of this class. A newly-created SCTP server
|
||||
* channel is open but not yet bound. An attempt to invoke the
|
||||
* {@link #accept accept} method of an unbound channel will cause the
|
||||
* {@link java.nio.channels.NotYetBoundException} to be thrown. An SCTP server
|
||||
* channel can be bound by invoking one of the
|
||||
* {@link #bind(java.net.SocketAddress,int) bind} methods defined by this class.
|
||||
*
|
||||
* <p> Socket options are configured using the
|
||||
* {@link #setOption(SctpSocketOption,Object) setOption} method. SCTP server socket
|
||||
* channels support the following options:
|
||||
* <blockquote>
|
||||
* <table border>
|
||||
* <tr>
|
||||
* <th>Option Name</th>
|
||||
* <th>Description</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td> {@link SctpStandardSocketOption#SCTP_INIT_MAXSTREAMS
|
||||
* SCTP_INIT_MAXSTREAMS} </td>
|
||||
* <td> The maximum number of streams requested by the local endpoint during
|
||||
* association initialization </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* Additional (implementation specific) options may also be supported. The list
|
||||
* of options supported is obtained by invoking the {@link #supportedOptions()
|
||||
* supportedOptions} method.
|
||||
*
|
||||
* <p>SCTP server channels are safe for use by multiple concurrent threads.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class SctpServerChannel
|
||||
extends AbstractSelectableChannel
|
||||
{
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*
|
||||
* @param provider
|
||||
* The selector provider for this channel
|
||||
*/
|
||||
protected SctpServerChannel(SelectorProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an SCTP server channel.
|
||||
*
|
||||
* <P> The new channel's socket is initially unbound; it must be bound
|
||||
* to a specific address via one of its socket's {@link #bind bind}
|
||||
* methods before associations can be accepted.
|
||||
*
|
||||
* @return A new SCTP server channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the SCTP protocol is not supported
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public static SctpServerChannel open() throws
|
||||
IOException {
|
||||
return new sun.nio.ch.SctpServerChannelImpl((SelectorProvider)null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts an association on this channel's socket.
|
||||
*
|
||||
* <P> If this channel is in non-blocking mode then this method will
|
||||
* immediately return {@code null} if there are no pending associations.
|
||||
* Otherwise it will block indefinitely until a new association is
|
||||
* available or an I/O error occurs.
|
||||
*
|
||||
* <P> The {@code SCTPChannel} returned by this method, if any, will be in
|
||||
* blocking mode regardless of the blocking mode of this channel.
|
||||
*
|
||||
* <P> If a security manager has been installed then for each new
|
||||
* association this method verifies that the address and port number of the
|
||||
* assocaitions's remote peer are permitted by the security manager's {@link
|
||||
* java.lang.SecurityManager#checkAccept(String,int) checkAccept} method.
|
||||
*
|
||||
* @return The SCTP channel for the new association, or {@code null}
|
||||
* if this channel is in non-blocking mode and no association is
|
||||
* available to be accepted
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AsynchronousCloseException
|
||||
* If another thread closes this channel
|
||||
* while the accept operation is in progress
|
||||
*
|
||||
* @throws java.nio.channels.ClosedByInterruptException
|
||||
* If another thread interrupts the current thread
|
||||
* while the accept operation is in progress, thereby
|
||||
* closing the channel and setting the current thread's
|
||||
* interrupt status
|
||||
*
|
||||
* @throws java.nio.channels.NotYetBoundException
|
||||
* If this channel's socket has not yet been bound
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and it does not permit
|
||||
* access to the remote peer of the new association
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpChannel accept() throws IOException;
|
||||
|
||||
/**
|
||||
* Binds the channel's socket to a local address and configures the socket
|
||||
* to listen for associations.
|
||||
*
|
||||
* <P> This method works as if invoking it were equivalent to evaluating the
|
||||
* expression:
|
||||
* <blockquote><pre>
|
||||
* bind(local, 0);
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or {@code null} to
|
||||
* bind the socket to an automatically assigned socket address
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and its {@link
|
||||
* java.lang.SecurityManager#checkListen(int) checkListen} method
|
||||
* denies the operation
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public final SctpServerChannel bind(SocketAddress local)
|
||||
throws IOException {
|
||||
return bind(local, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the channel's socket to a local address and configures the socket
|
||||
* to listen for associations.
|
||||
*
|
||||
* <P> This method is used to establish a relationship between the socket
|
||||
* and the local address. Once a relationship is established then
|
||||
* the socket remains bound until the channel is closed. This relationship
|
||||
* may not necesssarily be with the address {@code local} as it may be
|
||||
* removed by {@link #unbindAddress unbindAddress}, but there will always be
|
||||
* at least one local address bound to the channel's socket once an
|
||||
* invocation of this method successfully completes.
|
||||
*
|
||||
* <P> Once the channel's socket has been successfully bound to a specific
|
||||
* address, that is not automatically assigned, more addresses
|
||||
* may be bound to it using {@link #bindAddress bindAddress}, or removed
|
||||
* using {@link #unbindAddress unbindAddress}.
|
||||
*
|
||||
* <P> The backlog parameter is the maximum number of pending associations
|
||||
* on the socket. Its exact semantics are implementation specific. An
|
||||
* implementation may impose an implementation specific maximum length or
|
||||
* may choose to ignore the parameter. If the backlog parameter has the
|
||||
* value {@code 0}, or a negative value, then an implementation specific
|
||||
* default is used.
|
||||
*
|
||||
* @param local
|
||||
* The local address to bind the socket, or {@code null} to
|
||||
* bind the socket to an automatically assigned socket address
|
||||
*
|
||||
* @param backlog
|
||||
* The maximum number number of pending associations
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound
|
||||
*
|
||||
* @throws java.nio.channels.UnsupportedAddressTypeException
|
||||
* If the type of the given address is not supported
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If a security manager has been installed and its {@link
|
||||
* java.lang.SecurityManager#checkListen(int) checkListen} method
|
||||
* denies the operation
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpServerChannel bind(SocketAddress local,
|
||||
int backlog)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Adds the given address to the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise {@link
|
||||
* java.nio.channels.NotYetBoundException} is thrown. The {@link #bind bind}
|
||||
* method takes a {@code SocketAddress} as its argument which typically
|
||||
* contains a port number as well as an address. Addresses subquently bound
|
||||
* using this method are simply addresses as the SCTP port number remains
|
||||
* the same for the lifetime of the channel.
|
||||
*
|
||||
* <P> New associations accepted after this method successfully completes
|
||||
* will be associated with the given address.
|
||||
*
|
||||
* @param address
|
||||
* The address to add to the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws java.nio.channels.AlreadyBoundException
|
||||
* If this channel is already bound to the given address
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpServerChannel bindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Removes the given address from the bound addresses for the channel's
|
||||
* socket.
|
||||
*
|
||||
* <P> The given address must not be the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address.
|
||||
* The channel must be first bound using {@link #bind bind} before
|
||||
* invoking this method, otherwise
|
||||
* {@link java.nio.channels.NotYetBoundException} is thrown.
|
||||
* If this method is invoked on a channel that does not have
|
||||
* {@code address} as one of its bound addresses, or that has only one
|
||||
* local address bound to it, then this method throws {@link
|
||||
* IllegalUnbindException}.
|
||||
* The initial address that the channel's socket is bound to using
|
||||
* {@link #bind bind} may be removed from the bound addresses for the
|
||||
* channel's socket.
|
||||
*
|
||||
* <P> New associations accepted after this method successfully completes
|
||||
* will not be associated with the given address.
|
||||
*
|
||||
* @param address
|
||||
* The address to remove from the bound addresses for the socket
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws java.nio.channels.NotYetBoundException
|
||||
* If this channel is not yet bound
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If address is {@code null} or the {@link
|
||||
* java.net.InetAddress#isAnyLocalAddress wildcard} address
|
||||
*
|
||||
* @throws IllegalUnbindException
|
||||
* If the implementation does not support removing addresses from a
|
||||
* listening socket, {@code address} is not bound to the channel's
|
||||
* socket, or the channel has only one address bound to it
|
||||
*
|
||||
* @throws IOException
|
||||
* If some other I/O error occurs
|
||||
*/
|
||||
public abstract SctpServerChannel unbindAddress(InetAddress address)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns all of the socket addresses to which this channel's socket is
|
||||
* bound.
|
||||
*
|
||||
* @return All the socket addresses that this channel's socket is
|
||||
* bound to, or an empty {@code Set} if the channel's socket is not
|
||||
* bound
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If the channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*/
|
||||
public abstract Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the value of a socket option.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @return The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> T getOption(SctpSocketOption<T> name) throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the value of a socket option.
|
||||
*
|
||||
* @param name
|
||||
* The socket option
|
||||
*
|
||||
* @param value
|
||||
* The value of the socket option. A value of {@code null} may be
|
||||
* a valid value for some socket options.
|
||||
*
|
||||
* @return This channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the socket option is not supported by this channel
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the value is not a valid value for this socket option
|
||||
*
|
||||
* @throws java.nio.channels.ClosedChannelException
|
||||
* If this channel is closed
|
||||
*
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public abstract <T> SctpServerChannel setOption(SctpSocketOption<T> name,
|
||||
T value)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a set of the socket options supported by this channel.
|
||||
*
|
||||
* <P> This method will continue to return the set of options even after the
|
||||
* channel has been closed.
|
||||
*
|
||||
* @return A set of the socket options supported by this channel
|
||||
*/
|
||||
public abstract Set<SctpSocketOption<?>> supportedOptions();
|
||||
|
||||
/**
|
||||
* Returns an operation set identifying this channel's supported
|
||||
* operations.
|
||||
*
|
||||
* <P> SCTP server channels only support the accepting of new
|
||||
* associations, so this method returns
|
||||
* {@link java.nio.channels.SelectionKey#OP_ACCEPT}.
|
||||
*
|
||||
* @return The valid-operation set
|
||||
*/
|
||||
@Override
|
||||
public final int validOps() {
|
||||
return SelectionKey.OP_ACCEPT;
|
||||
}
|
||||
}
|
38
jdk/src/share/classes/com/sun/nio/sctp/SctpSocketOption.java
Normal file
38
jdk/src/share/classes/com/sun/nio/sctp/SctpSocketOption.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketOption;
|
||||
|
||||
/**
|
||||
* A socket option associated with an SCTP channel.
|
||||
*
|
||||
* @param <T> The type of the socket option value.
|
||||
*
|
||||
* @since 1.7
|
||||
*
|
||||
* @see SctpStandardSocketOption
|
||||
*/
|
||||
public interface SctpSocketOption<T> extends SocketOption<T> { }
|
@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import sun.nio.ch.SctpStdSocketOption;
|
||||
|
||||
/**
|
||||
* SCTP channels supports the socket options defined by this class
|
||||
* (as well as those listed in the particular channel class) and may support
|
||||
* additional Implementation specific socket options.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class SctpStandardSocketOption {
|
||||
private SctpStandardSocketOption() {}
|
||||
/**
|
||||
* Enables or disables message fragmentation.
|
||||
*
|
||||
* <P> The value of this socket option is a {@code Boolean} that represents
|
||||
* whether the option is enabled or disabled. If enabled no SCTP message
|
||||
* fragmentation will be performed. Instead if a message being sent
|
||||
* exceeds the current PMTU size, the message will NOT be sent and
|
||||
* an error will be indicated to the user.
|
||||
*
|
||||
* <P> It is implementation specific whether or not this option is
|
||||
* supported.
|
||||
*/
|
||||
public static final SctpSocketOption<Boolean> SCTP_DISABLE_FRAGMENTS = new
|
||||
SctpStdSocketOption<Boolean>("SCTP_DISABLE_FRAGMENTS", Boolean.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS);
|
||||
|
||||
/**
|
||||
* Enables or disables explicit message completion.
|
||||
*
|
||||
* <p> The value of this socket option is a {@code Boolean} that represents
|
||||
* whether the option is enabled or disabled. When this option is enabled,
|
||||
* the {@code send} method may be invoked multiple times to a send message.
|
||||
* The {@code isComplete} parameter of the {@link MessageInfo} must only
|
||||
* be set to {@code true} for the final send to indicate that the message is
|
||||
* complete. If this option is disabled then each individual {@code send}
|
||||
* invocation is considered complete.
|
||||
*
|
||||
* <P> The default value of the option is {@code false} indicating that the
|
||||
* option is disabled. It is implementation specific whether or not this
|
||||
* option is supported.
|
||||
*/
|
||||
public static final SctpSocketOption<Boolean> SCTP_EXPLICIT_COMPLETE = new
|
||||
SctpStdSocketOption<Boolean>("SCTP_EXPLICIT_COMPLETE", Boolean.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE);
|
||||
|
||||
/**
|
||||
* Fragmented interleave controls how the presentation of messages occur
|
||||
* for the message receiver. There are three levels of fragment interleave
|
||||
* defined. Two of the levels effect {@link SctpChannel}, while
|
||||
* {@link SctpMultiChannel} is effected by all three levels.
|
||||
*
|
||||
* <P> This option takes an {@code Integer} value. It can be set to a value
|
||||
* of {@code 0}, {@code 1} or {@code 2}.
|
||||
*
|
||||
* <P> Setting the three levels provides the following receiver
|
||||
* interactions:
|
||||
*
|
||||
* <P> {@code level 0} - Prevents the interleaving of any messages. This
|
||||
* means that when a partial delivery begins, no other messages will be
|
||||
* received except the message being partially delivered. If another message
|
||||
* arrives on a different stream (or association) that could be delivered,
|
||||
* it will be blocked waiting for the user to read all of the partially
|
||||
* delivered message.
|
||||
*
|
||||
* <P> {@code level 1} - Allows interleaving of messages that are from
|
||||
* different associations. For {@code SctpChannel}, level 0 and
|
||||
* level 1 have the same meaning since an {@code SctpChannel} always
|
||||
* receives messages from the same association. Note that setting an {@code
|
||||
* SctpMultiChannel} to this level may cause multiple partial
|
||||
* delivers from different associations but for any given association, only
|
||||
* one message will be delivered until all parts of a message have been
|
||||
* delivered. This means that one large message, being read with an
|
||||
* association identification of "X", will block other messages from
|
||||
* association "X" from being delivered.
|
||||
*
|
||||
* <P> {@code level 2} - Allows complete interleaving of messages. This
|
||||
* level requires that the sender carefully observe not only the peer
|
||||
* {@code Association} but also must pay careful attention to the stream
|
||||
* number. With this option enabled a partially delivered message may begin
|
||||
* being delivered for association "X" stream "Y" and the next subsequent
|
||||
* receive may return a message from association "X" stream "Z". Note that
|
||||
* no other messages would be delivered for association "X" stream "Y"
|
||||
* until all of stream "Y"'s partially delivered message was read.
|
||||
* Note that this option effects both channel types. Also note that
|
||||
* for an {@code SctpMultiChannel} not only may another streams
|
||||
* message from the same association be delivered from the next receive,
|
||||
* some other associations message may be delivered upon the next receive.
|
||||
*
|
||||
* <P> It is implementation specific whether or not this option is
|
||||
* supported.
|
||||
*/
|
||||
public static final SctpSocketOption<Integer> SCTP_FRAGMENT_INTERLEAVE =
|
||||
new SctpStdSocketOption<Integer>("SCTP_FRAGMENT_INTERLEAVE",
|
||||
Integer.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE);
|
||||
|
||||
/**
|
||||
* The maximum number of streams requested by the local endpoint during
|
||||
* association initialization.
|
||||
*
|
||||
* <P> The value of this socket option is an {@link
|
||||
* SctpStandardSocketOption.InitMaxStreams InitMaxStreams}, that represents
|
||||
* the maximum number of inbound and outbound streams that an association
|
||||
* on the channel is prepared to support.
|
||||
*
|
||||
* <P> For an {@link SctpChannel} this option may only be used to
|
||||
* change the number of inbound/outbound streams prior to connecting.
|
||||
*
|
||||
* <P> For an {@link SctpMultiChannel} this option determines
|
||||
* the maximum number of inbound/outbound streams new associations setup
|
||||
* on the channel will be prepared to support.
|
||||
*
|
||||
* <P> For an {@link SctpServerChannel} this option determines the
|
||||
* maximum number of inbound/outbound streams accepted sockets will
|
||||
* negotiate with their connecting peer.
|
||||
*
|
||||
* <P> In all cases the value set by this option is used in the negotiation
|
||||
* of new associations setup on the channel's socket and the actual
|
||||
* maximum number of inbound/outbound streams that have been negotiated
|
||||
* with the peer can be retrieved from the appropriate {@link
|
||||
* Association}. The {@code Association} can be retrieved from the
|
||||
* {@link AssociationChangeNotification.AssocChangeEvent#COMM_UP COMM_UP}
|
||||
* {@link AssociationChangeNotification} belonging to that association.
|
||||
*
|
||||
* <p> This value is bounded by the actual implementation. In other
|
||||
* words the user may be able to support more streams than the Operating
|
||||
* System. In such a case, the Operating System limit may override the
|
||||
* value requested by the user. The default value of 0 indicates to use
|
||||
* the endpoints default value.
|
||||
*/
|
||||
public static final SctpSocketOption
|
||||
<SctpStandardSocketOption.InitMaxStreams> SCTP_INIT_MAXSTREAMS =
|
||||
new SctpStdSocketOption<SctpStandardSocketOption.InitMaxStreams>(
|
||||
"SCTP_INIT_MAXSTREAMS", SctpStandardSocketOption.InitMaxStreams.class);
|
||||
|
||||
/**
|
||||
* Enables or disables a Nagle-like algorithm.
|
||||
*
|
||||
* <P> The value of this socket option is a {@code Boolean} that represents
|
||||
* whether the option is enabled or disabled. SCTP uses an algorithm like
|
||||
* <em>The Nagle Algorithm</em> to coalesce short segments and
|
||||
* improve network efficiency.
|
||||
*/
|
||||
public static final SctpSocketOption<Boolean> SCTP_NODELAY =
|
||||
new SctpStdSocketOption<Boolean>("SCTP_NODELAY", Boolean.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SCTP_NODELAY);
|
||||
|
||||
/**
|
||||
* Requests that the local SCTP stack use the given peer address as
|
||||
* the association primary.
|
||||
*
|
||||
* <P> The value of this socket option is a {@code SocketAddress}
|
||||
* that represents the peer address that the local SCTP stack should use as
|
||||
* the association primary. The address must be one of the association
|
||||
* peer's addresses.
|
||||
*
|
||||
* <P> An {@code SctpMultiChannel} can control more than one
|
||||
* association, the association parameter must be given when setting or
|
||||
* retrieving this option.
|
||||
*
|
||||
* <P> Since {@code SctpChannel} only controls one association,
|
||||
* the association parameter is not required and this option can be
|
||||
* set or queried directly.
|
||||
*/
|
||||
public static final SctpSocketOption<SocketAddress> SCTP_PRIMARY_ADDR =
|
||||
new SctpStdSocketOption<SocketAddress>
|
||||
("SCTP_PRIMARY_ADDR", SocketAddress.class);
|
||||
|
||||
/**
|
||||
* Requests that the peer mark the enclosed address as the association
|
||||
* primary.
|
||||
*
|
||||
* <P> The value of this socket option is a {@code SocketAddress}
|
||||
* that represents the local address that the peer should use as its
|
||||
* primary address. The given address must be one of the association's
|
||||
* locally bound addresses.
|
||||
*
|
||||
* <P> An {@code SctpMultiChannel} can control more than one
|
||||
* association, the association parameter must be given when setting or
|
||||
* retrieving this option.
|
||||
*
|
||||
* <P> Since {@code SctpChannel} only controls one association,
|
||||
* the association parameter is not required and this option can be
|
||||
* queried directly.
|
||||
*
|
||||
* <P> Note, this is a set only option and cannot be retrieved by {@code
|
||||
* getOption}. It is implementation specific whether or not this
|
||||
* option is supported.
|
||||
*/
|
||||
public static final SctpSocketOption<SocketAddress> SCTP_SET_PEER_PRIMARY_ADDR =
|
||||
new SctpStdSocketOption<SocketAddress>
|
||||
("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class);
|
||||
|
||||
/**
|
||||
* The size of the socket send buffer.
|
||||
*
|
||||
* <p> The value of this socket option is an {@code Integer} that is the
|
||||
* size of the socket send buffer in bytes. The socket send buffer is an
|
||||
* output buffer used by the networking implementation. It may need to be
|
||||
* increased for high-volume connections. The value of the socket option is
|
||||
* a <em>hint</em> to the implementation to size the buffer and the actual
|
||||
* size may differ. The socket option can be queried to retrieve the actual
|
||||
* size.
|
||||
*
|
||||
* <p> For {@code SctpChannel}, this controls the amount of data
|
||||
* the SCTP stack may have waiting in internal buffers to be sent. This
|
||||
* option therefore bounds the maximum size of data that can be sent in a
|
||||
* single send call.
|
||||
*
|
||||
* <P> For {@code SctpMultiChannel}, the effect is the same as for {@code
|
||||
* SctpChannel}, except that it applies to all associations. The option
|
||||
* applies to each association's window size separately.
|
||||
*
|
||||
* <p> An implementation allows this socket option to be set before the
|
||||
* socket is bound or connected. Whether an implementation allows the
|
||||
* socket send buffer to be changed after the socket is bound is system
|
||||
* dependent.
|
||||
*/
|
||||
public static final SctpSocketOption<Integer> SO_SNDBUF =
|
||||
new SctpStdSocketOption<Integer>("SO_SNDBUF", Integer.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SO_SNDBUF);
|
||||
|
||||
/**
|
||||
* The size of the socket receive buffer.
|
||||
*
|
||||
* <P> The value of this socket option is an {@code Integer} that is the
|
||||
* size of the socket receive buffer in bytes. The socket receive buffer is
|
||||
* an input buffer used by the networking implementation. It may need to be
|
||||
* increased for high-volume connections or decreased to limit the possible
|
||||
* backlog of incoming data. The value of the socket option is a
|
||||
* <em>hint</em> to the implementation to size the buffer and the actual
|
||||
* size may differ.
|
||||
*
|
||||
* <P> For {@code SctpChannel}, this controls the receiver window size.
|
||||
*
|
||||
* <P> For {@code SctpMultiChannel}, the meaning is implementation
|
||||
* dependent. It might control the receive buffer for each association bound
|
||||
* to the socket descriptor or it might control the receive buffer for the
|
||||
* whole socket.
|
||||
*
|
||||
* <p> An implementation allows this socket option to be set before the
|
||||
* socket is bound or connected. Whether an implementation allows the
|
||||
* socket receive buffer to be changed after the socket is bound is system
|
||||
* dependent.
|
||||
*/
|
||||
public static final SctpSocketOption<Integer> SO_RCVBUF =
|
||||
new SctpStdSocketOption<Integer>("SO_RCVBUF", Integer.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SO_RCVBUF);
|
||||
|
||||
/**
|
||||
* Linger on close if data is present.
|
||||
*
|
||||
* <p> The value of this socket option is an {@code Integer} that controls
|
||||
* the action taken when unsent data is queued on the socket and a method
|
||||
* to close the socket is invoked. If the value of the socket option is zero
|
||||
* or greater, then it represents a timeout value, in seconds, known as the
|
||||
* <em>linger interval</em>. The linger interval is the timeout for the
|
||||
* {@code close} method to block while the operating system attempts to
|
||||
* transmit the unsent data or it decides that it is unable to transmit the
|
||||
* data. If the value of the socket option is less than zero then the option
|
||||
* is disabled. In that case the {@code close} method does not wait until
|
||||
* unsent data is transmitted; if possible the operating system will transmit
|
||||
* any unsent data before the connection is closed.
|
||||
*
|
||||
* <p> This socket option is intended for use with sockets that are configured
|
||||
* in {@link java.nio.channels.SelectableChannel#isBlocking() blocking} mode
|
||||
* only. The behavior of the {@code close} method when this option is
|
||||
* enabled on a non-blocking socket is not defined.
|
||||
*
|
||||
* <p> The initial value of this socket option is a negative value, meaning
|
||||
* that the option is disabled. The option may be enabled, or the linger
|
||||
* interval changed, at any time. The maximum value of the linger interval
|
||||
* is system dependent. Setting the linger interval to a value that is
|
||||
* greater than its maximum value causes the linger interval to be set to
|
||||
* its maximum value.
|
||||
*/
|
||||
public static final SctpSocketOption<Integer> SO_LINGER =
|
||||
new SctpStdSocketOption<Integer>("SO_LINGER", Integer.class,
|
||||
sun.nio.ch.SctpStdSocketOption.SO_LINGER);
|
||||
|
||||
/**
|
||||
* This class is used to set the maximum number of inbound/outbound streams
|
||||
* used by the local endpoint during association initialization. An
|
||||
* instance of this class is used to set the {@link
|
||||
* SctpStandardSocketOption#SCTP_INIT_MAXSTREAMS SCTP_INIT_MAXSTREAMS}
|
||||
* socket option.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public static class InitMaxStreams {
|
||||
private int maxInStreams;
|
||||
private int maxOutStreams;
|
||||
|
||||
private InitMaxStreams(int maxInStreams, int maxOutStreams) {
|
||||
this.maxInStreams = maxInStreams;
|
||||
this.maxOutStreams = maxOutStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an InitMaxStreams instance.
|
||||
*
|
||||
* @param maxInStreams
|
||||
* The maximum number of inbound streams, where
|
||||
* {@code 0 <= maxInStreams <= 65536}
|
||||
*
|
||||
* @param maxOutStreams
|
||||
* The maximum number of outbound streams, where
|
||||
* {@code 0 <= maxOutStreams <= 65536}
|
||||
*
|
||||
* @return An {@code InitMaxStreams} instance
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If an argument is outside of specified bounds
|
||||
*/
|
||||
public static InitMaxStreams create
|
||||
(int maxInStreams, int maxOutStreams) {
|
||||
if (maxOutStreams < 0 || maxOutStreams > 65535)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid maxOutStreams value");
|
||||
if (maxInStreams < 0 || maxInStreams > 65535)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid maxInStreams value");
|
||||
|
||||
return new InitMaxStreams(maxInStreams, maxOutStreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of inbound streams.
|
||||
*
|
||||
* @return Maximum inbound streams
|
||||
*/
|
||||
public int maxInStreams() {
|
||||
return maxInStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of outbound streams.
|
||||
*
|
||||
* @return Maximum outbound streams
|
||||
*/
|
||||
public int maxOutStreams() {
|
||||
return maxOutStreams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this init max streams, including
|
||||
* the maximum in and out bound streams.
|
||||
*
|
||||
* @return A string representation of this init max streams
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(super.toString()).append(" [");
|
||||
sb.append("maxInStreams:").append(maxInStreams);
|
||||
sb.append("maxOutStreams:").append(maxOutStreams).append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified object is another {@code InitMaxStreams}
|
||||
* instance with the same number of in and out bound streams.
|
||||
*
|
||||
* @param obj
|
||||
* The object to be compared with this init max streams
|
||||
*
|
||||
* @return true if the specified object is another
|
||||
* {@code InitMaxStreams} instance with the same number of in
|
||||
* and out bound streams
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj != null && obj instanceof InitMaxStreams) {
|
||||
InitMaxStreams that = (InitMaxStreams) obj;
|
||||
if (this.maxInStreams == that.maxInStreams &&
|
||||
this.maxOutStreams == that.maxOutStreams)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for this init max streams.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7 ^ maxInStreams ^ maxOutStreams;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* Notification emitted when a send failed notification has been received.
|
||||
*
|
||||
* <P> A send failed notification indicates that a message cannot be delivered.
|
||||
* Typically this is because the association has been shutdown with unsent data
|
||||
* in the socket output buffer, or in the case of a {@link SctpMultiChannel}
|
||||
* the association failed to setup.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class SendFailedNotification implements Notification {
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected SendFailedNotification() {}
|
||||
|
||||
/**
|
||||
* Returns the association that this notification is applicable to.
|
||||
*
|
||||
* @return The association that failed to send, or {@code null} if
|
||||
* there is no association, that is, the notification follows a
|
||||
* {@linkplain
|
||||
* com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent#CANT_START}
|
||||
*/
|
||||
@Override
|
||||
public abstract Association association();
|
||||
|
||||
/**
|
||||
* Returns the address.
|
||||
*
|
||||
* @return The peer primary address of the association or the address that
|
||||
* the message was sent to
|
||||
*/
|
||||
public abstract SocketAddress address();
|
||||
|
||||
/**
|
||||
* Returns the data that was to be sent.
|
||||
*
|
||||
* @return The user data. The buffers position will be {@code 0} and its
|
||||
* limit will be set to the end of the data.
|
||||
*/
|
||||
public abstract ByteBuffer buffer();
|
||||
|
||||
/**
|
||||
* Returns the error code.
|
||||
*
|
||||
* <P> The errorCode gives the reason why the send failed, and if set, will
|
||||
* be a SCTP protocol error code as defined in RFC2960 section 3.3.10
|
||||
*
|
||||
* @return The error code
|
||||
*/
|
||||
public abstract int errorCode();
|
||||
|
||||
/**
|
||||
* Returns the stream number that the messge was to be sent on.
|
||||
*
|
||||
* @return The stream number
|
||||
*/
|
||||
public abstract int streamNumber();
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.sun.nio.sctp;
|
||||
|
||||
/**
|
||||
* Notification emitted when a peers shutdowns an the association.
|
||||
*
|
||||
* <P> When a peer sends a <i>SHUTDOWN</i>, the SCTP stack delivers this
|
||||
* notification to inform the application that it should cease sending data.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public abstract class ShutdownNotification implements Notification {
|
||||
/**
|
||||
* Initializes a new instance of this class.
|
||||
*/
|
||||
protected ShutdownNotification() {}
|
||||
|
||||
/**
|
||||
* Returns the association that this notification is applicable to.
|
||||
*
|
||||
* @return The association that received the shutdown
|
||||
*/
|
||||
public abstract Association association();
|
||||
}
|
75
jdk/src/share/classes/com/sun/nio/sctp/package-info.java
Normal file
75
jdk/src/share/classes/com/sun/nio/sctp/package-info.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Java API for Stream Control Transport Protocol.
|
||||
*
|
||||
* <P> The Stream Control Transport Protocol (SCTP) is a reliable,
|
||||
* message-oriented, transport protocol existing at an equivalent level with UDP
|
||||
* (User Datagram Protocol) and TCP (Transmission Control Protocol). SCTP is
|
||||
* session oriented and an association between the endpoints must be established
|
||||
* before any data can be transmitted.
|
||||
*
|
||||
* <P> SCTP has direct support for multi-homing, meaning than an endpoint may be
|
||||
* represented by more than one address and each address may be used for sending
|
||||
* and receiving data, thus providing network redundancy. The connection between
|
||||
* two endpoints is referred to as an association between those endpoints.
|
||||
* Endpoints can exchange a list of addresses during association setup. One
|
||||
* address is designated as the primary address, this is the default address that
|
||||
* the peer will use for sending data. A single port number is used across the
|
||||
* entire address list at an endpoint for a specific session.
|
||||
*
|
||||
* <P> SCTP is message based. I/O operations operate upon messages and message
|
||||
* boundaries are preserved. Each association may support multiple independant
|
||||
* logical streams. Each stream represents a sequence of messages within a single
|
||||
* association and streams are independant of one another, meaning that stream
|
||||
* identifiers and sequence numbers are included in the data packet to allow
|
||||
* sequencing of messages on a per-stream basis.
|
||||
*
|
||||
* <P> This package provides two programming model styles. The one-to-one style
|
||||
* supported by {@link com.sun.nio.sctp.SctpChannel} and {@link
|
||||
* com.sun.nio.sctp.SctpServerChannel}, and the one-to-many
|
||||
* style supported by {@link com.sun.nio.sctp.SctpMultiChannel}.
|
||||
* The semantics of the one-to-one style interface are very similar to TCP.
|
||||
* An {@code SctpChannel} can only control one SCTP association. The
|
||||
* semantics of the one-to-many style interface are very similar to UDP. An
|
||||
* {@code SctpMutliChannel} can control multiple SCTP associations.
|
||||
*
|
||||
* <P> Applications can send and receive per-message ancillary information through
|
||||
* {@link com.sun.nio.sctp.MessageInfo}. For example, the stream number that
|
||||
* the message it is to be sent or received from. The SCTP stack is event driven
|
||||
* and applications can receive notifications of certain SCTP events by invoking
|
||||
* the {@code receive} method of the SCTP channel with an appropriate {@link
|
||||
* com.sun.nio.sctp.NotificationHandler notification handler}.
|
||||
*
|
||||
* <P> The SCTP protocol is defined by
|
||||
* <A HREF="http://tools.ietf.org/html/rfc4960">RFC4960</A>, and the optional
|
||||
* extension for <I>Dynamic Address Reconfiguration</I> is defined by
|
||||
* <A HREF="http://tools.ietf.org/html/rfc5061">RFC5061</A>.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
|
||||
package com.sun.nio.sctp;
|
170
jdk/src/share/classes/sun/nio/ch/SctpMessageInfoImpl.java
Normal file
170
jdk/src/share/classes/sun/nio/ch/SctpMessageInfoImpl.java
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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.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();
|
||||
}
|
||||
}
|
76
jdk/src/share/classes/sun/nio/ch/SctpStdSocketOption.java
Normal file
76
jdk/src/share/classes/sun/nio/ch/SctpStdSocketOption.java
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 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;
|
||||
}
|
||||
}
|
120
jdk/src/solaris/classes/sun/nio/ch/SctpAssocChange.java
Normal file
120
jdk/src/solaris/classes/sun/nio/ch/SctpAssocChange.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 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();
|
||||
}
|
||||
}
|
52
jdk/src/solaris/classes/sun/nio/ch/SctpAssociationImpl.java
Normal file
52
jdk/src/solaris/classes/sun/nio/ch/SctpAssociationImpl.java
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 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();
|
||||
}
|
||||
}
|
||||
|
1073
jdk/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java
Normal file
1073
jdk/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java
Normal file
File diff suppressed because it is too large
Load Diff
959
jdk/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java
Normal file
959
jdk/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java
Normal file
@ -0,0 +1,959 @@
|
||||
/*
|
||||
* 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.net.InetAddress;
|
||||
import java.net.SocketAddress;
|
||||
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.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;
|
||||
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.SctpStandardSocketOption.*;
|
||||
import static sun.nio.ch.SctpResultContainer.*;
|
||||
|
||||
/**
|
||||
* An implementation of SctpMultiChannel
|
||||
*/
|
||||
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;
|
||||
|
||||
/* 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())
|
||||
throw new AlreadyBoundException();
|
||||
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;
|
||||
|
||||
Net.listen(fd, 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)) {
|
||||
throw new AlreadyBoundException();
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
nd.preClose(fd);
|
||||
|
||||
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) {
|
||||
nd.close(fd);
|
||||
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();
|
||||
|
||||
SctpNet.setSocketOption(fdVal, name, value,
|
||||
association.associationID());
|
||||
}
|
||||
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) {
|
||||
checkAssociation(association);
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
||||
return (T)SctpNet.getSocketOption(fdVal, name,
|
||||
association.associationID());
|
||||
}
|
||||
}
|
||||
|
||||
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<T>
|
||||
extends AbstractNotificationHandler<T>
|
||||
{
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
AssociationChangeNotification not, T 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 absHandler =
|
||||
(AbstractNotificationHandler)handler;
|
||||
switch(resultContainer.type()) {
|
||||
case ASSOCIATION_CHANGED :
|
||||
result = absHandler.handleNotification(
|
||||
resultContainer.getAssociationChanged(), attachment);
|
||||
case PEER_ADDRESS_CHANGED :
|
||||
result = absHandler.handleNotification(
|
||||
resultContainer.getPeerAddressChanged(), attachment);
|
||||
case SEND_FAILED :
|
||||
result = absHandler.handleNotification(
|
||||
resultContainer.getSendFailed(), attachment);
|
||||
case SHUTDOWN :
|
||||
result = absHandler.handleNotification(
|
||||
resultContainer.getShutdown(), attachment);
|
||||
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();
|
||||
for (java.util.Map.Entry<SocketAddress, Association> entry : addrAssocs) {
|
||||
if (entry.getValue().equals(association)) {
|
||||
addressMap.remove(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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();
|
||||
int pos = src.position();
|
||||
int lim = src.limit();
|
||||
assert (pos <= lim && streamNumber > 0);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
if (src instanceof DirectBuffer)
|
||||
return sendFromNativeBuffer(fd, src, rem, pos, target, assocId,
|
||||
streamNumber, unordered, ppid);
|
||||
|
||||
/* Substitute a native buffer */
|
||||
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, rem, pos, 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,
|
||||
int rem,
|
||||
int pos,
|
||||
SocketAddress target,
|
||||
int assocId,
|
||||
int streamNumber,
|
||||
boolean unordered,
|
||||
int ppid)
|
||||
throws IOException {
|
||||
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.EMPTY_SET;
|
||||
|
||||
return SctpNet.getLocalAddresses(fdVal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getRemoteAddresses(Association association)
|
||||
throws IOException {
|
||||
synchronized (stateLock) {
|
||||
checkAssociation(association);
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
||||
return SctpNet.getRemoteAddresses(fdVal, association.associationID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel branch(Association association)
|
||||
throws IOException {
|
||||
synchronized (stateLock) {
|
||||
return null; //TODO: implement
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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"));
|
||||
nd = new SctpSocketDispatcher();
|
||||
}
|
||||
}
|
268
jdk/src/solaris/classes/sun/nio/ch/SctpNet.java
Normal file
268
jdk/src/solaris/classes/sun/nio/ch/SctpNet.java
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
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.SctpStandardSocketOption.*;
|
||||
|
||||
public class SctpNet {
|
||||
static final String osName = AccessController.doPrivileged(
|
||||
new GetPropertyAction("os.name"));
|
||||
|
||||
/* -- Miscellaneous SCTP utilities -- */
|
||||
|
||||
static boolean bindxIPv4MappedAddresses() {
|
||||
if ("SunOS".equals(osName)) {
|
||||
/* Solaris supports IPv4Mapped Addresses with bindx */
|
||||
return true;
|
||||
} /* else { //other OS/implementations */
|
||||
|
||||
/* lksctp/linux requires Ipv4 addresses */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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,
|
||||
bindxIPv4MappedAddresses());
|
||||
}
|
||||
|
||||
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 void setSocketOption(int fd,
|
||||
SctpSocketOption name,
|
||||
Object value,
|
||||
int assocId)
|
||||
throws IOException {
|
||||
if (value == null)
|
||||
throw new IllegalArgumentException("Invalid option value");
|
||||
|
||||
Class<?> type = name.type();
|
||||
if (!type.isInstance(value))
|
||||
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());
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
/* Native Methods */
|
||||
static native int socket0(boolean oneToOne) 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 void setPrimAddrOption0(int fd, int assocId, InetAddress ia,
|
||||
int port) throws IOException;
|
||||
|
||||
static native void setPeerPrimAddrOption0(int fd, int assocId,
|
||||
InetAddress ia, int port) 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);
|
||||
}
|
||||
|
37
jdk/src/solaris/classes/sun/nio/ch/SctpNotification.java
Normal file
37
jdk/src/solaris/classes/sun/nio/ch/SctpNotification.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 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);
|
||||
}
|
119
jdk/src/solaris/classes/sun/nio/ch/SctpPeerAddrChange.java
Normal file
119
jdk/src/solaris/classes/sun/nio/ch/SctpPeerAddrChange.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.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();
|
||||
}
|
||||
}
|
||||
|
126
jdk/src/solaris/classes/sun/nio/ch/SctpResultContainer.java
Normal file
126
jdk/src/solaris/classes/sun/nio/ch/SctpResultContainer.java
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
return sb.append(", Value: ").append(value.toString()).toString();
|
||||
}
|
||||
}
|
110
jdk/src/solaris/classes/sun/nio/ch/SctpSendFailed.java
Normal file
110
jdk/src/solaris/classes/sun/nio/ch/SctpSendFailed.java
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.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();
|
||||
}
|
||||
}
|
429
jdk/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java
Normal file
429
jdk/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
* 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.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.AlreadyBoundException;
|
||||
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.SctpStandardSocketOption;
|
||||
|
||||
/**
|
||||
* An implementation of SctpServerChannel
|
||||
*/
|
||||
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;
|
||||
|
||||
/* 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())
|
||||
throw new AlreadyBoundException();
|
||||
|
||||
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;
|
||||
|
||||
Net.listen(fd, 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)) {
|
||||
throw new AlreadyBoundException();
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
nd.preClose(fd);
|
||||
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) {
|
||||
nd.close(fd);
|
||||
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
|
||||
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(SctpStandardSocketOption.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 null;
|
||||
|
||||
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"));
|
||||
nd = new SctpSocketDispatcher();
|
||||
initIDs();
|
||||
}
|
||||
}
|
69
jdk/src/solaris/classes/sun/nio/ch/SctpShutdown.java
Normal file
69
jdk/src/solaris/classes/sun/nio/ch/SctpShutdown.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 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();
|
||||
}
|
||||
}
|
68
jdk/src/solaris/classes/sun/nio/ch/SctpSocketDispatcher.java
Normal file
68
jdk/src/solaris/classes/sun/nio/ch/SctpSocketDispatcher.java
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
329
jdk/src/solaris/native/sun/nio/ch/Sctp.h
Normal file
329
jdk/src/solaris/native/sun/nio/ch/Sctp.h
Normal file
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
#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;
|
||||
|
||||
jboolean loadSocketExtensionFuncs(JNIEnv* env);
|
||||
|
||||
#endif /* !SUN_NIO_CH_SCTP_H */
|
594
jdk/src/solaris/native/sun/nio/ch/SctpChannelImpl.c
Normal file
594
jdk/src/solaris/native/sun/nio/ch/SctpChannelImpl.c
Normal file
@ -0,0 +1,594 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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) {
|
||||
fprintf(stdout, "\nNative: handleSFN: recvmsg failed: errno = %d ", errno);
|
||||
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,
|
||||
sri->sinfo_stream, ssf->ssf_error, isaObj, bufferObj);
|
||||
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;JI)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_sun_nio_ch_SctpChannelImpl_receive0
|
||||
(JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj,
|
||||
jlong address, jint length) {
|
||||
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))];
|
||||
|
||||
/* 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, 0)) < 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, 0)) < 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);
|
||||
}
|
||||
|
609
jdk/src/solaris/native/sun/nio/ch/SctpNet.c
Normal file
609
jdk/src/solaris/native/sun/nio/ch/SctpNet.c
Normal file
@ -0,0 +1,609 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
funcsLoaded = JNI_TRUE;
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* Try to load the socket API extension functions */
|
||||
if (!funcsLoaded && !loadSocketExtensionFuncs(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = socket(ipv6_available() ? AF_INET6 : AF_INET,
|
||||
(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);
|
||||
}
|
||||
|
||||
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 (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;
|
||||
unsigned 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 (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;
|
||||
struct sockaddr_storage ss;
|
||||
int ss_len = sizeof(ss);
|
||||
unsigned int prim_len = sizeof(prim);
|
||||
|
||||
prim.ssp_assoc_id = assocId;
|
||||
prim.ssp_addr = ss;
|
||||
|
||||
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, (struct sockaddr*)&ss);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_storage ss;
|
||||
int ss_len = sizeof(ss);
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&ss,
|
||||
&ss_len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
prim.ssp_assoc_id = assocId;
|
||||
prim.ssp_addr = ss;
|
||||
|
||||
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) {
|
||||
struct sctp_setpeerprim prim;
|
||||
struct sockaddr_storage ss;
|
||||
int ss_len = sizeof(ss);
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&ss,
|
||||
&ss_len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
prim.sspp_assoc_id = assocId;
|
||||
prim.sspp_addr = ss;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
53
jdk/src/solaris/native/sun/nio/ch/SctpServerChannelImpl.c
Normal file
53
jdk/src/solaris/native/sun/nio/ch/SctpServerChannelImpl.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
150
jdk/src/windows/classes/sun/nio/ch/SctpChannelImpl.java
Normal file
150
jdk/src/windows/classes/sun/nio/ch/SctpChannelImpl.java
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import com.sun.nio.sctp.Association;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.NotificationHandler;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpSocketOption;
|
||||
|
||||
/**
|
||||
* Unimplemented.
|
||||
*/
|
||||
public class SctpChannelImpl extends SctpChannel
|
||||
{
|
||||
private static final String message = "SCTP not supported on this platform";
|
||||
|
||||
public SctpChannelImpl(SelectorProvider provider) {
|
||||
super(provider);
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association association() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel bind(SocketAddress local)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel bindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel unbindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connect(SocketAddress remote) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connect(SocketAddress remote, int maxOutStreams,
|
||||
int maxInStreams) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionPending() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishConnect() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getRemoteAddresses()
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel shutdown() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SctpSocketOption<T> name)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SctpChannel setOption(SctpSocketOption<T> name, T value)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SctpSocketOption<?>> supportedOptions() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> MessageInfo receive(ByteBuffer dst, T attachment,
|
||||
NotificationHandler<T> handler) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int send(ByteBuffer src, MessageInfo messageInfo)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implConfigureBlocking(boolean block) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
}
|
137
jdk/src/windows/classes/sun/nio/ch/SctpMultiChannelImpl.java
Normal file
137
jdk/src/windows/classes/sun/nio/ch/SctpMultiChannelImpl.java
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import com.sun.nio.sctp.Association;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.NotificationHandler;
|
||||
import com.sun.nio.sctp.SctpMultiChannel;
|
||||
import com.sun.nio.sctp.SctpSocketOption;
|
||||
|
||||
/**
|
||||
* Unimplemented.
|
||||
*/
|
||||
public class SctpMultiChannelImpl extends SctpMultiChannel
|
||||
{
|
||||
private static final String message = "SCTP not supported on this platform";
|
||||
|
||||
public SctpMultiChannelImpl(SelectorProvider provider) {
|
||||
super(provider);
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Association> associations() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpMultiChannel bind(SocketAddress local,
|
||||
int backlog) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpMultiChannel bindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpMultiChannel unbindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getRemoteAddresses
|
||||
(Association association) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpMultiChannel shutdown(Association association)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SctpSocketOption<T> name,
|
||||
Association association) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SctpMultiChannel setOption(SctpSocketOption<T> name,
|
||||
T value, Association association) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SctpSocketOption<?>> supportedOptions() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> MessageInfo receive(ByteBuffer buffer, T attachment,
|
||||
NotificationHandler<T> handler) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int send(ByteBuffer buffer, MessageInfo messageInfo)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel branch(Association association)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implConfigureBlocking(boolean block) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
}
|
102
jdk/src/windows/classes/sun/nio/ch/SctpServerChannelImpl.java
Normal file
102
jdk/src/windows/classes/sun/nio/ch/SctpServerChannelImpl.java
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import com.sun.nio.sctp.SctpSocketOption;
|
||||
|
||||
/**
|
||||
* Unimplemented.
|
||||
*/
|
||||
public class SctpServerChannelImpl extends SctpServerChannel
|
||||
{
|
||||
private static final String message = "SCTP not supported on this platform";
|
||||
|
||||
public SctpServerChannelImpl(SelectorProvider provider) {
|
||||
super(provider);
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpChannel accept() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpServerChannel bind(SocketAddress local,
|
||||
int backlog) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpServerChannel bindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SctpServerChannel unbindAddress(InetAddress address)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketAddress> getAllLocalAddresses()
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SctpSocketOption<T> name) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> SctpServerChannel setOption(SctpSocketOption<T> name,
|
||||
T value) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SctpSocketOption<?>> supportedOptions() {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implConfigureBlocking(boolean block) throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() throws IOException {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
}
|
148
jdk/test/com/sun/nio/sctp/MessageInfoTests.java
Normal file
148
jdk/test/com/sun/nio/sctp/MessageInfoTests.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import com.sun.nio.sctp.Association;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
|
||||
public class MessageInfoTests {
|
||||
static final int DEFAULT_STREAM_NUMBER = 14;
|
||||
static final int TEST_STREAM_NUMBER = 15;
|
||||
static final int TEST_PPID = 8;
|
||||
static final long TEST_TTL = 10000L;
|
||||
static final SocketAddress addr = new TestSocketAddress();
|
||||
static final Association assoc = new TestAssociation(1, 1, 1);
|
||||
|
||||
void test(String[] args) {
|
||||
/* TEST 1 : createOutGoing(SocketAddress,int) */
|
||||
MessageInfo info = MessageInfo.createOutgoing(addr,
|
||||
DEFAULT_STREAM_NUMBER);
|
||||
checkDefaults(info);
|
||||
checkGetterSetters(info);
|
||||
|
||||
/* TEST 2 : createOutGoing(Association,SocketAddress,int) */
|
||||
info = MessageInfo.createOutgoing(assoc, addr, DEFAULT_STREAM_NUMBER);
|
||||
checkDefaults(info);
|
||||
check(info.association().equals(assoc), "incorrect association");
|
||||
checkGetterSetters(info);
|
||||
|
||||
/* TEST 3: null values */
|
||||
info = MessageInfo.createOutgoing(null, 0);
|
||||
check(info.address() == null, "address should be null");
|
||||
check(info.association() == null, "association should be null");
|
||||
info = MessageInfo.createOutgoing(assoc, null, 0);
|
||||
check(info.address() == null, "address should be null");
|
||||
|
||||
/* Test 4: IllegalArgumentException */
|
||||
testIAE(new Runnable() {
|
||||
public void run() { MessageInfo.createOutgoing(addr, -1); } });
|
||||
testIAE(new Runnable() {
|
||||
public void run() { MessageInfo.createOutgoing(addr, 65537); } });
|
||||
testIAE(new Runnable() {
|
||||
public void run() { MessageInfo.createOutgoing(null, addr, 0); } });
|
||||
testIAE(new Runnable() {
|
||||
public void run() { MessageInfo.createOutgoing(assoc, addr, -1); } });
|
||||
testIAE(new Runnable() {
|
||||
public void run() { MessageInfo.createOutgoing(assoc, addr, 65537);}});
|
||||
|
||||
final MessageInfo iaeInfo = MessageInfo.createOutgoing(assoc, addr, 0);
|
||||
testIAE(new Runnable() {
|
||||
public void run() { iaeInfo.streamNumber(-1); } });
|
||||
testIAE(new Runnable() {
|
||||
public void run() { iaeInfo.streamNumber(65537); } });
|
||||
}
|
||||
|
||||
/* TEST : unordered = false, timeToLive = 0, complete = true,
|
||||
* payloadProtocolID = 0. */
|
||||
void checkDefaults(MessageInfo info) {
|
||||
check(info.isUnordered() == false, "default unordered value not false");
|
||||
check(info.timeToLive() == 0L, "timeToLive should be 0L");
|
||||
check(info.isComplete() == true, "default complete value not true");
|
||||
check(info.payloadProtocolID() == 0, "default PPID not 0");
|
||||
check(info.bytes() == 0, "default bytes value not 0");
|
||||
check(info.streamNumber() == DEFAULT_STREAM_NUMBER,
|
||||
"incorrect default stream number");
|
||||
check(info.address().equals(addr), "incorrect address");
|
||||
}
|
||||
|
||||
void checkGetterSetters(MessageInfo info) {
|
||||
check(info.streamNumber(TEST_STREAM_NUMBER).streamNumber() ==
|
||||
TEST_STREAM_NUMBER, "stream number not being set correctly");
|
||||
|
||||
check(info.complete(false).isComplete() == false,
|
||||
"complete not being set correctly");
|
||||
|
||||
check(info.unordered(true).isUnordered() == true,
|
||||
"unordered not being set correctly");
|
||||
|
||||
check(info.payloadProtocolID(TEST_PPID).payloadProtocolID() ==
|
||||
TEST_PPID, "PPID not being set correctly");
|
||||
|
||||
check(info.timeToLive(TEST_TTL).timeToLive() == TEST_TTL,
|
||||
"TTL not being set correctly");
|
||||
}
|
||||
|
||||
void testIAE(Runnable runnable) {
|
||||
try {
|
||||
runnable.run();
|
||||
fail("IllegalArgumentException should have been thrown");
|
||||
} catch(IllegalArgumentException iae) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
static class TestSocketAddress extends SocketAddress {}
|
||||
|
||||
static class TestAssociation extends Association {
|
||||
TestAssociation(int assocID, int maxInStreams, int maxOutStreams) {
|
||||
super(assocID, maxInStreams, maxOutStreams);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass();
|
||||
else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
350
jdk/test/com/sun/nio/sctp/SctpChannel/Bind.java
Normal file
350
jdk/test/com/sun/nio/sctp/SctpChannel/Bind.java
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import com.sun.nio.sctp.AssociationChangeNotification;
|
||||
import com.sun.nio.sctp.AbstractNotificationHandler;
|
||||
import com.sun.nio.sctp.HandlerResult;
|
||||
import com.sun.nio.sctp.IllegalUnbindException;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.PeerAddressChangeNotification;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import com.sun.nio.sctp.ShutdownNotification;
|
||||
import static java.lang.System.out;
|
||||
|
||||
/**
|
||||
* Tests bind, bindAddress, unbindAddress, getLocalAddress, and
|
||||
* getAllLocalAddresses.
|
||||
*/
|
||||
public class Bind {
|
||||
void test(String[] args) {
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Simply bind tests */
|
||||
testBind();
|
||||
|
||||
/* Test unconnected */
|
||||
testBindUnbind(false);
|
||||
|
||||
/* Test connected */
|
||||
/* Adding/Removing addresses from a connected association is optional.
|
||||
* This test can be run on systems that support dynamic address
|
||||
* reconfiguration */
|
||||
//testBindUnbind(true);
|
||||
}
|
||||
|
||||
void testBind() {
|
||||
SctpChannel channel = null;
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
|
||||
/* TEST 1: empty set if channel is not bound */
|
||||
check(channel.getAllLocalAddresses().isEmpty(),
|
||||
"getAllLocalAddresses returned non empty set for unbound channel");
|
||||
|
||||
/* TEST 2: null to bind the channel to an automatically assigned
|
||||
* socket address */
|
||||
channel.bind(null);
|
||||
|
||||
/* TEST 3: non empty set if the channel is bound */
|
||||
check(!channel.getAllLocalAddresses().isEmpty(),
|
||||
"getAllLocalAddresses returned empty set for bound channel");
|
||||
debug("getAllLocalAddresses on channel bound to the wildcard:\n"
|
||||
+ channel.getAllLocalAddresses());
|
||||
|
||||
/* TEST 4: AlreadyBoundException if this channel is already bound */
|
||||
try { channel.bind(null); }
|
||||
catch (AlreadyBoundException unused) { pass(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
|
||||
/* TEST 5: UnsupportedAddressTypeException */
|
||||
try {
|
||||
channel.close(); /* open a new unbound channel for test */
|
||||
channel = SctpChannel.open();
|
||||
channel.bind(new UnsupportedSocketAddress());
|
||||
fail("UnsupportedSocketAddress expected");
|
||||
} catch (UnsupportedAddressTypeException unused) { pass();
|
||||
} catch (IOException ioe) { unexpected(ioe); }
|
||||
|
||||
/* TEST 6: AlreadyConnectedException */
|
||||
try {
|
||||
channel.close(); /* open a new unbound channel for test */
|
||||
channel = SctpChannel.open();
|
||||
connectChannel(channel);
|
||||
channel.bind(null);
|
||||
fail("AlreadyConnectedException expected");
|
||||
} catch (AlreadyConnectedException unused) { pass();
|
||||
} catch (IOException ioe) { unexpected(ioe); }
|
||||
|
||||
/* TEST 7: ClosedChannelException - If this channel is closed */
|
||||
try {
|
||||
channel.close(); /* open a new unbound channel for test */
|
||||
channel = SctpChannel.open();
|
||||
channel.close();
|
||||
channel.bind(null);
|
||||
fail("ClosedChannelException expected");
|
||||
} catch (ClosedChannelException unused) { pass();
|
||||
} catch (IOException ioe) { unexpected(ioe); }
|
||||
|
||||
/* TEST 8: ClosedChannelException if channel is closed */
|
||||
try {
|
||||
channel.getAllLocalAddresses();
|
||||
fail("should have thrown ClosedChannelException");
|
||||
} catch (ClosedChannelException cce) {
|
||||
pass();
|
||||
} catch (Exception ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
try { channel.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
|
||||
void testBindUnbind(boolean connected) {
|
||||
SctpChannel channel = null;
|
||||
SctpChannel peerChannel = null;
|
||||
|
||||
debug("testBindUnbind, connected: " + connected);
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
|
||||
List<InetAddress> addresses = Util.getAddresses(true, false);
|
||||
Iterator iterator = addresses.iterator();
|
||||
InetSocketAddress a = new InetSocketAddress((InetAddress)iterator.next(), 0);
|
||||
debug("channel.bind( " + a + ")");
|
||||
channel.bind(a);
|
||||
while (iterator.hasNext()) {
|
||||
InetAddress ia = (InetAddress)iterator.next();
|
||||
debug("channel.bindAddress(" + ia + ")");
|
||||
channel.bindAddress(ia);
|
||||
}
|
||||
if (debug) {Util.dumpAddresses(channel, out);}
|
||||
|
||||
if (connected) {
|
||||
/* Test with connected channel */
|
||||
peerChannel = connectChannel(channel);
|
||||
}
|
||||
|
||||
/* TEST 1: bind/unbindAddresses on the system addresses */
|
||||
debug("bind/unbindAddresses on the system addresses");
|
||||
List<InetAddress> addrs = Util.getAddresses(true, false);
|
||||
for (InetAddress addr : addrs) {
|
||||
try {
|
||||
debug("unbindAddress: " + addr);
|
||||
check(boundAddress(channel, addr), "trying to remove address that is not bound");
|
||||
channel.unbindAddress(addr);
|
||||
if (debug) {Util.dumpAddresses(channel, out);}
|
||||
check(!boundAddress(channel, addr), "address was not removed");
|
||||
|
||||
debug("bindAddress: " + addr);
|
||||
channel.bindAddress(addr);
|
||||
if (debug) {Util.dumpAddresses(channel, out);}
|
||||
check(boundAddress(channel, addr), "address is not bound");
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/* TEST 2: bindAddress - already bound address. */
|
||||
InetAddress againAddress = addrs.get(0);
|
||||
try {
|
||||
debug("bind already bound address " + againAddress);
|
||||
channel.bindAddress(againAddress);
|
||||
} catch (AlreadyBoundException unused) {
|
||||
debug("Caught AlreadyBoundException - OK");
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 3: bind non local address */
|
||||
try {
|
||||
InetAddress nla = InetAddress.getByName("123.123.123.123");
|
||||
debug("bind non local address " + nla);
|
||||
channel.bindAddress(nla);
|
||||
} catch (IOException ioe) {
|
||||
debug("Informative only " + ioe);
|
||||
}
|
||||
|
||||
/* TEST 4: unbind address that is not bound */
|
||||
try {
|
||||
debug("unbind address that is not bound " + againAddress);
|
||||
/* remove address first then again */
|
||||
channel.unbindAddress(againAddress);
|
||||
channel.unbindAddress(againAddress);
|
||||
} catch (IllegalUnbindException unused) {
|
||||
debug("Caught IllegalUnbindException - OK");
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 5: unbind address that is not bound */
|
||||
try {
|
||||
InetAddress nla = InetAddress.getByName("123.123.123.123");
|
||||
debug("unbind address that is not bound " + nla);
|
||||
channel.unbindAddress(nla);
|
||||
|
||||
} catch (IllegalUnbindException unused) {
|
||||
debug("Caught IllegalUnbindException - OK");
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
if (connected) {
|
||||
channel.shutdown();
|
||||
|
||||
BindNotificationHandler handler = new BindNotificationHandler();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
MessageInfo info;
|
||||
while((info = peerChannel.receive(buffer, null, handler)) != null) {
|
||||
if (info != null) {
|
||||
if (info.bytes() == -1) {
|
||||
debug("peerChannel Reached EOF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while((info = channel.receive(buffer, null, handler)) != null) {
|
||||
if (info != null) {
|
||||
if (info.bytes() == -1) {
|
||||
debug("channel Reached EOF");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} finally {
|
||||
try { if (channel != null) channel.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
|
||||
boolean boundAddress(SctpChannel channel, InetAddress addr)
|
||||
throws IOException {
|
||||
for (SocketAddress boundAddr : channel.getAllLocalAddresses()) {
|
||||
if (((InetSocketAddress) boundAddr).getAddress().equals(addr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SctpChannel connectChannel(SctpChannel channel)
|
||||
throws IOException {
|
||||
debug("connecting channel...");
|
||||
try {
|
||||
SctpServerChannel ssc = SctpServerChannel.open();
|
||||
ssc.bind(null);
|
||||
Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
Iterator<SocketAddress> iterator = addrs.iterator();
|
||||
SocketAddress addr = iterator.next();
|
||||
debug("using " + addr + "...");
|
||||
channel.connect(addr);
|
||||
SctpChannel peerChannel = ssc.accept();
|
||||
ssc.close();
|
||||
debug("connected");
|
||||
return peerChannel;
|
||||
} catch (IOException ioe) {
|
||||
debug("Cannot connect channel");
|
||||
unexpected(ioe);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
class BindNotificationHandler extends AbstractNotificationHandler<Object>
|
||||
{
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
AssociationChangeNotification acn, Object unused)
|
||||
{
|
||||
debug("AssociationChangeNotification: " + acn);
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
PeerAddressChangeNotification pacn, Object unused)
|
||||
{
|
||||
debug("PeerAddressChangeNotification: " + pacn);
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
ShutdownNotification sn, Object unused)
|
||||
{
|
||||
debug("ShutdownNotification: " + sn);
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedSocketAddress extends SocketAddress { }
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
283
jdk/test/com/sun/nio/sctp/SctpChannel/Connect.java
Normal file
283
jdk/test/com/sun/nio/sctp/SctpChannel/Connect.java
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ConnectionPendingException;
|
||||
import java.nio.channels.NoConnectionPendingException;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
/**
|
||||
* Tests connect, finishConnect, isConnectionPending,
|
||||
* getRemoteAddresses and association.
|
||||
*/
|
||||
public class Connect {
|
||||
final CountDownLatch finishedLatch = new CountDownLatch(1);
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
Server server = null;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connect to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new Server();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doTest(address);
|
||||
}
|
||||
|
||||
void doTest(SocketAddress addr) {
|
||||
SctpChannel channel = null;
|
||||
final SocketAddress peerAddress = addr;
|
||||
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
|
||||
/* TEST 0.5 Verify default values for new/unconnected channel */
|
||||
check(channel.getRemoteAddresses().isEmpty(),
|
||||
"non empty set for unconnected channel");
|
||||
check(channel.association() == null,
|
||||
"non-null association for unconnected channel");
|
||||
check(!channel.isConnectionPending(),
|
||||
"should not have a connection pending");
|
||||
|
||||
/* TEST 1: non-blocking connect */
|
||||
channel.configureBlocking(false);
|
||||
if (channel.connect(peerAddress) != true) {
|
||||
debug("non-blocking connect did not immediately succeed");
|
||||
check(channel.isConnectionPending(),
|
||||
"should return true for isConnectionPending");
|
||||
try {
|
||||
channel.connect(peerAddress);
|
||||
fail("should have thrown ConnectionPendingException");
|
||||
} catch (ConnectionPendingException cpe) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
channel.configureBlocking(true);
|
||||
check(channel.finishConnect(),
|
||||
"finishConnect should have returned true");
|
||||
}
|
||||
|
||||
/* TEST 1.5 Verify after connect */
|
||||
check(!channel.getRemoteAddresses().isEmpty(),
|
||||
"empty set for connected channel");
|
||||
check(channel.association() != null,
|
||||
"null association for connected channel");
|
||||
check(!channel.isConnectionPending(),
|
||||
"pending connection for connected channel");
|
||||
|
||||
/* TEST 2: Verify AlreadyConnectedException thrown */
|
||||
try {
|
||||
channel.connect(peerAddress);
|
||||
fail("should have thrown AlreadyConnectedException");
|
||||
} catch (AlreadyConnectedException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 3: UnresolvedAddressException */
|
||||
channel.close();
|
||||
channel = SctpChannel.open();
|
||||
InetSocketAddress unresolved =
|
||||
InetSocketAddress.createUnresolved("xxyyzzabc", 4567);
|
||||
try {
|
||||
channel.connect(unresolved);
|
||||
fail("should have thrown UnresolvedAddressException");
|
||||
} catch (UnresolvedAddressException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 4: UnsupportedAddressTypeException */
|
||||
SocketAddress unsupported = new UnsupportedSocketAddress();
|
||||
try {
|
||||
channel.connect(unsupported);
|
||||
fail("should have thrown UnsupportedAddressTypeException");
|
||||
} catch (UnsupportedAddressTypeException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 5: ClosedChannelException */
|
||||
channel.close();
|
||||
final SctpChannel closedChannel = channel;
|
||||
testCCE(new Callable<Void>() {
|
||||
public Void call() throws IOException {
|
||||
closedChannel.connect(peerAddress); return null; } });
|
||||
|
||||
/* TEST 5.5 getRemoteAddresses */
|
||||
testCCE(new Callable<Void>() {
|
||||
public Void call() throws IOException {
|
||||
closedChannel.getRemoteAddresses(); return null; } });
|
||||
testCCE(new Callable<Void>() {
|
||||
public Void call() throws IOException {
|
||||
closedChannel.association(); return null; } });
|
||||
check(!channel.isConnectionPending(),
|
||||
"pending connection for closed channel");
|
||||
|
||||
/* Run some more finishConnect tests */
|
||||
|
||||
/* TEST 6: NoConnectionPendingException */
|
||||
channel = SctpChannel.open();
|
||||
try {
|
||||
channel.finishConnect();
|
||||
fail("should have thrown NoConnectionPendingException");
|
||||
} catch (NoConnectionPendingException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 7: ClosedChannelException */
|
||||
channel.close();
|
||||
final SctpChannel cceChannel = channel;
|
||||
testCCE(new Callable<Void>() {
|
||||
public Void call() throws IOException {
|
||||
cceChannel.finishConnect(); return null; } });
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
finishedLatch.countDown();
|
||||
try { if (channel != null) channel.close(); }
|
||||
catch (IOException e) { unexpected(e);}
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedSocketAddress extends SocketAddress { }
|
||||
|
||||
void testCCE(Callable callable) {
|
||||
try {
|
||||
callable.call();
|
||||
fail("should have thrown ClosedChannelException");
|
||||
} catch (ClosedChannelException cce) {
|
||||
pass();
|
||||
} catch (Exception ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
class Server implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
|
||||
public Server() throws IOException {
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
(new Thread(this, "Server-" + serverAddr.getPort())).start();
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
SctpChannel sc = null;
|
||||
try {
|
||||
sc = ssc.accept();
|
||||
finishedLatch.await();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
} finally {
|
||||
try { if (ssc != null) ssc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
try { if (sc != null) sc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
361
jdk/test/com/sun/nio/sctp/SctpChannel/Receive.java
Normal file
361
jdk/test/com/sun/nio/sctp/SctpChannel/Receive.java
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import com.sun.nio.sctp.AbstractNotificationHandler;
|
||||
import com.sun.nio.sctp.AssociationChangeNotification;
|
||||
import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
|
||||
import com.sun.nio.sctp.HandlerResult;
|
||||
import com.sun.nio.sctp.IllegalReceiveException;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.Notification;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import com.sun.nio.sctp.ShutdownNotification;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class Receive {
|
||||
/* Latches used to synchronize between the client and server so that
|
||||
* connections without any IO may not be closed without being accepted */
|
||||
final CountDownLatch clientFinishedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch serverFinishedLatch = new CountDownLatch(1);
|
||||
|
||||
/* Used to verify that the ppid is being sent and received correctly */
|
||||
static final int PPID = 5;
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
Server server;
|
||||
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new Server();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doTest(address);
|
||||
}
|
||||
|
||||
void doTest(SocketAddress peerAddress) {
|
||||
SctpChannel channel = null;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);
|
||||
MessageInfo info;
|
||||
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
ReceiveNotificationHandler handler =
|
||||
new ReceiveNotificationHandler(channel);
|
||||
|
||||
/* TEST 1: Verify NotYetConnectedException thrown */
|
||||
try {
|
||||
channel.receive(buffer, null, handler);
|
||||
fail("should have thrown NotYetConnectedException");
|
||||
} catch (NotYetConnectedException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
channel.connect(peerAddress);
|
||||
|
||||
/* TEST 2: receive small message */
|
||||
do {
|
||||
debug("Test 2: invoking receive");
|
||||
info = channel.receive(buffer, null, handler);
|
||||
if (info == null) {
|
||||
fail("unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(handler.receivedCommUp(), "SCTP_COMM_UP not received");
|
||||
check(info != null, "info is null");
|
||||
check(info.address() != null, "address is null");
|
||||
check(info.association() != null, "association is null");
|
||||
check(info.isComplete(), "message is not complete");
|
||||
check(info.isUnordered() != true,
|
||||
"message should not be unordered");
|
||||
check(info.streamNumber() >= 0, "invalid stream number");
|
||||
check(info.payloadProtocolID() == PPID, "PPID incorrect");
|
||||
check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.SMALL_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
buffer.clear();
|
||||
|
||||
/* TEST 3: receive large message */
|
||||
do {
|
||||
debug("Test 3: invoking receive");
|
||||
info = channel.receive(buffer, null, handler);
|
||||
if (info == null) {
|
||||
fail("unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.address() != null, "address is null");
|
||||
check(info.association() != null, "association is null");
|
||||
check(info.isComplete(), "message is not complete");
|
||||
check(info.isUnordered() != true,
|
||||
"message should not be unordered");
|
||||
check(info.streamNumber() >= 0, "invalid stream number");
|
||||
check(info.bytes() == Util.LARGE_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.LARGE_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
buffer.clear();
|
||||
|
||||
/* TEST 4: EOF */
|
||||
buffer.clear(); // buffer position 0
|
||||
info = channel.receive(buffer,null, handler);
|
||||
check(info != null, "info is null");
|
||||
check(info.bytes() == -1, "should have received EOF");
|
||||
check(buffer.position() == 0, "buffer position should be unchanged");
|
||||
|
||||
/* TEST 5: ClosedChannelException */
|
||||
channel.close();
|
||||
try {
|
||||
channel.receive(buffer, null, null);
|
||||
fail("should have thrown ClosedChannelException");
|
||||
} catch (ClosedChannelException cce) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
handler = null;
|
||||
|
||||
/* TEST 6: handler returns RETURN after handling a notification */
|
||||
ReceiveNotificationHandler handler2 =
|
||||
new ReceiveNotificationHandler(null); /* HandlerResult.RETURN */
|
||||
channel = SctpChannel.open(peerAddress, 0, 0);
|
||||
info = channel.receive(buffer, null, handler2);
|
||||
check(info == null, "channel should return null");
|
||||
check(handler2.receivedCommUp(), "SCTP_COMM_UP not received");
|
||||
check(buffer.position() == 0, "buffer position should be unchanged");
|
||||
|
||||
/* TEST 7: Non blocking channel return null if no data */
|
||||
channel.configureBlocking(false);
|
||||
info = channel.receive(buffer, null, null);
|
||||
check(info == null, "non-blocking channel should return null");
|
||||
check(buffer.position() == 0, "buffer position should be unchanged");
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
clientFinishedLatch.countDown();
|
||||
try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }
|
||||
catch (InterruptedException ie) { unexpected(ie); }
|
||||
if (channel != null) {
|
||||
try { channel.close(); }
|
||||
catch (IOException e) { unexpected (e);}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Server implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
|
||||
public Server() throws IOException {
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
(new Thread(this, "Server-" + serverAddr.getPort())).start();
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
SctpChannel sc = ssc.accept();
|
||||
|
||||
/* send a small message */
|
||||
MessageInfo info = MessageInfo.createOutgoing(null, 0)
|
||||
.payloadProtocolID(PPID);
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(Util.SMALL_BUFFER);
|
||||
buf.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buf.flip();
|
||||
|
||||
debug("sending small message: " + buf);
|
||||
sc.send(buf, info);
|
||||
|
||||
/* send a large message */
|
||||
buf = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);
|
||||
buf.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buf.flip();
|
||||
|
||||
debug("sending large message: " + buf);
|
||||
sc.send(buf, info);
|
||||
sc.shutdown();
|
||||
debug("shutdown");
|
||||
ReceiveNotificationHandler handler =
|
||||
new ReceiveNotificationHandler(sc);
|
||||
sc.receive(buf, null, handler);
|
||||
sc.close();
|
||||
|
||||
/* accept another socket for the TEST 6 */
|
||||
sc = ssc.accept();
|
||||
ssc.close();
|
||||
|
||||
clientFinishedLatch.await(10L, TimeUnit.SECONDS);
|
||||
serverFinishedLatch.countDown();
|
||||
sc.close();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReceiveNotificationHandler extends AbstractNotificationHandler<Object>
|
||||
{
|
||||
SctpChannel channel;
|
||||
boolean receivedCommUp; // false
|
||||
|
||||
public ReceiveNotificationHandler(SctpChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public boolean receivedCommUp() {
|
||||
return receivedCommUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
Notification notification, Object attachment) {
|
||||
fail("Unknown notification type");
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
AssociationChangeNotification notification, Object attachment) {
|
||||
AssocChangeEvent event = notification.event();
|
||||
debug("AssociationChangeNotification");
|
||||
debug(" Association: " + notification.association());
|
||||
debug(" Event: " + event);
|
||||
|
||||
if (event.equals(AssocChangeEvent.COMM_UP))
|
||||
receivedCommUp = true;
|
||||
|
||||
if (channel == null)
|
||||
return HandlerResult.RETURN;
|
||||
|
||||
/* TEST 4: IllegalReceiveException - If the given handler invokes
|
||||
* the receive method of this channel*/
|
||||
ByteBuffer buffer = ByteBuffer.allocate(10);
|
||||
try {
|
||||
channel.receive(buffer, null, this);
|
||||
fail("IllegalReceiveException expected");
|
||||
} catch (IllegalReceiveException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
ShutdownNotification notification, Object attachment) {
|
||||
debug("ShutdownNotification");
|
||||
debug(" Association: " + notification.association());
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) {
|
||||
System.out.println(Thread.currentThread() + " " + message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
419
jdk/test/com/sun/nio/sctp/SctpChannel/Send.java
Normal file
419
jdk/test/com/sun/nio/sctp/SctpChannel/Send.java
Normal file
@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import com.sun.nio.sctp.AbstractNotificationHandler;
|
||||
import com.sun.nio.sctp.Association;
|
||||
import com.sun.nio.sctp.AssociationChangeNotification;
|
||||
import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;
|
||||
import com.sun.nio.sctp.HandlerResult;
|
||||
import com.sun.nio.sctp.InvalidStreamException;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.Notification;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class Send {
|
||||
/* Latches used to synchronize between the client and server so that
|
||||
* connections without any IO may not be closed without being accepted */
|
||||
final CountDownLatch clientFinishedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch serverFinishedLatch = new CountDownLatch(1);
|
||||
|
||||
SendNotificationHandler handler = new SendNotificationHandler();
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
Server server = null;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new Server();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doTest(address);
|
||||
}
|
||||
|
||||
void doTest(SocketAddress peerAddress) {
|
||||
SctpChannel channel = null;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);
|
||||
MessageInfo info = MessageInfo.createOutgoing(null, 0);
|
||||
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
|
||||
/* TEST 1: Verify NotYetConnectedException thrown */
|
||||
try {
|
||||
channel.send(buffer, info);
|
||||
fail("should have thrown NotYetConnectedException");
|
||||
} catch (NotYetConnectedException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
channel.connect(peerAddress);
|
||||
/* Receive CommUp */
|
||||
channel.receive(buffer, null, handler);
|
||||
|
||||
/* save for TEST 8 */
|
||||
Association association = channel.association();
|
||||
|
||||
/* TEST 2: send small message */
|
||||
int streamNumber = 0;
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
info = MessageInfo.createOutgoing(null, streamNumber);
|
||||
buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
int position = buffer.position();
|
||||
int remaining = buffer.remaining();
|
||||
|
||||
debug("sending small message: " + buffer);
|
||||
int sent = channel.send(buffer, info);
|
||||
|
||||
check(sent == remaining, "sent should be equal to remaining");
|
||||
check(buffer.position() == (position + sent),
|
||||
"buffers position should have been incremented by sent");
|
||||
|
||||
buffer.clear();
|
||||
|
||||
/* TEST 3: send large message */
|
||||
streamNumber = handler.maxOutStreams() - 1;
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
info = MessageInfo.createOutgoing(null, streamNumber);
|
||||
buffer.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
|
||||
debug("sending large message: " + buffer);
|
||||
sent = channel.send(buffer, info);
|
||||
|
||||
check(sent == remaining, "sent should be equal to remaining");
|
||||
check(buffer.position() == (position + sent),
|
||||
"buffers position should have been incremented by sent");
|
||||
|
||||
/* TEST 4: InvalidStreamExcepton */
|
||||
streamNumber = handler.maxInStreams;
|
||||
info = MessageInfo.createOutgoing(null, streamNumber);
|
||||
buffer.clear();
|
||||
buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
debug("sending small message: " + buffer);
|
||||
try {
|
||||
sent = channel.send(buffer, info);
|
||||
fail("should have thrown InvalidStreamExcepton");
|
||||
} catch (InvalidStreamException ise){
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
check(buffer.remaining() == remaining,
|
||||
"remaining should not be changed");
|
||||
check(buffer.position() == position,
|
||||
"buffers position should not be changed");
|
||||
|
||||
/* TEST 5: Non blocking send should return zero if there is
|
||||
insufficient room in the underlying output buffer */
|
||||
buffer.clear();
|
||||
channel.configureBlocking(false);
|
||||
info = MessageInfo.createOutgoing(null, 1);
|
||||
buffer.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
|
||||
int count = 0; // do not loop forever
|
||||
do {
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
debug("sending large message: " + buffer);
|
||||
sent = channel.send(buffer, info);
|
||||
if (sent == 0) {
|
||||
check(buffer.remaining() == remaining,
|
||||
"remaining should not be changed");
|
||||
check(buffer.position() == position,
|
||||
"buffers position should not be changed");
|
||||
}
|
||||
buffer.rewind();
|
||||
} while (sent != 0 && count++ < 100);
|
||||
|
||||
/* TEST 6: ClosedChannelException */
|
||||
channel.close();
|
||||
try {
|
||||
channel.send(buffer, info);
|
||||
fail("should have thrown ClosedChannelException");
|
||||
} catch (ClosedChannelException cce) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 7: send without previous receive.
|
||||
* Verify that send can still throw InvalidStreamExcepton */
|
||||
debug("Opening new channel.");
|
||||
channel = SctpChannel.open(peerAddress, 0, 0);
|
||||
streamNumber = Short.MAX_VALUE - 1;
|
||||
info = MessageInfo.createOutgoing(null, streamNumber);
|
||||
buffer.clear();
|
||||
buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
debug("sending small message: " + buffer);
|
||||
try {
|
||||
sent = channel.send(buffer, info);
|
||||
fail("should have thrown InvalidStreamExcepton");
|
||||
} catch (InvalidStreamException ise){
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
check(buffer.remaining() == remaining,
|
||||
"remaining should not be changed");
|
||||
check(buffer.position() == position,
|
||||
"buffers position should not be changed");
|
||||
|
||||
/* Receive CommUp */
|
||||
channel.receive(buffer, null, handler);
|
||||
check(handler.receivedCommUp(), "should have received COMM_UP");
|
||||
|
||||
/* TEST 8: Send to an invalid preferred SocketAddress */
|
||||
SocketAddress addr = new InetSocketAddress("123.123.123.123", 3456);
|
||||
info = MessageInfo.createOutgoing(addr, 0);
|
||||
debug("sending to " + addr);
|
||||
debug("sending small message: " + buffer);
|
||||
try {
|
||||
sent = channel.send(buffer, info);
|
||||
fail("Invalid address should have thrown an Exception.");
|
||||
} catch (Exception e){
|
||||
pass();
|
||||
debug("OK, caught " + e);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
clientFinishedLatch.countDown();
|
||||
try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }
|
||||
catch (InterruptedException ie) { unexpected(ie); }
|
||||
if (channel != null) {
|
||||
try { channel.close(); }
|
||||
catch (IOException e) { unexpected (e);}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Server implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
|
||||
public Server() throws IOException {
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
(new Thread(this, "Server-" + serverAddr.getPort())).start();
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);
|
||||
SctpChannel sc1 = null, sc2 = null;
|
||||
try {
|
||||
sc1 = ssc.accept();
|
||||
|
||||
/* receive a small message */
|
||||
MessageInfo info;
|
||||
do {
|
||||
info = sc1.receive(buffer, null, null);
|
||||
if (info == null) {
|
||||
fail("Server: unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.streamNumber() == 0,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.SMALL_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
/* receive a large message */
|
||||
buffer.clear();
|
||||
do {
|
||||
info = sc1.receive(buffer, null, null);
|
||||
if (info == null) {
|
||||
fail("Server: unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.streamNumber() == handler.maxOutStreams() - 1,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.LARGE_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.LARGE_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
/* TEST 7 ++ */
|
||||
sc2 = ssc.accept();
|
||||
|
||||
clientFinishedLatch.await(10L, TimeUnit.SECONDS);
|
||||
serverFinishedLatch.countDown();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
} finally {
|
||||
try { if (ssc != null) ssc.close(); }
|
||||
catch (IOException unused) {}
|
||||
try { if (sc1 != null) sc1.close(); }
|
||||
catch (IOException unused) {}
|
||||
try { if (sc2 != null) sc2.close(); }
|
||||
catch (IOException unused) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SendNotificationHandler extends AbstractNotificationHandler<Void>
|
||||
{
|
||||
boolean receivedCommUp; // false
|
||||
int maxInStreams;
|
||||
int maxOutStreams;
|
||||
|
||||
public boolean receivedCommUp() {
|
||||
return receivedCommUp;
|
||||
}
|
||||
|
||||
public int maxInStreams() {
|
||||
return maxInStreams;
|
||||
}
|
||||
|
||||
public int maxOutStreams(){
|
||||
return maxOutStreams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
Notification notification, Void attachment) {
|
||||
fail("Unknown notification type");
|
||||
return HandlerResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
AssociationChangeNotification notification, Void attachment) {
|
||||
AssocChangeEvent event = notification.event();
|
||||
Association association = notification.association();
|
||||
debug("AssociationChangeNotification");
|
||||
debug(" Association: " + notification.association());
|
||||
debug(" Event: " + event);
|
||||
|
||||
if (event.equals(AssocChangeEvent.COMM_UP))
|
||||
receivedCommUp = true;
|
||||
|
||||
this.maxInStreams = association.maxInboundStreams();
|
||||
this.maxOutStreams = association.maxOutboundStreams();
|
||||
|
||||
return HandlerResult.RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
274
jdk/test/com/sun/nio/sctp/SctpChannel/Shutdown.java
Normal file
274
jdk/test/com/sun/nio/sctp/SctpChannel/Shutdown.java
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import com.sun.nio.sctp.AbstractNotificationHandler;
|
||||
import com.sun.nio.sctp.HandlerResult;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import com.sun.nio.sctp.ShutdownNotification;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class Shutdown {
|
||||
static CountDownLatch finishedLatch = new CountDownLatch(1);
|
||||
static CountDownLatch sentLatch = new CountDownLatch(1);
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
ShutdownServer server = null;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new ShutdownServer();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doTest(address);
|
||||
}
|
||||
|
||||
void doTest(SocketAddress peerAddress) {
|
||||
SctpChannel channel = null;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Util.SMALL_BUFFER);
|
||||
MessageInfo info;
|
||||
|
||||
try {
|
||||
channel = SctpChannel.open();
|
||||
|
||||
/* TEST 1: Verify NotYetConnectedException thrown */
|
||||
debug("Test 1: NotYetConnectedException");
|
||||
try {
|
||||
channel.shutdown();
|
||||
fail("shutdown not throwing expected NotYetConnectedException");
|
||||
} catch (NotYetConnectedException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
channel.connect(peerAddress);
|
||||
sentLatch.await();
|
||||
channel.shutdown();
|
||||
|
||||
/* TEST 2: receive data sent before shutdown */
|
||||
do {
|
||||
debug("Test 2: invoking receive");
|
||||
info = channel.receive(buffer, null, null);
|
||||
if (info == null) {
|
||||
fail("unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.SMALL_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
buffer.clear();
|
||||
|
||||
/* TEST 3: receive notifications on the SCTP stack */
|
||||
debug("Test 3: receive notifications");
|
||||
while ((info = channel.receive(buffer, null, null )) != null &&
|
||||
info.bytes() != -1 );
|
||||
|
||||
|
||||
/* TEST 4: If the channel is already shutdown then invoking this
|
||||
* method has no effect. */
|
||||
debug("Test 4: no-op");
|
||||
try {
|
||||
channel.shutdown();
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
/* TEST 5: Further sends will throw ClosedChannelException */
|
||||
debug("Test 5: ClosedChannelException");
|
||||
info = MessageInfo.createOutgoing(null, 1);
|
||||
try {
|
||||
channel.send(buffer, info);
|
||||
fail("shutdown not throwing expected ClosedChannelException");
|
||||
} catch (ClosedChannelException unused) {
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
}finally {
|
||||
finishedLatch.countDown();
|
||||
try { if (channel != null) channel.close(); }
|
||||
catch (IOException e) { unexpected(e);}
|
||||
}
|
||||
}
|
||||
|
||||
class ShutdownServer implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
|
||||
public ShutdownServer() throws IOException {
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
//serverAddr = (InetSocketAddress)(ssc.getAllLocalAddresses().iterator().next());
|
||||
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
|
||||
}
|
||||
|
||||
public void start() {
|
||||
(new Thread(this, "ShutdownServer-" + serverAddr.getPort())).start();
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
SctpChannel sc = null;
|
||||
try {
|
||||
sc = ssc.accept();
|
||||
|
||||
/* send a message */
|
||||
MessageInfo info = MessageInfo.createOutgoing(null, 1);
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(Util.SMALL_BUFFER);
|
||||
buf.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buf.flip();
|
||||
sc.send(buf, info);
|
||||
|
||||
/* notify client that the data has been sent */
|
||||
sentLatch.countDown();
|
||||
|
||||
/* wait until after the client has finished its tests */
|
||||
finishedLatch.await();
|
||||
|
||||
buf.clear();
|
||||
ShutdownNotificationHandler handler =
|
||||
new ShutdownNotificationHandler();
|
||||
BooleanWrapper bool = new BooleanWrapper();
|
||||
sc.configureBlocking(false);
|
||||
sc.receive(buf, bool, handler);
|
||||
check(bool.booleanValue(), "SHUTDOWN not received on Server");
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
} finally {
|
||||
try { if (ssc != null) ssc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
try { if (sc != null) sc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BooleanWrapper {
|
||||
boolean bool;
|
||||
|
||||
boolean booleanValue() {
|
||||
return bool;
|
||||
}
|
||||
|
||||
void booleanValue(boolean value) {
|
||||
bool = value;
|
||||
}
|
||||
}
|
||||
|
||||
class ShutdownNotificationHandler extends AbstractNotificationHandler<BooleanWrapper>
|
||||
{
|
||||
@Override
|
||||
public HandlerResult handleNotification(
|
||||
ShutdownNotification sn, BooleanWrapper bool)
|
||||
{
|
||||
bool.booleanValue(true);
|
||||
debug(sn.toString());
|
||||
return HandlerResult.RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
157
jdk/test/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java
Normal file
157
jdk/test/com/sun/nio/sctp/SctpChannel/SocketOptionTests.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpSocketOption;
|
||||
import static com.sun.nio.sctp.SctpStandardSocketOption.*;
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class SocketOptionTests {
|
||||
<T> void checkOption(SctpChannel sc, SctpSocketOption<T> name,
|
||||
T expectedValue) throws IOException {
|
||||
T value = sc.getOption(name);
|
||||
check(value.equals(expectedValue), name + ": value (" + value +
|
||||
") not as expected (" + expectedValue + ")");
|
||||
}
|
||||
|
||||
<T> void optionalSupport(SctpChannel sc, SctpSocketOption<T> name,
|
||||
T value) {
|
||||
try {
|
||||
sc.setOption(name, value);
|
||||
checkOption(sc, name, value);
|
||||
} catch (IOException e) {
|
||||
/* Informational only, not all options have native support */
|
||||
out.println(name + " not supported. " + e);
|
||||
}
|
||||
}
|
||||
|
||||
void test(String[] args) {
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SctpChannel sc = SctpChannel.open();
|
||||
|
||||
/* check supported options */
|
||||
Set<SctpSocketOption<?>> options = sc.supportedOptions();
|
||||
List<? extends SctpSocketOption<?>> expected = Arrays.<SctpSocketOption<?>>asList(
|
||||
SCTP_DISABLE_FRAGMENTS, SCTP_EXPLICIT_COMPLETE,
|
||||
SCTP_FRAGMENT_INTERLEAVE, SCTP_INIT_MAXSTREAMS,
|
||||
SCTP_NODELAY, SCTP_PRIMARY_ADDR, SCTP_SET_PEER_PRIMARY_ADDR,
|
||||
SO_SNDBUF, SO_RCVBUF, SO_LINGER);
|
||||
|
||||
for (SctpSocketOption opt: expected) {
|
||||
if (!options.contains(opt))
|
||||
fail(opt.name() + " should be supported");
|
||||
}
|
||||
|
||||
InitMaxStreams streams = InitMaxStreams.create(1024, 1024);
|
||||
sc.setOption(SCTP_INIT_MAXSTREAMS, streams);
|
||||
checkOption(sc, SCTP_INIT_MAXSTREAMS, streams);
|
||||
streams = sc.getOption(SCTP_INIT_MAXSTREAMS);
|
||||
check(streams.maxInStreams() == 1024, "Max in streams: value: "
|
||||
+ streams.maxInStreams() + ", expected 1024 ");
|
||||
check(streams.maxOutStreams() == 1024, "Max out streams: value: "
|
||||
+ streams.maxOutStreams() + ", expected 1024 ");
|
||||
|
||||
optionalSupport(sc, SCTP_DISABLE_FRAGMENTS, true);
|
||||
optionalSupport(sc, SCTP_EXPLICIT_COMPLETE, true);
|
||||
optionalSupport(sc, SCTP_FRAGMENT_INTERLEAVE, 1);
|
||||
|
||||
|
||||
//TODO: SCTP_PRIMARY_ADDR
|
||||
//sc.bind(null);
|
||||
//connect
|
||||
//InetSocketAddress addr = new InetSocketAddress(0);
|
||||
//sc.setOption(SCTP_PRIMARY_ADDR, addr);
|
||||
|
||||
sc.setOption(SCTP_NODELAY, true);
|
||||
checkOption(sc, SCTP_NODELAY, true);
|
||||
sc.setOption(SO_SNDBUF, 16*1024);
|
||||
sc.setOption(SO_RCVBUF, 16*1024);
|
||||
checkOption(sc, SO_LINGER, -1); /* default should be negative */
|
||||
sc.setOption(SO_LINGER, 2000);
|
||||
checkOption(sc, SO_LINGER, 2000);
|
||||
|
||||
|
||||
/* NullPointerException */
|
||||
try {
|
||||
sc.setOption(null, "value");
|
||||
fail("NullPointerException not thrown for setOption");
|
||||
} catch (NullPointerException unused) {
|
||||
pass();
|
||||
}
|
||||
try {
|
||||
sc.getOption(null);
|
||||
fail("NullPointerException not thrown for getOption");
|
||||
} catch (NullPointerException unused) {
|
||||
pass();
|
||||
}
|
||||
|
||||
/* ClosedChannelException */
|
||||
sc.close();
|
||||
try {
|
||||
sc.setOption(SCTP_INIT_MAXSTREAMS, streams);
|
||||
fail("ClosedChannelException not thrown");
|
||||
} catch (ClosedChannelException unused) {
|
||||
pass();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
}
|
138
jdk/test/com/sun/nio/sctp/SctpChannel/Util.java
Normal file
138
jdk/test/com/sun/nio/sctp/SctpChannel/Util.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.SocketException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class Util {
|
||||
static final int SMALL_BUFFER = 128;
|
||||
static final String SMALL_MESSAGE =
|
||||
"Under the bridge and over the dam, looking for berries, berries for jam";
|
||||
|
||||
static final int LARGE_BUFFER = 32768;
|
||||
static final String LARGE_MESSAGE;
|
||||
|
||||
static {
|
||||
StringBuffer sb = new StringBuffer(LARGE_BUFFER);
|
||||
for (int i=0; i<460; i++)
|
||||
sb.append(SMALL_MESSAGE);
|
||||
|
||||
LARGE_MESSAGE = sb.toString();
|
||||
}
|
||||
|
||||
static boolean isSCTPSupported() {
|
||||
try {
|
||||
SctpChannel c = SctpChannel.open();
|
||||
c.close();
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
out.println(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a list of all the addresses on the system.
|
||||
* @param inclLoopback
|
||||
* if {@code true}, include the loopback addresses
|
||||
* @param ipv4Only
|
||||
* it {@code true}, only IPv4 addresses will be included
|
||||
*/
|
||||
static List<InetAddress> getAddresses(boolean inclLoopback,
|
||||
boolean ipv4Only)
|
||||
throws SocketException {
|
||||
ArrayList<InetAddress> list = new ArrayList<InetAddress>();
|
||||
Enumeration<NetworkInterface> nets =
|
||||
NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface netInf : Collections.list(nets)) {
|
||||
Enumeration<InetAddress> addrs = netInf.getInetAddresses();
|
||||
for (InetAddress addr : Collections.list(addrs)) {
|
||||
if (!list.contains(addr) &&
|
||||
(inclLoopback ? true : !addr.isLoopbackAddress()) &&
|
||||
(ipv4Only ? (addr instanceof Inet4Address) : true)) {
|
||||
list.add(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void dumpAddresses(SctpChannel channel,
|
||||
PrintStream printStream)
|
||||
throws IOException {
|
||||
Set<SocketAddress> addrs = channel.getAllLocalAddresses();
|
||||
printStream.println("Local Addresses: ");
|
||||
for (Iterator<SocketAddress> it = addrs.iterator(); it.hasNext(); ) {
|
||||
InetSocketAddress addr = (InetSocketAddress)it.next();
|
||||
printStream.println("\t" + addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the contents of the given ByteBuffer with the contens of the
|
||||
* given byte array. true if, and only if, the contents are the same.
|
||||
*/
|
||||
static boolean compare(ByteBuffer bb, byte[] message) {
|
||||
if (message.length != bb.remaining()) {
|
||||
out.println("Compare failed, byte array length != to buffer remaining");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<message.length; i++) {
|
||||
byte b = bb.get();
|
||||
if (message[i] != b) {
|
||||
out.println("Position " + i + ": " + message[i] + " != " + b);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean compare(ByteBuffer bb, String str) {
|
||||
try{
|
||||
return Util.compare(bb, str.getBytes("ISO-8859-1"));
|
||||
} catch (UnsupportedEncodingException unsupported) {
|
||||
throw new AssertionError(unsupported);
|
||||
}
|
||||
}
|
||||
}
|
320
jdk/test/com/sun/nio/sctp/SctpMultiChannel/Send.java
Normal file
320
jdk/test/com/sun/nio/sctp/SctpMultiChannel/Send.java
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.nio.ByteBuffer;
|
||||
import com.sun.nio.sctp.Association;
|
||||
import com.sun.nio.sctp.InvalidStreamException;
|
||||
import com.sun.nio.sctp.MessageInfo;
|
||||
import com.sun.nio.sctp.SctpMultiChannel;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class Send {
|
||||
/* Latches used to synchronize between the client and server so that
|
||||
* connections without any IO may not be closed without being accepted */
|
||||
final CountDownLatch clientFinishedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch serverFinishedLatch = new CountDownLatch(1);
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
Server server = null;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new Server();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doTest(address);
|
||||
}
|
||||
|
||||
void doTest(SocketAddress peerAddress) {
|
||||
SctpMultiChannel channel = null;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);
|
||||
MessageInfo info = MessageInfo.createOutgoing(null, 0);
|
||||
|
||||
try {
|
||||
channel = SctpMultiChannel.open();
|
||||
|
||||
/* TEST 1: send small message */
|
||||
int streamNumber = 0;
|
||||
debug("sending to " + peerAddress + " on stream number: " + streamNumber);
|
||||
info = MessageInfo.createOutgoing(peerAddress, streamNumber);
|
||||
buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
int position = buffer.position();
|
||||
int remaining = buffer.remaining();
|
||||
|
||||
debug("sending small message: " + buffer);
|
||||
int sent = channel.send(buffer, info);
|
||||
|
||||
check(sent == remaining, "sent should be equal to remaining");
|
||||
check(buffer.position() == (position + sent),
|
||||
"buffers position should have been incremented by sent");
|
||||
|
||||
/* TEST 2: receive the echoed message */
|
||||
buffer.clear();
|
||||
info = channel.receive(buffer, null, null);
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.streamNumber() == streamNumber,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.SMALL_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
|
||||
/* TEST 3: send large message */
|
||||
Set<Association> assocs = channel.associations();
|
||||
check(assocs.size() == 1, "there should be only one association");
|
||||
Iterator<Association> it = assocs.iterator();
|
||||
check(it.hasNext());
|
||||
Association assoc = it.next();
|
||||
streamNumber = assoc.maxOutboundStreams() - 1;
|
||||
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
info = MessageInfo.createOutgoing(assoc, null, streamNumber);
|
||||
buffer.clear();
|
||||
buffer.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
|
||||
debug("sending large message: " + buffer);
|
||||
sent = channel.send(buffer, info);
|
||||
|
||||
check(sent == remaining, "sent should be equal to remaining");
|
||||
check(buffer.position() == (position + sent),
|
||||
"buffers position should have been incremented by sent");
|
||||
|
||||
/* TEST 4: receive the echoed message */
|
||||
buffer.clear();
|
||||
info = channel.receive(buffer, null, null);
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.streamNumber() == streamNumber,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.LARGE_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.LARGE_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
|
||||
/* TEST 5: InvalidStreamExcepton */
|
||||
streamNumber = assoc.maxOutboundStreams() + 1;
|
||||
info = MessageInfo.createOutgoing(assoc, null, streamNumber);
|
||||
buffer.clear();
|
||||
buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));
|
||||
buffer.flip();
|
||||
position = buffer.position();
|
||||
remaining = buffer.remaining();
|
||||
|
||||
debug("sending on stream number: " + streamNumber);
|
||||
debug("sending small message: " + buffer);
|
||||
try {
|
||||
sent = channel.send(buffer, info);
|
||||
fail("should have thrown InvalidStreamExcepton");
|
||||
} catch (InvalidStreamException ise){
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
check(buffer.remaining() == remaining,
|
||||
"remaining should not be changed");
|
||||
check(buffer.position() == position,
|
||||
"buffers position should not be changed");
|
||||
|
||||
|
||||
/* TEST 5: getRemoteAddresses(Association) */
|
||||
channel.getRemoteAddresses(assoc);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
clientFinishedLatch.countDown();
|
||||
try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }
|
||||
catch (InterruptedException ie) { unexpected(ie); }
|
||||
if (channel != null) {
|
||||
try { channel.close(); }
|
||||
catch (IOException e) { unexpected (e);}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Server implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpMultiChannel serverChannel;
|
||||
|
||||
public Server() throws IOException {
|
||||
serverChannel = SctpMultiChannel.open().bind(null);
|
||||
java.util.Set<SocketAddress> addrs = serverChannel.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
(new Thread(this, "Server-" + serverAddr.getPort())).start();
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);
|
||||
try {
|
||||
MessageInfo info;
|
||||
|
||||
/* receive a small message */
|
||||
do {
|
||||
info = serverChannel.receive(buffer, null, null);
|
||||
if (info == null) {
|
||||
fail("Server: unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
check(info != null, "info is null");
|
||||
check(info.streamNumber() == 0,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.SMALL_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
check(info != null, "info is null");
|
||||
Set<Association> assocs = serverChannel.associations();
|
||||
check(assocs.size() == 1, "there should be only one association");
|
||||
Iterator<Association> it = assocs.iterator();
|
||||
check(it.hasNext());
|
||||
Association assoc = it.next();
|
||||
|
||||
/* echo the message */
|
||||
debug("Server: echoing first message");
|
||||
buffer.flip();
|
||||
int bytes = serverChannel.send(buffer, info);
|
||||
debug("Server: sent " + bytes + "bytes");
|
||||
|
||||
/* receive a large message */
|
||||
buffer.clear();
|
||||
do {
|
||||
info = serverChannel.receive(buffer, null, null);
|
||||
if (info == null) {
|
||||
fail("Server: unexpected null from receive");
|
||||
return;
|
||||
}
|
||||
} while (!info.isComplete());
|
||||
|
||||
buffer.flip();
|
||||
|
||||
check(info.streamNumber() == assoc.maxInboundStreams() - 1,
|
||||
"message not sent on the correct stream");
|
||||
check(info.bytes() == Util.LARGE_MESSAGE.getBytes("ISO-8859-1").
|
||||
length, "bytes received not equal to message length");
|
||||
check(info.bytes() == buffer.remaining(), "bytes != remaining");
|
||||
check(Util.compare(buffer, Util.LARGE_MESSAGE),
|
||||
"received message not the same as sent message");
|
||||
|
||||
/* echo the message */
|
||||
debug("Server: echoing second message");
|
||||
buffer.flip();
|
||||
bytes = serverChannel.send(buffer, info);
|
||||
debug("Server: sent " + bytes + "bytes");
|
||||
|
||||
clientFinishedLatch.await(10L, TimeUnit.SECONDS);
|
||||
serverFinishedLatch.countDown();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
} finally {
|
||||
try { if (serverChannel != null) serverChannel.close(); }
|
||||
catch (IOException unused) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {System.err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { System.out.println(message); } }
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
138
jdk/test/com/sun/nio/sctp/SctpMultiChannel/Util.java
Normal file
138
jdk/test/com/sun/nio/sctp/SctpMultiChannel/Util.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.SocketException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class Util {
|
||||
static final int SMALL_BUFFER = 128;
|
||||
static final String SMALL_MESSAGE =
|
||||
"Under the bridge and over the dam, looking for berries, berries for jam";
|
||||
|
||||
static final int LARGE_BUFFER = 32768;
|
||||
static final String LARGE_MESSAGE;
|
||||
|
||||
static {
|
||||
StringBuffer sb = new StringBuffer(LARGE_BUFFER);
|
||||
for (int i=0; i<460; i++)
|
||||
sb.append(SMALL_MESSAGE);
|
||||
|
||||
LARGE_MESSAGE = sb.toString();
|
||||
}
|
||||
|
||||
static boolean isSCTPSupported() {
|
||||
try {
|
||||
SctpChannel c = SctpChannel.open();
|
||||
c.close();
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
out.println(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a list of all the addresses on the system.
|
||||
* @param inclLoopback
|
||||
* if {@code true}, include the loopback addresses
|
||||
* @param ipv4Only
|
||||
* it {@code true}, only IPv4 addresses will be included
|
||||
*/
|
||||
static List<InetAddress> getAddresses(boolean inclLoopback,
|
||||
boolean ipv4Only)
|
||||
throws SocketException {
|
||||
ArrayList<InetAddress> list = new ArrayList<InetAddress>();
|
||||
Enumeration<NetworkInterface> nets =
|
||||
NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface netInf : Collections.list(nets)) {
|
||||
Enumeration<InetAddress> addrs = netInf.getInetAddresses();
|
||||
for (InetAddress addr : Collections.list(addrs)) {
|
||||
if (!list.contains(addr) &&
|
||||
(inclLoopback ? true : !addr.isLoopbackAddress()) &&
|
||||
(ipv4Only ? (addr instanceof Inet4Address) : true)) {
|
||||
list.add(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void dumpAddresses(SctpChannel channel,
|
||||
PrintStream printStream)
|
||||
throws IOException {
|
||||
Set<SocketAddress> addrs = channel.getAllLocalAddresses();
|
||||
printStream.println("Local Addresses: ");
|
||||
for (Iterator<SocketAddress> it = addrs.iterator(); it.hasNext(); ) {
|
||||
InetSocketAddress addr = (InetSocketAddress)it.next();
|
||||
printStream.println("\t" + addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the contents of the given ByteBuffer with the contens of the
|
||||
* given byte array. true if, and only if, the contents are the same.
|
||||
*/
|
||||
static boolean compare(ByteBuffer bb, byte[] message) {
|
||||
if (message.length != bb.remaining()) {
|
||||
out.println("Compare failed, byte array length != to buffer remaining");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<message.length; i++) {
|
||||
byte b = bb.get();
|
||||
if (message[i] != b) {
|
||||
out.println("Position " + i + ": " + message[i] + " != " + b);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean compare(ByteBuffer bb, String str) {
|
||||
try{
|
||||
return Util.compare(bb, str.getBytes("ISO-8859-1"));
|
||||
} catch (UnsupportedEncodingException unsupported) {
|
||||
throw new AssertionError(unsupported);
|
||||
}
|
||||
}
|
||||
}
|
274
jdk/test/com/sun/nio/sctp/SctpServerChannel/Accept.java
Normal file
274
jdk/test/com/sun/nio/sctp/SctpServerChannel/Accept.java
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
import java.nio.channels.NotYetBoundException;
|
||||
import java.nio.channels.ClosedByInterruptException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class Accept {
|
||||
static CountDownLatch acceptLatch = new CountDownLatch(1);
|
||||
static CountDownLatch closeByIntLatch = new CountDownLatch(1);
|
||||
static CountDownLatch asyncCloseLatch = new CountDownLatch(1);
|
||||
AcceptServer server = null;
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new AcceptServer();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doClient(address);
|
||||
}
|
||||
|
||||
void doClient(SocketAddress peerAddress) {
|
||||
SctpChannel channel = null;
|
||||
|
||||
try {
|
||||
channel = SctpChannel.open(peerAddress, 0, 0);
|
||||
acceptLatch.await();
|
||||
|
||||
/* for test 4 */
|
||||
closeByIntLatch.await();
|
||||
sleep(500);
|
||||
server.thread().interrupt();
|
||||
|
||||
/* for test 5 */
|
||||
asyncCloseLatch.await();
|
||||
sleep(500);
|
||||
server.channel().close();
|
||||
|
||||
/* wait for the server thread to finish */
|
||||
join(server.thread(), 10000);
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
} finally {
|
||||
try { if (channel != null) channel.close(); }
|
||||
catch (IOException e) { unexpected(e);}
|
||||
}
|
||||
}
|
||||
|
||||
class AcceptServer implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
private Thread serverThread;
|
||||
|
||||
public AcceptServer() throws IOException {
|
||||
ssc = SctpServerChannel.open();
|
||||
|
||||
/* TEST 1: NotYetBoundException */
|
||||
debug("TEST 1: NotYetBoundException");
|
||||
try {
|
||||
ssc.accept();
|
||||
fail();
|
||||
} catch (NotYetBoundException nybe) {
|
||||
debug(" caught NotYetBoundException");
|
||||
pass();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
}
|
||||
|
||||
ssc.bind(null);
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
|
||||
/* TEST 2: null if this channel is in non-blocking mode and no
|
||||
* association is available to be accepted */
|
||||
ssc.configureBlocking(false);
|
||||
debug("TEST 2: non-blocking mode null");
|
||||
try {
|
||||
SctpChannel sc = ssc.accept();
|
||||
check(sc == null, "non-blocking mode should return null");
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} finally {
|
||||
ssc.configureBlocking(true);
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
serverThread = new Thread(this, "AcceptServer-" +
|
||||
serverAddr.getPort());
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
InetSocketAddress address() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
SctpServerChannel channel() {
|
||||
return ssc;
|
||||
}
|
||||
|
||||
Thread thread() {
|
||||
return serverThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
SctpChannel sc = null;
|
||||
try {
|
||||
/* TEST 3: accepted channel */
|
||||
debug("TEST 3: accepted channel");
|
||||
sc = ssc.accept();
|
||||
|
||||
checkAcceptedChannel(sc);
|
||||
acceptLatch.countDown();
|
||||
|
||||
/* TEST 4: ClosedByInterruptException */
|
||||
debug("TEST 4: ClosedByInterruptException");
|
||||
try {
|
||||
closeByIntLatch.countDown();
|
||||
ssc.accept();
|
||||
fail();
|
||||
} catch (ClosedByInterruptException unused) {
|
||||
debug(" caught ClosedByInterruptException");
|
||||
pass();
|
||||
}
|
||||
|
||||
/* TEST 5: AsynchronousCloseException */
|
||||
debug("TEST 5: AsynchronousCloseException");
|
||||
/* reset thread interrupt status */
|
||||
Thread.currentThread().interrupted();
|
||||
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
try {
|
||||
asyncCloseLatch.countDown();
|
||||
ssc.accept();
|
||||
fail();
|
||||
} catch (AsynchronousCloseException unused) {
|
||||
debug(" caught AsynchronousCloseException");
|
||||
pass();
|
||||
}
|
||||
|
||||
/* TEST 6: ClosedChannelException */
|
||||
debug("TEST 6: ClosedChannelException");
|
||||
try {
|
||||
ssc.accept();
|
||||
fail();
|
||||
} catch (ClosedChannelException unused) {
|
||||
debug(" caught ClosedChannelException");
|
||||
pass();
|
||||
}
|
||||
ssc = null;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} finally {
|
||||
try { if (ssc != null) ssc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
try { if (sc != null) sc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkAcceptedChannel(SctpChannel sc) {
|
||||
try {
|
||||
debug("Checking accepted SctpChannel");
|
||||
check(sc.association() != null,
|
||||
"accepted channel should have an association");
|
||||
check(!(sc.getRemoteAddresses().isEmpty()),
|
||||
"accepted channel should be connected");
|
||||
check(!(sc.isConnectionPending()),
|
||||
"accepted channel should not have a connection pending");
|
||||
check(sc.isBlocking(),
|
||||
"accepted channel should be blocking");
|
||||
try { sc.connect(new TestSocketAddress()); fail(); }
|
||||
catch (AlreadyConnectedException unused) { pass(); }
|
||||
try { sc.bind(new TestSocketAddress()); fail(); }
|
||||
catch (AlreadyConnectedException unused) { pass(); }
|
||||
} catch (IOException unused) { fail(); }
|
||||
}
|
||||
|
||||
static class TestSocketAddress extends SocketAddress {}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { out.println(message); } }
|
||||
void sleep(long millis) { try { Thread.currentThread().sleep(millis); }
|
||||
catch(InterruptedException ie) { unexpected(ie); }}
|
||||
void join(Thread thread, long millis) { try { thread.join(millis); }
|
||||
catch(InterruptedException ie) { unexpected(ie); }}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4927640
|
||||
* @summary Tests the SCTP protocol implementation
|
||||
* @author chegar
|
||||
*/
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import com.sun.nio.sctp.SctpServerChannel;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.err;
|
||||
|
||||
public class NonBlockingAccept {
|
||||
static CountDownLatch acceptLatch = new CountDownLatch(1);
|
||||
static final int SEL_TIMEOUT = 10000;
|
||||
static final int NUM_TEST_CONNECTIONS = 10;
|
||||
|
||||
void test(String[] args) {
|
||||
SocketAddress address = null;
|
||||
NonblockingServer server;
|
||||
|
||||
if (!Util.isSCTPSupported()) {
|
||||
out.println("SCTP protocol is not supported");
|
||||
out.println("Test cannot be run");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length == 2) {
|
||||
/* requested to connecct to a specific address */
|
||||
try {
|
||||
int port = Integer.valueOf(args[1]);
|
||||
address = new InetSocketAddress(args[0], port);
|
||||
} catch (NumberFormatException nfe) {
|
||||
err.println(nfe);
|
||||
}
|
||||
} else {
|
||||
/* start server on local machine, default */
|
||||
try {
|
||||
server = new NonblockingServer();
|
||||
server.start();
|
||||
address = server.address();
|
||||
debug("Server started and listening on " + address);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doClient(address);
|
||||
}
|
||||
|
||||
void doClient(SocketAddress peerAddress) {
|
||||
Set<SctpChannel> channels = new HashSet<SctpChannel>(NUM_TEST_CONNECTIONS);
|
||||
|
||||
try {
|
||||
for (int i=0; i<NUM_TEST_CONNECTIONS;) {
|
||||
debug("connecting " + ++i);
|
||||
channels.add(SctpChannel.open(peerAddress, 0, 0));
|
||||
sleep(100);
|
||||
}
|
||||
|
||||
/* don't close the channels until they have been accepted */
|
||||
acceptLatch.await();
|
||||
|
||||
for(SctpChannel sc: channels)
|
||||
sc.close();
|
||||
} catch (IOException ioe) {
|
||||
unexpected(ioe);
|
||||
} catch (InterruptedException ie) {
|
||||
unexpected(ie);
|
||||
}
|
||||
}
|
||||
|
||||
class NonblockingServer implements Runnable
|
||||
{
|
||||
final InetSocketAddress serverAddr;
|
||||
private SctpServerChannel ssc;
|
||||
private Thread serverThread;
|
||||
|
||||
public NonblockingServer() throws IOException {
|
||||
ssc = SctpServerChannel.open().bind(null);
|
||||
java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();
|
||||
if (addrs.isEmpty())
|
||||
debug("addrs should not be empty");
|
||||
|
||||
serverAddr = (InetSocketAddress) addrs.iterator().next();
|
||||
}
|
||||
|
||||
void start() {
|
||||
serverThread = new Thread(this, "NonblockingServer-" +
|
||||
serverAddr.getPort());
|
||||
serverThread.start();
|
||||
}
|
||||
|
||||
InetSocketAddress address () {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Selector acceptSelector = null;
|
||||
SelectionKey acceptKey = null;
|
||||
|
||||
try {
|
||||
acceptSelector = Selector.open();
|
||||
ssc.configureBlocking(false);
|
||||
check(ssc.isBlocking() == false, "Should be in non-blocking mode");
|
||||
acceptKey = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
int connectionsAccepted = 0;
|
||||
while (connectionsAccepted < NUM_TEST_CONNECTIONS) {
|
||||
int keysAdded = acceptSelector.select(SEL_TIMEOUT);
|
||||
if (keysAdded > 0) {
|
||||
Set<SelectionKey> keys = acceptSelector.selectedKeys();
|
||||
Iterator<SelectionKey> i = keys.iterator();
|
||||
while(i.hasNext()) {
|
||||
SelectionKey sk = i.next();
|
||||
i.remove();
|
||||
SctpServerChannel nextReady =
|
||||
(SctpServerChannel)sk.channel();
|
||||
check(nextReady.equals(ssc),
|
||||
"channels should be equal");
|
||||
check(sk.isAcceptable(),
|
||||
"key should be acceptable");
|
||||
check(!sk.isReadable(),
|
||||
"key should not be readable");
|
||||
check(!sk.isWritable(),
|
||||
"key should not be writable");
|
||||
check(!sk.isConnectable(),
|
||||
"key should not be connectable");
|
||||
SctpChannel acceptsc = nextReady.accept();
|
||||
connectionsAccepted++;
|
||||
debug("Accepted " + connectionsAccepted + " connections");
|
||||
check(acceptsc != null,
|
||||
"Accepted channel should not be null");
|
||||
if (acceptsc != null) {
|
||||
checkAcceptedChannel(acceptsc);
|
||||
acceptsc.close();
|
||||
}
|
||||
} /* while */
|
||||
} /* if */
|
||||
} /* while */
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} finally {
|
||||
acceptLatch.countDown();
|
||||
if (acceptKey != null) acceptKey.cancel();
|
||||
try { if (acceptSelector != null) acceptSelector.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
try { if (ssc != null) ssc.close(); }
|
||||
catch (IOException ioe) { unexpected(ioe); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkAcceptedChannel(SctpChannel sc) {
|
||||
try {
|
||||
debug("Checking accepted SctpChannel");
|
||||
check(sc.association() != null,
|
||||
"accepted channel should have an association");
|
||||
check(!(sc.getRemoteAddresses().isEmpty()),
|
||||
"accepted channel should be connected");
|
||||
check(!(sc.isConnectionPending()),
|
||||
"accepted channel should not have a connection pending");
|
||||
check(sc.isBlocking(),
|
||||
"accepted channel should be blocking");
|
||||
try { sc.connect(new TestSocketAddress()); fail(); }
|
||||
catch (AlreadyConnectedException unused) { pass(); }
|
||||
try { sc.bind(new TestSocketAddress()); fail(); }
|
||||
catch (AlreadyConnectedException unused) { pass(); }
|
||||
} catch (IOException unused) { fail(); }
|
||||
}
|
||||
|
||||
static class TestSocketAddress extends SocketAddress {}
|
||||
|
||||
//--------------------- Infrastructure ---------------------------
|
||||
boolean debug = true;
|
||||
volatile int passed = 0, failed = 0;
|
||||
void pass() {passed++;}
|
||||
void fail() {failed++; Thread.dumpStack();}
|
||||
void fail(String msg) {err.println(msg); fail();}
|
||||
void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||
void check(boolean cond) {if (cond) pass(); else fail();}
|
||||
void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
|
||||
void debug(String message) {if(debug) { out.println(message); } }
|
||||
void sleep(long millis) { try { Thread.currentThread().sleep(millis); }
|
||||
catch(InterruptedException ie) { unexpected(ie); }}
|
||||
public static void main(String[] args) throws Throwable {
|
||||
Class<?> k = new Object(){}.getClass().getEnclosingClass();
|
||||
try {k.getMethod("instanceMain",String[].class)
|
||||
.invoke( k.newInstance(), (Object) args);}
|
||||
catch (Throwable e) {throw e.getCause();}}
|
||||
public void instanceMain(String[] args) throws Throwable {
|
||||
try {test(args);} catch (Throwable t) {unexpected(t);}
|
||||
out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
|
||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||
|
||||
}
|
138
jdk/test/com/sun/nio/sctp/SctpServerChannel/Util.java
Normal file
138
jdk/test/com/sun/nio/sctp/SctpServerChannel/Util.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.SocketException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import com.sun.nio.sctp.SctpChannel;
|
||||
import static java.lang.System.out;
|
||||
|
||||
public class Util {
|
||||
static final int SMALL_BUFFER = 128;
|
||||
static final String SMALL_MESSAGE =
|
||||
"Under the bridge and over the dam, looking for berries, berries for jam";
|
||||
|
||||
static final int LARGE_BUFFER = 32768;
|
||||
static final String LARGE_MESSAGE;
|
||||
|
||||
static {
|
||||
StringBuffer sb = new StringBuffer(LARGE_BUFFER);
|
||||
for (int i=0; i<460; i++)
|
||||
sb.append(SMALL_MESSAGE);
|
||||
|
||||
LARGE_MESSAGE = sb.toString();
|
||||
}
|
||||
|
||||
static boolean isSCTPSupported() {
|
||||
try {
|
||||
SctpChannel c = SctpChannel.open();
|
||||
c.close();
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
out.println(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns a list of all the addresses on the system.
|
||||
* @param inclLoopback
|
||||
* if {@code true}, include the loopback addresses
|
||||
* @param ipv4Only
|
||||
* it {@code true}, only IPv4 addresses will be included
|
||||
*/
|
||||
static List<InetAddress> getAddresses(boolean inclLoopback,
|
||||
boolean ipv4Only)
|
||||
throws SocketException {
|
||||
ArrayList<InetAddress> list = new ArrayList<InetAddress>();
|
||||
Enumeration<NetworkInterface> nets =
|
||||
NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface netInf : Collections.list(nets)) {
|
||||
Enumeration<InetAddress> addrs = netInf.getInetAddresses();
|
||||
for (InetAddress addr : Collections.list(addrs)) {
|
||||
if (!list.contains(addr) &&
|
||||
(inclLoopback ? true : !addr.isLoopbackAddress()) &&
|
||||
(ipv4Only ? (addr instanceof Inet4Address) : true)) {
|
||||
list.add(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void dumpAddresses(SctpChannel channel,
|
||||
PrintStream printStream)
|
||||
throws IOException {
|
||||
Set<SocketAddress> addrs = channel.getAllLocalAddresses();
|
||||
printStream.println("Local Addresses: ");
|
||||
for (Iterator<SocketAddress> it = addrs.iterator(); it.hasNext(); ) {
|
||||
InetSocketAddress addr = (InetSocketAddress)it.next();
|
||||
printStream.println("\t" + addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the contents of the given ByteBuffer with the contens of the
|
||||
* given byte array. true if, and only if, the contents are the same.
|
||||
*/
|
||||
static boolean compare(ByteBuffer bb, byte[] message) {
|
||||
if (message.length != bb.remaining()) {
|
||||
out.println("Compare failed, byte array length != to buffer remaining");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<message.length; i++) {
|
||||
byte b = bb.get();
|
||||
if (message[i] != b) {
|
||||
out.println("Position " + i + ": " + message[i] + " != " + b);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean compare(ByteBuffer bb, String str) {
|
||||
try{
|
||||
return Util.compare(bb, str.getBytes("ISO-8859-1"));
|
||||
} catch (UnsupportedEncodingException unsupported) {
|
||||
throw new AssertionError(unsupported);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user