Java Code Examples for org.jboss.netty.channel.ChannelFuture#addListener()

The following examples show how to use org.jboss.netty.channel.ChannelFuture#addListener() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: NioClientSocketPipelineSink.java    From android-netty with Apache License 2.0 6 votes vote down vote up
private void connect(
        final NioClientSocketChannel channel, final ChannelFuture cf,
        SocketAddress remoteAddress) {
    try {
        if (channel.channel.connect(remoteAddress)) {
            channel.worker.register(channel, cf);
        } else {
            channel.getCloseFuture().addListener(new ChannelFutureListener() {
                public void operationComplete(ChannelFuture f)
                        throws Exception {
                    if (!cf.isDone()) {
                        cf.setFailure(new ClosedChannelException());
                    }
                }
            });
            cf.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            channel.connectFuture = cf;
            nextBoss().register(channel, cf);
        }

    } catch (Throwable t) {
        cf.setFailure(t);
        fireExceptionCaught(channel, t);
        channel.worker.close(channel, succeededFuture(channel));
    }
}
 
Example 2
Source File: FileServerHandler.java    From netty-file-parent with Apache License 2.0 6 votes vote down vote up
private void writeResponse(Channel channel) {
	ChannelBuffer buf = ChannelBuffers.copiedBuffer(
			this.responseContent.toString(), CharsetUtil.UTF_8);
	this.responseContent.setLength(0);

	boolean close = ("close".equalsIgnoreCase(this.request
			.getHeader("Connection")))
			|| ((this.request.getProtocolVersion()
					.equals(HttpVersion.HTTP_1_0)) && (!"keep-alive"
					.equalsIgnoreCase(this.request.getHeader("Connection"))));

	HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
			HttpResponseStatus.OK);
	response.setContent(buf);
	response.setHeader("Content-Type", "text/plain; charset=UTF-8");
	if (!close) {
		response.setHeader("Content-Length",
				String.valueOf(buf.readableBytes()));
	}
	ChannelFuture future = channel.write(response);
	if (close)
		future.addListener(ChannelFutureListener.CLOSE);
}
 
Example 3
Source File: NettyClient.java    From jstorm with Apache License 2.0 6 votes vote down vote up
/**
 * Avoid channel double close
 */
void closeChannel(final Channel channel) {
    synchronized (channelClosing) {
        if (closingChannel.contains(channel)) {
            LOG.info(channel.toString() + " has already been closed");
            return;
        }

        closingChannel.add(channel);
    }

    LOG.debug(channel.toString() + " begin to close");
    ChannelFuture closeFuture = channel.close();
    closeFuture.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture future) throws Exception {

            synchronized (channelClosing) {
                closingChannel.remove(channel);
            }
            LOG.debug(channel.toString() + " closed.");
        }
    });
}
 
Example 4
Source File: DefaultPinpointServer.java    From pinpoint with Apache License 2.0 5 votes vote down vote up
private ChannelFuture write0(Object message, ChannelFutureListener futureListener) {
    ChannelFuture future = channel.write(message);
    if (futureListener != null) {
        future.addListener(futureListener);
    }
    return future;
}
 
Example 5
Source File: PinpointClientHandshaker.java    From pinpoint with Apache License 2.0 5 votes vote down vote up
private void handshake(HandshakeJob handshakeJob) {
    handshakeCount.incrementAndGet();
    
    Channel channel = handshakeJob.getChannel();
    ControlHandshakePacket packet = handshakeJob.getHandshakePacket();
    
    logger.info("{} do handshake({}/{}). channel:{}.", id, handshakeCount.get(), maxHandshakeCount, channel);
    final ChannelFuture future = channel.write(packet);

    future.addListener(handShakeFailFutureListener);
}
 
Example 6
Source File: DefaultPinpointClientHandler.java    From pinpoint with Apache License 2.0 5 votes vote down vote up
private ChannelFuture write0(Object message, ChannelFutureListener futureListener) {
    if (futureListener == null) {
        throw new NullPointerException("futureListener");
    }
    ChannelFuture future = write0(message);
    future.addListener(futureListener);
    return future;
}
 
Example 7
Source File: DefaultPinpointClientHandler.java    From pinpoint with Apache License 2.0 5 votes vote down vote up
private void closeChannel() {
    Channel channel = this.channel;
    if (channel != null) {
        sendClosedPacket(channel);

        ChannelFuture closeFuture = channel.close();
        closeFuture.addListener(new WriteFailFutureListener(logger, "close() event failed.", "close() event success."));
        closeFuture.awaitUninterruptibly();
    }
}
 
Example 8
Source File: HttpServerHandler.java    From glowroot with Apache License 2.0 5 votes vote down vote up
private void writeResponse(MessageEvent e) throws Exception {
    HttpResponse response =
            new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
    response.setContent(ChannelBuffers.copiedBuffer("Hello world", CharsetUtil.UTF_8));
    addHeader(response, HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
    ChannelFuture future = e.getChannel().write(response);
    future.addListener(ChannelFutureListener.CLOSE);
}
 
Example 9
Source File: NetworkFailureHandler.java    From flink with Apache License 2.0 5 votes vote down vote up
@Override
public void channelOpen(ChannelHandlerContext context, ChannelStateEvent event) throws Exception {
	// Suspend incoming traffic until connected to the remote host.
	final Channel sourceChannel = event.getChannel();
	sourceChannel.setReadable(false);

	boolean isBlocked = blocked.get();
	LOG.debug("Attempt to open proxy channel from [{}] to [{}:{}] in state [blocked = {}]",
		sourceChannel.getLocalAddress(),
		remoteHost,
		remotePort,
		isBlocked);

	if (isBlocked) {
		sourceChannel.close();
		return;
	}

	// Start the connection attempt.
	ClientBootstrap targetConnectionBootstrap = new ClientBootstrap(channelFactory);
	targetConnectionBootstrap.getPipeline().addLast(TARGET_CHANNEL_HANDLER_NAME, new TargetChannelHandler(event.getChannel(), blocked));
	ChannelFuture connectFuture = targetConnectionBootstrap.connect(new InetSocketAddress(remoteHost, remotePort));
	sourceToTargetChannels.put(sourceChannel, connectFuture.getChannel());

	connectFuture.addListener(future -> {
		if (future.isSuccess()) {
			// Connection attempt succeeded:
			// Begin to accept incoming traffic.
			sourceChannel.setReadable(true);
		} else {
			// Close the connection if the connection attempt has failed.
			sourceChannel.close();
		}
	});
}
 
Example 10
Source File: NettyServerHandler.java    From migration-tool with Apache License 2.0 5 votes vote down vote up
@SuppressWarnings("rawtypes")
public void run() {
	//暂不支持List
	if (message instanceof List) {
		List messages = (List) message;
		for (Object messageObject : messages) {
			threadPool.execute(new HandlerRunnable(ctx, messageObject, threadPool, timeout));
		}
	} else {
		long beginTime = System.currentTimeMillis();
		String response = ServerHandler.handleRequest(message);
		log.debug("request:" + (String)message + " response:" + response);
		// already timeout,so not return
		if ((System.currentTimeMillis() - beginTime) >= timeout) {
			log.warn("timeout,so give up send response to client,request message is:" + message + ",response is:" + response + ",client is:" + ctx.getChannel().getRemoteAddress()
					+ ",consumetime is:" + (System.currentTimeMillis() - beginTime) + ",timeout is:" + timeout);
			return;
		}
		ChannelFuture wf = ctx.getChannel().write(response);
		wf.addListener(new ChannelFutureListener() {
			public void operationComplete(ChannelFuture future) throws Exception {
				if (!future.isSuccess()) {
					log.error("server write response error,request message is:" + message);
				}
			}
		});
	}
}
 
Example 11
Source File: NettyServerHandler.java    From migration-tool with Apache License 2.0 5 votes vote down vote up
private void sendErrorResponse(final ChannelHandlerContext ctx, final Object message) {
	ChannelFuture wf = ctx.getChannel().write(Commands.ERROR);
	wf.addListener(new ChannelFutureListener() {
		public void operationComplete(ChannelFuture future) throws Exception {
			if (!future.isSuccess()) {
				log.error("server write response error! request message is:" + message);
			}
		}
	});
}
 
Example 12
Source File: NetworkFailureHandler.java    From Flink-CEPplus with Apache License 2.0 5 votes vote down vote up
@Override
public void channelOpen(ChannelHandlerContext context, ChannelStateEvent event) throws Exception {
	// Suspend incoming traffic until connected to the remote host.
	final Channel sourceChannel = event.getChannel();
	sourceChannel.setReadable(false);

	boolean isBlocked = blocked.get();
	LOG.debug("Attempt to open proxy channel from [{}] to [{}:{}] in state [blocked = {}]",
		sourceChannel.getLocalAddress(),
		remoteHost,
		remotePort,
		isBlocked);

	if (isBlocked) {
		sourceChannel.close();
		return;
	}

	// Start the connection attempt.
	ClientBootstrap targetConnectionBootstrap = new ClientBootstrap(channelFactory);
	targetConnectionBootstrap.getPipeline().addLast(TARGET_CHANNEL_HANDLER_NAME, new TargetChannelHandler(event.getChannel(), blocked));
	ChannelFuture connectFuture = targetConnectionBootstrap.connect(new InetSocketAddress(remoteHost, remotePort));
	sourceToTargetChannels.put(sourceChannel, connectFuture.getChannel());

	connectFuture.addListener(future -> {
		if (future.isSuccess()) {
			// Connection attempt succeeded:
			// Begin to accept incoming traffic.
			sourceChannel.setReadable(true);
		} else {
			// Close the connection if the connection attempt has failed.
			sourceChannel.close();
		}
	});
}
 
Example 13
Source File: TSOClient.java    From phoenix-omid with Apache License 2.0 5 votes vote down vote up
private void sendRequest(final StateMachine.Fsm fsm, RequestEvent request) {
    TSOProto.Request req = request.getRequest();

    if (req.hasTimestampRequest()) {
        timestampRequests.add(new RequestAndTimeout(request, newTimeout(new TimestampRequestTimeoutEvent())));
    } else if (req.hasCommitRequest()) {
        TSOProto.CommitRequest commitReq = req.getCommitRequest();
        commitRequests.put(commitReq.getStartTimestamp(), new RequestAndTimeout(
                request, newTimeout(new CommitRequestTimeoutEvent(commitReq.getStartTimestamp()))));
    } else if (req.hasFenceRequest()) {
        TSOProto.FenceRequest fenceReq = req.getFenceRequest();
        fenceRequests.put(fenceReq.getTableId(), new RequestAndTimeout(
                request, newTimeout(new FenceRequestTimeoutEvent(fenceReq.getTableId()))));
    } else {
        request.error(new IllegalArgumentException("Unknown request type"));
        return;
    }
    ChannelFuture f = channel.write(req);

    f.addListener(new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) {
            if (!future.isSuccess()) {
                fsm.sendEvent(new ErrorEvent(future.getCause()));
            }
        }
    });
}
 
Example 14
Source File: WebSocketChannelHandler.java    From usergrid with Apache License 2.0 5 votes vote down vote up
private void sendHttpResponse( ChannelHandlerContext ctx, HttpRequest req, HttpResponse res ) {
    // Generate an error page if response status code is not OK (200).
    if ( res.getStatus().getCode() != 200 ) {
        res.setContent( ChannelBuffers.copiedBuffer( res.getStatus().toString(), CharsetUtil.UTF_8 ) );
        setContentLength( res, res.getContent().readableBytes() );
    }

    // Send the response and close the connection if necessary.
    ChannelFuture f = ctx.getChannel().write( res );
    if ( !isKeepAlive( req ) || ( res.getStatus().getCode() != 200 ) ) {
        f.addListener( ChannelFutureListener.CLOSE );
    }
}
 
Example 15
Source File: NetworkFailureHandler.java    From flink with Apache License 2.0 5 votes vote down vote up
@Override
public void channelOpen(ChannelHandlerContext context, ChannelStateEvent event) throws Exception {
	// Suspend incoming traffic until connected to the remote host.
	final Channel sourceChannel = event.getChannel();
	sourceChannel.setReadable(false);

	boolean isBlocked = blocked.get();
	LOG.debug("Attempt to open proxy channel from [{}] to [{}:{}] in state [blocked = {}]",
		sourceChannel.getLocalAddress(),
		remoteHost,
		remotePort,
		isBlocked);

	if (isBlocked) {
		sourceChannel.close();
		return;
	}

	// Start the connection attempt.
	ClientBootstrap targetConnectionBootstrap = new ClientBootstrap(channelFactory);
	targetConnectionBootstrap.getPipeline().addLast(TARGET_CHANNEL_HANDLER_NAME, new TargetChannelHandler(event.getChannel(), blocked));
	ChannelFuture connectFuture = targetConnectionBootstrap.connect(new InetSocketAddress(remoteHost, remotePort));
	sourceToTargetChannels.put(sourceChannel, connectFuture.getChannel());

	connectFuture.addListener(future -> {
		if (future.isSuccess()) {
			// Connection attempt succeeded:
			// Begin to accept incoming traffic.
			sourceChannel.setReadable(true);
		} else {
			// Close the connection if the connection attempt has failed.
			sourceChannel.close();
		}
	});
}
 
Example 16
Source File: NettyAsyncHttpProvider.java    From ck with Apache License 2.0 4 votes vote down vote up
private <T> Future<T> doConnect(final Request request, final AsyncHandler<T> asyncHandler, NettyResponseFuture<T> f) throws IOException{

		if (isClose.get()){
			throw new IOException("Closed");
		}

		if (activeConnectionsCount.getAndIncrement() >= config.getMaxTotalConnections()) {
			throw new IOException("Too many connections");
		}
		URI uri = createUri(request.getUrl());

		if (log.isDebugEnabled())
			log.debug("Lookup cache: " + uri.toString());

		Channel channel = lookupInCache(uri);
		if (channel != null && channel.isOpen()) {
			HttpRequest nettyRequest = buildRequest(config,request,uri);
			if (f == null) {
				f = new NettyResponseFuture<T>(uri, request, asyncHandler,
						nettyRequest, config.getRequestTimeoutInMs());
			}
			executeRequest(channel, config,f,nettyRequest);
			return f;
		}
		ConnectListener<T> c = new ConnectListener.Builder<T>(config, request, asyncHandler,f).build();
		configure(uri.getScheme().compareToIgnoreCase("https") == 0, c);

		ChannelFuture channelFuture;
		try{
			if (config.getProxyServer() == null) {
				channelFuture = bootstrap.connect(new InetSocketAddress(uri.getHost(), getPort(uri)));
			} else {
				channelFuture = bootstrap.connect(
						new InetSocketAddress(config.getProxyServer().getHost(), config.getProxyServer().getPort()));
			}
			bootstrap.setOption("connectTimeout", config.getConnectionTimeoutInMs());
		} catch (Throwable t){
			activeConnectionsCount.decrementAndGet();
			log.error(t);
			c.future().abort(t.getCause());
			return c.future();
		}
		channelFuture.addListener(c);
		openChannels.add(channelFuture.getChannel());
		return c.future();
	}
 
Example 17
Source File: ShuffleHandler.java    From big-c with Apache License 2.0 4 votes vote down vote up
protected ChannelFuture sendMapOutput(ChannelHandlerContext ctx, Channel ch,
    String user, String mapId, int reduce, MapOutputInfo mapOutputInfo)
    throws IOException {
  final IndexRecord info = mapOutputInfo.indexRecord;
  final ShuffleHeader header =
    new ShuffleHeader(mapId, info.partLength, info.rawLength, reduce);
  final DataOutputBuffer dob = new DataOutputBuffer();
  header.write(dob);
  ch.write(wrappedBuffer(dob.getData(), 0, dob.getLength()));
  final File spillfile =
      new File(mapOutputInfo.mapOutputFileName.toString());
  RandomAccessFile spill;
  try {
    spill = SecureIOUtils.openForRandomRead(spillfile, "r", user, null);
  } catch (FileNotFoundException e) {
    LOG.info(spillfile + " not found");
    return null;
  }
  ChannelFuture writeFuture;
  if (ch.getPipeline().get(SslHandler.class) == null) {
    final FadvisedFileRegion partition = new FadvisedFileRegion(spill,
        info.startOffset, info.partLength, manageOsCache, readaheadLength,
        readaheadPool, spillfile.getAbsolutePath(), 
        shuffleBufferSize, shuffleTransferToAllowed);
    writeFuture = ch.write(partition);
    writeFuture.addListener(new ChannelFutureListener() {
        // TODO error handling; distinguish IO/connection failures,
        //      attribute to appropriate spill output
      @Override
      public void operationComplete(ChannelFuture future) {
        if (future.isSuccess()) {
          partition.transferSuccessful();
        }
        partition.releaseExternalResources();
      }
    });
  } else {
    // HTTPS cannot be done with zero copy.
    final FadvisedChunkedFile chunk = new FadvisedChunkedFile(spill,
        info.startOffset, info.partLength, sslFileBufferSize,
        manageOsCache, readaheadLength, readaheadPool,
        spillfile.getAbsolutePath());
    writeFuture = ch.write(chunk);
  }
  metrics.shuffleConnections.incr();
  metrics.shuffleOutputBytes.incr(info.partLength); // optimistic
  return writeFuture;
}
 
Example 18
Source File: ShuffleHandler.java    From hadoop with Apache License 2.0 4 votes vote down vote up
protected ChannelFuture sendMapOutput(ChannelHandlerContext ctx, Channel ch,
    String user, String mapId, int reduce, MapOutputInfo mapOutputInfo)
    throws IOException {
  final IndexRecord info = mapOutputInfo.indexRecord;
  final ShuffleHeader header =
    new ShuffleHeader(mapId, info.partLength, info.rawLength, reduce);
  final DataOutputBuffer dob = new DataOutputBuffer();
  header.write(dob);
  ch.write(wrappedBuffer(dob.getData(), 0, dob.getLength()));
  final File spillfile =
      new File(mapOutputInfo.mapOutputFileName.toString());
  RandomAccessFile spill;
  try {
    spill = SecureIOUtils.openForRandomRead(spillfile, "r", user, null);
  } catch (FileNotFoundException e) {
    LOG.info(spillfile + " not found");
    return null;
  }
  ChannelFuture writeFuture;
  if (ch.getPipeline().get(SslHandler.class) == null) {
    final FadvisedFileRegion partition = new FadvisedFileRegion(spill,
        info.startOffset, info.partLength, manageOsCache, readaheadLength,
        readaheadPool, spillfile.getAbsolutePath(), 
        shuffleBufferSize, shuffleTransferToAllowed);
    writeFuture = ch.write(partition);
    writeFuture.addListener(new ChannelFutureListener() {
        // TODO error handling; distinguish IO/connection failures,
        //      attribute to appropriate spill output
      @Override
      public void operationComplete(ChannelFuture future) {
        if (future.isSuccess()) {
          partition.transferSuccessful();
        }
        partition.releaseExternalResources();
      }
    });
  } else {
    // HTTPS cannot be done with zero copy.
    final FadvisedChunkedFile chunk = new FadvisedChunkedFile(spill,
        info.startOffset, info.partLength, sslFileBufferSize,
        manageOsCache, readaheadLength, readaheadPool,
        spillfile.getAbsolutePath());
    writeFuture = ch.write(chunk);
  }
  metrics.shuffleConnections.incr();
  metrics.shuffleOutputBytes.incr(info.partLength); // optimistic
  return writeFuture;
}
 
Example 19
Source File: ShuffleHandler.java    From tez with Apache License 2.0 4 votes vote down vote up
/**
 * Calls sendMapOutput for the mapId pointed by ReduceContext.mapsToSend
 * and increments it. This method is first called by messageReceived()
 * maxSessionOpenFiles times and then on the completion of every
 * sendMapOutput operation. This limits the number of open files on a node,
 * which can get really large(exhausting file descriptors on the NM) if all
 * sendMapOutputs are called in one go, as was done previous to this change.
 * @param reduceContext used to call sendMapOutput with correct params.
 * @return the ChannelFuture of the sendMapOutput, can be null.
 */
public ChannelFuture sendMap(ReduceContext reduceContext)
    throws Exception {

  ChannelFuture nextMap = null;
  if (reduceContext.getMapsToSend().get() <
      reduceContext.getMapIds().size()) {
    int nextIndex = reduceContext.getMapsToSend().getAndIncrement();
    String mapId = reduceContext.getMapIds().get(nextIndex);

    try {
      MapOutputInfo info = reduceContext.getInfoMap().get(mapId);
      if (info == null) {
        info = getMapOutputInfo(reduceContext.dagId, mapId, reduceContext.getReduceRange(),
            reduceContext.getJobId(),
            reduceContext.getUser());
      }
      nextMap = sendMapOutput(
          reduceContext.getCtx(),
          reduceContext.getCtx().getChannel(),
          reduceContext.getUser(), mapId,
          reduceContext.getReduceRange(), info);
      if (null == nextMap) {
        sendError(reduceContext.getCtx(), NOT_FOUND);
        return null;
      }
      nextMap.addListener(new ReduceMapFileCount(reduceContext));
    } catch (IOException e) {
      if (e instanceof DiskChecker.DiskErrorException) {
        LOG.error("Shuffle error :" + e);
      } else {
        LOG.error("Shuffle error :", e);
      }
      String errorMessage = getErrorMessage(e);
      sendError(reduceContext.getCtx(), errorMessage,
          INTERNAL_SERVER_ERROR);
      return null;
    }
  }
  return nextMap;
}
 
Example 20
Source File: NettyHttpChannel.java    From Elasticsearch with Apache License 2.0 4 votes vote down vote up
@Override
public void doSendResponse(RestResponse response) {
    // if the response object was created upstream, then use it;
    // otherwise, create a new one
    HttpResponse resp = newResponse();
    resp.setStatus(getStatus(response.status()));

    CorsHandler.setCorsResponseHeaders(nettyRequest, resp, transport.getCorsConfig());

    String opaque = nettyRequest.headers().get("X-Opaque-Id");
    if (opaque != null) {
        resp.headers().add("X-Opaque-Id", opaque);
    }

    // Add all custom headers
    Map<String, List<String>> customHeaders = response.getHeaders();
    if (customHeaders != null) {
        for (Map.Entry<String, List<String>> headerEntry : customHeaders.entrySet()) {
            for (String headerValue : headerEntry.getValue()) {
                resp.headers().add(headerEntry.getKey(), headerValue);
            }
        }
    }

    BytesReference content = response.content();
    ChannelBuffer buffer;
    boolean addedReleaseListener = false;
    try {
        buffer = content.toChannelBuffer();
        resp.setContent(buffer);

        // If our response doesn't specify a content-type header, set one
        if (!resp.headers().contains(HttpHeaders.Names.CONTENT_TYPE)) {
            resp.headers().add(HttpHeaders.Names.CONTENT_TYPE, response.contentType());
        }

        // If our response has no content-length, calculate and set one
        if (!resp.headers().contains(HttpHeaders.Names.CONTENT_LENGTH)) {
            resp.headers().add(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buffer.readableBytes()));
        }

        if (transport.resetCookies) {
            String cookieString = nettyRequest.headers().get(HttpHeaders.Names.COOKIE);
            if (cookieString != null) {
                CookieDecoder cookieDecoder = new CookieDecoder();
                Set<Cookie> cookies = cookieDecoder.decode(cookieString);
                if (!cookies.isEmpty()) {
                    // Reset the cookies if necessary.
                    CookieEncoder cookieEncoder = new CookieEncoder(true);
                    for (Cookie cookie : cookies) {
                        cookieEncoder.addCookie(cookie);
                    }
                    resp.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
                }
            }
        }

        ChannelFuture future;

        if (orderedUpstreamMessageEvent != null) {
            OrderedDownstreamChannelEvent downstreamChannelEvent = new OrderedDownstreamChannelEvent(orderedUpstreamMessageEvent, 0, true, resp);
            future = downstreamChannelEvent.getFuture();
            channel.getPipeline().sendDownstream(downstreamChannelEvent);
        } else {
            future = channel.write(resp);
        }

        if (content instanceof Releasable) {
            future.addListener(new ReleaseChannelFutureListener((Releasable) content));
            addedReleaseListener = true;
        }

        if (isCloseConnection()) {
            future.addListener(ChannelFutureListener.CLOSE);
        }

    } finally {
        if (!addedReleaseListener && content instanceof Releasable) {
            ((Releasable) content).close();
        }
    }
}