@Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    if (httpChildChannel != null) {
      HttpChildChannel httpChildChannel = this.httpChildChannel;
      this.httpChildChannel = null;

      if (httpChildChannel.setReadClosed() || httpChildChannel.setWriteClosed()) {
        fireExceptionCaught(httpChildChannel, e.getCause());
        fireChannelClosed(httpChildChannel);
      }
    }

    Channel channel = ctx.getChannel();
    channel.close();
  }
  @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;
      }
    }
  }