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 io.netty.channel; 17 18 19 import io.netty.buffer.ByteBuf; 20 import io.netty.buffer.ByteBufAllocator; 21 import io.netty.util.AttributeKey; 22 import io.netty.util.AttributeMap; 23 import io.netty.util.concurrent.EventExecutor; 24 import io.netty.util.concurrent.FutureListener; 25 26 import java.net.ConnectException; 27 import java.net.SocketAddress; 28 import java.nio.channels.Channels; 29 30 /** 31 * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline} 32 * and other handlers. A handler can notify the next {@link ChannelHandler} in the {@link ChannelPipeline}, 33 * modify the {@link ChannelPipeline} it belongs to dynamically. 34 * 35 * <h3>Notify</h3> 36 * 37 * You can notify the closest handler in the 38 * same {@link ChannelPipeline} by calling one of the various methods provided here. 39 * Please refer to {@link ChannelPipeline} to understand how an event flows. 40 * 41 * <h3>Modifying a pipeline</h3> 42 * 43 * You can get the {@link ChannelPipeline} your handler belongs to by calling 44 * {@link #pipeline()}. A non-trivial application could insert, remove, or 45 * replace handlers in the pipeline dynamically at runtime. 46 * 47 * <h3>Retrieving for later use</h3> 48 * 49 * You can keep the {@link ChannelHandlerContext} for later use, such as 50 * triggering an event outside the handler methods, even from a different thread. 51 * <pre> 52 * public class MyHandler extends {@link ChannelDuplexHandler} { 53 * 54 * <b>private {@link ChannelHandlerContext} ctx;</b> 55 * 56 * public void beforeAdd({@link ChannelHandlerContext} ctx) { 57 * <b>this.ctx = ctx;</b> 58 * } 59 * 60 * public void login(String username, password) { 61 * ctx.write(new LoginMessage(username, password)); 62 * } 63 * ... 64 * } 65 * </pre> 66 * 67 * <h3>Storing stateful information</h3> 68 * 69 * {@link #attr(AttributeKey)} allow you to 70 * store and access stateful information that is related with a handler and its 71 * context. Please refer to {@link ChannelHandler} to learn various recommended 72 * ways to manage stateful information. 73 * 74 * <h3>A handler can have more than one context</h3> 75 * 76 * Please note that a {@link ChannelHandler} instance can be added to more than 77 * one {@link ChannelPipeline}. It means a single {@link ChannelHandler} 78 * instance can have more than one {@link ChannelHandlerContext} and therefore 79 * the single instance can be invoked with different 80 * {@link ChannelHandlerContext}s if it is added to one or more 81 * {@link ChannelPipeline}s more than once. 82 * <p> 83 * For example, the following handler will have as many independent {@link AttributeKey}s 84 * as how many times it is added to pipelines, regardless if it is added to the 85 * same pipeline multiple times or added to different pipelines multiple times: 86 * <pre> 87 * public class FactorialHandler extends {@link ChannelInboundHandlerAdapter}<{@link Integer}> { 88 * 89 * private final {@link AttributeKey}<{@link Integer}> counter = 90 * new {@link AttributeKey}<{@link Integer}>("counter"); 91 * 92 * // This handler will receive a sequence of increasing integers starting 93 * // from 1. 94 * {@code @Override} 95 * public void channelRead({@link ChannelHandlerContext} ctx, Object msg) { 96 * Integer a = ctx.attr(counter).get(); 97 * 98 * if (a == null) { 99 * a = 1; 100 * } 101 * 102 * attr.set(a * integer)); 103 * } 104 * } 105 * 106 * // Different context objects are given to "f1", "f2", "f3", and "f4" even if 107 * // they refer to the same handler instance. Because the FactorialHandler 108 * // stores its state in a context object (as an (using an {@link AttributeKey}), the factorial is 109 * // calculated correctly 4 times once the two pipelines (p1 and p2) are active. 110 * FactorialHandler fh = new FactorialHandler(); 111 * 112 * {@link ChannelPipeline} p1 = {@link Channels}.pipeline(); 113 * p1.addLast("f1", fh); 114 * p1.addLast("f2", fh); 115 * 116 * {@link ChannelPipeline} p2 = {@link Channels}.pipeline(); 117 * p2.addLast("f3", fh); 118 * p2.addLast("f4", fh); 119 * </pre> 120 * 121 * <h3>Additional resources worth reading</h3> 122 * <p> 123 * Please refer to the {@link ChannelHandler}, and 124 * {@link ChannelPipeline} to find out more about inbound and outbound operations, 125 * what fundamental differences they have, how they flow in a pipeline, and how to handle 126 * the operation in your application. 127 */ 128 public interface ChannelHandlerContext 129 extends AttributeMap { 130 131 /** 132 * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}. 133 */ 134 Channel channel(); 135 136 /** 137 * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly 138 * submit tasks that get executed in the event loop. For more information please refer to the 139 * {@link EventExecutor} javadoc. 140 */ 141 EventExecutor executor(); 142 143 /** 144 * The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler} 145 * was added to the {@link ChannelPipeline}. This name can also be used to access the registered 146 * {@link ChannelHandler} from the {@link ChannelPipeline}. 147 */ 148 String name(); 149 150 /** 151 * The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}. 152 */ 153 ChannelHandler handler(); 154 155 /** 156 * Return {@code true} if the {@link ChannelHandler} which belongs to this context was removed 157 * from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the 158 * {@link EventLoop}. 159 */ 160 boolean isRemoved(); 161 162 /** 163 * A {@link Channel} was registered to its {@link EventLoop}. 164 * 165 * This will result in having the {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method 166 * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 167 * {@link Channel}. 168 */ 169 ChannelHandlerContext fireChannelRegistered(); 170 171 /** 172 * A {@link Channel} was unregistered from its {@link EventLoop}. 173 * 174 * This will result in having the {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method 175 * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 176 * {@link Channel}. 177 */ 178 ChannelHandlerContext fireChannelUnregistered(); 179 180 /** 181 * A {@link Channel} is active now, which means it is connected. 182 * 183 * This will result in having the {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method 184 * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 185 * {@link Channel}. 186 */ 187 ChannelHandlerContext fireChannelActive(); 188 189 /** 190 * A {@link Channel} is inactive now, which means it is closed. 191 * 192 * This will result in having the {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method 193 * called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 194 * {@link Channel}. 195 */ 196 ChannelHandlerContext fireChannelInactive(); 197 198 /** 199 * A {@link Channel} received an {@link Throwable} in one of its inbound operations. 200 * 201 * This will result in having the {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)} 202 * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 203 * {@link Channel}. 204 */ 205 ChannelHandlerContext fireExceptionCaught(Throwable cause); 206 207 /** 208 * A {@link Channel} received an user defined event. 209 * 210 * This will result in having the {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} 211 * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 212 * {@link Channel}. 213 */ 214 ChannelHandlerContext fireUserEventTriggered(Object evt); 215 216 /** 217 * A {@link Channel} received a message. 218 * 219 * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} 220 * method called of the next {@link ChannelInboundHandler} contained in the {@link ChannelPipeline} of the 221 * {@link Channel}. 222 */ 223 ChannelHandlerContext fireChannelRead(Object msg); 224 225 /** 226 * Triggers an {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext)} 227 * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. 228 */ 229 ChannelHandlerContext fireChannelReadComplete(); 230 231 /** 232 * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)} 233 * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. 234 */ 235 ChannelHandlerContext fireChannelWritabilityChanged(); 236 237 /** 238 * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 239 * completes, either because the operation was successful or because of an error. 240 * <p> 241 * This will result in having the 242 * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method 243 * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 244 * {@link Channel}. 245 */ 246 ChannelFuture bind(SocketAddress localAddress); 247 248 /** 249 * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 250 * completes, either because the operation was successful or because of an error. 251 * <p> 252 * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with 253 * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} 254 * will be used. 255 * <p> 256 * This will result in having the 257 * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 258 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 259 * {@link Channel}. 260 */ 261 ChannelFuture connect(SocketAddress remoteAddress); 262 263 /** 264 * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the 265 * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 266 * an error. 267 * <p> 268 * This will result in having the 269 * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 270 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 271 * {@link Channel}. 272 */ 273 ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); 274 275 /** 276 * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, 277 * either because the operation was successful or because of an error. 278 * <p> 279 * This will result in having the 280 * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} 281 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 282 * {@link Channel}. 283 */ 284 ChannelFuture disconnect(); 285 286 /** 287 * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, 288 * either because the operation was successful or because of 289 * an error. 290 * 291 * After it is closed it is not possible to reuse it again. 292 * <p> 293 * This will result in having the 294 * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} 295 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 296 * {@link Channel}. 297 */ 298 ChannelFuture close(); 299 300 /** 301 * Request to deregister from the previous assigned {@link EventExecutor} and notify the 302 * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 303 * an error. 304 * <p> 305 * This will result in having the 306 * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} 307 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 308 * {@link Channel}. 309 * 310 */ 311 ChannelFuture deregister(); 312 313 /** 314 * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 315 * completes, either because the operation was successful or because of an error. 316 * 317 * The given {@link ChannelPromise} will be notified. 318 * <p> 319 * This will result in having the 320 * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method 321 * called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 322 * {@link Channel}. 323 */ 324 ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); 325 326 /** 327 * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation 328 * completes, either because the operation was successful or because of an error. 329 * 330 * The given {@link ChannelFuture} will be notified. 331 * 332 * <p> 333 * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with 334 * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException} 335 * will be used. 336 * <p> 337 * This will result in having the 338 * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 339 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 340 * {@link Channel}. 341 */ 342 ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); 343 344 /** 345 * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the 346 * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 347 * an error. 348 * 349 * The given {@link ChannelPromise} will be notified and also returned. 350 * <p> 351 * This will result in having the 352 * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)} 353 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 354 * {@link Channel}. 355 */ 356 ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); 357 358 /** 359 * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes, 360 * either because the operation was successful or because of an error. 361 * 362 * The given {@link ChannelPromise} will be notified. 363 * <p> 364 * This will result in having the 365 * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)} 366 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 367 * {@link Channel}. 368 */ 369 ChannelFuture disconnect(ChannelPromise promise); 370 371 /** 372 * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes, 373 * either because the operation was successful or because of 374 * an error. 375 * 376 * After it is closed it is not possible to reuse it again. 377 * The given {@link ChannelPromise} will be notified. 378 * <p> 379 * This will result in having the 380 * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)} 381 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 382 * {@link Channel}. 383 */ 384 ChannelFuture close(ChannelPromise promise); 385 386 /** 387 * Request to deregister from the previous assigned {@link EventExecutor} and notify the 388 * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of 389 * an error. 390 * 391 * The given {@link ChannelPromise} will be notified. 392 * <p> 393 * This will result in having the 394 * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)} 395 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 396 * {@link Channel}. 397 */ 398 ChannelFuture deregister(ChannelPromise promise); 399 400 /** 401 * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an 402 * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was 403 * read, and triggers a 404 * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the 405 * handler can decide to continue reading. If there's a pending read operation already, this method does nothing. 406 * <p> 407 * This will result in having the 408 * {@link ChannelOutboundHandler#read(ChannelHandlerContext)} 409 * method called of the next {@link ChannelOutboundHandler} contained in the {@link ChannelPipeline} of the 410 * {@link Channel}. 411 */ 412 ChannelHandlerContext read(); 413 414 /** 415 * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. 416 * This method will not request to actual flush, so be sure to call {@link #flush()} 417 * once you want to request to flush all pending data to the actual transport. 418 */ 419 ChannelFuture write(Object msg); 420 421 /** 422 * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}. 423 * This method will not request to actual flush, so be sure to call {@link #flush()} 424 * once you want to request to flush all pending data to the actual transport. 425 */ 426 ChannelFuture write(Object msg, ChannelPromise promise); 427 428 /** 429 * Request to flush all pending messages via this ChannelOutboundInvoker. 430 */ 431 ChannelHandlerContext flush(); 432 433 /** 434 * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}. 435 */ 436 ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); 437 438 /** 439 * Shortcut for call {@link #write(Object)} and {@link #flush()}. 440 */ 441 ChannelFuture writeAndFlush(Object msg); 442 443 /** 444 * Return the assigned {@link ChannelPipeline} 445 */ 446 ChannelPipeline pipeline(); 447 448 /** 449 * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s. 450 */ 451 ByteBufAllocator alloc(); 452 453 /** 454 * Return a new {@link ChannelPromise}. 455 */ 456 ChannelPromise newPromise(); 457 458 /** 459 * Return an new {@link ChannelProgressivePromise} 460 */ 461 ChannelProgressivePromise newProgressivePromise(); 462 463 /** 464 * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()} 465 * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also 466 * every call of blocking methods will just return without blocking. 467 */ 468 ChannelFuture newSucceededFuture(); 469 470 /** 471 * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()} 472 * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also 473 * every call of blocking methods will just return without blocking. 474 */ 475 ChannelFuture newFailedFuture(Throwable cause); 476 477 /** 478 * Return a special ChannelPromise which can be reused for different operations. 479 * <p> 480 * It's only supported to use 481 * it for {@link ChannelHandlerContext#write(Object, ChannelPromise)}. 482 * </p> 483 * <p> 484 * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used 485 * if you want to save an object allocation for every write operation. You will not be able to detect if the 486 * operation was complete, only if it failed as the implementation will call 487 * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case. 488 * </p> 489 * <strong>Be aware this is an expert feature and should be used with care!</strong> 490 */ 491 ChannelPromise voidPromise(); 492 493 }