use of io.netty.util.concurrent.GenericFutureListener in project ratpack by ratpack.
the class RequestActionSupport method sendRequestBodyStream.
private void sendRequestBodyStream(Downstream<? super T> downstream, Channel channel, Publisher<? extends ByteBuf> publisher) {
streamingBody = true;
((DefaultExecution) execution).delimit(downstream::error, continuation -> {
continuation.resume(() -> {
publisher.subscribe(new Subscriber<ByteBuf>() {
private Subscription subscription;
private final AtomicBoolean done = new AtomicBoolean();
private long pending = requestConfig.content.getContentLength();
private final GenericFutureListener<Future<? super Void>> cancelOnCloseListener = c -> cancel();
private void cancel() {
subscription.cancel();
reset();
}
@Override
public void onSubscribe(Subscription subscription) {
if (subscription == null) {
throw new NullPointerException("'subscription' is null");
}
if (this.subscription != null) {
subscription.cancel();
return;
}
this.subscription = subscription;
if (channel.isOpen()) {
channel.closeFuture().addListener(cancelOnCloseListener);
if (channel.isWritable()) {
this.subscription.request(1);
}
onWritabilityChanged = () -> {
if (channel.isWritable() && !done.get()) {
this.subscription.request(1);
}
};
} else {
cancel();
}
}
@Override
public void onNext(ByteBuf o) {
o.touch();
if (!channel.isOpen()) {
o.release();
cancel();
return;
}
if (pending == 0) {
o.release();
subscription.request(1);
return;
}
int chunkSize = o.readableBytes();
if (pending > 0) {
if (chunkSize > pending) {
chunkSize = (int) pending;
o = o.slice(0, chunkSize);
}
pending = pending - chunkSize;
}
channel.write(new DefaultHttpContent(o));
if (channel.isWritable()) {
subscription.request(1);
} else {
channel.flush();
}
}
@Override
public void onError(Throwable t) {
if (t == null) {
throw new NullPointerException("error is null");
}
reset();
forceDispose(channel.pipeline()).addListener(future -> {
if (!future.isSuccess()) {
t.addSuppressed(future.cause());
}
downstream.error(t);
});
}
@Override
public void onComplete() {
if (done.compareAndSet(false, true)) {
if (pending > 0) {
reset();
forceDispose(channel.pipeline()).addListener(future -> {
Throwable t = new IllegalStateException("Publisher completed before sending advertised number of bytes");
if (!future.isSuccess()) {
t.addSuppressed(future.cause());
}
downstream.error(t);
});
} else {
reset();
channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
}
}
}
private void reset() {
if (done.compareAndSet(false, true)) {
onWritabilityChanged = NOOP_RUNNABLE;
channel.closeFuture().removeListener(cancelOnCloseListener);
streamingBody = false;
}
}
});
});
});
}
use of io.netty.util.concurrent.GenericFutureListener in project cdap by caskdata.
the class AbstractSocksServerConnectHandler method handleConnectRequest.
/**
* Handles the CONNECT socks request.
*
* @param ctx the context object for the channel
* @param destAddress the destination address
* @param destPort the destination port that the remote {@code localhost} is listening to
* @param responseFunc a {@link Function} for creating a {@link SocksMessage} to send back to client
* once the relay channel has been established
*/
private void handleConnectRequest(ChannelHandlerContext ctx, String destAddress, int destPort, Function<InetSocketAddress, SocksMessage> responseFunc, Supplier<SocksMessage> failureResponseSupplier) {
// Create a forwarding channel handler, which returns a Future.
// When that handler future completed successfully, responds with a Socks success response.
// After the success response completed successfully, add the relay handler to the pipeline.
Channel inboundChannel = ctx.channel();
createForwardingChannelHandler(inboundChannel, destAddress, destPort).addListener((GenericFutureListener<Future<RelayChannelHandler>>) handlerFuture -> {
if (handlerFuture.isSuccess()) {
RelayChannelHandler handler = handlerFuture.get();
SocketAddress relayAddress = handler.getRelayAddress();
if (!(relayAddress instanceof InetSocketAddress)) {
LOG.warn("Relay address is not InetSocketAddress: {} {}", relayAddress.getClass(), relayAddress);
inboundChannel.writeAndFlush(failureResponseSupplier.get()).addListener(channelFuture -> Channels.closeOnFlush(inboundChannel));
} else {
inboundChannel.writeAndFlush(responseFunc.apply((InetSocketAddress) relayAddress)).addListener(channelFuture -> {
if (channelFuture.isSuccess()) {
ctx.pipeline().remove(AbstractSocksServerConnectHandler.this);
ctx.pipeline().addLast(handler);
} else {
Channels.closeOnFlush(inboundChannel);
}
});
}
} else {
Channels.closeOnFlush(inboundChannel);
}
});
}
use of io.netty.util.concurrent.GenericFutureListener in project pollen by MoonflowerTeam.
the class PollinatedFabricLoginChannel method processClient.
private CompletableFuture<@Nullable FriendlyByteBuf> processClient(Minecraft client, PacketListener listener, FriendlyByteBuf data, Consumer<GenericFutureListener<? extends Future<? super Void>>> listenerAdder) {
CompletableFuture<FriendlyByteBuf> future = new CompletableFuture<>();
NetworkRegistry.processMessage(this.deserialize(data, PollinatedPacketDirection.LOGIN_CLIENTBOUND), new PollinatedFabricLoginPacketContext(pkt -> {
try {
future.complete(this.serialize(pkt, PollinatedPacketDirection.LOGIN_SERVERBOUND));
} catch (Throwable t) {
t.printStackTrace();
future.completeExceptionally(t);
}
}, listener.getConnection(), __ -> {
}, PollinatedPacketDirection.LOGIN_CLIENTBOUND), this.clientMessageHandler.get().get());
return future;
}
use of io.netty.util.concurrent.GenericFutureListener in project flink by splunk.
the class HandlerUtils method transferFile.
public static void transferFile(ChannelHandlerContext ctx, File file, HttpRequest httpRequest) throws FlinkException {
final RandomAccessFile randomAccessFile;
try {
randomAccessFile = new RandomAccessFile(file, "r");
} catch (FileNotFoundException e) {
throw new FlinkException("Can not find file " + file + ".", e);
}
try {
final long fileLength = randomAccessFile.length();
final FileChannel fileChannel = randomAccessFile.getChannel();
try {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
response.headers().set(CONTENT_TYPE, "text/plain");
if (HttpHeaders.isKeepAlive(httpRequest)) {
response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
}
HttpHeaders.setContentLength(response, fileLength);
// write the initial line and the header.
ctx.write(response);
// write the content.
final ChannelFuture lastContentFuture;
final GenericFutureListener<Future<? super Void>> completionListener = future -> {
fileChannel.close();
randomAccessFile.close();
};
if (ctx.pipeline().get(SslHandler.class) == null) {
ctx.write(new DefaultFileRegion(fileChannel, 0, fileLength), ctx.newProgressivePromise()).addListener(completionListener);
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
} else {
lastContentFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(randomAccessFile, 0, fileLength, 8192)), ctx.newProgressivePromise()).addListener(completionListener);
// HttpChunkedInput will write the end marker (LastHttpContent) for us.
}
// close the connection, if no keep-alive is needed
if (!HttpHeaders.isKeepAlive(httpRequest)) {
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
} catch (IOException ex) {
fileChannel.close();
throw ex;
}
} catch (IOException ioe) {
try {
randomAccessFile.close();
} catch (IOException e) {
throw new FlinkException("Close file or channel error.", e);
}
throw new FlinkException("Could not transfer file " + file + " to the client.", ioe);
}
}
use of io.netty.util.concurrent.GenericFutureListener in project aws-sdk-java-v2 by aws.
the class MultiplexedChannelRecord method acquireClaimedStream.
void acquireClaimedStream(Promise<Channel> promise) {
doInEventLoop(connection.eventLoop(), () -> {
if (state != RecordState.OPEN) {
String message;
// GOAWAY
if (state == RecordState.CLOSED_TO_NEW) {
message = String.format("Connection %s received GOAWAY with Last Stream ID %d. Unable to open new " + "streams on this connection.", connection, lastStreamId);
} else {
message = String.format("Connection %s was closed while acquiring new stream.", connection);
}
log.warn(connection, () -> message);
promise.setFailure(new IOException(message));
return;
}
Future<Http2StreamChannel> streamFuture = new Http2StreamChannelBootstrap(connection).open();
streamFuture.addListener((GenericFutureListener<Future<Http2StreamChannel>>) future -> {
warnIfNotInEventLoop(connection.eventLoop());
if (!future.isSuccess()) {
promise.setFailure(future.cause());
return;
}
Http2StreamChannel channel = future.getNow();
channel.pipeline().addLast(UnusedChannelExceptionHandler.getInstance());
channel.attr(ChannelAttributeKey.HTTP2_FRAME_STREAM).set(channel.stream());
channel.attr(ChannelAttributeKey.CHANNEL_DIAGNOSTICS).set(new ChannelDiagnostics(channel));
childChannels.put(channel.id(), channel);
promise.setSuccess(channel);
if (closeIfIdleTask == null && allowedIdleConnectionTimeMillis != null) {
enableCloseIfIdleTask();
}
});
}, promise);
}
Aggregations