/*
* Copyright © 2015 Cask Data, Inc.
*
* Licensed 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 co.cask.cdap.gateway.router.handlers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.timeout.IdleState;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handles states when a channel has been idle for a configured time interval, by closing the channel if an
* HTTP Request is not in progress.
*/
public class IdleEventProcessor extends IdleStateAwareChannelHandler {
private static final Logger LOG = LoggerFactory.getLogger(IdleEventProcessor.class);
private boolean requestInProgress;
@Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
if (IdleState.ALL_IDLE == e.getState()) {
if (requestInProgress) {
LOG.trace("Request is in progress, so not closing channel.");
} else {
// No data has been sent or received for a while. Close channel.
Channel channel = ctx.getChannel();
channel.close();
LOG.trace("No data has been sent or received for channel '{}' for more than the configured idle timeout. " +
"Closing the channel. Local Address: {}, Remote Address: {}",
channel, channel.getLocalAddress(), channel.getRemoteAddress());
}
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
Object message = e.getMessage();
if (message instanceof HttpResponse) {
HttpResponse response = (HttpResponse) message;
if (!response.isChunked()) {
requestInProgress = false;
}
} else if (message instanceof HttpChunk) {
HttpChunk chunk = (HttpChunk) message;
if (chunk.isLast()) {
requestInProgress = false;
}
}
ctx.sendUpstream(e);
}
@Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Object message = e.getMessage();
if (message instanceof HttpRequest || message instanceof HttpChunk) {
requestInProgress = true;
}
ctx.sendDownstream(e);
}
}