@Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { HttpChildChannel httpChildChannel = this.httpChildChannel; if (httpChildChannel != null) { this.httpChildChannel = null; switch (httpChildChannel.readState()) { case UPGRADED: if (httpChildChannel.setReadClosed()) { fireChannelDisconnected(httpChildChannel); fireChannelUnbound(httpChildChannel); fireChannelClosed(httpChildChannel); } break; case CONTENT_COMPLETE: break; default: ChannelException exception = new ChannelException("Channel closed unexpectedly"); exception.fillInStackTrace(); fireExceptionCaught(httpChildChannel, exception); break; } switch (httpChildChannel.writeState()) { case UPGRADED: case CONTENT_CLOSE: if (httpChildChannel.setWriteClosed()) { fireChannelDisconnected(httpChildChannel); fireChannelUnbound(httpChildChannel); fireChannelClosed(httpChildChannel); } break; case CONTENT_COMPLETE: break; default: ChannelException exception = new ChannelException("Channel closed unexpectedly"); exception.fillInStackTrace(); fireExceptionCaught(httpChildChannel, exception); break; } } }
@Override protected void httpMessageReceived( ChannelHandlerContext ctx, MessageEvent e, HttpChunk httpMessage) throws Exception { ChannelBuffer content = httpMessage.getContent(); if (content.readable()) { fireMessageReceived(httpChildChannel, content); } boolean last = httpMessage.isLast(); if (last) { HttpChildChannel httpChildChannel = this.httpChildChannel; httpChildChannel.readState(HttpReadState.CONTENT_COMPLETE); this.httpChildChannel = null; fireInputShutdown(httpChildChannel); if (httpChildChannel.setReadClosed()) { fireChannelDisconnected(httpChildChannel); fireChannelUnbound(httpChildChannel); fireChannelClosed(httpChildChannel); } } }
@Override protected void httpMessageReceived( ChannelHandlerContext ctx, MessageEvent e, HttpRequest httpRequest) throws Exception { HttpVersion version = httpRequest.getProtocolVersion(); URI httpLocation = getEffectiveURI(httpRequest); if (httpLocation == null) { // see RFC-7230 section 5.4 Host HttpResponse httpResponse = new DefaultHttpResponse(version, BAD_REQUEST); ChannelFuture future = future(ctx.getChannel()); write(ctx, future, httpResponse); return; } // channel's local address is resolved address so get the bind address from // server channel's attachment ChannelAddress transportCandidate = (ChannelAddress) ctx.getChannel().getParent().getAttachment(); ChannelAddress candidate = new ChannelAddress(httpLocation, transportCandidate); Entry<ChannelAddress, HttpServerChannel> httpBinding = httpBindings.floorEntry(candidate); if (httpBinding == null) { HttpResponse httpResponse = new DefaultHttpResponse(version, NOT_FOUND); ChannelFuture future = future(ctx.getChannel()); write(ctx, future, httpResponse); return; } HttpServerChannel parent = httpBinding.getValue(); ChannelFactory factory = parent.getFactory(); ChannelConfig config = parent.getConfig(); ChannelPipelineFactory pipelineFactory = config.getPipelineFactory(); ChannelPipeline pipeline = pipelineFactory.getPipeline(); ChannelAddress httpLocalAddress = parent.getLocalAddress(); Channel transport = ctx.getChannel(); ChannelAddress remoteAddress = remoteAddress(transport); ChannelAddress httpRemoteAddress = new ChannelAddress(httpLocation, remoteAddress, true); HttpChildChannelSink sink = new HttpChildChannelSink(transport); HttpChildChannel httpChildChannel = new HttpChildChannel(parent, factory, pipeline, sink); HttpChannelConfig httpChildConfig = httpChildChannel.getConfig(); httpChildConfig.setMethod(httpRequest.getMethod()); httpChildConfig.setVersion(version); httpChildConfig.getReadHeaders().set(httpRequest.headers()); httpChildConfig.setReadQuery(new QueryStringDecoder(httpRequest.getUri())); httpChildConfig.setWriteQuery(new QueryStringEncoder(httpRequest.getUri())); httpChildConfig.setStatus(HttpResponseStatus.OK); this.httpChildChannel = httpChildChannel; ChannelBuffer content = httpRequest.getContent(); // update read state before firing channel events if (isTransferEncodingChunked(httpRequest)) { httpChildChannel.readState(HttpReadState.CONTENT_CHUNKED); } else if (isContentLengthSet(httpRequest)) { long contentLength = getContentLength(httpRequest); contentLength -= content.readableBytes(); if (contentLength > 0) { httpChildChannel.readState(HttpReadState.CONTENT_CHUNKED); } else { httpChildChannel.readState(HttpReadState.CONTENT_COMPLETE); } } else { // see RFC-7230 section 3.3 // content indicated by presence of Content-Length or Transfer-Encoding httpChildChannel.readState(HttpReadState.CONTENT_COMPLETE); } fireChannelOpen(httpChildChannel); httpChildChannel.setLocalAddress(httpLocalAddress); httpChildChannel.setBound(); fireChannelBound(httpChildChannel, httpLocalAddress); httpChildChannel.setRemoteAddress(httpRemoteAddress); httpChildChannel.setConnected(); fireChannelConnected(httpChildChannel, httpRemoteAddress); if (content.readable()) { fireMessageReceived(httpChildChannel, content); } // note: status may be set in reaction to one of the above events, such as CONNECTED // so defer status code check until this point if (httpChildConfig.getStatus().getCode() == SWITCHING_PROTOCOLS.getCode()) { httpChildChannel.readState(HttpReadState.UPGRADED); } switch (httpChildChannel.readState()) { case CONTENT_COMPLETE: fireInputShutdown(httpChildChannel); this.httpChildChannel = null; if (httpChildChannel.setReadClosed()) { fireChannelDisconnected(httpChildChannel); fireChannelUnbound(httpChildChannel); fireChannelClosed(httpChildChannel); } break; default: break; } }