More clearly specified TCP/UDP port requirements. Code polish

This commit is contained in:
nathan 2017-11-08 15:53:22 +01:00
parent c33a086465
commit 12c628bcae
6 changed files with 112 additions and 46 deletions

View File

@ -95,21 +95,21 @@ class Client<C extends Connection> extends EndPointClient<C> implements Connecti
*/
@SuppressWarnings("AutoBoxing")
public
Client(final Configuration options) throws InitializationException, SecurityException, IOException {
super(options);
Client(final Configuration config) throws InitializationException, SecurityException, IOException {
super(config);
String threadName = Client.class.getSimpleName();
Logger logger2 = this.logger;
if (options.localChannelName != null && (options.tcpPort > 0 || options.udpPort > 0 || options.host != null) ||
options.localChannelName == null && (options.tcpPort == 0 || options.udpPort == 0 || options.host == null)) {
if (config.localChannelName != null && (config.tcpPort > 0 || config.udpPort > 0 || config.host != null) ||
config.localChannelName == null && (config.tcpPort == 0 || config.udpPort == 0 || config.host == null)) {
String msg = threadName + " Local channel use and TCP/UDP use are MUTUALLY exclusive. Unable to determine intent.";
logger2.error(msg);
throw new IllegalArgumentException(msg);
}
localChannelName = options.localChannelName;
hostName = options.host;
localChannelName = config.localChannelName;
hostName = config.host;
boolean isAndroid = PlatformDependent.isAndroid();
@ -130,33 +130,33 @@ class Client<C extends Connection> extends EndPointClient<C> implements Connecti
manageForShutdown(boss);
if (options.localChannelName != null && options.tcpPort < 0 && options.udpPort < 0) {
if (config.localChannelName != null && config.tcpPort <= 0 && config.udpPort <= 0) {
// no networked bootstraps. LOCAL connection only
Bootstrap localBootstrap = new Bootstrap();
this.bootstraps.add(new BootstrapWrapper("LOCAL", options.localChannelName, -1, localBootstrap));
this.bootstraps.add(new BootstrapWrapper("LOCAL", config.localChannelName, -1, localBootstrap));
EventLoopGroup localBoss = new DefaultEventLoopGroup(DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-LOCAL",
threadGroup));
localBootstrap.group(localBoss)
.channel(LocalChannel.class)
.remoteAddress(new LocalAddress(options.localChannelName))
.remoteAddress(new LocalAddress(config.localChannelName))
.handler(new RegistrationLocalHandlerClient<C>(threadName, registrationWrapper));
manageForShutdown(localBoss);
}
else {
if (options.host == null) {
if (config.host == null) {
throw new IllegalArgumentException("You must define what host you want to connect to.");
}
if (options.tcpPort < 0 && options.udpPort < 0) {
if (config.tcpPort <= 0 && config.udpPort <= 0) {
throw new IllegalArgumentException("You must define what port you want to connect to.");
}
if (options.tcpPort > 0) {
if (config.tcpPort > 0) {
Bootstrap tcpBootstrap = new Bootstrap();
this.bootstraps.add(new BootstrapWrapper("TCP", options.host, options.tcpPort, tcpBootstrap));
this.bootstraps.add(new BootstrapWrapper("TCP", config.host, config.tcpPort, tcpBootstrap));
if (isAndroid) {
// android ONLY supports OIO (not NIO)
@ -173,7 +173,7 @@ class Client<C extends Connection> extends EndPointClient<C> implements Connecti
tcpBootstrap.group(boss)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(WRITE_BUFF_LOW, WRITE_BUFF_HIGH))
.remoteAddress(options.host, options.tcpPort)
.remoteAddress(config.host, config.tcpPort)
.handler(new RegistrationRemoteHandlerClientTCP<C>(threadName,
registrationWrapper,
serializationManager));
@ -184,9 +184,9 @@ class Client<C extends Connection> extends EndPointClient<C> implements Connecti
}
if (options.udpPort > 0) {
if (config.udpPort > 0) {
Bootstrap udpBootstrap = new Bootstrap();
this.bootstraps.add(new BootstrapWrapper("UDP", options.host, options.udpPort, udpBootstrap));
this.bootstraps.add(new BootstrapWrapper("UDP", config.host, config.udpPort, udpBootstrap));
if (isAndroid) {
// android ONLY supports OIO (not NIO)
@ -204,7 +204,7 @@ class Client<C extends Connection> extends EndPointClient<C> implements Connecti
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(WRITE_BUFF_LOW, WRITE_BUFF_HIGH))
.localAddress(new InetSocketAddress(0)) // bind to wildcard
.remoteAddress(new InetSocketAddress(options.host, options.udpPort))
.remoteAddress(new InetSocketAddress(config.host, config.udpPort))
.handler(new RegistrationRemoteHandlerClientUDP<C>(threadName,
registrationWrapper,
serializationManager));

View File

@ -30,15 +30,19 @@ class Configuration {
/**
* Specify the TCP port to use. The server will listen on this port, the client will connect to it.
* <p>
* Must be > 0 to be used
*/
public int tcpPort = -1;
public int tcpPort = 0;
/**
* Specify the UDP port to use. The server will listen on this port, the client will connect to it.
* <p>
* Must be > 0 to be used
* <p>
* UDP requires TCP to handshake
*/
public int udpPort = -1;
public int udpPort = 0;
/**
* Specify the local channel name to use, if the default is not wanted.

View File

@ -16,7 +16,7 @@
package dorkbox.network;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.net.Socket;
import org.slf4j.Logger;
@ -59,6 +59,8 @@ import io.netty.channel.socket.oio.OioServerSocketChannel;
*/
public
class Server<C extends Connection> extends EndPointServer<C> {
/**
* Gets the version number.
*/
@ -84,7 +86,8 @@ class Server<C extends Connection> extends EndPointServer<C> {
private final String localChannelName;
private final String hostName;
private final CountDownLatch blockUntilDone = new CountDownLatch(1);
private volatile boolean isRunning = false;
/**
* Starts a LOCAL <b>only</b> server, with the default serialization scheme.
@ -99,21 +102,21 @@ class Server<C extends Connection> extends EndPointServer<C> {
*/
@SuppressWarnings("AutoBoxing")
public
Server(Configuration options) throws InitializationException, SecurityException, IOException {
Server(Configuration config) throws InitializationException, SecurityException, IOException {
// watch-out for serialization... it can be NULL incoming. The EndPoint (superclass) sets it, if null, so
// you have to make sure to use this.serialization
super(options);
super(config);
tcpPort = options.tcpPort;
udpPort = options.udpPort;
tcpPort = config.tcpPort;
udpPort = config.udpPort;
localChannelName = options.localChannelName;
localChannelName = config.localChannelName;
if (options.host == null) {
if (config.host == null) {
hostName = "0.0.0.0";
}
else {
hostName = options.host;
hostName = config.host;
}
@ -213,7 +216,7 @@ class Server<C extends Connection> extends EndPointServer<C> {
serializationManager));
// have to check options.host for null. we don't bind to 0.0.0.0, we bind to "null" to get the "any" address!
if (options.host != null) {
if (config.host != null) {
tcpBootstrap.localAddress(hostName, tcpPort);
}
else {
@ -351,8 +354,9 @@ class Server<C extends Connection> extends EndPointServer<C> {
future = udpBootstrap.bind();
future.await();
} catch (Exception e) {
String errorMessage = stopWithErrorMessage(logger2, "Could not bind to address " + hostName + " UDP port " +
udpPort + " on the server.",
String errorMessage = stopWithErrorMessage(logger2,
"Could not bind to address " + hostName + " UDP port " + udpPort +
" on the server.",
e);
throw new IllegalArgumentException(errorMessage);
}
@ -369,11 +373,69 @@ class Server<C extends Connection> extends EndPointServer<C> {
manageForShutdown(future);
}
isRunning = true;
// we now BLOCK until the stop method is called.
// if we want to continue running code in the server, bind should be called in a separate, non-daemon thread.
if (blockUntilTerminate) {
waitForShutdown();
}
}
@Override
protected
void stopExtraActions() {
isRunning = false;
}
/**
* @return true if this server has successfully bound to an IP address and is running
*/
public
boolean isRunning() {
return isRunning;
}
/**
* Checks to see if different server (using the specified configuration) is already running. This will check across JVMs by checking the
* network socket directly, and assumes that if the port is in use and answers, then the server is "running". This does not try to
* authenticate or validate the connection.
* <p>
* This does not check local-channels (which are intra-JVM only) or UDP connections.
* </p>
*
* @return true if the configuration matches and can connect (but not verify) to the TCP control socket.
*/
public static
boolean isRunning(Configuration config) {
String host = config.host;
// for us, we want a "null" host to connect to the "any" interface.
if (host == null) {
host = "0.0.0.0";
}
if (config.tcpPort == 0) {
return false;
}
Socket sock = null;
// since we check the socket, if we cannot connect to a socket, then we're done.
try {
sock = new Socket(host, config.tcpPort);
// if we can connect to the socket, it means that we are already running.
return sock.isConnected();
} catch (Exception ignored) {
if (sock != null) {
try {
sock.close();
} catch (IOException ignored2) {
}
}
}
return false;
}
}

View File

@ -115,32 +115,32 @@ class EndPointBase<C extends Connection> extends EndPoint {
/**
* @param type this is either "Client" or "Server", depending on who is creating this endpoint.
* @param options these are the specific connection options
* @param config these are the specific connection options
*
* @throws InitializationException
* @throws SecurityException
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public
EndPointBase(Class<? extends EndPointBase> type, final Configuration options) throws InitializationException, SecurityException, IOException {
EndPointBase(Class<? extends EndPointBase> type, final Configuration config) throws InitializationException, SecurityException, IOException {
super(type);
// make sure that 'localhost' is ALWAYS our specific loopback IP address
if (options.host != null && (options.host.equals("localhost") || options.host.startsWith("127."))) {
if (config.host != null && (config.host.equals("localhost") || config.host.startsWith("127."))) {
// localhost IP might not always be 127.0.0.1
options.host = NetUtil.LOCALHOST.getHostAddress();
config.host = NetUtil.LOCALHOST.getHostAddress();
}
// serialization stuff
if (options.serialization != null) {
this.serializationManager = options.serialization;
if (config.serialization != null) {
this.serializationManager = config.serialization;
} else {
this.serializationManager = CryptoSerializationManager.DEFAULT();
}
// setup our RMI serialization managers. Can only be called once
rmiEnabled = serializationManager.initRmiSerialization();
rmiExecutor = options.rmiExecutor;
rmiExecutor = config.rmiExecutor;
// The registration wrapper permits the registration process to access protected/package fields/methods, that we don't want
@ -153,17 +153,17 @@ class EndPointBase<C extends Connection> extends EndPoint {
// we have to be able to specify WHAT property store we want to use, since it can change!
if (options.settingsStore == null) {
if (config.settingsStore == null) {
this.propertyStore = new PropertyStore();
}
else {
this.propertyStore = options.settingsStore;
this.propertyStore = config.settingsStore;
}
this.propertyStore.init(this.serializationManager, null);
// null it out, since it is sensitive!
options.settingsStore = null;
config.settingsStore = null;
if (!(this.propertyStore instanceof NullSettingsStore)) {
@ -217,7 +217,7 @@ class EndPointBase<C extends Connection> extends EndPoint {
if (this.rmiEnabled) {
// these register the listener for registering a class implementation for RMI (internal use only)
this.connectionManager.add(new RegisterRmiSystemListener());
this.globalRmiBridge = new RmiBridge(logger, options.rmiExecutor, true);
this.globalRmiBridge = new RmiBridge(logger, config.rmiExecutor, true);
}
else {
this.globalRmiBridge = null;

View File

@ -50,8 +50,8 @@ class EndPointClient<C extends Connection> extends EndPointBase<C> implements Ru
public
EndPointClient(Configuration options) throws InitializationException, SecurityException, IOException {
super(Client.class, options);
EndPointClient(Configuration config) throws InitializationException, SecurityException, IOException {
super(Client.class, config);
}
protected

View File

@ -30,8 +30,8 @@ public
class EndPointServer<C extends Connection> extends EndPointBase<C> {
public
EndPointServer(final Configuration options) throws InitializationException, SecurityException, IOException {
super(Server.class, options);
EndPointServer(final Configuration config) throws InitializationException, SecurityException, IOException {
super(Server.class, config);
}
/**