All Downloads are FREE. Search and download functionalities are using the official Maven repository.

reactor.io.net.NetStreams Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2011-2015 Pivotal Software Inc, All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package reactor.io.net;

import reactor.Environment;
import reactor.core.support.Assert;
import reactor.fn.Function;
import reactor.io.buffer.Buffer;
import reactor.io.net.http.HttpClient;
import reactor.io.net.http.HttpServer;
import reactor.io.net.impl.netty.http.NettyHttpClient;
import reactor.io.net.impl.netty.http.NettyHttpServer;
import reactor.io.net.impl.netty.tcp.NettyTcpClient;
import reactor.io.net.impl.netty.tcp.NettyTcpServer;
import reactor.io.net.impl.netty.udp.NettyDatagramServer;
import reactor.io.net.impl.zmq.tcp.ZeroMQTcpClient;
import reactor.io.net.impl.zmq.tcp.ZeroMQTcpServer;
import reactor.io.net.tcp.TcpClient;
import reactor.io.net.tcp.TcpServer;
import reactor.io.net.udp.DatagramServer;
import reactor.rx.Streams;

/**
 * A Streams add-on to work with network facilities from reactor-net, e.g.:
 * 

*

 * {@code
 * //echo server
 * NetStreams.tcpServer(1234).start( connection -> ch.writeWith(connection) );
 *
 * NetStreams.tcpClient(1234).start( connection ->
 *    connection
 *      //Listen for any incoming data on that connection, they will be Buffer an IOStream can easily decode
 *      .nest()
 *      .flatMap(self -> IOStreams.decode(new StringCodec('\n'), self))
 *      .consume(log::info);
 *
 *    //Push anything from the publisher returned, here a simple Reactor Stream. By default a Buffer is expected
 *    //Will close after write
 *    return connection.writeWith(Streams.just(Buffer.wrap("hello\n")));
 * });
 *
 * //We can also preconfigure global codecs and other custom client/server parameter with the Function signature:
 * NetStreams.tcpServer(spec -> spec.codec(kryoCodec).listen(1235)).start( intput -> {
 *      input.consume(log::info);
 *      return input.writeWith(Streams.period(1l));
 * });
 *
 * //Assigning the same codec to a client and a server greatly improve readability and provide for extended type safety.
 * NetStreams.tcpClient(spec -> spec.connect("localhost", 1235).codec(kryoCodec)).start( input -> {
 *   input.consume(log::info);
 *   return input.writeWith(Streams.just("hello"));
 * });
 *
 * }
 * 
* * @author Stephane Maldini */ public class NetStreams extends Streams { public static final int DEFAULT_PORT = 12012; public static final String DEFAULT_BIND_ADDRESS = "127.0.0.1"; public static final Class DEFAULT_TCP_SERVER_TYPE; public static final Class DEFAULT_TCP_CLIENT_TYPE; public static final Class DEFAULT_HTTP_SERVER_TYPE; public static final Class DEFAULT_HTTP_CLIENT_TYPE; public static final Class DEFAULT_UDP_SERVER_TYPE; private NetStreams() { } // Marker interfaces to avoid complicated generic dance for Java < 8 Users. public interface TcpServerFactory extends Function, Spec.TcpServerSpec> { } public interface TcpClientFactory extends Function, Spec.TcpClientSpec> { } public interface HttpServerFactory extends Function, Spec.HttpServerSpec> { } public interface HttpClientFactory extends Function, Spec.HttpClientSpec> { } public interface UdpServerFactory extends Function, Spec.DatagramServerSpec> { } // TCP /** * Bind a new TCP server to "loopback" on port {@literal 12012}. By default the default server implementation is * scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer() { return tcpServer(DEFAULT_BIND_ADDRESS); } /** * Bind a new TCP server to "loopback" on the given port. By default the default server implementation is scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpServer} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when server is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param port the port to listen on loopback * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer(int port) { return tcpServer(DEFAULT_BIND_ADDRESS, port); } /** * Bind a new TCP server to the given bind address on port {@literal 12012}. By default the default server * implementation is scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpServer} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when server is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param bindAddress bind address (e.g. "127.0.0.1") to create the server on the default port 12012 * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer(String bindAddress) { return tcpServer(bindAddress, DEFAULT_PORT); } /** * Bind a new TCP server to the given bind address and port. By default the default server implementation is scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpServer} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when server is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param port the port to listen on the passed bind address * @param bindAddress bind address (e.g. "127.0.0.1") to create the server on the passed port * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer(final String bindAddress, final int port) { return tcpServer(new Function, Spec.TcpServerSpec>() { @Override public Spec.TcpServerSpec apply(Spec.TcpServerSpec serverSpec) { if (Environment.alive()) { serverSpec.env(Environment.get()); } return serverSpec.listen(bindAddress, port); } }); } /** * Bind a new TCP server to the specified bind address and port. By default the default server implementation is * scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpServer} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when server is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer( Function, ? extends Spec.TcpServerSpec> configuringFunction ) { return tcpServer(DEFAULT_TCP_SERVER_TYPE, configuringFunction); } /** * Bind a new TCP server to the specified bind address and port. *

* A {@link reactor.io.net.tcp.TcpServer} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when server is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param serverFactory the given implementation class for this peer * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpServer tcpServer( Class serverFactory, Function, ? extends Spec.TcpServerSpec> configuringFunction ) { return configuringFunction.apply(new Spec.TcpServerSpec(serverFactory)).get(); } /** * Bind a new TCP client to the localhost on port 12012. By default the default client implementation is scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient() { return tcpClient(DEFAULT_BIND_ADDRESS); } /** * Bind a new TCP client to the specified connect address and port 12012. By default the default client * implementation is scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param bindAddress the address to connect to on port 12012 * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient(String bindAddress) { return tcpClient(bindAddress, DEFAULT_PORT); } /** * Bind a new TCP client to "loopback" on the the specified port. By default the default client implementation is * scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param port the port to connect to on "loopback" * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient(int port) { return tcpClient(DEFAULT_BIND_ADDRESS, port); } /** * Bind a new TCP client to the specified connect address and port. By default the default client implementation is * scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param bindAddress the address to connect to * @param port the port to connect to * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient(final String bindAddress, final int port) { return tcpClient(new Function, Spec.TcpClientSpec>() { @Override public Spec.TcpClientSpec apply(Spec.TcpClientSpec clientSpec) { if (Environment.alive()) { clientSpec.env(Environment.get()); } return clientSpec.connect(bindAddress, port); } }); } /** * Bind a new TCP client to the specified connect address and port. By default the default client implementation is * scanned * from the classpath on Class init. Support for Netty first and ZeroMQ then is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient( Function, ? extends Spec.TcpClientSpec> configuringFunction ) { return tcpClient(DEFAULT_TCP_CLIENT_TYPE, configuringFunction); } /** * Bind a new TCP client to the specified connect address and port. *

* A {@link reactor.io.net.tcp.TcpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param clientFactory the given implementation class for this peer * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static TcpClient tcpClient( Class clientFactory, Function, ? extends Spec.TcpClientSpec> configuringFunction ) { return configuringFunction.apply(new Spec.TcpClientSpec(clientFactory)).get(); } // HTTP /** * Build a simple Netty HTTP server listening on 127.0.0.1 and 12012 * @return a simple HTTP Server */ public static HttpServer httpServer() { return httpServer(DEFAULT_BIND_ADDRESS); } /** * Build a simple Netty HTTP server listening on 127.0.0.1 and 12012 * * @param bindAddress address to listen for (e.g. 0.0.0.0 or 127.0.0.1) * @return a simple HTTP server */ public static HttpServer httpServer(String bindAddress) { return httpServer(bindAddress, DEFAULT_PORT); } /** * Build a simple Netty HTTP server listening on 127.0.0.1 and the passed port * * @param port the port to listen to * @return a simple HTTP server */ public static HttpServer httpServer(int port) { return httpServer(DEFAULT_BIND_ADDRESS, port); } /** * Build a simple Netty HTTP server listening othe passed bind address and port * * @param bindAddress address to listen for (e.g. 0.0.0.0 or 127.0.0.1) * @param port the port to listen to * @return a simple HTTP server */ public static HttpServer httpServer(final String bindAddress, final int port) { return httpServer(new Function, Spec.HttpServerSpec>() { @Override public Spec.HttpServerSpec apply(Spec.HttpServerSpec serverSpec) { if (Environment.alive()) { serverSpec.env(Environment.get()); } return serverSpec.listen(bindAddress, port); } }); } /** * Build a Netty HTTP Server with the passed factory * * @param configuringFunction a factory to build server configuration (see also {@link HttpServerFactory} * @param incoming data type * @param outgoing data type * @return a Netty HTTP server with the passed factory */ public static HttpServer httpServer( Function, ? extends Spec.HttpServerSpec> configuringFunction ) { return httpServer(DEFAULT_HTTP_SERVER_TYPE, configuringFunction); } /** * @param serverFactory a target implementation server class * @param configuringFunction a factory to build server configuration (see also {@link HttpServerFactory} * @param incoming data type * @param outgoing data type * @return a simple HTTP server */ public static HttpServer httpServer( Class serverFactory, Function, ? extends Spec.HttpServerSpec> configuringFunction ) { return configuringFunction.apply(new Spec.HttpServerSpec(serverFactory)).get(); } /** * @return a simple HTTP client */ public static HttpClient httpClient() { return httpClient(new Function, Spec.HttpClientSpec>() { @Override public Spec.HttpClientSpec apply(Spec.HttpClientSpec clientSpec) { if (Environment.alive()) { clientSpec.env(Environment.get()); } return clientSpec; } }); } /** * Bind a new HTTP client to the specified connect address and port. By default the default server implementation is * scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.http.HttpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will * emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static HttpClient httpClient( Function, ? extends Spec.HttpClientSpec> configuringFunction ) { return httpClient(DEFAULT_HTTP_CLIENT_TYPE, configuringFunction); } /** * Bind a new HTTP client to the specified connect address and port. By default the default server implementation is * scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* A {@link reactor.io.net.http.HttpClient} is a specific kind of {@link org.reactivestreams.Publisher} that will * emit: * - onNext {@link reactor.io.net.ChannelStream} to consume data from * - onComplete when client is shutdown * - onError when any exception (more specifically IO exception) occurs * From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param clientFactory the given implementation class for this peer * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static HttpClient httpClient( Class clientFactory, Function, ? extends Spec.HttpClientSpec> configuringFunction ) { return configuringFunction.apply(new Spec.HttpClientSpec(clientFactory)).get(); } // UDP /** * Bind a new UDP server to the "loopback" address. By default the default server implementation is scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer() { return udpServer(DEFAULT_BIND_ADDRESS); } /** * Bind a new UDP server to the given bind address. By default the default server implementation is scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param bindAddress bind address (e.g. "127.0.0.1") to create the server on the passed port * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer(String bindAddress) { return udpServer(bindAddress, DEFAULT_PORT); } /** * Bind a new UDP server to the "loopback" address and specified port. By default the default server implementation * is scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param port the port to listen on the passed bind address * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer(int port) { return udpServer(DEFAULT_BIND_ADDRESS, port); } /** * Bind a new UDP server to the given bind address and port. By default the default server implementation is scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param port the port to listen on the passed bind address * @param bindAddress bind address (e.g. "127.0.0.1") to create the server on the passed port * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer(final String bindAddress, final int port) { return udpServer(new Function, Spec.DatagramServerSpec>() { @Override public Spec.DatagramServerSpec apply(Spec.DatagramServerSpec serverSpec) { if (Environment.alive()) { serverSpec.env(Environment.get()); } return serverSpec.listen(bindAddress, port); } }); } /** * Bind a new UDP server to the specified bind address and port. By default the default server implementation is * scanned * from the classpath on Class init. Support for Netty is provided as long as the relevant * library dependencies are on the classpath. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer( Function, ? extends Spec.DatagramServerSpec> configuringFunction ) { return udpServer(DEFAULT_UDP_SERVER_TYPE, configuringFunction); } /** * Bind a new UDP server to the specified bind address and port. *

* From the emitted {@link ReactorChannel}, one can decide to add in-channel consumers to read any incoming * data. *

* To reply data on the active connection, {@link ReactorChannel#writeWith} can subscribe to any passed {@link org.reactivestreams.Publisher}. *

* Note that {@link reactor.rx.Stream#getCapacity} will be used to switch on/off a channel in auto-read / flush on * write mode. * If the capacity is Long.MAX_Value, write on flush and auto read will apply. Otherwise, data will be flushed every * capacity batch size and read will pause when capacity number of elements have been dispatched. *

* Emitted channels will run on the same thread they have beem receiving IO events. * Apart from dispatching the write, it is possible to use {@link reactor.rx.Stream#dispatchOn} to process requests * asynchronously. *

* By default the type of emitted data or received data is {@link reactor.io.buffer.Buffer} * * @param serverFactory the given implementation class for this peer * @param configuringFunction a function will apply and return a {@link reactor.io.net.Spec} to customize the peer * @param the given input type received by this peer. Any configured codec decoder must match * this type. * @param the given output type received by this peer. Any configured codec encoder must match * this type. * @return a new Stream of ChannelStream, typically a peer of connections. */ public static DatagramServer udpServer( Class serverFactory, Function, ? extends Spec.DatagramServerSpec> configuringFunction ) { return configuringFunction.apply(new Spec.DatagramServerSpec(serverFactory)).get(); } /** * Utils to read the ChannelStream underlying channel */ @SuppressWarnings("unchecked") public static E delegate(ChannelStream channelStream) { return (E) delegate(channelStream, Object.class); } @SuppressWarnings("unchecked") public static E delegate(ChannelStream channelStream, Class clazz) { Assert.isTrue( clazz.isAssignableFrom(channelStream.delegate().getClass()), "Underlying channel is not of the given type: " + clazz.getName() ); return (E) channelStream.delegate(); } /** * INTERNAL CLASSPATH INIT */ static { boolean hasNetty = false; try { Class.forName("io.netty.channel.Channel"); hasNetty = true; } catch (ClassNotFoundException cnfe) { //IGNORE } if (hasNetty) { DEFAULT_TCP_SERVER_TYPE = NettyTcpServer.class; DEFAULT_TCP_CLIENT_TYPE = NettyTcpClient.class; DEFAULT_UDP_SERVER_TYPE = NettyDatagramServer.class; DEFAULT_HTTP_SERVER_TYPE = NettyHttpServer.class; DEFAULT_HTTP_CLIENT_TYPE = NettyHttpClient.class; } else { boolean hasZMQ = false; DEFAULT_UDP_SERVER_TYPE = null; DEFAULT_HTTP_SERVER_TYPE = null; DEFAULT_HTTP_CLIENT_TYPE = null; try { Class.forName("org.zeromq.ZMQ"); hasZMQ = true; } catch (ClassNotFoundException cnfe) { //IGNORE } if (hasZMQ) { DEFAULT_TCP_SERVER_TYPE = ZeroMQTcpServer.class; DEFAULT_TCP_CLIENT_TYPE = ZeroMQTcpClient.class; } else { DEFAULT_TCP_SERVER_TYPE = null; DEFAULT_TCP_CLIENT_TYPE = null; } } } /** * @return a Specification to configure and supply a Reconnect handler */ static public Spec.IncrementalBackoffReconnect backoffReconnect() { return new Spec.IncrementalBackoffReconnect(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy