@Override public void messageReceived(final ChannelHandlerContext ctx, MessageEvent e) throws Exception { // call super to reset the read timeout super.messageReceived(ctx, e); Channel channel = ctx.getChannel(); Object attribute = Channels.getAttribute(channel); if (attribute instanceof Callback) { Object message = e.getMessage(); Callback ac = (Callback) attribute; if (message instanceof HttpChunk) { // the AsyncCallable is to be processed on the last chunk if (HttpChunk.class.cast(message).isLast()) // process the AsyncCallable before passing the message to the protocol ac.call(); // FIXME remove attribute? } else { LOGGER.info("Received unexpected message while expecting a chunk: " + message); ac.call(); Channels.setDiscard(channel); } } else if (attribute instanceof NettyResponseFuture<?>) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; protocol.handle(channel, future, e.getMessage()); } else if (attribute != DiscardEvent.INSTANCE) { // unhandled message LOGGER.debug("Orphan channel {} with attribute {} received message {}, closing", channel, attribute, e.getMessage()); Channels.silentlyCloseChannel(channel); } }
@Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { if (requestSender.isClosed()) return; Channel channel = ctx.getChannel(); channelManager.removeAll(channel); try { super.channelClosed(ctx, e); } catch (Exception ex) { LOGGER.trace("super.channelClosed", ex); } Object attribute = Channels.getAttribute(channel); LOGGER.debug("Channel Closed: {} with attribute {}", channel, attribute); if (attribute instanceof Callback) { Callback callback = (Callback) attribute; Channels.setAttribute(channel, callback.future()); callback.call(); } else if (attribute instanceof NettyResponseFuture<?>) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; future.touch(); if (!config.getIOExceptionFilters().isEmpty() && requestSender.applyIoExceptionFiltersAndReplayRequest(future, CHANNEL_CLOSED_EXCEPTION, channel)) return; protocol.onClose(future); requestSender.handleUnexpectedClosedChannel(channel, future); } }
Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture<?>) { future = (NettyResponseFuture<?>) attribute;
public void close() { channelPool.destroy(); openChannels.close(); for (Channel channel : openChannels) { Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture<?>) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; future.cancelTimeouts(); } } // FIXME also shutdown in provider config.executorService().shutdown(); if (allowReleaseSocketChannelFactory) { socketChannelFactory.releaseExternalResources(); plainBootstrap.releaseExternalResources(); secureBootstrap.releaseExternalResources(); webSocketBootstrap.releaseExternalResources(); secureWebSocketBootstrap.releaseExternalResources(); } }
private boolean isChannelCloseable(Channel channel) { Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; if (!future.isDone()) LOGGER.error("Future not in appropriate state %s, not closing", future); } return true; }
@Override public void onClose(Channel channel) { logger.trace("onClose {}"); Object attribute = Channels.getAttribute(channel); if (!(attribute instanceof NettyResponseFuture)) return; try { NettyResponseFuture<?> nettyResponse = NettyResponseFuture.class.cast(attribute); WebSocketUpgradeHandler h = WebSocketUpgradeHandler.class.cast(nettyResponse.getAsyncHandler()); NettyWebSocket webSocket = NettyWebSocket.class.cast(h.onCompleted()); // FIXME How could this test not succeed, we just checked above that attribute is a NettyResponseFuture???? logger.trace("Connection was closed abnormally (that is, with no close frame being sent)."); if (attribute != DiscardEvent.INSTANCE && webSocket != null) webSocket.close(1006, "Connection was closed abnormally (that is, with no close frame being sent)."); } catch (Throwable t) { logger.error("onError", t); } } }
@Override public void onError(Channel channel, Throwable e) { try { Object attribute = Channels.getAttribute(channel); logger.warn("onError {}", e); if (!(attribute instanceof NettyResponseFuture)) { return; } NettyResponseFuture<?> nettyResponse = (NettyResponseFuture<?>) attribute; WebSocketUpgradeHandler h = WebSocketUpgradeHandler.class.cast(nettyResponse.getAsyncHandler()); NettyWebSocket webSocket = NettyWebSocket.class.cast(h.onCompleted()); if (webSocket != null) { webSocket.onError(e.getCause()); webSocket.close(); } } catch (Throwable t) { logger.error("onError", t); } }
Object attribute = Channels.getAttribute(channel);
public boolean retry(NettyResponseFuture<?> future, Channel channel) { if (isClosed()) return false; // FIXME this was done in AHC2, is this a bug? // channelManager.removeAll(channel); if (future == null) { Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture) future = (NettyResponseFuture<?>) attribute; } if (future != null && future.canBeReplayed()) { future.setState(NettyResponseFuture.STATE.RECONNECTED); LOGGER.debug("Trying to recover request {}\n", future.getNettyRequest().getHttpRequest()); if (future.getAsyncHandler() instanceof AsyncHandlerExtensions) AsyncHandlerExtensions.class.cast(future.getAsyncHandler()).onRetry(); try { sendNextRequest(future.getRequest(), future); return true; } catch (IOException iox) { future.setState(NettyResponseFuture.STATE.CLOSED); future.abort(iox); LOGGER.error("Remotely Closed, unable to recover", iox); return false; } } else { LOGGER.debug("Unable to recover future {}\n", future); return false; } }
Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture<?>) { future = (NettyResponseFuture<?>) attribute;
public void close() { channelPool.destroy(); openChannels.close(); for (Channel channel : openChannels) { Object attribute = Channels.getAttribute(channel); if (attribute instanceof NettyResponseFuture<?>) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; future.cancelTimeouts(); } } // FIXME also shutdown in provider config.executorService().shutdown(); if (allowReleaseSocketChannelFactory) { socketChannelFactory.releaseExternalResources(); plainBootstrap.releaseExternalResources(); secureBootstrap.releaseExternalResources(); webSocketBootstrap.releaseExternalResources(); secureWebSocketBootstrap.releaseExternalResources(); } }
@Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { if (requestSender.isClosed()) return; Channel channel = ctx.getChannel(); channelManager.removeAll(channel); try { super.channelClosed(ctx, e); } catch (Exception ex) { LOGGER.trace("super.channelClosed", ex); } Object attribute = Channels.getAttribute(channel); LOGGER.debug("Channel Closed: {} with attribute {}", channel, attribute); if (attribute instanceof Callback) { Callback callback = (Callback) attribute; Channels.setAttribute(channel, callback.future()); callback.call(); } else if (attribute instanceof NettyResponseFuture<?>) { NettyResponseFuture<?> future = (NettyResponseFuture<?>) attribute; future.touch(); if (!config.getIOExceptionFilters().isEmpty() && requestSender.applyIoExceptionFiltersAndReplayRequest(future, CHANNEL_CLOSED_EXCEPTION, channel)) return; protocol.onClose(channel); if (future == null || future.isDone()) channelManager.closeChannel(channel); else if (!requestSender.retry(future, ctx.getChannel())) requestSender.abort(future, REMOTELY_CLOSED_EXCEPTION); } }