View Javadoc

1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.channel;
17  
18  import java.net.InetSocketAddress;
19  import java.net.SocketAddress;
20  import java.nio.channels.NotYetConnectedException;
21  import java.nio.channels.SelectionKey;
22  
23  import org.jboss.netty.channel.socket.DatagramChannel;
24  import org.jboss.netty.channel.socket.ServerSocketChannel;
25  import org.jboss.netty.channel.socket.SocketChannel;
26  import org.jboss.netty.channel.socket.nio.NioSocketChannelConfig;
27  
28  
29  /**
30   * A nexus to a network socket or a component which is capable of I/O
31   * operations such as read, write, connect, and bind.
32   * <p>
33   * A channel provides a user:
34   * <ul>
35   * <li>the current state of the channel (e.g. is it open? is it connected?),</li>
36   * <li>the {@linkplain ChannelConfig configuration parameters} of the channel (e.g. receive buffer size),</li>
37   * <li>the I/O operations that the channel supports (e.g. read, write, connect, and bind), and</li>
38   * <li>the {@link ChannelPipeline} which handles all {@linkplain ChannelEvent I/O events and requests}
39   *     associated with the channel.</li>
40   * </ul>
41   *
42   * <h3>All I/O operations are asynchronous.</h3>
43   * <p>
44   * All I/O operations in Netty are asynchronous.  It means any I/O calls will
45   * return immediately with no guarantee that the requested I/O operation has
46   * been completed at the end of the call.  Instead, you will be returned with
47   * a {@link ChannelFuture} instance which will notify you when the requested I/O
48   * operation has succeeded, failed, or canceled.
49   *
50   * <h3>Channels are hierarchical</h3>
51   * <p>
52   * A {@link Channel} can have a {@linkplain #getParent() parent} depending on
53   * how it was created.  For instance, a {@link SocketChannel}, that was accepted
54   * by {@link ServerSocketChannel}, will return the {@link ServerSocketChannel}
55   * as its parent on {@link #getParent()}.
56   * <p>
57   * The semantics of the hierarchical structure depends on the transport
58   * implementation where the {@link Channel} belongs to.  For example, you could
59   * write a new {@link Channel} implementation that creates the sub-channels that
60   * share one socket connection, as <a href="http://beepcore.org/">BEEP</a> and
61   * <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a> do.
62   *
63   * <h3>Downcast to access transport-specific operations</h3>
64   * <p>
65   * Some transports exposes additional operations that is specific to the
66   * transport.  Down-cast the {@link Channel} to sub-type to invoke such
67   * operations.  For example, with the old I/O datagram transport, multicast
68   * join / leave operations are provided by {@link DatagramChannel}.
69   *
70   * <h3>InterestOps</h3>
71   * <p>
72   * A {@link Channel} has a property called {@link #getInterestOps() interestOps}
73   * which is similar to that of {@link SelectionKey#interestOps() NIO SelectionKey}.
74   * It is represented as a <a href="http://en.wikipedia.org/wiki/Bit_field">bit
75   * field</a> which is composed of the two flags.
76   * <ul>
77   * <li>{@link #OP_READ} - If set, a message sent by a remote peer will be read
78   *     immediately.  If unset, the message from the remote peer will not be read
79   *     until the {@link #OP_READ} flag is set again (i.e. read suspension).</li>
80   * <li>{@link #OP_WRITE} - If set, a write request will not be sent to a remote
81   *     peer until the {@link #OP_WRITE} flag is cleared and the write request
82   *     will be pending in a queue.  If unset, the write request will be flushed
83   *     out as soon as possible from the queue.</li>
84   * <li>{@link #OP_READ_WRITE} - This is a combination of {@link #OP_READ} and
85   *     {@link #OP_WRITE}, which means only write requests are suspended.</li>
86   * <li>{@link #OP_NONE} - This is a combination of (NOT {@link #OP_READ}) and
87   *     (NOT {@link #OP_WRITE}), which means only read operation is suspended.</li>
88   * </ul>
89   * </p><p>
90   * You can set or clear the {@link #OP_READ} flag to suspend and resume read
91   * operation via {@link #setReadable(boolean)}.
92   * </p><p>
93   * Please note that you cannot suspend or resume write operation just like you
94   * can set or clear {@link #OP_READ}. The {@link #OP_WRITE} flag is read only
95   * and provided simply as a mean to tell you if the size of pending write
96   * requests exceeded a certain threshold or not so that you don't issue too many
97   * pending writes that lead to an {@link OutOfMemoryError}.  For example, the
98   * NIO socket transport uses the {@code writeBufferLowWaterMark} and
99   * {@code writeBufferHighWaterMark} properties in {@link NioSocketChannelConfig}
100  * to determine when to set or clear the {@link #OP_WRITE} flag.
101  * </p>
102  *
103  * @apiviz.landmark
104  * @apiviz.composedOf org.jboss.netty.channel.ChannelConfig
105  * @apiviz.composedOf org.jboss.netty.channel.ChannelPipeline
106  *
107  * @apiviz.exclude ^org\.jboss\.netty\.channel\.([a-z]+\.)+[^\.]+Channel$
108  */
109 public interface Channel extends Comparable<Channel> {
110 
111     /**
112      * The {@link #getInterestOps() interestOps} value which tells that only
113      * read operation has been suspended.
114      */
115     int OP_NONE = 0;
116 
117     /**
118      * The {@link #getInterestOps() interestOps} value which tells that neither
119      * read nor write operation has been suspended.
120      */
121     int OP_READ = 1;
122 
123     /**
124      * The {@link #getInterestOps() interestOps} value which tells that both
125      * read and write operation has been suspended.
126      */
127     int OP_WRITE = 4;
128 
129     /**
130      * The {@link #getInterestOps() interestOps} value which tells that only
131      * write operation has been suspended.
132      */
133     int OP_READ_WRITE = OP_READ | OP_WRITE;
134 
135     /**
136      * Returns the unique integer ID of this channel.
137      */
138     Integer getId();
139 
140     /**
141      * Returns the {@link ChannelFactory} which created this channel.
142      */
143     ChannelFactory getFactory();
144 
145     /**
146      * Returns the parent of this channel.
147      *
148      * @return the parent channel.
149      *         {@code null} if this channel does not have a parent channel.
150      */
151     Channel getParent();
152 
153     /**
154      * Returns the configuration of this channel.
155      */
156     ChannelConfig getConfig();
157 
158     /**
159      * Returns the {@link ChannelPipeline} which handles {@link ChannelEvent}s
160      * associated with this channel.
161      */
162     ChannelPipeline getPipeline();
163 
164     /**
165      * Returns {@code true} if and only if this channel is open.
166      */
167     boolean isOpen();
168 
169     /**
170      * Returns {@code true} if and only if this channel is bound to a
171      * {@linkplain #getLocalAddress() local address}.
172      */
173     boolean isBound();
174 
175     /**
176      * Returns {@code true} if and only if this channel is connected to a
177      * {@linkplain #getRemoteAddress() remote address}.
178      */
179     boolean isConnected();
180 
181     /**
182      * Returns the local address where this channel is bound to.  The returned
183      * {@link SocketAddress} is supposed to be down-cast into more concrete
184      * type such as {@link InetSocketAddress} to retrieve the detailed
185      * information.
186      *
187      * @return the local address of this channel.
188      *         {@code null} if this channel is not bound.
189      */
190     SocketAddress getLocalAddress();
191 
192     /**
193      * Returns the remote address where this channel is connected to.  The
194      * returned {@link SocketAddress} is supposed to be down-cast into more
195      * concrete type such as {@link InetSocketAddress} to retrieve the detailed
196      * information.
197      *
198      * @return the remote address of this channel.
199      *         {@code null} if this channel is not connected.
200      *         If this channel is not connected but it can receive messages
201      *         from arbitrary remote addresses (e.g. {@link DatagramChannel},
202      *         use {@link MessageEvent#getRemoteAddress()} to determine
203      *         the origination of the received message as this method will
204      *         return {@code null}.
205      */
206     SocketAddress getRemoteAddress();
207 
208     /**
209      * Sends a message to this channel asynchronously.    If this channel was
210      * created by a connectionless transport (e.g. {@link DatagramChannel})
211      * and is not connected yet, you have to call {@link #write(Object, SocketAddress)}
212      * instead.  Otherwise, the write request will fail with
213      * {@link NotYetConnectedException} and an {@code 'exceptionCaught'} event
214      * will be triggered.
215      *
216      * @param message the message to write
217      *
218      * @return the {@link ChannelFuture} which will be notified when the
219      *         write request succeeds or fails
220      *
221      * @throws NullPointerException if the specified message is {@code null}
222      */
223     ChannelFuture write(Object message);
224 
225     /**
226      * Sends a message to this channel asynchronously.  It has an additional
227      * parameter that allows a user to specify where to send the specified
228      * message instead of this channel's current remote address.  If this
229      * channel was created by a connectionless transport (e.g. {@link DatagramChannel})
230      * and is not connected yet, you must specify non-null address.  Otherwise,
231      * the write request will fail with {@link NotYetConnectedException} and
232      * an {@code 'exceptionCaught'} event will be triggered.
233      *
234      * @param message       the message to write
235      * @param remoteAddress where to send the specified message.
236      *                      This method is identical to {@link #write(Object)}
237      *                      if {@code null} is specified here.
238      *
239      * @return the {@link ChannelFuture} which will be notified when the
240      *         write request succeeds or fails
241      *
242      * @throws NullPointerException if the specified message is {@code null}
243      */
244     ChannelFuture write(Object message, SocketAddress remoteAddress);
245 
246     /**
247      * Binds this channel to the specified local address asynchronously.
248      *
249      * @param localAddress where to bind
250      *
251      * @return the {@link ChannelFuture} which will be notified when the
252      *         bind request succeeds or fails
253      *
254      * @throws NullPointerException if the specified address is {@code null}
255      */
256     ChannelFuture bind(SocketAddress localAddress);
257 
258     /**
259      * Connects this channel to the specified remote address asynchronously.
260      *
261      * @param remoteAddress where to connect
262      *
263      * @return the {@link ChannelFuture} which will be notified when the
264      *         connection request succeeds or fails
265      *
266      * @throws NullPointerException if the specified address is {@code null}
267      */
268     ChannelFuture connect(SocketAddress remoteAddress);
269 
270     /**
271      * Disconnects this channel from the current remote address asynchronously.
272      *
273      * @return the {@link ChannelFuture} which will be notified when the
274      *         disconnection request succeeds or fails
275      */
276     ChannelFuture disconnect();
277 
278     /**
279      * Unbinds this channel from the current local address asynchronously.
280      *
281      * @return the {@link ChannelFuture} which will be notified when the
282      *         unbind request succeeds or fails
283      */
284     ChannelFuture unbind();
285 
286     /**
287      * Closes this channel asynchronously.  If this channel is bound or
288      * connected, it will be disconnected and unbound first.  Once a channel
289      * is closed, it can not be open again.  Calling this method on a closed
290      * channel has no effect.  Please note that this method always returns the
291      * same future instance.
292      *
293      * @return the {@link ChannelFuture} which will be notified when the
294      *         close request succeeds or fails
295      */
296     ChannelFuture close();
297 
298     /**
299      * Returns the {@link ChannelFuture} which will be notified when this
300      * channel is closed.  This method always returns the same future instance.
301      */
302     ChannelFuture getCloseFuture();
303 
304     /**
305      * Returns the current {@code interestOps} of this channel.
306      *
307      * @return {@link #OP_NONE}, {@link #OP_READ}, {@link #OP_WRITE}, or
308      *         {@link #OP_READ_WRITE}
309      */
310     int getInterestOps();
311 
312     /**
313      * Returns {@code true} if and only if the I/O thread will read a message
314      * from this channel.  This method is a shortcut to the following code:
315      * <pre>
316      * return (getInterestOps() & OP_READ) != 0;
317      * </pre>
318      */
319     boolean isReadable();
320 
321     /**
322      * Returns {@code true} if and only if the I/O thread will perform the
323      * requested write operation immediately.  Any write requests made when
324      * this method returns {@code false} are queued until the I/O thread is
325      * ready to process the queued write requests.  This method is a shortcut
326      * to the following code:
327      * <pre>
328      * return (getInterestOps() & OP_WRITE) == 0;
329      * </pre>
330      */
331     boolean isWritable();
332 
333     /**
334      * Changes the {@code interestOps} of this channel asynchronously.
335      *
336      * @param interestOps the new {@code interestOps}
337      *
338      * @return the {@link ChannelFuture} which will be notified when the
339      *         {@code interestOps} change request succeeds or fails
340      */
341     ChannelFuture setInterestOps(int interestOps);
342 
343     /**
344      * Suspends or resumes the read operation of the I/O thread asynchronously.
345      * This method is a shortcut to the following code:
346      * <pre>
347      * int interestOps = getInterestOps();
348      * if (readable) {
349      *     setInterestOps(interestOps | OP_READ);
350      * } else {
351      *     setInterestOps(interestOps & ~OP_READ);
352      * }
353      * </pre>
354      *
355      * @param readable {@code true} to resume the read operation and
356      *                 {@code false} to suspend the read operation
357      *
358      * @return the {@link ChannelFuture} which will be notified when the
359      *         {@code interestOps} change request succeeds or fails
360      */
361     ChannelFuture setReadable(boolean readable);
362 
363     /**
364      * Retrieves an object which is {@link #setAttachment(Object) attached} to
365      * this {@link Channel}.
366      *
367      * @return {@code null} if no object was attached or {@code null} was
368      *         attached
369      */
370     Object getAttachment();
371 
372     /**
373      * Attaches an object to this {@link Channel} to store a stateful
374      * information
375      */
376     void setAttachment(Object attachment);
377 }