4640544: New I/O: Complete socket-channel functionality

Reviewed-by: iris, sherman, chegar
This commit is contained in:
Alan Bateman 2008-08-31 18:39:01 +01:00
parent deaa5d9446
commit 63d86bcfda
62 changed files with 5739 additions and 1634 deletions

View File

@ -39,6 +39,9 @@ FILES_src = \
java/nio/channels/FileLock.java \
java/nio/channels/GatheringByteChannel.java \
java/nio/channels/InterruptibleChannel.java \
java/nio/channels/MembershipKey.java \
java/nio/channels/MulticastChannel.java \
java/nio/channels/NetworkChannel.java \
java/nio/channels/ReadableByteChannel.java \
java/nio/channels/ScatteringByteChannel.java \
java/nio/channels/SelectableChannel.java \
@ -73,6 +76,7 @@ FILES_src = \
sun/nio/ch/DatagramSocketAdaptor.java \
sun/nio/ch/DefaultSelectorProvider.java \
sun/nio/ch/DirectBuffer.java \
sun/nio/ch/ExtendedSocketOption.java \
sun/nio/ch/FileChannelImpl.java \
sun/nio/ch/FileDispatcher.java \
sun/nio/ch/FileKey.java \
@ -80,12 +84,14 @@ FILES_src = \
sun/nio/ch/IOUtil.java \
sun/nio/ch/IOStatus.java \
sun/nio/ch/IOVecWrapper.java \
sun/nio/ch/MembershipKeyImpl.java \
sun/nio/ch/MembershipRegistry.java \
sun/nio/ch/NativeDispatcher.java \
sun/nio/ch/NativeObject.java \
sun/nio/ch/NativeThread.java \
sun/nio/ch/NativeThreadSet.java \
sun/nio/ch/Net.java \
sun/nio/ch/OptionAdaptor.java \
sun/nio/ch/OptionKey.java \
sun/nio/ch/PipeImpl.java \
sun/nio/ch/PollArrayWrapper.java \
sun/nio/ch/Reflect.java \
@ -99,8 +105,7 @@ FILES_src = \
sun/nio/ch/SocketAdaptor.java \
sun/nio/ch/SocketChannelImpl.java \
sun/nio/ch/SocketDispatcher.java \
sun/nio/ch/SocketOpts.java \
sun/nio/ch/SocketOptsImpl.java \
sun/nio/ch/SocketOptionRegistry.java \
sun/nio/ch/SourceChannelImpl.java \
sun/nio/ch/Util.java \
\
@ -240,6 +245,7 @@ FILES_gen_ex = \
java/nio/InvalidMarkException.java \
java/nio/ReadOnlyBufferException.java \
\
java/nio/channels/AlreadyBoundException.java \
java/nio/channels/AlreadyConnectedException.java \
java/nio/channels/AsynchronousCloseException.java \
java/nio/channels/ClosedByInterruptException.java \
@ -258,14 +264,15 @@ FILES_gen_ex = \
java/nio/channels/UnresolvedAddressException.java \
java/nio/channels/UnsupportedAddressTypeException.java \
\
sun/nio/ch/AlreadyBoundException.java \
\
java/nio/charset/CharacterCodingException.java \
java/nio/charset/IllegalCharsetNameException.java \
java/nio/charset/UnsupportedCharsetException.java
FILES_gen_csp = sun/nio/cs/StandardCharsets.java
FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) $(FILES_gen_csp)
FILES_gen_sor = sun/nio/ch/SocketOptionRegistry.java
FILES_gen = $(FILES_gen_coder) $(FILES_gen_buffer) $(FILES_gen_ex) \
$(FILES_gen_csp) $(FILES_gen_sor)
FILES_java = $(FILES_src) $(FILES_gen)

View File

@ -56,18 +56,18 @@ FILES_java += \
sun/nio/ch/DevPollSelectorProvider.java \
sun/nio/ch/InheritedChannel.java \
sun/nio/ch/PollSelectorProvider.java \
sun/nio/ch/PollSelectorImpl.java
sun/nio/ch/PollSelectorImpl.java
FILES_c += \
DevPollArrayWrapper.c \
InheritedChannel.c \
PollArrayWrapper.c \
NativeThread.c
NativeThread.c \
PollArrayWrapper.c
FILES_export += \
sun/nio/ch/DevPollArrayWrapper.java \
sun/nio/ch/InheritedChannel.java \
sun/nio/ch/NativeThread.java
sun/nio/ch/NativeThread.java
endif # PLATFORM = solaris
ifeq ($(PLATFORM), windows)
@ -94,14 +94,14 @@ FILES_java += \
FILES_c += \
EPollArrayWrapper.c \
PollArrayWrapper.c \
InheritedChannel.c \
NativeThread.c
NativeThread.c \
PollArrayWrapper.c
FILES_export += \
sun/nio/ch/EPollArrayWrapper.java \
sun/nio/ch/InheritedChannel.java \
sun/nio/ch/NativeThread.java
sun/nio/ch/NativeThread.java
endif # PLATFORM = linux
# Find platform-specific C source files
@ -618,12 +618,6 @@ $(BUF_GEN)/%Exception.java: genExceptions.sh $(BUF_SRC)/exceptions
@$(RM) $@.temp
$(GEN_EX_CMD) $(BUF_SRC)/exceptions $(BUF_GEN)
$(SCH_GEN)/%Exception.java: genExceptions.sh $(SCH_SRC)/exceptions
$(prep-target)
@$(RM) $@.temp
$(GEN_EX_CMD) $(SCH_SRC)/exceptions $(SCH_GEN)
#
# Generated charset-provider classes
#
@ -638,4 +632,29 @@ $(SCS_GEN)/StandardCharsets.java: genCharsetProvider.sh \
HASHER="$(BOOT_JAVA_CMD) -jar $(HASHER_JARFILE)" \
$(SH) -e genCharsetProvider.sh $(SCS_SRC)/standard-charsets $(SCS_GEN)
#
# Generated channel implementation classes.
# C source is compiled in TEMPDIR to avoid turds left by Windows compilers.
#
GENSOR_SRC = $(SHARE_SRC)/native/sun/nio/ch/genSocketOptionRegistry.c
GENSOR_EXE = $(TEMPDIR)/genSocketOptionRegistry$(EXE_SUFFIX)
SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSOR_SRC) | \
$(NAWK) '/^.*Copyright.*Sun/ { print $$3 }')
$(TEMPDIR)/$(GENSOR_SRC) : $(GENSOR_SRC)
$(install-file)
$(GENSOR_EXE) : $(TEMPDIR)/$(GENSOR_SRC)
$(prep-target)
($(CD) $(TEMPDIR); $(CC) $(CPPFLAGS) $(LDDFLAGS) \
-o genSocketOptionRegistry$(EXE_SUFFIX) $(GENSOR_SRC))
$(SCH_GEN)/SocketOptionRegistry.java: $(GENSOR_EXE)
$(prep-target)
NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(SOR_COPYRIGHT_YEARS) > $@
$(GENSOR_EXE) >> $@
.PHONY: sources

View File

@ -1,3 +1,27 @@
#
# Copyright 2001-2008 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:
@ -61,20 +85,29 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_socket0;
Java_sun_nio_ch_Net_bind;
Java_sun_nio_ch_Net_connect;
Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0;
Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
Java_sun_nio_ch_Net_blockOrUnblock6;
Java_sun_nio_ch_Net_setInterface4;
Java_sun_nio_ch_Net_getInterface4;
Java_sun_nio_ch_Net_setInterface6;
Java_sun_nio_ch_Net_getInterface6;
Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_ServerSocketChannelImpl_listen;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
Java_sun_nio_ch_SocketChannelImpl_shutdown;
local:
*;

View File

@ -1,3 +1,27 @@
#
# Copyright 2001-2008 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:
@ -59,20 +83,29 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_socket0;
Java_sun_nio_ch_Net_bind;
Java_sun_nio_ch_Net_connect;
Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0;
Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
Java_sun_nio_ch_Net_blockOrUnblock6;
Java_sun_nio_ch_Net_setInterface4;
Java_sun_nio_ch_Net_getInterface4;
Java_sun_nio_ch_Net_setInterface6;
Java_sun_nio_ch_Net_getInterface6;
Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_ServerSocketChannelImpl_listen;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
Java_sun_nio_ch_SocketChannelImpl_shutdown;
local:
*;

View File

@ -31,7 +31,7 @@ BUILDDIR = ../..
PRODUCT = java
include $(BUILDDIR)/common/Defs.gmk
SUBDIRS = server
SUBDIRS = multicast server
all build clean clobber::
$(SUBDIRS-loop)

View File

@ -1,5 +1,5 @@
#
# Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2007 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
@ -23,17 +23,30 @@
# have any questions.
#
# Generated exception classes for sun.nio.ch
#
# Makefile for the nio/multicast sample code
#
SINCE=1.4
PACKAGE=sun.nio.ch
# This year should only change if the generated source is modified.
COPYRIGHT_YEARS=2000-2007
BUILDDIR = ../../..
PRODUCT = java
SUPER=IllegalStateException
include $(BUILDDIR)/common/Defs.gmk
gen AlreadyBoundException "
* Unchecked exception thrown when an attempt is made to bind a {@link
* SocketChannel} that is already bound." \
9002280723481772026L
SAMPLE_SRC_DIR = $(SHARE_SRC)/sample/nio/multicast
SAMPLE_DST_DIR = $(SAMPLEDIR)/nio/multicast
SAMPLE_FILES = \
$(SAMPLE_DST_DIR)/Reader.java \
$(SAMPLE_DST_DIR)/Sender.java \
$(SAMPLE_DST_DIR)/MulticastAddress.java
all build: $(SAMPLE_FILES)
$(SAMPLE_DST_DIR)/%: $(SAMPLE_SRC_DIR)/%
$(install-file)
clean clobber:
$(RM) -r $(SAMPLE_DST_DIR)
.PHONY: all build clean clobber

View File

@ -25,7 +25,6 @@
package java.net;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import sun.security.action.*;

View File

@ -0,0 +1,39 @@
/*
* Copyright 2007-2008 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 java.net;
/**
* Represents a family of communication protocols.
*
* @since 1.7
*/
public interface ProtocolFamily {
/**
* Returns the name of the protocol family.
*/
String name();
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2007-2008 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 java.net;
/**
* A socket option associated with a socket.
*
* <p> In the {@link java.nio.channels channels} package, the {@link
* java.nio.channels.NetworkChannel} interface defines the {@link
* java.nio.channels.NetworkChannel#setOption(SocketOption,Object) setOption}
* and {@link java.nio.channels.NetworkChannel#getOption(SocketOption) getOption}
* methods to set and query the channel's socket options.
*
* @param <T> The type of the socket option value.
*
* @since 1.7
*
* @see StandardSocketOption
*/
public interface SocketOption<T> {
/**
* Returns the name of the socket option.
*/
String name();
/**
* Returns the type of the socket option value.
*/
Class<T> type();
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2007-2008 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 java.net;
/**
* Defines the standard family of communication protocols.
*
* @since 1.7
*/
public enum StandardProtocolFamily implements ProtocolFamily {
/**
* Internet Protocol Version 4 (IPv4)
*/
INET,
/**
* Internet Protocol Version 6 (IPv6)
*/
INET6
}

View File

@ -0,0 +1,352 @@
/*
* Copyright 2007-2008 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 java.net;
/**
* Defines the <em>standard</em> socket options.
*
* <p> The {@link SocketOption#name name} of each socket option defined by this
* class is its field name.
*
* <p> In this release, the socket options defined here are used by {@link
* java.nio.channels.NetworkChannel network} channels in the {@link
* java.nio.channels channels} package.
*
* @since 1.7
*/
public final class StandardSocketOption {
private StandardSocketOption() { }
// -- SOL_SOCKET --
/**
* Allow transmission of broadcast datagrams.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The option is specific to
* datagram-oriented sockets sending to {@link java.net.Inet4Address IPv4}
* broadcast addresses. When the socket option is enabled then the socket
* can be used to send <em>broadcast datagrams</em>.
*
* <p> The initial value of this socket option is {@code FALSE}. The socket
* option may be enabled or disabled at any time. Some operating systems may
* require that the Java virtual machine be started with implementation
* specific privileges to enable this option or send broadcast datagrams.
*
* @see <a href="http://www.ietf.org/rfc/rfc919.txt">RFC&nbsp;929:
* Broadcasting Internet Datagrams</a>
*/
public static final SocketOption<Boolean> SO_BROADCAST =
new StdSocketOption<Boolean>("SO_BROADCAST", Boolean.class);
/**
* Keep connection alive.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. When the {@code SO_KEEPALIVE}
* option is enabled the operating system may use a <em>keep-alive</em>
* mechanism to periodically probe the other end of a connection when the
* connection is otherwise idle. The exact semantics of the keep alive
* mechanism is system dependent and therefore unspecified.
*
* <p> The initial value of this socket option is {@code FALSE}. The socket
* option may be enabled or disabled at any time.
*
* @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122
* Requirements for Internet Hosts -- Communication Layers</a>
*/
public static final SocketOption<Boolean> SO_KEEPALIVE =
new StdSocketOption<Boolean>("SO_KEEPALIVE", Boolean.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 datagram-oriented sockets, the size of the send buffer may limit
* the size of the datagrams that may be sent by the socket. Whether
* datagrams larger than the buffer size are sent or discarded is system
* dependent.
*
* <p> The initial/default size of the socket send buffer and the range of
* allowable values is system dependent although a negative size is not
* allowed. An attempt to set the socket send buffer to larger than its
* maximum size causes it to be set to its maximum size.
*
* <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 SocketOption<Integer> SO_SNDBUF =
new StdSocketOption<Integer>("SO_SNDBUF", Integer.class);
/**
* 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 datagram-oriented sockets, the size of the receive buffer may
* limit the size of the datagrams that can be received. Whether datagrams
* larger than the buffer size can be received is system dependent.
* Increasing the socket receive buffer may be important for cases where
* datagrams arrive in bursts faster than they can be processed.
*
* <p> In the case of stream-oriented sockets and the TCP/IP protocol, the
* size of the socket receive buffer may be used when advertising the size
* of the TCP receive window to the remote peer.
*
* <p> The initial/default size of the socket receive buffer and the range
* of allowable values is system dependent although a negative size is not
* allowed. An attempt to set the socket receive buffer to larger than its
* maximum size causes it to be set to its maximum size.
*
* <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.
*
* @see <a href="http://www.ietf.org/rfc/rfc1323.txt">RFC&nbsp;1323: TCP
* Extensions for High Performance</a>
*/
public static final SocketOption<Integer> SO_RCVBUF =
new StdSocketOption<Integer>("SO_RCVBUF", Integer.class);
/**
* Re-use address.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The exact semantics of this
* socket option are socket type and system dependent.
*
* <p> In the case of stream-oriented sockets, this socket option will
* usually determine whether the socket can be bound to a socket address
* when a previous connection involving that socket address is in the
* <em>TIME_WAIT</em> state. On implementations where the semantics differ,
* and the socket option is not required to be enabled in order to bind the
* socket when a previous connection is in this state, then the
* implementation may choose to ignore this option.
*
* <p> For datagram-oriented sockets the socket option is used to allow
* multiple programs bind to the same address. This option should be enabled
* when the socket is to be used for Internet Protocol (IP) multicasting.
*
* <p> An implementation allows this socket option to be set before the
* socket is bound or connected. Changing the value of this socket option
* after the socket is bound has no effect. The default value of this
* socket option is system dependent.
*
* @see <a href="http://www.ietf.org/rfc/rfc793.txt">RFC&nbsp;793: Transmission
* Control Protocol</a>
*/
public static final SocketOption<Boolean> SO_REUSEADDR =
new StdSocketOption<Boolean>("SO_REUSEADDR", Boolean.class);
/**
* 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 SocketOption<Integer> SO_LINGER =
new StdSocketOption<Integer>("SO_LINGER", Integer.class);
// -- IPPROTO_IP --
/**
* The Type of Service (ToS) octet in the Internet Protocol (IP) header.
*
* <p> The value of this socket option is an {@code Integer}, the least
* significant 8 bits of which represents the value of the ToS octet in IP
* packets sent by sockets to an {@link StandardProtocolFamily#INET IPv4}
* socket. The interpretation of the ToS octet is network specific and
* is not defined by this class. Further information on the ToS octet can be
* found in <a href="http://www.ietf.org/rfc/rfc1349.txt">RFC&nbsp;1349</a>
* and <a href="http://www.ietf.org/rfc/rfc2474.txt">RFC&nbsp;2474</a>. The
* value of the socket option is a <em>hint</em>. An implementation may
* ignore the value, or ignore specific values.
*
* <p> The initial/default value of the TOS field in the ToS octet is
* implementation specific but will typically be {@code 0}. For
* datagram-oriented sockets the option may be configured at any time after
* the socket has been bound. The new value of the octet is used when sending
* subsequent datagrams. It is system dependent whether this option can be
* queried or changed prior to binding the socket.
*
* <p> The behavior of this socket option on a stream-oriented socket, or an
* {@link StandardProtocolFamily#INET6 IPv6} socket, is not defined in this
* release.
*/
public static final SocketOption<Integer> IP_TOS =
new StdSocketOption<Integer>("IP_TOS", Integer.class);
/**
* The network interface for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is a {@link NetworkInterface} that
* represents the outgoing interface for multicast datagrams sent by the
* datagram-oriented socket. For {@link StandardProtocolFamily#INET6 IPv6}
* sockets then it is system dependent whether setting this option also
* sets the outgoing interface for multlicast datagrams sent to IPv4
* addresses.
*
* <p> The initial/default value of this socket option may be {@code null}
* to indicate that outgoing interface will be selected by the operating
* system, typically based on the network routing tables. An implementation
* allows this socket option to be set after the socket is bound. Whether
* the socket option can be queried or changed prior to binding the socket
* is system dependent.
*
* @see java.nio.channels.MulticastChannel
*/
public static final SocketOption<NetworkInterface> IP_MULTICAST_IF =
new StdSocketOption<NetworkInterface>("IP_MULTICAST_IF", NetworkInterface.class);
/**
* The <em>time-to-live</em> for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is an {@code Integer} in the range
* <tt>0&nbsp;<=&nbsp;value&nbsp;<=&nbsp;255</tt>. It is used to control
* the scope of multicast datagrams sent by the datagram-oriented socket.
* In the case of an {@link StandardProtocolFamily#INET IPv4} socket
* the option is the time-to-live (TTL) on multicast datagrams sent by the
* socket. Datagrams with a TTL of zero are not transmitted on the network
* but may be delivered locally. In the case of an {@link
* StandardProtocolFamily#INET6 IPv6} socket the option is the
* <em>hop limit</em> which is number of <em>hops</em> that the datagram can
* pass through before expiring on the network. For IPv6 sockets it is
* system dependent whether the option also sets the <em>time-to-live</em>
* on multicast datagrams sent to IPv4 addresses.
*
* <p> The initial/default value of the time-to-live setting is typically
* {@code 1}. An implementation allows this socket option to be set after
* the socket is bound. Whether the socket option can be queried or changed
* prior to binding the socket is system dependent.
*
* @see java.nio.channels.MulticastChannel
*/
public static final SocketOption<Integer> IP_MULTICAST_TTL =
new StdSocketOption<Integer>("IP_MULTICAST_TTL", Integer.class);
/**
* Loopback for Internet Protocol (IP) multicast datagrams.
*
* <p> The value of this socket option is a {@code Boolean} that controls
* the <em>loopback</em> of multicast datagrams. The value of the socket
* option represents if the option is enabled or disabled.
*
* <p> The exact semantics of this socket options are system dependent.
* In particular, it is system dependent whether the loopback applies to
* multicast datagrams sent from the socket or received by the socket.
* For {@link StandardProtocolFamily#INET6 IPv6} sockets then it is
* system dependent whether the option also applies to multicast datagrams
* sent to IPv4 addresses.
*
* <p> The initial/default value of this socket option is {@code TRUE}. An
* implementation allows this socket option to be set after the socket is
* bound. Whether the socket option can be queried or changed prior to
* binding the socket is system dependent.
*
* @see java.nio.channels.MulticastChannel
*/
public static final SocketOption<Boolean> IP_MULTICAST_LOOP =
new StdSocketOption<Boolean>("IP_MULTICAST_LOOP", Boolean.class);
// -- IPPROTO_TCP --
/**
* Disable the Nagle algorithm.
*
* <p> The value of this socket option is a {@code Boolean} that represents
* whether the option is enabled or disabled. The socket option is specific to
* stream-oriented sockets using the TCP/IP protocol. TCP/IP uses an algorithm
* known as <em>The Nagle Algorithm</em> to coalesce short segments and
* improve network efficiency.
*
* <p> The default value of this socket option is {@code FALSE}. The
* socket option should only be enabled in cases where it is known that the
* coalescing impacts performance. The socket option may be enabled at any
* time. In other words, the Nagle Algorithm can be disabled. Once the option
* is enabled, it is system dependent whether it can be subsequently
* disabled. In that case, invoking the {@code setOption} method to disable
* the option has no effect.
*
* @see <a href="http://www.ietf.org/rfc/rfc1122.txt">RFC&nbsp;1122:
* Requirements for Internet Hosts -- Communication Layers</a>
*/
public static final SocketOption<Boolean> TCP_NODELAY =
new StdSocketOption<Boolean>("TCP_NODELAY", Boolean.class);
private static class StdSocketOption<T> implements SocketOption<T> {
private final String name;
private final Class<T> type;
StdSocketOption(String name, Class<T> type) {
this.name = name;
this.type = type;
}
@Override public String name() { return name; }
@Override public Class<T> type() { return type; }
@Override public String toString() { return name; }
}
}

View File

@ -26,28 +26,21 @@
package java.nio.channels;
import java.io.IOException;
import java.net.ProtocolFamily;
import java.net.DatagramSocket;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.*;
/**
* A selectable channel for datagram-oriented sockets.
*
*
* <p> Datagram channels are not a complete abstraction of network datagram
* sockets. Binding and the manipulation of socket options must be done
* through an associated {@link java.net.DatagramSocket} object obtained by
* invoking the {@link #socket() socket} method. It is not possible to create
* a channel for an arbitrary, pre-existing datagram socket, nor is it possible
* to specify the {@link java.net.DatagramSocketImpl} object to be used by a
* datagram socket associated with a datagram channel.
*
* <p> A datagram channel is created by invoking the {@link #open open} method
* of this class. A newly-created datagram channel is open but not connected.
* A datagram channel need not be connected in order for the {@link #send send}
* and {@link #receive receive} methods to be used. A datagram channel may be
* <p> A datagram channel is created by invoking one of the {@link #open open} methods
* of this class. It is not possible to create a channel for an arbitrary,
* pre-existing datagram socket. A newly-created datagram channel is open but not
* connected. A datagram channel need not be connected in order for the {@link #send
* send} and {@link #receive receive} methods to be used. A datagram channel may be
* connected, by invoking its {@link #connect connect} method, in order to
* avoid the overhead of the security checks are otherwise performed as part of
* every send and receive operation. A datagram channel must be connected in
@ -59,11 +52,57 @@ import java.nio.channels.spi.*;
* disconnected or closed. Whether or not a datagram channel is connected may
* be determined by invoking its {@link #isConnected isConnected} method.
*
* <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
* setOption} method. Datagram channels support the following options:
* <blockquote>
* <table border>
* <tr>
* <th>Option Name</th>
* <th>Description</th>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
* <td> The size of the socket send buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
* <td> The size of the socket receive buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
* <td> Re-use address </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} </td>
* <td> Allow transmission of broadcast datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_TOS IP_TOS} </td>
* <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} </td>
* <td> The network interface for Internet Protocol (IP) multicast datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_TTL
* IP_MULTICAST_TTL} </td>
* <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast
* datagrams </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#IP_MULTICAST_LOOP
* IP_MULTICAST_LOOP} </td>
* <td> Loopback for Internet Protocol (IP) multicast datagrams </td>
* </tr>
* </table>
* </blockquote>
* Additional (implementation specific) options may also be supported.
*
* <p> Datagram 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. </p>
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
@ -71,7 +110,7 @@ import java.nio.channels.spi.*;
public abstract class DatagramChannel
extends AbstractSelectableChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
{
/**
@ -88,7 +127,13 @@ public abstract class DatagramChannel
* java.nio.channels.spi.SelectorProvider#openDatagramChannel()
* openDatagramChannel} method of the system-wide default {@link
* java.nio.channels.spi.SelectorProvider} object. The channel will not be
* connected. </p>
* connected.
*
* <p> The {@link ProtocolFamily ProtocolFamily} of the channel's socket
* is platform (and possibly configuration) dependent and therefore unspecified.
* The {@link #open(ProtocolFamily) open} allows the protocol family to be
* selected when opening a datagram channel, and should be used to open
* datagram channels that are intended for Internet Protocol multicasting.
*
* @return A new datagram channel
*
@ -99,6 +144,39 @@ public abstract class DatagramChannel
return SelectorProvider.provider().openDatagramChannel();
}
/**
* Opens a datagram channel.
*
* <p> The {@code family} parameter is used to specify the {@link
* ProtocolFamily}. If the datagram channel is to be used for IP multicasing
* then this should correspond to the address type of the multicast groups
* that this channel will join.
*
* <p> The new channel is created by invoking the {@link
* java.nio.channels.spi.SelectorProvider#openDatagramChannel(ProtocolFamily)
* openDatagramChannel} method of the system-wide default {@link
* java.nio.channels.spi.SelectorProvider} object. The channel will not be
* connected.
*
* @param family
* The protocol family
*
* @return A new datagram channel
*
* @throws UnsupportedOperationException
* If the specified protocol family is not supported. For example,
* suppose the parameter is specified as {@link
* java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
* but IPv6 is not enabled on the platform.
* @throws IOException
* If an I/O error occurs
*
* @since 1.7
*/
public static DatagramChannel open(ProtocolFamily family) throws IOException {
return SelectorProvider.provider().openDatagramChannel(family);
}
/**
* Returns an operation set identifying this channel's supported
* operations.
@ -117,6 +195,32 @@ public abstract class DatagramChannel
// -- Socket-specific operations --
/**
* @throws AlreadyBoundException {@inheritDoc}
* @throws UnsupportedAddressTypeException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
* @throws SecurityException
* If a security manager has been installed and its {@link
* SecurityManager#checkListen checkListen} method denies the
* operation
*
* @since 1.7
*/
public abstract DatagramChannel bind(SocketAddress local)
throws IOException;
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
*
* @since 1.7
*/
public abstract <T> DatagramChannel setOption(SocketOption<T> name, T value)
throws IOException;
/**
* Retrieves a datagram socket associated with this channel.
*
@ -128,10 +232,10 @@ public abstract class DatagramChannel
public abstract DatagramSocket socket();
/**
* Tells whether or not this channel's socket is connected. </p>
* Tells whether or not this channel's socket is connected.
*
* @return <tt>true</tt> if, and only if, this channel's socket
* is connected
* @return {@code true} if, and only if, this channel's socket
* is {@link #isOpen open} and connected
*/
public abstract boolean isConnected();
@ -206,6 +310,19 @@ public abstract class DatagramChannel
*/
public abstract DatagramChannel disconnect() throws IOException;
/**
* Returns the remote address to which this channel's socket is connected.
*
* @return The remote address; {@code null} if the channel is not {@link
* #isOpen open} or the channel's socket is not connected
*
* @throws IOException
* If an I/O error occurs
*
* @since 1.7
*/
public abstract SocketAddress getConnectedAddress() throws IOException;
/**
* Receives a datagram via this channel.
*

View File

@ -0,0 +1,183 @@
/*
* Copyright 2007-2008 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 java.nio.channels;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.io.IOException;
import java.util.List;
/**
* A token representing the membership of an Internet Protocol (IP) multicast
* group.
*
* <p> A membership key may represent a membership to receive all datagrams sent
* to the group, or it may be <em>source-specific</em>, meaning that it
* represents a membership that receives only datagrams from a specific source
* address. Whether or not a membership key is source-specific may be determined
* by invoking its {@link #getSourceAddress() getSourceAddress} method.
*
* <p> A membership key is valid upon creation and remains valid until the
* membership is dropped by invoking the {@link #drop() drop} method, or
* the channel is closed. The validity of the membership key may be tested
* by invoking its {@link #isValid() isValid} method.
*
* <p> Where a membership key is not source-specific and the underlying operation
* system supports source filtering, then the {@link #block block} and {@link
* #unblock unblock} methods can be used to block or unblock multicast datagrams
* from particular source addresses.
*
* @see MulticastChannel
*
* @since 1.7
*/
public abstract class MembershipKey {
/**
* Initializes a new instance of this class.
*/
protected MembershipKey() {
}
/**
* Tells whether or not this membership is valid.
*
* <p> A multicast group membership is valid upon creation and remains
* valid until the membership is dropped by invoking the {@link #drop() drop}
* method, or the channel is closed.
*
* @return {@code true} if this membership key is valid, {@code false}
* otherwise
*/
public abstract boolean isValid();
/**
* Drop membership.
*
* <p> If the membership key represents a membership to receive all datagrams
* then the membership is dropped and the channel will no longer receive any
* datagrams sent to the group. If the membership key is source-specific
* then the channel will no longer receive datagrams sent to the group from
* that source address.
*
* <p> After membership is dropped it may still be possible to receive
* datagrams sent to the group. This can arise when datagrams are waiting to
* be received in the socket's receive buffer. After membership is dropped
* then the channel may {@link MulticastChannel#join join} the group again
* in which case a new membership key is returned.
*
* <p> Upon return, this membership object will be {@link #isValid() invalid}.
* If the multicast group membership is already invalid then invoking this
* method has no effect. Once a multicast group membership is invalid,
* it remains invalid forever.
*
* @throws IOException
* If an I/O error occurs
*/
public abstract void drop() throws IOException;
/**
* Block multicast datagrams from the given source address.
*
* <p> If this membership key is not source-specific, and the underlying
* operating system supports source filtering, then this method blocks
* multicast datagrams from the given source address. If the given source
* address is already blocked then this method has no effect.
* After a source address is blocked it may still be possible to receive
* datagams from that source. This can arise when datagrams are waiting to
* be received in the socket's receive buffer.
*
* @param source
* The source address to block
*
* @return This membership key
*
* @throws IllegalArgumentException
* If the {@code source} parameter is not a unicast address or
* is not the same address type as the multicast group
* @throws IllegalStateException
* If this membership key is source-specific or is no longer valid
* @throws UnsupportedOperationException
* If the underlying operating system does not support source
* filtering
* @throws IOException
* If an I/O error occurs
*/
public abstract MembershipKey block(InetAddress source) throws IOException;
/**
* Unblock multicast datagrams from the given source address that was
* previously blocked using the {@link #block(InetAddress) block} method.
*
* @param source
* The source address to unblock
*
* @return This membership key
*
* @throws IllegalStateException
* If the given source address is not currently blocked or the
* membership key is no longer valid
* @throws IOException
* If an I/O error occurs
*/
public abstract MembershipKey unblock(InetAddress source) throws IOException;
/**
* Returns the channel for which this membership key was created. This
* method will continue to return the channel even after the membership
* becomes {@link #isValid invalid}.
*
* @return the channel
*/
public abstract MulticastChannel getChannel();
/**
* Returns the multicast group for which this membership key was created.
* This method will continue to return the group even after the membership
* becomes {@link #isValid invalid}.
*
* @return the multicast group
*/
public abstract InetAddress getGroup();
/**
* Returns the network interface for which this membership key was created.
* This method will continue to return the network interface even after the
* membership becomes {@link #isValid invalid}.
*
* @return the network interface
*/
public abstract NetworkInterface getNetworkInterface();
/**
* Returns the source address if this membership key is source-specific,
* or {@code null} if this membership is not source-specific.
*
* @return The source address if this membership key is source-specific,
* otherwise {@code null}
*/
public abstract InetAddress getSourceAddress();
}

View File

@ -0,0 +1,211 @@
/*
* Copyright 2007-2008 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 java.nio.channels;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.io.IOException;
import java.net.ProtocolFamily; // javadoc
import java.net.StandardProtocolFamily; // javadoc
import java.net.StandardSocketOption; // javadoc
/**
* A network channel that supports Internet Protocol (IP) multicasting.
*
* <p> IP multicasting is the transmission of IP datagrams to members of
* a <em>group</em> that is zero or more hosts identified by a single destination
* address.
*
* <p> In the case of a channel to an {@link StandardProtocolFamily#INET IPv4} socket,
* the underlying operating system supports <a href="http://www.ietf.org/rfc/rfc2236.txt">
* <i>RFC&nbsp;2236: Internet Group Management Protocol, Version 2 (IGMPv2)</i></a>.
* It may optionally support source filtering as specified by <a
* href="http://www.ietf.org/rfc/rfc3376.txt"> <i>RFC&nbsp;3376: Internet Group
* Management Protocol, Version 3 (IGMPv3)</i></a>.
* For channels to an {@link StandardProtocolFamily#INET6 IPv6} socket, the equivalent
* standards are <a href="http://www.ietf.org/rfc/rfc2710.txt"> <i>RFC&nbsp;2710:
* Multicast Listener Discovery (MLD) for IPv6</i></a> and <a
* href="http://www.ietf.org/rfc/rfc3810.txt"> <i>RFC&nbsp;3810: Multicast Listener
* Discovery Version 2 (MLDv2) for IPv6</i></a>.
*
* <p> The {@link #join(InetAddress,NetworkInterface)} method is used to
* join a group and receive all multicast datagrams sent to the group. A channel
* may join several multicast groups and may join the same group on several
* {@link NetworkInterface interfaces}. Membership is dropped by invoking the {@link
* MembershipKey#drop drop} method on the returned {@link MembershipKey}. If the
* underlying platform supports source filtering then the {@link MembershipKey#block
* block} and {@link MembershipKey#unblock unblock} methods can be used to block or
* unblock multicast datagrams from particular source addresses.
*
* <p> The {@link #join(InetAddress,NetworkInterface,InetAddress)} method
* is used to begin receiving datagrams sent to a group whose source address matches
* a given source address. This method throws {@link UnsupportedOperationException}
* if the underlying platform does not support source filtering. Membership is
* <em>cumulative</em> and this method may be invoked again with the same group
* and interface to allow receiving datagrams from other source addresses. The
* method returns a {@link MembershipKey} that represents membership to receive
* datagrams from the given source address. Invoking the key's {@link
* MembershipKey#drop drop} method drops membership so that datagrams from the
* source address can no longer be received.
*
* <h4>Platform dependencies</h4>
*
* The multicast implementation is intended to map directly to the native
* multicasting facility. Consequently, the following items should be considered
* when developing an application that receives IP multicast datagrams:
*
* <ol>
*
* <li><p> The creation of the channel should specify the {@link ProtocolFamily}
* that corresponds to the address type of the multicast groups that the channel
* will join. There is no guarantee that a channel to a socket in one protocol
* family can join and receive multicast datagrams when the address of the
* multicast group corresponds to another protocol family. For example, it is
* implementation specific if a channel to an {@link StandardProtocolFamily#INET6 IPv6}
* socket can join an {@link StandardProtocolFamily#INET IPv4} multicast group and receive
* multicast datagrams sent to the group. </p></li>
*
* <li><p> The channel's socket should be bound to the {@link
* InetAddress#isAnyLocalAddress wildcard} address. If the socket is bound to
* a specific address, rather than the wildcard address then it is implementation
* specific if multicast datagrams are received by the socket. </p></li>
*
* <li><p> The {@link StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} option should be
* enabled prior to {@link NetworkChannel#bind binding} the socket. This is
* required to allow multiple members of the group to bind to the same
* address. </p></li>
*
* </ol>
*
* <p> <b>Usage Example:</b>
* <pre>
* // join multicast group on this interface, and also use this
* // interface for outgoing multicast datagrams
* NetworkInterface ni = NetworkInterface.getByName("hme0");
*
* DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
* .setOption(StandardSocketOption.SO_REUSEADDR, true)
* .bind(new InetSocketAddress(5000))
* .setOption(StandardSocketOption.IP_MULTICAST_IF, ni);
*
* InetAddress group = InetAddress.getByName("225.4.5.6");
*
* MembershipKey key = dc.join(group, ni);
* </pre>
*
* @since 1.7
*/
public interface MulticastChannel
extends NetworkChannel
{
/**
* Joins a multicast group to begin receiving all datagrams sent to the group,
* returning a membership key.
*
* <p> If this channel is currently a member of the group on the given
* interface to receive all datagrams then the membership key, representing
* that membership, is returned. Otherwise this channel joins the group and
* the resulting new membership key is returned. The resulting membership key
* is not {@link MembershipKey#getSourceAddress source-specific}.
*
* <p> A multicast channel may join several multicast groups, including
* the same group on more than one interface. An implementation may impose a
* limit on the number of groups that may be joined at the same time.
*
* @param group
* The multicast address to join
* @param interf
* The network interface on which to join the group
*
* @return The membership key
*
* @throws IllegalArgumentException
* If the group parameter is not a {@link InetAddress#isMulticastAddress
* multicast} address, or the group parameter is an address type
* that is not supported by this channel
* @throws IllegalStateException
* If the channel already has source-specific membership of the
* group on the interface
* @throws ClosedChannelException
* If this channel is closed
* @throws IOException
* If an I/O error occurs
* @throws SecurityException
* If a security manager is set, and its
* {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
* method denies access to the multiast group
*/
MembershipKey join(InetAddress group, NetworkInterface interf)
throws IOException;
/**
* Joins a multicast group to begin receiving datagrams sent to the group
* from a given source address.
*
* <p> If this channel is currently a member of the group on the given
* interface to receive datagrams from the given source address then the
* membership key, representing that membership, is returned. Otherwise this
* channel joins the group and the resulting new membership key is returned.
* The resulting membership key is {@link MembershipKey#getSourceAddress
* source-specific}.
*
* <p> Membership is <em>cumulative</em> and this method may be invoked
* again with the same group and interface to allow receiving datagrams sent
* by other source addresses to the group.
*
* @param group
* The multicast address to join
* @param interf
* The network interface on which to join the group
* @param source
* The source address
*
* @return The membership key
*
* @throws IllegalArgumentException
* If the group parameter is not a {@link
* InetAddress#isMulticastAddress multicast} address, the
* source parameter is not a unicast address, the group
* parameter is an address type that is not supported by this channel,
* or the source parameter is not the same address type as the group
* @throws IllegalStateException
* If the channel is currently a member of the group on the given
* interface to receive all datagrams
* @throws UnsupportedOperationException
* If the underlying operation system does not support source filtering
* @throws ClosedChannelException
* If this channel is closed
* @throws IOException
* If an I/O error occurs
* @throws SecurityException
* If a security manager is set, and its
* {@link SecurityManager#checkMulticast(InetAddress) checkMulticast}
* method denies access to the multiast group
*/
MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source)
throws IOException;
}

View File

@ -0,0 +1,158 @@
/*
* Copyright 2007-2008 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 java.nio.channels;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.util.Set;
import java.io.IOException;
/**
* A channel to a network socket.
*
* <p> A channel that implements this interface is a channel to a network
* socket. The {@link #bind(SocketAddress) bind} method is used to bind the
* socket to a local {@link SocketAddress address}, the {@link #getLocalAddress()
* getLocalAddress} method returns the address that the socket is bound to, and
* the {@link #setOption(SocketOption,Object) setOption} and {@link
* #getOption(SocketOption) getOption} methods are used to set and query socket
* options. An implementation of this interface should specify the socket options
* that it supports.
*
* <p> The {@link #bind bind} and {@link #setOption setOption} methods that do
* not otherwise have a value to return are specified to return the network
* channel upon which they are invoked. This allows method invocations to be
* chained. Implementations of this interface should specialize the return type
* so that method invocations on the implementation class can be chained.
*
* @since 1.7
*/
public interface NetworkChannel
extends Channel
{
/**
* Binds the channel's socket to a local address.
*
* <p> This method is used to establish an association between the socket and
* a local address. Once an association is established then the socket remains
* bound until the channel is closed. If the {@code local} parameter has the
* value {@code null} then the socket will be bound to an address that is
* assigned automatically.
*
* @param local
* The address to bind the socket, or {@code null} to bind the socket
* to an automatically assigned socket address
*
* @return This channel
*
* @throws AlreadyBoundException
* If the socket is already bound
* @throws UnsupportedAddressTypeException
* If the type of the given address is not supported
* @throws ClosedChannelException
* If the channel is closed
* @throws IOException
* If some other I/O error occurs
* @throws SecurityException
* If a security manager is installed and it denies an unspecified
* permission. An implementation of this interface should specify
* any required permissions.
*
* @see #getLocalAddress
*/
NetworkChannel bind(SocketAddress local) throws IOException;
/**
* Returns the socket address that this channel's socket is bound to, or
* {@code null} if the socket is not bound.
*
* <p> Where the channel is {@link #bind bound} to an Internet Protocol
* socket address then the return value from this method is of type {@link
* java.net.InetSocketAddress}.
*
* @return The socket address that the socket is bound to, or {@code null}
* if the channel is not {@link #isOpen open} or the channel's socket
* is not bound
*
* @throws IOException
* If an I/O error occurs
*/
SocketAddress getLocalAddress() 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 IllegalArgumentException
* If the socket option is not supported by this channel, or
* 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 java.net.StandardSocketOption
*/
<T> NetworkChannel setOption(SocketOption<T> name, T value) 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 IllegalArgumentException
* 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 java.net.StandardSocketOption
*/
<T> T getOption(SocketOption<T> name) 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
*/
Set<SocketOption<?>> options();
}

View File

@ -27,33 +27,44 @@ package java.nio.channels;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.channels.spi.*;
/**
* A selectable channel for stream-oriented listening sockets.
*
* <p> Server-socket channels are not a complete abstraction of listening
* network sockets. Binding and the manipulation of socket options must be
* done through an associated {@link java.net.ServerSocket} object obtained by
* invoking the {@link #socket() socket} method. It is not possible to create
* a channel for an arbitrary, pre-existing server socket, nor is it possible
* to specify the {@link java.net.SocketImpl} object to be used by a server
* socket associated with a server-socket channel.
*
* <p> A server-socket channel is created by invoking the {@link #open() open}
* method of this class. A newly-created server-socket channel is open but not
* yet bound. An attempt to invoke the {@link #accept() accept} method of an
* unbound server-socket channel will cause a {@link NotYetBoundException} to
* be thrown. A server-socket channel can be bound by invoking one of the
* {@link java.net.ServerSocket#bind(java.net.SocketAddress,int) bind} methods
* of an associated server socket.
* method of this class. It is not possible to create a channel for an arbitrary,
* pre-existing {@link ServerSocket}. A newly-created server-socket channel is
* open but not yet bound. An attempt to invoke the {@link #accept() accept}
* method of an unbound server-socket channel will cause a {@link NotYetBoundException}
* to be thrown. A server-socket 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(SocketOption,Object)
* setOption} method. Server-socket channels support the following options:
* <blockquote>
* <table border>
* <tr>
* <th>Option Name</th>
* <th>Description</th>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
* <td> The size of the socket receive buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
* <td> Re-use address </td>
* </tr>
* </table>
* </blockquote>
* Additional (implementation specific) options may also be supported.
*
* <p> Server-socket channels are safe for use by multiple concurrent threads.
* </p>
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
@ -61,6 +72,7 @@ import java.nio.channels.spi.*;
public abstract class ServerSocketChannel
extends AbstractSelectableChannel
implements NetworkChannel
{
/**
@ -109,6 +121,89 @@ public abstract class ServerSocketChannel
// -- ServerSocket-specific operations --
/**
* Binds the channel's socket to a local address and configures the socket
* to listen for connections.
*
* <p> An invocation of this method is equivalent to the following:
* <blockquote><pre>
* bind(local, 0);
* </pre></blockquote>
*
* @param local
* The local address to bind the socket, or {@code null} to bind
* to an automatically assigned socket address
*
* @return This channel
*
* @throws AlreadyBoundException {@inheritDoc}
* @throws UnsupportedAddressTypeException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
* @throws SecurityException
* If a security manager has been installed and its {@link
* SecurityManager#checkListen checkListen} method denies the
* operation
*
* @since 1.7
*/
public final ServerSocketChannel 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 connections.
*
* <p> This method is used to establish an association between the socket and
* a local address. Once an association is established then the socket remains
* bound until the channel is closed.
*
* <p> The {@code backlog} parameter is the maximum number of pending
* connections on the socket. Its exact semantics are implementation specific.
* In particular, an implementation may impose a maximum length or may choose
* to ignore the parameter altogther. If the {@code backlog} parameter has
* the value {@code 0}, or a negative value, then an implementation specific
* default is used.
*
* @param local
* The address to bind the socket, or {@code null} to bind to an
* automatically assigned socket address
* @param backlog
* The maximum number of pending connections
*
* @return This channel
*
* @throws AlreadyBoundException
* If the socket is already bound
* @throws UnsupportedAddressTypeException
* If the type of the given address is not supported
* @throws ClosedChannelException
* If this channel is closed
* @throws IOException
* If some other I/O error occurs
* @throws SecurityException
* If a security manager has been installed and its {@link
* SecurityManager#checkListen checkListen} method denies the
* operation
*
* @since 1.7
*/
public abstract ServerSocketChannel bind(SocketAddress local, int backlog)
throws IOException;
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
*
* @since 1.7
*/
public abstract <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
throws IOException;
/**
* Retrieves a server socket associated with this channel.
*

View File

@ -27,24 +27,17 @@ package java.nio.channels;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.spi.*;
/**
* A selectable channel for stream-oriented connecting sockets.
*
* <p> Socket channels are not a complete abstraction of connecting network
* sockets. Binding, shutdown, and the manipulation of socket options must be
* done through an associated {@link java.net.Socket} object obtained by
* invoking the {@link #socket() socket} method. It is not possible to create
* a channel for an arbitrary, pre-existing socket, nor is it possible to
* specify the {@link java.net.SocketImpl} object to be used by a socket
* associated with a socket channel.
*
* <p> A socket channel is created by invoking one of the {@link #open open}
* methods of this class. A newly-created socket channel is open but not yet
* methods of this class. It is not possible to create a channel for an arbitrary,
* pre-existing socket. A newly-created socket channel is open but not yet
* connected. An attempt to invoke an I/O operation upon an unconnected
* channel will cause a {@link NotYetConnectedException} to be thrown. A
* socket channel can be connected by invoking its {@link #connect connect}
@ -59,16 +52,6 @@ import java.nio.channels.spi.*;
* Whether or not a connection operation is in progress may be determined by
* invoking the {@link #isConnectionPending isConnectionPending} method.
*
* <p> The input and output sides of a socket channel may independently be
* <i>shut down</i> without actually closing the channel. Shutting down the
* input side of a channel by invoking the {@link java.net.Socket#shutdownInput
* shutdownInput} method of an associated socket object will cause further
* reads on the channel to return <tt>-1</tt>, the end-of-stream indication.
* Shutting down the output side of the channel by invoking the {@link
* java.net.Socket#shutdownOutput shutdownOutput} method of an associated
* socket object will cause further writes on the channel to throw a {@link
* ClosedChannelException}.
*
* <p> Socket channels support <i>asynchronous shutdown,</i> which is similar
* to the asynchronous close operation specified in the {@link Channel} class.
* If the input side of a socket is shut down by one thread while another
@ -79,6 +62,43 @@ import java.nio.channels.spi.*;
* channel, then the blocked thread will receive an {@link
* AsynchronousCloseException}.
*
* <p> Socket options are configured using the {@link #setOption(SocketOption,Object)
* setOption} method. Socket channels support the following options:
* <blockquote>
* <table border>
* <tr>
* <th>Option Name</th>
* <th>Description</th>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} </td>
* <td> The size of the socket send buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} </td>
* <td> The size of the socket receive buffer </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} </td>
* <td> Keep connection alive </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} </td>
* <td> Re-use address </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#SO_LINGER SO_LINGER} </td>
* <td> Linger on close if data is present (when configured in blocking mode
* only) </td>
* </tr>
* <tr>
* <td> {@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} </td>
* <td> Disable the Nagle algorithm </td>
* </tr>
* </table>
* </blockquote>
* Additional (implementation specific) options may also be supported.
*
* <p> Socket 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
@ -87,7 +107,6 @@ import java.nio.channels.spi.*;
* or write operation while an invocation of one of these methods is in
* progress will block until that invocation is complete. </p>
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
@ -95,7 +114,7 @@ import java.nio.channels.spi.*;
public abstract class SocketChannel
extends AbstractSelectableChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel
{
/**
@ -191,6 +210,73 @@ public abstract class SocketChannel
// -- Socket-specific operations --
/**
* @throws ConnectionPendingException
* If a non-blocking connection operation is already in progress on
* this channel
* @throws AlreadyBoundException {@inheritDoc}
* @throws UnsupportedAddressTypeException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
*
* @since 1.7
*/
@Override
public abstract SocketChannel bind(SocketAddress local)
throws IOException;
/**
* @throws IllegalArgumentException {@inheritDoc}
* @throws ClosedChannelException {@inheritDoc}
* @throws IOException {@inheritDoc}
*
* @since 1.7
*/
@Override
public abstract <T> SocketChannel setOption(SocketOption<T> name, T value)
throws IOException;
/**
* Shutdown the connection for reading without closing the channel.
*
* <p> Once shutdown for reading then further reads on the channel will
* return {@code -1}, the end-of-stream indication. If the input side of the
* connection is already shutdown then invoking this method has no effect.
*
* @return The channel
*
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ClosedChannelException
* If this channel is closed
* @throws IOException
* If some other I/O error occurs
*
* @since 1.7
*/
public abstract SocketChannel shutdownInput() throws IOException;
/**
* Shutdown the connection for writing without closing the channel.
*
* <p> Once shutdown for writing then further attempts to write to the
* channel will throw {@link ClosedChannelException}. If the output side of
* the connection is already shutdown then invoking this method has no
* effect.
*
* @return The channel
*
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ClosedChannelException
* If this channel is closed
* @throws IOException
* If some other I/O error occurs
*
* @since 1.7
*/
public abstract SocketChannel shutdownOutput() throws IOException;
/**
* Retrieves a socket associated with this channel.
*
@ -202,10 +288,10 @@ public abstract class SocketChannel
public abstract Socket socket();
/**
* Tells whether or not this channel's network socket is connected. </p>
* Tells whether or not this channel's network socket is connected.
*
* @return <tt>true</tt> if, and only if, this channel's network socket
* is connected
* is {@link #isOpen open} and connected
*/
public abstract boolean isConnected();
@ -339,6 +425,22 @@ public abstract class SocketChannel
*/
public abstract boolean finishConnect() throws IOException;
/**
* Returns the remote address to which this channel's socket is connected.
*
* <p> Where the channel is bound and connected to an Internet Protocol
* socket address then the return value from this method is of type {@link
* java.net.InetSocketAddress}.
*
* @return The remote address; {@code null} if the channel is not {@link
* #isOpen open} or the channel's socket is not connected
*
* @throws IOException
* If an I/O error occurs
*
* @since 1.7
*/
public abstract SocketAddress getConnectedAddress() throws IOException;
// -- ByteChannel operations --

View File

@ -146,3 +146,14 @@ gen OverlappingFileLockException "
* virtual machine, or when another thread is already waiting to lock an
* overlapping region of the same file." \
2047812138163068433L
SINCE=1.7
SUPER=IllegalStateException
gen AlreadyBoundException "
* Unchecked exception thrown when an attempt is made to bind the socket a
* network oriented channel that is already bound." \
6796072983322737592L

View File

@ -0,0 +1,231 @@
/*
* Copyright 2001-2005 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.
*/
/**
* Defines channels, which represent connections to entities that are capable of
* performing I/O operations, such as files and sockets; defines selectors, for
* multiplexed, non-blocking I/O operations.
*
* <a name="channels"></a>
*
* <blockquote><table cellspacing=1 cellpadding=0 summary="Lists channels and their descriptions">
* <tr><th><p align="left">Channels</p></th><th><p align="left">Description</p></th></tr>
* <tr><td valign=top><tt><i>{@link java.nio.channels.Channel}</i></tt></td>
* <td>A nexus for I/O operations</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ReadableByteChannel}</i></tt></td>
* <td>Can read into a buffer</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.ScatteringByteChannel}&nbsp;&nbsp;</i></tt></td>
* <td>Can read into a sequence of&nbsp;buffers</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.WritableByteChannel}</i></tt></td>
* <td>Can write from a buffer</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.GatheringByteChannel}</i></tt></td>
* <td>Can write from a sequence of&nbsp;buffers</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ByteChannel}</i></tt></td>
* <td>Can read/write to/from a&nbsp;buffer</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.SeekableByteChannel}</i></tt></td>
* <td>A {@code ByteChannel} connected to an entity that contains a variable-length sequence of bytes</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.NetworkChannel}</i></tt></td>
* <td>A channel to a network socket</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.MulticastChannel}</i></tt></td>
* <td>Can join Internet Protocol (IP) multicast groups</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.Channels}</tt></td>
* <td>Utility methods for channel/stream interoperation</td></tr>
* </table></blockquote>
*
* <p> A <i>channel</i> represents an open connection to an entity such as a
* hardware device, a file, a network socket, or a program component that is
* capable of performing one or more distinct I/O operations, for example reading
* or writing. As specified in the {@link java.nio.channels.Channel} interface,
* channels are either open or closed, and they are both <i>asynchronously
* closeable</i> and <i>interruptible</i>.
*
* <p> The {@link java.nio.channels.Channel} interface is extended by several
* other interfaces.
*
* <p> The {@link java.nio.channels.ReadableByteChannel} interface specifies a
* {@link java.nio.channels.ReadableByteChannel#read read} method that reads bytes
* from the channel into a buffer; similarly, the {@link
* java.nio.channels.WritableByteChannel} interface specifies a {@link
* java.nio.channels.WritableByteChannel#write write} method that writes bytes
* from a buffer to the channel. The {@link java.nio.channels.ByteChannel}
* interface unifies these two interfaces for the common case of channels that can
* both read and write bytes. The {@link java.nio.channels.SeekableByteChannel}
* interface extends the {@code ByteChannel} interface with methods to {@link
* java.nio.channels.SeekableByteChannel#position() query} and {@link
* java.nio.channels.SeekableByteChannel#position(long) modify} the channel's
* current position, and its {@link java.nio.channels.SeekableByteChannel#size
* size}.
*
* <p> The {@link java.nio.channels.ScatteringByteChannel} and {@link
* java.nio.channels.GatheringByteChannel} interfaces extend the {@link
* java.nio.channels.ReadableByteChannel} and {@link
* java.nio.channels.WritableByteChannel} interfaces, respectively, adding {@link
* java.nio.channels.ScatteringByteChannel#read read} and {@link
* java.nio.channels.GatheringByteChannel#write write} methods that take a
* sequence of buffers rather than a single buffer.
*
* <p> The {@link java.nio.channels.NetworkChannel} interface specifies methods
* to {@link java.nio.channels.NetworkChannel#bind bind} the channel's socket,
* obtain the address to which the socket is bound, and methods to {@link
* java.nio.channels.NetworkChannel#getOption get} and {@link
* java.nio.channels.NetworkChannel#setOption set} socket options. The {@link
* java.nio.channels.MulticastChannel} interface specifies methods to join
* Internet Protocol (IP) multicast groups.
*
* <p> The {@link java.nio.channels.Channels} utility class defines static methods
* that support the interoperation of the stream classes of the <tt>{@link
* java.io}</tt> package with the channel classes of this package. An appropriate
* channel can be constructed from an {@link java.io.InputStream} or an {@link
* java.io.OutputStream}, and conversely an {@link java.io.InputStream} or an
* {@link java.io.OutputStream} can be constructed from a channel. A {@link
* java.io.Reader} can be constructed that uses a given charset to decode bytes
* from a given readable byte channel, and conversely a {@link java.io.Writer} can
* be constructed that uses a given charset to encode characters into bytes and
* write them to a given writable byte channel.
*
* <blockquote><table cellspacing=1 cellpadding=0 summary="Lists file channels and their descriptions">
* <tr><th><p align="left">File channels</p></th><th><p align="left">Description</p></th></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.FileChannel}</tt></td>
* <td>Reads, writes, maps, and manipulates files</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.FileLock}</tt></td>
* <td>A lock on a (region of a) file</td></tr>
* <tr><td valign=top><tt>{@link java.nio.MappedByteBuffer}/{@link java.nio.MappedBigByteBuffer}&nbsp;&nbsp;</tt></td>
* <td>A direct byte buffer or big byte buffer mapped to a region of a&nbsp;file</td></tr>
* </table></blockquote>
*
* <p> The {@link java.nio.channels.FileChannel} class supports the usual
* operations of reading bytes from, and writing bytes to, a channel connected to
* a file, as well as those of querying and modifying the current file position
* and truncating the file to a specific size. It defines methods for acquiring
* locks on the whole file or on a specific region of a file; these methods return
* instances of the {@link java.nio.channels.FileLock} class. Finally, it defines
* methods for forcing updates to the file to be written to the storage device that
* contains it, for efficiently transferring bytes between the file and other
* channels, and for mapping a region of the file directly into memory.
*
* <p> A {@code FileChannel} is created by invoking one of its static {@link
* java.nio.channels.FileChannel#open open} methods, or by invoking the {@code
* getChannel} method of a {@link java.io.FileInputStream}, {@link
* java.io.FileOutputStream}, or {@link java.io.RandomAccessFile} to return a
* file channel connected to the same underlying file as the <tt>{@link java.io}</tt>
* class.
*
* <a name="multiplex"></a>
* <blockquote><table cellspacing=1 cellpadding=0 summary="Lists multiplexed, non-blocking channels and their descriptions">
* <tr><th><p align="left">Multiplexed, non-blocking I/O</p></th><th><p align="left">Description</p></th></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.SelectableChannel}</tt></td>
* <td>A channel that can be multiplexed</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.DatagramChannel}</tt></td>
* <td>A channel to a datagram-oriented socket</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SinkChannel}</tt></td>
* <td>The write end of a pipe</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SourceChannel}</tt></td>
* <td>The read end of a pipe</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.ServerSocketChannel}&nbsp;&nbsp;</tt></td>
* <td>A channel to a stream-oriented listening socket</td></tr>
* <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.SocketChannel}</tt></td>
* <td>A channel for a stream-oriented connecting socket</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.Selector}</tt></td>
* <td>A multiplexor of selectable channels</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.SelectionKey}</tt></td>
* <td>A token representing the registration <br> of a channel
* with&nbsp;a&nbsp;selector</td></tr>
* <tr><td valign=top><tt>{@link java.nio.channels.Pipe}</tt></td>
* <td>Two channels that form a unidirectional&nbsp;pipe</td></tr>
* </table></blockquote>
*
* <p> Multiplexed, non-blocking I/O, which is much more scalable than
* thread-oriented, blocking I/O, is provided by <i>selectors</i>, <i>selectable
* channels</i>, and <i>selection keys</i>.
*
* <p> A <a href="Selector.html"><i>selector</i></a> is a multiplexor of <a
* href="SelectableChannel.html"><i>selectable channels</i></a>, which in turn are
* a special type of channel that can be put into <a
* href="SelectableChannel.html#bm"><i>non-blocking mode</i></a>. To perform
* multiplexed I/O operations, one or more selectable channels are first created,
* put into non-blocking mode, and {@link
* java.nio.channels.SelectableChannel#register <i>registered</i>}
* with a selector. Registering a channel specifies the set of I/O operations
* that will be tested for readiness by the selector, and returns a <a
* href="SelectionKey.html"><i>selection key</i></a> that represents the
* registration.
*
* <p> Once some channels have been registered with a selector, a <a
* href="Selector.html#selop"><i>selection operation</i></a> can be performed in
* order to discover which channels, if any, have become ready to perform one or
* more of the operations in which interest was previously declared. If a channel
* is ready then the key returned when it was registered will be added to the
* selector's <i>selected-key set</i>. The key set, and the keys within it, can
* be examined in order to determine the operations for which each channel is
* ready. From each key one can retrieve the corresponding channel in order to
* perform whatever I/O operations are required.
*
* <p> That a selection key indicates that its channel is ready for some operation
* is a hint, but not a guarantee, that such an operation can be performed by a
* thread without causing the thread to block. It is imperative that code that
* performs multiplexed I/O be written so as to ignore these hints when they prove
* to be incorrect.
*
* <p> This package defines selectable-channel classes corresponding to the {@link
* java.net.DatagramSocket}, {@link java.net.ServerSocket}, and {@link
* java.net.Socket} classes defined in the <tt>{@link java.net}</tt> package.
* Minor changes to these classes have been made in order to support sockets that
* are associated with channels. This package also defines a simple class that
* implements unidirectional pipes. In all cases, a new selectable channel is
* created by invoking the static <tt>open</tt> method of the corresponding class.
* If a channel needs an associated socket then a socket will be created as a side
* effect of this operation.
*
* <p> The implementation of selectors, selectable channels, and selection keys
* can be replaced by "plugging in" an alternative definition or instance of the
* {@link java.nio.channels.spi.SelectorProvider} class defined in the <tt>{@link
* java.nio.channels.spi}</tt> package. It is not expected that many developers
* will actually make use of this facility; it is provided primarily so that
* sophisticated users can take advantage of operating-system-specific
* I/O-multiplexing mechanisms when very high performance is required.
*
* <p> Much of the bookkeeping and synchronization required to implement the
* multiplexed-I/O abstractions is performed by the {@link
* java.nio.channels.spi.AbstractInterruptibleChannel}, {@link
* java.nio.channels.spi.AbstractSelectableChannel}, {@link
* java.nio.channels.spi.AbstractSelectionKey}, and {@link
* java.nio.channels.spi.AbstractSelector} classes in the <tt>{@link
* java.nio.channels.spi}</tt> package. When defining a custom selector provider,
* only the {@link java.nio.channels.spi.AbstractSelector} and {@link
* java.nio.channels.spi.AbstractSelectionKey} classes should be subclassed
* directly; custom channel classes should extend the appropriate {@link
* java.nio.channels.SelectableChannel} subclasses defined in this package.
*
* <hr width="80%">
* <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
* or method in any class or interface in this package will cause a {@link
* java.lang.NullPointerException NullPointerException} to be thrown.
*
* @since 1.4
* @author Mark Reinhold
* @author JSR-51 Expert Group
*/
package java.nio.channels;

View File

@ -1,222 +0,0 @@
<!--
Copyright 2001-2005 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.
-->
<!doctype html public "-//IETF//DTD HTML//EN">
<html>
<body bgcolor="white">
Defines channels, which represent connections to entities that are capable of
performing I/O operations, such as files and sockets; defines selectors, for
multiplexed, non-blocking I/O operations.
<a name="channels">
<blockquote><table cellspacing=1 cellpadding=0 summary="Lists channels and their descriptions">
<tr><th><p align="left">Channels</p></th><th><p align="left">Description</p></th></tr>
<tr><td valign=top><tt><i>{@link java.nio.channels.Channel}</i></tt></td>
<td>A nexus for I/O operations</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ReadableByteChannel}</i></tt></td>
<td>Can read into a buffer</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.ScatteringByteChannel}&nbsp;&nbsp;</i></tt></td>
<td>Can read into a sequence of&nbsp;buffers</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.WritableByteChannel}</i></tt></td>
<td>Can write from a buffer</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;<i>{@link java.nio.channels.GatheringByteChannel}</i></tt></td>
<td>Can write from a sequence of&nbsp;buffers</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ByteChannel}</i></tt></td>
<td>Can read/write to/from a&nbsp;buffer</td></tr>
<tr><td valign=top><tt>{@link java.nio.channels.Channels}</tt></td>
<td>Utility methods for channel/stream interoperation</td></tr>
</table></blockquote>
<p> A <i>channel</i> represents an open connection to an entity such as a
hardware device, a file, a network socket, or a program component that is
capable of performing one or more distinct I/O operations, for example reading
or writing. As specified in the {@link java.nio.channels.Channel} interface,
channels are either open or closed, and they are both <i>asynchronously
closeable</i> and <i>interruptible</i>.
<p> The {@link java.nio.channels.Channel} interface is extended by several
other interfaces, each of which specifies a new I/O operation.
<p> The {@link java.nio.channels.ReadableByteChannel} interface specifies a
{@link java.nio.channels.ReadableByteChannel#read read} method that reads bytes
from the channel into a buffer; similarly, the {@link
java.nio.channels.WritableByteChannel} interface specifies a {@link
java.nio.channels.WritableByteChannel#write write} method that writes bytes
from a buffer to the channel. The {@link java.nio.channels.ByteChannel}
interface unifies these two interfaces for the common case of channels that can
both read and write bytes.
<p> The {@link java.nio.channels.ScatteringByteChannel} and {@link
java.nio.channels.GatheringByteChannel} interfaces extend the {@link
java.nio.channels.ReadableByteChannel} and {@link
java.nio.channels.WritableByteChannel} interfaces, respectively, adding {@link
java.nio.channels.ScatteringByteChannel#read read} and {@link
java.nio.channels.GatheringByteChannel#write write} methods that take a
sequence of buffers rather than a single buffer.
<p> The {@link java.nio.channels.Channels} utility class defines static methods
that support the interoperation of the stream classes of the <tt>{@link
java.io}</tt> package with the channel classes of this package. An appropriate
channel can be constructed from an {@link java.io.InputStream} or an {@link
java.io.OutputStream}, and conversely an {@link java.io.InputStream} or an
{@link java.io.OutputStream} can be constructed from a channel. A {@link
java.io.Reader} can be constructed that uses a given charset to decode bytes
from a given readable byte channel, and conversely a {@link java.io.Writer} can
be constructed that uses a given charset to encode characters into bytes and
write them to a given writable byte channel.
<blockquote><table cellspacing=1 cellpadding=0 summary="Lists file channels and their descriptions">
<tr><th><p align="left">File channels</p></th><th><p align="left">Description</p></th></tr>
<tr><td valign=top><tt>{@link java.nio.channels.FileChannel}</tt></td>
<td>Reads, writes, maps, and manipulates files</td></tr>
<tr><td valign=top><tt>{@link java.nio.channels.FileLock}</tt></td>
<td>A lock on a (region of a) file</td></tr>
<tr><td valign=top><tt>{@link java.nio.MappedByteBuffer}&nbsp;&nbsp;</tt></td>
<td>A direct byte buffer mapped to a region of a&nbsp;file</td></tr>
</table></blockquote>
<p> The {@link java.nio.channels.FileChannel} class supports the usual
operations of reading bytes from, and writing bytes to, a channel connected to
a file, as well as those of querying and modifying the current file position
and truncating the file to a specific size. It defines methods for acquiring
locks on the whole file or on a specific region of a file; these methods return
instances of the {@link java.nio.channels.FileLock} class. Finally, it defines
methods for forcing updates to the file to be written to the storage device that
contains it, for efficiently transferring bytes between the file and other
channels, and for mapping a region of the file directly into memory. This last
operation creates an instance of the {@link java.nio.MappedByteBuffer}
class, which extends the {@link java.nio.ByteBuffer} class with several
file-related operations.
<p> A <tt>getChannel</tt> method has been added to each of the {@link
java.io.FileInputStream#getChannel FileInputStream}, {@link
java.io.FileOutputStream#getChannel FileOutputStream}, and {@link
java.io.RandomAccessFile#getChannel RandomAccessFile} classes of the <tt>{@link
java.io java.io}</tt> package. Invoking this method upon an instance of one of
these classes will return a file channel connected to the underlying file.
<a name="multiplex">
<blockquote><table cellspacing=1 cellpadding=0 summary="Lists multiplexed, non-blocking channels and their descriptions">
<tr><th><p align="left">Multiplexed, non-blocking I/O</p></th><th><p align="left">Description</p></th></tr>
<tr><td valign=top><tt>{@link java.nio.channels.SelectableChannel}</tt></td>
<td>A channel that can be multiplexed</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.DatagramChannel}</tt></td>
<td>A channel for a {@link java.net.DatagramSocket java.net.DatagramSocket}</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SinkChannel}</tt></td>
<td>The write end of a pipe</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.Pipe.SourceChannel}</tt></td>
<td>The read end of a pipe</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.ServerSocketChannel}&nbsp;&nbsp;</tt></td>
<td>A channel for a {@link java.net.ServerSocket java.net.ServerSocket}</td></tr>
<tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.SocketChannel}</tt></td>
<td>A channel for a {@link java.net.Socket java.net.Socket}</td></tr>
<tr><td valign=top><tt>{@link java.nio.channels.Selector}</tt></td>
<td>A multiplexor of selectable channels</td></tr>
<tr><td valign=top><tt>{@link java.nio.channels.SelectionKey}</tt></td>
<td>A token representing the registration <br> of a channel
with&nbsp;a&nbsp;selector</td></tr>
<tr><td valign=top><tt>{@link java.nio.channels.Pipe}</tt></td>
<td>Two channels that form a unidirectional&nbsp;pipe</td></tr>
</table></blockquote>
<p> Multiplexed, non-blocking I/O, which is much more scalable than
thread-oriented, blocking I/O, is provided by <i>selectors</i>, <i>selectable
channels</i>, and <i>selection keys</i>.
<p> A <a href="Selector.html"><i>selector</i></a> is a multiplexor of <a
href="SelectableChannel.html"><i>selectable channels</i></a>, which in turn are
a special type of channel that can be put into <a
href="SelectableChannel.html#bm"><i>non-blocking mode</i></a>. To perform
multiplexed I/O operations, one or more selectable channels are first created,
put into non-blocking mode, and {@link
java.nio.channels.SelectableChannel#register </code><i>registered</i><code>}
with a selector. Registering a channel specifies the set of I/O operations
that will be tested for readiness by the selector, and returns a <a
href="SelectionKey.html"><i>selection key</i></a> that represents the
registration.
<p> Once some channels have been registered with a selector, a <a
href="Selector.html#selop"><i>selection operation</i></a> can be performed in
order to discover which channels, if any, have become ready to perform one or
more of the operations in which interest was previously declared. If a channel
is ready then the key returned when it was registered will be added to the
selector's <i>selected-key set</i>. The key set, and the keys within it, can
be examined in order to determine the operations for which each channel is
ready. From each key one can retrieve the corresponding channel in order to
perform whatever I/O operations are required.
<p> That a selection key indicates that its channel is ready for some operation
is a hint, but not a guarantee, that such an operation can be performed by a
thread without causing the thread to block. It is imperative that code that
performs multiplexed I/O be written so as to ignore these hints when they prove
to be incorrect.
<p> This package defines selectable-channel classes corresponding to the {@link
java.net.DatagramSocket}, {@link java.net.ServerSocket}, and {@link
java.net.Socket} classes defined in the <tt>{@link java.net}</tt> package.
Minor changes to these classes have been made in order to support sockets that
are associated with channels. This package also defines a simple class that
implements unidirectional pipes. In all cases, a new selectable channel is
created by invoking the static <tt>open</tt> method of the corresponding class.
If a channel needs an associated socket then a socket will be created as a side
effect of this operation.
<p> The implementation of selectors, selectable channels, and selection keys
can be replaced by "plugging in" an alternative definition or instance of the
{@link java.nio.channels.spi.SelectorProvider} class defined in the <tt>{@link
java.nio.channels.spi}</tt> package. It is not expected that many developers
will actually make use of this facility; it is provided primarily so that
sophisticated users can take advantage of operating-system-specific
I/O-multiplexing mechanisms when very high performance is required.
<p> Much of the bookkeeping and synchronization required to implement the
multiplexed-I/O abstractions is performed by the {@link
java.nio.channels.spi.AbstractInterruptibleChannel}, {@link
java.nio.channels.spi.AbstractSelectableChannel}, {@link
java.nio.channels.spi.AbstractSelectionKey}, and {@link
java.nio.channels.spi.AbstractSelector} classes in the <tt>{@link
java.nio.channels.spi}</tt> package. When defining a custom selector provider,
only the {@link java.nio.channels.spi.AbstractSelector} and {@link
java.nio.channels.spi.AbstractSelectionKey} classes should be subclassed
directly; custom channel classes should extend the appropriate {@link
java.nio.channels.SelectableChannel} subclasses defined in this package.
<p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
or method in any class or interface in this package will cause a {@link
java.lang.NullPointerException NullPointerException} to be thrown.
@since 1.4
@author Mark Reinhold
@author JSR-51 Expert Group
</body>
</html>

View File

@ -25,10 +25,8 @@
package java.nio.channels.spi;
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.ProtocolFamily;
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
@ -190,7 +188,25 @@ public abstract class SelectorProvider {
throws IOException;
/**
* Opens a pipe. </p>
* Opens a datagram channel.
*
* @param family
* The protocol family
*
* @return A new datagram channel
*
* @throws UnsupportedOperationException
* If the specified protocol family is not supported
* @throws IOException
* If an I/O error occurs
*
* @since 1.7
*/
public abstract DatagramChannel openDatagramChannel(ProtocolFamily family)
throws IOException;
/**
* Opens a pipe. </p>
*
* @return The new pipe
*/

View File

@ -31,7 +31,7 @@ import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.lang.ref.SoftReference;
import java.util.*;
/**
@ -47,11 +47,14 @@ class DatagramChannelImpl
private static NativeDispatcher nd = new DatagramDispatcher();
// Our file descriptor
FileDescriptor fd = null;
private final FileDescriptor fd;
// fd value needed for dev/poll. This value will remain valid
// even after the value in the file descriptor object has been set to -1
int fdVal;
private final int fdVal;
// The protocol family of the socket
private final ProtocolFamily family;
// IDs of native threads doing reads and writes, for signalling
private volatile long readerThread = 0;
@ -59,8 +62,8 @@ class DatagramChannelImpl
// Cached InetAddress and port for unconnected DatagramChannels
// used by receive0
private InetAddress cachedSenderInetAddress = null;
private int cachedSenderPort = 0;
private InetAddress cachedSenderInetAddress;
private int cachedSenderPort;
// Lock held by current reading or connecting thread
private final Object readLock = new Object();
@ -76,20 +79,20 @@ class DatagramChannelImpl
// State (does not necessarily increase monotonically)
private static final int ST_UNINITIALIZED = -1;
private static int ST_UNCONNECTED = 0;
private static int ST_CONNECTED = 1;
private static final int ST_UNCONNECTED = 0;
private static final int ST_CONNECTED = 1;
private static final int ST_KILLED = 2;
private int state = ST_UNINITIALIZED;
// Binding
private SocketAddress localAddress = null;
SocketAddress remoteAddress = null;
// Options
private SocketOpts.IP options = null;
private SocketAddress localAddress;
private SocketAddress remoteAddress;
// Our socket adaptor, if any
private DatagramSocket socket = null;
private DatagramSocket socket;
// Multicast support
private MembershipRegistry registry;
// -- End of fields protected by stateLock
@ -98,7 +101,26 @@ class DatagramChannelImpl
throws IOException
{
super(sp);
this.fd = Net.socket(false);
this.family = Net.isIPv6Available() ?
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
this.fd = Net.socket(family, false);
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED;
}
public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) {
super(sp);
if ((family != StandardProtocolFamily.INET) &&
(family != StandardProtocolFamily.INET6)) {
throw new UnsupportedOperationException("Protocol family not supported");
}
if (family == StandardProtocolFamily.INET6) {
if (!Net.isIPv6Available()) {
throw new UnsupportedOperationException("IPv6 not available");
}
}
this.family = family;
this.fd = Net.socket(family, false);
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED;
}
@ -107,9 +129,12 @@ class DatagramChannelImpl
throws IOException
{
super(sp);
this.family = Net.isIPv6Available() ?
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
this.fd = fd;
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED;
this.localAddress = Net.localAddress(fd);
}
public DatagramSocket socket() {
@ -120,6 +145,156 @@ class DatagramChannelImpl
}
}
@Override
public SocketAddress getLocalAddress() throws IOException {
synchronized (stateLock) {
if (!isOpen())
return null;
return localAddress;
}
}
@Override
public SocketAddress getConnectedAddress() throws IOException {
synchronized (stateLock) {
if (!isOpen())
return null;
return remoteAddress;
}
}
@Override
public DatagramChannel setOption(SocketOption name, Object value)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("Invalid option name");
synchronized (stateLock) {
ensureOpen();
if (name == StandardSocketOption.IP_TOS) {
// IPv4 only; no-op for IPv6
if (family == StandardProtocolFamily.INET) {
Net.setSocketOption(fd, family, name, value);
}
return this;
}
if (name == StandardSocketOption.IP_MULTICAST_TTL ||
name == StandardSocketOption.IP_MULTICAST_LOOP)
{
// options are protocol dependent
Net.setSocketOption(fd, family, name, value);
return this;
}
if (name == StandardSocketOption.IP_MULTICAST_IF) {
if (value == null)
throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
NetworkInterface interf = (NetworkInterface)value;
if (family == StandardProtocolFamily.INET6) {
int index = interf.getIndex();
if (index == -1)
throw new IOException("Network interface cannot be identified");
Net.setInterface6(fd, index);
} else {
// need IPv4 address to identify interface
Inet4Address target = Net.anyInet4Address(interf);
if (target == null)
throw new IOException("Network interface not configured for IPv4");
int targetAddress = Net.inet4AsInt(target);
Net.setInterface4(fd, targetAddress);
}
return this;
}
// remaining options don't need any special handling
Net.setSocketOption(fd, Net.UNSPEC, name, value);
return this;
}
}
@Override
@SuppressWarnings("unchecked")
public <T> T getOption(SocketOption<T> name)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("Invalid option name");
synchronized (stateLock) {
ensureOpen();
if (name == StandardSocketOption.IP_TOS) {
// IPv4 only; always return 0 on IPv6
if (family == StandardProtocolFamily.INET) {
return (T) Net.getSocketOption(fd, family, name);
} else {
return (T) Integer.valueOf(0);
}
}
if (name == StandardSocketOption.IP_MULTICAST_TTL ||
name == StandardSocketOption.IP_MULTICAST_LOOP)
{
return (T) Net.getSocketOption(fd, family, name);
}
if (name == StandardSocketOption.IP_MULTICAST_IF) {
if (family == StandardProtocolFamily.INET) {
int address = Net.getInterface4(fd);
if (address == 0)
return null; // default interface
InetAddress ia = Net.inet4FromInt(address);
NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
if (ni == null)
throw new IOException("Unable to map address to interface");
return (T) ni;
} else {
int index = Net.getInterface6(fd);
if (index == 0)
return null; // default interface
NetworkInterface ni = NetworkInterface.getByIndex(index);
if (ni == null)
throw new IOException("Unable to map index to interface");
return (T) ni;
}
}
// no special handling
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
}
}
private static class LazyInitialization {
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
private static Set<SocketOption<?>> defaultOptions() {
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
set.add(StandardSocketOption.SO_SNDBUF);
set.add(StandardSocketOption.SO_RCVBUF);
set.add(StandardSocketOption.SO_REUSEADDR);
set.add(StandardSocketOption.SO_BROADCAST);
set.add(StandardSocketOption.IP_TOS);
set.add(StandardSocketOption.IP_MULTICAST_IF);
set.add(StandardSocketOption.IP_MULTICAST_TTL);
set.add(StandardSocketOption.IP_MULTICAST_LOOP);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SocketOption<?>> options() {
return LazyInitialization.defaultOptions;
}
private void ensureOpen() throws ClosedChannelException {
if (!isOpen())
throw new ClosedChannelException();
@ -135,8 +310,10 @@ class DatagramChannelImpl
synchronized (readLock) {
ensureOpen();
// If socket is not bound then behave as if nothing received
if (!isBound()) // ## NotYetBoundException ??
// Will be fixed by 6621699
if (localAddress() == null) {
return null;
}
int n = 0;
ByteBuffer bb = null;
try {
@ -267,6 +444,12 @@ class DatagramChannelImpl
do {
n = send(fd, src, target);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
synchronized (stateLock) {
if (isOpen() && (localAddress == null)) {
localAddress = Net.localAddress(fd);
}
}
return IOStatus.normalize(n);
} finally {
writerThread = 0;
@ -316,7 +499,8 @@ class DatagramChannelImpl
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
int written = send0(fd, ((DirectBuffer)bb).address() + pos,
boolean preferIPv6 = (family != StandardProtocolFamily.INET);
int written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
rem, target);
if (written > 0)
bb.position(pos + written);
@ -453,42 +637,8 @@ class DatagramChannelImpl
IOUtil.configureBlocking(fd, block);
}
public SocketOpts options() {
synchronized (stateLock) {
if (options == null) {
SocketOptsImpl.Dispatcher d
= new SocketOptsImpl.Dispatcher() {
int getInt(int opt) throws IOException {
return Net.getIntOption(fd, opt);
}
void setInt(int opt, int arg)
throws IOException
{
Net.setIntOption(fd, opt, arg);
}
};
options = new SocketOptsImpl.IP(d);
}
return options;
}
}
public boolean isBound() {
return Net.localPortNumber(fd) != 0;
}
public SocketAddress localAddress() {
synchronized (stateLock) {
if (isConnected() && (localAddress == null)) {
// Socket was not bound before connecting,
// so ask what the address turned out to be
localAddress = Net.localAddress(fd);
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
InetSocketAddress isa = (InetSocketAddress)localAddress;
sm.checkConnect(isa.getAddress().getHostAddress(), -1);
}
return localAddress;
}
}
@ -499,22 +649,37 @@ class DatagramChannelImpl
}
}
public void bind(SocketAddress local) throws IOException {
@Override
public DatagramChannel bind(SocketAddress local) throws IOException {
synchronized (readLock) {
synchronized (writeLock) {
synchronized (stateLock) {
ensureOpen();
if (isBound())
if (localAddress != null)
throw new AlreadyBoundException();
InetSocketAddress isa = Net.checkAddress(local);
InetSocketAddress isa;
if (local == null) {
isa = new InetSocketAddress(0);
} else {
isa = Net.checkAddress(local);
// only Inet4Address allowed with IPv4 socket
if (family == StandardProtocolFamily.INET) {
InetAddress addr = isa.getAddress();
if (!(addr instanceof Inet4Address))
throw new UnsupportedAddressTypeException();
}
}
SecurityManager sm = System.getSecurityManager();
if (sm != null)
if (sm != null) {
sm.checkListen(isa.getPort());
Net.bind(fd, isa.getAddress(), isa.getPort());
}
Net.bind(family, fd, isa.getAddress(), isa.getPort());
localAddress = Net.localAddress(fd);
}
}
}
return this;
}
public boolean isConnected() {
@ -533,7 +698,6 @@ class DatagramChannelImpl
}
public DatagramChannel connect(SocketAddress sa) throws IOException {
int trafficClass = 0;
int localPort = 0;
synchronized(readLock) {
@ -545,10 +709,10 @@ class DatagramChannelImpl
if (sm != null)
sm.checkConnect(isa.getAddress().getHostAddress(),
isa.getPort());
int n = Net.connect(fd,
int n = Net.connect(family,
fd,
isa.getAddress(),
isa.getPort(),
trafficClass);
isa.getPort());
if (n <= 0)
throw new Error(); // Can't happen
@ -558,6 +722,11 @@ class DatagramChannelImpl
sender = isa;
cachedSenderInetAddress = isa.getAddress();
cachedSenderPort = isa.getPort();
// Socket was not bound before connecting,
if (localAddress == null) {
localAddress = Net.localAddress(fd);
}
}
}
}
@ -584,9 +753,215 @@ class DatagramChannelImpl
return this;
}
/**
* Joins channel's socket to the given group/interface and
* optional source address.
*/
private MembershipKey innerJoin(InetAddress group,
NetworkInterface interf,
InetAddress source)
throws IOException
{
if (!group.isMulticastAddress())
throw new IllegalArgumentException("Group not a multicast address");
// check multicast address is compatible with this socket
if (!(group instanceof Inet4Address)) {
if (family == StandardProtocolFamily.INET)
throw new IllegalArgumentException("Group is not IPv4 address");
if (!(group instanceof Inet6Address))
throw new IllegalArgumentException("Address type not supported");
}
// check source address
if (source != null) {
if (source.isAnyLocalAddress())
throw new IllegalArgumentException("Source address is a wildcard address");
if (source.isMulticastAddress())
throw new IllegalArgumentException("Source address is multicast address");
if (source.getClass() != group.getClass())
throw new IllegalArgumentException("Source address is different type to group");
}
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkMulticast(group);
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
// check the registry to see if we are already a member of the group
if (registry == null) {
registry = new MembershipRegistry();
} else {
// return existing membership key
MembershipKey key = registry.checkMembership(group, interf, source);
if (key != null)
return key;
}
MembershipKeyImpl key;
if (family == StandardProtocolFamily.INET6) {
int index = interf.getIndex();
if (index == -1)
throw new IOException("Network interface cannot be identified");
// need multicast and source address as byte arrays
byte[] groupAddress = Net.inet6AsByteArray(group);
byte[] sourceAddress = (source == null) ? null :
Net.inet6AsByteArray(source);
// join the group
int n = Net.join6(fd, groupAddress, index, sourceAddress);
if (n == IOStatus.UNAVAILABLE)
throw new UnsupportedOperationException();
key = new MembershipKeyImpl.Type6(this, group, interf, source,
groupAddress, index, sourceAddress);
} else {
// need IPv4 address to identify interface
Inet4Address target = Net.anyInet4Address(interf);
if (target == null)
throw new IOException("Network interface not configured for IPv4");
int groupAddress = Net.inet4AsInt(group);
int targetAddress = Net.inet4AsInt(target);
int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
// join the group
int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
if (n == IOStatus.UNAVAILABLE)
throw new UnsupportedOperationException();
key = new MembershipKeyImpl.Type4(this, group, interf, source,
groupAddress, targetAddress, sourceAddress);
}
registry.add(key);
return key;
}
}
@Override
public MembershipKey join(InetAddress group,
NetworkInterface interf)
throws IOException
{
return innerJoin(group, interf, null);
}
@Override
public MembershipKey join(InetAddress group,
NetworkInterface interf,
InetAddress source)
throws IOException
{
if (source == null)
throw new NullPointerException("source address is null");
return innerJoin(group, interf, source);
}
// package-private
void drop(MembershipKeyImpl key)
throws IOException
{
assert key.getChannel() == this;
synchronized (stateLock) {
if (!key.isValid())
return;
if (family == StandardProtocolFamily.INET6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
Net.drop6(fd, key6.group(), key6.index(), key6.source());
} else {
MembershipKeyImpl.Type4 key4 =
(MembershipKeyImpl.Type4)key;
Net.drop4(fd, key4.group(), key4.interfaceAddress(), key4.source());
}
key.invalidate();
registry.remove(key);
}
}
/**
* Block datagrams from given source if a memory to receive all
* datagrams.
*/
void block(MembershipKeyImpl key, InetAddress source)
throws IOException
{
assert key.getChannel() == this;
assert key.getSourceAddress() == null;
synchronized (stateLock) {
if (!key.isValid())
throw new IllegalStateException("key is no longer valid");
if (source.isAnyLocalAddress())
throw new IllegalArgumentException("Source address is a wildcard address");
if (source.isMulticastAddress())
throw new IllegalArgumentException("Source address is multicast address");
if (source.getClass() != key.getGroup().getClass())
throw new IllegalArgumentException("Source address is different type to group");
int n;
if (family == StandardProtocolFamily.INET6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
n = Net.block6(fd, key6.group(), key6.index(),
Net.inet6AsByteArray(source));
} else {
MembershipKeyImpl.Type4 key4 =
(MembershipKeyImpl.Type4)key;
n = Net.block4(fd, key4.group(), key4.interfaceAddress(),
Net.inet4AsInt(source));
}
if (n == IOStatus.UNAVAILABLE) {
// ancient kernel
throw new UnsupportedOperationException();
}
}
}
/**
* Unblock given source.
*/
void unblock(MembershipKeyImpl key, InetAddress source)
throws IOException
{
assert key.getChannel() == this;
assert key.getSourceAddress() == null;
synchronized (stateLock) {
if (!key.isValid())
throw new IllegalStateException("key is no longer valid");
if (family == StandardProtocolFamily.INET6) {
MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key;
Net.unblock6(fd, key6.group(), key6.index(),
Net.inet6AsByteArray(source));
} else {
MembershipKeyImpl.Type4 key4 =
(MembershipKeyImpl.Type4)key;
Net.unblock4(fd, key4.group(), key4.interfaceAddress(),
Net.inet4AsInt(source));
}
}
}
protected void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
// if member of mulitcast group then invalidate all keys
if (registry != null)
registry.invalidateAll();
long th;
if ((th = readerThread) != 0)
NativeThread.signal(th);
@ -695,8 +1070,8 @@ class DatagramChannelImpl
boolean connected)
throws IOException;
private native int send0(FileDescriptor fd, long address, int len,
SocketAddress sa)
private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len,
SocketAddress sa)
throws IOException;
static {

View File

@ -45,16 +45,9 @@ public class DatagramSocketAdaptor
// The channel being adapted
private final DatagramChannelImpl dc;
// Option adaptor object, created on demand
private volatile OptionAdaptor opts = null;
// Timeout "option" value for receives
private volatile int timeout = 0;
// Traffic-class/Type-of-service
private volatile int trafficClass = 0;
// ## super will create a useless impl
private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
// Invoke the DatagramSocketAdaptor(SocketAddress) constructor,
@ -82,7 +75,7 @@ public class DatagramSocketAdaptor
throw new IllegalArgumentException("connect: " + port);
if (remote == null)
throw new IllegalArgumentException("connect: null address");
if (!isClosed())
if (isClosed())
return;
try {
dc.connect(remote);
@ -124,11 +117,11 @@ public class DatagramSocketAdaptor
}
public boolean isBound() {
return dc.isBound();
return dc.localAddress() != null;
}
public boolean isConnected() {
return dc.isConnected();
return dc.remoteAddress() != null;
}
public InetAddress getInetAddress() {
@ -157,7 +150,7 @@ public class DatagramSocketAdaptor
// Legacy DatagramSocket will send in this case
// and set address and port of the packet
InetSocketAddress isa = (InetSocketAddress)
dc.remoteAddress;
dc.remoteAddress();
p.setPort(isa.getPort());
p.setAddress(isa.getAddress());
dc.write(bb);
@ -241,21 +234,32 @@ public class DatagramSocketAdaptor
public InetAddress getLocalAddress() {
if (isClosed())
return null;
try {
return Net.asInetSocketAddress(dc.localAddress()).getAddress();
} catch (Exception x) {
return new InetSocketAddress(0).getAddress();
SocketAddress local = dc.localAddress();
if (local == null)
local = new InetSocketAddress(0);
InetAddress result = ((InetSocketAddress)local).getAddress();
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkConnect(result.getHostAddress(), -1);
} catch (SecurityException x) {
return new InetSocketAddress(0).getAddress();
}
}
return result;
}
public int getLocalPort() {
if (isClosed())
return -1;
try {
return Net.asInetSocketAddress(dc.localAddress()).getPort();
SocketAddress local = dc.getLocalAddress();
if (local != null) {
return ((InetSocketAddress)local).getPort();
}
} catch (Exception x) {
return 0;
}
return 0;
}
public void setSoTimeout(int timeout) throws SocketException {
@ -266,55 +270,87 @@ public class DatagramSocketAdaptor
return timeout;
}
private OptionAdaptor opts() {
if (opts == null)
opts = new OptionAdaptor(dc);
return opts;
private void setBooleanOption(SocketOption<Boolean> name, boolean value)
throws SocketException
{
try {
dc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private void setIntOption(SocketOption<Integer> name, int value)
throws SocketException
{
try {
dc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {
try {
return dc.getOption(name).booleanValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return false; // keep compiler happy
}
}
private int getIntOption(SocketOption<Integer> name) throws SocketException {
try {
return dc.getOption(name).intValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return -1; // keep compiler happy
}
}
public void setSendBufferSize(int size) throws SocketException {
opts().setSendBufferSize(size);
if (size <= 0)
throw new IllegalArgumentException("Invalid send size");
setIntOption(StandardSocketOption.SO_SNDBUF, size);
}
public int getSendBufferSize() throws SocketException {
return opts().getSendBufferSize();
return getIntOption(StandardSocketOption.SO_SNDBUF);
}
public void setReceiveBufferSize(int size) throws SocketException {
opts().setReceiveBufferSize(size);
if (size <= 0)
throw new IllegalArgumentException("Invalid receive size");
setIntOption(StandardSocketOption.SO_RCVBUF, size);
}
public int getReceiveBufferSize() throws SocketException {
return opts().getReceiveBufferSize();
return getIntOption(StandardSocketOption.SO_RCVBUF);
}
public void setReuseAddress(boolean on) throws SocketException {
opts().setReuseAddress(on);
setBooleanOption(StandardSocketOption.SO_REUSEADDR, on);
}
public boolean getReuseAddress() throws SocketException {
return opts().getReuseAddress();
return getBooleanOption(StandardSocketOption.SO_REUSEADDR);
}
public void setBroadcast(boolean on) throws SocketException {
opts().setBroadcast(on);
setBooleanOption(StandardSocketOption.SO_BROADCAST, on);
}
public boolean getBroadcast() throws SocketException {
return opts().getBroadcast();
return getBooleanOption(StandardSocketOption.SO_BROADCAST);
}
public void setTrafficClass(int tc) throws SocketException {
opts().setTrafficClass(tc);
trafficClass = tc;
setIntOption(StandardSocketOption.IP_TOS, tc);
}
public int getTrafficClass() throws SocketException {
int tc = opts().getTrafficClass();
if (tc < 0) {
tc = trafficClass;
}
return tc;
return getIntOption(StandardSocketOption.IP_TOS);
}
public void close() {

View File

@ -0,0 +1,44 @@
/*
* Copyright 2007-2008 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.SocketOption;
/**
* Defines socket options that are supported by the implementation
* but not defined in StandardSocketOption.
*/
class ExtendedSocketOption {
private ExtendedSocketOption() { }
static final SocketOption<Boolean> SO_OOBINLINE =
new SocketOption<Boolean>() {
public String name() { return "SO_OOBINLINE"; }
public Class<Boolean> type() { return Boolean.class; }
public String toString() { return name(); }
};
}

View File

@ -0,0 +1,222 @@
/*
* Copyright 2007-2008 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.channels.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.io.IOException;
import java.util.HashSet;
/**
* MembershipKey implementation.
*/
class MembershipKeyImpl
extends MembershipKey
{
private final MulticastChannel ch;
private final InetAddress group;
private final NetworkInterface interf;
private final InetAddress source;
// true when key is valid
private volatile boolean valid = true;
// lock used when creating or accessing blockedSet
private Object stateLock = new Object();
// set of source addresses that are blocked
private HashSet<InetAddress> blockedSet;
private MembershipKeyImpl(MulticastChannel ch,
InetAddress group,
NetworkInterface interf,
InetAddress source)
{
this.ch = ch;
this.group = group;
this.interf = interf;
this.source = source;
}
/**
* MembershipKey will additional context for IPv4 membership
*/
static class Type4 extends MembershipKeyImpl {
private final int groupAddress;
private final int interfAddress;
private final int sourceAddress;
Type4(MulticastChannel ch,
InetAddress group,
NetworkInterface interf,
InetAddress source,
int groupAddress,
int interfAddress,
int sourceAddress)
{
super(ch, group, interf, source);
this.groupAddress = groupAddress;
this.interfAddress = interfAddress;
this.sourceAddress = sourceAddress;
}
int group() {
return groupAddress;
}
int interfaceAddress() {
return interfAddress;
}
int source() {
return sourceAddress;
}
}
/**
* MembershipKey will additional context for IPv6 membership
*/
static class Type6 extends MembershipKeyImpl {
private final byte[] groupAddress;
private final int index;
private final byte[] sourceAddress;
Type6(MulticastChannel ch,
InetAddress group,
NetworkInterface interf,
InetAddress source,
byte[] groupAddress,
int index,
byte[] sourceAddress)
{
super(ch, group, interf, source);
this.groupAddress = groupAddress;
this.index = index;
this.sourceAddress = sourceAddress;
}
byte[] group() {
return groupAddress;
}
int index() {
return index;
}
byte[] source() {
return sourceAddress;
}
}
public boolean isValid() {
return valid;
}
// package-private
void invalidate() {
valid = false;
}
public void drop() throws IOException {
// delegate to channel
((DatagramChannelImpl)ch).drop(this);
}
@Override
public MulticastChannel getChannel() {
return ch;
}
@Override
public InetAddress getGroup() {
return group;
}
@Override
public NetworkInterface getNetworkInterface() {
return interf;
}
@Override
public InetAddress getSourceAddress() {
return source;
}
@Override
public MembershipKey block(InetAddress toBlock)
throws IOException
{
if (source != null)
throw new IllegalStateException("key is source-specific");
synchronized (stateLock) {
if ((blockedSet != null) && blockedSet.contains(toBlock)) {
// already blocked, nothing to do
return this;
}
((DatagramChannelImpl)ch).block(this, toBlock);
// created blocked set if required and add source address
if (blockedSet == null)
blockedSet = new HashSet<InetAddress>();
blockedSet.add(toBlock);
}
return this;
}
@Override
public MembershipKey unblock(InetAddress toUnblock)
throws IOException
{
synchronized (stateLock) {
if ((blockedSet == null) || !blockedSet.contains(toUnblock))
throw new IllegalStateException("not blocked");
((DatagramChannelImpl)ch).unblock(this, toUnblock);
blockedSet.remove(toUnblock);
}
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(64);
sb.append('<');
sb.append(group.getHostAddress());
sb.append(',');
sb.append(interf.getName());
if (source != null) {
sb.append(',');
sb.append(source.getHostAddress());
}
sb.append('>');
return sb.toString();
}
}

View File

@ -0,0 +1,129 @@
/*
* Copyright 2007-2008 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.channels.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
/**
* Simple registry of membership keys for a MulticastChannel.
*
* Instances of this object are not safe by multiple concurrent threads.
*/
class MembershipRegistry {
// map multicast group to keys
private Map<InetAddress,List<MembershipKeyImpl>> groups = null;
MembershipRegistry() {
}
/**
* Checks registry for membership of the group on the given
* network interface.
*/
MembershipKey checkMembership(InetAddress group, NetworkInterface interf,
InetAddress source)
{
if (groups != null) {
List<MembershipKeyImpl> keys = groups.get(group);
if (keys != null) {
for (MembershipKeyImpl key: keys) {
if (key.getNetworkInterface().equals(interf)) {
// already a member to receive all packets so return
// existing key or detect conflict
if (source == null) {
if (key.getSourceAddress() == null)
return key;
throw new IllegalStateException("Already a member to receive all packets");
}
// already have source-specific membership so return key
// or detect conflict
if (key.getSourceAddress() == null)
throw new IllegalStateException("Already have source-specific membership");
if (source.equals(key.getSourceAddress()))
return key;
}
}
}
}
return null;
}
/**
* Add membership to the registry, returning a new membership key.
*/
void add(MembershipKeyImpl key) {
InetAddress group = key.getGroup();
List<MembershipKeyImpl> keys;
if (groups == null) {
groups = new HashMap<InetAddress,List<MembershipKeyImpl>>();
keys = null;
} else {
keys = groups.get(group);
}
if (keys == null) {
keys = new LinkedList<MembershipKeyImpl>();
groups.put(group, keys);
}
keys.add(key);
}
/**
* Remove a key from the registry
*/
void remove(MembershipKeyImpl key) {
InetAddress group = key.getGroup();
List<MembershipKeyImpl> keys = groups.get(group);
if (keys != null) {
Iterator<MembershipKeyImpl> i = keys.iterator();
while (i.hasNext()) {
if (i.next() == key) {
i.remove();
break;
}
}
if (keys.isEmpty()) {
groups.remove(group);
}
}
}
/**
* Invalidate all keys in the registry
*/
void invalidateAll() {
for (InetAddress group: groups.keySet()) {
for (MembershipKeyImpl key: groups.get(group)) {
key.invalidate();
}
}
}
}

View File

@ -26,21 +26,43 @@
package sun.nio.ch;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.nio.channels.*;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
class Net { // package-private
private Net() { }
// unspecified protocol family
static final ProtocolFamily UNSPEC = new ProtocolFamily() {
public String name() {
return "UNSPEC";
}
};
// -- Miscellaneous utilities --
private static volatile boolean checkedIPv6 = false;
private static volatile boolean isIPv6Available;
/**
* Tells whether dual-IPv4/IPv6 sockets should be used.
*/
static boolean isIPv6Available() {
if (!checkedIPv6) {
isIPv6Available = isIPv6Available0();
checkedIPv6 = true;
}
return isIPv6Available;
}
static InetSocketAddress checkAddress(SocketAddress sa) {
if (sa == null)
throw new IllegalArgumentException();
throw new NullPointerException();
if (!(sa instanceof InetSocketAddress))
throw new UnsupportedAddressTypeException(); // ## needs arg
InetSocketAddress isa = (InetSocketAddress)sa;
@ -63,6 +85,8 @@ class Net { // package-private
Exception nx = x;
if (x instanceof ClosedChannelException)
nx = new SocketException("Socket is closed");
else if (x instanceof NotYetConnectedException)
nx = new SocketException("Socket is not connected");
else if (x instanceof AlreadyBoundException)
nx = new SocketException("Already bound");
else if (x instanceof NotYetBoundException)
@ -105,73 +129,359 @@ class Net { // package-private
translateException(x, false);
}
/**
* Returns any IPv4 address of the given network interface, or
* null if the interface does not have any IPv4 addresses.
*/
static Inet4Address anyInet4Address(final NetworkInterface interf) {
return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
public Inet4Address run() {
Enumeration<InetAddress> addrs = interf.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = addrs.nextElement();
if (addr instanceof Inet4Address) {
return (Inet4Address)addr;
}
}
return null;
}
});
}
/**
* Returns an IPv4 address as an int.
*/
static int inet4AsInt(InetAddress ia) {
if (ia instanceof Inet4Address) {
byte[] addr = ia.getAddress();
int address = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000);
return address;
}
throw new AssertionError("Should not reach here");
}
/**
* Returns an InetAddress from the given IPv4 address
* represented as an int.
*/
static InetAddress inet4FromInt(int address) {
byte[] addr = new byte[4];
addr[0] = (byte) ((address >>> 24) & 0xFF);
addr[1] = (byte) ((address >>> 16) & 0xFF);
addr[2] = (byte) ((address >>> 8) & 0xFF);
addr[3] = (byte) (address & 0xFF);
try {
return InetAddress.getByAddress(addr);
} catch (UnknownHostException uhe) {
throw new AssertionError("Should not reach here");
}
}
/**
* Returns an IPv6 address as a byte array
*/
static byte[] inet6AsByteArray(InetAddress ia) {
if (ia instanceof Inet6Address) {
return ia.getAddress();
}
// need to construct IPv4-mapped address
if (ia instanceof Inet4Address) {
byte[] ip4address = ia.getAddress();
byte[] address = new byte[16];
address[10] = (byte)0xff;
address[11] = (byte)0xff;
address[12] = ip4address[0];
address[13] = ip4address[1];
address[14] = ip4address[2];
address[15] = ip4address[3];
return address;
}
throw new AssertionError("Should not reach here");
}
// -- Socket options
static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
SocketOption name, Object value)
throws IOException
{
if (value == null)
throw new IllegalArgumentException("Invalid option value");
// only simple values supported by this method
Class<?> type = name.type();
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
// special handling
if (name == StandardSocketOption.SO_RCVBUF ||
name == StandardSocketOption.SO_SNDBUF)
{
int i = ((Integer)value).intValue();
if (i < 0)
throw new IllegalArgumentException("Invalid send/receive buffer size");
}
if (name == StandardSocketOption.SO_LINGER) {
int i = ((Integer)value).intValue();
if (i < 0)
value = Integer.valueOf(-1);
if (i > 65535)
value = Integer.valueOf(65535);
}
if (name == StandardSocketOption.IP_TOS) {
int i = ((Integer)value).intValue();
if (i < 0 || i > 255)
throw new IllegalArgumentException("Invalid IP_TOS value");
}
if (name == StandardSocketOption.IP_MULTICAST_TTL) {
int i = ((Integer)value).intValue();
if (i < 0 || i > 255)
throw new IllegalArgumentException("Invalid TTL/hop value");
}
// map option name to platform level/name
OptionKey key = SocketOptionRegistry.findOption(name, family);
if (key == null)
throw new AssertionError("Option not found");
int arg;
if (type == Integer.class) {
arg = ((Integer)value).intValue();
} else {
boolean b = ((Boolean)value).booleanValue();
arg = (b) ? 1 : 0;
}
boolean mayNeedConversion = (family == UNSPEC);
setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg);
}
static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
SocketOption name)
throws IOException
{
Class<?> type = name.type();
// only simple values supported by this method
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
// map option name to platform level/name
OptionKey key = SocketOptionRegistry.findOption(name, family);
if (key == null)
throw new AssertionError("Option not found");
boolean mayNeedConversion = (family == UNSPEC);
int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
if (type == Integer.class) {
return Integer.valueOf(value);
} else {
return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
}
}
// -- Socket operations --
static native boolean isIPv6Available0();
static FileDescriptor socket(boolean stream) {
return IOUtil.newFD(socket0(stream, false));
return socket(UNSPEC, stream);
}
static FileDescriptor socket(ProtocolFamily family, boolean stream) {
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
return IOUtil.newFD(socket0(preferIPv6, stream, false));
}
static FileDescriptor serverSocket(boolean stream) {
return IOUtil.newFD(socket0(stream, true));
return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
}
// Due to oddities SO_REUSEADDR on windows reuse is ignored
private static native int socket0(boolean stream, boolean reuse);
private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
static native void bind(FileDescriptor fd, InetAddress addr, int port)
static void bind(FileDescriptor fd, InetAddress addr, int port)
throws IOException
{
bind(UNSPEC, fd, addr, port);
}
static void bind(ProtocolFamily family, FileDescriptor fd,
InetAddress addr, int port) throws IOException
{
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
bind0(preferIPv6, fd, addr, port);
}
private static native void bind0(boolean preferIPv6, FileDescriptor fd,
InetAddress addr, int port)
throws IOException;
static native int connect(FileDescriptor fd,
InetAddress remote,
int remotePort,
int trafficClass)
static native void listen(FileDescriptor fd, int backlog) throws IOException;
static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
throws IOException
{
return connect(UNSPEC, fd, remote, remotePort);
}
static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
throws IOException
{
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
return connect0(preferIPv6, fd, remote, remotePort);
}
private static native int connect0(boolean preferIPv6,
FileDescriptor fd,
InetAddress remote,
int remotePort)
throws IOException;
public final static int SHUT_RD = 0;
public final static int SHUT_WR = 1;
public final static int SHUT_RDWR = 2;
static native void shutdown(FileDescriptor fd, int how) throws IOException;
private static native int localPort(FileDescriptor fd)
throws IOException;
private static native InetAddress localInetAddress(FileDescriptor fd)
throws IOException;
static InetSocketAddress localAddress(FileDescriptor fd) {
try {
return new InetSocketAddress(localInetAddress(fd),
localPort(fd));
} catch (IOException x) {
throw new Error(x); // Can't happen
}
}
static int localPortNumber(FileDescriptor fd) {
try {
return localPort(fd);
} catch (IOException x) {
throw new Error(x); // Can't happen
}
}
private static native int getIntOption0(FileDescriptor fd, int opt)
throws IOException;
static int getIntOption(FileDescriptor fd, int opt)
static InetSocketAddress localAddress(FileDescriptor fd)
throws IOException
{
return getIntOption0(fd, opt);
return new InetSocketAddress(localInetAddress(fd), localPort(fd));
}
private static native void setIntOption0(FileDescriptor fd,
int opt, int arg)
private static native int remotePort(FileDescriptor fd)
throws IOException;
static void setIntOption(FileDescriptor fd, int opt, int arg)
private static native InetAddress remoteInetAddress(FileDescriptor fd)
throws IOException;
static InetSocketAddress remoteAddress(FileDescriptor fd)
throws IOException
{
setIntOption0(fd, opt, arg);
return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
}
private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
int level, int opt)
throws IOException;
private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
int level, int opt, int arg)
throws IOException;
// -- Multicast support --
/**
* Join IPv4 multicast group
*/
static int join4(FileDescriptor fd, int group, int interf, int source)
throws IOException
{
return joinOrDrop4(true, fd, group, interf, source);
}
/**
* Drop membership of IPv4 multicast group
*/
static void drop4(FileDescriptor fd, int group, int interf, int source)
throws IOException
{
joinOrDrop4(false, fd, group, interf, source);
}
private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
throws IOException;
/**
* Block IPv4 source
*/
static int block4(FileDescriptor fd, int group, int interf, int source)
throws IOException
{
return blockOrUnblock4(true, fd, group, interf, source);
}
/**
* Unblock IPv6 source
*/
static void unblock4(FileDescriptor fd, int group, int interf, int source)
throws IOException
{
blockOrUnblock4(false, fd, group, interf, source);
}
private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
int interf, int source)
throws IOException;
/**
* Join IPv6 multicast group
*/
static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException
{
return joinOrDrop6(true, fd, group, index, source);
}
/**
* Drop membership of IPv6 multicast group
*/
static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException
{
joinOrDrop6(false, fd, group, index, source);
}
private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException;
/**
* Block IPv6 source
*/
static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException
{
return blockOrUnblock6(true, fd, group, index, source);
}
/**
* Unblock IPv6 source
*/
static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException
{
blockOrUnblock6(false, fd, group, index, source);
}
static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
throws IOException;
static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
static native int getInterface4(FileDescriptor fd) throws IOException;
static native void setInterface6(FileDescriptor fd, int index) throws IOException;
static native int getInterface6(FileDescriptor fd) throws IOException;
private static native void initIDs();
static {

View File

@ -1,229 +0,0 @@
/*
* Copyright 2001 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.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
// Adaptor class for java.net-style options
//
// The option get/set methods in the socket, server-socket, and datagram-socket
// adaptors delegate to an instance of this class.
//
class OptionAdaptor { // package-private
private final SocketOpts.IP opts;
OptionAdaptor(SocketChannelImpl sc) {
opts = (SocketOpts.IP)sc.options();
}
OptionAdaptor(ServerSocketChannelImpl ssc) {
opts = (SocketOpts.IP)ssc.options();
}
OptionAdaptor(DatagramChannelImpl dc) {
opts = (SocketOpts.IP)dc.options();
}
private SocketOpts.IP opts() {
return opts;
}
private SocketOpts.IP.TCP tcpOpts() {
return (SocketOpts.IP.TCP)opts;
}
public void setTcpNoDelay(boolean on) throws SocketException {
try {
tcpOpts().noDelay(on);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public boolean getTcpNoDelay() throws SocketException {
try {
return tcpOpts().noDelay();
} catch (Exception x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
public void setSoLinger(boolean on, int linger) throws SocketException {
try {
if (linger > 65535)
linger = 65535;
opts().linger(on ? linger : -1);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public int getSoLinger() throws SocketException {
try {
return opts().linger();
} catch (Exception x) {
Net.translateToSocketException(x);
return 0; // Never happens
}
}
public void setOOBInline(boolean on) throws SocketException {
try {
opts().outOfBandInline(on);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public boolean getOOBInline() throws SocketException {
try {
return opts().outOfBandInline();
} catch (Exception x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
public void setSendBufferSize(int size)
throws SocketException
{
try {
opts().sendBufferSize(size);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public int getSendBufferSize() throws SocketException {
try {
return opts().sendBufferSize();
} catch (Exception x) {
Net.translateToSocketException(x);
return 0; // Never happens
}
}
public void setReceiveBufferSize(int size)
throws SocketException
{
try {
opts().receiveBufferSize(size);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public int getReceiveBufferSize() throws SocketException {
try {
return opts().receiveBufferSize();
} catch (Exception x) {
Net.translateToSocketException(x);
return 0; // Never happens
}
}
public void setKeepAlive(boolean on) throws SocketException {
try {
opts().keepAlive(on);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public boolean getKeepAlive() throws SocketException {
try {
return opts().keepAlive();
} catch (Exception x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
public void setTrafficClass(int tc) throws SocketException {
if (tc < 0 || tc > 255)
throw new IllegalArgumentException("tc is not in range 0 -- 255");
try {
opts().typeOfService(tc);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public int getTrafficClass() throws SocketException {
try {
return opts().typeOfService();
} catch (Exception x) {
Net.translateToSocketException(x);
return 0; // Never happens
}
}
public void setReuseAddress(boolean on)
throws SocketException
{
try {
opts().reuseAddress(on);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public boolean getReuseAddress() throws SocketException {
try {
return opts().reuseAddress();
} catch (Exception x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
public void setBroadcast(boolean on)
throws SocketException
{
try {
opts().broadcast(on);
} catch (Exception x) {
Net.translateToSocketException(x);
}
}
public boolean getBroadcast() throws SocketException {
try {
return opts().broadcast();
} catch (Exception x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2007-2008 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;
/**
* Represents the level/name of a socket option
*/
class OptionKey {
private int level;
private int name;
OptionKey(int level, int name) {
this.level = level;
this.name = name;
}
int level() {
return level;
}
int name() {
return name;
}
}

View File

@ -29,6 +29,7 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.ProtocolFamily;
import java.nio.channels.*;
import java.nio.channels.spi.*;
@ -41,6 +42,10 @@ public abstract class SelectorProviderImpl
return new DatagramChannelImpl(this);
}
public DatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException {
return new DatagramChannelImpl(this, family);
}
public Pipe openPipe() throws IOException {
return new PipeImpl(this);
}
@ -54,5 +59,4 @@ public abstract class SelectorProviderImpl
public SocketChannel openSocketChannel() throws IOException {
return new SocketChannelImpl(this);
}
}

View File

@ -44,9 +44,6 @@ public class ServerSocketAdaptor // package-private
// The channel being adapted
private final ServerSocketChannelImpl ssc;
// Option adaptor object, created on demand
private volatile OptionAdaptor opts = null;
// Timeout "option" value for accepts
private volatile int timeout = 0;
@ -174,18 +171,21 @@ public class ServerSocketAdaptor // package-private
return timeout;
}
private OptionAdaptor opts() {
if (opts == null)
opts = new OptionAdaptor(ssc);
return opts;
}
public void setReuseAddress(boolean on) throws SocketException {
opts().setReuseAddress(on);
try {
ssc.setOption(StandardSocketOption.SO_REUSEADDR, on);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
public boolean getReuseAddress() throws SocketException {
return opts().getReuseAddress();
try {
return ssc.getOption(StandardSocketOption.SO_REUSEADDR).booleanValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return false; // Never happens
}
}
public String toString() {
@ -197,11 +197,23 @@ public class ServerSocketAdaptor // package-private
}
public void setReceiveBufferSize(int size) throws SocketException {
opts().setReceiveBufferSize(size);
// size 0 valid for ServerSocketChannel, invalid for ServerSocket
if (size <= 0)
throw new IllegalArgumentException("size cannot be 0 or negative");
try {
ssc.setOption(StandardSocketOption.SO_RCVBUF, size);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
public int getReceiveBufferSize() throws SocketException {
return opts().getReceiveBufferSize();
try {
return ssc.getOption(StandardSocketOption.SO_RCVBUF).intValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return -1; // Never happens
}
}
}

View File

@ -33,8 +33,7 @@ import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.Iterator;
import java.util.*;
/**
@ -75,10 +74,7 @@ class ServerSocketChannelImpl
private int state = ST_UNINITIALIZED;
// Binding
private SocketAddress localAddress = null; // null => unbound
// Options, created on demand
private SocketOpts.IP.TCP options = null;
private SocketAddress localAddress; // null => unbound
// Our socket adaptor, if any
ServerSocket socket;
@ -103,7 +99,6 @@ class ServerSocketChannelImpl
localAddress = Net.localAddress(fd);
}
public ServerSocket socket() {
synchronized (stateLock) {
if (socket == null)
@ -112,6 +107,69 @@ class ServerSocketChannelImpl
}
}
@Override
public SocketAddress getLocalAddress() throws IOException {
synchronized (stateLock) {
if (!isOpen())
return null;
return localAddress;
}
}
@Override
public ServerSocketChannel setOption(SocketOption name, Object value)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("invalid option name");
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
// no options that require special handling
Net.setSocketOption(fd, Net.UNSPEC, name, value);
return this;
}
}
@Override
@SuppressWarnings("unchecked")
public <T> T getOption(SocketOption<T> name)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("invalid option name");
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
// no options that require special handling
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
}
}
private static class LazyInitialization {
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
private static Set<SocketOption<?>> defaultOptions() {
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
set.add(StandardSocketOption.SO_RCVBUF);
set.add(StandardSocketOption.SO_REUSEADDR);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SocketOption<?>> options() {
return LazyInitialization.defaultOptions;
}
public boolean isBound() {
synchronized (stateLock) {
return localAddress != null;
@ -124,22 +182,25 @@ class ServerSocketChannelImpl
}
}
public void bind(SocketAddress local, int backlog) throws IOException {
@Override
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
synchronized (lock) {
if (!isOpen())
throw new ClosedChannelException();
if (isBound())
throw new AlreadyBoundException();
InetSocketAddress isa = Net.checkAddress(local);
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());
listen(fd, backlog < 1 ? 50 : backlog);
Net.listen(fd, backlog < 1 ? 50 : backlog);
synchronized (stateLock) {
localAddress = Net.localAddress(fd);
}
}
return this;
}
public SocketChannel accept() throws IOException {
@ -196,24 +257,6 @@ class ServerSocketChannelImpl
IOUtil.configureBlocking(fd, block);
}
public SocketOpts options() {
synchronized (stateLock) {
if (options == null) {
SocketOptsImpl.Dispatcher d
= new SocketOptsImpl.Dispatcher() {
int getInt(int opt) throws IOException {
return Net.getIntOption(fd, opt);
}
void setInt(int opt, int arg) throws IOException {
Net.setIntOption(fd, opt, arg);
}
};
options = new SocketOptsImpl.IP.TCP(d);
}
return options;
}
}
protected void implCloseSelectableChannel() throws IOException {
synchronized (stateLock) {
nd.preClose(fd);
@ -320,9 +363,6 @@ class ServerSocketChannelImpl
// -- Native methods --
private static native void listen(FileDescriptor fd, int backlog)
throws IOException;
// Accepts a new connection, setting the given file descriptor to refer to
// the new socket and setting isaa[0] to the socket's remote address.
// Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no

View File

@ -54,16 +54,9 @@ public class SocketAdaptor
// The channel being adapted
private final SocketChannelImpl sc;
// Option adaptor object, created on demand
private volatile OptionAdaptor opts = null;
// Timeout "option" value for reads
private volatile int timeout = 0;
// Traffic-class/Type-of-service
private volatile int trafficClass = 0;
// ## super will create a useless impl
private SocketAdaptor(SocketChannelImpl sc) {
this.sc = sc;
@ -145,8 +138,6 @@ public class SocketAdaptor
public void bind(SocketAddress local) throws IOException {
try {
if (local == null)
local = new InetSocketAddress(0);
sc.bind(local);
} catch (Exception x) {
Net.translateException(x);
@ -154,27 +145,39 @@ public class SocketAdaptor
}
public InetAddress getInetAddress() {
if (!sc.isConnected())
SocketAddress remote = sc.remoteAddress();
if (remote == null) {
return null;
return Net.asInetSocketAddress(sc.remoteAddress()).getAddress();
} else {
return ((InetSocketAddress)remote).getAddress();
}
}
public InetAddress getLocalAddress() {
if (!sc.isBound())
return new InetSocketAddress(0).getAddress();
return Net.asInetSocketAddress(sc.localAddress()).getAddress();
if (sc.isOpen()) {
SocketAddress local = sc.localAddress();
if (local != null)
return ((InetSocketAddress)local).getAddress();
}
return new InetSocketAddress(0).getAddress();
}
public int getPort() {
if (!sc.isConnected())
SocketAddress remote = sc.remoteAddress();
if (remote == null) {
return 0;
return Net.asInetSocketAddress(sc.remoteAddress()).getPort();
} else {
return ((InetSocketAddress)remote).getPort();
}
}
public int getLocalPort() {
if (!sc.isBound())
SocketAddress local = sc.localAddress();
if (local == null) {
return -1;
return Net.asInetSocketAddress(sc.localAddress()).getPort();
} else {
return ((InetSocketAddress)local).getPort();
}
}
private class SocketInputStream
@ -276,26 +279,60 @@ public class SocketAdaptor
return os;
}
private OptionAdaptor opts() {
if (opts == null)
opts = new OptionAdaptor(sc);
return opts;
private void setBooleanOption(SocketOption<Boolean> name, boolean value)
throws SocketException
{
try {
sc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private void setIntOption(SocketOption<Integer> name, int value)
throws SocketException
{
try {
sc.setOption(name, value);
} catch (IOException x) {
Net.translateToSocketException(x);
}
}
private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {
try {
return sc.getOption(name).booleanValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return false; // keep compiler happy
}
}
private int getIntOption(SocketOption<Integer> name) throws SocketException {
try {
return sc.getOption(name).intValue();
} catch (IOException x) {
Net.translateToSocketException(x);
return -1; // keep compiler happy
}
}
public void setTcpNoDelay(boolean on) throws SocketException {
opts().setTcpNoDelay(on);
setBooleanOption(StandardSocketOption.TCP_NODELAY, on);
}
public boolean getTcpNoDelay() throws SocketException {
return opts().getTcpNoDelay();
return getBooleanOption(StandardSocketOption.TCP_NODELAY);
}
public void setSoLinger(boolean on, int linger) throws SocketException {
opts().setSoLinger(on, linger);
if (!on)
linger = -1;
setIntOption(StandardSocketOption.SO_LINGER, linger);
}
public int getSoLinger() throws SocketException {
return opts().getSoLinger();
return getIntOption(StandardSocketOption.SO_LINGER);
}
public void sendUrgentData(int data) throws IOException {
@ -303,11 +340,11 @@ public class SocketAdaptor
}
public void setOOBInline(boolean on) throws SocketException {
opts().setOOBInline(on);
setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on);
}
public boolean getOOBInline() throws SocketException {
return opts().getOOBInline();
return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE);
}
public void setSoTimeout(int timeout) throws SocketException {
@ -321,48 +358,49 @@ public class SocketAdaptor
}
public void setSendBufferSize(int size) throws SocketException {
opts().setSendBufferSize(size);
// size 0 valid for SocketChannel, invalid for Socket
if (size <= 0)
throw new IllegalArgumentException("Invalid send size");
setIntOption(StandardSocketOption.SO_SNDBUF, size);
}
public int getSendBufferSize() throws SocketException {
return opts().getSendBufferSize();
return getIntOption(StandardSocketOption.SO_SNDBUF);
}
public void setReceiveBufferSize(int size) throws SocketException {
opts().setReceiveBufferSize(size);
// size 0 valid for SocketChannel, invalid for Socket
if (size <= 0)
throw new IllegalArgumentException("Invalid receive size");
setIntOption(StandardSocketOption.SO_RCVBUF, size);
}
public int getReceiveBufferSize() throws SocketException {
return opts().getReceiveBufferSize();
return getIntOption(StandardSocketOption.SO_RCVBUF);
}
public void setKeepAlive(boolean on) throws SocketException {
opts().setKeepAlive(on);
setBooleanOption(StandardSocketOption.SO_KEEPALIVE, on);
}
public boolean getKeepAlive() throws SocketException {
return opts().getKeepAlive();
return getBooleanOption(StandardSocketOption.SO_KEEPALIVE);
}
public void setTrafficClass(int tc) throws SocketException {
opts().setTrafficClass(tc);
trafficClass = tc;
setIntOption(StandardSocketOption.IP_TOS, tc);
}
public int getTrafficClass() throws SocketException {
int tc = opts().getTrafficClass();
if (tc < 0) {
tc = trafficClass;
}
return tc;
return getIntOption(StandardSocketOption.IP_TOS);
}
public void setReuseAddress(boolean on) throws SocketException {
opts().setReuseAddress(on);
setBooleanOption(StandardSocketOption.SO_REUSEADDR, on);
}
public boolean getReuseAddress() throws SocketException {
return opts().getReuseAddress();
return getBooleanOption(StandardSocketOption.SO_REUSEADDR);
}
public void close() throws IOException {
@ -402,7 +440,7 @@ public class SocketAdaptor
}
public boolean isBound() {
return sc.isBound();
return sc.localAddress() != null;
}
public boolean isClosed() {

View File

@ -31,6 +31,7 @@ import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
/**
@ -78,19 +79,16 @@ class SocketChannelImpl
private int state = ST_UNINITIALIZED;
// Binding
private SocketAddress localAddress = null;
private SocketAddress remoteAddress = null;
private SocketAddress localAddress;
private SocketAddress remoteAddress;
// Input/Output open
private boolean isInputOpen = true;
private boolean isOutputOpen = true;
private boolean readyToConnect = false;
// Options, created on demand
private SocketOpts.IP.TCP options = null;
// Socket adaptor, created on demand
private Socket socket = null;
private Socket socket;
// -- End of fields protected by stateLock
@ -114,6 +112,7 @@ class SocketChannelImpl
this.fd = fd;
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_CONNECTED;
this.localAddress = Net.localAddress(fd);
this.remoteAddress = remote;
}
@ -125,6 +124,98 @@ class SocketChannelImpl
}
}
@Override
public SocketAddress getLocalAddress() throws IOException {
synchronized (stateLock) {
if (!isOpen())
return null;
return localAddress;
}
}
@Override
public SocketAddress getConnectedAddress() throws IOException {
synchronized (stateLock) {
if (!isOpen())
return null;
return remoteAddress;
}
}
@Override
public SocketChannel setOption(SocketOption name, Object value)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("Invalid option name");
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
// special handling for IP_TOS: no-op when IPv6
if (name == StandardSocketOption.IP_TOS) {
if (!Net.isIPv6Available())
Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value);
return this;
}
// no options that require special handling
Net.setSocketOption(fd, Net.UNSPEC, name, value);
return this;
}
}
@Override
@SuppressWarnings("unchecked")
public <T> T getOption(SocketOption<T> name)
throws IOException
{
if (name == null)
throw new NullPointerException();
if (!options().contains(name))
throw new IllegalArgumentException("Invalid option name");
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
// special handling for IP_TOS: always return 0 when IPv6
if (name == StandardSocketOption.IP_TOS) {
return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) :
(T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name);
}
// no options that require special handling
return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
}
}
private static class LazyInitialization {
static final Set<SocketOption<?>> defaultOptions = defaultOptions();
private static Set<SocketOption<?>> defaultOptions() {
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
set.add(StandardSocketOption.SO_SNDBUF);
set.add(StandardSocketOption.SO_RCVBUF);
set.add(StandardSocketOption.SO_KEEPALIVE);
set.add(StandardSocketOption.SO_REUSEADDR);
set.add(StandardSocketOption.SO_LINGER);
set.add(StandardSocketOption.TCP_NODELAY);
// additional options required by socket adaptor
set.add(StandardSocketOption.IP_TOS);
set.add(ExtendedSocketOption.SO_OOBINLINE);
return Collections.unmodifiableSet(set);
}
}
@Override
public final Set<SocketOption<?>> options() {
return LazyInitialization.defaultOptions;
}
private boolean ensureReadOpen() throws ClosedChannelException {
synchronized (stateLock) {
if (!isOpen())
@ -410,43 +501,8 @@ class SocketChannelImpl
IOUtil.configureBlocking(fd, block);
}
public SocketOpts options() {
synchronized (stateLock) {
if (options == null) {
SocketOptsImpl.Dispatcher d
= new SocketOptsImpl.Dispatcher() {
int getInt(int opt) throws IOException {
return Net.getIntOption(fd, opt);
}
void setInt(int opt, int arg)
throws IOException
{
Net.setIntOption(fd, opt, arg);
}
};
options = new SocketOptsImpl.IP.TCP(d);
}
return options;
}
}
public boolean isBound() {
synchronized (stateLock) {
if (state == ST_CONNECTED)
return true;
return localAddress != null;
}
}
public SocketAddress localAddress() {
synchronized (stateLock) {
if (state == ST_CONNECTED &&
(localAddress == null ||
((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress())) {
// Socket was not bound before connecting or
// Socket was bound with an "anyLocalAddress"
localAddress = Net.localAddress(fd);
}
return localAddress;
}
}
@ -457,19 +513,25 @@ class SocketChannelImpl
}
}
public void bind(SocketAddress local) throws IOException {
@Override
public SocketChannel bind(SocketAddress local) throws IOException {
synchronized (readLock) {
synchronized (writeLock) {
synchronized (stateLock) {
ensureOpenAndUnconnected();
if (!isOpen())
throw new ClosedChannelException();
if (state == ST_PENDING)
throw new ConnectionPendingException();
if (localAddress != null)
throw new AlreadyBoundException();
InetSocketAddress isa = Net.checkAddress(local);
InetSocketAddress isa = (local == null) ?
new InetSocketAddress(0) : Net.checkAddress(local);
Net.bind(fd, isa.getAddress(), isa.getPort());
localAddress = Net.localAddress(fd);
}
}
}
return this;
}
public boolean isConnected() {
@ -496,7 +558,6 @@ class SocketChannelImpl
}
public boolean connect(SocketAddress sa) throws IOException {
int trafficClass = 0; // ## Pick up from options
int localPort = 0;
synchronized (readLock) {
@ -524,13 +585,24 @@ class SocketChannelImpl
ia = InetAddress.getLocalHost();
n = Net.connect(fd,
ia,
isa.getPort(),
trafficClass);
isa.getPort());
if ( (n == IOStatus.INTERRUPTED)
&& isOpen())
continue;
break;
}
synchronized (stateLock) {
if (isOpen() && (localAddress == null) ||
((InetSocketAddress)localAddress)
.getAddress().isAnyLocalAddress())
{
// Socket was not bound before connecting or
// Socket was bound with an "anyLocalAddress"
localAddress = Net.localAddress(fd);
}
}
} finally {
readerCleanup();
end((n > 0) || (n == IOStatus.UNAVAILABLE));
@ -646,29 +718,37 @@ class SocketChannelImpl
}
}
public final static int SHUT_RD = 0;
public final static int SHUT_WR = 1;
public final static int SHUT_RDWR = 2;
public void shutdownInput() throws IOException {
@Override
public SocketChannel shutdownInput() throws IOException {
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
isInputOpen = false;
shutdown(fd, SHUT_RD);
if (readerThread != 0)
NativeThread.signal(readerThread);
if (!isConnected())
throw new NotYetConnectedException();
if (isInputOpen) {
Net.shutdown(fd, Net.SHUT_RD);
if (readerThread != 0)
NativeThread.signal(readerThread);
isInputOpen = false;
}
return this;
}
}
public void shutdownOutput() throws IOException {
@Override
public SocketChannel shutdownOutput() throws IOException {
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
isOutputOpen = false;
shutdown(fd, SHUT_WR);
if (writerThread != 0)
NativeThread.signal(writerThread);
if (!isConnected())
throw new NotYetConnectedException();
if (isOutputOpen) {
Net.shutdown(fd, Net.SHUT_WR);
if (writerThread != 0)
NativeThread.signal(writerThread);
isOutputOpen = false;
}
return this;
}
}
@ -869,9 +949,6 @@ class SocketChannelImpl
boolean block, boolean ready)
throws IOException;
private static native void shutdown(FileDescriptor fd, int how)
throws IOException;
static {
Util.load();
nd = new SocketDispatcher();

View File

@ -1,115 +0,0 @@
/*
* Copyright 2001 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.nio.*;
import java.net.NetworkInterface;
// Typical use:
//
// sc.options()
// .noDelay(true)
// .typeOfService(SocketOpts.IP.TOS_RELIABILITY)
// .sendBufferSize(1024)
// .receiveBufferSize(1024)
// .keepAlive(true);
//
public interface SocketOpts { // SocketOptions already used in java.net
// Options that apply to all kinds of sockets
// SO_BROADCAST
public abstract boolean broadcast() throws IOException;
public abstract SocketOpts broadcast(boolean b) throws IOException;
// SO_KEEPALIVE
public abstract boolean keepAlive() throws IOException;
public abstract SocketOpts keepAlive(boolean b) throws IOException;
// SO_LINGER
public abstract int linger() throws IOException;
public abstract SocketOpts linger(int n) throws IOException;
// SO_OOBINLINE
public abstract boolean outOfBandInline() throws IOException;
public abstract SocketOpts outOfBandInline(boolean b) throws IOException;
// SO_RCVBUF
public abstract int receiveBufferSize() throws IOException;
public abstract SocketOpts receiveBufferSize(int n) throws IOException;
// SO_SNDBUF
public abstract int sendBufferSize() throws IOException;
public abstract SocketOpts sendBufferSize(int n) throws IOException;
// SO_REUSEADDR
public abstract boolean reuseAddress() throws IOException;
public abstract SocketOpts reuseAddress(boolean b) throws IOException;
// IP-specific options
public static interface IP
extends SocketOpts
{
// IP_MULTICAST_IF2
public abstract NetworkInterface multicastInterface()
throws IOException;
public abstract IP multicastInterface(NetworkInterface ni)
throws IOException;
// IP_MULTICAST_LOOP
public abstract boolean multicastLoop() throws IOException;
public abstract IP multicastLoop(boolean b) throws IOException;
// IP_TOS
public static final int TOS_LOWDELAY = 0x10;
public static final int TOS_THROUGHPUT = 0x08;
public static final int TOS_RELIABILITY = 0x04;
public static final int TOS_MINCOST = 0x02;
public abstract int typeOfService() throws IOException;
public abstract IP typeOfService(int tos) throws IOException;
// TCP-specific options
public static interface TCP
extends IP
{
// TCP_NODELAY
public abstract boolean noDelay() throws IOException;
public abstract TCP noDelay(boolean b) throws IOException;
}
}
}

View File

@ -1,318 +0,0 @@
/*
* Copyright 2001 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.NetworkInterface;
import java.net.SocketOptions;
import java.nio.channels.*;
class SocketOptsImpl
implements SocketOpts
{
static abstract class Dispatcher {
abstract int getInt(int opt) throws IOException;
abstract void setInt(int opt, int arg) throws IOException;
// Others that pass addresses, etc., will come later
}
private final Dispatcher d;
SocketOptsImpl(Dispatcher d) {
this.d = d;
}
protected boolean getBoolean(int opt) throws IOException {
return d.getInt(opt) > 0;
}
protected void setBoolean(int opt, boolean b) throws IOException {
d.setInt(opt, b ? 1 : 0);
}
protected int getInt(int opt) throws IOException {
return d.getInt(opt);
}
protected void setInt(int opt, int n) throws IOException {
d.setInt(opt, n);
}
protected NetworkInterface getNetworkInterface(int opt)
throws IOException
{
throw new UnsupportedOperationException("NYI");
}
protected void setNetworkInterface(int opt, NetworkInterface ni)
throws IOException
{
throw new UnsupportedOperationException("NYI");
}
protected void addToString(StringBuffer sb, String s) {
char c = sb.charAt(sb.length() - 1);
if ((c != '[') && (c != '='))
sb.append(' ');
sb.append(s);
}
protected void addToString(StringBuffer sb, int n) {
addToString(sb, Integer.toString(n));
}
// SO_BROADCAST
public boolean broadcast() throws IOException {
return getBoolean(SocketOptions.SO_BROADCAST);
}
public SocketOpts broadcast(boolean b) throws IOException {
setBoolean(SocketOptions.SO_BROADCAST, b);
return this;
}
// SO_KEEPALIVE
public boolean keepAlive() throws IOException {
return getBoolean(SocketOptions.SO_KEEPALIVE);
}
public SocketOpts keepAlive(boolean b) throws IOException {
setBoolean(SocketOptions.SO_KEEPALIVE, b);
return this;
}
// SO_LINGER
public int linger() throws IOException {
return getInt(SocketOptions.SO_LINGER);
}
public SocketOpts linger(int n) throws IOException {
setInt(SocketOptions.SO_LINGER, n);
return this;
}
// SO_OOBINLINE
public boolean outOfBandInline() throws IOException {
return getBoolean(SocketOptions.SO_OOBINLINE);
}
public SocketOpts outOfBandInline(boolean b) throws IOException {
setBoolean(SocketOptions.SO_OOBINLINE, b);
return this;
}
// SO_RCVBUF
public int receiveBufferSize() throws IOException {
return getInt(SocketOptions.SO_RCVBUF);
}
public SocketOpts receiveBufferSize(int n) throws IOException {
if (n <= 0)
throw new IllegalArgumentException("Invalid receive size");
setInt(SocketOptions.SO_RCVBUF, n);
return this;
}
// SO_SNDBUF
public int sendBufferSize() throws IOException {
return getInt(SocketOptions.SO_SNDBUF);
}
public SocketOpts sendBufferSize(int n) throws IOException {
if (n <= 0)
throw new IllegalArgumentException("Invalid send size");
setInt(SocketOptions.SO_SNDBUF, n);
return this;
}
// SO_REUSEADDR
public boolean reuseAddress() throws IOException {
return getBoolean(SocketOptions.SO_REUSEADDR);
}
public SocketOpts reuseAddress(boolean b) throws IOException {
setBoolean(SocketOptions.SO_REUSEADDR, b);
return this;
}
// toString
protected void toString(StringBuffer sb) throws IOException {
int n;
if (broadcast())
addToString(sb, "broadcast");
if (keepAlive())
addToString(sb, "keepalive");
if ((n = linger()) > 0) {
addToString(sb, "linger=");
addToString(sb, n);
}
if (outOfBandInline())
addToString(sb, "oobinline");
if ((n = receiveBufferSize()) > 0) {
addToString(sb, "rcvbuf=");
addToString(sb, n);
}
if ((n = sendBufferSize()) > 0) {
addToString(sb, "sndbuf=");
addToString(sb, n);
}
if (reuseAddress())
addToString(sb, "reuseaddr");
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(this.getClass().getInterfaces()[0].getName());
sb.append('[');
int i = sb.length();
try {
toString(sb);
} catch (IOException x) {
sb.setLength(i);
sb.append("closed");
}
sb.append(']');
return sb.toString();
}
// IP-specific socket options
static class IP
extends SocketOptsImpl
implements SocketOpts.IP
{
IP(Dispatcher d) {
super(d);
}
// IP_MULTICAST_IF2
// ## Do we need IP_MULTICAST_IF also?
public NetworkInterface multicastInterface() throws IOException {
return getNetworkInterface(SocketOptions.IP_MULTICAST_IF2);
}
public SocketOpts.IP multicastInterface(NetworkInterface ni)
throws IOException
{
setNetworkInterface(SocketOptions.IP_MULTICAST_IF2, ni);
return this;
}
// IP_MULTICAST_LOOP
public boolean multicastLoop() throws IOException {
return getBoolean(SocketOptions.IP_MULTICAST_LOOP);
}
public SocketOpts.IP multicastLoop(boolean b) throws IOException {
setBoolean(SocketOptions.IP_MULTICAST_LOOP, b);
return this;
}
// IP_TOS
public int typeOfService() throws IOException {
return getInt(SocketOptions.IP_TOS);
}
public SocketOpts.IP typeOfService(int tos) throws IOException {
setInt(SocketOptions.IP_TOS, tos);
return this;
}
// toString
protected void toString(StringBuffer sb) throws IOException {
super.toString(sb);
int n;
if ((n = typeOfService()) > 0) {
addToString(sb, "tos=");
addToString(sb, n);
}
}
// TCP-specific IP options
public static class TCP
extends SocketOptsImpl.IP
implements SocketOpts.IP.TCP
{
TCP(Dispatcher d) {
super(d);
}
// TCP_NODELAY
public boolean noDelay() throws IOException {
return getBoolean(SocketOptions.TCP_NODELAY);
}
public SocketOpts.IP.TCP noDelay(boolean b) throws IOException {
setBoolean(SocketOptions.TCP_NODELAY, b);
return this;
}
// toString
protected void toString(StringBuffer sb) throws IOException {
super.toString(sb);
if (noDelay())
addToString(sb, "nodelay");
}
}
}
}

View File

@ -82,7 +82,7 @@ void init(JNIEnv *env) {
}
}
jobject
JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
jobject iaObj;
init(env);
@ -159,7 +159,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
return iaObj;
}
jint
JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
{
jint family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?

View File

@ -116,7 +116,7 @@ NET_AllocSockaddr(struct sockaddr **him, int *len);
JNIEXPORT int JNICALL
NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress);
jobject
JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
void initLocalAddrTable ();
@ -124,10 +124,10 @@ void initLocalAddrTable ();
void
NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
jint
JNIEXPORT jint JNICALL
NET_GetPortFromSockaddr(struct sockaddr *him);
jint
JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
int

View File

@ -0,0 +1,129 @@
/*
* Copyright 2007 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 <stdio.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif
/**
* Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
* socket options to the platform specific level and option.
*/
static void out(char* s) {
printf("%s\n", s);
}
static void emit(const char *name, char * family, int level, int optname) {
printf(" map.put(new RegistryKey(%s, %s),", name, family);
printf(" new OptionKey(%d, %d));\n", level, optname);
}
static void emit_unspec(const char *name, int level, int optname) {
emit(name, "Net.UNSPEC", level, optname);
}
static void emit_inet(const char *name, int level, int optname) {
emit(name, "StandardProtocolFamily.INET", level, optname);
}
static void emit_inet6(const char *name, int level, int optname) {
emit(name, "StandardProtocolFamily.INET6", level, optname);
}
int main(int argc, const char* argv[]) {
out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT ");
out("package sun.nio.ch; ");
out("import java.net.SocketOption; ");
out("import java.net.StandardSocketOption; ");
out("import java.net.ProtocolFamily; ");
out("import java.net.StandardProtocolFamily; ");
out("import java.util.Map; ");
out("import java.util.HashMap; ");
out("class SocketOptionRegistry { ");
out(" private SocketOptionRegistry() { } ");
out(" private static class RegistryKey { ");
out(" private final SocketOption name; ");
out(" private final ProtocolFamily family; ");
out(" RegistryKey(SocketOption name, ProtocolFamily family) { ");
out(" this.name = name; ");
out(" this.family = family; ");
out(" } ");
out(" public int hashCode() { ");
out(" return name.hashCode() + family.hashCode(); ");
out(" } ");
out(" public boolean equals(Object ob) { ");
out(" if (ob == null) return false; ");
out(" if (!(ob instanceof RegistryKey)) return false; ");
out(" RegistryKey other = (RegistryKey)ob; ");
out(" if (this.name != other.name) return false; ");
out(" if (this.family != other.family) return false; ");
out(" return true; ");
out(" } ");
out(" } ");
out(" private static class LazyInitialization { ");
out(" static final Map<RegistryKey,OptionKey> options = options(); ");
out(" private static Map<RegistryKey,OptionKey> options() { ");
out(" Map<RegistryKey,OptionKey> map = ");
out(" new HashMap<RegistryKey,OptionKey>(); ");
emit_unspec("StandardSocketOption.SO_BROADCAST", SOL_SOCKET, SO_BROADCAST);
emit_unspec("StandardSocketOption.SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE);
emit_unspec("StandardSocketOption.SO_LINGER", SOL_SOCKET, SO_LINGER);
emit_unspec("StandardSocketOption.SO_SNDBUF", SOL_SOCKET, SO_SNDBUF);
emit_unspec("StandardSocketOption.SO_RCVBUF", SOL_SOCKET, SO_RCVBUF);
emit_unspec("StandardSocketOption.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
emit_unspec("StandardSocketOption.TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY);
emit_inet("StandardSocketOption.IP_TOS", IPPROTO_IP, IP_TOS);
emit_inet("StandardSocketOption.IP_MULTICAST_IF", IPPROTO_IP, IP_MULTICAST_IF);
emit_inet("StandardSocketOption.IP_MULTICAST_TTL", IPPROTO_IP, IP_MULTICAST_TTL);
emit_inet("StandardSocketOption.IP_MULTICAST_LOOP", IPPROTO_IP, IP_MULTICAST_LOOP);
#ifdef AF_INET6
emit_inet6("StandardSocketOption.IP_MULTICAST_IF", IPPROTO_IPV6, IPV6_MULTICAST_IF);
emit_inet6("StandardSocketOption.IP_MULTICAST_TTL", IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
emit_inet6("StandardSocketOption.IP_MULTICAST_LOOP", IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
#endif
emit_unspec("ExtendedSocketOption.SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE);
out(" return map; ");
out(" } ");
out(" } ");
out(" public static OptionKey findOption(SocketOption name, ProtocolFamily family) { ");
out(" RegistryKey key = new RegistryKey(name, family); ");
out(" return LazyInitialization.options.get(key); ");
out(" } ");
out("} ");
return 0;
}

View File

@ -0,0 +1,127 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.net.SocketException;
/**
* Parses and represents a multicast address.
*/
class MulticastAddress {
private final InetAddress group;
private final int port;
private final NetworkInterface interf;
private MulticastAddress(InetAddress group, int port, NetworkInterface interf) {
this.group = group;
this.port = port;
this.interf = interf;
}
InetAddress group() {
return group;
}
int port() {
return port;
}
/**
* @return The network interface, may be {@code null}
*/
NetworkInterface interf() {
return interf;
}
/**
* Parses a string of the form "group:port[@interface]", returning
* a MulticastAddress representing the address
*/
static MulticastAddress parse(String s) {
String[] components = s.split("@");
if (components.length > 2)
throw new IllegalArgumentException("At most one '@' expected");
// get group and port
String target = components[0];
int len = components[0].length();
int colon = components[0].lastIndexOf(':');
if ((colon < 1) || (colon > (len-2)))
throw new IllegalArgumentException("group:port expected");
String groupString = target.substring(0, colon);
int port = -1;
try {
port = Integer.parseInt(target.substring(colon+1, len));
} catch (NumberFormatException x) {
throw new IllegalArgumentException(x);
}
// handle IPv6 literal address
if (groupString.charAt(0) == '[') {
len = groupString.length();
if (groupString.charAt(len-1) != ']')
throw new IllegalArgumentException("missing ']'");
groupString = groupString.substring(1,len-1);
if (groupString.length() == 0)
throw new IllegalArgumentException("missing IPv6 address");
}
// get group address
InetAddress group = null;
try {
group = InetAddress.getByName(groupString);
} catch (UnknownHostException x) {
throw new IllegalArgumentException(x);
}
if (!group.isMulticastAddress()) {
throw new IllegalArgumentException("'" + group.getHostAddress() +
"' is not multicast address");
}
// optional interface
NetworkInterface interf = null;
if (components.length == 2) {
try {
interf = NetworkInterface.getByName(components[1]);
} catch (SocketException x) {
throw new IllegalArgumentException(x);
}
if (interf == null) {
throw new IllegalArgumentException("'" + components[1] +
"' is not valid interface");
}
}
return new MulticastAddress(group, port, interf);
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.nio.channels.*;
import java.nio.charset.*;
import java.nio.ByteBuffer;
import java.net.*;
import java.io.IOException;
import java.util.*;
public class Reader {
static void usage() {
System.err.println("usage: java Reader group:port@interf [-only source...] [-block source...]");
System.exit(-1);
}
static void printDatagram(SocketAddress sa, ByteBuffer buf) {
System.out.format("-- datagram from %s --\n",
((InetSocketAddress)sa).getAddress().getHostAddress());
System.out.println(Charset.defaultCharset().decode(buf));
}
static void parseAddessList(String s, List<InetAddress> list)
throws UnknownHostException
{
String[] sources = s.split(",");
for (int i=0; i<sources.length; i++) {
list.add(InetAddress.getByName(sources[i]));
}
}
public static void main(String[] args) throws IOException {
if (args.length == 0)
usage();
// first parameter is the multicast address (interface required)
MulticastAddress target = MulticastAddress.parse(args[0]);
if (target.interf() == null)
usage();
// addition arguments are source addresses to include or exclude
List<InetAddress> includeList = new ArrayList<InetAddress>();
List<InetAddress> excludeList = new ArrayList<InetAddress>();
int argc = 1;
while (argc < args.length) {
String option = args[argc++];
if (argc >= args.length)
usage();
String value = args[argc++];
if (option.equals("-only")) {
parseAddessList(value, includeList);
continue;
}
if (option.equals("-block")) {
parseAddessList(value, excludeList);
continue;
}
usage();
}
if (!includeList.isEmpty() && !excludeList.isEmpty()) {
usage();
}
// create and bind socket
ProtocolFamily family = StandardProtocolFamily.INET;
if (target.group() instanceof Inet6Address) {
family = StandardProtocolFamily.INET6;
}
DatagramChannel dc = DatagramChannel.open(family)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(target.port()));
if (includeList.isEmpty()) {
// join group and block addresses on the exclude list
MembershipKey key = dc.join(target.group(), target.interf());
for (InetAddress source: excludeList) {
key.block(source);
}
} else {
// join with source-specific membership for each source
for (InetAddress source: includeList) {
dc.join(target.group(), target.interf(), source);
}
}
// register socket with Selector
Selector sel = Selector.open();
dc.configureBlocking(false);
dc.register(sel, SelectionKey.OP_READ);
// print out each datagram that we receive
ByteBuffer buf = ByteBuffer.allocateDirect(4096);
for (;;) {
int updated = sel.select();
if (updated > 0) {
Iterator<SelectionKey> iter = sel.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey sk = iter.next();
iter.remove();
DatagramChannel ch = (DatagramChannel)sk.channel();
SocketAddress sa = ch.receive(buf);
if (sa != null) {
buf.flip();
printDatagram(sa, buf);
buf.rewind();
buf.limit(buf.capacity());
}
}
}
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.net.*;
import java.io.IOException;
import java.util.*;
/**
* Sample multicast sender to send a message in a multicast datagram
* to a given group.
*/
public class Sender {
private static void usage() {
System.err.println("usage: java Sender group:port[@interface] message");
System.exit(-1);
}
public static void main(String[] args) throws IOException {
if (args.length < 2)
usage();
MulticastAddress target = MulticastAddress.parse(args[0]);
// create socket
ProtocolFamily family = StandardProtocolFamily.INET;
if (target.group() instanceof Inet6Address)
family = StandardProtocolFamily.INET6;
DatagramChannel dc = DatagramChannel.open(family).bind(new InetSocketAddress(0));
if (target.interf() != null) {
dc.setOption(StandardSocketOption.IP_MULTICAST_IF, target.interf());
}
// send multicast packet
dc.send(Charset.defaultCharset().encode(args[1]),
new InetSocketAddress(target.group(), target.port()));
dc.close();
}
}

View File

@ -791,7 +791,7 @@ NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
#endif /* AF_INET6 */
}
jint
JNIEXPORT jint JNICALL
NET_GetPortFromSockaddr(struct sockaddr *him) {
#ifdef AF_INET6
if (him->sa_family == AF_INET6) {

View File

@ -198,7 +198,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jobject fdo, jlong address,
jboolean preferIPv6, jobject fdo, jlong address,
jint len, jobject dest)
{
jint fd = fdval(env, fdo);
@ -215,7 +215,7 @@ Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
if (NET_InetAddressToSockaddr(env, destAddress, destPort,
(struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
&sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}

View File

@ -33,12 +33,6 @@
static jfieldID key_st_dev; /* id for FileKey.st_dev */
static jfieldID key_st_ino; /* id for FileKey.st_ino */
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while ((_result == -1) && (errno == EINTR)); \
} while(0)
JNIEXPORT void JNICALL
Java_sun_nio_ch_FileKey_initIDs(JNIEnv *env, jclass clazz)

View File

@ -37,61 +37,171 @@
#include "net_util.h"
#include "net_util_md.h"
#include "nio_util.h"
#include "java_net_SocketOptions.h"
#include "nio.h"
#ifdef __linux__
#include <sys/utsname.h>
/**
* Definitions for source-specific multicast to allow for building
* with older header files.
*/
#define IPV6_MULTICAST_IF 17
#ifndef SO_BSDCOMPAT
#define SO_BSDCOMPAT 14
#ifdef __solaris__
#ifndef IP_BLOCK_SOURCE
#define IP_BLOCK_SOURCE 0x15
#define IP_UNBLOCK_SOURCE 0x16
#define IP_ADD_SOURCE_MEMBERSHIP 0x17
#define IP_DROP_SOURCE_MEMBERSHIP 0x18
#define MCAST_BLOCK_SOURCE 0x2b
#define MCAST_UNBLOCK_SOURCE 0x2c
#define MCAST_JOIN_SOURCE_GROUP 0x2d
#define MCAST_LEAVE_SOURCE_GROUP 0x2e
#endif /* IP_BLOCK_SOURCE */
struct my_ip_mreq_source {
struct in_addr imr_multiaddr;
struct in_addr imr_sourceaddr;
struct in_addr imr_interface;
};
/*
* Use #pragma pack() construct to force 32-bit alignment on amd64.
*/
#if defined(amd64)
#pragma pack(4)
#endif
struct my_group_source_req {
uint32_t gsr_interface; /* interface index */
struct sockaddr_storage gsr_group; /* group address */
struct sockaddr_storage gsr_source; /* source address */
};
#if defined(amd64)
#pragma pack()
#endif
#endif /* __solaris__ */
#ifdef __linux__
#ifndef IP_BLOCK_SOURCE
#define IP_BLOCK_SOURCE 38
#define IP_UNBLOCK_SOURCE 37
#define IP_ADD_SOURCE_MEMBERSHIP 39
#define IP_DROP_SOURCE_MEMBERSHIP 40
#define MCAST_BLOCK_SOURCE 43
#define MCAST_UNBLOCK_SOURCE 44
#define MCAST_JOIN_SOURCE_GROUP 42
#define MCAST_LEAVE_SOURCE_GROUP 45
#endif /* IP_BLOCK_SOURCE */
struct my_ip_mreq_source {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
struct in_addr imr_sourceaddr;
};
struct my_group_source_req {
uint32_t gsr_interface; /* interface index */
struct sockaddr_storage gsr_group; /* group address */
struct sockaddr_storage gsr_source; /* source address */
};
#endif /* __linux__ */
#define COPY_INET6_ADDRESS(env, source, target) \
(*env)->GetByteArrayRegion(env, source, 0, 16, target)
/*
* Copy IPv6 group, interface index, and IPv6 source address
* into group_source_req structure.
*/
static void initGroupSourceReq(JNIEnv* env, jbyteArray group, jint index,
jbyteArray source, struct my_group_source_req* req)
{
struct sockaddr_in6* sin6;
req->gsr_interface = (uint32_t)index;
sin6 = (struct sockaddr_in6*)&(req->gsr_group);
sin6->sin6_family = AF_INET6;
COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
sin6 = (struct sockaddr_in6*)&(req->gsr_source);
sin6->sin6_family = AF_INET6;
COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
{
/* Here because Windows native code does need to init IDs */
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
{
return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT int JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
jboolean reuse)
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse)
{
int fd;
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
int domain = (ipv6_available() && preferIPv6) ? AF_INET6 : AF_INET;
#ifdef AF_INET6
if (ipv6_available())
fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
else
#endif /* AF_INET6 */
fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
fd = socket(domain, type, 0);
if (fd < 0) {
return handleSocketError(env, errno);
}
if (reuse) {
int arg = 1;
if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
sizeof(arg)) < 0) {
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
sizeof(arg)) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.setIntOption");
close(fd);
return -1;
}
}
#ifdef __linux__
/* By default, Linux uses the route default */
if (domain == AF_INET6 && type == SOCK_DGRAM) {
int arg = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
sizeof(arg)) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.setIntOption");
close(fd);
return -1;
}
}
#endif
return fd;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
jobject fdo, jobject ia, int port)
Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
jobject fdo, jobject iao, int port)
{
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
int rv = 0;
if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
return;
}
@ -101,27 +211,27 @@ Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
{
if (listen(fdval(env, fdo), backlog) < 0)
handleSocketError(env, errno);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz,
jobject fdo, jobject iao, jint port,
jint trafficClass)
Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
jobject fdo, jobject iao, jint port)
{
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
int rv;
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, JNI_TRUE) != 0) {
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa,
&sa_len, preferIPv6) != 0)
{
return IOS_THROWN;
}
#ifdef AF_INET6
#if 0
if (trafficClass != 0 && ipv6_available()) { /* ## FIX */
NET_SetTrafficClass((struct sockaddr *)&sa, trafficClass);
}
#endif
#endif
rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
if (rv != 0) {
if (errno == EINPROGRESS) {
@ -159,119 +269,79 @@ Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
}
#ifdef NEEDED
/* ## This is gross. We should generate platform-specific constant
* ## definitions into a .java file and use those directly.
*/
static int
mapOption(JNIEnv *env, int opt, int *klevel, int *kopt)
{
switch (opt) {
case java_net_SocketOptions_IP_TOS:
*klevel = IPPROTO_IP;
*kopt = IP_TOS;
break;
case java_net_SocketOptions_SO_BROADCAST:
case java_net_SocketOptions_SO_KEEPALIVE:
case java_net_SocketOptions_SO_LINGER:
case java_net_SocketOptions_SO_OOBINLINE:
case java_net_SocketOptions_SO_RCVBUF:
case java_net_SocketOptions_SO_REUSEADDR:
case java_net_SocketOptions_SO_SNDBUF:
*klevel = SOL_SOCKET;
break;
case java_net_SocketOptions_TCP_NODELAY:
*klevel = IPPROTO_IP;
*kopt = TCP_NODELAY;
return 0;
default:
JNU_ThrowByName(env, "java/lang/IllegalArgumentException", NULL);
return -1;
}
switch (opt) {
case java_net_SocketOptions_SO_BROADCAST: *kopt = SO_BROADCAST; break;
case java_net_SocketOptions_SO_KEEPALIVE: *kopt = SO_KEEPALIVE; break;
case java_net_SocketOptions_SO_LINGER: *kopt = SO_LINGER; break;
case java_net_SocketOptions_SO_OOBINLINE: *kopt = SO_OOBINLINE; break;
case java_net_SocketOptions_SO_RCVBUF: *kopt = SO_RCVBUF; break;
case java_net_SocketOptions_SO_REUSEADDR: *kopt = SO_REUSEADDR; break;
case java_net_SocketOptions_SO_SNDBUF: *kopt = SO_SNDBUF; break;
default:
return -1;
}
return 0;
}
#endif
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
jobject fdo, jint opt)
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
jboolean mayNeedConversion, jint level, jint opt)
{
int klevel, kopt;
int result;
struct linger linger;
u_char carg;
void *arg;
int arglen;
int arglen, n;
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"Unsupported socket option");
return -1;
/* Option value is an int except for a few specific cases */
arg = (void *)&result;
arglen = sizeof(result);
if (level == IPPROTO_IP &&
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
arg = (void*)&carg;
arglen = sizeof(carg);
}
if (opt == java_net_SocketOptions_SO_LINGER) {
if (level == SOL_SOCKET && opt == SO_LINGER) {
arg = (void *)&linger;
arglen = sizeof(linger);
} else {
arg = (void *)&result;
arglen = sizeof(result);
}
if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
if (mayNeedConversion) {
n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
} else {
n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
}
if (n < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.getIntOption");
return -1;
}
if (opt == java_net_SocketOptions_SO_LINGER)
return linger.l_onoff ? linger.l_linger : -1;
else
return result;
if (level == IPPROTO_IP &&
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP))
{
return (jint)carg;
}
if (level == SOL_SOCKET && opt == SO_LINGER)
return linger.l_onoff ? (jint)linger.l_linger : (jint)-1;
return (jint)result;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
jobject fdo, jint opt, jint arg)
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
jboolean mayNeedConversion, jint level, jint opt, jint arg)
{
int klevel, kopt;
int result;
struct linger linger;
u_char carg;
void *parg;
int arglen;
int arglen, n;
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"Unsupported socket option");
return;
/* Option value is an int except for a few specific cases */
parg = (void*)&arg;
arglen = sizeof(arg);
if (level == IPPROTO_IP &&
(opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
parg = (void*)&carg;
arglen = sizeof(carg);
carg = (u_char)arg;
}
if (opt == java_net_SocketOptions_SO_LINGER) {
if (level == SOL_SOCKET && opt == SO_LINGER) {
parg = (void *)&linger;
arglen = sizeof(linger);
if (arg >= 0) {
@ -281,19 +351,199 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
linger.l_onoff = 0;
linger.l_linger = 0;
}
} else {
parg = (void *)&arg;
arglen = sizeof(arg);
}
if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
if (mayNeedConversion) {
n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
} else {
n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
}
if (n < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.setIntOption");
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
jint group, jint interf, jint source)
{
struct ip_mreq mreq;
struct my_ip_mreq_source mreq_source;
int opt, n, optlen;
void* optval;
if (source == 0) {
mreq.imr_multiaddr.s_addr = htonl(group);
mreq.imr_interface.s_addr = htonl(interf);
opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
optval = (void*)&mreq;
optlen = sizeof(mreq);
} else {
mreq_source.imr_multiaddr.s_addr = htonl(group);
mreq_source.imr_sourceaddr.s_addr = htonl(source);
mreq_source.imr_interface.s_addr = htonl(interf);
opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
optval = (void*)&mreq_source;
optlen = sizeof(mreq_source);
}
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
if (n < 0) {
if (join && (errno == ENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
jint group, jint interf, jint source)
{
struct my_ip_mreq_source mreq_source;
int n;
int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
mreq_source.imr_multiaddr.s_addr = htonl(group);
mreq_source.imr_sourceaddr.s_addr = htonl(source);
mreq_source.imr_interface.s_addr = htonl(interf);
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
(void*)&mreq_source, sizeof(mreq_source));
if (n < 0) {
if (block && (errno == ENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
jbyteArray group, jint index, jbyteArray source)
{
struct ipv6_mreq mreq6;
struct my_group_source_req req;
int opt, n, optlen;
void* optval;
if (source == NULL) {
COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
mreq6.ipv6mr_interface = (int)index;
opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
optval = (void*)&mreq6;
optlen = sizeof(mreq6);
} else {
#ifdef __linux__
/* Include-mode filtering broken on Linux at least to 2.6.24 */
return IOS_UNAVAILABLE;
#else
initGroupSourceReq(env, group, index, source, &req);
opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
optval = (void*)&req;
optlen = sizeof(req);
#endif
}
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen);
if (n < 0) {
if (join && (errno == ENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
jbyteArray group, jint index, jbyteArray source)
{
struct my_group_source_req req;
int n;
int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
initGroupSourceReq(env, group, index, source, &req);
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
(void*)&req, sizeof(req));
if (n < 0) {
if (block && (errno == ENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
{
struct in_addr in;
int arglen = sizeof(struct in_addr);
int n;
in.s_addr = htonl(interf);
n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
(void*)&(in.s_addr), arglen);
if (n < 0) {
handleSocketError(env, errno);
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
{
struct in_addr in;
int arglen = sizeof(struct in_addr);
int n;
n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
if (n < 0) {
handleSocketError(env, errno);
return -1;
}
return ntohl(in.s_addr);
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
{
int value = (jint)index;
int arglen = sizeof(value);
int n;
n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
(void*)&(index), arglen);
if (n < 0) {
handleSocketError(env, errno);
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
{
int index;
int arglen = sizeof(index);
int n;
n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
if (n < 0) {
handleSocketError(env, errno);
return -1;
}
return (jint)index;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow)
{
int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
(jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
if (shutdown(fdval(env, fdo), how) < 0)
handleSocketError(env, errno);
}
/* Declared in nio_util.h */

View File

@ -65,14 +65,6 @@ Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv *env, jclass c)
"(Ljava/net/InetAddress;I)V");
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_ServerSocketChannelImpl_listen(JNIEnv *env, jclass cl,
jobject fdo, jint backlog)
{
if (listen(fdval(env, fdo), backlog) < 0)
handleSocketError(env, errno);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
jobject ssfdo, jobject newfdo,

View File

@ -35,10 +35,6 @@
#include <netinet/in.h>
#endif
#if defined(__solaris__) && !defined(_SOCKLEN_T)
typedef size_t socklen_t; /* New in SunOS 5.7, so need this for 5.6 */
#endif
#include "jni.h"
#include "jni_util.h"
#include "net_util.h"
@ -88,12 +84,3 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
}
return 0;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_SocketChannelImpl_shutdown(JNIEnv *env, jclass cl,
jobject fdo, jint how)
{
if (shutdown(fdval(env, fdo), how) < 0)
handleSocketError(env, errno);
}

View File

@ -27,8 +27,15 @@
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include <errno.h>
#include <sys/types.h>
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \
} while(0)
/* NIO utility procedures */

View File

@ -889,7 +889,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr
return 0;
}
jint
JNIEXPORT jint JNICALL
NET_GetPortFromSockaddr(struct sockaddr *him) {
if (him->sa_family == AF_INET6) {
return ntohs(((struct sockaddr_in6*)him)->sin6_port);

View File

@ -39,46 +39,9 @@ static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
static jfieldID ia_addrID;
static jfieldID ia_famID;
static jclass isa_class; /* java.net.InetSocketAddress */
static jclass ia_class;
static jmethodID isa_ctorID; /* .InetSocketAddress(InetAddress, int) */
static jmethodID ia_ctorID;
static jmethodID isa_ctorID; /* java.net.InetSocketAddress(InetAddress, int) */
/*
* Returns JNI_TRUE if DatagramChannelImpl has already cached an
* InetAddress/port corresponding to the socket address.
*/
static jboolean isSenderCached(JNIEnv *env, jobject this, struct sockaddr_in *sa) {
jobject senderAddr;
/* shouldn't happen until we have dual IPv4/IPv6 stack (post-XP ?) */
if (sa->sin_family != AF_INET) {
return JNI_FALSE;
}
/*
* Compare source address to cached InetAddress
*/
senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
if (senderAddr == NULL) {
return JNI_FALSE;
}
if ((jint)ntohl(sa->sin_addr.s_addr) !=
(*env)->GetIntField(env, senderAddr, ia_addrID)) {
return JNI_FALSE;
}
/*
* Compare source port to cached port
*/
if ((jint)ntohs(sa->sin_port) !=
(*env)->GetIntField(env, this, dci_senderPortID)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
@ -99,32 +62,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
"Ljava/net/InetAddress;");
dci_senderPortID = (*env)->GetFieldID(env, clazz,
"cachedSenderPort", "I");
clazz = (*env)->FindClass(env, "java/net/Inet4Address");
ia_class = (*env)->NewGlobalRef(env, clazz);
ia_addrID = (*env)->GetFieldID(env, clazz, "address", "I");
ia_famID = (*env)->GetFieldID(env, clazz, "family", "I");
ia_ctorID = (*env)->GetMethodID(env, clazz, "<init>", "()V");
}
/*
* Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable
*/
__inline static jboolean supportPortUnreachable() {
static jboolean initDone;
static jboolean portUnreachableSupported;
if (!initDone) {
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize = sizeof(ver);
GetVersionEx(&ver);
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) {
portUnreachableSupported = JNI_TRUE;
} else {
portUnreachableSupported = JNI_FALSE;
}
initDone = JNI_TRUE;
}
return portUnreachableSupported;
}
/*
@ -140,15 +77,8 @@ jboolean purgeOutstandingICMP(JNIEnv *env, jclass clazz, jint fd)
char buf[1];
fd_set tbl;
struct timeval t = { 0, 0 };
struct sockaddr_in rmtaddr;
int addrlen = sizeof(rmtaddr);
/*
* A no-op if this OS doesn't support it.
*/
if (!supportPortUnreachable()) {
return JNI_FALSE;
}
SOCKETADDRESS sa;
int addrlen = sizeof(sa);
/*
* Peek at the queue to see if there is an ICMP port unreachable. If there
@ -161,7 +91,7 @@ jboolean purgeOutstandingICMP(JNIEnv *env, jclass clazz, jint fd)
break;
}
if (recvfrom(fd, buf, 1, MSG_PEEK,
(struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) {
(struct sockaddr *)&sa, &addrlen) != SOCKET_ERROR) {
break;
}
if (WSAGetLastError() != WSAECONNRESET) {
@ -169,7 +99,7 @@ jboolean purgeOutstandingICMP(JNIEnv *env, jclass clazz, jint fd)
break;
}
recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen);
recvfrom(fd, buf, 1, 0, (struct sockaddr *)&sa, &addrlen);
got_icmp = JNI_TRUE;
}
@ -182,12 +112,12 @@ Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
{
jint fd = fdval(env, fdo);
int rv = 0;
struct sockaddr_in psa;
int sa_len = sizeof(psa);
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
memset(&psa, 0, sa_len);
memset(&sa, 0, sa_len);
rv = connect((SOCKET)fd, (struct sockaddr *)&psa, sa_len);
rv = connect((SOCKET)fd, (struct sockaddr *)&sa, sa_len);
if (rv == SOCKET_ERROR) {
handleSocketError(env, WSAGetLastError());
}
@ -200,10 +130,11 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
struct sockaddr_in psa;
int sa_len = sizeof(psa);
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
BOOL retry = FALSE;
jint n;
jobject senderAddr;
do {
retry = FALSE;
@ -211,7 +142,7 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
(char *)buf,
len,
0,
(struct sockaddr *)&psa,
(struct sockaddr *)&sa,
&sa_len);
if (n == SOCKET_ERROR) {
@ -233,21 +164,30 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
}
} while (retry);
if (!isSenderCached(env, this, &psa)) {
int port = ntohs(psa.sin_port);
jobject ia = (*env)->NewObject(env, ia_class, ia_ctorID);
jobject isa = NULL;
if (psa.sin_family != AF_INET) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family unavailable");
/*
* If the source address and port match the cached address
* and port in DatagramChannelImpl then we don't need to
* create InetAddress and InetSocketAddress objects.
*/
senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
if (senderAddr != NULL) {
if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
senderAddr)) {
senderAddr = NULL;
} else {
jint port = (*env)->GetIntField(env, this, dci_senderPortID);
if (port != NET_GetPortFromSockaddr((struct sockaddr *)&sa)) {
senderAddr = NULL;
}
}
}
if (senderAddr == NULL) {
jobject isa = NULL;
int port;
jobject ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa,
&port);
if (ia != NULL) {
// populate InetAddress (assumes AF_INET)
(*env)->SetIntField(env, ia, ia_addrID, ntohl(psa.sin_addr.s_addr));
// create InetSocketAddress
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
}
@ -258,9 +198,8 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
// update cachedSenderInetAddress/cachedSenderPort
(*env)->SetObjectField(env, this, dci_senderAddrID, ia);
(*env)->SetIntField(env, this, dci_senderPortID, port);
// update sender
(*env)->SetIntField(env, this, dci_senderPortID,
NET_GetPortFromSockaddr((struct sockaddr *)&sa));
(*env)->SetObjectField(env, this, dci_senderID, isa);
}
return n;
@ -268,21 +207,20 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jobject fdo, jlong address,
jint len, jobject dest)
jboolean preferIPv6, jobject fdo,
jlong address, jint len, jobject dest)
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKETADDRESS psa;
int sa_len = sizeof(psa);
SOCKETADDRESS sa;
int sa_len;
jint rv = 0;
jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
jint destPort = (*env)->GetIntField(env, dest, isa_portID);
if (NET_InetAddressToSockaddr(env, destAddress, destPort,
(struct sockaddr *)&psa,
&sa_len, JNI_FALSE) != 0) {
(struct sockaddr *)&sa,
&sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
@ -290,7 +228,7 @@ Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
buf,
len,
0,
(struct sockaddr *)&psa,
(struct sockaddr *)&sa,
sa_len);
if (rv == SOCKET_ERROR) {
int theErr = (jint)WSAGetLastError();

View File

@ -36,51 +36,95 @@
#include "sun_nio_ch_Net.h"
static jfieldID ia_addrID;
static jclass ia_class;
static jmethodID ia_ctorID;
static jfieldID ia_famID;
/**************************************************************
* static method to store field IDs in initializers
/**
* Definitions to allow for building with older SDK include files.
*/
#ifndef MCAST_BLOCK_SOURCE
#define MCAST_BLOCK_SOURCE 43
#define MCAST_UNBLOCK_SOURCE 44
#define MCAST_JOIN_SOURCE_GROUP 45
#define MCAST_LEAVE_SOURCE_GROUP 46
#endif /* MCAST_BLOCK_SOURCE */
typedef struct my_ip_mreq_source {
IN_ADDR imr_multiaddr;
IN_ADDR imr_sourceaddr;
IN_ADDR imr_interface;
};
typedef struct my_group_source_req {
ULONG gsr_interface;
SOCKADDR_STORAGE gsr_group;
SOCKADDR_STORAGE gsr_source;
};
/**
* Copy IPv6 address as jbytearray to target
*/
#define COPY_INET6_ADDRESS(env, source, target) \
(*env)->GetByteArrayRegion(env, source, 0, 16, target)
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
{
clazz = (*env)->FindClass(env, "java/net/Inet4Address");
ia_class = (*env)->NewGlobalRef(env, clazz);
ia_addrID = (*env)->GetFieldID(env, clazz, "address", "I");
ia_famID = (*env)->GetFieldID(env, clazz, "family", "I");
ia_ctorID = (*env)->GetMethodID(env, clazz, "<init>", "()V");
/* nothing to do */
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
{
/*
* Return true if Windows Vista or newer, and IPv6 is configured
*/
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize = sizeof(ver);
GetVersionEx(&ver);
if ((ver.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(ver.dwMajorVersion >= 6) && ipv6_available())
{
return JNI_TRUE;
}
return JNI_FALSE;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
jboolean reuse)
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse)
{
SOCKET s;
int domain = (preferIPv6) ? AF_INET6 : AF_INET;
s = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
s = socket(domain, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
if (s != INVALID_SOCKET) {
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
/* IPV6_V6ONLY is true by default */
if (domain == AF_INET6) {
int opt = 0;
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(const char *)&opt, sizeof(opt));
}
} else {
NET_ThrowNew(env, WSAGetLastError(), "socket");
}
return (jint)s;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz,
jobject fdo, jobject iao, jint port)
Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
jobject fdo, jobject iao, jint port)
{
SOCKETADDRESS sa;
int rv;
int sa_len = sizeof(sa);
int sa_len;
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
return;
}
@ -89,16 +133,25 @@ Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz,
NET_ThrowNew(env, WSAGetLastError(), "bind");
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
{
if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "listen");
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao,
jint port, jint trafficClass)
Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo,
jobject iao, jint port)
{
SOCKETADDRESS sa;
int rv;
int sa_len = sizeof(sa);
int sa_len;
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) {
return IOS_THROWN;
if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
rv = connect(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
@ -116,7 +169,7 @@ Java_sun_nio_ch_Net_connect(JNIEnv *env, jclass clazz, jobject fdo, jobject iao,
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
{
struct sockaddr_in sa;
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
@ -127,50 +180,64 @@ Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
NET_ThrowNew(env, error, "getsockname");
return IOS_THROWN;
}
return (jint)ntohs(sa.sin_port);
return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
}
JNIEXPORT jobject JNICALL
Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
{
struct sockaddr_in sa;
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
jobject iao;
int port;
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
return NULL;
}
iao = (*env)->NewObject(env, ia_class, ia_ctorID);
if (iao == NULL) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
} else {
(*env)->SetIntField(env, iao, ia_addrID, ntohl(sa.sin_addr.s_addr));
}
return iao;
return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
jobject fdo, jint opt)
Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
{
int klevel, kopt;
int result;
struct linger linger;
char *arg;
int arglen;
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"Unsupported socket option");
if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
int error = WSAGetLastError();
if (error == WSAEINVAL) {
return 0;
}
NET_ThrowNew(env, error, "getsockname");
return IOS_THROWN;
}
return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
}
if (opt == java_net_SocketOptions_SO_LINGER) {
JNIEXPORT jobject JNICALL
Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
{
SOCKETADDRESS sa;
int sa_len = sizeof(sa);
int port;
if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
return NULL;
}
return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
jboolean mayNeedConversion, jint level, jint opt)
{
int result = 0;
struct linger linger;
char *arg;
int arglen, n;
if (level == SOL_SOCKET && opt == SO_LINGER) {
arg = (char *)&linger;
arglen = sizeof(linger);
} else {
@ -178,34 +245,40 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
arglen = sizeof(result);
}
if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
/**
* HACK: IP_TOS is deprecated on Windows and querying the option
* returns a protocol error. NET_GetSockOpt handles this and uses
* a fallback mechanism.
*/
if (level == IPPROTO_IP && opt == IP_TOS) {
mayNeedConversion = JNI_TRUE;
}
if (mayNeedConversion) {
n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen);
} else {
n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen);
}
if (n < 0) {
handleSocketError(env, WSAGetLastError());
return IOS_THROWN;
}
if (opt == java_net_SocketOptions_SO_LINGER)
if (level == SOL_SOCKET && opt == SO_LINGER)
return linger.l_onoff ? linger.l_linger : -1;
else
return result;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
jobject fdo, jint opt, jint arg)
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
jboolean mayNeedConversion, jint level, jint opt, jint arg)
{
int klevel, kopt;
struct linger linger;
char *parg;
int arglen;
int arglen, n;
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"Unsupported socket option");
return;
}
if (opt == java_net_SocketOptions_SO_LINGER) {
if (level == SOL_SOCKET && opt == SO_LINGER) {
parg = (char *)&linger;
arglen = sizeof(linger);
if (arg >= 0) {
@ -220,7 +293,200 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
arglen = sizeof(arg);
}
if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "sun.nio.ch.Net.setIntOption");
if (mayNeedConversion) {
n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
} else {
n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
}
if (n < 0)
handleSocketError(env, WSAGetLastError());
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_joinOrDrop4(JNIEnv *env, jobject this, jboolean join, jobject fdo,
jint group, jint interf, jint source)
{
struct ip_mreq mreq;
struct my_ip_mreq_source mreq_source;
int opt, n, optlen;
void* optval;
if (source == 0) {
mreq.imr_multiaddr.s_addr = htonl(group);
mreq.imr_interface.s_addr = htonl(interf);
opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
optval = (void*)&mreq;
optlen = sizeof(mreq);
} else {
mreq_source.imr_multiaddr.s_addr = htonl(group);
mreq_source.imr_sourceaddr.s_addr = htonl(source);
mreq_source.imr_interface.s_addr = htonl(interf);
opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP;
optval = (void*)&mreq_source;
optlen = sizeof(mreq_source);
}
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen);
if (n < 0) {
if (join && (WSAGetLastError() == WSAENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, WSAGetLastError());
}
return 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_blockOrUnblock4(JNIEnv *env, jobject this, jboolean block, jobject fdo,
jint group, jint interf, jint source)
{
struct my_ip_mreq_source mreq_source;
int n;
int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE;
mreq_source.imr_multiaddr.s_addr = htonl(group);
mreq_source.imr_sourceaddr.s_addr = htonl(source);
mreq_source.imr_interface.s_addr = htonl(interf);
n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt,
(void*)&mreq_source, sizeof(mreq_source));
if (n < 0) {
if (block && (WSAGetLastError() == WSAENOPROTOOPT))
return IOS_UNAVAILABLE;
handleSocketError(env, WSAGetLastError());
}
return 0;
}
/**
* Call setsockopt with a IPPROTO_IPV6 level socket option
* and a group_source_req structure as the option value. The
* given IPv6 group, interface index, and IPv6 source address
* are copied into the structure.
*/
static int setGroupSourceReqOption(JNIEnv* env,
jobject fdo,
int opt,
jbyteArray group,
jint index,
jbyteArray source)
{
struct my_group_source_req req;
struct sockaddr_in6* sin6;
req.gsr_interface = (ULONG)index;
sin6 = (struct sockaddr_in6*)&(req.gsr_group);
sin6->sin6_family = AF_INET6;
COPY_INET6_ADDRESS(env, group, (jbyte*)&(sin6->sin6_addr));
sin6 = (struct sockaddr_in6*)&(req.gsr_source);
sin6->sin6_family = AF_INET6;
COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr));
return setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, (void*)&req, sizeof(req));
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_joinOrDrop6(JNIEnv *env, jobject this, jboolean join, jobject fdo,
jbyteArray group, jint index, jbyteArray source)
{
struct ipv6_mreq mreq6;
int n;
if (source == NULL) {
int opt = (join) ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
COPY_INET6_ADDRESS(env, group, (jbyte*)&(mreq6.ipv6mr_multiaddr));
mreq6.ipv6mr_interface = (int)index;
n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt,
(void*)&mreq6, sizeof(mreq6));
} else {
int opt = (join) ? MCAST_JOIN_SOURCE_GROUP : MCAST_LEAVE_SOURCE_GROUP;
n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
}
if (n < 0) {
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_blockOrUnblock6(JNIEnv *env, jobject this, jboolean block, jobject fdo,
jbyteArray group, jint index, jbyteArray source)
{
int opt = (block) ? MCAST_BLOCK_SOURCE : MCAST_UNBLOCK_SOURCE;
int n = setGroupSourceReqOption(env, fdo, opt, group, index, source);
if (n < 0) {
handleSocketError(env, errno);
}
return 0;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setInterface4(JNIEnv* env, jobject this, jobject fdo, jint interf)
{
struct in_addr in;
int arglen = sizeof(struct in_addr);
int n;
in.s_addr = htonl(interf);
n = setsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF,
(void*)&(in.s_addr), arglen);
if (n < 0) {
handleSocketError(env, WSAGetLastError());
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getInterface4(JNIEnv* env, jobject this, jobject fdo)
{
struct in_addr in;
int arglen = sizeof(struct in_addr);
int n;
n = getsockopt(fdval(env, fdo), IPPROTO_IP, IP_MULTICAST_IF, (void*)&in, &arglen);
if (n < 0) {
handleSocketError(env, WSAGetLastError());
return IOS_THROWN;
}
return ntohl(in.s_addr);
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setInterface6(JNIEnv* env, jobject this, jobject fdo, jint index)
{
int value = (jint)index;
int arglen = sizeof(value);
int n;
n = setsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF,
(void*)&(index), arglen);
if (n < 0) {
handleSocketError(env, errno);
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_getInterface6(JNIEnv* env, jobject this, jobject fdo)
{
int index;
int arglen = sizeof(index);
int n;
n = getsockopt(fdval(env, fdo), IPPROTO_IPV6, IPV6_MULTICAST_IF, (void*)&index, &arglen);
if (n < 0) {
handleSocketError(env, errno);
return -1;
}
return (jint)index;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) {
int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SD_RECEIVE :
(jhow == sun_nio_ch_Net_SHUT_WR) ? SD_SEND : SD_BOTH;
if (shutdown(fdval(env, fdo), how) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "shutdown");
}
}

View File

@ -46,10 +46,6 @@
static jfieldID fd_fdID; /* java.io.FileDescriptor.fd */
static jclass isa_class; /* java.net.InetSocketAddress */
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
static jclass ia_class; /* java.net.InetAddress */
static jmethodID ia_ctorID; /* InetAddress() */
static jfieldID ia_addrID; /* java.net.InetAddress.address */
static jfieldID ia_famID; /* java.net.InetAddress.family */
/**************************************************************
@ -66,12 +62,6 @@ Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv *env, jclass cls)
isa_class = (*env)->NewGlobalRef(env, cls);
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
"(Ljava/net/InetAddress;I)V");
cls = (*env)->FindClass(env, "java/net/Inet4Address");
ia_class = (*env)->NewGlobalRef(env, cls);
ia_ctorID = (*env)->GetMethodID(env, cls, "<init>","()V");
ia_addrID = (*env)->GetFieldID(env, cls, "address", "I");
ia_famID = (*env)->GetFieldID(env, cls, "family", "I");
}
JNIEXPORT void JNICALL
@ -90,8 +80,9 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
{
jint ssfd = (*env)->GetIntField(env, ssfdo, fd_fdID);
jint newfd;
struct sockaddr_in sa;
jobject remote_ia = 0;
SOCKETADDRESS sa;
jobject remote_ia;
int remote_port;
jobject isa;
jobject ia;
int addrlen = sizeof(sa);
@ -106,14 +97,13 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
return IOS_THROWN;
}
(*env)->SetIntField(env, newfdo, fd_fdID, newfd);
remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
ia = (*env)->NewObject(env, ia_class, ia_ctorID);
(*env)->SetIntField(env, ia, ia_addrID, ntohl(sa.sin_addr.s_addr));
(*env)->SetIntField(env, ia, ia_famID, sa.sin_family);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia,
ntohs(sa.sin_port));
isa = (*env)->NewObject(env, isa_class, isa_ctorID,
remote_ia, remote_port);
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
return 1;
}

View File

@ -139,12 +139,3 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
return 0;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_SocketChannelImpl_shutdown(JNIEnv *env, jclass cl,
jobject fdo, jint how)
{
if (shutdown(fdval(env, fdo), how) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "shutdown");
}
}

View File

@ -0,0 +1,220 @@
/*
* Copyright 2007-2008 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 4527345
* @summary Unit test for DatagramChannel's multicast support
* @build BasicMulticastTests NetworkConfiguration
*/
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
public class BasicMulticastTests {
/**
* Tests that existing membership key is returned by join methods and that
* membership key methods return the expected results
*/
static void membershipKeyTests(NetworkInterface nif,
InetAddress group,
InetAddress source)
throws IOException
{
System.out.format("MembershipKey test using %s @ %s\n",
group.getHostAddress(), nif.getName());
ProtocolFamily family = (group instanceof Inet4Address) ?
StandardProtocolFamily.INET : StandardProtocolFamily.INET6;
DatagramChannel dc = DatagramChannel.open(family)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(source, 0));
// check existing key is returned
MembershipKey key = dc.join(group, nif);
MembershipKey other = dc.join(group, nif);
if (other != key) {
throw new RuntimeException("existing key not returned");
}
// check key
if (!key.isValid())
throw new RuntimeException("key is not valid");
if (!key.getGroup().equals(group))
throw new RuntimeException("group is incorrect");
if (!key.getNetworkInterface().equals(nif))
throw new RuntimeException("network interface is incorrect");
if (key.getSourceAddress() != null)
throw new RuntimeException("key is source specific");
// drop membership
key.drop();
if (key.isValid()) {
throw new RuntimeException("key is still valid");
}
// source-specific
try {
key = dc.join(group, nif, source);
other = dc.join(group, nif, source);
if (other != key) {
throw new RuntimeException("existing key not returned");
}
if (!key.isValid())
throw new RuntimeException("key is not valid");
if (!key.getGroup().equals(group))
throw new RuntimeException("group is incorrect");
if (!key.getNetworkInterface().equals(nif))
throw new RuntimeException("network interface is incorrect");
if (!key.getSourceAddress().equals(source))
throw new RuntimeException("key's source address incorrect");
// drop membership
key.drop();
if (key.isValid()) {
throw new RuntimeException("key is still valid");
}
} catch (UnsupportedOperationException x) {
}
// done
dc.close();
}
/**
* Tests exceptions for invalid arguments or scenarios
*/
static void exceptionTests(NetworkInterface nif)
throws IOException
{
System.out.println("Exception Tests");
DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(0));
InetAddress group = InetAddress.getByName("225.4.5.6");
InetAddress notGroup = InetAddress.getByName("1.2.3.4");
InetAddress thisHost = InetAddress.getLocalHost();
// IllegalStateException
MembershipKey key;
key = dc.join(group, nif);
try {
dc.join(group, nif, thisHost);
throw new RuntimeException("IllegalStateException not thrown");
} catch (IllegalStateException x) {
} catch (UnsupportedOperationException x) {
}
key.drop();
try {
key = dc.join(group, nif, thisHost);
try {
dc.join(group, nif);
throw new RuntimeException("IllegalStateException not thrown");
} catch (IllegalStateException x) {
}
key.drop();
} catch (UnsupportedOperationException x) {
}
// IllegalArgumentException
try {
dc.join(notGroup, nif);
throw new RuntimeException("IllegalArgumentException not thrown");
} catch (IllegalArgumentException x) {
}
try {
dc.join(notGroup, nif, thisHost);
throw new RuntimeException("IllegalArgumentException not thrown");
} catch (IllegalArgumentException x) {
} catch (UnsupportedOperationException x) {
}
// NullPointerException
try {
dc.join(null, nif);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
try {
dc.join(group, null);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
try {
dc.join(group, nif, null);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
} catch (UnsupportedOperationException x) {
}
dc.close();
// ClosedChannelException
try {
dc.join(group, nif);
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
}
try {
dc.join(group, nif, thisHost);
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
} catch (UnsupportedOperationException x) {
}
}
/**
* Probe interfaces to get interfaces that support IPv4 or IPv6 multicasting
* and invoke tests.
*/
public static void main(String[] args) throws IOException {
// multicast groups used for the test
InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
InetAddress ip6Group = InetAddress.getByName("ff02::a");
NetworkConfiguration config = NetworkConfiguration.probe();
NetworkInterface nif = config.ip4Interfaces().iterator().next();
InetAddress anySource = config.ip4Addresses(nif).iterator().next();
membershipKeyTests(nif, ip4Group, anySource);
exceptionTests(nif);
// re-run the membership key tests with IPv6 if available
Iterator<NetworkInterface> iter = config.ip6Interfaces().iterator();
if (iter.hasNext()) {
nif = iter.next();
anySource = config.ip6Addresses(nif).iterator().next();
membershipKeyTests(nif, ip6Group, anySource);
}
}
}

View File

@ -0,0 +1,220 @@
/*
* Copyright 2007-2008 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 4527345
* @summary Unit test for DatagramChannel's multicast support
* @build MulticastSendReceiveTests NetworkConfiguration
*/
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
public class MulticastSendReceiveTests {
static Random rand = new Random();
/**
* Send datagram from given local address to given multicast
* group.
*/
static int sendDatagram(InetAddress local,
NetworkInterface nif,
InetAddress group,
int port)
throws IOException
{
ProtocolFamily family = (group instanceof Inet6Address) ?
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
DatagramChannel dc = DatagramChannel.open(family)
.bind(new InetSocketAddress(local, 0))
.setOption(StandardSocketOption.IP_MULTICAST_IF, nif);
int id = rand.nextInt();
byte[] msg = Integer.toString(id).getBytes("UTF-8");
ByteBuffer buf = ByteBuffer.wrap(msg);
System.out.format("Send message from %s -> group %s (id=0x%x)\n",
local.getHostAddress(), group.getHostAddress(), id);
dc.send(buf, new InetSocketAddress(group, port));
dc.close();
return id;
}
/**
* Wait (with timeout) for datagram.
*
* @param expectedSender - expected sender address, or
* null if no datagram expected
* @param id - expected id of datagram
*/
static void receiveDatagram(DatagramChannel dc,
InetAddress expectedSender,
int id)
throws IOException
{
Selector sel = Selector.open();
dc.configureBlocking(false);
dc.register(sel, SelectionKey.OP_READ);
ByteBuffer buf = ByteBuffer.allocateDirect(100);
try {
for (;;) {
System.out.println("Waiting to receive message");
sel.select(5*1000);
SocketAddress sa = dc.receive(buf);
// no datagram received
if (sa == null) {
if (expectedSender != null) {
throw new RuntimeException("Expected message not recieved");
}
System.out.println("No message received (correct)");
return;
}
// datagram received
InetAddress sender = ((InetSocketAddress)sa).getAddress();
buf.flip();
byte[] bytes = new byte[buf.remaining()];
buf.get(bytes);
int receivedId = Integer.parseInt(new String(bytes));
System.out.format("Received message from %s (id=0x%x)\n",
sender, receivedId);
if (expectedSender == null) {
if (receivedId == id)
throw new RuntimeException("Message not expected");
System.out.println("Message ignored (has wrong id)");
} else {
if (sender.equals(expectedSender)) {
System.out.println("Message expected");
return;
}
System.out.println("Message ignored (wrong sender)");
}
sel.selectedKeys().clear();
buf.rewind();
}
} finally {
sel.close();
}
}
/**
* Exercise multicast send/receive on given group/interface
*/
static void test(NetworkInterface nif, InetAddress group, InetAddress source)
throws IOException
{
ProtocolFamily family = (group instanceof Inet6Address) ?
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
System.out.format("create channel to %s socket\n", family.name());
DatagramChannel dc = DatagramChannel.open(family)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(0));
// join group
System.out.format("join %s @ %s\n", group.getHostAddress(),
nif.getName());
MembershipKey key = dc.join(group, nif);
// send message to group
int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
int id = sendDatagram(source, nif, group, port);
// receive message and check id matches
receiveDatagram(dc, source, id);
// exclude-mode filtering
try {
System.out.format("block %s\n", source.getHostAddress());
// may throw UOE
key.block(source);
id = sendDatagram(source, nif, group, port);
receiveDatagram(dc, null, id);
// unblock source, send message, message should be received
System.out.format("unblock %s\n", source.getHostAddress());
key.unblock(source);
id = sendDatagram(source, nif, group, port);
receiveDatagram(dc, source, id);
} catch (UnsupportedOperationException x) {
System.out.println("Exclude-mode filtering not supported!");
}
key.drop();
// include-mode filtering
InetAddress bogus = (group instanceof Inet6Address) ?
InetAddress.getByName("fe80::1234") :
InetAddress.getByName("1.2.3.4");
System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
nif.getName(), bogus.getHostAddress());
try {
// may throw UOE
key = dc.join(group, nif, bogus);
id = sendDatagram(source, nif, group, port);
receiveDatagram(dc, null, id);
System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
nif.getName(), source.getHostAddress());
key = dc.join(group, nif, source);
id = sendDatagram(source, nif, group, port);
receiveDatagram(dc, source, id);
} catch (UnsupportedOperationException x) {
System.out.println("Include-mode filtering not supported!");
}
// done
dc.close();
}
public static void main(String[] args) throws IOException {
NetworkConfiguration config = NetworkConfiguration.probe();
// multicast groups used for the test
InetAddress ip4Group = InetAddress.getByName("225.4.5.6");
InetAddress ip6Group = InetAddress.getByName("ff02::a");
for (NetworkInterface nif: config.ip4Interfaces()) {
InetAddress source = config.ip4Addresses(nif).iterator().next();
test(nif, ip4Group, source);
}
for (NetworkInterface nif: config.ip6Interfaces()) {
InetAddress source = config.ip6Addresses(nif).iterator().next();
test(nif, ip6Group, source);
}
}
}

View File

@ -0,0 +1,97 @@
/*
* Copyright 2007-2008 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.*;
import java.util.*;
import java.io.IOException;
/**
* Helper class for multicasting tests.
*/
class NetworkConfiguration {
private Map<NetworkInterface,List<InetAddress>> ip4Interfaces;
private Map<NetworkInterface,List<InetAddress>> ip6Interfaces;
private NetworkConfiguration(Map<NetworkInterface,List<InetAddress>> ip4Interfaces,
Map<NetworkInterface,List<InetAddress>> ip6Interfaces)
{
this.ip4Interfaces = ip4Interfaces;
this.ip6Interfaces = ip6Interfaces;
}
Iterable<NetworkInterface> ip4Interfaces() {
return ip4Interfaces.keySet();
}
Iterable<NetworkInterface> ip6Interfaces() {
return ip6Interfaces.keySet();
}
Iterable<InetAddress> ip4Addresses(NetworkInterface nif) {
return ip4Interfaces.get(nif);
}
Iterable<InetAddress> ip6Addresses(NetworkInterface nif) {
return ip6Interfaces.get(nif);
}
static NetworkConfiguration probe() throws IOException {
Map<NetworkInterface,List<InetAddress>> ip4Interfaces =
new HashMap<NetworkInterface,List<InetAddress>>();
Map<NetworkInterface,List<InetAddress>> ip6Interfaces =
new HashMap<NetworkInterface,List<InetAddress>>();
// find the interfaces that support IPv4 and IPv6
List<NetworkInterface> nifs = Collections
.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif: nifs) {
// ignore intertaces that are down or don't support multicast
if (!nif.isUp() || !nif.supportsMulticast() || nif.isLoopback())
continue;
List<InetAddress> addrs = Collections.list(nif.getInetAddresses());
for (InetAddress addr: addrs) {
if (addr instanceof Inet4Address) {
List<InetAddress> list = ip4Interfaces.get(nif);
if (list == null) {
list = new LinkedList<InetAddress>();
}
list.add(addr);
ip4Interfaces.put(nif, list);
}
if (addr instanceof Inet6Address) {
List<InetAddress> list = ip6Interfaces.get(nif);
if (list == null) {
list = new LinkedList<InetAddress>();
}
list.add(addr);
ip6Interfaces.put(nif, list);
}
}
}
return new NetworkConfiguration(ip4Interfaces, ip6Interfaces);
}
}

View File

@ -0,0 +1,115 @@
/*
* Copyright 2007-2008 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 4640544
* @summary Unit test for setOption/getOption/options methods
*/
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.io.IOException;
import java.util.*;
import static java.net.StandardSocketOption.*;
public class SocketOptionTests {
static <T> void checkOption(DatagramChannel dc,
SocketOption<T> name,
T expectedValue)
throws IOException
{
T value = dc.getOption(name);
if (!value.equals(expectedValue))
throw new RuntimeException("value not as expected");
}
public static void main(String[] args) throws IOException {
DatagramChannel dc = DatagramChannel.open();
// check supported options
Set<SocketOption<?>> options = dc.options();
List<? extends SocketOption<?>> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL,
IP_MULTICAST_LOOP);
for (SocketOption opt: expected) {
if (!options.contains(opt))
throw new RuntimeException(opt.name() + " should be supported");
}
// check specified defaults
checkOption(dc, SO_BROADCAST, false);
checkOption(dc, IP_MULTICAST_TTL, 1); // true on supported platforms
checkOption(dc, IP_MULTICAST_LOOP, true); // true on supported platforms
// allowed to change when not bound
dc.setOption(SO_BROADCAST, true);
checkOption(dc, SO_BROADCAST, true);
dc.setOption(SO_BROADCAST, false);
checkOption(dc, SO_BROADCAST, false);
dc.setOption(SO_SNDBUF, 16*1024); // can't check
dc.setOption(SO_RCVBUF, 16*1024); // can't check
dc.setOption(SO_REUSEADDR, true);
checkOption(dc, SO_REUSEADDR, true);
dc.setOption(SO_REUSEADDR, false);
checkOption(dc, SO_REUSEADDR, false);
// bind socket
dc.bind(new InetSocketAddress(0));
// allow to change when bound
dc.setOption(SO_BROADCAST, true);
checkOption(dc, SO_BROADCAST, true);
dc.setOption(SO_BROADCAST, false);
checkOption(dc, SO_BROADCAST, false);
dc.setOption(IP_TOS, 0x08); // can't check
dc.setOption(IP_MULTICAST_TTL, 2);
checkOption(dc, IP_MULTICAST_TTL, 2);
dc.setOption(IP_MULTICAST_LOOP, false);
checkOption(dc, IP_MULTICAST_LOOP, false);
dc.setOption(IP_MULTICAST_LOOP, true);
checkOption(dc, IP_MULTICAST_LOOP, true);
// NullPointerException
try {
dc.setOption(null, "value");
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
try {
dc.getOption(null);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
// ClosedChannelException
dc.close();
try {
dc.setOption(IP_MULTICAST_LOOP, true);
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
}
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2007-2008 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 4640544
* @summary Unit test for ServerSocketChannel setOption/getOption/options
* methods.
*/
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.io.IOException;
import java.util.*;
import static java.net.StandardSocketOption.*;
public class SocketOptionTests {
static void checkOption(ServerSocketChannel ssc, SocketOption name, Object expectedValue)
throws IOException
{
Object value = ssc.getOption(name);
if (!value.equals(expectedValue))
throw new RuntimeException("value not as expected");
}
public static void main(String[] args) throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open();
// check supported options
Set<SocketOption<?>> options = ssc.options();
if (!options.contains(SO_REUSEADDR))
throw new RuntimeException("SO_REUSEADDR should be supported");
if (!options.contains(SO_RCVBUF))
throw new RuntimeException("SO_RCVBUF should be supported");
// allowed to change when not bound
ssc.setOption(SO_RCVBUF, 256*1024); // can't check
ssc.setOption(SO_REUSEADDR, true);
checkOption(ssc, SO_REUSEADDR, true);
ssc.setOption(SO_REUSEADDR, false);
checkOption(ssc, SO_REUSEADDR, false);
// NullPointerException
try {
ssc.setOption(null, "value");
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
try {
ssc.getOption(null);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
// ClosedChannelException
ssc.close();
try {
ssc.setOption(SO_REUSEADDR, true);
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
}
}
}

View File

@ -0,0 +1,129 @@
/*
* Copyright 2007-2008 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 4640544
* @summary Unit test to check SocketChannel setOption/getOption/options
* methods.
*/
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.io.IOException;
import java.util.*;
import static java.net.StandardSocketOption.*;
public class SocketOptionTests {
static void checkOption(SocketChannel sc, SocketOption name, Object expectedValue)
throws IOException
{
Object value = sc.getOption(name);
if (!value.equals(expectedValue))
throw new RuntimeException("value not as expected");
}
public static void main(String[] args) throws IOException {
SocketChannel sc = SocketChannel.open();
// check supported options
Set<SocketOption<?>> options = sc.options();
List<? extends SocketOption> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, TCP_NODELAY);
for (SocketOption opt: expected) {
if (!options.contains(opt))
throw new RuntimeException(opt.name() + " should be supported");
}
// check specified defaults
int linger = sc.<Integer>getOption(SO_LINGER);
if (linger >= 0)
throw new RuntimeException("initial value of SO_LINGER should be < 0");
checkOption(sc, SO_KEEPALIVE, false);
checkOption(sc, TCP_NODELAY, false);
// allowed to change when not bound
sc.setOption(SO_KEEPALIVE, true);
checkOption(sc, SO_KEEPALIVE, true);
sc.setOption(SO_KEEPALIVE, false);
checkOption(sc, SO_KEEPALIVE, false);
sc.setOption(SO_SNDBUF, 128*1024); // can't check
sc.setOption(SO_RCVBUF, 256*1024); // can't check
sc.setOption(SO_REUSEADDR, true);
checkOption(sc, SO_REUSEADDR, true);
sc.setOption(SO_REUSEADDR, false);
checkOption(sc, SO_REUSEADDR, false);
sc.setOption(SO_LINGER, 10);
linger = sc.<Integer>getOption(SO_LINGER);
if (linger < 1)
throw new RuntimeException("expected linger to be enabled");
sc.setOption(SO_LINGER, -1);
linger = sc.<Integer>getOption(SO_LINGER);
if (linger >= 0)
throw new RuntimeException("expected linger to be disabled");
sc.setOption(TCP_NODELAY, true);
checkOption(sc, TCP_NODELAY, true);
sc.setOption(TCP_NODELAY, false); // can't check
// bind socket
sc.bind(new InetSocketAddress(0));
// allow to change when bound
sc.setOption(SO_KEEPALIVE, true);
checkOption(sc, SO_KEEPALIVE, true);
sc.setOption(SO_KEEPALIVE, false);
checkOption(sc, SO_KEEPALIVE, false);
sc.setOption(SO_LINGER, 10);
linger = sc.<Integer>getOption(SO_LINGER);
if (linger < 1)
throw new RuntimeException("expected linger to be enabled");
sc.setOption(SO_LINGER, -1);
linger = sc.<Integer>getOption(SO_LINGER);
if (linger >= 0)
throw new RuntimeException("expected linger to be disabled");
sc.setOption(TCP_NODELAY, true); // can't check
sc.setOption(TCP_NODELAY, false); // can't check
// NullPointerException
try {
sc.setOption(null, "value");
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
try {
sc.getOption(null);
throw new RuntimeException("NullPointerException not thrown");
} catch (NullPointerException x) {
}
// ClosedChannelException
sc.close();
try {
sc.setOption(TCP_NODELAY, true);
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
}
}
}

View File

@ -38,7 +38,7 @@ public class TestUtil {
// executing in a different network.
public static final String HOST = "javaweb.sfbay.sun.com";
public static final String REFUSING_HOST = "jano1.sfbay.sun.com";
public static final String FAR_HOST = "theclub.ireland.sun.com";
public static final String FAR_HOST = "irejano.ireland.sun.com";
public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah";
private TestUtil() { }
@ -102,5 +102,4 @@ public class TestUtil {
static boolean onWindows() {
return osName.startsWith("Windows");
}
}

View File

@ -0,0 +1,187 @@
/*
* Copyright 2007-2008 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 4640544
* @summary Unit test for channels that implement NetworkChannel
*/
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.io.IOException;
import java.util.*;
public class NetworkChannelTests {
static interface ChannelFactory {
NetworkChannel open() throws IOException;
}
static class BogusSocketAddress extends SocketAddress {
}
/**
* Exercise bind method.
*/
static void bindTests(ChannelFactory factory) throws IOException {
NetworkChannel ch;
// AlreadyBoundException
ch = factory.open().bind(new InetSocketAddress(0));
try {
ch.bind(new InetSocketAddress(0));
throw new RuntimeException("AlreadyBoundException not thrown");
} catch (AlreadyBoundException x) {
}
ch.close();
// bind(null)
ch = factory.open().bind(null);
if (ch.getLocalAddress() == null)
throw new RuntimeException("socket not found");
ch.close();
// UnsupportedAddressTypeException
ch = factory.open();
try {
ch.bind(new BogusSocketAddress());
throw new RuntimeException("UnsupportedAddressTypeException not thrown");
} catch (UnsupportedAddressTypeException x) {
}
ch.close();
// ClosedChannelException
try {
ch.bind(new InetSocketAddress(0));
throw new RuntimeException("ClosedChannelException not thrown");
} catch (ClosedChannelException x) {
}
}
/**
* Exercise getLocalAddress method.
*/
static void localAddressTests(ChannelFactory factory) throws IOException {
NetworkChannel ch;
// not bound
ch = factory.open();
if (ch.getLocalAddress() != null) {
throw new RuntimeException("Local address returned when not bound");
}
// bound
InetSocketAddress local =
(InetSocketAddress)(ch.bind(new InetSocketAddress(0)).getLocalAddress());
if (!local.getAddress().isAnyLocalAddress()) {
if (NetworkInterface.getByInetAddress(local.getAddress()) == null)
throw new RuntimeException("not bound to local address");
}
if (local.getPort() <= 0)
throw new RuntimeException("not bound to local port");
// closed
ch.close();
if (ch.getLocalAddress() != null) {
throw new RuntimeException("Local address return when closed");
}
}
/**
* Exercise getConnectedAddress method (SocketChannel only)
*/
static void connectedAddressTests() throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open()
.bind(new InetSocketAddress(0));
InetSocketAddress local = (InetSocketAddress)(ssc.getLocalAddress());
int port = local.getPort();
InetSocketAddress server = new InetSocketAddress(InetAddress.getLocalHost(), port);
SocketChannel sc = SocketChannel.open();
// not connected
if (sc.getConnectedAddress() != null)
throw new RuntimeException("getConnectedAddress returned address when not connected");
// connected
sc.connect(server);
SocketAddress remote = sc.getConnectedAddress();
if (!remote.equals(server))
throw new RuntimeException("getConnectedAddress returned incorrect address");
// closed
sc.close();
if (sc.getConnectedAddress() != null)
throw new RuntimeException("getConnectedAddress returned address when closed");
ssc.close();
}
public static void main(String[] args) throws IOException {
ChannelFactory factory;
// -- SocketChannel --
factory = new ChannelFactory() {
public NetworkChannel open() throws IOException {
return SocketChannel.open();
}
};
bindTests(factory);
localAddressTests(factory);
connectedAddressTests();
// -- ServerSocketChannel --
factory = new ChannelFactory() {
public NetworkChannel open() throws IOException {
return ServerSocketChannel.open();
}
};
bindTests(factory);
localAddressTests(factory);
// backlog values
ServerSocketChannel.open()
.bind(new InetSocketAddress(0), 100).close();
ServerSocketChannel.open()
.bind(new InetSocketAddress(0), 0).close();
ServerSocketChannel.open()
.bind(new InetSocketAddress(0), -1).close();
// -- DatagramChannel --
factory = new ChannelFactory() {
public NetworkChannel open() throws IOException {
return DatagramChannel.open();
}
};
bindTests(factory);
localAddressTests(factory);
}
}