@Override @Nullable protected SslInfo initSslInfo() { SslHandler sslHandler = ((Connection) this.request).channel().pipeline().get(SslHandler.class); if (sslHandler != null) { SSLSession session = sslHandler.engine().getSession(); return new DefaultSslInfo(session); } return null; }
@Override @Nullable protected String initId() { return this.request instanceof Connection ? ((Connection) this.request).channel().id().asShortText() : null; }
@Override @Nullable protected SslInfo initSslInfo() { SslHandler sslHandler = ((Connection) this.request).channel().pipeline().get(SslHandler.class); if (sslHandler != null) { SSLSession session = sslHandler.engine().getSession(); return new DefaultSslInfo(session); } return null; }
@Override @Nullable protected String initId() { return this.request instanceof Connection ? ((Connection) this.request).channel().id().asShortText() : null; }
/** * A variant of {@link #ReactorNettyTcpClient(String, int, ReactorNettyCodec)} * that still manages the lifecycle of the {@link TcpClient} and underlying * resources, but allows for direct configuration of other properties of the * client through a {@code Function<TcpClient, TcpClient>}. * @param clientConfigurer the configurer function * @param codec for encoding and decoding the input/output byte streams * @since 5.1.3 * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(Function<TcpClient, TcpClient> clientConfigurer, ReactorNettyCodec<P> codec) { Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = clientConfigurer.apply(TcpClient .create(this.poolResources) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel()))); }
/** * Simple constructor with the host and port to use to connect to. * <p>This constructor manages the lifecycle of the {@link TcpClient} and * underlying resources such as {@link ConnectionProvider}, * {@link LoopResources}, and {@link ChannelGroup}. * <p>For full control over the initialization and lifecycle of the * TcpClient, use {@link #ReactorNettyTcpClient(TcpClient, ReactorNettyCodec)}. * @param host the host to connect to * @param port the port to connect to * @param codec for encoding and decoding the input/output byte streams * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(String host, int port, ReactorNettyCodec<P> codec) { Assert.notNull(host, "host is required"); Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = TcpClient.create(this.poolResources) .host(host).port(port) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel())); }
/** * Creates a new instance * * @param connection the {@link Connection} to for managing the server */ public TcpDuplexConnection(Connection connection) { this.connection = Objects.requireNonNull(connection, "connection must not be null"); this.channelClosed = FutureMono.from(connection.channel().closeFuture()) .doFinally( s -> { if (!isDisposed()) { dispose(); } }) .subscribe(); }
/** * Creates a new instance * * @param connection the {@link Connection} to for managing the server */ public WebsocketDuplexConnection(Connection connection) { this.connection = Objects.requireNonNull(connection, "connection must not be null"); this.channelClosed = FutureMono.from(connection.channel().closeFuture()) .doFinally( s -> { if (!isDisposed()) { dispose(); } }) .subscribe(); }
@Override public Flux<Frame> receive() { return connection .inbound() .receive() .map( buf -> { CompositeByteBuf composite = connection.channel().alloc().compositeBuffer(); ByteBuf length = wrappedBuffer(new byte[FRAME_LENGTH_SIZE]); FrameHeaderFlyweight.encodeLength(length, 0, buf.readableBytes()); composite.addComponents(true, length, buf.retain()); return Frame.from(composite); }); }
@Override public Mono<Void> send(Publisher<Frame> frames) { return Flux.from(frames) .transform( frameFlux -> { if (frameFlux instanceof Fuseable.QueueSubscription) { Fuseable.QueueSubscription<Frame> queueSubscription = (Fuseable.QueueSubscription<Frame>) frameFlux; queueSubscription.requestFusion(Fuseable.ASYNC); return new SendPublisher<>( queueSubscription, frameFlux, connection.channel(), frame -> frame.content().retain(), ByteBuf::readableBytes); } else { return new SendPublisher<>( frameFlux, connection.channel(), frame -> frame.content().retain(), ByteBuf::readableBytes); } }) .then(); } }
@Override public Mono<Void> send(Publisher<Frame> frames) { return Flux.from(frames) .transform( frameFlux -> { if (frameFlux instanceof Fuseable.QueueSubscription) { Fuseable.QueueSubscription<Frame> queueSubscription = (Fuseable.QueueSubscription<Frame>) frameFlux; queueSubscription.requestFusion(Fuseable.ASYNC); return new SendPublisher<>( queueSubscription, frameFlux, connection.channel(), this::toBinaryWebSocketFrame, binaryWebSocketFrame -> binaryWebSocketFrame.content().readableBytes()); } else { return new SendPublisher<>( Queues.<Frame>small().get(), frameFlux, connection.channel(), this::toBinaryWebSocketFrame, binaryWebSocketFrame -> binaryWebSocketFrame.content().readableBytes()); } }) .then(); }
/** * A variant of {@link #ReactorNettyTcpClient(String, int, ReactorNettyCodec)} * that still manages the lifecycle of the {@link TcpClient} and underlying * resources, but allows for direct configuration of other properties of the * client through a {@code Function<TcpClient, TcpClient>}. * @param clientConfigurer the configurer function * @param codec for encoding and decoding the input/output byte streams * @since 5.1.3 * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(Function<TcpClient, TcpClient> clientConfigurer, ReactorNettyCodec<P> codec) { Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = clientConfigurer.apply(TcpClient .create(this.poolResources) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel()))); }
/** * Simple constructor with the host and port to use to connect to. * <p>This constructor manages the lifecycle of the {@link TcpClient} and * underlying resources such as {@link ConnectionProvider}, * {@link LoopResources}, and {@link ChannelGroup}. * <p>For full control over the initialization and lifecycle of the * TcpClient, use {@link #ReactorNettyTcpClient(TcpClient, ReactorNettyCodec)}. * @param host the host to connect to * @param port the port to connect to * @param codec for encoding and decoding the input/output byte streams * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(String host, int port, ReactorNettyCodec<P> codec) { Assert.notNull(host, "host is required"); Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = TcpClient.create(this.poolResources) .host(host).port(port) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel())); }
/** * Bind the {@link Connection} to the channel scope via an attribute. Can be * retrieved later by {@link #from}. If a previous reference {@link Connection} was * bound, this instance will take precedence. * * @return this {@link Connection}. */ default Connection bind() { channel().attr(ReactorNetty.CONNECTION) .set(this); return this; }
static boolean mustChunkFileTransfer(Connection c, Path file) { // if channel multiplexing a parent channel as an http2 stream if (c.channel().parent() != null && c.channel().parent().pipeline().get(Http2ConnectionHandler.class) != null) { return true; } ChannelPipeline p = c.channel().pipeline(); return p.get(SslHandler.class) != null || p.get(NettyPipeline.CompressionHandler) != null || (!(c.channel().eventLoop() instanceof NioEventLoop) && !"file".equals(file.toUri().getScheme())); }
/** * Remove a named handler if present and return this context * * @param name handler name * * @return this Connection */ default Connection removeHandler(String name) { ReactorNetty.removeHandler(channel(), name); return this; }
static void addChunkedWriter(Connection c){ if (c.channel() .pipeline() .get(ChunkedWriteHandler.class) == null) { c.addHandlerLast(NettyPipeline.ChunkedWriter, new ChunkedWriteHandler()); } }
protected HttpOperations(Connection connection, ConnectionObserver listener) { super(connection, listener); //reset channel to manual read if re-used connection.channel() .config() .setAutoRead(false); }
@Override public void onStateChange(Connection connection, State newState) { if (newState == State.DISCONNECTING) { if (connection.channel() .isActive() && !connection.isPersistent()) { connection.dispose(); } } childObs.onStateChange(connection, newState); } }
@Override public NettyOutbound sendObject(Object message) { onTerminate().subscribe(null, null, () -> ReactorNetty.safeRelease(message)); return then(FutureMono.deferFuture(() -> connection.channel() .writeAndFlush(message))); }