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 * https://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.handler.timeout; 17 18 import io.netty.bootstrap.ServerBootstrap; 19 import io.netty.channel.Channel; 20 import io.netty.channel.ChannelDuplexHandler; 21 import io.netty.channel.ChannelHandlerContext; 22 import io.netty.channel.ChannelInitializer; 23 24 import java.util.concurrent.TimeUnit; 25 26 /** 27 * Raises a {@link ReadTimeoutException} when no data was read within a certain 28 * period of time. 29 * 30 * <pre> 31 * // The connection is closed when there is no inbound traffic 32 * // for 30 seconds. 33 * 34 * public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> { 35 * public void initChannel({@link Channel} channel) { 36 * channel.pipeline().addLast("readTimeoutHandler", new {@link ReadTimeoutHandler}(30)); 37 * channel.pipeline().addLast("myHandler", new MyHandler()); 38 * } 39 * } 40 * 41 * // Handler should handle the {@link ReadTimeoutException}. 42 * public class MyHandler extends {@link ChannelDuplexHandler} { 43 * {@code @Override} 44 * public void exceptionCaught({@link ChannelHandlerContext} ctx, {@link Throwable} cause) 45 * throws {@link Exception} { 46 * if (cause instanceof {@link ReadTimeoutException}) { 47 * // do something 48 * } else { 49 * super.exceptionCaught(ctx, cause); 50 * } 51 * } 52 * } 53 * 54 * {@link ServerBootstrap} bootstrap = ...; 55 * ... 56 * bootstrap.childHandler(new MyChannelInitializer()); 57 * ... 58 * </pre> 59 * @see WriteTimeoutHandler 60 * @see IdleStateHandler 61 */ 62 public class ReadTimeoutHandler extends IdleStateHandler { 63 private boolean closed; 64 65 /** 66 * Creates a new instance. 67 * 68 * @param timeoutSeconds 69 * read timeout in seconds 70 */ 71 public ReadTimeoutHandler(int timeoutSeconds) { 72 this(timeoutSeconds, TimeUnit.SECONDS); 73 } 74 75 /** 76 * Creates a new instance. 77 * 78 * @param timeout 79 * read timeout 80 * @param unit 81 * the {@link TimeUnit} of {@code timeout} 82 */ 83 public ReadTimeoutHandler(long timeout, TimeUnit unit) { 84 super(timeout, 0, 0, unit); 85 } 86 87 @Override 88 protected final void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { 89 assert evt.state() == IdleState.READER_IDLE; 90 readTimedOut(ctx); 91 } 92 93 /** 94 * Is called when a read timeout was detected. 95 */ 96 protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { 97 if (!closed) { 98 ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE); 99 ctx.close(); 100 closed = true; 101 } 102 } 103 }