/** * Creates a new instance * * @param bindAddress the address to bind to * @param port the port to bind to * @return a new instance * @throws NullPointerException if {@code bindAddress} is {@code null} */ public static TcpServerTransport create(String bindAddress, int port) { Objects.requireNonNull(bindAddress, "bindAddress must not be null"); TcpServer server = TcpServer.create().host(bindAddress).port(port); return create(server); }
private HttpServer createHttpServer() { HttpServer server = HttpServer.create(); if (this.resourceFactory != null) { LoopResources resources = this.resourceFactory.getLoopResources(); Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); server = server.tcpConfiguration((tcpServer) -> tcpServer.runOn(resources) .addressSupplier(this::getListenAddress)); } else { server = server.tcpConfiguration( (tcpServer) -> tcpServer.addressSupplier(this::getListenAddress)); } if (getSsl() != null && getSsl().isEnabled()) { SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(getSsl(), getHttp2(), getSslStoreProvider()); server = sslServerCustomizer.apply(server); } if (getCompression() != null && getCompression().getEnabled()) { CompressionCustomizer compressionCustomizer = new CompressionCustomizer( getCompression()); server = compressionCustomizer.apply(server); } server = server.protocol(listProtocols()).forwarded(this.useForwardHeaders); return applyCustomizers(server); }
@Override public Mono<CloseableChannel> start(ConnectionAcceptor acceptor) { Objects.requireNonNull(acceptor, "acceptor must not be null"); return server .doOnConnection( c -> { c.addHandlerLast(new RSocketLengthCodec()); TcpDuplexConnection connection = new TcpDuplexConnection(c); acceptor.apply(connection).then(Mono.<Void>never()).subscribe(c.disposeSubscriber()); }) .bind() .map(CloseableChannel::new); } }
@Override public Mono<InetSocketAddress> bind(int port, ServiceMethodRegistry methodRegistry) { return Mono.defer( () -> { TcpServer tcpServer = TcpServer.create() .runOn(loopResources) .addressSupplier(() -> new InetSocketAddress(port)) .doOnConnection( connection -> { LOGGER.info("Accepted connection on {}", connection.channel()); connection.onDispose( () -> { LOGGER.info("Connection closed on {}", connection.channel()); connections.remove(connection); }); connections.add(connection); }); return RSocketFactory.receive() .frameDecoder( frame -> ByteBufPayload.create( frame.sliceData().retain(), frame.sliceMetadata().retain())) .acceptor(new RSocketServiceAcceptor(codec, methodRegistry)) .transport(() -> TcpServerTransport.create(tcpServer)) .start() .map(server -> this.server = server) .map(CloseableChannel::address); }); }
/** * Creates TcpServer. * * @return tcp server */ private TcpServer newTcpServer() { return TcpServer.create() .runOn(loopResources) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.SO_REUSEADDR, true) .addressSupplier(() -> new InetSocketAddress(config.getPort())) .bootstrap(b -> BootstrapHandlers.updateConfiguration(b, "inbound", channelInitializer)); }
/** * Builds generic http server with given parameters. * * @param loopResources loop resources * @param port listen port * @param metrics gateway metrics * @return http server */ protected final HttpServer prepareHttpServer( LoopResources loopResources, int port, GatewayMetrics metrics) { return HttpServer.create() .tcpConfiguration( tcpServer -> { if (loopResources != null) { tcpServer = tcpServer.runOn(loopResources); } if (metrics != null) { tcpServer = tcpServer.doOnConnection( connection -> { metrics.incConnection(); connection.onDispose(metrics::decConnection); }); } return tcpServer.addressSupplier(() -> new InetSocketAddress(port)); }); }
/** * Set a {@link ChannelOption} value for low level connection settings like {@code SO_TIMEOUT} * or {@code SO_KEEPALIVE}. This will apply to each new channel from remote peer. * Use a value of {@code null} to remove a previous set {@link ChannelOption}. * * @param key the option key * @param value the option value * @param <T> the option type * * @return new {@link TcpServer} * * @see ServerBootstrap#childOption(ChannelOption, Object) */ public final <T> TcpServer option(ChannelOption<T> key, @Nullable T value) { Objects.requireNonNull(key, "key"); return bootstrap(b -> b.childOption(key, value)); }
@Override protected void initServer() { this.reactorHandler = createHttpHandlerAdapter(); this.reactorServer = reactor.netty.http.server.HttpServer.create() .tcpConfiguration(server -> server.host(getHost())) .port(getPort()); }
/** * Run IO loops on a supplied {@link EventLoopGroup} from the {@link LoopResources} * container. Will prefer native (epoll/kqueue) implementation if available unless the * environment property {@code reactor.netty.native} is set to {@code false}. * * @param channelResources a {@link LoopResources} accepting native runtime * expectation and returning an eventLoopGroup * * @return a new {@link TcpServer} */ public final TcpServer runOn(LoopResources channelResources) { return runOn(channelResources, LoopResources.DEFAULT_NATIVE); }
@Override public Mono<? extends DisposableServer> bind(ServerBootstrap b) { return source.bind(b); }
/** * Bind the {@link TcpServer} and return a {@link Mono} of {@link DisposableServer}. If * {@link Mono} is cancelled, the underlying binding will be aborted. Once the {@link * DisposableServer} has been emitted and is not necessary anymore, disposing main server * loop must be done by the user via {@link DisposableServer#dispose()}. * * If updateConfiguration phase fails, a {@link Mono#error(Throwable)} will be returned; * * @return a {@link Mono} of {@link DisposableServer} */ public final Mono<? extends DisposableServer> bind() { ServerBootstrap b; try{ b = configure(); } catch (Throwable t){ Exceptions.throwIfFatal(t); return Mono.error(t); } return bind(b); }
@Test @Ignore public void startContentServer() { Random random = new Random(0); byte[] content = new byte[1024 * 10]; random.nextBytes(content); HttpServer server = HttpServer.create() .port(CONTENT_SERVER_PORT) .tcpConfiguration(tcpServer -> tcpServer.host("0.0.0.0") .option(ChannelOption.SO_LINGER, -1)); server.route(routes -> routes.get("/**", (req, res) -> res.header("Content-length", String.valueOf(content.length)) .header("Content-type", "application/octet-stream") .header("Connection", "Close") .sendByteArray(Flux.just(content)))) .wiretap(true) .bindNow(); }
.handle((req, resp) -> req.receive().then(resp.sendNotFound())) .tcpConfiguration(tcp -> tcp.doOnConnection(c -> { channelRef.set(c.channel()); HttpServerCodec codec = c.channel()
@Test(timeout = 2000) public void startAndAwait() throws InterruptedException { AtomicReference<DisposableServer> conn = new AtomicReference<>(); CountDownLatch startLatch = new CountDownLatch(1); Thread t = new Thread(() -> TcpServer.create() .handle((in, out) -> out.sendString(Mono.just("foo"))) .bindUntilJavaShutdown(Duration.ofMillis(200), c -> { conn.set(c); startLatch.countDown(); })); t.start(); //let the server initialize startLatch.await(); //check nothing happens for 200ms t.join(200); Assertions.assertThat(t.isAlive()).isTrue(); //check that stopping the bnc stops the server conn.get().disposeNow(); t.join(); Assertions.assertThat(t.isAlive()).isFalse(); }
@DisplayName("creates client with TcpServer") @Test void createTcpClient() { assertThat(TcpServerTransport.create(TcpServer.create())).isNotNull(); }
/** * The port to which this server should bind. * * @param port The port to bind to. * * @return a new {@link HttpServer} */ public final HttpServer port(int port) { return tcpConfiguration(tcpServer -> tcpServer.port(port)); }