diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfe9aed..3151604 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
#### v0.1.0
-SSL Support for TCP channel
+ * SSL Support for TCP channel (#5, #6)
+ * Optimize network message transport (#4, #11)
+ * Better logging and enhanced test examples (#9)
+ * Better error reporting on non-serializable objects in a message (#14, #16)
+ * Separation of examples and library, and corresponding dependencies (#22)
+ * Fixed issue where messages would be transferred before connection listeners were notified (#20, #21)
+ * Fixed issue where dropped sockets would not be detected (#10, #23)
#### V0.0.0
Initial Release
\ No newline at end of file
diff --git a/README.md b/README.md
index a9be3b3..050b702 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,56 @@
# monkey-netty
![Build](https://github.com/tlf30/monkey-netty/workflows/Java%20CI%20with%20Gradle/badge.svg)
-An implementation of a server-client communication system for jMonkeyEngine using Netty.IO that utilizes both TCP and UDP communication.
-See example for server and client in `examples` module
+An implementation of a server-client communication system for jMonkeyEngine using Netty.IO that utilizes both TCP and UDP communication.
+
+**Checkout our [Wiki](https://github.com/tlf30/monkey-netty/wiki) for getting started.**
+
+**See example for server and client in `examples` module.**
+
+## Installing with Gradle
+In your `build.gradle` you will need to:
+
+1. Include the github repo:
+```groovy
+repositories {
+ ...
+ maven {
+ url = 'https://maven.pkg.github.com/tlf30/monkey-netty'
+ }
+}
+```
+
+2. Specify the dependency:
+```groovy
+dependencies {
+ ...
+ implementation 'io.tlf.monkeynetty:monkey-netty:0.1.0'
+}
+```
+
+## Installing with Maven
+In your pom.xml you will need to:
+
+1. Include the github repo:
+```xml
+
+ ...
+
+ monkey-netty
+ Monkey-Netty GitHub Packages
+ https://maven.pkg.github.com/tlf30/monkey-netty
+
+
+```
+
+2. Specify the dependency:
+```xml
+
+ ...
+
+ io.tlf.monkeynetty
+ monkey-netty
+ 0.1.0
+
+
+```
+
diff --git a/build.gradle b/build.gradle
index ff929ed..e5df123 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
allprojects {
- version = '0.1.0-SNAPSHOT'
+ version = '0.1.0'
group = "io.tlf.monkeynetty"
ext {
diff --git a/examples/src/main/java/io/tlf/monkeynetty/test/JmeClient.java b/examples/src/main/java/io/tlf/monkeynetty/test/JmeClient.java
index 16193ba..4030ae5 100644
--- a/examples/src/main/java/io/tlf/monkeynetty/test/JmeClient.java
+++ b/examples/src/main/java/io/tlf/monkeynetty/test/JmeClient.java
@@ -24,6 +24,7 @@ of this software and associated documentation files (the "Software"), to deal
package io.tlf.monkeynetty.test;
+import io.netty.handler.logging.LogLevel;
import io.tlf.monkeynetty.ConnectionListener;
import io.tlf.monkeynetty.test.messages.TestUDPBigMessageA;
import io.tlf.monkeynetty.test.messages.TestTCPBigMessageA;
@@ -50,8 +51,9 @@ public class JmeClient extends SimpleApplication {
@Override
public void simpleInitApp() {
- client = new NettyClient("test", true, 10000, "localhost");
+ client = new NettyClient("test", true, 10000, "localhost");
stateManager.attach(client);
+ client.setLogLevel(LogLevel.INFO);
client.registerListener(new MessageListener() {
@Override
public void onMessage(NetworkMessage msg, NetworkServer server, NetworkClient client) {
@@ -60,7 +62,7 @@ public void onMessage(NetworkMessage msg, NetworkServer server, NetworkClient cl
@Override
public Class extends NetworkMessage>[] getSupportedMessages() {
- return new Class[] {TestTCPMessage.class, TestUDPMessage.class, TestTCPBigMessageA.class, TestTCPBigMessageB.class, TestUDPBigMessageA.class, TestUDPBigMessageB.class};
+ return new Class[]{TestTCPMessage.class, TestUDPMessage.class, TestTCPBigMessageA.class, TestTCPBigMessageB.class, TestUDPBigMessageA.class, TestUDPBigMessageB.class};
}
});
diff --git a/monkey-netty/build.gradle b/monkey-netty/build.gradle
index 4c0f645..f250fd5 100644
--- a/monkey-netty/build.gradle
+++ b/monkey-netty/build.gradle
@@ -3,6 +3,11 @@ plugins {
id 'maven-publish'
}
+java {
+ withJavadocJar()
+ withSourcesJar()
+}
+
publishing {
repositories {
maven {
@@ -17,6 +22,29 @@ publishing {
publications {
gpr(MavenPublication) {
from(components.java)
+ pom {
+ name = 'Monkey Netty'
+ description = 'A implementation of a server-client communication system for jMonkeyEngine using Netty.IO that utilizes both TCP and UDP communication.'
+ url = 'https://github.com/tlf30/monkey-netty'
+ licenses {
+ license {
+ name = 'MIT License'
+ url = 'https://opensource.org/licenses/MIT'
+ }
+ }
+ developers {
+ developer {
+ id = 'tlf30'
+ name = 'Trevor Flynn'
+ email = 'liquidcrystalstudios@gmail.com'
+ }
+ }
+ scm {
+ connection = 'scm:git:git://github.com/tlf30/monkey-netty.git'
+ developerConnection = 'scm:git:ssh://tlf30/monkey-netty.git'
+ url = 'https://github.com/tlf30/monkey-netty/'
+ }
+ }
}
}
}
diff --git a/monkey-netty/src/main/java/io/tlf/monkeynetty/NetworkServer.java b/monkey-netty/src/main/java/io/tlf/monkeynetty/NetworkServer.java
index 2fb4cc0..9e718b5 100644
--- a/monkey-netty/src/main/java/io/tlf/monkeynetty/NetworkServer.java
+++ b/monkey-netty/src/main/java/io/tlf/monkeynetty/NetworkServer.java
@@ -61,6 +61,35 @@ public interface NetworkServer {
*/
public NetworkProtocol[] getProtocol();
+ /**
+ * @return true if the server is currently blocking new connections
+ */
+ public boolean isBlocking();
+
+ /**
+ * Set if the server should block incoming connections. If true
+ * the server will close all incoming connections immediately without
+ * performing a handshake after establishing the connection.
+ *
+ * @param blocking If the server should block incoming connections.
+ */
+ public void setBlocking(boolean blocking);
+
+ /**
+ * @return The maximum number of connections the server will allow.
+ */
+ public int getMaxConnections();
+
+ /**
+ * This sets the maximum number of connections the server will be allowed to have at any given time.
+ * If a connection is attempted to the server and the server currently has the maximum number of
+ * connections, it will immediately close the connection without performing a handshake after establishing
+ * the connection.
+ *
+ * @param maxConnections The maximum number of connections the server will allow.
+ */
+ public void setMaxConnections(int maxConnections);
+
/**
* Send a message to all clients connected to the server.
*
diff --git a/monkey-netty/src/main/java/io/tlf/monkeynetty/client/NettyClient.java b/monkey-netty/src/main/java/io/tlf/monkeynetty/client/NettyClient.java
index ba353b5..305e105 100644
--- a/monkey-netty/src/main/java/io/tlf/monkeynetty/client/NettyClient.java
+++ b/monkey-netty/src/main/java/io/tlf/monkeynetty/client/NettyClient.java
@@ -99,14 +99,38 @@ public class NettyClient extends BaseAppState implements NetworkClient {
private final Object handlerLock = new Object();
private final LinkedList messageCache = new LinkedList<>();
+ /**
+ * Creates a new client configured to connect to the server.
+ * This connection will have SSL disabled.
+ * @param service The name of the service running on this client
+ * @param port The port the server is listening on
+ * @param server The host/ip of the server
+ */
public NettyClient(String service, int port, String server) {
this(service, false, false, port, server);
}
+ /**
+ * Creates a new client configured to connect to the server.
+ *
+ * @param service The name of the service running on this client
+ * @param ssl If the client should attempt to connect with ssl
+ * @param port The port the server is listening on
+ * @param server The host/ip of the server
+ */
public NettyClient(String service, boolean ssl, int port, String server) {
this(service, ssl, true, port, server);
}
+ /**
+ * Creates a new client configured to connect to the server.
+ *
+ * @param service The name of the service running on this client
+ * @param ssl If the client should attempt to connect with ssl
+ * @param sslSelfSigned If the client will allow the server to use a self signed ssl certificate
+ * @param port The port the server is listening on
+ * @param server The host/ip of the server
+ */
public NettyClient(String service, boolean ssl, boolean sslSelfSigned, int port, String server) {
this.service = service;
this.port = port;
@@ -131,30 +155,68 @@ public void onEnable() {
setupTcp();
}
+ @Override
public void onDisable() {
disconnect();
}
- public int getConnectionTimeout() {
- return connectionTimeout;
- }
-
+ /**
+ * Set the timeout duration in milliseconds for creating a new connection from the client to the server.
+ * This does not effect the read/write timeouts for messages after the connection has been established.
+ * @param connectionTimeout The timeout in milliseconds for creating a new connection.
+ */
public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
+ /**
+ * @return The timeout in milliseconds for creating a new connection
+ */
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
+
+ /**
+ * Sets the Netty.IO internal log level.
+ * This will not change the java.util.logger Logger for Monkey-Netty.
+ * @param logLevel The internal Netty.IO log level
+ */
public void setLogLevel(LogLevel logLevel) {
this.logLevel = logLevel;
}
+ /**
+ * @return The internal Netty.IO log level
+ */
+ public LogLevel getLogLevel() {
+ return logLevel;
+ }
+
+ /**
+ * Sets the message cache mode. By default the mode is MessageCacheMode.ENABLE_TCP
+ * See MessageCacheMode for more information about the supported mode options.
+ * @param mode The desired message cache mode.
+ */
public void setMessageCacheMode(MessageCacheMode mode) {
this.cacheMode = mode;
}
+ /**
+ * @return The current message cache mode.
+ */
public MessageCacheMode getMessageCacheMode() {
return cacheMode;
}
+ /**
+ * Internal use only
+ * Setup the TCP netty.io pipeline.
+ * This will create a dedicated TCP channel to the server.
+ * The pipeline is setup to handle NetworkMessage message types.
+ * The pipeline will also send/receive a ping to/from the server to ensure the connection is still active.
+ * If the connection becomes inactive, the client will attempt a new connection.
+ * The pipeline will be configured with SSL if SSL parameters have been passed to the client.
+ */
private void setupTcp() {
LOGGER.fine("Setting up tcp");
if (ssl) {
@@ -208,6 +270,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
} else {
LOGGER.log(Level.SEVERE, "Received message that was not a NetworkMessage object");
}
+ ctx.fireChannelRead(msg);
}
@Override
@@ -225,14 +288,12 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
new ChannelDuplexHandler() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
- System.out.println("Got event: " + evt.getClass().getName());
if (evt instanceof IdleStateEvent) {
- System.out.println("Got idle state: " + ((IdleStateEvent) evt).state());
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {
handleInactiveConnection();
} else if (e.state() == IdleState.WRITER_IDLE) {
- ctx.writeAndFlush(new PingMessage());
+ send(new PingMessage());
}
}
}
@@ -254,6 +315,13 @@ public void channelInactive(ChannelHandlerContext ctx) {
}
}
+ /**
+ * Internal use onle
+ * Setup the UDP netty.io pipeline.
+ * This will create a dedicated UDP channel to the server.
+ * The pipeline is setup to handle NetworkMessage message types.
+ * @param hash The hash that will be used to establish the UDP channel with the server.
+ */
private void setupUdp(String hash) {
LOGGER.fine("Setting up udp");
udpGroup = new NioEventLoopGroup();
@@ -278,13 +346,17 @@ protected void initChannel(DatagramChannel socketChannel) {
new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object netObj) {
- AddressedEnvelope