/* * Copyright 2007-2010 Sun Microsystems, Inc. * * This file is part of Project Darkstar Server. * * Project Darkstar Server is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation and * distributed hereunder to you. * * Project Darkstar Server 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Sun designates this particular file as subject to the "Classpath" * exception as provided by Sun in the LICENSE file that accompanied * this code. * * -- */ package com.sun.sgs.nio.channels; import java.io.IOException; import java.net.SocketAddress; import java.nio.channels.ClosedChannelException; import java.nio.channels.NotYetBoundException; import java.nio.channels.UnsupportedAddressTypeException; import java.util.concurrent.ExecutionException; import com.sun.sgs.nio.channels.spi.AsynchronousChannelProvider; /** * An asynchronous channel for stream-oriented listening sockets. * <p> * An asynchronous server-socket channel is created by invoking the * {@link AsynchronousServerSocketChannel#open(AsynchronousChannelGroup) open} * method of this class. A newly-created asynchronous server-socket channel * is open but not yet bound. It can be bound to a local address and * configured to listen for connections by invoking the * {@link AsynchronousServerSocketChannel#bind(SocketAddress, int) bind} * method. Once bound, the * {@link AsynchronousServerSocketChannel#accept(Object, CompletionHandler) * accept} method is used to initiate the accepting of connections * to the channel's socket. An attempt to invoke the {@code accept} method on * an unbound channel will cause a {@link NotYetBoundException} to be thrown. * <p> * Channels of this type are safe for use by multiple concurrent threads * though at most one accept operation can be outstanding at any time. If a * thread initiates an accept operation before a previous accept operation * has completed then an {@link AcceptPendingException} will be thrown. * Whether or not an operation is pending may be determined by invoking the * {@link AsynchronousServerSocketChannel#isAcceptPending isAcceptPending} * method. * <p> * Socket options are configured using the * {@link AsynchronousServerSocketChannel#setOption setOption} method. * Channels of this type support the following options: * <blockquote> * <table> * <tr> * <th>Option Name</th> * <th>Description</th> * </tr> * <tr> * <td>{@link StandardSocketOption#SO_RCVBUF SO_RCVBUF}</td> * <td>The size of the socket receive buffer</td> * </tr> * <tr> * <td>{@link StandardSocketOption#SO_REUSEADDR SO_REUSEADDR}</td> * <td>Re-use address</td> * </tr> * </table> * </blockquote> * and may support additional (implementation specific) options. The list of * options supported is obtained by invoking the * {@link NetworkChannel#options options} method. * * <h4>Usage Example:</h4> * <pre> * final AsynchronousServerSocketChannel listener = * AsynchronousServerSocketChannel.open().bind( * new InetSocketAddress(5000)); * * listener.accept( * new CompletionHandler<AsynchronousSocketChannel,Void>() { * public void completed(IoFuture<AsynchronousSocketChannel,Void> * result) * { * try { * AsynchronousSocketChannel ch = result.getNow(); * : * } catch (ExecutionException x) { .. } * * // accept the next connection * listener.accept(this); * } * }); * </pre> */ public abstract class AsynchronousServerSocketChannel extends AsynchronousChannel implements NetworkChannel { /** * Initializes a new instance of this class. * * @param provider the asynchronous channel provider for this channel */ protected AsynchronousServerSocketChannel( AsynchronousChannelProvider provider) { super(provider); } /** * Opens an asynchronous server-socket channel. * <p> * The new channel is created by invoking the * {@link AsynchronousChannelProvider#openAsynchronousServerSocketChannel * openAsynchronousServerSocketChannel} method on the * {@link AsynchronousChannelProvider} object that created the given * group. If the group parameter is {@code null} then the resulting * channel is created by the system-wide default provider, and bound * to the <em>default group</em>. * * @param group the group to which the newly constructed channel should * be bound, or {@code null} for the default group * @return a new asynchronous server socket channel * @throws ShutdownChannelGroupException the specified group is shutdown * @throws IOException if an I/O error occurs */ public static AsynchronousServerSocketChannel open( AsynchronousChannelGroup group) throws IOException { return AsynchronousChannelProvider.provider() .openAsynchronousServerSocketChannel(group); } /** * Opens an asynchronous server-socket channel. * <p> * This method returns an asynchronous server socket channel that is * bound to the <em>default group</em>. This method is equivalent to * evaluating the expression: * <pre> * open((AsynchronousChannelGroup)null); * </pre> * * @return a new asynchronous server socket channel * @throws IOException if an I/O error occurs */ public static AsynchronousServerSocketChannel open() throws IOException { return open((AsynchronousChannelGroup) null); } /** * Binds the channel's socket to a local address and configures the * socket to listen for connections. * <p> * This method works as if invoking it were equivalent to evaluating the * expression: * <pre> * bind(local, 0); * </pre> * * @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 if the socket is already bound * @throws UnsupportedAddressTypeException if the type of the given * address is not supported * @throws SecurityException if a security manager has been installed * and its checkListen method denies the operation * @throws ClosedChannelException if the channel is closed * @throws IOException if some other I/O error occurs */ public final AsynchronousServerSocketChannel 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 associated channel is closed. An * attempt to bind a socket that is already bound throws * AlreadyBoundException. If the local parameter has the value null then * the socket address is assigned automatically. * <p> * The backlog parameter is the maximum number of pending connections on * the socket. Its exact semantics are implementation specific. An * implementation may impose an implementation specific maximum length * or may choose to ignore the parameter. If the backlog parameter has * the value 0, or a negative value, then an implementation specific * default is used. * * @param local the local address to bind the socket, or {@code null} * to bind to an automatically assigned socket address * @param backlog the maximum number 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 SecurityException if a security manager has been installed * and its checkListen method denies the operation * @throws ClosedChannelException if the channel is closed * @throws IOException if some other I/O error occurs */ public abstract AsynchronousServerSocketChannel bind(SocketAddress local, int backlog) throws IOException; /** * {@inheritDoc} */ public abstract AsynchronousServerSocketChannel setOption( SocketOption name, Object value) throws IOException; /** * Accepts a connection. * <p> * This method initiates accepting a connection made to this channel's * socket, returning an {@link IoFuture} representing the pending result * of the operation. The {@code IoFuture}'s {@link IoFuture#get() get} * method will return the {@link AsynchronousSocketChannel} for the new * connection on successful completion. * <p> * When a new connection is accepted then the resulting * {@code AsynchronousSocketChannel} will be bound to the same * {@link AsynchronousChannelGroup} as this channel. * <p> * If a security manager has been installed then it verifies that the * address and port number of the connection's remote endpoint are * permitted by the security manager's {@link SecurityManager#checkAccept * checkAccept} method. The permission check is performed with privileges * that are restricted by the calling context of this method. If the * permission check fails then the operation completes by throwing * {@link ExecutionException} with cause {@link SecurityException}. * * @param <A> the attachment type * @param attachment the object to {@link IoFuture#attach attach} to the * returned {@code IoFuture} object; can be {@code null} * @param handler the handler for consuming the result; can be * {@code null} * @return an {@code IoFuture} object representing the pending result * @throws ClosedAsynchronousChannelException if this channel is closed * @throws AcceptPendingException if an accept operation is already in * progress on this channel * @throws NotYetBoundException if this channel's socket has not yet * been bound */ public abstract <A> IoFuture<AsynchronousSocketChannel, A> accept( A attachment, CompletionHandler<AsynchronousSocketChannel, ? super A> handler); /** * Accepts a connection. * <p> * This method initiates accepting a connection made to this channel's * socket, returning an {@link IoFuture} representing the pending result * of the operation. Its {@link IoFuture#get() get} method will return * the {@link AsynchronousSocketChannel} for the new connection on * successful completion. * <p> * This method works as if invoking it were equivalent to evaluating the * expression: * <pre> * accept((Object)null, handler); * </pre> * * When a new connection is accepted then the resulting * {@code AsynchronousSocketChannel} will be bound to the same * {@link AsynchronousChannelGroup} as this channel. * * @param <A> the attachment type * @param handler the handler for consuming the result; can be {@code null} * * @return an {@code IoFuture} object representing the pending result * * @throws ClosedAsynchronousChannelException if this channel is closed * @throws AcceptPendingException if an accept operation is already in * progress on this channel * @throws NotYetBoundException if this channel's socket has not yet * been bound */ public final <A> IoFuture<AsynchronousSocketChannel, A> accept( CompletionHandler<AsynchronousSocketChannel, ? super A> handler) { return accept(null, handler); } /** * Tells whether or not an accept is pending for this channel. * <p> * The result of this method is a <em>snapshot</em> of the channel * state. It may be invalid when the caller goes to examine the result * and should not be used for the purpose of coordination. * * @return {@code true} if, and only if, an accept is pending for this * this channel but has not yet completed. */ public abstract boolean isAcceptPending(); }