io.netty.channel.Channel Maven / Gradle / Ivy
/*
* 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:
*
* https://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 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.
*
* A channel provides a user:
*
* - the current state of the channel (e.g. is it open? is it connected?),
* - the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),
* - the I/O operations that the channel supports (e.g. read, write, connect, and bind), and
* - the {@link ChannelPipeline} which handles all I/O events and requests
* associated with the channel.
*
*
* All I/O operations are asynchronous.
*
* 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.
*
*
Channels are hierarchical
*
* 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()}.
*
* 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 BEEP and
* SSH do.
*
*
Downcast to access transport-specific operations
*
* 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}.
*
*
Release resources
*
* 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, ChannelOutboundInvoker, Comparable {
/**
* Returns the globally unique identifier of this {@link Channel}.
*/
ChannelId id();
/**
* 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.
*
* {@link WriteBufferWaterMark} can be used to configure on which condition
* the write buffer would cause this channel to change writability.
*/
default boolean isWritable() {
ChannelOutboundBuffer buf = unsafe().outboundBuffer();
return buf != null && buf.isWritable();
}
/**
* Get how many bytes can be written until {@link #isWritable()} returns {@code false}.
* This quantity will always be non-negative. If {@link #isWritable()} is {@code false} then 0.
*
* {@link WriteBufferWaterMark} can be used to define writability settings.
*/
default long bytesBeforeUnwritable() {
ChannelOutboundBuffer buf = unsafe().outboundBuffer();
// isWritable() is currently assuming if there is no outboundBuffer then the channel is not writable.
// We should be consistent with that here.
return buf != null ? buf.bytesBeforeUnwritable() : 0;
}
/**
* Get how many bytes must be drained from underlying buffers until {@link #isWritable()} returns {@code true}.
* This quantity will always be non-negative. If {@link #isWritable()} is {@code true} then 0.
*
* {@link WriteBufferWaterMark} can be used to define writability settings.
*/
default long bytesBeforeWritable() {
ChannelOutboundBuffer buf = unsafe().outboundBuffer();
// isWritable() is currently assuming if there is no outboundBuffer then the channel is not writable.
// We should be consistent with that here.
return buf != null ? buf.bytesBeforeWritable() : Long.MAX_VALUE;
}
/**
* Returns an internal-use-only 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.
*/
default ByteBufAllocator alloc() {
return config().getAllocator();
}
@Override
default Channel read() {
pipeline().read();
return this;
}
@Override
default Channel flush() {
pipeline().flush();
return this;
}
@Override
default ChannelFuture writeAndFlush(Object msg) {
return pipeline().writeAndFlush(msg);
}
@Override
default ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
return pipeline().writeAndFlush(msg, promise);
}
@Override
default ChannelFuture write(Object msg, ChannelPromise promise) {
return pipeline().write(msg, promise);
}
@Override
default ChannelFuture write(Object msg) {
return pipeline().write(msg);
}
@Override
default ChannelFuture deregister(ChannelPromise promise) {
return pipeline().deregister(promise);
}
@Override
default ChannelFuture close(ChannelPromise promise) {
return pipeline().close(promise);
}
@Override
default ChannelFuture disconnect(ChannelPromise promise) {
return pipeline().disconnect(promise);
}
@Override
default ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
return pipeline().connect(remoteAddress, localAddress, promise);
}
@Override
default ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
return pipeline().connect(remoteAddress, promise);
}
@Override
default ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
return pipeline().bind(localAddress, promise);
}
@Override
default ChannelFuture deregister() {
return pipeline().deregister();
}
@Override
default ChannelFuture close() {
return pipeline().close();
}
@Override
default ChannelFuture disconnect() {
return pipeline().disconnect();
}
@Override
default ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
return pipeline().connect(remoteAddress, localAddress);
}
@Override
default ChannelFuture connect(SocketAddress remoteAddress) {
return pipeline().connect(remoteAddress);
}
@Override
default ChannelFuture bind(SocketAddress localAddress) {
return pipeline().bind(localAddress);
}
@Override
default ChannelPromise newPromise() {
return pipeline().newPromise();
}
@Override
default ChannelProgressivePromise newProgressivePromise() {
return pipeline().newProgressivePromise();
}
@Override
default ChannelFuture newSucceededFuture() {
return pipeline().newSucceededFuture();
}
@Override
default ChannelFuture newFailedFuture(Throwable cause) {
return pipeline().newFailedFuture(cause);
}
@Override
default ChannelPromise voidPromise() {
return pipeline().voidPromise();
}
/**
* Unsafe operations that should never 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:
*
* - {@link #localAddress()}
* - {@link #remoteAddress()}
* - {@link #closeForcibly()}
* - {@link #register(EventLoop, ChannelPromise)}
* - {@link #deregister(ChannelPromise)}
* - {@link #voidPromise()}
*
*/
interface Unsafe {
/**
* Return the assigned {@link RecvByteBufAllocator.Handle} which will be used to allocate {@link ByteBuf}'s when
* receiving data.
*/
RecvByteBufAllocator.Handle recvBufAllocHandle();
/**
* 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} 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();
}
}