/* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package io.netty.channel; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.SocketChannel; import io.netty.util.AttributeMap; import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.FutureListener; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.SocketAddress; /** * A nexus to a network socket or a component which is capable of I/O * operations such as read, write, connect, and bind. * <p> * A channel provides a user: * <ul> * <li>the current state of the channel (e.g. is it open? is it connected?),</li> * <li>the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),</li> * <li>the I/O operations that the channel supports (e.g. read, write, connect, and bind), and</li> * <li>the {@link ChannelPipeline} which handles all I/O events and requests * associated with the channel.</li> * </ul> * * <h3>All I/O operations are asynchronous.</h3> * <p> * All I/O operations in Netty are asynchronous. It means any I/O calls will * return immediately with no guarantee that the requested I/O operation has * been completed at the end of the call. Instead, you will be returned with * a {@link ChannelFuture} instance which will notify you when the requested I/O * operation has succeeded, failed, or canceled. * * <h3>Channels are hierarchical</h3> * <p> * A {@link Channel} can have a {@linkplain #parent() parent} depending on * how it was created. For instance, a {@link SocketChannel}, that was accepted * by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel} * as its parent on {@link #parent()}. * <p> * The semantics of the hierarchical structure depends on the transport * implementation where the {@link Channel} belongs to. For example, you could * write a new {@link Channel} implementation that creates the sub-channels that * share one socket connection, as <a href="http://beepcore.org/">BEEP</a> and * <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a> do. * * <h3>Downcast to access transport-specific operations</h3> * <p> * Some transports exposes additional operations that is specific to the * transport. Down-cast the {@link Channel} to sub-type to invoke such * operations. For example, with the old I/O datagram transport, multicast * join / leave operations are provided by {@link DatagramChannel}. * * <h3>Release resources</h3> * <p> * It is important to call {@link #close()} or {@link #close(ChannelPromise)} to release all * resources once you are done with the {@link Channel}. This ensures all resources are * released in a proper way, i.e. filehandles. */ public interface Channel extends AttributeMap, Comparable<Channel> { /** * Return the {@link EventLoop} this {@link Channel} was registered to. */ EventLoop eventLoop(); /** * Returns the parent of this channel. * * @return the parent channel. * {@code null} if this channel does not have a parent channel. */ Channel parent(); /** * Returns the configuration of this channel. */ ChannelConfig config(); /** * Returns {@code true} if the {@link Channel} is open and may get active later */ boolean isOpen(); /** * Returns {@code true} if the {@link Channel} is registered with an {@link EventLoop}. */ boolean isRegistered(); /** * Return {@code true} if the {@link Channel} is active and so connected. */ boolean isActive(); /** * Return the {@link ChannelMetadata} of the {@link Channel} which describe the nature of the {@link Channel}. */ ChannelMetadata metadata(); /** * Returns the local address where this channel is bound to. The returned * {@link SocketAddress} is supposed to be down-cast into more concrete * type such as {@link InetSocketAddress} to retrieve the detailed * information. * * @return the local address of this channel. * {@code null} if this channel is not bound. */ SocketAddress localAddress(); /** * Returns the remote address where this channel is connected to. The * returned {@link SocketAddress} is supposed to be down-cast into more * concrete type such as {@link InetSocketAddress} to retrieve the detailed * information. * * @return the remote address of this channel. * {@code null} if this channel is not connected. * If this channel is not connected but it can receive messages * from arbitrary remote addresses (e.g. {@link DatagramChannel}, * use {@link DatagramPacket#recipient()} to determine * the origination of the received message as this method will * return {@code null}. */ SocketAddress remoteAddress(); /** * Returns the {@link ChannelFuture} which will be notified when this * channel is closed. This method always returns the same future instance. */ ChannelFuture closeFuture(); /** * Returns {@code true} if and only if the I/O thread will perform the * requested write operation immediately. Any write requests made when * this method returns {@code false} are queued until the I/O thread is * ready to process the queued write requests. */ boolean isWritable(); /** * Returns an <em>internal-use-only</em> object that provides unsafe operations. */ Unsafe unsafe(); /** * Return the assigned {@link ChannelPipeline}. */ ChannelPipeline pipeline(); /** * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. */ ByteBufAllocator alloc(); /** * Return a new {@link ChannelPromise}. */ ChannelPromise newPromise(); /** * Return an new {@link ChannelProgressivePromise}. */ ChannelProgressivePromise newProgressivePromise(); /** * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also * every call of blocking methods will just return without blocking. */ ChannelFuture newSucceededFuture(); /** * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also * every call of blocking methods will just return without blocking. */ ChannelFuture newFailedFuture(Throwable cause); /** * Return a special ChannelPromise which can be reused for different operations. * <p> * It's only supported to use * it for {@link Channel#write(Object, ChannelPromise)}. * </p> * <p> * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used * if you want to save an object allocation for every write operation. You will not be able to detect if the * operation was complete, only if it failed as the implementation will call * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. * </p> * <strong>Be aware this is an expert feature and should be used with care!</strong> */ ChannelPromise voidPromise(); /** * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * completes, either because the operation was successful or because of an error. * <p> * This will result in having the * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture bind(SocketAddress localAddress); /** * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * completes, either because the operation was successful or because of an error. * <p> * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} * will be used. * <p> * This will result in having the * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture connect(SocketAddress remoteAddress); /** * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of * an error. * <p> * This will result in having the * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); /** * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, * either because the operation was successful or because of an error. * <p> * This will result in having the * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture disconnect(); /** * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, * either because the operation was successful or because of * an error. * * After it is closed it is not possible to reuse it again. * <p> * This will result in having the * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture close(); /** * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of * an error. * <p> * This will result in having the * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. * */ ChannelFuture deregister(); /** * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * completes, either because the operation was successful or because of an error. * * The given {@link ChannelPromise} will be notified. * <p> * This will result in having the * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); /** * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation * completes, either because the operation was successful or because of an error. * * The given {@link ChannelFuture} will be notified. * * <p> * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} * will be used. * <p> * This will result in having the * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); /** * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of * an error. * * The given {@link ChannelPromise} will be notified and also returned. * <p> * This will result in having the * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); /** * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, * either because the operation was successful or because of an error. * * The given {@link ChannelPromise} will be notified. * <p> * This will result in having the * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture disconnect(ChannelPromise promise); /** * Request to close this {@link Channel} and notify the {@link ChannelFuture} once the operation completes, * either because the operation was successful or because of * an error. * * After it is closed it is not possible to reuse it again. * The given {@link ChannelPromise} will be notified. * <p> * This will result in having the * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture close(ChannelPromise promise); /** * Request to deregister this {@link Channel} from the previous assigned {@link EventExecutor} and notify the * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of * an error. * * The given {@link ChannelPromise} will be notified. * <p> * This will result in having the * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ ChannelFuture deregister(ChannelPromise promise); /** * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was * read, and triggers a * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. * <p> * This will result in having the * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the * {@link Channel}. */ Channel read(); /** * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. * This method will not request to actual flush, so be sure to call {@link #flush()} * once you want to request to flush all pending data to the actual transport. */ ChannelFuture write(Object msg); /** * Request to write a message via this {@link Channel} through the {@link ChannelPipeline}. * This method will not request to actual flush, so be sure to call {@link #flush()} * once you want to request to flush all pending data to the actual transport. */ ChannelFuture write(Object msg, ChannelPromise promise); /** * Request to flush all pending messages. */ Channel flush(); /** * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. */ ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); /** * Shortcut for call {@link #write(Object)} and {@link #flush()}. */ ChannelFuture writeAndFlush(Object msg); /** * <em>Unsafe</em> operations that should <em>never</em> be called from user-code. These methods * are only provided to implement the actual transport, and must be invoked from an I/O thread except for the * following methods: * <ul> * <li>{@link #localAddress()}</li> * <li>{@link #remoteAddress()}</li> * <li>{@link #closeForcibly()}</li> * <li>{@link #register(EventLoop, ChannelPromise)}</li> * <li>{@link #voidPromise()}</li> * </ul> */ interface Unsafe { /** * Return the {@link SocketAddress} to which is bound local or * {@code null} if none. */ SocketAddress localAddress(); /** * Return the {@link SocketAddress} to which is bound remote or * {@code null} if none is bound yet. */ SocketAddress remoteAddress(); /** * Register the {@link Channel} of the {@link ChannelPromise} with the {@link EventLoop} and notify * the {@link ChannelFuture} once the registration was complete. */ void register(EventLoop eventLoop, ChannelPromise promise); /** * Bind the {@link SocketAddress} to the {@link Channel} of the {@link ChannelPromise} and notify * it once its done. */ void bind(SocketAddress localAddress, ChannelPromise promise); /** * Connect the {@link Channel} of the given {@link ChannelFuture} with the given remote {@link SocketAddress}. * If a specific local {@link SocketAddress} should be used it need to be given as argument. Otherwise just * pass {@code null} to it. * * The {@link ChannelPromise} will get notified once the connect operation was complete. */ void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); /** * Disconnect the {@link Channel} of the {@link ChannelFuture} and notify the {@link ChannelPromise} once the * operation was complete. */ void disconnect(ChannelPromise promise); /** * Close the {@link Channel} of the {@link ChannelPromise} and notify the {@link ChannelPromise} once the * operation was complete. */ void close(ChannelPromise promise); /** * Closes the {@link Channel} immediately without firing any events. Probably only useful * when registration attempt failed. */ void closeForcibly(); /** * Deregister the {@link Channel} of the {@link ChannelPromise} from {@link EventLoop} and notify the * {@link ChannelPromise} once the operation was complete. */ void deregister(ChannelPromise promise); /** * Schedules a read operation that fills the inbound buffer of the first {@link ChannelInboundHandler} in the * {@link ChannelPipeline}. If there's already a pending read operation, this method does nothing. */ void beginRead(); /** * Schedules a write operation. */ void write(Object msg, ChannelPromise promise); /** * Flush out all write operations scheduled via {@link #write(Object, ChannelPromise)}. */ void flush(); /** * Return a special ChannelPromise which can be reused and passed to the operations in {@link Unsafe}. * It will never be notified of a success or error and so is only a placeholder for operations * that take a {@link ChannelPromise} as argument but for which you not want to get notified. */ ChannelPromise voidPromise(); /** * Returns the {@link ChannelOutboundBuffer} of the {@link Channel} where the pending write requests are stored. */ ChannelOutboundBuffer outboundBuffer(); } }