From e5fc2cef87a6f44366a232d9d0aff8432919fa75 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 29 Nov 2013 14:34:06 -0800 Subject: [PATCH 001/180] Initial commit --- .gitignore | 8 + LICENSE.txt | 7 + README.md | 26 +++ pom.xml | 115 ++++++++++++ .../java/ch/spacebase/packetlib/Client.java | 64 +++++++ .../packetlib/ConnectionListener.java | 39 +++++ .../java/ch/spacebase/packetlib/Server.java | 164 ++++++++++++++++++ .../java/ch/spacebase/packetlib/Session.java | 75 ++++++++ .../spacebase/packetlib/SessionFactory.java | 22 +++ .../packetlib/event/server/ServerAdapter.java | 28 +++ .../event/server/ServerBoundEvent.java | 29 ++++ .../event/server/ServerClosedEvent.java | 29 ++++ .../event/server/ServerClosingEvent.java | 29 ++++ .../packetlib/event/server/ServerEvent.java | 14 ++ .../event/server/ServerListener.java | 38 ++++ .../event/server/SessionAddedEvent.java | 40 +++++ .../event/server/SessionRemovedEvent.java | 40 +++++ .../event/session/ConnectedEvent.java | 29 ++++ .../event/session/DisconnectedEvent.java | 39 +++++ .../event/session/DisconnectingEvent.java | 39 +++++ .../event/session/PacketReceivedEvent.java | 40 +++++ .../event/session/PacketSentEvent.java | 40 +++++ .../event/session/SessionAdapter.java | 28 +++ .../packetlib/event/session/SessionEvent.java | 14 ++ .../event/session/SessionListener.java | 38 ++++ .../netty/NettyConnectionListener.java | 57 ++++++ .../packetlib/netty/NettyServerSession.java | 23 +++ .../packetlib/netty/NettySession.java | 145 ++++++++++++++++ .../packetlib/netty/NettySessionFactory.java | 61 +++++++ .../packetlib/netty/PacketCodec.java | 53 ++++++ .../ch/spacebase/packetlib/packet/Packet.java | 34 ++++ .../packetlib/packet/PacketProtocol.java | 94 ++++++++++ .../packetlib/test/ClientSessionListener.java | 38 ++++ .../spacebase/packetlib/test/PingPacket.java | 42 +++++ .../packetlib/test/PingServerTest.java | 14 ++ .../packetlib/test/ServerListener.java | 32 ++++ .../packetlib/test/ServerSessionListener.java | 28 +++ .../packetlib/test/TestProtocol.java | 29 ++++ 38 files changed, 1684 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/ch/spacebase/packetlib/Client.java create mode 100644 src/main/java/ch/spacebase/packetlib/ConnectionListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/Server.java create mode 100644 src/main/java/ch/spacebase/packetlib/Session.java create mode 100644 src/main/java/ch/spacebase/packetlib/SessionFactory.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java create mode 100644 src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java create mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettySession.java create mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java create mode 100644 src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java create mode 100644 src/main/java/ch/spacebase/packetlib/packet/Packet.java create mode 100644 src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/PingPacket.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/PingServerTest.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/ServerListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java create mode 100644 src/main/java/ch/spacebase/packetlib/test/TestProtocol.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6ca7485c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +bin +lib +.settings +.classpath +.project +.git +target + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..ff34e2af --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright (C) 2013 Steveice10 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..ddcc6348 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +

PacketLib

+========== + + +About PacketLib +-------- + +PacketLib is a library for networking between clients and servers with packets. It was made as a basis for other projects involving packet networking. + + +Test Example +-------- + +See ch.spacebase.packetlib.test.PingServerTest + + +Building the Source +-------- + +PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. + + +License +--------- + +PacketLib is licensed under the [MIT license](http://www.opensource.org/licenses/mit-license.html). diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..6e4def15 --- /dev/null +++ b/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + ch.spacebase + packetlib + 1.0-SNAPSHOT + jar + + PacketLib + A library for networking between a client and a server with packets. + http://github.com/Steveice10/PacketLib/ + + + + MIT + http://www.opensource.org/licenses/mit-license.html + repo + + + + + scm:git:git@github.com:Steveice10/PacketLib.git + scm:git:git@github.com:Steveice10/PacketLib.git + git@github.com:Steveice10/PacketLib/ + + + + + spacebase + spacebase-releases + http://repo.spacebase.ch/content/repositories/release/ + + + spacebase + spacebase-snapshots + http://repo.spacebase.ch/content/repositories/snapshots/ + + + + + + steveice10 + Steveice10 + Steveice10@gmail.com + + + + + UTF-8 + + + + + spacebase-releases + http://repo.spacebase.ch/content/repositories/release/ + + + spacebase-snapshots + http://repo.spacebase.ch/content/repositories/snapshots/ + + + + + + io.netty + netty-all + 5.0.0.Alpha1 + + + + + clean install + ${basedir}/src/main/java + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.5 + + + package + + shade + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + diff --git a/src/main/java/ch/spacebase/packetlib/Client.java b/src/main/java/ch/spacebase/packetlib/Client.java new file mode 100644 index 00000000..9cdae8a4 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/Client.java @@ -0,0 +1,64 @@ +package ch.spacebase.packetlib; + +import ch.spacebase.packetlib.packet.PacketProtocol; + +/** + * A client that may connect to a server. + */ +public class Client { + + private String host; + private int port; + private PacketProtocol protocol; + private SessionFactory factory; + private Session session; + + public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.factory = factory; + } + + /** + * Connects the client. + * @return This client after being connected. + */ + public Client connect() { + this.session = this.factory.createClientSession(this); + return this; + } + + /** + * Gets the host the client is connecting to. + * @return The host the client is connecting to. + */ + public String getHost() { + return this.host; + } + + /** + * Gets the port the client is connecting to. + * @return The port the client is connecting to. + */ + public int getPort() { + return this.port; + } + + /** + * Gets the packet protocol of the client. + * @return The client's packet protocol. + */ + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + + /** + * Gets the session of the client. + * @return The client's session. + */ + public Session getSession() { + return this.session; + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/ConnectionListener.java b/src/main/java/ch/spacebase/packetlib/ConnectionListener.java new file mode 100644 index 00000000..d7c6d6de --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/ConnectionListener.java @@ -0,0 +1,39 @@ +package ch.spacebase.packetlib; + +import ch.spacebase.packetlib.packet.PacketProtocol; + +/** + * A listener for new sessions on a host and port. + */ +public interface ConnectionListener { + + /** + * Gets the host the session is listening on. + * @return The listening host. + */ + public String getHost(); + + /** + * Gets the port the session is listening on. + * @return The listening port. + */ + public int getPort(); + + /** + * Gets the packet protocol of the listener. + * @return The listener's packet protocol. + */ + public PacketProtocol getPacketProtocol(); + + /** + * Returns true if the listener is listening. + * @return True if the listener is listening. + */ + public boolean isListening(); + + /** + * Closes the listener. + */ + public void close(); + +} diff --git a/src/main/java/ch/spacebase/packetlib/Server.java b/src/main/java/ch/spacebase/packetlib/Server.java new file mode 100644 index 00000000..721dbd36 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/Server.java @@ -0,0 +1,164 @@ +package ch.spacebase.packetlib; + +import java.util.ArrayList; +import java.util.List; + +import ch.spacebase.packetlib.event.server.ServerBoundEvent; +import ch.spacebase.packetlib.event.server.ServerClosedEvent; +import ch.spacebase.packetlib.event.server.ServerClosingEvent; +import ch.spacebase.packetlib.event.server.ServerEvent; +import ch.spacebase.packetlib.event.server.ServerListener; +import ch.spacebase.packetlib.event.server.SessionAddedEvent; +import ch.spacebase.packetlib.event.server.SessionRemovedEvent; +import ch.spacebase.packetlib.packet.PacketProtocol; + +/** + * A server that listens on a given host and port. + */ +public class Server { + + private String host; + private int port; + private PacketProtocol protocol; + private SessionFactory factory; + private ConnectionListener listener; + private List sessions = new ArrayList(); + + private List listeners = new ArrayList(); + + public Server(String host, int port, PacketProtocol protocol, SessionFactory factory) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.factory = factory; + this.protocol.newServer(this); + } + + /** + * Binds and initializes the server. + * @return The server after being bound. + */ + public Server bind() { + this.listener = this.factory.createServerListener(this); + this.callEvent(new ServerBoundEvent(this)); + return this; + } + + /** + * Gets the host this server is bound to. + * @return The server's host. + */ + public String getHost() { + return this.host; + } + + /** + * Gets the port this server is bound to. + * @return The server's port. + */ + public int getPort() { + return this.port; + } + + /** + * Gets the listeners listening on this session. + * @return This session's listeners. + */ + public List getListeners() { + return new ArrayList(this.listeners); + } + + /** + * Adds a listener to this session. + * @param listener Listener to add. + */ + public void addListener(ServerListener listener) { + this.listeners.add(listener); + } + + /** + * Removes a listener from this session. + * @param listener Listener to remove. + */ + public void removeListener(ServerListener listener) { + this.listeners.remove(listener); + } + + /** + * Calls an event on the listeners of this session. + * @param event Event to call. + */ + public void callEvent(ServerEvent event) { + for(ServerListener listener : this.listeners) { + event.call(listener); + } + } + + /** + * Gets the packet protocol of the server. + * @return The server's packet protocol. + */ + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + + /** + * Gets all sessions belonging to this server. + * @return Sessions belonging to this server. + */ + public List getSessions() { + return new ArrayList(this.sessions); + } + + /** + * Adds the given session to this server. + * @param session Session to add. + */ + public void addSession(Session session) { + this.sessions.add(session); + this.callEvent(new SessionAddedEvent(this, session)); + } + + /** + * Removes the given session from this server. + * @param session Session to remove. + */ + public void removeSession(Session session) { + this.sessions.remove(session); + if(session.isConnected()) { + session.disconnect("Connection closed."); + } + + this.callEvent(new SessionRemovedEvent(this, session)); + } + + /** + * Gets whether the server is listening. + * @return Whether the server is listening. + */ + public boolean isListening() { + return this.listener.isListening(); + } + + /** + * Closes the server. + */ + public void close() { + // Close server in a separate thread to prevent stalling from closing a server inside an event or packet handling. + new Thread(new Runnable() { + @Override + public void run() { + callEvent(new ServerClosingEvent(Server.this)); + for(Session session : getSessions()) { + if(session.isConnected()) { + session.disconnect("Server closed."); + } + } + + listener.close(); + callEvent(new ServerClosedEvent(Server.this)); + } + }, "CloseServer").start(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/Session.java b/src/main/java/ch/spacebase/packetlib/Session.java new file mode 100644 index 00000000..1c2bc8ba --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/Session.java @@ -0,0 +1,75 @@ +package ch.spacebase.packetlib; + +import java.util.List; + +import ch.spacebase.packetlib.event.session.SessionEvent; +import ch.spacebase.packetlib.event.session.SessionListener; +import ch.spacebase.packetlib.packet.Packet; +import ch.spacebase.packetlib.packet.PacketProtocol; + +/** + * A network session. + */ +public interface Session { + + /** + * Gets the host the session is connected to. + * @return The connected host. + */ + public String getHost(); + + /** + * Gets the port the session is connected to. + * @return The connected port. + */ + public int getPort(); + + /** + * Gets the packet protocol of the session. + * @return The session's packet protocol. + */ + public PacketProtocol getPacketProtocol(); + + /** + * Gets the listeners listening on this session. + * @return This session's listeners. + */ + public List getListeners(); + + /** + * Adds a listener to this session. + * @param listener Listener to add. + */ + public void addListener(SessionListener listener); + + /** + * Removes a listener from this session. + * @param listener Listener to remove. + */ + public void removeListener(SessionListener listener); + + /** + * Calls an event on the listeners of this session. + * @param event Event to call. + */ + public void callEvent(SessionEvent event); + + /** + * Returns true if the session is connected. + * @return True if the session is connected. + */ + public boolean isConnected(); + + /** + * Sends a packet. + * @param packet Packet to send. + */ + public void send(Packet packet); + + /** + * Disconnects the session. + * @param reason Reason for disconnecting. + */ + public void disconnect(String reason); + +} diff --git a/src/main/java/ch/spacebase/packetlib/SessionFactory.java b/src/main/java/ch/spacebase/packetlib/SessionFactory.java new file mode 100644 index 00000000..ce5ad827 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/SessionFactory.java @@ -0,0 +1,22 @@ +package ch.spacebase.packetlib; + +/** + * A factory for creating sessions. + */ +public interface SessionFactory { + + /** + * Creates a client session. + * @param host Host to connect to. + * @param port Port to connect to. + * @return The created session. + */ + public Session createClientSession(Client client); + + /** + * Initializes the factory for creating server sessions. + * @param server Server to initialize for. + */ + public ConnectionListener createServerListener(Server server); + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java new file mode 100644 index 00000000..e6d2d67f --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java @@ -0,0 +1,28 @@ +package ch.spacebase.packetlib.event.server; + +/** + * An adapter for picking server events to listen for. + */ +public class ServerAdapter implements ServerListener { + + @Override + public void serverBound(ServerBoundEvent event) { + } + + @Override + public void serverClosing(ServerClosingEvent event) { + } + + @Override + public void serverClosed(ServerClosedEvent event) { + } + + @Override + public void sessionAdded(SessionAddedEvent event) { + } + + @Override + public void sessionRemoved(SessionRemovedEvent event) { + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java new file mode 100644 index 00000000..d2a6e043 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java @@ -0,0 +1,29 @@ +package ch.spacebase.packetlib.event.server; + +import ch.spacebase.packetlib.Server; + +/** + * Called when the server is bound to its host and port. + */ +public class ServerBoundEvent implements ServerEvent { + + private Server server; + + public ServerBoundEvent(Server server) { + this.server = server; + } + + /** + * Gets the server involved in this event. + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + + @Override + public void call(ServerListener listener) { + listener.serverBound(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java new file mode 100644 index 00000000..445d8234 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java @@ -0,0 +1,29 @@ +package ch.spacebase.packetlib.event.server; + +import ch.spacebase.packetlib.Server; + +/** + * Called when the server is closed. + */ +public class ServerClosedEvent implements ServerEvent { + + private Server server; + + public ServerClosedEvent(Server server) { + this.server = server; + } + + /** + * Gets the server involved in this event. + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + + @Override + public void call(ServerListener listener) { + listener.serverClosed(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java new file mode 100644 index 00000000..44734d08 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java @@ -0,0 +1,29 @@ +package ch.spacebase.packetlib.event.server; + +import ch.spacebase.packetlib.Server; + +/** + * Called when the server is about to close. + */ +public class ServerClosingEvent implements ServerEvent { + + private Server server; + + public ServerClosingEvent(Server server) { + this.server = server; + } + + /** + * Gets the server involved in this event. + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + + @Override + public void call(ServerListener listener) { + listener.serverClosing(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java new file mode 100644 index 00000000..e926c54e --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java @@ -0,0 +1,14 @@ +package ch.spacebase.packetlib.event.server; + +/** + * An event relating to servers. + */ +public interface ServerEvent { + + /** + * Calls the event. + * @param listener Listener to call the event on. + */ + public void call(ServerListener listener); + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java b/src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java new file mode 100644 index 00000000..139f8a03 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java @@ -0,0 +1,38 @@ +package ch.spacebase.packetlib.event.server; + +/** + * A listener for listening to server events. + */ +public interface ServerListener { + + /** + * Called when a server is bound to its host and port. + * @param event Data relating to the event. + */ + public void serverBound(ServerBoundEvent event); + + /** + * Called when a server is about to close. + * @param event Data relating to the event. + */ + public void serverClosing(ServerClosingEvent event); + + /** + * Called when a server is closed. + * @param event Data relating to the event. + */ + public void serverClosed(ServerClosedEvent event); + + /** + * Called when a session is added to the server. + * @param event Data relating to the event. + */ + public void sessionAdded(SessionAddedEvent event); + + /** + * Called when a session is removed and disconnected from the server. + * @param event Data relating to the event. + */ + public void sessionRemoved(SessionRemovedEvent event); + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java new file mode 100644 index 00000000..9e1b405e --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java @@ -0,0 +1,40 @@ +package ch.spacebase.packetlib.event.server; + +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.Session; + +/** + * Called when a session is added to the server. + */ +public class SessionAddedEvent implements ServerEvent { + + private Server server; + private Session session; + + public SessionAddedEvent(Server server, Session session) { + this.server = server; + this.session = session; + } + + /** + * Gets the server involved in this event. + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + @Override + public void call(ServerListener listener) { + listener.sessionAdded(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java b/src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java new file mode 100644 index 00000000..186c09ac --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java @@ -0,0 +1,40 @@ +package ch.spacebase.packetlib.event.server; + +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.Session; + +/** + * Called when a session is removed and disconnected from the server. + */ +public class SessionRemovedEvent implements ServerEvent { + + private Server server; + private Session session; + + public SessionRemovedEvent(Server server, Session session) { + this.server = server; + this.session = session; + } + + /** + * Gets the server involved in this event. + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + @Override + public void call(ServerListener listener) { + listener.sessionRemoved(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java new file mode 100644 index 00000000..65d3bea6 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java @@ -0,0 +1,29 @@ +package ch.spacebase.packetlib.event.session; + +import ch.spacebase.packetlib.Session; + +/** + * Called when the session connects. + */ +public class ConnectedEvent implements SessionEvent { + + private Session session; + + public ConnectedEvent(Session session) { + this.session = session; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + @Override + public void call(SessionListener listener) { + listener.connected(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java new file mode 100644 index 00000000..f72794e2 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java @@ -0,0 +1,39 @@ +package ch.spacebase.packetlib.event.session; + +import ch.spacebase.packetlib.Session; + +/** + * Called when the session is disconnected. + */ +public class DisconnectedEvent implements SessionEvent { + + private Session session; + private String reason; + + public DisconnectedEvent(Session session, String reason) { + this.session = session; + this.reason = reason; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the reason given for the session disconnecting. + * @return The event's reason. + */ + public String getReason() { + return this.reason; + } + + @Override + public void call(SessionListener listener) { + listener.disconnected(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java new file mode 100644 index 00000000..5ec3cf69 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java @@ -0,0 +1,39 @@ +package ch.spacebase.packetlib.event.session; + +import ch.spacebase.packetlib.Session; + +/** + * Called when the session is about to disconnect. + */ +public class DisconnectingEvent implements SessionEvent { + + private Session session; + private String reason; + + public DisconnectingEvent(Session session, String reason) { + this.session = session; + this.reason = reason; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the reason given for the session disconnecting. + * @return The event's reason. + */ + public String getReason() { + return this.reason; + } + + @Override + public void call(SessionListener listener) { + listener.disconnecting(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java new file mode 100644 index 00000000..15ed4fb1 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java @@ -0,0 +1,40 @@ +package ch.spacebase.packetlib.event.session; + +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.packet.Packet; + +/** + * Called when the session receives a packet. + */ +public class PacketReceivedEvent implements SessionEvent { + + private Session session; + private Packet packet; + + public PacketReceivedEvent(Session session, Packet packet) { + this.session = session; + this.packet = packet; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the packet involved in this event. + * @return The event's packet. + */ + public Packet getPacket() { + return this.packet; + } + + @Override + public void call(SessionListener listener) { + listener.packetReceived(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java new file mode 100644 index 00000000..2b717e32 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java @@ -0,0 +1,40 @@ +package ch.spacebase.packetlib.event.session; + +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.packet.Packet; + +/** + * Called when the session has sent a packet. + */ +public class PacketSentEvent implements SessionEvent { + + private Session session; + private Packet packet; + + public PacketSentEvent(Session session, Packet packet) { + this.session = session; + this.packet = packet; + } + + /** + * Gets the session involved in this event. + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the packet involved in this event. + * @return The event's packet. + */ + public Packet getPacket() { + return this.packet; + } + + @Override + public void call(SessionListener listener) { + listener.packetSent(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java b/src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java new file mode 100644 index 00000000..70bb508d --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java @@ -0,0 +1,28 @@ +package ch.spacebase.packetlib.event.session; + +/** + * An adapter for picking session events to listen for. + */ +public class SessionAdapter implements SessionListener { + + @Override + public void packetReceived(PacketReceivedEvent event) { + } + + @Override + public void packetSent(PacketSentEvent event) { + } + + @Override + public void connected(ConnectedEvent event) { + } + + @Override + public void disconnecting(DisconnectingEvent event) { + } + + @Override + public void disconnected(DisconnectedEvent event) { + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java new file mode 100644 index 00000000..7af4d048 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java @@ -0,0 +1,14 @@ +package ch.spacebase.packetlib.event.session; + +/** + * An event relating to sessions. + */ +public interface SessionEvent { + + /** + * Calls the event. + * @param listener Listener to call the event on. + */ + public void call(SessionListener listener); + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java b/src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java new file mode 100644 index 00000000..7353be9d --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java @@ -0,0 +1,38 @@ +package ch.spacebase.packetlib.event.session; + +/** + * A listener for listening to session events. + */ +public interface SessionListener { + + /** + * Called when a session receives a packet. + * @param event Data relating to the event. + */ + public void packetReceived(PacketReceivedEvent event); + + /** + * Called when a session sends a packet. + * @param event Data relating to the event. + */ + public void packetSent(PacketSentEvent event); + + /** + * Called when a session connects. + * @param event Data relating to the event. + */ + public void connected(ConnectedEvent event); + + /** + * Called when a session is about to disconnect. + * @param event Data relating to the event. + */ + public void disconnecting(DisconnectingEvent event); + + /** + * Called when a session is disconnected. + * @param event Data relating to the event. + */ + public void disconnected(DisconnectedEvent event); + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java b/src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java new file mode 100644 index 00000000..ca66902d --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java @@ -0,0 +1,57 @@ +package ch.spacebase.packetlib.netty; + +import ch.spacebase.packetlib.ConnectionListener; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; + +public class NettyConnectionListener implements ConnectionListener { + + private String host; + private int port; + private PacketProtocol protocol; + private EventLoopGroup group; + private Channel channel; + + public NettyConnectionListener(String host, int port, PacketProtocol protocol, EventLoopGroup group, Channel channel) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.group = group; + this.channel = channel; + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public int getPort() { + return this.port; + } + + @Override + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + + @Override + public boolean isListening() { + return this.channel.isOpen(); + } + + @Override + public void close() { + if(this.channel.isOpen()) { + this.channel.close().syncUninterruptibly(); + } + + try { + this.group.shutdownGracefully().sync(); + } catch(InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java b/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java new file mode 100644 index 00000000..867aa6fc --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java @@ -0,0 +1,23 @@ +package ch.spacebase.packetlib.netty; + +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; + +public class NettyServerSession extends NettySession { + + private Server server; + + public NettyServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Server server) { + super(host, port, protocol, group); + this.server = server; + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + this.server.removeSession(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettySession.java b/src/main/java/ch/spacebase/packetlib/netty/NettySession.java new file mode 100644 index 00000000..abc0fcf7 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/netty/NettySession.java @@ -0,0 +1,145 @@ +package ch.spacebase.packetlib.netty; + +import java.util.ArrayList; +import java.util.List; + +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.event.session.ConnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectingEvent; +import ch.spacebase.packetlib.event.session.PacketReceivedEvent; +import ch.spacebase.packetlib.event.session.PacketSentEvent; +import ch.spacebase.packetlib.event.session.SessionEvent; +import ch.spacebase.packetlib.event.session.SessionListener; +import ch.spacebase.packetlib.packet.Packet; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; + +public class NettySession extends SimpleChannelInboundHandler implements Session { + + private String host; + private int port; + private PacketProtocol protocol; + private EventLoopGroup group; + private Channel channel; + private boolean disconnected; + + private List listeners = new ArrayList(); + + public NettySession(String host, int port, PacketProtocol protocol, EventLoopGroup group) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.group = group; + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public int getPort() { + return this.port; + } + + @Override + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + + @Override + public List getListeners() { + return new ArrayList(this.listeners); + } + + @Override + public void addListener(SessionListener listener) { + this.listeners.add(listener); + } + + @Override + public void removeListener(SessionListener listener) { + this.listeners.remove(listener); + } + + @Override + public void callEvent(SessionEvent event) { + for(SessionListener listener : this.listeners) { + event.call(listener); + } + } + + @Override + public boolean isConnected() { + return this.channel != null && this.channel.isOpen(); + } + + @Override + public void send(Packet packet) { + if(this.channel == null) { + return; + } + + this.channel.writeAndFlush(packet); + this.callEvent(new PacketSentEvent(this, packet)); + } + + @Override + public void disconnect(String reason) { + if(reason == null) { + reason = "Connection closed."; + } + + if(this.channel != null) { + this.callEvent(new DisconnectingEvent(this, reason)); + this.channel.close().syncUninterruptibly(); + this.callEvent(new DisconnectedEvent(this, reason)); + } + + if(this.group != null) { + this.group.shutdownGracefully(); + } + + this.disconnected = true; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + if(this.disconnected) { + ctx.channel().close().syncUninterruptibly(); + return; + } + + this.channel = ctx.channel(); + this.callEvent(new ConnectedEvent(this)); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + if(!this.disconnected) { + this.disconnect("Connection closed."); + } + + this.channel = null; + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if(!this.disconnected) { + this.disconnect("Internal exception: " + cause); + this.channel = null; + System.err.println("Networking exception occured: " + cause); + cause.printStackTrace(); + } + } + + @Override + protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { + this.callEvent(new PacketReceivedEvent(this, packet)); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java b/src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java new file mode 100644 index 00000000..85bf0350 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java @@ -0,0 +1,61 @@ +package ch.spacebase.packetlib.netty; + +import java.net.InetSocketAddress; + +import ch.spacebase.packetlib.Client; +import ch.spacebase.packetlib.ConnectionListener; +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.SessionFactory; +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; + +public class NettySessionFactory implements SessionFactory { + + @Override + public Session createClientSession(final Client client) { + final EventLoopGroup group = new NioEventLoopGroup(); + return (NettySession) new Bootstrap().channel(NioSocketChannel.class).handler(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + NettySession session = new NettySession(client.getHost(), client.getPort(), client.getPacketProtocol(), group); + session.getPacketProtocol().newClientSession(client, session); + ch.config().setOption(ChannelOption.IP_TOS, 0x18); + ch.config().setOption(ChannelOption.TCP_NODELAY, false); + ch.pipeline() + .addLast("timer", new ReadTimeoutHandler(30)) + .addLast("codec", new PacketCodec(client.getPacketProtocol())) + .addLast("manager", session); + } + }).group(group).remoteAddress(client.getHost(), client.getPort()).connect().syncUninterruptibly().channel().pipeline().get("manager"); + } + + @Override + public ConnectionListener createServerListener(final Server server) { + final EventLoopGroup group = new NioEventLoopGroup(); + return new NettyConnectionListener(server.getHost(), server.getPort(), server.getPacketProtocol(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); + NettySession session = new NettyServerSession(address.getHostName(), address.getPort(), server.getPacketProtocol(), null, server); + session.getPacketProtocol().newServerSession(server, session); + ch.config().setOption(ChannelOption.IP_TOS, 0x18); + ch.config().setOption(ChannelOption.TCP_NODELAY, false); + ch.pipeline() + .addLast("timer", new ReadTimeoutHandler(30)) + .addLast("codec", new PacketCodec(server.getPacketProtocol())) + .addLast("manager", session); + server.addSession(session); + } + }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java b/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java new file mode 100644 index 00000000..c1097fd2 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java @@ -0,0 +1,53 @@ +package ch.spacebase.packetlib.netty; + +import java.nio.ByteBuffer; +import java.util.List; + +import ch.spacebase.packetlib.packet.Packet; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; + +public class PacketCodec extends ByteToMessageCodec { + + private PacketProtocol protocol; + + public PacketCodec(PacketProtocol protocol) { + this.protocol = protocol; + } + + @Override + public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { + try { + ByteBuffer out = ByteBuffer.allocate(packet.getLength() + 1); + out.put((byte) (packet.getId() & 0xFF)); + packet.write(out); + out.flip(); + buf.writeBytes(this.protocol.encode(out.array())); + } catch(Throwable t) { + t.printStackTrace(); + } + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + try { + byte array[] = new byte[buf.readableBytes()]; + for(int index = 0; index < array.length; index++) { + array[index] = buf.readByte(); + } + + ByteBuffer in = ByteBuffer.allocate(buf.capacity()).put(this.protocol.decode(array)); + in.flip(); + + int id = in.get() & 0xFF; + Packet packet = this.protocol.createPacket(id); + packet.read(in); + out.add(packet); + } catch(Throwable t) { + t.printStackTrace(); + } + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/packet/Packet.java b/src/main/java/ch/spacebase/packetlib/packet/Packet.java new file mode 100644 index 00000000..45b5b31e --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/packet/Packet.java @@ -0,0 +1,34 @@ +package ch.spacebase.packetlib.packet; + +import java.nio.ByteBuffer; + +/** + * A network packet. + */ +public interface Packet { + + /** + * Gets the id of the packet. + * @return The packet's id. + */ + public int getId(); + + /** + * Gets the length of the packet. + * @return The packet's length. + */ + public int getLength(); + + /** + * Reads the packet from the given input buffer. + * @param in The buffer to read from. + */ + public void read(ByteBuffer in); + + /** + * Writes the packet to the given output buffer. + * @param in The buffer to write to. + */ + public void write(ByteBuffer out); + +} diff --git a/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java b/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java new file mode 100644 index 00000000..7bb01de9 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java @@ -0,0 +1,94 @@ +package ch.spacebase.packetlib.packet; + +import ch.spacebase.packetlib.Client; +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.Session; + +/** + * A protocol for packet sending and receiving. + */ +public abstract class PacketProtocol { + + @SuppressWarnings("unchecked") + private final Class registry[] = (Class[]) new Class[256]; + + /** + * Called when a client is created with this protocol. + * @param client The client that the session belongs to. + * @param session The created session. + */ + public abstract void newClientSession(Client client, Session session); + + /** + * Called when a server is created with this protocol. + * @param server The created server. + */ + public abstract void newServer(Server server); + + /** + * Called when a server's session is created with this protocol. + * @param server The server that the session belongs to. + * @param session The created session. + */ + public abstract void newServerSession(Server server, Session session); + + /** + * Decodes the given data array into readable form. + * @param data Data to decode. + * @return The decoded data. + */ + public byte[] decode(byte data[]) { + return data; + } + + /** + * Encodes the given data array for sending over the network. + * @param data Data to encode. + * @return The encoded data. + */ + public byte[] encode(byte data[]) { + return data; + } + + /** + * Registers a packet to this protocol. + * @param packet Packet to register. + */ + public final void register(Class packet) { + int id = 0; + try { + id = packet.getDeclaredConstructor().newInstance().getId(); + } catch(NoSuchMethodError e) { + System.err.println("Packet \"" + packet.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + System.err.println("Failed to instantiate packet " + packet.getName() + " to get id."); + e.printStackTrace(); + } + + registry[id] = packet; + } + + /** + * Creates a new instance of the packet with the given id. + * @param id Id of the packet to create, or null if it could not be created. + * @return The created packet + * @throws IllegalArgumentException If the packet ID is invalid. + */ + public final Packet createPacket(int id) { + if(id < 0 || id >= registry.length || registry[id] == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + try { + return registry[id].getDeclaredConstructor().newInstance(); + } catch(NoSuchMethodError e) { + System.err.println("Packet \"" + id + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + System.err.println("Failed to instantiate packet " + id + "."); + e.printStackTrace(); + } + + return null; + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java b/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java new file mode 100644 index 00000000..ca930f38 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java @@ -0,0 +1,38 @@ +package ch.spacebase.packetlib.test; + +import ch.spacebase.packetlib.event.session.ConnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectingEvent; +import ch.spacebase.packetlib.event.session.PacketReceivedEvent; +import ch.spacebase.packetlib.event.session.SessionAdapter; + +public class ClientSessionListener extends SessionAdapter { + + @Override + public void packetReceived(PacketReceivedEvent event) { + if(event.getPacket() instanceof PingPacket) { + PingPacket packet = (PingPacket) event.getPacket(); + System.out.println("CLIENT RECV: " + packet.getPingId()); + if(packet.getPingId() == 2345) { + event.getSession().disconnect("Finished"); + } + } + } + + @Override + public void connected(ConnectedEvent event) { + event.getSession().send(new PingPacket(1043)); + event.getSession().send(new PingPacket(2345)); + } + + @Override + public void disconnecting(DisconnectingEvent event) { + System.out.println("CLIENT Disconnecting: " + event.getReason()); + } + + @Override + public void disconnected(DisconnectedEvent event) { + System.out.println("CLIENT Disconnected: " + event.getReason()); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/PingPacket.java b/src/main/java/ch/spacebase/packetlib/test/PingPacket.java new file mode 100644 index 00000000..762f5a2d --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/PingPacket.java @@ -0,0 +1,42 @@ +package ch.spacebase.packetlib.test; + +import java.nio.ByteBuffer; + +import ch.spacebase.packetlib.packet.Packet; + +public class PingPacket implements Packet { + + private int id; + + public PingPacket() { + } + + public PingPacket(int id) { + this.id = id; + } + + public int getPingId() { + return this.id; + } + + @Override + public int getId() { + return 0; + } + + @Override + public int getLength() { + return 4; + } + + @Override + public void read(ByteBuffer in) { + this.id = in.getInt(); + } + + @Override + public void write(ByteBuffer out) { + out.putInt(this.id); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java b/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java new file mode 100644 index 00000000..a9e121af --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java @@ -0,0 +1,14 @@ +package ch.spacebase.packetlib.test; + +import ch.spacebase.packetlib.Client; +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.netty.NettySessionFactory; + +public class PingServerTest { + + public static void main(String[] args) { + new Server("127.0.0.1", 25565, new TestProtocol(), new NettySessionFactory()).bind(); + new Client("127.0.0.1", 25565, new TestProtocol(), new NettySessionFactory()).connect(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerListener.java b/src/main/java/ch/spacebase/packetlib/test/ServerListener.java new file mode 100644 index 00000000..47d68bf6 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/ServerListener.java @@ -0,0 +1,32 @@ +package ch.spacebase.packetlib.test; + +import ch.spacebase.packetlib.event.server.ServerAdapter; +import ch.spacebase.packetlib.event.server.ServerClosedEvent; +import ch.spacebase.packetlib.event.server.ServerClosingEvent; +import ch.spacebase.packetlib.event.server.SessionAddedEvent; +import ch.spacebase.packetlib.event.server.SessionRemovedEvent; + +public class ServerListener extends ServerAdapter { + + @Override + public void serverClosing(ServerClosingEvent event) { + System.out.println("CLOSING SERVER..."); + } + + @Override + public void serverClosed(ServerClosedEvent event) { + System.out.println("SERVER CLOSED"); + } + + @Override + public void sessionAdded(SessionAddedEvent event) { + System.out.println("SESSION ADDED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + } + + @Override + public void sessionRemoved(SessionRemovedEvent event) { + System.out.println("SESSION REMOVED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + event.getServer().close(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java b/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java new file mode 100644 index 00000000..129ec7c3 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java @@ -0,0 +1,28 @@ +package ch.spacebase.packetlib.test; + +import ch.spacebase.packetlib.event.session.DisconnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectingEvent; +import ch.spacebase.packetlib.event.session.PacketReceivedEvent; +import ch.spacebase.packetlib.event.session.SessionAdapter; + +public class ServerSessionListener extends SessionAdapter { + + @Override + public void packetReceived(PacketReceivedEvent event) { + if(event.getPacket() instanceof PingPacket) { + System.out.println("SERVER RECV: " + ((PingPacket) event.getPacket()).getPingId()); + event.getSession().send(event.getPacket()); + } + } + + @Override + public void disconnecting(DisconnectingEvent event) { + System.out.println("SERVER Disconnecting: " + event.getReason()); + } + + @Override + public void disconnected(DisconnectedEvent event) { + System.out.println("SERVER Disconnected: " + event.getReason()); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java b/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java new file mode 100644 index 00000000..1628b8af --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java @@ -0,0 +1,29 @@ +package ch.spacebase.packetlib.test; + +import ch.spacebase.packetlib.Client; +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.packet.PacketProtocol; + +public class TestProtocol extends PacketProtocol { + + public TestProtocol() { + this.register(PingPacket.class); + } + + @Override + public void newClientSession(Client client, Session session) { + session.addListener(new ClientSessionListener()); + } + + @Override + public void newServer(Server server) { + server.addListener(new ServerListener()); + } + + @Override + public void newServerSession(Server server, Session session) { + session.addListener(new ServerSessionListener()); + } + +} From 91d16ae3bea0479de90770b6ee139086a1e1200d Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 14 Dec 2013 16:41:25 -0800 Subject: [PATCH 002/180] Change packet header to have length int, add splitter to split packets by length, add encryption support, misc changes in preparation for MCProtocolLib rewrite --- .../java/ch/spacebase/packetlib/Client.java | 12 +- .../packetlib/ConnectionListener.java | 8 - .../java/ch/spacebase/packetlib/Server.java | 102 ++++++- .../java/ch/spacebase/packetlib/Session.java | 39 +++ .../packetlib/crypt/AESEncryption.java | 44 +++ .../packetlib/crypt/PacketEncryption.java | 42 +++ .../event/session/PacketReceivedEvent.java | 14 +- .../event/session/PacketSentEvent.java | 14 +- .../ch/spacebase/packetlib/io/NetInput.java | 115 ++++++++ .../ch/spacebase/packetlib/io/NetOutput.java | 108 +++++++ .../packetlib/io/stream/StreamNetInput.java | 137 +++++++++ .../packetlib/io/stream/StreamNetOutput.java | 117 ++++++++ .../packetlib/netty/NettyServerSession.java | 23 -- .../packetlib/netty/NettySession.java | 145 ---------- .../packetlib/netty/PacketCodec.java | 53 ---- .../ch/spacebase/packetlib/packet/Packet.java | 33 ++- .../packetlib/packet/PacketProtocol.java | 159 +++++++---- .../TcpConnectionListener.java} | 14 +- .../packetlib/tcp/TcpPacketCodec.java | 45 +++ .../packetlib/tcp/TcpPacketEncryptor.java | 59 ++++ .../packetlib/tcp/TcpPacketSizer.java | 63 ++++ .../packetlib/tcp/TcpServerSession.java | 37 +++ .../spacebase/packetlib/tcp/TcpSession.java | 270 ++++++++++++++++++ .../TcpSessionFactory.java} | 27 +- .../packetlib/tcp/io/ByteBufNetInput.java | 115 ++++++++ .../packetlib/tcp/io/ByteBufNetOutput.java | 105 +++++++ .../packetlib/test/ClientSessionListener.java | 8 +- .../spacebase/packetlib/test/PingPacket.java | 32 +-- .../packetlib/test/PingServerTest.java | 24 +- .../packetlib/test/ServerListener.java | 9 + .../packetlib/test/ServerSessionListener.java | 2 +- .../packetlib/test/TestProtocol.java | 35 ++- 32 files changed, 1616 insertions(+), 394 deletions(-) create mode 100644 src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java create mode 100644 src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java create mode 100644 src/main/java/ch/spacebase/packetlib/io/NetInput.java create mode 100644 src/main/java/ch/spacebase/packetlib/io/NetOutput.java create mode 100644 src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java create mode 100644 src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java delete mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java delete mode 100644 src/main/java/ch/spacebase/packetlib/netty/NettySession.java delete mode 100644 src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java rename src/main/java/ch/spacebase/packetlib/{netty/NettyConnectionListener.java => tcp/TcpConnectionListener.java} (64%) create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java rename src/main/java/ch/spacebase/packetlib/{netty/NettySessionFactory.java => tcp/TcpSessionFactory.java} (61%) create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java create mode 100644 src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java diff --git a/src/main/java/ch/spacebase/packetlib/Client.java b/src/main/java/ch/spacebase/packetlib/Client.java index 9cdae8a4..521af6b0 100644 --- a/src/main/java/ch/spacebase/packetlib/Client.java +++ b/src/main/java/ch/spacebase/packetlib/Client.java @@ -10,23 +10,13 @@ public class Client { private String host; private int port; private PacketProtocol protocol; - private SessionFactory factory; private Session session; public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { this.host = host; this.port = port; this.protocol = protocol; - this.factory = factory; - } - - /** - * Connects the client. - * @return This client after being connected. - */ - public Client connect() { - this.session = this.factory.createClientSession(this); - return this; + this.session = factory.createClientSession(this); } /** diff --git a/src/main/java/ch/spacebase/packetlib/ConnectionListener.java b/src/main/java/ch/spacebase/packetlib/ConnectionListener.java index d7c6d6de..16761050 100644 --- a/src/main/java/ch/spacebase/packetlib/ConnectionListener.java +++ b/src/main/java/ch/spacebase/packetlib/ConnectionListener.java @@ -1,7 +1,5 @@ package ch.spacebase.packetlib; -import ch.spacebase.packetlib.packet.PacketProtocol; - /** * A listener for new sessions on a host and port. */ @@ -19,12 +17,6 @@ public interface ConnectionListener { */ public int getPort(); - /** - * Gets the packet protocol of the listener. - * @return The listener's packet protocol. - */ - public PacketProtocol getPacketProtocol(); - /** * Returns true if the listener is listening. * @return True if the listener is listening. diff --git a/src/main/java/ch/spacebase/packetlib/Server.java b/src/main/java/ch/spacebase/packetlib/Server.java index 721dbd36..be419679 100644 --- a/src/main/java/ch/spacebase/packetlib/Server.java +++ b/src/main/java/ch/spacebase/packetlib/Server.java @@ -1,7 +1,10 @@ package ch.spacebase.packetlib; +import java.lang.reflect.Constructor; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import ch.spacebase.packetlib.event.server.ServerBoundEvent; import ch.spacebase.packetlib.event.server.ServerClosedEvent; @@ -19,19 +22,19 @@ public class Server { private String host; private int port; - private PacketProtocol protocol; + private Class protocol; private SessionFactory factory; private ConnectionListener listener; private List sessions = new ArrayList(); + private Map flags = new HashMap(); private List listeners = new ArrayList(); - public Server(String host, int port, PacketProtocol protocol, SessionFactory factory) { + public Server(String host, int port, Class protocol, SessionFactory factory) { this.host = host; this.port = port; this.protocol = protocol; this.factory = factory; - this.protocol.newServer(this); } /** @@ -60,16 +63,93 @@ public class Server { return this.port; } + /** + * Gets the packet protocol of the server. + * @return The server's packet protocol. + */ + public Class getPacketProtocol() { + return this.protocol; + } + + /** + * Creates a new packet protocol instance from this server's protocol class. + * @return The created protocol instance. + * @throws IllegalStateException If the protocol does not have a no-params constructor or cannot be instantiated. + */ + public PacketProtocol createPacketProtocol() { + try { + Constructor constructor = this.protocol.getDeclaredConstructor(); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + + return constructor.newInstance(); + } catch(NoSuchMethodError e) { + throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); + } + } + + /** + * Gets this server's set flags. + * @return This server's flags. + */ + public Map getGlobalFlags() { + return new HashMap(this.flags); + } + + /** + * Checks whether this server has a flag set. + * @param key Key of the flag to check for. + * @return Whether this server has a flag set. + */ + public boolean hasGlobalFlag(String key) { + return this.flags.containsKey(key); + } + + /** + * Gets the value of the given flag as an instance of the given type. If this + * session belongs to a server, the server's flags will be checked for the flag + * as well. + * @param key Key of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getGlobalFlag(String key) { + Object value = this.flags.get(key); + if(value == null) { + return null; + } + + try { + return (T) value; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); + } + } + + /** + * Sets the value of a flag. The flag will be used in sessions if a session does + * not contain a value for the flag. + * @param key Key of the flag. + * @param value Value to set the flag to. + */ + public void setGlobalFlag(String key, Object value) { + this.flags.put(key, value); + } + /** * Gets the listeners listening on this session. - * @return This session's listeners. + * @return This server's listeners. */ public List getListeners() { return new ArrayList(this.listeners); } /** - * Adds a listener to this session. + * Adds a listener to this server. * @param listener Listener to add. */ public void addListener(ServerListener listener) { @@ -77,7 +157,7 @@ public class Server { } /** - * Removes a listener from this session. + * Removes a listener from this server. * @param listener Listener to remove. */ public void removeListener(ServerListener listener) { @@ -85,7 +165,7 @@ public class Server { } /** - * Calls an event on the listeners of this session. + * Calls an event on the listeners of this server. * @param event Event to call. */ public void callEvent(ServerEvent event) { @@ -94,14 +174,6 @@ public class Server { } } - /** - * Gets the packet protocol of the server. - * @return The server's packet protocol. - */ - public PacketProtocol getPacketProtocol() { - return this.protocol; - } - /** * Gets all sessions belonging to this server. * @return Sessions belonging to this server. diff --git a/src/main/java/ch/spacebase/packetlib/Session.java b/src/main/java/ch/spacebase/packetlib/Session.java index 1c2bc8ba..dc816cc0 100644 --- a/src/main/java/ch/spacebase/packetlib/Session.java +++ b/src/main/java/ch/spacebase/packetlib/Session.java @@ -1,6 +1,7 @@ package ch.spacebase.packetlib; import java.util.List; +import java.util.Map; import ch.spacebase.packetlib.event.session.SessionEvent; import ch.spacebase.packetlib.event.session.SessionListener; @@ -12,6 +13,11 @@ import ch.spacebase.packetlib.packet.PacketProtocol; */ public interface Session { + /** + * Connects this session to its host and port. + */ + public void connect(); + /** * Gets the host the session is connected to. * @return The connected host. @@ -30,6 +36,39 @@ public interface Session { */ public PacketProtocol getPacketProtocol(); + /** + * Gets this session's set flags. If this session belongs to a server, the server's + * flags will be included in the results. + * @return This session's flags. + */ + public Map getFlags(); + + /** + * Checks whether this session has a flag set. If this session belongs to a server, + * the server's flags will also be checked. + * @param key Key of the flag to check for. + * @return Whether this session has a flag set. + */ + public boolean hasFlag(String key); + + /** + * Gets the value of the given flag as an instance of the given type. If this + * session belongs to a server, the server's flags will be checked for the flag + * as well. + * @param key Key of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + public T getFlag(String key); + + /** + * Sets the value of a flag. This does not change a server's flags if this session + * belongs to a server. + * @param key Key of the flag. + * @param value Value to set the flag to. + */ + public void setFlag(String key, Object value); + /** * Gets the listeners listening on this session. * @return This session's listeners. diff --git a/src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java b/src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java new file mode 100644 index 00000000..a3db36f8 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java @@ -0,0 +1,44 @@ +package ch.spacebase.packetlib.crypt; + +import java.security.GeneralSecurityException; +import java.security.Key; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; + +/** + * An encryption implementation using "AES/CFB8/NoPadding" encryption. + */ +public class AESEncryption implements PacketEncryption { + + private Cipher inCipher; + private Cipher outCipher; + + public AESEncryption(Key key) throws GeneralSecurityException { + this.inCipher = Cipher.getInstance("AES/CFB8/NoPadding"); + this.inCipher.init(2, key, new IvParameterSpec(key.getEncoded())); + this.outCipher = Cipher.getInstance("AES/CFB8/NoPadding"); + this.outCipher.init(1, key, new IvParameterSpec(key.getEncoded())); + } + + @Override + public int getDecryptOutputSize(int length) { + return this.inCipher.getOutputSize(length); + } + + @Override + public int getEncryptOutputSize(int length) { + return this.outCipher.getOutputSize(length); + } + + @Override + public int decrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { + return this.inCipher.update(input, inputOffset, inputLength, output, outputOffset); + } + + @Override + public int encrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { + return this.outCipher.update(input, inputOffset, inputLength, output, outputOffset); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java b/src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java new file mode 100644 index 00000000..836e500d --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java @@ -0,0 +1,42 @@ +package ch.spacebase.packetlib.crypt; + +/** + * An interface for encrypting packets. + */ +public interface PacketEncryption { + + /** + * Gets the output size from decrypting. + * @param length Length of the data being decrypted. + */ + public int getDecryptOutputSize(int length); + + /** + * Gets the output size from encrypting. + * @param length Length of the data being encrypted. + */ + public int getEncryptOutputSize(int length); + + /** + * Decrypts the given data. + * @param input Input data to decrypt. + * @param inputOffset Offset of the data to start decrypting at. + * @param inputLength Length of the data to be decrypted. + * @param output Array to output decrypted data to. + * @param outputOffset Offset of the output array to start at. + * @return The number of bytes stored in the output array. + */ + public int decrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; + + /** + * Encrypts the given data. + * @param input Input data to encrypt. + * @param inputOffset Offset of the data to start encrypting at. + * @param inputLength Length of the data to be encrypted. + * @param output Array to output encrypted data to. + * @param outputOffset Offset of the output array to start at. + * @return The number of bytes stored in the output array. + */ + public int encrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; + +} diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java index 15ed4fb1..8e535709 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java @@ -25,11 +25,17 @@ public class PacketReceivedEvent implements SessionEvent { } /** - * Gets the packet involved in this event. - * @return The event's packet. + * Gets the packet involved in this event as the required type. + * @return The event's packet as the required type. + * @throws IllegalStateException If the packet's value isn't of the required type. */ - public Packet getPacket() { - return this.packet; + @SuppressWarnings("unchecked") + public T getPacket() { + try { + return (T) this.packet; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); + } } @Override diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java b/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java index 2b717e32..212c74a6 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java @@ -25,11 +25,17 @@ public class PacketSentEvent implements SessionEvent { } /** - * Gets the packet involved in this event. - * @return The event's packet. + * Gets the packet involved in this event as the required type. + * @return The event's packet as the required type. + * @throws IllegalStateException If the packet's value isn't of the required type. */ - public Packet getPacket() { - return this.packet; + @SuppressWarnings("unchecked") + public T getPacket() { + try { + return (T) this.packet; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); + } } @Override diff --git a/src/main/java/ch/spacebase/packetlib/io/NetInput.java b/src/main/java/ch/spacebase/packetlib/io/NetInput.java new file mode 100644 index 00000000..09b4b4f5 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/io/NetInput.java @@ -0,0 +1,115 @@ +package ch.spacebase.packetlib.io; + +import java.io.IOException; + +/** + * An interface for reading network data. + */ +public interface NetInput { + + /** + * Reads the next boolean. + * @return The next boolean. + * @throws IOException If an I/O error occurs. + */ + public boolean readBoolean() throws IOException; + + /** + * Reads the next byte. + * @return The next byte. + * @throws IOException If an I/O error occurs. + */ + public byte readByte() throws IOException; + + /** + * Reads the next unsigned byte. + * @return The next unsigned byte. + * @throws IOException If an I/O error occurs. + */ + public int readUnsignedByte() throws IOException; + + /** + * Reads the next short. + * @return The next short. + * @throws IOException If an I/O error occurs. + */ + public short readShort() throws IOException; + + /** + * Reads the next unsigned short. + * @return The next unsigned short. + * @throws IOException If an I/O error occurs. + */ + public int readUnsignedShort() throws IOException; + + /** + * Reads the next char. + * @return The next char. + * @throws IOException If an I/O error occurs. + */ + public char readChar() throws IOException; + + /** + * Reads the next integer. + * @return The next integer. + * @throws IOException If an I/O error occurs. + */ + public int readInt() throws IOException; + + /** + * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * @return The next varint. + * @throws IOException If an I/O error occurs. + */ + public int readVarInt() throws IOException; + + /** + * Reads the next long. + * @return The next long. + * @throws IOException If an I/O error occurs. + */ + public long readLong() throws IOException; + + /** + * Reads the next float. + * @return The next float. + * @throws IOException If an I/O error occurs. + */ + public float readFloat() throws IOException; + + /** + * Reads the next double. + * @return The next double. + * @throws IOException If an I/O error occurs. + */ + public double readDouble() throws IOException; + + /** + * Reads the next byte array, getting the length from a prefixed length value. + * @return The next byte array. + * @throws IOException If an I/O error occurs. + */ + public byte[] readPrefixedBytes() throws IOException; + + /** + * Reads the next byte array. + * @param The length of the byte array. + * @return The next byte array. + * @throws IOException If an I/O error occurs. + */ + public byte[] readBytes(int length) throws IOException; + + /** + * Reads the next string. + * @return The next string. + * @throws IOException If an I/O error occurs. + */ + public String readString() throws IOException; + + /** + * Gets the number of available bytes. + * @return The number of available bytes. + */ + public int available() throws IOException; + +} diff --git a/src/main/java/ch/spacebase/packetlib/io/NetOutput.java b/src/main/java/ch/spacebase/packetlib/io/NetOutput.java new file mode 100644 index 00000000..898bf29a --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/io/NetOutput.java @@ -0,0 +1,108 @@ +package ch.spacebase.packetlib.io; + +import java.io.IOException; + +/** + * An interface for writing network data. + */ +public interface NetOutput { + + /** + * Writes a boolean. + * @param b Boolean to write. + * @throws IOException If an I/O error occurs. + */ + public void writeBoolean(boolean b) throws IOException; + + /** + * Writes a byte. + * @param b Byte to write. + * @throws IOException If an I/O error occurs. + */ + public void writeByte(int b) throws IOException; + + /** + * Writes a short. + * @param s Short to write. + * @throws IOException If an I/O error occurs. + */ + public void writeShort(int s) throws IOException; + + /** + * Writes a char. + * @param c Char to write. + * @throws IOException If an I/O error occurs. + */ + public void writeChar(int c) throws IOException; + + /** + * Writes a integer. + * @param i Integer to write. + * @throws IOException If an I/O error occurs. + */ + public void writeInt(int i) throws IOException; + + /** + * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * @return i Varint to write. + * @throws IOException If an I/O error occurs. + */ + public void writeVarInt(int i) throws IOException; + + /** + * Writes a long. + * @param l Long to write. + * @throws IOException If an I/O error occurs. + */ + public void writeLong(long l) throws IOException; + + /** + * Writes a float. + * @param f Float to write. + * @throws IOException If an I/O error occurs. + */ + public void writeFloat(float f) throws IOException; + + /** + * Writes a double. + * @param d Double to write. + * @throws IOException If an I/O error occurs. + */ + public void writeDouble(double d) throws IOException; + + /** + * Writes a byte array, prefixing the written data with the array's length. + * @param b Byte array to write. + * @throws IOException If an I/O error occurs. + */ + public void writePrefixedBytes(byte b[]) throws IOException; + + /** + * Writes a byte array. + * @param b Byte array to write. + * @throws IOException If an I/O error occurs. + */ + public void writeBytes(byte b[]) throws IOException; + + /** + * Writes a byte array, using the given amount of bytes. + * @param b Byte array to write. + * @param length Bytes to write. + * @throws IOException If an I/O error occurs. + */ + public void writeBytes(byte b[], int length) throws IOException; + + /** + * Writes a string. + * @param s String to write. + * @throws IOException If an I/O error occurs. + */ + public void writeString(String s) throws IOException; + + /** + * Flushes the output. + * @throws IOException If an I/O error occurs. + */ + public void flush() throws IOException; + +} diff --git a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java b/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java new file mode 100644 index 00000000..cd498b34 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java @@ -0,0 +1,137 @@ +package ch.spacebase.packetlib.io.stream; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +import ch.spacebase.packetlib.io.NetInput; + +/** + * A NetInput implementation using an InputStream as a backend. + */ +public class StreamNetInput implements NetInput { + + private InputStream in; + + public StreamNetInput(InputStream in) { + this.in = in; + } + + @Override + public boolean readBoolean() throws IOException { + return this.readByte() == 1; + } + + @Override + public byte readByte() throws IOException { + return (byte) this.readUnsignedByte(); + } + + @Override + public int readUnsignedByte() throws IOException { + int b = this.in.read(); + if(b < 0) { + throw new EOFException(); + } + + return b; + } + + @Override + public short readShort() throws IOException { + return (short) this.readUnsignedShort(); + } + + @Override + public int readUnsignedShort() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + return (ch1 << 8) + (ch2 << 0); + } + + @Override + public char readChar() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + return (char) ((ch1 << 8) + (ch2 << 0)); + } + + @Override + public int readInt() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + int ch3 = this.readUnsignedByte(); + int ch4 = this.readUnsignedByte(); + return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); + } + + @Override + public int readVarInt() throws IOException { + int ret = 0; + int size = 0; + byte b; + while(((b = this.readByte()) & 128) == 128) { + ret |= (b & 127) << size++ * 7; + if(size > 5) { + throw new IOException("Varint too big"); + } + } + + return ret; + } + + @Override + public long readLong() throws IOException { + byte read[] = this.readBytes(8); + return ((long) read[0] << 56) + ((long) (read[1] & 255) << 48) + ((long) (read[2] & 255) << 40) + ((long) (read[3] & 255) << 32) + ((long) (read[4] & 255) << 24) + ((read[5] & 255) << 16) + ((read[6] & 255) << 8) + ((read[7] & 255) << 0); + } + + @Override + public float readFloat() throws IOException { + return Float.intBitsToFloat(this.readInt()); + } + + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(this.readLong()); + } + + @Override + public byte[] readPrefixedBytes() throws IOException { + short length = this.readShort(); + return this.readBytes(length); + } + + @Override + public byte[] readBytes(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + byte b[] = new byte[length]; + int n = 0; + while(n < length) { + int count = this.in.read(b, n, length - n); + if(count < 0) { + throw new EOFException(); + } + + n += count; + } + + return b; + } + + @Override + public String readString() throws IOException { + int length = this.readVarInt(); + byte bytes[] = this.readBytes(length); + return new String(bytes, "UTF-8"); + } + + @Override + public int available() throws IOException { + return this.in.available(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java b/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java new file mode 100644 index 00000000..7723423c --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java @@ -0,0 +1,117 @@ +package ch.spacebase.packetlib.io.stream; + +import java.io.IOException; +import java.io.OutputStream; + +import ch.spacebase.packetlib.io.NetOutput; + +/** + * A NetOutput implementation using an OutputStream as a backend. + */ +public class StreamNetOutput implements NetOutput { + + private OutputStream out; + + public StreamNetOutput(OutputStream out) { + this.out = out; + } + + @Override + public void writeBoolean(boolean b) throws IOException { + this.writeByte(b ? 1 : 0); + } + + @Override + public void writeByte(int b) throws IOException { + this.out.write(b); + } + + @Override + public void writeShort(int s) throws IOException { + this.writeByte((byte) ((s >>> 8) & 0xFF)); + this.writeByte((byte) ((s >>> 0) & 0xFF)); + } + + @Override + public void writeChar(int c) throws IOException { + this.writeByte((byte) ((c >>> 8) & 0xFF)); + this.writeByte((byte) ((c >>> 0) & 0xFF)); + } + + @Override + public void writeInt(int i) throws IOException { + this.writeByte((byte) ((i >>> 24) & 0xFF)); + this.writeByte((byte) ((i >>> 16) & 0xFF)); + this.writeByte((byte) ((i >>> 8) & 0xFF)); + this.writeByte((byte) ((i >>> 0) & 0xFF)); + } + + @Override + public void writeVarInt(int i) throws IOException { + while((i & -128) != 0) { + this.writeByte(i & 127 | 128); + i >>>= 7; + } + + this.writeByte(i); + } + + @Override + public void writeLong(long l) throws IOException { + this.writeByte((byte) (l >>> 56)); + this.writeByte((byte) (l >>> 48)); + this.writeByte((byte) (l >>> 40)); + this.writeByte((byte) (l >>> 32)); + this.writeByte((byte) (l >>> 24)); + this.writeByte((byte) (l >>> 16)); + this.writeByte((byte) (l >>> 8)); + this.writeByte((byte) (l >>> 0)); + } + + @Override + public void writeFloat(float f) throws IOException { + this.writeInt(Float.floatToIntBits(f)); + } + + @Override + public void writeDouble(double d) throws IOException { + this.writeLong(Double.doubleToLongBits(d)); + } + + @Override + public void writePrefixedBytes(byte b[]) throws IOException { + this.writeShort(b.length); + this.writeBytes(b); + } + + @Override + public void writeBytes(byte b[]) throws IOException { + this.writeBytes(b, b.length); + } + + @Override + public void writeBytes(byte b[], int length) throws IOException { + this.out.write(b, 0, length); + } + + @Override + public void writeString(String s) throws IOException { + if(s == null) { + throw new IllegalArgumentException("String cannot be null!"); + } + + byte[] bytes = s.getBytes("UTF-8"); + if(bytes.length > 32767) { + throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); + } else { + this.writeVarInt(bytes.length); + this.writeBytes(bytes); + } + } + + @Override + public void flush() throws IOException { + this.out.flush(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java b/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java deleted file mode 100644 index 867aa6fc..00000000 --- a/src/main/java/ch/spacebase/packetlib/netty/NettyServerSession.java +++ /dev/null @@ -1,23 +0,0 @@ -package ch.spacebase.packetlib.netty; - -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.packet.PacketProtocol; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; - -public class NettyServerSession extends NettySession { - - private Server server; - - public NettyServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Server server) { - super(host, port, protocol, group); - this.server = server; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - this.server.removeSession(this); - } - -} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettySession.java b/src/main/java/ch/spacebase/packetlib/netty/NettySession.java deleted file mode 100644 index abc0fcf7..00000000 --- a/src/main/java/ch/spacebase/packetlib/netty/NettySession.java +++ /dev/null @@ -1,145 +0,0 @@ -package ch.spacebase.packetlib.netty; - -import java.util.ArrayList; -import java.util.List; - -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.event.session.ConnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectingEvent; -import ch.spacebase.packetlib.event.session.PacketReceivedEvent; -import ch.spacebase.packetlib.event.session.PacketSentEvent; -import ch.spacebase.packetlib.event.session.SessionEvent; -import ch.spacebase.packetlib.event.session.SessionListener; -import ch.spacebase.packetlib.packet.Packet; -import ch.spacebase.packetlib.packet.PacketProtocol; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; - -public class NettySession extends SimpleChannelInboundHandler implements Session { - - private String host; - private int port; - private PacketProtocol protocol; - private EventLoopGroup group; - private Channel channel; - private boolean disconnected; - - private List listeners = new ArrayList(); - - public NettySession(String host, int port, PacketProtocol protocol, EventLoopGroup group) { - this.host = host; - this.port = port; - this.protocol = protocol; - this.group = group; - } - - @Override - public String getHost() { - return this.host; - } - - @Override - public int getPort() { - return this.port; - } - - @Override - public PacketProtocol getPacketProtocol() { - return this.protocol; - } - - @Override - public List getListeners() { - return new ArrayList(this.listeners); - } - - @Override - public void addListener(SessionListener listener) { - this.listeners.add(listener); - } - - @Override - public void removeListener(SessionListener listener) { - this.listeners.remove(listener); - } - - @Override - public void callEvent(SessionEvent event) { - for(SessionListener listener : this.listeners) { - event.call(listener); - } - } - - @Override - public boolean isConnected() { - return this.channel != null && this.channel.isOpen(); - } - - @Override - public void send(Packet packet) { - if(this.channel == null) { - return; - } - - this.channel.writeAndFlush(packet); - this.callEvent(new PacketSentEvent(this, packet)); - } - - @Override - public void disconnect(String reason) { - if(reason == null) { - reason = "Connection closed."; - } - - if(this.channel != null) { - this.callEvent(new DisconnectingEvent(this, reason)); - this.channel.close().syncUninterruptibly(); - this.callEvent(new DisconnectedEvent(this, reason)); - } - - if(this.group != null) { - this.group.shutdownGracefully(); - } - - this.disconnected = true; - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - if(this.disconnected) { - ctx.channel().close().syncUninterruptibly(); - return; - } - - this.channel = ctx.channel(); - this.callEvent(new ConnectedEvent(this)); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - if(!this.disconnected) { - this.disconnect("Connection closed."); - } - - this.channel = null; - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if(!this.disconnected) { - this.disconnect("Internal exception: " + cause); - this.channel = null; - System.err.println("Networking exception occured: " + cause); - cause.printStackTrace(); - } - } - - @Override - protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { - this.callEvent(new PacketReceivedEvent(this, packet)); - } - -} diff --git a/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java b/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java deleted file mode 100644 index c1097fd2..00000000 --- a/src/main/java/ch/spacebase/packetlib/netty/PacketCodec.java +++ /dev/null @@ -1,53 +0,0 @@ -package ch.spacebase.packetlib.netty; - -import java.nio.ByteBuffer; -import java.util.List; - -import ch.spacebase.packetlib.packet.Packet; -import ch.spacebase.packetlib.packet.PacketProtocol; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageCodec; - -public class PacketCodec extends ByteToMessageCodec { - - private PacketProtocol protocol; - - public PacketCodec(PacketProtocol protocol) { - this.protocol = protocol; - } - - @Override - public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { - try { - ByteBuffer out = ByteBuffer.allocate(packet.getLength() + 1); - out.put((byte) (packet.getId() & 0xFF)); - packet.write(out); - out.flip(); - buf.writeBytes(this.protocol.encode(out.array())); - } catch(Throwable t) { - t.printStackTrace(); - } - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - try { - byte array[] = new byte[buf.readableBytes()]; - for(int index = 0; index < array.length; index++) { - array[index] = buf.readByte(); - } - - ByteBuffer in = ByteBuffer.allocate(buf.capacity()).put(this.protocol.decode(array)); - in.flip(); - - int id = in.get() & 0xFF; - Packet packet = this.protocol.createPacket(id); - packet.read(in); - out.add(packet); - } catch(Throwable t) { - t.printStackTrace(); - } - } - -} diff --git a/src/main/java/ch/spacebase/packetlib/packet/Packet.java b/src/main/java/ch/spacebase/packetlib/packet/Packet.java index 45b5b31e..bd3ca7ca 100644 --- a/src/main/java/ch/spacebase/packetlib/packet/Packet.java +++ b/src/main/java/ch/spacebase/packetlib/packet/Packet.java @@ -1,34 +1,33 @@ package ch.spacebase.packetlib.packet; -import java.nio.ByteBuffer; +import java.io.IOException; + +import ch.spacebase.packetlib.io.NetInput; +import ch.spacebase.packetlib.io.NetOutput; /** * A network packet. */ public interface Packet { - - /** - * Gets the id of the packet. - * @return The packet's id. - */ - public int getId(); - - /** - * Gets the length of the packet. - * @return The packet's length. - */ - public int getLength(); /** * Reads the packet from the given input buffer. - * @param in The buffer to read from. + * @param in The input source to read from. */ - public void read(ByteBuffer in); + public void read(NetInput in) throws IOException; /** * Writes the packet to the given output buffer. - * @param in The buffer to write to. + * @param out The output destination to write to. */ - public void write(ByteBuffer out); + public void write(NetOutput out) throws IOException; + + /** + * Gets whether the packet has handling and writing priority. + * If the result is true, the thread will wait for the packet to finish writing + * when writing and the packet will be handled immediately after reading it. + * @return Whether the packet has priority. + */ + public boolean isPriority(); } diff --git a/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java b/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java index 7bb01de9..4450740d 100644 --- a/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java +++ b/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java @@ -1,16 +1,22 @@ package ch.spacebase.packetlib.packet; +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + import ch.spacebase.packetlib.Client; import ch.spacebase.packetlib.Server; import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.crypt.PacketEncryption; /** * A protocol for packet sending and receiving. + * All implementations must have a no-params constructor for server protocol creation. */ public abstract class PacketProtocol { - @SuppressWarnings("unchecked") - private final Class registry[] = (Class[]) new Class[256]; + private final Map> incoming = new HashMap>(); + private final Map, Integer> outgoing = new HashMap, Integer>(); /** * Called when a client is created with this protocol. @@ -19,12 +25,6 @@ public abstract class PacketProtocol { */ public abstract void newClientSession(Client client, Session session); - /** - * Called when a server is created with this protocol. - * @param server The created server. - */ - public abstract void newServer(Server server); - /** * Called when a server's session is created with this protocol. * @param server The server that the session belongs to. @@ -33,62 +33,97 @@ public abstract class PacketProtocol { public abstract void newServerSession(Server server, Session session); /** - * Decodes the given data array into readable form. - * @param data Data to decode. - * @return The decoded data. + * Gets this protocol's active packet encryption. + * @return The protocol's packet encryption, or null if packets should not be encrypted. */ - public byte[] decode(byte data[]) { - return data; - } - - /** - * Encodes the given data array for sending over the network. - * @param data Data to encode. - * @return The encoded data. - */ - public byte[] encode(byte data[]) { - return data; - } - - /** - * Registers a packet to this protocol. - * @param packet Packet to register. - */ - public final void register(Class packet) { - int id = 0; - try { - id = packet.getDeclaredConstructor().newInstance().getId(); - } catch(NoSuchMethodError e) { - System.err.println("Packet \"" + packet.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - System.err.println("Failed to instantiate packet " + packet.getName() + " to get id."); - e.printStackTrace(); - } - - registry[id] = packet; - } - - /** - * Creates a new instance of the packet with the given id. - * @param id Id of the packet to create, or null if it could not be created. - * @return The created packet - * @throws IllegalArgumentException If the packet ID is invalid. - */ - public final Packet createPacket(int id) { - if(id < 0 || id >= registry.length || registry[id] == null) { - throw new IllegalArgumentException("Invalid packet id: " + id); - } - - try { - return registry[id].getDeclaredConstructor().newInstance(); - } catch(NoSuchMethodError e) { - System.err.println("Packet \"" + id + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - System.err.println("Failed to instantiate packet " + id + "."); - e.printStackTrace(); - } - + public PacketEncryption getEncryption() { return null; } + /** + * Clears all currently registered packets. + */ + public final void clearPackets() { + this.incoming.clear(); + this.outgoing.clear(); + } + + /** + * Registers a packet to this protocol as both incoming and outgoing. + * @param id Id to register the packet to. + * @param packet Packet to register. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + */ + public final void register(int id, Class packet) { + this.registerIncoming(id, packet); + this.registerOutgoing(id, packet); + } + + /** + * Registers an incoming packet to this protocol. + * @param id Id to register the packet to. + * @param packet Packet to register. + * @throws IllegalArgumentException If the packet fails a test creation. + */ + public final void registerIncoming(int id, Class packet) { + this.incoming.put(id, packet); + try { + this.createIncomingPacket(id); + } catch(IllegalStateException e) { + this.incoming.remove(id); + throw new IllegalArgumentException(e.getMessage(), e.getCause()); + } + } + + /** + * Registers an outgoing packet to this protocol. + * @param id Id to register the packet to. + * @param packet Packet to register. + */ + public final void registerOutgoing(int id, Class packet) { + this.outgoing.put(packet, id); + } + + /** + * Creates a new instance of an incoming packet with the given id. + * @param id Id of the packet to create. + * @return The created packet. + * @throws IllegalArgumentException If the packet ID is invalid. + * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. + */ + public final Packet createIncomingPacket(int id) { + if(id < 0 || !this.incoming.containsKey(id) || this.incoming.get(id) == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + Class packet = this.incoming.get(id); + try { + Constructor constructor = packet.getDeclaredConstructor(); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + + return constructor.newInstance(); + } catch(NoSuchMethodError e) { + throw new IllegalStateException("Packet \"" + id + ", " + packet.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + packet.getName() + "\".", e); + } + } + + /** + * Gets the registered id of an outgoing packet class. + * @param packet Class of the packet to get the id for. + * @return The packet's registered id. + * @throws IllegalArgumentException If the packet is not registered. + */ + public final int getOutgoingId(Class packet) { + if(!this.outgoing.containsKey(packet) || this.outgoing.get(packet) == null) { + throw new IllegalArgumentException("Unregistered outgoing packet class: " + packet.getName()); + } + + return this.outgoing.get(packet); + } + + } diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java similarity index 64% rename from src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java rename to src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java index ca66902d..38271637 100644 --- a/src/main/java/ch/spacebase/packetlib/netty/NettyConnectionListener.java +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java @@ -1,22 +1,19 @@ -package ch.spacebase.packetlib.netty; +package ch.spacebase.packetlib.tcp; import ch.spacebase.packetlib.ConnectionListener; -import ch.spacebase.packetlib.packet.PacketProtocol; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; -public class NettyConnectionListener implements ConnectionListener { +public class TcpConnectionListener implements ConnectionListener { private String host; private int port; - private PacketProtocol protocol; private EventLoopGroup group; private Channel channel; - public NettyConnectionListener(String host, int port, PacketProtocol protocol, EventLoopGroup group, Channel channel) { + public TcpConnectionListener(String host, int port, EventLoopGroup group, Channel channel) { this.host = host; this.port = port; - this.protocol = protocol; this.group = group; this.channel = channel; } @@ -31,11 +28,6 @@ public class NettyConnectionListener implements ConnectionListener { return this.port; } - @Override - public PacketProtocol getPacketProtocol() { - return this.protocol; - } - @Override public boolean isListening() { return this.channel.isOpen(); diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java new file mode 100644 index 00000000..216d54f1 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java @@ -0,0 +1,45 @@ +package ch.spacebase.packetlib.tcp; + +import java.util.List; + +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.event.session.PacketReceivedEvent; +import ch.spacebase.packetlib.io.NetInput; +import ch.spacebase.packetlib.io.NetOutput; +import ch.spacebase.packetlib.packet.Packet; +import ch.spacebase.packetlib.tcp.io.ByteBufNetInput; +import ch.spacebase.packetlib.tcp.io.ByteBufNetOutput; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; + +public class TcpPacketCodec extends ByteToMessageCodec { + + private Session session; + + public TcpPacketCodec(Session session) { + this.session = session; + } + + @Override + public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { + NetOutput out = new ByteBufNetOutput(buf); + out.writeVarInt(this.session.getPacketProtocol().getOutgoingId(packet.getClass())); + packet.write(out); + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + NetInput in = new ByteBufNetInput(buf); + int id = in.readVarInt(); + Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); + System.out.println(packet.getClass()); + packet.read(in); + if(packet.isPriority()) { + this.session.callEvent(new PacketReceivedEvent(this.session, packet)); + } + + out.add(packet); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java new file mode 100644 index 00000000..ff7cc2e5 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java @@ -0,0 +1,59 @@ +package ch.spacebase.packetlib.tcp; + +import java.util.List; + +import ch.spacebase.packetlib.Session; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; + +public class TcpPacketEncryptor extends ByteToMessageCodec { + + private Session session; + private byte[] decryptedArray = new byte[0]; + private byte[] encryptedArray = new byte[0]; + + public TcpPacketEncryptor(Session session) { + this.session = session; + } + + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + if(this.session.getPacketProtocol().getEncryption() != null) { + int length = in.readableBytes(); + byte[] bytes = this.getBytes(in); + int outLength = this.session.getPacketProtocol().getEncryption().getEncryptOutputSize(length); + if(this.encryptedArray.length < outLength) { + this.encryptedArray = new byte[outLength]; + } + + out.writeBytes(this.encryptedArray, 0, this.session.getPacketProtocol().getEncryption().encrypt(bytes, 0, length, this.encryptedArray, 0)); + } else { + out.writeBytes(in); + } + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + if(this.session.getPacketProtocol().getEncryption() != null) { + int length = buf.readableBytes(); + byte[] bytes = this.getBytes(buf); + ByteBuf result = ctx.alloc().heapBuffer(this.session.getPacketProtocol().getEncryption().getDecryptOutputSize(length)); + result.writerIndex(this.session.getPacketProtocol().getEncryption().decrypt(bytes, 0, length, result.array(), result.arrayOffset())); + out.add(result); + } else { + out.add(buf.readBytes(buf.readableBytes())); + } + } + + private byte[] getBytes(ByteBuf buf) { + int length = buf.readableBytes(); + if(this.decryptedArray.length < length) { + this.decryptedArray = new byte[length]; + } + + buf.readBytes(this.decryptedArray, 0, length); + return this.decryptedArray; + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java new file mode 100644 index 00000000..8b296a21 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java @@ -0,0 +1,63 @@ +package ch.spacebase.packetlib.tcp; + +import java.util.List; + +import ch.spacebase.packetlib.tcp.io.ByteBufNetInput; +import ch.spacebase.packetlib.tcp.io.ByteBufNetOutput; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; +import io.netty.handler.codec.CorruptedFrameException; + +public class TcpPacketSizer extends ByteToMessageCodec { + + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + int length = in.readableBytes(); + out.ensureWritable(varintLength(length) + length); + new ByteBufNetOutput(out).writeVarInt(length); + out.writeBytes(in); + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + buf.markReaderIndex(); + byte[] lengthBytes = new byte[5]; + for(int index = 0; index < lengthBytes.length; index++) { + if(!buf.isReadable()) { + buf.resetReaderIndex(); + return; + } + + lengthBytes[index] = buf.readByte(); + if(lengthBytes[index] >= 0) { + int length = new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)).readVarInt(); + if(buf.readableBytes() < length) { + buf.resetReaderIndex(); + return; + } + + out.add(buf.readBytes(length)); + return; + } + } + + throw new CorruptedFrameException("Length is too long."); + } + + private static int varintLength(int i) { + if((i & -128) == 0) { + return 1; + } else if((i & -16384) == 0) { + return 2; + } else if((i & -2097152) == 0) { + return 3; + } else if((i & -268435456) == 0) { + return 4; + } else { + return 5; + } + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java new file mode 100644 index 00000000..29ca14cb --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java @@ -0,0 +1,37 @@ +package ch.spacebase.packetlib.tcp; + +import java.util.Map; + +import ch.spacebase.packetlib.Server; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; + +public class TcpServerSession extends TcpSession { + + private Server server; + + public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server) { + super(host, port, protocol, group, bootstrap); + this.server = server; + } + + @Override + public void connect() { + } + + @Override + public Map getFlags() { + Map ret = super.getFlags(); + ret.putAll(this.server.getGlobalFlags()); + return ret; + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + this.server.removeSession(this); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java new file mode 100644 index 00000000..d82b62c2 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java @@ -0,0 +1,270 @@ +package ch.spacebase.packetlib.tcp; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.event.session.ConnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectedEvent; +import ch.spacebase.packetlib.event.session.DisconnectingEvent; +import ch.spacebase.packetlib.event.session.PacketReceivedEvent; +import ch.spacebase.packetlib.event.session.PacketSentEvent; +import ch.spacebase.packetlib.event.session.SessionEvent; +import ch.spacebase.packetlib.event.session.SessionListener; +import ch.spacebase.packetlib.packet.Packet; +import ch.spacebase.packetlib.packet.PacketProtocol; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.timeout.ReadTimeoutException; + +public class TcpSession extends SimpleChannelInboundHandler implements Session { + + private String host; + private int port; + private PacketProtocol protocol; + private Bootstrap bootstrap; + private EventLoopGroup group; + private Channel channel; + private boolean disconnected = false; + private boolean writing = false; + private List packets = new ArrayList(); + + private Map flags = new HashMap(); + private List listeners = new ArrayList(); + + public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.group = group; + this.bootstrap = bootstrap; + } + + @Override + public void connect() { + if(this.bootstrap == null) { + if(!this.disconnected) { + return; + } else { + throw new IllegalStateException("Session disconnected."); + } + } + + this.bootstrap.connect().syncUninterruptibly(); + this.bootstrap = null; + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public int getPort() { + return this.port; + } + + @Override + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + + @Override + public Map getFlags() { + return new HashMap(this.flags); + } + + @Override + public boolean hasFlag(String key) { + return this.getFlags().containsKey(key); + } + + @SuppressWarnings("unchecked") + @Override + public T getFlag(String key) { + Object value = this.getFlags().get(key); + if(value == null) { + return null; + } + + try { + return (T) value; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); + } + } + + @Override + public void setFlag(String key, Object value) { + this.flags.put(key, value); + } + + @Override + public List getListeners() { + return new ArrayList(this.listeners); + } + + @Override + public void addListener(SessionListener listener) { + this.listeners.add(listener); + } + + @Override + public void removeListener(SessionListener listener) { + this.listeners.remove(listener); + } + + @Override + public void callEvent(SessionEvent event) { + for(SessionListener listener : this.listeners) { + event.call(listener); + } + } + + @Override + public boolean isConnected() { + return this.channel != null && this.channel.isOpen() && !this.disconnected; + } + + @Override + public void send(final Packet packet) { + this.writing = true; + if(this.channel == null) { + this.writing = false; + return; + } + + this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if(!future.isSuccess()) { + exceptionCaught(null, future.cause()); + } + + writing = false; + callEvent(new PacketSentEvent(TcpSession.this, packet)); + } + }); + + if(packet.isPriority()) { + while(this.writing) { + try { + Thread.sleep(2); + } catch(InterruptedException e) { + } + } + } + } + + @Override + public void disconnect(String reason) { + if(this.disconnected) { + return; + } + + this.disconnected = true; + if(this.writing) { + while(this.writing) { + try { + Thread.sleep(2); + } catch(InterruptedException e) { + } + } + + try { + Thread.sleep(250); + } catch(InterruptedException e) { + } + } + + if(reason == null) { + reason = "Connection closed."; + } + + if(this.channel != null) { + if(this.channel.isOpen()) { + this.callEvent(new DisconnectingEvent(this, reason)); + } + + this.channel.close().syncUninterruptibly(); + } + + this.callEvent(new DisconnectedEvent(this, reason)); + if(this.group != null) { + this.group.shutdownGracefully(); + } + + this.channel = null; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + if(this.disconnected) { + ctx.channel().close().syncUninterruptibly(); + return; + } + + this.channel = ctx.channel(); + this.disconnected = false; + this.callEvent(new ConnectedEvent(this)); + new PacketHandleThread().start(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + this.disconnect("Connection closed."); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + this.writing = false; + if(!this.disconnected) { + if(cause instanceof ReadTimeoutException) { + this.disconnect("Connection timed out."); + } else { + this.disconnect("Internal exception: " + cause); + cause.printStackTrace(); + } + } + } + + @Override + protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { + if(!packet.isPriority()) { + this.packets.add(packet); + } + } + + private class PacketHandleThread extends Thread { + @Override + public void run() { + try { + while(!disconnected) { + while(packets.size() > 0) { + callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); + } + + try { + Thread.sleep(5); + } catch(InterruptedException e) { + } + } + } catch(Throwable t) { + try { + exceptionCaught(null, t); + } catch(Exception e) { + System.err.println("Exception while handling exception!"); + e.printStackTrace(); + } + } + } + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java similarity index 61% rename from src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java rename to src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java index 85bf0350..b3a7d379 100644 --- a/src/main/java/ch/spacebase/packetlib/netty/NettySessionFactory.java +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.netty; +package ch.spacebase.packetlib.tcp; import java.net.InetSocketAddress; @@ -7,6 +7,7 @@ import ch.spacebase.packetlib.ConnectionListener; import ch.spacebase.packetlib.Server; import ch.spacebase.packetlib.Session; import ch.spacebase.packetlib.SessionFactory; +import ch.spacebase.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -18,40 +19,48 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.timeout.ReadTimeoutHandler; -public class NettySessionFactory implements SessionFactory { +public class TcpSessionFactory implements SessionFactory { @Override public Session createClientSession(final Client client) { final EventLoopGroup group = new NioEventLoopGroup(); - return (NettySession) new Bootstrap().channel(NioSocketChannel.class).handler(new ChannelInitializer() { + final Bootstrap bootstrap = new Bootstrap().channel(NioSocketChannel.class); + final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap); + bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { - NettySession session = new NettySession(client.getHost(), client.getPort(), client.getPacketProtocol(), group); session.getPacketProtocol().newClientSession(client, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ch.pipeline() .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("codec", new PacketCodec(client.getPacketProtocol())) + .addLast("encryption", new TcpPacketEncryptor(session)) + .addLast("sizer", new TcpPacketSizer()) + .addLast("codec", new TcpPacketCodec(session)) .addLast("manager", session); } - }).group(group).remoteAddress(client.getHost(), client.getPort()).connect().syncUninterruptibly().channel().pipeline().get("manager"); + }).group(group).remoteAddress(client.getHost(), client.getPort()); + return session; + //.connect().syncUninterruptibly().channel().pipeline().get("manager"); } @Override public ConnectionListener createServerListener(final Server server) { final EventLoopGroup group = new NioEventLoopGroup(); - return new NettyConnectionListener(server.getHost(), server.getPort(), server.getPacketProtocol(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); - NettySession session = new NettyServerSession(address.getHostName(), address.getPort(), server.getPacketProtocol(), null, server); + PacketProtocol protocol = server.createPacketProtocol(); + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); session.getPacketProtocol().newServerSession(server, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ch.pipeline() .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("codec", new PacketCodec(server.getPacketProtocol())) + .addLast("encryption", new TcpPacketEncryptor(session)) + .addLast("sizer", new TcpPacketSizer()) + .addLast("codec", new TcpPacketCodec(session)) .addLast("manager", session); server.addSession(session); } diff --git a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java new file mode 100644 index 00000000..d354015f --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java @@ -0,0 +1,115 @@ +package ch.spacebase.packetlib.tcp.io; + +import io.netty.buffer.ByteBuf; + +import java.io.IOException; + +import ch.spacebase.packetlib.io.NetInput; + +/** + * A NetInput implementation using a ByteBuf as a backend. + */ +public class ByteBufNetInput implements NetInput { + + private ByteBuf buf; + + public ByteBufNetInput(ByteBuf buf) { + this.buf = buf; + } + + @Override + public boolean readBoolean() throws IOException { + return this.buf.readBoolean(); + } + + @Override + public byte readByte() throws IOException { + return this.buf.readByte(); + } + + @Override + public int readUnsignedByte() throws IOException { + return this.buf.readUnsignedByte(); + } + + @Override + public short readShort() throws IOException { + return this.buf.readShort(); + } + + @Override + public int readUnsignedShort() throws IOException { + return this.buf.readUnsignedShort(); + } + + @Override + public char readChar() throws IOException { + return this.buf.readChar(); + } + + @Override + public int readInt() throws IOException { + return this.buf.readInt(); + } + + @Override + public int readVarInt() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) != 0) { + value |= (b & 0x7F) << size; + size += 7; + if(size > 35) { + throw new IOException("Variable length quantity is too long (must be <= 35)"); + } + } + + return value | (b << size); + } + + @Override + public long readLong() throws IOException { + return this.buf.readLong(); + } + + @Override + public float readFloat() throws IOException { + return this.buf.readFloat(); + } + + @Override + public double readDouble() throws IOException { + return this.buf.readDouble(); + } + + @Override + public byte[] readPrefixedBytes() throws IOException { + short length = this.buf.readShort(); + return this.readBytes(length); + } + + @Override + public byte[] readBytes(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + byte b[] = new byte[length]; + this.buf.readBytes(b); + return b; + } + + @Override + public String readString() throws IOException { + int length = this.readVarInt(); + byte bytes[] = this.readBytes(length); + return new String(bytes, "UTF-8"); + } + + @Override + public int available() throws IOException { + return this.buf.readableBytes(); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java new file mode 100644 index 00000000..3e7548f8 --- /dev/null +++ b/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java @@ -0,0 +1,105 @@ +package ch.spacebase.packetlib.tcp.io; + +import io.netty.buffer.ByteBuf; + +import java.io.IOException; + +import ch.spacebase.packetlib.io.NetOutput; + +/** + * A NetOutput implementation using a ByteBuf as a backend. + */ +public class ByteBufNetOutput implements NetOutput { + + private ByteBuf buf; + + public ByteBufNetOutput(ByteBuf buf) { + this.buf = buf; + } + + @Override + public void writeBoolean(boolean b) throws IOException { + this.buf.writeBoolean(b); + } + + @Override + public void writeByte(int b) throws IOException { + this.buf.writeByte(b); + } + + @Override + public void writeShort(int s) throws IOException { + this.buf.writeShort(s); + } + + @Override + public void writeChar(int c) throws IOException { + this.buf.writeChar(c); + } + + @Override + public void writeInt(int i) throws IOException { + this.buf.writeInt(i); + } + + @Override + public void writeVarInt(int i) throws IOException { + while((i & 0xFFFFFF80) != 0L) { + this.writeByte((i & 0x7F) | 0x80); + i >>>= 7; + } + + this.writeByte(i & 0x7F); + } + + @Override + public void writeLong(long l) throws IOException { + this.buf.writeLong(l); + } + + @Override + public void writeFloat(float f) throws IOException { + this.buf.writeFloat(f); + } + + @Override + public void writeDouble(double d) throws IOException { + this.buf.writeDouble(d); + } + + @Override + public void writePrefixedBytes(byte b[]) throws IOException { + this.buf.writeShort(b.length); + this.buf.writeBytes(b); + } + + @Override + public void writeBytes(byte b[]) throws IOException { + this.buf.writeBytes(b); + } + + @Override + public void writeBytes(byte b[], int length) throws IOException { + this.buf.writeBytes(b, 0, length); + } + + @Override + public void writeString(String s) throws IOException { + if(s == null) { + throw new IllegalArgumentException("String cannot be null!"); + } + + byte[] bytes = s.getBytes("UTF-8"); + if(bytes.length > 32767) { + throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); + } else { + this.writeVarInt(bytes.length); + this.writeBytes(bytes); + } + } + + @Override + public void flush() throws IOException { + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java b/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java index ca930f38..f79b7a27 100644 --- a/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java +++ b/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java @@ -11,9 +11,9 @@ public class ClientSessionListener extends SessionAdapter { @Override public void packetReceived(PacketReceivedEvent event) { if(event.getPacket() instanceof PingPacket) { - PingPacket packet = (PingPacket) event.getPacket(); + PingPacket packet = event.getPacket(); System.out.println("CLIENT RECV: " + packet.getPingId()); - if(packet.getPingId() == 2345) { + if(packet.getPingId().equals("exit")) { event.getSession().disconnect("Finished"); } } @@ -21,8 +21,8 @@ public class ClientSessionListener extends SessionAdapter { @Override public void connected(ConnectedEvent event) { - event.getSession().send(new PingPacket(1043)); - event.getSession().send(new PingPacket(2345)); + event.getSession().send(new PingPacket("hello")); + event.getSession().send(new PingPacket("exit")); } @Override diff --git a/src/main/java/ch/spacebase/packetlib/test/PingPacket.java b/src/main/java/ch/spacebase/packetlib/test/PingPacket.java index 762f5a2d..331381ff 100644 --- a/src/main/java/ch/spacebase/packetlib/test/PingPacket.java +++ b/src/main/java/ch/spacebase/packetlib/test/PingPacket.java @@ -1,42 +1,40 @@ package ch.spacebase.packetlib.test; -import java.nio.ByteBuffer; +import java.io.IOException; +import ch.spacebase.packetlib.io.NetInput; +import ch.spacebase.packetlib.io.NetOutput; import ch.spacebase.packetlib.packet.Packet; public class PingPacket implements Packet { - private int id; + private String id; - public PingPacket() { + @SuppressWarnings("unused") + private PingPacket() { } - public PingPacket(int id) { + public PingPacket(String id) { this.id = id; } - public int getPingId() { + public String getPingId() { return this.id; } - + @Override - public int getId() { - return 0; + public void read(NetInput in) throws IOException { + this.id = in.readString(); } @Override - public int getLength() { - return 4; + public void write(NetOutput out) throws IOException { + out.writeString(this.id); } @Override - public void read(ByteBuffer in) { - this.id = in.getInt(); - } - - @Override - public void write(ByteBuffer out) { - out.putInt(this.id); + public boolean isPriority() { + return false; } } diff --git a/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java b/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java index a9e121af..d46941f3 100644 --- a/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java +++ b/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java @@ -1,14 +1,32 @@ package ch.spacebase.packetlib.test; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + import ch.spacebase.packetlib.Client; import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.netty.NettySessionFactory; +import ch.spacebase.packetlib.tcp.TcpSessionFactory; public class PingServerTest { public static void main(String[] args) { - new Server("127.0.0.1", 25565, new TestProtocol(), new NettySessionFactory()).bind(); - new Client("127.0.0.1", 25565, new TestProtocol(), new NettySessionFactory()).connect(); + SecretKey key = null; + try { + KeyGenerator gen = KeyGenerator.getInstance("AES"); + gen.init(128); + key = gen.generateKey(); + } catch(NoSuchAlgorithmException e) { + System.err.println("AES algorithm not supported, exiting..."); + return; + } + + Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()).bind(); + server.addListener(new ServerListener(key)); + + Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); + client.getSession().connect(); } } diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerListener.java b/src/main/java/ch/spacebase/packetlib/test/ServerListener.java index 47d68bf6..e3cbe5d7 100644 --- a/src/main/java/ch/spacebase/packetlib/test/ServerListener.java +++ b/src/main/java/ch/spacebase/packetlib/test/ServerListener.java @@ -1,5 +1,7 @@ package ch.spacebase.packetlib.test; +import javax.crypto.SecretKey; + import ch.spacebase.packetlib.event.server.ServerAdapter; import ch.spacebase.packetlib.event.server.ServerClosedEvent; import ch.spacebase.packetlib.event.server.ServerClosingEvent; @@ -8,6 +10,12 @@ import ch.spacebase.packetlib.event.server.SessionRemovedEvent; public class ServerListener extends ServerAdapter { + private SecretKey key; + + public ServerListener(SecretKey key) { + this.key = key; + } + @Override public void serverClosing(ServerClosingEvent event) { System.out.println("CLOSING SERVER..."); @@ -21,6 +29,7 @@ public class ServerListener extends ServerAdapter { @Override public void sessionAdded(SessionAddedEvent event) { System.out.println("SESSION ADDED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + ((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key); } @Override diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java b/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java index 129ec7c3..4e2dc853 100644 --- a/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java +++ b/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java @@ -10,7 +10,7 @@ public class ServerSessionListener extends SessionAdapter { @Override public void packetReceived(PacketReceivedEvent event) { if(event.getPacket() instanceof PingPacket) { - System.out.println("SERVER RECV: " + ((PingPacket) event.getPacket()).getPingId()); + System.out.println("SERVER RECV: " + event.getPacket().getPingId()); event.getSession().send(event.getPacket()); } } diff --git a/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java b/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java index 1628b8af..2f6d346d 100644 --- a/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java +++ b/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java @@ -1,25 +1,46 @@ package ch.spacebase.packetlib.test; +import java.security.GeneralSecurityException; + +import javax.crypto.SecretKey; + import ch.spacebase.packetlib.Client; import ch.spacebase.packetlib.Server; import ch.spacebase.packetlib.Session; +import ch.spacebase.packetlib.crypt.AESEncryption; +import ch.spacebase.packetlib.crypt.PacketEncryption; import ch.spacebase.packetlib.packet.PacketProtocol; public class TestProtocol extends PacketProtocol { - public TestProtocol() { - this.register(PingPacket.class); + private AESEncryption encrypt; + + @SuppressWarnings("unused") + private TestProtocol() { + } + + public TestProtocol(SecretKey key) { + this.setSecretKey(key); + } + + public void setSecretKey(SecretKey key) { + this.register(0, PingPacket.class); + try { + this.encrypt = new AESEncryption(key); + } catch(GeneralSecurityException e) { + e.printStackTrace(); + } + } + + @Override + public PacketEncryption getEncryption() { + return this.encrypt; } @Override public void newClientSession(Client client, Session session) { session.addListener(new ClientSessionListener()); } - - @Override - public void newServer(Server server) { - server.addListener(new ServerListener()); - } @Override public void newServerSession(Server server, Session session) { From eec5807cfa85f6c95e7325ca9a27714cf741524c Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 14 Dec 2013 17:03:25 -0800 Subject: [PATCH 003/180] Remove debug message --- src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java index 216d54f1..2a8d9e5e 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java @@ -33,7 +33,6 @@ public class TcpPacketCodec extends ByteToMessageCodec { NetInput in = new ByteBufNetInput(buf); int id = in.readVarInt(); Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); - System.out.println(packet.getClass()); packet.read(in); if(packet.isPriority()) { this.session.callEvent(new PacketReceivedEvent(this.session, packet)); From ee8a02ddc51bd69905818dd7203b0d9aa536b0e1 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 19 Dec 2013 17:18:04 -0800 Subject: [PATCH 004/180] Added link for downloading builds --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ddcc6348..593635a7 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ See ch.spacebase.packetlib.test.PingServerTest -------- PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. +You can also download a build [here](http://build.spacebase.ch/job/PacketLib/). License From a933383832123a7b49b51ae3078f186e1b20ed49 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 3 Jan 2014 13:08:54 -0800 Subject: [PATCH 005/180] Changed "Internal exception" disconnect message to be identifiable as the library --- src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java index d82b62c2..859c5efb 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java @@ -229,7 +229,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S if(cause instanceof ReadTimeoutException) { this.disconnect("Connection timed out."); } else { - this.disconnect("Internal exception: " + cause); + this.disconnect("Internal network exception: " + cause); cause.printStackTrace(); } } From 90a4170a562b9dab6233a0bcac855afcae44440d Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Tue, 7 Jan 2014 18:57:37 -0800 Subject: [PATCH 006/180] Add option to not wait for session to connect before returning, ensure that channel has been obtained before returning. --- .../java/ch/spacebase/packetlib/Session.java | 6 ++++++ .../spacebase/packetlib/tcp/TcpSession.java | 20 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/spacebase/packetlib/Session.java b/src/main/java/ch/spacebase/packetlib/Session.java index dc816cc0..9ce06090 100644 --- a/src/main/java/ch/spacebase/packetlib/Session.java +++ b/src/main/java/ch/spacebase/packetlib/Session.java @@ -18,6 +18,12 @@ public interface Session { */ public void connect(); + /** + * Connects this session to its host and port. + * @param wait Whether to wait for the connection to be established before returning. + */ + public void connect(boolean wait); + /** * Gets the host the session is connected to. * @return The connected host. diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java index 859c5efb..b5ed211f 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java +++ b/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java @@ -49,6 +49,11 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public void connect() { + this.connect(true); + } + + @Override + public void connect(boolean wait) { if(this.bootstrap == null) { if(!this.disconnected) { return; @@ -57,8 +62,17 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } - this.bootstrap.connect().syncUninterruptibly(); + ChannelFuture future = this.bootstrap.connect(); this.bootstrap = null; + if(wait) { + future.syncUninterruptibly(); + while(this.channel == null && !this.disconnected) { + try { + Thread.sleep(5); + } catch(InterruptedException e) { + } + } + } } @Override @@ -229,10 +243,12 @@ public class TcpSession extends SimpleChannelInboundHandler implements S if(cause instanceof ReadTimeoutException) { this.disconnect("Connection timed out."); } else { - this.disconnect("Internal network exception: " + cause); + this.disconnect("Internal network exception: " + cause.toString()); cause.printStackTrace(); } } + + this.disconnected = true; } @Override From 67d531f598749bef9796fa591b8fa0e4d166662c Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 30 Jan 2014 20:16:59 -0800 Subject: [PATCH 007/180] Moved test classes out of source folder and into example folder. --- README.md | 2 +- .../ch/spacebase/packetlib/test/ClientSessionListener.java | 0 .../ch/spacebase/packetlib/test/PingPacket.java | 0 .../ch/spacebase/packetlib/test/PingServerTest.java | 0 .../ch/spacebase/packetlib/test/ServerListener.java | 0 .../ch/spacebase/packetlib/test/ServerSessionListener.java | 0 .../ch/spacebase/packetlib/test/TestProtocol.java | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename {src/main/java => example}/ch/spacebase/packetlib/test/ClientSessionListener.java (100%) rename {src/main/java => example}/ch/spacebase/packetlib/test/PingPacket.java (100%) rename {src/main/java => example}/ch/spacebase/packetlib/test/PingServerTest.java (100%) rename {src/main/java => example}/ch/spacebase/packetlib/test/ServerListener.java (100%) rename {src/main/java => example}/ch/spacebase/packetlib/test/ServerSessionListener.java (100%) rename {src/main/java => example}/ch/spacebase/packetlib/test/TestProtocol.java (100%) diff --git a/README.md b/README.md index 593635a7..d0d2923f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ PacketLib is a library for networking between clients and servers with packets. Test Example -------- -See ch.spacebase.packetlib.test.PingServerTest +See examples/ch/spacebase/packetlib/test/PingServerTest.java Building the Source diff --git a/src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java b/example/ch/spacebase/packetlib/test/ClientSessionListener.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/ClientSessionListener.java rename to example/ch/spacebase/packetlib/test/ClientSessionListener.java diff --git a/src/main/java/ch/spacebase/packetlib/test/PingPacket.java b/example/ch/spacebase/packetlib/test/PingPacket.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/PingPacket.java rename to example/ch/spacebase/packetlib/test/PingPacket.java diff --git a/src/main/java/ch/spacebase/packetlib/test/PingServerTest.java b/example/ch/spacebase/packetlib/test/PingServerTest.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/PingServerTest.java rename to example/ch/spacebase/packetlib/test/PingServerTest.java diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerListener.java b/example/ch/spacebase/packetlib/test/ServerListener.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/ServerListener.java rename to example/ch/spacebase/packetlib/test/ServerListener.java diff --git a/src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java b/example/ch/spacebase/packetlib/test/ServerSessionListener.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/ServerSessionListener.java rename to example/ch/spacebase/packetlib/test/ServerSessionListener.java diff --git a/src/main/java/ch/spacebase/packetlib/test/TestProtocol.java b/example/ch/spacebase/packetlib/test/TestProtocol.java similarity index 100% rename from src/main/java/ch/spacebase/packetlib/test/TestProtocol.java rename to example/ch/spacebase/packetlib/test/TestProtocol.java From e19e1a44e97a2ee13677af90804bbe4d538e7cd9 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 1 Mar 2014 16:47:03 -0800 Subject: [PATCH 008/180] Refactored ch.spacebase to org.spacehq, reformatted code and line endings. --- .gitignore | 6 +- LICENSE.txt | 2 +- README.md | 4 +- .../packetlib/test/ClientSessionListener.java | 8 +- .../spacehq}/packetlib/test/PingPacket.java | 16 +- .../packetlib/test/PingServerTest.java | 13 +- .../packetlib/test/ServerListener.java | 14 +- .../packetlib/test/ServerSessionListener.java | 10 +- .../spacehq}/packetlib/test/TestProtocol.java | 27 ++- pom.xml | 206 +++++++++--------- .../packetlib/tcp/TcpSessionFactory.java | 70 ------ .../spacehq}/packetlib/Client.java | 18 +- .../packetlib/ConnectionListener.java | 13 +- .../spacehq}/packetlib/Server.java | 79 ++++--- .../spacehq}/packetlib/Session.java | 59 +++-- .../spacehq}/packetlib/SessionFactory.java | 8 +- .../packetlib/crypt/AESEncryption.java | 15 +- .../packetlib/crypt/PacketEncryption.java | 30 +-- .../packetlib/event/server/ServerAdapter.java | 2 +- .../event/server/ServerBoundEvent.java | 11 +- .../event/server/ServerClosedEvent.java | 11 +- .../event/server/ServerClosingEvent.java | 11 +- .../packetlib/event/server/ServerEvent.java | 5 +- .../event/server/ServerListener.java | 15 +- .../event/server/SessionAddedEvent.java | 16 +- .../event/server/SessionRemovedEvent.java | 16 +- .../event/session/ConnectedEvent.java | 11 +- .../event/session/DisconnectedEvent.java | 14 +- .../event/session/DisconnectingEvent.java | 14 +- .../event/session/PacketReceivedEvent.java | 16 +- .../event/session/PacketSentEvent.java | 16 +- .../event/session/SessionAdapter.java | 2 +- .../packetlib/event/session/SessionEvent.java | 5 +- .../event/session/SessionListener.java | 17 +- .../spacehq}/packetlib/io/NetInput.java | 49 +++-- .../spacehq}/packetlib/io/NetOutput.java | 52 +++-- .../packetlib/io/stream/StreamNetInput.java | 12 +- .../packetlib/io/stream/StreamNetOutput.java | 10 +- .../spacehq}/packetlib/packet/Packet.java | 15 +- .../packetlib/packet/PacketProtocol.java | 60 ++--- .../packetlib/tcp/TcpConnectionListener.java | 18 +- .../packetlib/tcp/TcpPacketCodec.java | 30 +-- .../packetlib/tcp/TcpPacketEncryptor.java | 8 +- .../packetlib/tcp/TcpPacketSizer.java | 12 +- .../packetlib/tcp/TcpServerSession.java | 28 +-- .../spacehq}/packetlib/tcp/TcpSession.java | 165 +++++++------- .../packetlib/tcp/TcpSessionFactory.java | 66 ++++++ .../packetlib/tcp/io/ByteBufNetInput.java | 11 +- .../packetlib/tcp/io/ByteBufNetOutput.java | 9 +- 49 files changed, 704 insertions(+), 621 deletions(-) rename example/{ch/spacebase => org/spacehq}/packetlib/test/ClientSessionListener.java (70%) rename example/{ch/spacebase => org/spacehq}/packetlib/test/PingPacket.java (74%) rename example/{ch/spacebase => org/spacehq}/packetlib/test/PingServerTest.java (81%) rename example/{ch/spacebase => org/spacehq}/packetlib/test/ServerListener.java (71%) rename example/{ch/spacebase => org/spacehq}/packetlib/test/ServerSessionListener.java (67%) rename example/{ch/spacebase => org/spacehq}/packetlib/test/TestProtocol.java (72%) delete mode 100644 src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/Client.java (90%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/ConnectionListener.java (91%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/Server.java (90%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/Session.java (88%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/SessionFactory.java (91%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/crypt/AESEncryption.java (96%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/crypt/PacketEncryption.java (64%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerAdapter.java (91%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerBoundEvent.java (83%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerClosedEvent.java (82%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerClosingEvent.java (83%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerEvent.java (80%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/ServerListener.java (92%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/SessionAddedEvent.java (83%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/server/SessionRemovedEvent.java (83%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/ConnectedEvent.java (82%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/DisconnectedEvent.java (87%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/DisconnectingEvent.java (87%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/PacketReceivedEvent.java (87%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/PacketSentEvent.java (87%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/SessionAdapter.java (90%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/SessionEvent.java (80%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/event/session/SessionListener.java (92%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/io/NetInput.java (70%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/io/NetOutput.java (67%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/io/stream/StreamNetInput.java (97%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/io/stream/StreamNetOutput.java (96%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/packet/Packet.java (83%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/packet/PacketProtocol.java (85%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpConnectionListener.java (89%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpPacketCodec.java (71%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpPacketEncryptor.java (96%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpPacketSizer.java (91%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpServerSession.java (67%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/TcpSession.java (68%) create mode 100644 src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/io/ByteBufNetInput.java (96%) rename src/main/java/{ch/spacebase => org/spacehq}/packetlib/tcp/io/ByteBufNetOutput.java (95%) diff --git a/.gitignore b/.gitignore index 6ca7485c..13f68391 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ bin lib + .settings .classpath .project -.git + +*.iml +.idea + target diff --git a/LICENSE.txt b/LICENSE.txt index ff34e2af..cff88880 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2013 Steveice10 +Copyright (C) 2013-2014 Steveice10 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index d0d2923f..f6331df2 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ PacketLib is a library for networking between clients and servers with packets. Test Example -------- -See examples/ch/spacebase/packetlib/test/PingServerTest.java +See examples/org/spacehq/packetlib/test/PingServerTest.java Building the Source -------- PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -You can also download a build [here](http://build.spacebase.ch/job/PacketLib/). +You can also download a build [here](http://build.spacehq.org/job/PacketLib/). License diff --git a/example/ch/spacebase/packetlib/test/ClientSessionListener.java b/example/org/spacehq/packetlib/test/ClientSessionListener.java similarity index 70% rename from example/ch/spacebase/packetlib/test/ClientSessionListener.java rename to example/org/spacehq/packetlib/test/ClientSessionListener.java index f79b7a27..8ba28636 100644 --- a/example/ch/spacebase/packetlib/test/ClientSessionListener.java +++ b/example/org/spacehq/packetlib/test/ClientSessionListener.java @@ -1,10 +1,6 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; -import ch.spacebase.packetlib.event.session.ConnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectingEvent; -import ch.spacebase.packetlib.event.session.PacketReceivedEvent; -import ch.spacebase.packetlib.event.session.SessionAdapter; +import org.spacehq.packetlib.event.session.*; public class ClientSessionListener extends SessionAdapter { diff --git a/example/ch/spacebase/packetlib/test/PingPacket.java b/example/org/spacehq/packetlib/test/PingPacket.java similarity index 74% rename from example/ch/spacebase/packetlib/test/PingPacket.java rename to example/org/spacehq/packetlib/test/PingPacket.java index 331381ff..428e61d0 100644 --- a/example/ch/spacebase/packetlib/test/PingPacket.java +++ b/example/org/spacehq/packetlib/test/PingPacket.java @@ -1,23 +1,23 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; + +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; +import org.spacehq.packetlib.packet.Packet; import java.io.IOException; -import ch.spacebase.packetlib.io.NetInput; -import ch.spacebase.packetlib.io.NetOutput; -import ch.spacebase.packetlib.packet.Packet; - public class PingPacket implements Packet { private String id; - + @SuppressWarnings("unused") private PingPacket() { } - + public PingPacket(String id) { this.id = id; } - + public String getPingId() { return this.id; } diff --git a/example/ch/spacebase/packetlib/test/PingServerTest.java b/example/org/spacehq/packetlib/test/PingServerTest.java similarity index 81% rename from example/ch/spacebase/packetlib/test/PingServerTest.java rename to example/org/spacehq/packetlib/test/PingServerTest.java index d46941f3..41c5c6d5 100644 --- a/example/ch/spacebase/packetlib/test/PingServerTest.java +++ b/example/org/spacehq/packetlib/test/PingServerTest.java @@ -1,13 +1,12 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; -import java.security.NoSuchAlgorithmException; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.tcp.TcpSessionFactory; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; - -import ch.spacebase.packetlib.Client; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.tcp.TcpSessionFactory; +import java.security.NoSuchAlgorithmException; public class PingServerTest { @@ -24,7 +23,7 @@ public class PingServerTest { Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()).bind(); server.addListener(new ServerListener(key)); - + Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); client.getSession().connect(); } diff --git a/example/ch/spacebase/packetlib/test/ServerListener.java b/example/org/spacehq/packetlib/test/ServerListener.java similarity index 71% rename from example/ch/spacebase/packetlib/test/ServerListener.java rename to example/org/spacehq/packetlib/test/ServerListener.java index e3cbe5d7..6d70dead 100644 --- a/example/ch/spacebase/packetlib/test/ServerListener.java +++ b/example/org/spacehq/packetlib/test/ServerListener.java @@ -1,21 +1,17 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; + +import org.spacehq.packetlib.event.server.*; import javax.crypto.SecretKey; -import ch.spacebase.packetlib.event.server.ServerAdapter; -import ch.spacebase.packetlib.event.server.ServerClosedEvent; -import ch.spacebase.packetlib.event.server.ServerClosingEvent; -import ch.spacebase.packetlib.event.server.SessionAddedEvent; -import ch.spacebase.packetlib.event.server.SessionRemovedEvent; - public class ServerListener extends ServerAdapter { private SecretKey key; - + public ServerListener(SecretKey key) { this.key = key; } - + @Override public void serverClosing(ServerClosingEvent event) { System.out.println("CLOSING SERVER..."); diff --git a/example/ch/spacebase/packetlib/test/ServerSessionListener.java b/example/org/spacehq/packetlib/test/ServerSessionListener.java similarity index 67% rename from example/ch/spacebase/packetlib/test/ServerSessionListener.java rename to example/org/spacehq/packetlib/test/ServerSessionListener.java index 4e2dc853..73b51d2c 100644 --- a/example/ch/spacebase/packetlib/test/ServerSessionListener.java +++ b/example/org/spacehq/packetlib/test/ServerSessionListener.java @@ -1,9 +1,9 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; -import ch.spacebase.packetlib.event.session.DisconnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectingEvent; -import ch.spacebase.packetlib.event.session.PacketReceivedEvent; -import ch.spacebase.packetlib.event.session.SessionAdapter; +import org.spacehq.packetlib.event.session.DisconnectedEvent; +import org.spacehq.packetlib.event.session.DisconnectingEvent; +import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.event.session.SessionAdapter; public class ServerSessionListener extends SessionAdapter { diff --git a/example/ch/spacebase/packetlib/test/TestProtocol.java b/example/org/spacehq/packetlib/test/TestProtocol.java similarity index 72% rename from example/ch/spacebase/packetlib/test/TestProtocol.java rename to example/org/spacehq/packetlib/test/TestProtocol.java index 2f6d346d..e644b2f5 100644 --- a/example/ch/spacebase/packetlib/test/TestProtocol.java +++ b/example/org/spacehq/packetlib/test/TestProtocol.java @@ -1,28 +1,27 @@ -package ch.spacebase.packetlib.test; +package org.spacehq.packetlib.test; -import java.security.GeneralSecurityException; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.crypt.AESEncryption; +import org.spacehq.packetlib.crypt.PacketEncryption; +import org.spacehq.packetlib.packet.PacketProtocol; import javax.crypto.SecretKey; - -import ch.spacebase.packetlib.Client; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.crypt.AESEncryption; -import ch.spacebase.packetlib.crypt.PacketEncryption; -import ch.spacebase.packetlib.packet.PacketProtocol; +import java.security.GeneralSecurityException; public class TestProtocol extends PacketProtocol { private AESEncryption encrypt; - + @SuppressWarnings("unused") private TestProtocol() { } - + public TestProtocol(SecretKey key) { this.setSecretKey(key); } - + public void setSecretKey(SecretKey key) { this.register(0, PingPacket.class); try { @@ -31,12 +30,12 @@ public class TestProtocol extends PacketProtocol { e.printStackTrace(); } } - + @Override public PacketEncryption getEncryption() { return this.encrypt; } - + @Override public void newClientSession(Client client, Session session) { session.addListener(new ClientSessionListener()); diff --git a/pom.xml b/pom.xml index 6e4def15..93eced0a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,115 +1,115 @@ - 4.0.0 - ch.spacebase - packetlib - 1.0-SNAPSHOT - jar + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + org.spacehq + packetlib + 1.0-SNAPSHOT + jar - PacketLib - A library for networking between a client and a server with packets. - http://github.com/Steveice10/PacketLib/ + PacketLib + A library for networking between a client and a server with packets. + http://github.com/Steveice10/PacketLib/ - - - MIT - http://www.opensource.org/licenses/mit-license.html - repo - - + + + MIT + http://www.opensource.org/licenses/mit-license.html + repo + + - - scm:git:git@github.com:Steveice10/PacketLib.git - scm:git:git@github.com:Steveice10/PacketLib.git - git@github.com:Steveice10/PacketLib/ - + + scm:git:git@github.com:Steveice10/PacketLib.git + scm:git:git@github.com:Steveice10/PacketLib.git + git@github.com:Steveice10/PacketLib/ + - - - spacebase - spacebase-releases - http://repo.spacebase.ch/content/repositories/release/ - - - spacebase - spacebase-snapshots - http://repo.spacebase.ch/content/repositories/snapshots/ - - + + + spacehq + spacehq-releases + http://repo.spacehq.org/content/repositories/release/ + + + spacehq + spacehq-snapshots + http://repo.spacehq.org/content/repositories/snapshots/ + + - - - steveice10 - Steveice10 - Steveice10@gmail.com - - + + + steveice10 + Steveice10 + Steveice10@gmail.com + + - - UTF-8 - + + UTF-8 + - - - spacebase-releases - http://repo.spacebase.ch/content/repositories/release/ - - - spacebase-snapshots - http://repo.spacebase.ch/content/repositories/snapshots/ - - + + + spacehq-releases + http://repo.spacehq.org/content/repositories/release/ + + + spacehq-snapshots + http://repo.spacehq.org/content/repositories/snapshots/ + + - - - io.netty - netty-all - 5.0.0.Alpha1 - - + + + io.netty + netty-all + 5.0.0.Alpha1 + + - - clean install - ${basedir}/src/main/java - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - - - org.apache.maven.plugins - maven-jar-plugin - 2.3.2 - - - - org.apache.maven.plugins - maven-shade-plugin - 1.5 - - - package - - shade - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - + + clean install + ${basedir}/src/main/java + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.5 + + + package + + shade + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java b/src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java deleted file mode 100644 index b3a7d379..00000000 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpSessionFactory.java +++ /dev/null @@ -1,70 +0,0 @@ -package ch.spacebase.packetlib.tcp; - -import java.net.InetSocketAddress; - -import ch.spacebase.packetlib.Client; -import ch.spacebase.packetlib.ConnectionListener; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.SessionFactory; -import ch.spacebase.packetlib.packet.PacketProtocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.timeout.ReadTimeoutHandler; - -public class TcpSessionFactory implements SessionFactory { - - @Override - public Session createClientSession(final Client client) { - final EventLoopGroup group = new NioEventLoopGroup(); - final Bootstrap bootstrap = new Bootstrap().channel(NioSocketChannel.class); - final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap); - bootstrap.handler(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - session.getPacketProtocol().newClientSession(client, session); - ch.config().setOption(ChannelOption.IP_TOS, 0x18); - ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ch.pipeline() - .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer()) - .addLast("codec", new TcpPacketCodec(session)) - .addLast("manager", session); - } - }).group(group).remoteAddress(client.getHost(), client.getPort()); - return session; - //.connect().syncUninterruptibly().channel().pipeline().get("manager"); - } - - @Override - public ConnectionListener createServerListener(final Server server) { - final EventLoopGroup group = new NioEventLoopGroup(); - return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); - PacketProtocol protocol = server.createPacketProtocol(); - TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); - session.getPacketProtocol().newServerSession(server, session); - ch.config().setOption(ChannelOption.IP_TOS, 0x18); - ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ch.pipeline() - .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer()) - .addLast("codec", new TcpPacketCodec(session)) - .addLast("manager", session); - server.addSession(session); - } - }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); - } - -} diff --git a/src/main/java/ch/spacebase/packetlib/Client.java b/src/main/java/org/spacehq/packetlib/Client.java similarity index 90% rename from src/main/java/ch/spacebase/packetlib/Client.java rename to src/main/java/org/spacehq/packetlib/Client.java index 521af6b0..4207abba 100644 --- a/src/main/java/ch/spacebase/packetlib/Client.java +++ b/src/main/java/org/spacehq/packetlib/Client.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib; +package org.spacehq.packetlib; -import ch.spacebase.packetlib.packet.PacketProtocol; +import org.spacehq.packetlib.packet.PacketProtocol; /** * A client that may connect to a server. @@ -11,16 +11,17 @@ public class Client { private int port; private PacketProtocol protocol; private Session session; - + public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { this.host = host; this.port = port; this.protocol = protocol; this.session = factory.createClientSession(this); } - + /** * Gets the host the client is connecting to. + * * @return The host the client is connecting to. */ public String getHost() { @@ -29,26 +30,29 @@ public class Client { /** * Gets the port the client is connecting to. + * * @return The port the client is connecting to. */ public int getPort() { return this.port; } - + /** * Gets the packet protocol of the client. + * * @return The client's packet protocol. */ public PacketProtocol getPacketProtocol() { return this.protocol; } - + /** * Gets the session of the client. + * * @return The client's session. */ public Session getSession() { return this.session; } - + } diff --git a/src/main/java/ch/spacebase/packetlib/ConnectionListener.java b/src/main/java/org/spacehq/packetlib/ConnectionListener.java similarity index 91% rename from src/main/java/ch/spacebase/packetlib/ConnectionListener.java rename to src/main/java/org/spacehq/packetlib/ConnectionListener.java index 16761050..9113bb2a 100644 --- a/src/main/java/ch/spacebase/packetlib/ConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/ConnectionListener.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib; +package org.spacehq.packetlib; /** * A listener for new sessions on a host and port. @@ -7,25 +7,28 @@ public interface ConnectionListener { /** * Gets the host the session is listening on. + * * @return The listening host. */ public String getHost(); - + /** * Gets the port the session is listening on. + * * @return The listening port. */ public int getPort(); - + /** * Returns true if the listener is listening. + * * @return True if the listener is listening. */ public boolean isListening(); - + /** * Closes the listener. */ public void close(); - + } diff --git a/src/main/java/ch/spacebase/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java similarity index 90% rename from src/main/java/ch/spacebase/packetlib/Server.java rename to src/main/java/org/spacehq/packetlib/Server.java index be419679..315c765d 100644 --- a/src/main/java/ch/spacebase/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -1,4 +1,7 @@ -package ch.spacebase.packetlib; +package org.spacehq.packetlib; + +import org.spacehq.packetlib.event.server.*; +import org.spacehq.packetlib.packet.PacketProtocol; import java.lang.reflect.Constructor; import java.util.ArrayList; @@ -6,15 +9,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import ch.spacebase.packetlib.event.server.ServerBoundEvent; -import ch.spacebase.packetlib.event.server.ServerClosedEvent; -import ch.spacebase.packetlib.event.server.ServerClosingEvent; -import ch.spacebase.packetlib.event.server.ServerEvent; -import ch.spacebase.packetlib.event.server.ServerListener; -import ch.spacebase.packetlib.event.server.SessionAddedEvent; -import ch.spacebase.packetlib.event.server.SessionRemovedEvent; -import ch.spacebase.packetlib.packet.PacketProtocol; - /** * A server that listens on a given host and port. */ @@ -26,19 +20,20 @@ public class Server { private SessionFactory factory; private ConnectionListener listener; private List sessions = new ArrayList(); - + private Map flags = new HashMap(); private List listeners = new ArrayList(); - + public Server(String host, int port, Class protocol, SessionFactory factory) { this.host = host; this.port = port; this.protocol = protocol; this.factory = factory; } - + /** * Binds and initializes the server. + * * @return The server after being bound. */ public Server bind() { @@ -46,9 +41,10 @@ public class Server { this.callEvent(new ServerBoundEvent(this)); return this; } - + /** * Gets the host this server is bound to. + * * @return The server's host. */ public String getHost() { @@ -57,22 +53,25 @@ public class Server { /** * Gets the port this server is bound to. + * * @return The server's port. */ public int getPort() { return this.port; } - + /** * Gets the packet protocol of the server. + * * @return The server's packet protocol. */ public Class getPacketProtocol() { return this.protocol; } - + /** * Creates a new packet protocol instance from this server's protocol class. + * * @return The created protocol instance. * @throws IllegalStateException If the protocol does not have a no-params constructor or cannot be instantiated. */ @@ -82,7 +81,7 @@ public class Server { if(!constructor.isAccessible()) { constructor.setAccessible(true); } - + return constructor.newInstance(); } catch(NoSuchMethodError e) { throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); @@ -90,28 +89,31 @@ public class Server { throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); } } - + /** * Gets this server's set flags. + * * @return This server's flags. */ public Map getGlobalFlags() { return new HashMap(this.flags); } - + /** * Checks whether this server has a flag set. + * * @param key Key of the flag to check for. * @return Whether this server has a flag set. */ public boolean hasGlobalFlag(String key) { return this.flags.containsKey(key); } - + /** * Gets the value of the given flag as an instance of the given type. If this * session belongs to a server, the server's flags will be checked for the flag * as well. + * * @param key Key of the flag. * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. @@ -122,50 +124,55 @@ public class Server { if(value == null) { return null; } - + try { return (T) value; } catch(ClassCastException e) { throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); } } - + /** * Sets the value of a flag. The flag will be used in sessions if a session does * not contain a value for the flag. - * @param key Key of the flag. + * + * @param key Key of the flag. * @param value Value to set the flag to. */ public void setGlobalFlag(String key, Object value) { this.flags.put(key, value); } - + /** * Gets the listeners listening on this session. + * * @return This server's listeners. */ public List getListeners() { return new ArrayList(this.listeners); } - + /** * Adds a listener to this server. + * * @param listener Listener to add. */ public void addListener(ServerListener listener) { this.listeners.add(listener); } - + /** * Removes a listener from this server. + * * @param listener Listener to remove. */ public void removeListener(ServerListener listener) { this.listeners.remove(listener); } - + /** * Calls an event on the listeners of this server. + * * @param event Event to call. */ public void callEvent(ServerEvent event) { @@ -173,26 +180,29 @@ public class Server { event.call(listener); } } - + /** * Gets all sessions belonging to this server. + * * @return Sessions belonging to this server. */ public List getSessions() { return new ArrayList(this.sessions); } - + /** * Adds the given session to this server. + * * @param session Session to add. */ public void addSession(Session session) { this.sessions.add(session); this.callEvent(new SessionAddedEvent(this, session)); } - + /** * Removes the given session from this server. + * * @param session Session to remove. */ public void removeSession(Session session) { @@ -200,18 +210,19 @@ public class Server { if(session.isConnected()) { session.disconnect("Connection closed."); } - + this.callEvent(new SessionRemovedEvent(this, session)); } - + /** * Gets whether the server is listening. + * * @return Whether the server is listening. */ public boolean isListening() { return this.listener.isListening(); } - + /** * Closes the server. */ @@ -226,7 +237,7 @@ public class Server { session.disconnect("Server closed."); } } - + listener.close(); callEvent(new ServerClosedEvent(Server.this)); } diff --git a/src/main/java/ch/spacebase/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java similarity index 88% rename from src/main/java/ch/spacebase/packetlib/Session.java rename to src/main/java/org/spacehq/packetlib/Session.java index 9ce06090..905b9069 100644 --- a/src/main/java/ch/spacebase/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -1,13 +1,13 @@ -package ch.spacebase.packetlib; +package org.spacehq.packetlib; + +import org.spacehq.packetlib.event.session.SessionEvent; +import org.spacehq.packetlib.event.session.SessionListener; +import org.spacehq.packetlib.packet.Packet; +import org.spacehq.packetlib.packet.PacketProtocol; import java.util.List; import java.util.Map; -import ch.spacebase.packetlib.event.session.SessionEvent; -import ch.spacebase.packetlib.event.session.SessionListener; -import ch.spacebase.packetlib.packet.Packet; -import ch.spacebase.packetlib.packet.PacketProtocol; - /** * A network session. */ @@ -17,102 +17,117 @@ public interface Session { * Connects this session to its host and port. */ public void connect(); - + /** * Connects this session to its host and port. + * * @param wait Whether to wait for the connection to be established before returning. */ public void connect(boolean wait); - + /** * Gets the host the session is connected to. + * * @return The connected host. */ public String getHost(); - + /** * Gets the port the session is connected to. + * * @return The connected port. */ public int getPort(); - + /** * Gets the packet protocol of the session. + * * @return The session's packet protocol. */ public PacketProtocol getPacketProtocol(); - + /** * Gets this session's set flags. If this session belongs to a server, the server's * flags will be included in the results. + * * @return This session's flags. */ public Map getFlags(); - + /** * Checks whether this session has a flag set. If this session belongs to a server, * the server's flags will also be checked. + * * @param key Key of the flag to check for. * @return Whether this session has a flag set. */ public boolean hasFlag(String key); - + /** * Gets the value of the given flag as an instance of the given type. If this * session belongs to a server, the server's flags will be checked for the flag * as well. + * * @param key Key of the flag. * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. */ public T getFlag(String key); - + /** * Sets the value of a flag. This does not change a server's flags if this session * belongs to a server. - * @param key Key of the flag. + * + * @param key Key of the flag. * @param value Value to set the flag to. */ public void setFlag(String key, Object value); - + /** * Gets the listeners listening on this session. + * * @return This session's listeners. */ public List getListeners(); - + /** * Adds a listener to this session. + * * @param listener Listener to add. */ public void addListener(SessionListener listener); - + /** * Removes a listener from this session. + * * @param listener Listener to remove. */ public void removeListener(SessionListener listener); - + /** * Calls an event on the listeners of this session. + * * @param event Event to call. */ public void callEvent(SessionEvent event); - + /** * Returns true if the session is connected. + * * @return True if the session is connected. */ public boolean isConnected(); - + /** * Sends a packet. + * * @param packet Packet to send. */ public void send(Packet packet); - + /** * Disconnects the session. + * * @param reason Reason for disconnecting. */ public void disconnect(String reason); diff --git a/src/main/java/ch/spacebase/packetlib/SessionFactory.java b/src/main/java/org/spacehq/packetlib/SessionFactory.java similarity index 91% rename from src/main/java/ch/spacebase/packetlib/SessionFactory.java rename to src/main/java/org/spacehq/packetlib/SessionFactory.java index ce5ad827..f38cb626 100644 --- a/src/main/java/ch/spacebase/packetlib/SessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/SessionFactory.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib; +package org.spacehq.packetlib; /** * A factory for creating sessions. @@ -7,16 +7,18 @@ public interface SessionFactory { /** * Creates a client session. + * * @param host Host to connect to. * @param port Port to connect to. * @return The created session. */ public Session createClientSession(Client client); - + /** * Initializes the factory for creating server sessions. + * * @param server Server to initialize for. */ public ConnectionListener createServerListener(Server server); - + } diff --git a/src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java b/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java similarity index 96% rename from src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java rename to src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java index a3db36f8..e5c8a20a 100644 --- a/src/main/java/ch/spacebase/packetlib/crypt/AESEncryption.java +++ b/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java @@ -1,10 +1,9 @@ -package ch.spacebase.packetlib.crypt; - -import java.security.GeneralSecurityException; -import java.security.Key; +package org.spacehq.packetlib.crypt; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; +import java.security.GeneralSecurityException; +import java.security.Key; /** * An encryption implementation using "AES/CFB8/NoPadding" encryption. @@ -13,24 +12,24 @@ public class AESEncryption implements PacketEncryption { private Cipher inCipher; private Cipher outCipher; - + public AESEncryption(Key key) throws GeneralSecurityException { this.inCipher = Cipher.getInstance("AES/CFB8/NoPadding"); this.inCipher.init(2, key, new IvParameterSpec(key.getEncoded())); this.outCipher = Cipher.getInstance("AES/CFB8/NoPadding"); this.outCipher.init(1, key, new IvParameterSpec(key.getEncoded())); } - + @Override public int getDecryptOutputSize(int length) { return this.inCipher.getOutputSize(length); } - + @Override public int getEncryptOutputSize(int length) { return this.outCipher.getOutputSize(length); } - + @Override public int decrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { return this.inCipher.update(input, inputOffset, inputLength, output, outputOffset); diff --git a/src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java similarity index 64% rename from src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java rename to src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java index 836e500d..78014060 100644 --- a/src/main/java/ch/spacebase/packetlib/crypt/PacketEncryption.java +++ b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.crypt; +package org.spacehq.packetlib.crypt; /** * An interface for encrypting packets. @@ -7,36 +7,40 @@ public interface PacketEncryption { /** * Gets the output size from decrypting. + * * @param length Length of the data being decrypted. */ public int getDecryptOutputSize(int length); - + /** * Gets the output size from encrypting. + * * @param length Length of the data being encrypted. */ public int getEncryptOutputSize(int length); - + /** * Decrypts the given data. - * @param input Input data to decrypt. - * @param inputOffset Offset of the data to start decrypting at. - * @param inputLength Length of the data to be decrypted. - * @param output Array to output decrypted data to. + * + * @param input Input data to decrypt. + * @param inputOffset Offset of the data to start decrypting at. + * @param inputLength Length of the data to be decrypted. + * @param output Array to output decrypted data to. * @param outputOffset Offset of the output array to start at. * @return The number of bytes stored in the output array. */ public int decrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; - + /** * Encrypts the given data. - * @param input Input data to encrypt. - * @param inputOffset Offset of the data to start encrypting at. - * @param inputLength Length of the data to be encrypted. - * @param output Array to output encrypted data to. + * + * @param input Input data to encrypt. + * @param inputOffset Offset of the data to start encrypting at. + * @param inputLength Length of the data to be encrypted. + * @param output Array to output encrypted data to. * @param outputOffset Offset of the output array to start at. * @return The number of bytes stored in the output array. */ public int encrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; - + } diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java b/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java similarity index 91% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java index e6d2d67f..c2b996ad 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerAdapter.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; /** * An adapter for picking server events to listen for. diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java similarity index 83% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java index d2a6e043..5661f72d 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerBoundEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; -import ch.spacebase.packetlib.Server; +import org.spacehq.packetlib.Server; /** * Called when the server is bound to its host and port. @@ -8,19 +8,20 @@ import ch.spacebase.packetlib.Server; public class ServerBoundEvent implements ServerEvent { private Server server; - + public ServerBoundEvent(Server server) { this.server = server; } - + /** * Gets the server involved in this event. + * * @return The event's server. */ public Server getServer() { return this.server; } - + @Override public void call(ServerListener listener) { listener.serverBound(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java similarity index 82% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java index 445d8234..909c8e8c 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; -import ch.spacebase.packetlib.Server; +import org.spacehq.packetlib.Server; /** * Called when the server is closed. @@ -8,19 +8,20 @@ import ch.spacebase.packetlib.Server; public class ServerClosedEvent implements ServerEvent { private Server server; - + public ServerClosedEvent(Server server) { this.server = server; } - + /** * Gets the server involved in this event. + * * @return The event's server. */ public Server getServer() { return this.server; } - + @Override public void call(ServerListener listener) { listener.serverClosed(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java similarity index 83% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java index 44734d08..f08cc306 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerClosingEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; -import ch.spacebase.packetlib.Server; +import org.spacehq.packetlib.Server; /** * Called when the server is about to close. @@ -8,19 +8,20 @@ import ch.spacebase.packetlib.Server; public class ServerClosingEvent implements ServerEvent { private Server server; - + public ServerClosingEvent(Server server) { this.server = server; } - + /** * Gets the server involved in this event. + * * @return The event's server. */ public Server getServer() { return this.server; } - + @Override public void call(ServerListener listener) { listener.serverClosing(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java similarity index 80% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java index e926c54e..bd84abc6 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; /** * An event relating to servers. @@ -7,8 +7,9 @@ public interface ServerEvent { /** * Calls the event. + * * @param listener Listener to call the event on. */ public void call(ServerListener listener); - + } diff --git a/src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java b/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java similarity index 92% rename from src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java rename to src/main/java/org/spacehq/packetlib/event/server/ServerListener.java index 139f8a03..54cb730e 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/ServerListener.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; /** * A listener for listening to server events. @@ -7,32 +7,37 @@ public interface ServerListener { /** * Called when a server is bound to its host and port. + * * @param event Data relating to the event. */ public void serverBound(ServerBoundEvent event); /** * Called when a server is about to close. + * * @param event Data relating to the event. */ public void serverClosing(ServerClosingEvent event); - + /** * Called when a server is closed. + * * @param event Data relating to the event. */ public void serverClosed(ServerClosedEvent event); - + /** * Called when a session is added to the server. + * * @param event Data relating to the event. */ public void sessionAdded(SessionAddedEvent event); - + /** * Called when a session is removed and disconnected from the server. + * * @param event Data relating to the event. */ public void sessionRemoved(SessionRemovedEvent event); - + } diff --git a/src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java similarity index 83% rename from src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java index 9e1b405e..019409dd 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/SessionAddedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java @@ -1,7 +1,7 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.Session; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.Session; /** * Called when a session is added to the server. @@ -10,28 +10,30 @@ public class SessionAddedEvent implements ServerEvent { private Server server; private Session session; - + public SessionAddedEvent(Server server, Session session) { this.server = server; this.session = session; } - + /** * Gets the server involved in this event. + * * @return The event's server. */ public Server getServer() { return this.server; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + @Override public void call(ServerListener listener) { listener.sessionAdded(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java similarity index 83% rename from src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java rename to src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java index 186c09ac..78ba5ead 100644 --- a/src/main/java/ch/spacebase/packetlib/event/server/SessionRemovedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java @@ -1,7 +1,7 @@ -package ch.spacebase.packetlib.event.server; +package org.spacehq.packetlib.event.server; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.Session; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.Session; /** * Called when a session is removed and disconnected from the server. @@ -10,28 +10,30 @@ public class SessionRemovedEvent implements ServerEvent { private Server server; private Session session; - + public SessionRemovedEvent(Server server, Session session) { this.server = server; this.session = session; } - + /** * Gets the server involved in this event. + * * @return The event's server. */ public Server getServer() { return this.server; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + @Override public void call(ServerListener listener) { listener.sessionRemoved(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java similarity index 82% rename from src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java index 65d3bea6..b9384ffd 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/ConnectedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; -import ch.spacebase.packetlib.Session; +import org.spacehq.packetlib.Session; /** * Called when the session connects. @@ -8,19 +8,20 @@ import ch.spacebase.packetlib.Session; public class ConnectedEvent implements SessionEvent { private Session session; - + public ConnectedEvent(Session session) { this.session = session; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + @Override public void call(SessionListener listener) { listener.connected(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java similarity index 87% rename from src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java index f72794e2..b3ce80a8 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; -import ch.spacebase.packetlib.Session; +import org.spacehq.packetlib.Session; /** * Called when the session is disconnected. @@ -9,28 +9,30 @@ public class DisconnectedEvent implements SessionEvent { private Session session; private String reason; - + public DisconnectedEvent(Session session, String reason) { this.session = session; this.reason = reason; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + /** * Gets the reason given for the session disconnecting. + * * @return The event's reason. */ public String getReason() { return this.reason; } - + @Override public void call(SessionListener listener) { listener.disconnected(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java b/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java similarity index 87% rename from src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java index 5ec3cf69..cd6e6425 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/DisconnectingEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java @@ -1,6 +1,6 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; -import ch.spacebase.packetlib.Session; +import org.spacehq.packetlib.Session; /** * Called when the session is about to disconnect. @@ -9,28 +9,30 @@ public class DisconnectingEvent implements SessionEvent { private Session session; private String reason; - + public DisconnectingEvent(Session session, String reason) { this.session = session; this.reason = reason; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + /** * Gets the reason given for the session disconnecting. + * * @return The event's reason. */ public String getReason() { return this.reason; } - + @Override public void call(SessionListener listener) { listener.disconnecting(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java similarity index 87% rename from src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java index 8e535709..e0a5d4c2 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java @@ -1,7 +1,7 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.packet.Packet; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.packet.Packet; /** * Called when the session receives a packet. @@ -10,22 +10,24 @@ public class PacketReceivedEvent implements SessionEvent { private Session session; private Packet packet; - + public PacketReceivedEvent(Session session, Packet packet) { this.session = session; this.packet = packet; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + /** * Gets the packet involved in this event as the required type. + * * @return The event's packet as the required type. * @throws IllegalStateException If the packet's value isn't of the required type. */ @@ -37,7 +39,7 @@ public class PacketReceivedEvent implements SessionEvent { throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); } } - + @Override public void call(SessionListener listener) { listener.packetReceived(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java similarity index 87% rename from src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java index 212c74a6..e82109ed 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java @@ -1,7 +1,7 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.packet.Packet; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.packet.Packet; /** * Called when the session has sent a packet. @@ -10,22 +10,24 @@ public class PacketSentEvent implements SessionEvent { private Session session; private Packet packet; - + public PacketSentEvent(Session session, Packet packet) { this.session = session; this.packet = packet; } - + /** * Gets the session involved in this event. + * * @return The event's session. */ public Session getSession() { return this.session; } - + /** * Gets the packet involved in this event as the required type. + * * @return The event's packet as the required type. * @throws IllegalStateException If the packet's value isn't of the required type. */ @@ -37,7 +39,7 @@ public class PacketSentEvent implements SessionEvent { throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); } } - + @Override public void call(SessionListener listener) { listener.packetSent(this); diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java b/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java similarity index 90% rename from src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java rename to src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java index 70bb508d..8821d138 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; /** * An adapter for picking session events to listen for. diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java b/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java similarity index 80% rename from src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java rename to src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java index 7af4d048..88e343fa 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/SessionEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; /** * An event relating to sessions. @@ -7,8 +7,9 @@ public interface SessionEvent { /** * Calls the event. + * * @param listener Listener to call the event on. */ public void call(SessionListener listener); - + } diff --git a/src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java b/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java similarity index 92% rename from src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java rename to src/main/java/org/spacehq/packetlib/event/session/SessionListener.java index 7353be9d..edb03da5 100644 --- a/src/main/java/ch/spacebase/packetlib/event/session/SessionListener.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.event.session; +package org.spacehq.packetlib.event.session; /** * A listener for listening to session events. @@ -7,32 +7,37 @@ public interface SessionListener { /** * Called when a session receives a packet. + * * @param event Data relating to the event. */ public void packetReceived(PacketReceivedEvent event); - + /** * Called when a session sends a packet. + * * @param event Data relating to the event. */ public void packetSent(PacketSentEvent event); - + /** * Called when a session connects. + * * @param event Data relating to the event. */ public void connected(ConnectedEvent event); - + /** * Called when a session is about to disconnect. + * * @param event Data relating to the event. */ public void disconnecting(DisconnectingEvent event); - + /** * Called when a session is disconnected. + * * @param event Data relating to the event. */ public void disconnected(DisconnectedEvent event); - + } diff --git a/src/main/java/ch/spacebase/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java similarity index 70% rename from src/main/java/ch/spacebase/packetlib/io/NetInput.java rename to src/main/java/org/spacehq/packetlib/io/NetInput.java index 09b4b4f5..714141c1 100644 --- a/src/main/java/ch/spacebase/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.io; +package org.spacehq.packetlib.io; import java.io.IOException; @@ -9,105 +9,120 @@ public interface NetInput { /** * Reads the next boolean. + * * @return The next boolean. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public boolean readBoolean() throws IOException; /** * Reads the next byte. + * * @return The next byte. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public byte readByte() throws IOException; /** * Reads the next unsigned byte. + * * @return The next unsigned byte. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public int readUnsignedByte() throws IOException; /** * Reads the next short. + * * @return The next short. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public short readShort() throws IOException; /** * Reads the next unsigned short. + * * @return The next unsigned short. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public int readUnsignedShort() throws IOException; /** * Reads the next char. + * * @return The next char. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public char readChar() throws IOException; /** * Reads the next integer. + * * @return The next integer. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public int readInt() throws IOException; - + /** * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * * @return The next varint. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public int readVarInt() throws IOException; /** * Reads the next long. + * * @return The next long. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public long readLong() throws IOException; /** * Reads the next float. + * * @return The next float. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public float readFloat() throws IOException; /** * Reads the next double. + * * @return The next double. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public double readDouble() throws IOException; /** * Reads the next byte array, getting the length from a prefixed length value. + * * @return The next byte array. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public byte[] readPrefixedBytes() throws IOException; - + /** * Reads the next byte array. + * * @param The length of the byte array. * @return The next byte array. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public byte[] readBytes(int length) throws IOException; /** * Reads the next string. + * * @return The next string. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public String readString() throws IOException; /** * Gets the number of available bytes. + * * @return The number of available bytes. */ public int available() throws IOException; diff --git a/src/main/java/ch/spacebase/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java similarity index 67% rename from src/main/java/ch/spacebase/packetlib/io/NetOutput.java rename to src/main/java/org/spacehq/packetlib/io/NetOutput.java index 898bf29a..4c536133 100644 --- a/src/main/java/ch/spacebase/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -1,4 +1,4 @@ -package ch.spacebase.packetlib.io; +package org.spacehq.packetlib.io; import java.io.IOException; @@ -9,99 +9,113 @@ public interface NetOutput { /** * Writes a boolean. + * * @param b Boolean to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeBoolean(boolean b) throws IOException; /** * Writes a byte. + * * @param b Byte to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeByte(int b) throws IOException; /** * Writes a short. + * * @param s Short to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeShort(int s) throws IOException; /** * Writes a char. + * * @param c Char to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeChar(int c) throws IOException; /** * Writes a integer. + * * @param i Integer to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeInt(int i) throws IOException; - + /** * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * * @return i Varint to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeVarInt(int i) throws IOException; - + /** * Writes a long. + * * @param l Long to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeLong(long l) throws IOException; /** * Writes a float. + * * @param f Float to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeFloat(float f) throws IOException; /** * Writes a double. + * * @param d Double to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeDouble(double d) throws IOException; /** * Writes a byte array, prefixing the written data with the array's length. + * * @param b Byte array to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writePrefixedBytes(byte b[]) throws IOException; - + /** * Writes a byte array. + * * @param b Byte array to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeBytes(byte b[]) throws IOException; /** * Writes a byte array, using the given amount of bytes. - * @param b Byte array to write. + * + * @param b Byte array to write. * @param length Bytes to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeBytes(byte b[], int length) throws IOException; /** * Writes a string. + * * @param s String to write. - * @throws IOException If an I/O error occurs. + * @throws java.io.IOException If an I/O error occurs. */ public void writeString(String s) throws IOException; /** * Flushes the output. - * @throws IOException If an I/O error occurs. + * + * @throws java.io.IOException If an I/O error occurs. */ public void flush() throws IOException; diff --git a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java similarity index 97% rename from src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java rename to src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index cd498b34..2d258328 100644 --- a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -1,11 +1,11 @@ -package ch.spacebase.packetlib.io.stream; +package org.spacehq.packetlib.io.stream; + +import org.spacehq.packetlib.io.NetInput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; -import ch.spacebase.packetlib.io.NetInput; - /** * A NetInput implementation using an InputStream as a backend. */ @@ -64,7 +64,7 @@ public class StreamNetInput implements NetInput { int ch4 = this.readUnsignedByte(); return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); } - + @Override public int readVarInt() throws IOException { int ret = 0; @@ -95,7 +95,7 @@ public class StreamNetInput implements NetInput { public double readDouble() throws IOException { return Double.longBitsToDouble(this.readLong()); } - + @Override public byte[] readPrefixedBytes() throws IOException { short length = this.readShort(); @@ -107,7 +107,7 @@ public class StreamNetInput implements NetInput { if(length < 0) { throw new IllegalArgumentException("Array cannot have length less than 0."); } - + byte b[] = new byte[length]; int n = 0; while(n < length) { diff --git a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java similarity index 96% rename from src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java rename to src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index 7723423c..cea32190 100644 --- a/src/main/java/ch/spacebase/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -1,10 +1,10 @@ -package ch.spacebase.packetlib.io.stream; +package org.spacehq.packetlib.io.stream; + +import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; import java.io.OutputStream; -import ch.spacebase.packetlib.io.NetOutput; - /** * A NetOutput implementation using an OutputStream as a backend. */ @@ -45,7 +45,7 @@ public class StreamNetOutput implements NetOutput { this.writeByte((byte) ((i >>> 8) & 0xFF)); this.writeByte((byte) ((i >>> 0) & 0xFF)); } - + @Override public void writeVarInt(int i) throws IOException { while((i & -128) != 0) { @@ -77,7 +77,7 @@ public class StreamNetOutput implements NetOutput { public void writeDouble(double d) throws IOException { this.writeLong(Double.doubleToLongBits(d)); } - + @Override public void writePrefixedBytes(byte b[]) throws IOException { this.writeShort(b.length); diff --git a/src/main/java/ch/spacebase/packetlib/packet/Packet.java b/src/main/java/org/spacehq/packetlib/packet/Packet.java similarity index 83% rename from src/main/java/ch/spacebase/packetlib/packet/Packet.java rename to src/main/java/org/spacehq/packetlib/packet/Packet.java index bd3ca7ca..e993ee3d 100644 --- a/src/main/java/ch/spacebase/packetlib/packet/Packet.java +++ b/src/main/java/org/spacehq/packetlib/packet/Packet.java @@ -1,23 +1,25 @@ -package ch.spacebase.packetlib.packet; +package org.spacehq.packetlib.packet; + +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; -import ch.spacebase.packetlib.io.NetInput; -import ch.spacebase.packetlib.io.NetOutput; - /** * A network packet. */ public interface Packet { - + /** * Reads the packet from the given input buffer. + * * @param in The input source to read from. */ public void read(NetInput in) throws IOException; /** * Writes the packet to the given output buffer. + * * @param out The output destination to write to. */ public void write(NetOutput out) throws IOException; @@ -26,8 +28,9 @@ public interface Packet { * Gets whether the packet has handling and writing priority. * If the result is true, the thread will wait for the packet to finish writing * when writing and the packet will be handled immediately after reading it. + * * @return Whether the packet has priority. */ public boolean isPriority(); - + } diff --git a/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java similarity index 85% rename from src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java rename to src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java index 4450740d..265f920e 100644 --- a/src/main/java/ch/spacebase/packetlib/packet/PacketProtocol.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java @@ -1,14 +1,14 @@ -package ch.spacebase.packetlib.packet; +package org.spacehq.packetlib.packet; + +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.crypt.PacketEncryption; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; -import ch.spacebase.packetlib.Client; -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.crypt.PacketEncryption; - /** * A protocol for packet sending and receiving. * All implementations must have a no-params constructor for server protocol creation. @@ -17,29 +17,32 @@ public abstract class PacketProtocol { private final Map> incoming = new HashMap>(); private final Map, Integer> outgoing = new HashMap, Integer>(); - + /** * Called when a client is created with this protocol. - * @param client The client that the session belongs to. + * + * @param client The client that the session belongs to. * @param session The created session. */ public abstract void newClientSession(Client client, Session session); - + /** * Called when a server's session is created with this protocol. - * @param server The server that the session belongs to. + * + * @param server The server that the session belongs to. * @param session The created session. */ public abstract void newServerSession(Server server, Session session); - + /** * Gets this protocol's active packet encryption. + * * @return The protocol's packet encryption, or null if packets should not be encrypted. */ public PacketEncryption getEncryption() { return null; } - + /** * Clears all currently registered packets. */ @@ -47,10 +50,11 @@ public abstract class PacketProtocol { this.incoming.clear(); this.outgoing.clear(); } - + /** * Registers a packet to this protocol as both incoming and outgoing. - * @param id Id to register the packet to. + * + * @param id Id to register the packet to. * @param packet Packet to register. * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. */ @@ -58,10 +62,11 @@ public abstract class PacketProtocol { this.registerIncoming(id, packet); this.registerOutgoing(id, packet); } - + /** * Registers an incoming packet to this protocol. - * @param id Id to register the packet to. + * + * @param id Id to register the packet to. * @param packet Packet to register. * @throws IllegalArgumentException If the packet fails a test creation. */ @@ -74,35 +79,37 @@ public abstract class PacketProtocol { throw new IllegalArgumentException(e.getMessage(), e.getCause()); } } - + /** * Registers an outgoing packet to this protocol. - * @param id Id to register the packet to. + * + * @param id Id to register the packet to. * @param packet Packet to register. */ public final void registerOutgoing(int id, Class packet) { this.outgoing.put(packet, id); } - + /** * Creates a new instance of an incoming packet with the given id. + * * @param id Id of the packet to create. * @return The created packet. * @throws IllegalArgumentException If the packet ID is invalid. - * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. + * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. */ public final Packet createIncomingPacket(int id) { if(id < 0 || !this.incoming.containsKey(id) || this.incoming.get(id) == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - + Class packet = this.incoming.get(id); try { Constructor constructor = packet.getDeclaredConstructor(); if(!constructor.isAccessible()) { constructor.setAccessible(true); } - + return constructor.newInstance(); } catch(NoSuchMethodError e) { throw new IllegalStateException("Packet \"" + id + ", " + packet.getName() + "\" does not have a no-params constructor for instantiation."); @@ -110,9 +117,10 @@ public abstract class PacketProtocol { throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + packet.getName() + "\".", e); } } - + /** * Gets the registered id of an outgoing packet class. + * * @param packet Class of the packet to get the id for. * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. @@ -121,9 +129,9 @@ public abstract class PacketProtocol { if(!this.outgoing.containsKey(packet) || this.outgoing.get(packet) == null) { throw new IllegalArgumentException("Unregistered outgoing packet class: " + packet.getName()); } - + return this.outgoing.get(packet); } - - + + } diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java similarity index 89% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index 38271637..dc32b739 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -1,44 +1,44 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; -import ch.spacebase.packetlib.ConnectionListener; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; +import org.spacehq.packetlib.ConnectionListener; public class TcpConnectionListener implements ConnectionListener { - + private String host; private int port; private EventLoopGroup group; private Channel channel; - + public TcpConnectionListener(String host, int port, EventLoopGroup group, Channel channel) { this.host = host; this.port = port; this.group = group; this.channel = channel; } - + @Override public String getHost() { return this.host; } - + @Override public int getPort() { return this.port; } - + @Override public boolean isListening() { return this.channel.isOpen(); } - + @Override public void close() { if(this.channel.isOpen()) { this.channel.close().syncUninterruptibly(); } - + try { this.group.shutdownGracefully().sync(); } catch(InterruptedException e) { diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java similarity index 71% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java index 2a8d9e5e..6f059cf2 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java @@ -1,33 +1,33 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; -import java.util.List; - -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.event.session.PacketReceivedEvent; -import ch.spacebase.packetlib.io.NetInput; -import ch.spacebase.packetlib.io.NetOutput; -import ch.spacebase.packetlib.packet.Packet; -import ch.spacebase.packetlib.tcp.io.ByteBufNetInput; -import ch.spacebase.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; +import org.spacehq.packetlib.packet.Packet; +import org.spacehq.packetlib.tcp.io.ByteBufNetInput; +import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; + +import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { private Session session; - + public TcpPacketCodec(Session session) { this.session = session; } - + @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { NetOutput out = new ByteBufNetOutput(buf); out.writeVarInt(this.session.getPacketProtocol().getOutgoingId(packet.getClass())); packet.write(out); } - + @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { NetInput in = new ByteBufNetInput(buf); @@ -37,8 +37,8 @@ public class TcpPacketCodec extends ByteToMessageCodec { if(packet.isPriority()) { this.session.callEvent(new PacketReceivedEvent(this.session, packet)); } - + out.add(packet); } - + } diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java similarity index 96% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java index ff7cc2e5..da2a4a99 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java @@ -1,11 +1,11 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; -import java.util.List; - -import ch.spacebase.packetlib.Session; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; +import org.spacehq.packetlib.Session; + +import java.util.List; public class TcpPacketEncryptor extends ByteToMessageCodec { diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java similarity index 91% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java index 8b296a21..01a6929f 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java @@ -1,14 +1,14 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; -import java.util.List; - -import ch.spacebase.packetlib.tcp.io.ByteBufNetInput; -import ch.spacebase.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.CorruptedFrameException; +import org.spacehq.packetlib.tcp.io.ByteBufNetInput; +import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; + +import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { @@ -45,7 +45,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { throw new CorruptedFrameException("Length is too long."); } - + private static int varintLength(int i) { if((i & -128) == 0) { return 1; diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java similarity index 67% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index 29ca14cb..90752133 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -1,37 +1,37 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; -import java.util.Map; - -import ch.spacebase.packetlib.Server; -import ch.spacebase.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.packet.PacketProtocol; + +import java.util.Map; public class TcpServerSession extends TcpSession { private Server server; - + public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server) { super(host, port, protocol, group, bootstrap); this.server = server; } - + @Override public void connect() { } - + @Override public Map getFlags() { Map ret = super.getFlags(); ret.putAll(this.server.getGlobalFlags()); return ret; } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - this.server.removeSession(this); - } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + this.server.removeSession(this); + } } diff --git a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java similarity index 68% rename from src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java rename to src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index b5ed211f..31e10ef7 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -1,31 +1,20 @@ -package ch.spacebase.packetlib.tcp; +package org.spacehq.packetlib.tcp; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.*; +import io.netty.handler.timeout.ReadTimeoutException; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.event.session.*; +import org.spacehq.packetlib.packet.Packet; +import org.spacehq.packetlib.packet.PacketProtocol; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import ch.spacebase.packetlib.Session; -import ch.spacebase.packetlib.event.session.ConnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectedEvent; -import ch.spacebase.packetlib.event.session.DisconnectingEvent; -import ch.spacebase.packetlib.event.session.PacketReceivedEvent; -import ch.spacebase.packetlib.event.session.PacketSentEvent; -import ch.spacebase.packetlib.event.session.SessionEvent; -import ch.spacebase.packetlib.event.session.SessionListener; -import ch.spacebase.packetlib.packet.Packet; -import ch.spacebase.packetlib.packet.PacketProtocol; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.timeout.ReadTimeoutException; - public class TcpSession extends SimpleChannelInboundHandler implements Session { - + private String host; private int port; private PacketProtocol protocol; @@ -35,10 +24,10 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private boolean disconnected = false; private boolean writing = false; private List packets = new ArrayList(); - + private Map flags = new HashMap(); private List listeners = new ArrayList(); - + public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap) { this.host = host; this.port = port; @@ -46,12 +35,12 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.group = group; this.bootstrap = bootstrap; } - + @Override public void connect() { this.connect(true); } - + @Override public void connect(boolean wait) { if(this.bootstrap == null) { @@ -61,7 +50,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S throw new IllegalStateException("Session disconnected."); } } - + ChannelFuture future = this.bootstrap.connect(); this.bootstrap = null; if(wait) { @@ -74,32 +63,32 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } } - + @Override public String getHost() { return this.host; } - + @Override public int getPort() { return this.port; } - + @Override public PacketProtocol getPacketProtocol() { return this.protocol; } - + @Override public Map getFlags() { return new HashMap(this.flags); } - + @Override public boolean hasFlag(String key) { return this.getFlags().containsKey(key); } - + @SuppressWarnings("unchecked") @Override public T getFlag(String key) { @@ -107,19 +96,19 @@ public class TcpSession extends SimpleChannelInboundHandler implements S if(value == null) { return null; } - + try { return (T) value; } catch(ClassCastException e) { throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); } } - + @Override public void setFlag(String key, Object value) { this.flags.put(key, value); } - + @Override public List getListeners() { return new ArrayList(this.listeners); @@ -141,12 +130,12 @@ public class TcpSession extends SimpleChannelInboundHandler implements S event.call(listener); } } - + @Override public boolean isConnected() { return this.channel != null && this.channel.isOpen() && !this.disconnected; } - + @Override public void send(final Packet packet) { this.writing = true; @@ -154,19 +143,19 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.writing = false; return; } - + this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(!future.isSuccess()) { - exceptionCaught(null, future.cause()); - } - - writing = false; - callEvent(new PacketSentEvent(TcpSession.this, packet)); - } + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if(!future.isSuccess()) { + exceptionCaught(null, future.cause()); + } + + writing = false; + callEvent(new PacketSentEvent(TcpSession.this, packet)); + } }); - + if(packet.isPriority()) { while(this.writing) { try { @@ -176,13 +165,13 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } } - + @Override public void disconnect(String reason) { if(this.disconnected) { return; } - + this.disconnected = true; if(this.writing) { while(this.writing) { @@ -191,7 +180,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } catch(InterruptedException e) { } } - + try { Thread.sleep(250); } catch(InterruptedException e) { @@ -201,55 +190,55 @@ public class TcpSession extends SimpleChannelInboundHandler implements S if(reason == null) { reason = "Connection closed."; } - + if(this.channel != null) { if(this.channel.isOpen()) { this.callEvent(new DisconnectingEvent(this, reason)); } - + this.channel.close().syncUninterruptibly(); } - + this.callEvent(new DisconnectedEvent(this, reason)); if(this.group != null) { this.group.shutdownGracefully(); } - + this.channel = null; } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - if(this.disconnected) { - ctx.channel().close().syncUninterruptibly(); - return; - } - - this.channel = ctx.channel(); - this.disconnected = false; - this.callEvent(new ConnectedEvent(this)); - new PacketHandleThread().start(); - } - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - this.disconnect("Connection closed."); - } + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + if(this.disconnected) { + ctx.channel().close().syncUninterruptibly(); + return; + } - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - this.writing = false; - if(!this.disconnected) { - if(cause instanceof ReadTimeoutException) { - this.disconnect("Connection timed out."); - } else { - this.disconnect("Internal network exception: " + cause.toString()); - cause.printStackTrace(); - } - } - - this.disconnected = true; - } + this.channel = ctx.channel(); + this.disconnected = false; + this.callEvent(new ConnectedEvent(this)); + new PacketHandleThread().start(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + this.disconnect("Connection closed."); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + this.writing = false; + if(!this.disconnected) { + if(cause instanceof ReadTimeoutException) { + this.disconnect("Connection timed out."); + } else { + this.disconnect("Internal network exception: " + cause.toString()); + cause.printStackTrace(); + } + } + + this.disconnected = true; + } @Override protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { @@ -257,7 +246,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.packets.add(packet); } } - + private class PacketHandleThread extends Thread { @Override public void run() { @@ -266,7 +255,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S while(packets.size() > 0) { callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); } - + try { Thread.sleep(5); } catch(InterruptedException e) { diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java new file mode 100644 index 00000000..3f531de3 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -0,0 +1,66 @@ +package org.spacehq.packetlib.tcp; + +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.timeout.ReadTimeoutHandler; +import org.spacehq.packetlib.*; +import org.spacehq.packetlib.packet.PacketProtocol; + +import java.net.InetSocketAddress; + +public class TcpSessionFactory implements SessionFactory { + + @Override + public Session createClientSession(final Client client) { + final EventLoopGroup group = new NioEventLoopGroup(); + final Bootstrap bootstrap = new Bootstrap().channel(NioSocketChannel.class); + final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap); + bootstrap.handler(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + session.getPacketProtocol().newClientSession(client, session); + ch.config().setOption(ChannelOption.IP_TOS, 0x18); + ch.config().setOption(ChannelOption.TCP_NODELAY, false); + ch.pipeline() + .addLast("timer", new ReadTimeoutHandler(30)) + .addLast("encryption", new TcpPacketEncryptor(session)) + .addLast("sizer", new TcpPacketSizer()) + .addLast("codec", new TcpPacketCodec(session)) + .addLast("manager", session); + } + }).group(group).remoteAddress(client.getHost(), client.getPort()); + return session; + //.connect().syncUninterruptibly().channel().pipeline().get("manager"); + } + + @Override + public ConnectionListener createServerListener(final Server server) { + final EventLoopGroup group = new NioEventLoopGroup(); + return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + @Override + public void initChannel(Channel ch) throws Exception { + InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); + PacketProtocol protocol = server.createPacketProtocol(); + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); + session.getPacketProtocol().newServerSession(server, session); + ch.config().setOption(ChannelOption.IP_TOS, 0x18); + ch.config().setOption(ChannelOption.TCP_NODELAY, false); + ch.pipeline() + .addLast("timer", new ReadTimeoutHandler(30)) + .addLast("encryption", new TcpPacketEncryptor(session)) + .addLast("sizer", new TcpPacketSizer()) + .addLast("codec", new TcpPacketCodec(session)) + .addLast("manager", session); + server.addSession(session); + } + }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); + } + +} diff --git a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java similarity index 96% rename from src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java rename to src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index d354015f..4df13e13 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -1,11 +1,10 @@ -package ch.spacebase.packetlib.tcp.io; +package org.spacehq.packetlib.tcp.io; import io.netty.buffer.ByteBuf; +import org.spacehq.packetlib.io.NetInput; import java.io.IOException; -import ch.spacebase.packetlib.io.NetInput; - /** * A NetInput implementation using a ByteBuf as a backend. */ @@ -64,7 +63,7 @@ public class ByteBufNetInput implements NetInput { throw new IOException("Variable length quantity is too long (must be <= 35)"); } } - + return value | (b << size); } @@ -82,7 +81,7 @@ public class ByteBufNetInput implements NetInput { public double readDouble() throws IOException { return this.buf.readDouble(); } - + @Override public byte[] readPrefixedBytes() throws IOException { short length = this.buf.readShort(); @@ -94,7 +93,7 @@ public class ByteBufNetInput implements NetInput { if(length < 0) { throw new IllegalArgumentException("Array cannot have length less than 0."); } - + byte b[] = new byte[length]; this.buf.readBytes(b); return b; diff --git a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java similarity index 95% rename from src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java rename to src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 3e7548f8..41bbee7a 100644 --- a/src/main/java/ch/spacebase/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -1,11 +1,10 @@ -package ch.spacebase.packetlib.tcp.io; +package org.spacehq.packetlib.tcp.io; import io.netty.buffer.ByteBuf; +import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; -import ch.spacebase.packetlib.io.NetOutput; - /** * A NetOutput implementation using a ByteBuf as a backend. */ @@ -41,7 +40,7 @@ public class ByteBufNetOutput implements NetOutput { public void writeInt(int i) throws IOException { this.buf.writeInt(i); } - + @Override public void writeVarInt(int i) throws IOException { while((i & 0xFFFFFF80) != 0L) { @@ -66,7 +65,7 @@ public class ByteBufNetOutput implements NetOutput { public void writeDouble(double d) throws IOException { this.buf.writeDouble(d); } - + @Override public void writePrefixedBytes(byte b[]) throws IOException { this.buf.writeShort(b.length); From 676089320150c54ee2fc860b5eccc9292c2c882a Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Tue, 18 Mar 2014 18:18:50 -0700 Subject: [PATCH 009/180] Minor cleanup, add Proxy support to TcpSessionFactory --- .../org/spacehq/packetlib/SessionFactory.java | 8 +++---- .../org/spacehq/packetlib/io/NetInput.java | 2 +- .../packetlib/tcp/ProxyOioChannelFactory.java | 23 ++++++++++++++++++ .../packetlib/tcp/TcpSessionFactory.java | 24 ++++++++++++++++--- 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java diff --git a/src/main/java/org/spacehq/packetlib/SessionFactory.java b/src/main/java/org/spacehq/packetlib/SessionFactory.java index f38cb626..15c83c90 100644 --- a/src/main/java/org/spacehq/packetlib/SessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/SessionFactory.java @@ -8,16 +8,16 @@ public interface SessionFactory { /** * Creates a client session. * - * @param host Host to connect to. - * @param port Port to connect to. + * @param client Client to create the session for. * @return The created session. */ public Session createClientSession(Client client); /** - * Initializes the factory for creating server sessions. + * Creates a server network listener. * - * @param server Server to initialize for. + * @param server Server to create the listener for. + * @return The created listener. */ public ConnectionListener createServerListener(Server server); diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index 714141c1..e04a272f 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -106,7 +106,7 @@ public interface NetInput { /** * Reads the next byte array. * - * @param The length of the byte array. + * @param length The length of the byte array. * @return The next byte array. * @throws java.io.IOException If an I/O error occurs. */ diff --git a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java new file mode 100644 index 00000000..22e54409 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java @@ -0,0 +1,23 @@ +package org.spacehq.packetlib.tcp; + +import io.netty.bootstrap.ChannelFactory; +import io.netty.channel.EventLoop; +import io.netty.channel.socket.oio.OioSocketChannel; + +import java.net.Proxy; +import java.net.Socket; + +public class ProxyOioChannelFactory implements ChannelFactory { + + private Proxy proxy; + + public ProxyOioChannelFactory(Proxy proxy) { + this.proxy = proxy; + } + + @Override + public OioSocketChannel newChannel(EventLoop eventLoop) { + return new OioSocketChannel(eventLoop, new Socket(this.proxy)); + } + +} diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index 3f531de3..3dc5fdbe 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -7,6 +7,7 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.timeout.ReadTimeoutHandler; @@ -14,13 +15,31 @@ import org.spacehq.packetlib.*; import org.spacehq.packetlib.packet.PacketProtocol; import java.net.InetSocketAddress; +import java.net.Proxy; public class TcpSessionFactory implements SessionFactory { + private Proxy clientProxy; + + public TcpSessionFactory() { + } + + public TcpSessionFactory(Proxy clientProxy) { + this.clientProxy = clientProxy; + } + @Override public Session createClientSession(final Client client) { - final EventLoopGroup group = new NioEventLoopGroup(); - final Bootstrap bootstrap = new Bootstrap().channel(NioSocketChannel.class); + Bootstrap bootstrap = new Bootstrap(); + EventLoopGroup group = null; + if(this.clientProxy != null) { + group = new OioEventLoopGroup(); + bootstrap.channelFactory(new ProxyOioChannelFactory(this.clientProxy)); + } else { + group = new NioEventLoopGroup(); + bootstrap.channel(NioSocketChannel.class); + } + final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap); bootstrap.handler(new ChannelInitializer() { @Override @@ -37,7 +56,6 @@ public class TcpSessionFactory implements SessionFactory { } }).group(group).remoteAddress(client.getHost(), client.getPort()); return session; - //.connect().syncUninterruptibly().channel().pipeline().get("manager"); } @Override From 52249597ceabcb0cbee8d8dbf58a49402fb4a268 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 22 Mar 2014 13:51:21 -0700 Subject: [PATCH 010/180] Only call PacketSendEvent if there are no errors in writing --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 31e10ef7..d437a3d2 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -147,12 +147,12 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { + writing = false; if(!future.isSuccess()) { exceptionCaught(null, future.cause()); + } else { + callEvent(new PacketSentEvent(TcpSession.this, packet)); } - - writing = false; - callEvent(new PacketSentEvent(TcpSession.this, packet)); } }); From f6d1c51ee072d9975eab59128c591c555fd991d9 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 3 Apr 2014 16:31:21 -0700 Subject: [PATCH 011/180] Update build server URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6331df2..470395e9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See examples/org/spacehq/packetlib/test/PingServerTest.java -------- PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -You can also download a build [here](http://build.spacehq.org/job/PacketLib/). +You can also download a build [here](http://build.spacehq.org/browse/PACKETLIB-MAIN). License From 21c7d90a78b0d6894a9692e1588339086d93eec5 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 4 Apr 2014 15:39:51 -0700 Subject: [PATCH 012/180] Catch and report exceptions from disconnect events --- .../org/spacehq/packetlib/tcp/TcpSession.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index d437a3d2..52f1d048 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -191,17 +191,26 @@ public class TcpSession extends SimpleChannelInboundHandler implements S reason = "Connection closed."; } - if(this.channel != null) { - if(this.channel.isOpen()) { - this.callEvent(new DisconnectingEvent(this, reason)); + try { + if(this.channel != null) { + if(this.channel.isOpen()) { + this.callEvent(new DisconnectingEvent(this, reason)); + } + + this.channel.close().syncUninterruptibly(); } - this.channel.close().syncUninterruptibly(); + this.callEvent(new DisconnectedEvent(this, reason)); + } catch(Throwable t) { + System.err.println("[WARNING] Throwable caught while firing disconnect events."); + t.printStackTrace(); } - this.callEvent(new DisconnectedEvent(this, reason)); if(this.group != null) { - this.group.shutdownGracefully(); + try { + this.group.shutdownGracefully(); + } catch(Exception e) { + } } this.channel = null; From 396b7bfab75bdeb2a264bb347b69f9027620b279 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 20 Jun 2014 14:39:10 -0700 Subject: [PATCH 013/180] Add interface for customizing packet headers. --- .../spacehq/packetlib/test/TestProtocol.java | 8 +++ .../packetlib/packet/DefaultPacketHeader.java | 59 +++++++++++++++ .../packetlib/packet/PacketHeader.java | 72 +++++++++++++++++++ .../packetlib/packet/PacketProtocol.java | 7 ++ .../spacehq/packetlib/tcp/TcpPacketCodec.java | 4 +- .../spacehq/packetlib/tcp/TcpPacketSizer.java | 58 ++++++++------- .../packetlib/tcp/TcpSessionFactory.java | 4 +- 7 files changed, 178 insertions(+), 34 deletions(-) create mode 100644 src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java create mode 100644 src/main/java/org/spacehq/packetlib/packet/PacketHeader.java diff --git a/example/org/spacehq/packetlib/test/TestProtocol.java b/example/org/spacehq/packetlib/test/TestProtocol.java index e644b2f5..93fac89b 100644 --- a/example/org/spacehq/packetlib/test/TestProtocol.java +++ b/example/org/spacehq/packetlib/test/TestProtocol.java @@ -5,6 +5,8 @@ import org.spacehq.packetlib.Server; import org.spacehq.packetlib.Session; import org.spacehq.packetlib.crypt.AESEncryption; import org.spacehq.packetlib.crypt.PacketEncryption; +import org.spacehq.packetlib.packet.DefaultPacketHeader; +import org.spacehq.packetlib.packet.PacketHeader; import org.spacehq.packetlib.packet.PacketProtocol; import javax.crypto.SecretKey; @@ -12,6 +14,7 @@ import java.security.GeneralSecurityException; public class TestProtocol extends PacketProtocol { + private PacketHeader header = new DefaultPacketHeader(); private AESEncryption encrypt; @SuppressWarnings("unused") @@ -36,6 +39,11 @@ public class TestProtocol extends PacketProtocol { return this.encrypt; } + @Override + public PacketHeader getPacketHeader() { + return this.header; + } + @Override public void newClientSession(Client client, Session session) { session.addListener(new ClientSessionListener()); diff --git a/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java b/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java new file mode 100644 index 00000000..2e160ae3 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java @@ -0,0 +1,59 @@ +package org.spacehq.packetlib.packet; + +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; + +import java.io.IOException; + +public class DefaultPacketHeader implements PacketHeader { + + @Override + public boolean isLengthVariable() { + return true; + } + + @Override + public int getLengthSize() { + return 5; + } + + @Override + public int getLengthSize(int length) { + return varintLength(length); + } + + @Override + public int readLength(NetInput in, int available) throws IOException { + return in.readVarInt(); + } + + @Override + public void writeLength(NetOutput out, int length) throws IOException { + out.writeVarInt(length); + } + + @Override + public int readPacketId(NetInput in) throws IOException { + return in.readVarInt(); + } + + @Override + public void writePacketId(NetOutput out, int packetId) throws IOException { + out.writeVarInt(packetId); + } + + private static int varintLength(int i) { + if((i & -128) == 0) { + return 1; + } else if((i & -16384) == 0) { + return 2; + } else if((i & -2097152) == 0) { + return 3; + } else if((i & -268435456) == 0) { + return 4; + } else { + return 5; + } + } + +} diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java new file mode 100644 index 00000000..19052596 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java @@ -0,0 +1,72 @@ +package org.spacehq.packetlib.packet; + +import org.spacehq.packetlib.io.NetInput; +import org.spacehq.packetlib.io.NetOutput; + +import java.io.IOException; + +/** + * The header of a protocol's packets. + */ +public interface PacketHeader { + + /** + * Gets whether the header's length value can vary in size. + * + * @return Whether the header's length value can vary in size. + */ + public boolean isLengthVariable(); + + /** + * Gets the size of the header's length value. + * + * @return The length value's size. + */ + public int getLengthSize(); + + /** + * Gets the size of the header's length value. + * + * @param length Length value to get the size of. + * @return The length value's size. + */ + public int getLengthSize(int length); + + /** + * Reads the length of a packet from the given input. + * + * @param in Input to read from. + * @param available Number of available bytes in the NetInput. + * @return The resulting packet length. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readLength(NetInput in, int available) throws IOException; + + /** + * Writes the length of a packet to the given output. + * + * @param out Output to write to. + * @param length Length to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeLength(NetOutput out, int length) throws IOException; + + /** + * Reads the ID of a packet from the given input. + * + * @param in Input to read from. + * @return The resulting packet ID. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readPacketId(NetInput in) throws IOException; + + /** + * Writes the ID of a packet to the given output. + * + * @param out Output to write to. + * @param packetId Packet ID to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writePacketId(NetOutput out, int packetId) throws IOException; + +} diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java index 265f920e..61ef4e02 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java @@ -18,6 +18,13 @@ public abstract class PacketProtocol { private final Map> incoming = new HashMap>(); private final Map, Integer> outgoing = new HashMap, Integer>(); + /** + * Gets the packet header of this protocol. + * + * @return The protocol's packet header. + */ + public abstract PacketHeader getPacketHeader(); + /** * Called when a client is created with this protocol. * diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java index 6f059cf2..ea655ee9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java @@ -24,14 +24,14 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { NetOutput out = new ByteBufNetOutput(buf); - out.writeVarInt(this.session.getPacketProtocol().getOutgoingId(packet.getClass())); + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet.getClass())); packet.write(out); } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { NetInput in = new ByteBufNetInput(buf); - int id = in.readVarInt(); + int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); packet.read(in); if(packet.isPriority()) { diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java index 01a6929f..17d6e4e2 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java @@ -5,6 +5,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.CorruptedFrameException; +import org.spacehq.packetlib.Session; import org.spacehq.packetlib.tcp.io.ByteBufNetInput; import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; @@ -12,51 +13,48 @@ import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { + private Session session; + + public TcpPacketSizer(Session session) { + this.session = session; + } + @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int length = in.readableBytes(); - out.ensureWritable(varintLength(length) + length); - new ByteBufNetOutput(out).writeVarInt(length); + out.ensureWritable(this.session.getPacketProtocol().getPacketHeader().getLengthSize(length) + length); + this.session.getPacketProtocol().getPacketHeader().writeLength(new ByteBufNetOutput(out), length); out.writeBytes(in); } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - buf.markReaderIndex(); - byte[] lengthBytes = new byte[5]; - for(int index = 0; index < lengthBytes.length; index++) { - if(!buf.isReadable()) { - buf.resetReaderIndex(); - return; - } - - lengthBytes[index] = buf.readByte(); - if(lengthBytes[index] >= 0) { - int length = new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)).readVarInt(); - if(buf.readableBytes() < length) { + int size = this.session.getPacketProtocol().getPacketHeader().getLengthSize(); + if(size > 0) { + buf.markReaderIndex(); + byte[] lengthBytes = new byte[size]; + for(int index = 0; index < lengthBytes.length; index++) { + if(!buf.isReadable()) { buf.resetReaderIndex(); return; } - out.add(buf.readBytes(length)); - return; + lengthBytes[index] = buf.readByte(); + if((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { + int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); + if(buf.readableBytes() < length) { + buf.resetReaderIndex(); + return; + } + + out.add(buf.readBytes(length)); + return; + } } - } - throw new CorruptedFrameException("Length is too long."); - } - - private static int varintLength(int i) { - if((i & -128) == 0) { - return 1; - } else if((i & -16384) == 0) { - return 2; - } else if((i & -2097152) == 0) { - return 3; - } else if((i & -268435456) == 0) { - return 4; + throw new CorruptedFrameException("Length is too long."); } else { - return 5; + out.add(buf); } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index 3dc5fdbe..9ee463c0 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -50,7 +50,7 @@ public class TcpSessionFactory implements SessionFactory { ch.pipeline() .addLast("timer", new ReadTimeoutHandler(30)) .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer()) + .addLast("sizer", new TcpPacketSizer(session)) .addLast("codec", new TcpPacketCodec(session)) .addLast("manager", session); } @@ -73,7 +73,7 @@ public class TcpSessionFactory implements SessionFactory { ch.pipeline() .addLast("timer", new ReadTimeoutHandler(30)) .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer()) + .addLast("sizer", new TcpPacketSizer(session)) .addLast("codec", new TcpPacketCodec(session)) .addLast("manager", session); server.addSession(session); From 00012666582ff796138c38178eb837cb0c5d9e9d Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 21 Jun 2014 19:30:59 -0700 Subject: [PATCH 014/180] Actually read the bytes instead of passing the same buffer to satisfy Netty. --- src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java index 17d6e4e2..fa2bdf75 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java @@ -54,7 +54,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { throw new CorruptedFrameException("Length is too long."); } else { - out.add(buf); + out.add(buf.readBytes(buf.readableBytes())); } } From 6b7b65b015ceccd9a12ce608adeb7fc97e59f70f Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 21 Jun 2014 19:50:34 -0700 Subject: [PATCH 015/180] Allow protocols to specify whether packet sizers or encryptors will ever be added to the connection. --- .../spacehq/packetlib/test/TestProtocol.java | 14 ++++++- .../packetlib/packet/PacketProtocol.java | 30 ++++++++++---- .../packetlib/tcp/TcpSessionFactory.java | 41 +++++++++++-------- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/example/org/spacehq/packetlib/test/TestProtocol.java b/example/org/spacehq/packetlib/test/TestProtocol.java index 93fac89b..c000f8da 100644 --- a/example/org/spacehq/packetlib/test/TestProtocol.java +++ b/example/org/spacehq/packetlib/test/TestProtocol.java @@ -35,8 +35,13 @@ public class TestProtocol extends PacketProtocol { } @Override - public PacketEncryption getEncryption() { - return this.encrypt; + public boolean needsPacketSizer() { + return true; + } + + @Override + public boolean needsPacketEncryptor() { + return true; } @Override @@ -44,6 +49,11 @@ public class TestProtocol extends PacketProtocol { return this.header; } + @Override + public PacketEncryption getEncryption() { + return this.encrypt; + } + @Override public void newClientSession(Client client, Session session) { session.addListener(new ClientSessionListener()); diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java index 61ef4e02..b4c8b5e0 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java @@ -18,6 +18,20 @@ public abstract class PacketProtocol { private final Map> incoming = new HashMap>(); private final Map, Integer> outgoing = new HashMap, Integer>(); + /** + * Gets whether this protocol will ever need a packet sizer. + * + * @return Whether this protocol will ever need a packet sizer. + */ + public abstract boolean needsPacketSizer(); + + /** + * Gets whether this protocol will ever need a packet encryptor. + * + * @return Whether this protocol will ever need a packet encryptor. + */ + public abstract boolean needsPacketEncryptor(); + /** * Gets the packet header of this protocol. * @@ -25,6 +39,13 @@ public abstract class PacketProtocol { */ public abstract PacketHeader getPacketHeader(); + /** + * Gets this protocol's active packet encryption. + * + * @return The protocol's packet encryption, or null if packets should not be encrypted. + */ + public abstract PacketEncryption getEncryption(); + /** * Called when a client is created with this protocol. * @@ -41,15 +62,6 @@ public abstract class PacketProtocol { */ public abstract void newServerSession(Server server, Session session); - /** - * Gets this protocol's active packet encryption. - * - * @return The protocol's packet encryption, or null if packets should not be encrypted. - */ - public PacketEncryption getEncryption() { - return null; - } - /** * Clears all currently registered packets. */ diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index 9ee463c0..bcde0bdf 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -2,10 +2,7 @@ package org.spacehq.packetlib.tcp; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -47,12 +44,18 @@ public class TcpSessionFactory implements SessionFactory { session.getPacketProtocol().newClientSession(client, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ch.pipeline() - .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer(session)) - .addLast("codec", new TcpPacketCodec(session)) - .addLast("manager", session); + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("timer", new ReadTimeoutHandler(30)); + if(session.getPacketProtocol().needsPacketEncryptor()) { + pipeline.addLast("encryption", new TcpPacketEncryptor(session)); + } + + if(session.getPacketProtocol().needsPacketSizer()) { + pipeline.addLast("sizer", new TcpPacketSizer(session)); + } + + pipeline.addLast("codec", new TcpPacketCodec(session)); + pipeline.addLast("manager", session); } }).group(group).remoteAddress(client.getHost(), client.getPort()); return session; @@ -70,12 +73,18 @@ public class TcpSessionFactory implements SessionFactory { session.getPacketProtocol().newServerSession(server, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ch.pipeline() - .addLast("timer", new ReadTimeoutHandler(30)) - .addLast("encryption", new TcpPacketEncryptor(session)) - .addLast("sizer", new TcpPacketSizer(session)) - .addLast("codec", new TcpPacketCodec(session)) - .addLast("manager", session); + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("timer", new ReadTimeoutHandler(30)); + if(session.getPacketProtocol().needsPacketEncryptor()) { + pipeline.addLast("encryption", new TcpPacketEncryptor(session)); + } + + if(session.getPacketProtocol().needsPacketSizer()) { + pipeline.addLast("sizer", new TcpPacketSizer(session)); + } + + pipeline.addLast("codec", new TcpPacketCodec(session)); + pipeline.addLast("manager", session); server.addSession(session); } }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); From 49651dded0256968b2b4e6c29989a24eb5498caa Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 21 Jun 2014 20:15:54 -0700 Subject: [PATCH 016/180] Allow PacketHeader to return -1 for packet IDs to signal that the packet should not be read yet. --- .../java/org/spacehq/packetlib/packet/PacketHeader.java | 2 +- src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java index 19052596..6e9203d4 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java @@ -55,7 +55,7 @@ public interface PacketHeader { * Reads the ID of a packet from the given input. * * @param in Input to read from. - * @return The resulting packet ID. + * @return The resulting packet ID, or -1 if the packet should not be read yet. * @throws java.io.IOException If an I/O error occurs. */ public int readPacketId(NetInput in) throws IOException; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java index ea655ee9..6d40c113 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java @@ -30,8 +30,14 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + int initial = buf.readerIndex(); NetInput in = new ByteBufNetInput(buf); int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); + if(id == -1) { + buf.readerIndex(initial); + return; + } + Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); packet.read(in); if(packet.isPriority()) { From 5e4868a3f32114dcf37622e58ea42348cbaa7c5b Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 28 Jun 2014 16:14:32 -0700 Subject: [PATCH 017/180] Update download URLs --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 470395e9..bcdf9a36 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ See examples/org/spacehq/packetlib/test/PingServerTest.java -------- PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -You can also download a build [here](http://build.spacehq.org/browse/PACKETLIB-MAIN). +Snapshots (if any exist) can be downloaded [here](http://repo.spacehq.org/content/repositories/snapshots/org/spacehq/packetlib). +Releases (if any exist) can be downloaded [here](http://repo.spacehq.org/content/repositories/release/org/spacehq/packetlib). License From 73f375ba20ec3861b869461b5ead713c9ea3a86a Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Wed, 16 Jul 2014 12:46:26 -0700 Subject: [PATCH 018/180] Add packet compression and methods for reading bytes to an existing array. --- .../java/org/spacehq/packetlib/Session.java | 14 ++++ .../org/spacehq/packetlib/io/NetInput.java | 20 +++++ .../packetlib/io/stream/StreamNetInput.java | 10 +++ .../packetlib/tcp/TcpPacketCompression.java | 76 +++++++++++++++++++ .../org/spacehq/packetlib/tcp/TcpSession.java | 20 +++++ .../packetlib/tcp/io/ByteBufNetInput.java | 20 +++++ 6 files changed, 160 insertions(+) create mode 100644 src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index 905b9069..ed82ddb6 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -111,6 +111,20 @@ public interface Session { */ public void callEvent(SessionEvent event); + /** + * Gets the compression packet length threshold for this session (-1 = disabled). + * + * @return This session's compression threshold. + */ + public int getCompressionThreshold(); + + /** + * Sets the compression packet length threshold for this session (-1 = disabled). + * + * @param threshold The new compression threshold. + */ + public void setCompressionThreshold(int threshold); + /** * Returns true if the session is connected. * diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index e04a272f..0ca86311 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -112,6 +112,26 @@ public interface NetInput { */ public byte[] readBytes(int length) throws IOException; + /** + * Reads as much data as possible into the given byte array. + * + * @param b Byte array to read to. + * @return The amount of bytes read, or -1 if no bytes could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readBytes(byte b[]) throws IOException; + + /** + * Reads the given amount of bytes into the given array at the given offset. + * + * @param b Byte array to read to. + * @param offset Offset of the array to read to. + * @param length Length of bytes to read. + * @return The amount of bytes read, or -1 if no bytes could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readBytes(byte b[], int offset, int length) throws IOException; + /** * Reads the next string. * diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index 2d258328..13d1a05a 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -122,6 +122,16 @@ public class StreamNetInput implements NetInput { return b; } + @Override + public int readBytes(byte[] b) throws IOException { + return this.in.read(b); + } + + @Override + public int readBytes(byte[] b, int offset, int length) throws IOException { + return this.in.read(b, offset, length); + } + @Override public String readString() throws IOException { int length = this.readVarInt(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java new file mode 100644 index 00000000..7d709f43 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java @@ -0,0 +1,76 @@ +package org.spacehq.packetlib.tcp; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; +import io.netty.handler.codec.DecoderException; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.tcp.io.ByteBufNetInput; +import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; + +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +public class TcpPacketCompression extends ByteToMessageCodec { + private static final int MAX_COMPRESSED_SIZE = 2097152; + + private Session session; + private Deflater deflater = new Deflater(); + private Inflater inflater = new Inflater(); + private byte buf[] = new byte[8192]; + + public TcpPacketCompression(Session session) { + this.session = session; + } + + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + int readable = in.readableBytes(); + ByteBufNetOutput output = new ByteBufNetOutput(out); + if(readable < this.session.getCompressionThreshold()) { + output.writeVarInt(0); + out.writeBytes(in); + } else { + byte[] bytes = new byte[readable]; + in.readBytes(bytes); + output.writeVarInt(bytes.length); + this.deflater.setInput(bytes, 0, readable); + this.deflater.finish(); + while(!this.deflater.finished()) { + int length = this.deflater.deflate(this.buf); + output.writeBytes(this.buf, length); + } + + this.deflater.reset(); + } + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + if(buf.readableBytes() != 0) { + ByteBufNetInput in = new ByteBufNetInput(buf); + int size = in.readVarInt(); + if(size == 0) { + out.add(in.readBytes(buf.readableBytes())); + } else { + if(size < this.session.getCompressionThreshold()) { + throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); + } + + if(size > MAX_COMPRESSED_SIZE) { + throw new DecoderException("Badly compressed packet: size of " + size + " is larger than protocol maximum of " + MAX_COMPRESSED_SIZE + "."); + } + + byte[] bytes = new byte[buf.readableBytes()]; + in.readBytes(bytes); + this.inflater.setInput(bytes); + byte[] inflated = new byte[size]; + this.inflater.inflate(inflated); + out.add(Unpooled.wrappedBuffer(inflated)); + this.inflater.reset(); + } + } + } +} diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 52f1d048..3a920713 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -23,6 +23,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private Channel channel; private boolean disconnected = false; private boolean writing = false; + private int compressionThreshold = -1; private List packets = new ArrayList(); private Map flags = new HashMap(); @@ -131,6 +132,25 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } + @Override + public int getCompressionThreshold() { + return this.compressionThreshold; + } + + @Override + public void setCompressionThreshold(int threshold) { + this.compressionThreshold = threshold; + if(this.channel != null) { + if(this.compressionThreshold >= 0) { + if(this.channel.pipeline().get("compression") == null) { + this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this)); + } + } else if(this.channel.pipeline().get("compression") != null) { + this.channel.pipeline().remove("compression"); + } + } + } + @Override public boolean isConnected() { return this.channel != null && this.channel.isOpen() && !this.disconnected; diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index 4df13e13..e141ae11 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -99,6 +99,26 @@ public class ByteBufNetInput implements NetInput { return b; } + @Override + public int readBytes(byte[] b) throws IOException { + return this.readBytes(b, 0, b.length); + } + + @Override + public int readBytes(byte[] b, int offset, int length) throws IOException { + int readable = this.buf.readableBytes(); + if(readable <= 0) { + return -1; + } + + if(readable < length) { + length = readable; + } + + this.buf.readBytes(b, offset, length); + return length; + } + @Override public String readString() throws IOException { int length = this.readVarInt(); From 2ce93ace27e801984ff5cc2b8a5d9327ee56fffd Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Mon, 4 Aug 2014 11:28:15 -0700 Subject: [PATCH 019/180] Add VarLong support, fix compression issue. --- .../org/spacehq/packetlib/io/NetInput.java | 8 ++++++ .../org/spacehq/packetlib/io/NetOutput.java | 8 ++++++ .../packetlib/io/stream/StreamNetInput.java | 27 ++++++++++++++----- .../packetlib/io/stream/StreamNetOutput.java | 14 ++++++++-- .../packetlib/tcp/TcpPacketCompression.java | 2 +- .../packetlib/tcp/io/ByteBufNetInput.java | 26 +++++++++++++----- .../packetlib/tcp/io/ByteBufNetOutput.java | 14 ++++++++-- 7 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index 0ca86311..bd9dbe93 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -79,6 +79,14 @@ public interface NetInput { */ public long readLong() throws IOException; + /** + * Reads the next varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. + * + * @return The next varlong. + * @throws java.io.IOException If an I/O error occurs. + */ + public long readVarLong() throws IOException; + /** * Reads the next float. * diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index 4c536133..b3ea3f1e 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -63,6 +63,14 @@ public interface NetOutput { */ public void writeLong(long l) throws IOException; + /** + * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. + * + * @return l Varlong to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeVarLong(long l) throws IOException; + /** * Writes a float. * diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index 13d1a05a..4e256c2c 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -67,17 +67,17 @@ public class StreamNetInput implements NetInput { @Override public int readVarInt() throws IOException { - int ret = 0; + int value = 0; int size = 0; - byte b; - while(((b = this.readByte()) & 128) == 128) { - ret |= (b & 127) << size++ * 7; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); if(size > 5) { - throw new IOException("Varint too big"); + throw new IOException("VarInt too long (length must be <= 5)"); } } - return ret; + return value | ((b & 0x7F) << (size * 7)); } @Override @@ -86,6 +86,21 @@ public class StreamNetInput implements NetInput { return ((long) read[0] << 56) + ((long) (read[1] & 255) << 48) + ((long) (read[2] & 255) << 40) + ((long) (read[3] & 255) << 32) + ((long) (read[4] & 255) << 24) + ((read[5] & 255) << 16) + ((read[6] & 255) << 8) + ((read[7] & 255) << 0); } + @Override + public long readVarLong() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 10) { + throw new IOException("VarLong too long (length must be <= 10)"); + } + } + + return value | ((b & 0x7F) << (size * 7)); + } + @Override public float readFloat() throws IOException { return Float.intBitsToFloat(this.readInt()); diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index cea32190..bfaa878c 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -48,8 +48,8 @@ public class StreamNetOutput implements NetOutput { @Override public void writeVarInt(int i) throws IOException { - while((i & -128) != 0) { - this.writeByte(i & 127 | 128); + while((i & ~0x7F) != 0) { + this.writeByte((i & 0x7F) | 0x80); i >>>= 7; } @@ -68,6 +68,16 @@ public class StreamNetOutput implements NetOutput { this.writeByte((byte) (l >>> 0)); } + @Override + public void writeVarLong(long l) throws IOException { + while((l & ~0x7F) != 0) { + this.writeByte((int) (l & 0x7F) | 0x80); + l >>>= 7; + } + + this.writeByte((int) l); + } + @Override public void writeFloat(float f) throws IOException { this.writeInt(Float.floatToIntBits(f)); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java index 7d709f43..02cbe076 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java @@ -53,7 +53,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { ByteBufNetInput in = new ByteBufNetInput(buf); int size = in.readVarInt(); if(size == 0) { - out.add(in.readBytes(buf.readableBytes())); + out.add(buf.readBytes(buf.readableBytes())); } else { if(size < this.session.getCompressionThreshold()) { throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index e141ae11..a240b506 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -56,15 +56,14 @@ public class ByteBufNetInput implements NetInput { int value = 0; int size = 0; int b; - while(((b = this.readByte()) & 0x80) != 0) { - value |= (b & 0x7F) << size; - size += 7; - if(size > 35) { - throw new IOException("Variable length quantity is too long (must be <= 35)"); + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 5) { + throw new IOException("VarInt too long (length must be <= 5)"); } } - return value | (b << size); + return value | ((b & 0x7F) << (size * 7)); } @Override @@ -72,6 +71,21 @@ public class ByteBufNetInput implements NetInput { return this.buf.readLong(); } + @Override + public long readVarLong() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 10) { + throw new IOException("VarLong too long (length must be <= 10)"); + } + } + + return value | ((b & 0x7F) << (size * 7)); + } + @Override public float readFloat() throws IOException { return this.buf.readFloat(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 41bbee7a..014336e7 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -43,12 +43,12 @@ public class ByteBufNetOutput implements NetOutput { @Override public void writeVarInt(int i) throws IOException { - while((i & 0xFFFFFF80) != 0L) { + while((i & ~0x7F) != 0) { this.writeByte((i & 0x7F) | 0x80); i >>>= 7; } - this.writeByte(i & 0x7F); + this.writeByte(i); } @Override @@ -56,6 +56,16 @@ public class ByteBufNetOutput implements NetOutput { this.buf.writeLong(l); } + @Override + public void writeVarLong(long l) throws IOException { + while((l & ~0x7F) != 0) { + this.writeByte((int) (l & 0x7F) | 0x80); + l >>>= 7; + } + + this.writeByte((int) l); + } + @Override public void writeFloat(float f) throws IOException { this.buf.writeFloat(f); From 1f8abf7eea9cea987770e16237e3f0676c5c01bb Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Mon, 11 Aug 2014 11:34:36 -0700 Subject: [PATCH 020/180] Add methods for reading/writing UUIDs as longs. --- src/main/java/org/spacehq/packetlib/io/NetInput.java | 9 +++++++++ src/main/java/org/spacehq/packetlib/io/NetOutput.java | 9 +++++++++ .../org/spacehq/packetlib/io/stream/StreamNetInput.java | 6 ++++++ .../org/spacehq/packetlib/io/stream/StreamNetOutput.java | 7 +++++++ .../org/spacehq/packetlib/tcp/io/ByteBufNetInput.java | 6 ++++++ .../org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java | 7 +++++++ 6 files changed, 44 insertions(+) diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index bd9dbe93..365793e6 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -1,6 +1,7 @@ package org.spacehq.packetlib.io; import java.io.IOException; +import java.util.UUID; /** * An interface for reading network data. @@ -148,6 +149,14 @@ public interface NetInput { */ public String readString() throws IOException; + /** + * Reads the next UUID. + * + * @return The next UUID. + * @throws java.io.IOException If an I/O error occurs. + */ + public UUID readUUID() throws IOException; + /** * Gets the number of available bytes. * diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index b3ea3f1e..5e438e81 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -1,6 +1,7 @@ package org.spacehq.packetlib.io; import java.io.IOException; +import java.util.UUID; /** * An interface for writing network data. @@ -120,6 +121,14 @@ public interface NetOutput { */ public void writeString(String s) throws IOException; + /** + * Writes a UUID. + * + * @param uuid UUID to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeUUID(UUID uuid) throws IOException; + /** * Flushes the output. * diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index 4e256c2c..f6273be3 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -5,6 +5,7 @@ import org.spacehq.packetlib.io.NetInput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.util.UUID; /** * A NetInput implementation using an InputStream as a backend. @@ -154,6 +155,11 @@ public class StreamNetInput implements NetInput { return new String(bytes, "UTF-8"); } + @Override + public UUID readUUID() throws IOException { + return new UUID(this.readLong(), this.readLong()); + } + @Override public int available() throws IOException { return this.in.available(); diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index bfaa878c..0b3cd7e5 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -4,6 +4,7 @@ import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; import java.io.OutputStream; +import java.util.UUID; /** * A NetOutput implementation using an OutputStream as a backend. @@ -119,6 +120,12 @@ public class StreamNetOutput implements NetOutput { } } + @Override + public void writeUUID(UUID uuid) throws IOException { + this.writeLong(uuid.getMostSignificantBits()); + this.writeLong(uuid.getLeastSignificantBits()); + } + @Override public void flush() throws IOException { this.out.flush(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index a240b506..f7b72b80 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf; import org.spacehq.packetlib.io.NetInput; import java.io.IOException; +import java.util.UUID; /** * A NetInput implementation using a ByteBuf as a backend. @@ -140,6 +141,11 @@ public class ByteBufNetInput implements NetInput { return new String(bytes, "UTF-8"); } + @Override + public UUID readUUID() throws IOException { + return new UUID(this.readLong(), this.readLong()); + } + @Override public int available() throws IOException { return this.buf.readableBytes(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 014336e7..298ae63e 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf; import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; +import java.util.UUID; /** * A NetOutput implementation using a ByteBuf as a backend. @@ -107,6 +108,12 @@ public class ByteBufNetOutput implements NetOutput { } } + @Override + public void writeUUID(UUID uuid) throws IOException { + this.writeLong(uuid.getMostSignificantBits()); + this.writeLong(uuid.getLeastSignificantBits()); + } + @Override public void flush() throws IOException { } From 249511e80fc1b61fe21f225f7dd8d6651bfea0bc Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Tue, 26 Aug 2014 20:21:06 -0700 Subject: [PATCH 021/180] Allow adjusting timeout and performing actions when a timeout occurs. --- .../java/org/spacehq/packetlib/Client.java | 38 +++++++++++++++++++ .../java/org/spacehq/packetlib/Server.java | 38 +++++++++++++++++++ .../org/spacehq/packetlib/TimeoutHandler.java | 5 +++ .../packetlib/tcp/TcpSessionFactory.java | 5 +-- .../packetlib/tcp/TcpTimeoutHandler.java | 24 ++++++++++++ 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/spacehq/packetlib/TimeoutHandler.java create mode 100644 src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java diff --git a/src/main/java/org/spacehq/packetlib/Client.java b/src/main/java/org/spacehq/packetlib/Client.java index 4207abba..91bdc841 100644 --- a/src/main/java/org/spacehq/packetlib/Client.java +++ b/src/main/java/org/spacehq/packetlib/Client.java @@ -11,6 +11,8 @@ public class Client { private int port; private PacketProtocol protocol; private Session session; + private int timeout = 30; + private TimeoutHandler timeoutHandler; public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { this.host = host; @@ -55,4 +57,40 @@ public class Client { return this.session; } + /** + * Gets the session timeout for this client in seconds. + * + * @return The client's session timeout. + */ + public int getTimeout() { + return this.timeout; + } + + /** + * Sets the session timeout for this client in seconds. Note: This will only be applied to sessions created after the timeout is set. + * + * @param timeout Timeout to set in seconds. + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + /** + * Gets the session timeout handler for this client. + * + * @return The client's session timeout handler. + */ + public TimeoutHandler getTimeoutHandler() { + return this.timeoutHandler; + } + + /** + * Sets the session timeout handler for this client. Note: This will only be applied to sessions created after the timeout is set. + * + * @param timeout Timeout handler to set. + */ + public void setTimeoutHandler(TimeoutHandler timeout) { + this.timeoutHandler = timeout; + } + } diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index 315c765d..5e93d1c4 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -18,6 +18,8 @@ public class Server { private int port; private Class protocol; private SessionFactory factory; + private int timeout = 30; + private TimeoutHandler timeoutHandler; private ConnectionListener listener; private List sessions = new ArrayList(); @@ -60,6 +62,42 @@ public class Server { return this.port; } + /** + * Gets the session timeout for this server in seconds. + * + * @return The client's session timeout. + */ + public int getTimeout() { + return this.timeout; + } + + /** + * Sets the session timeout for this server in seconds. Note: This will only be applied to sessions created after the timeout is set. + * + * @param timeout Timeout to set in seconds. + */ + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + /** + * Gets the session timeout handler for this server. + * + * @return The client's session timeout handler. + */ + public TimeoutHandler getTimeoutHandler() { + return this.timeoutHandler; + } + + /** + * Sets the session timeout handler for this server. Note: This will only be applied to sessions created after the timeout is set. + * + * @param timeout Timeout handler to set. + */ + public void setTimeoutHandler(TimeoutHandler timeout) { + this.timeoutHandler = timeout; + } + /** * Gets the packet protocol of the server. * diff --git a/src/main/java/org/spacehq/packetlib/TimeoutHandler.java b/src/main/java/org/spacehq/packetlib/TimeoutHandler.java new file mode 100644 index 00000000..996149e7 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/TimeoutHandler.java @@ -0,0 +1,5 @@ +package org.spacehq.packetlib; + +public interface TimeoutHandler { + public void onTimeout(Session session); +} diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index bcde0bdf..56cab804 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -7,7 +7,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.timeout.ReadTimeoutHandler; import org.spacehq.packetlib.*; import org.spacehq.packetlib.packet.PacketProtocol; @@ -45,7 +44,7 @@ public class TcpSessionFactory implements SessionFactory { ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("timer", new ReadTimeoutHandler(30)); + pipeline.addLast("timer", new TcpTimeoutHandler(session, client.getTimeout(), client.getTimeoutHandler())); if(session.getPacketProtocol().needsPacketEncryptor()) { pipeline.addLast("encryption", new TcpPacketEncryptor(session)); } @@ -74,7 +73,7 @@ public class TcpSessionFactory implements SessionFactory { ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("timer", new ReadTimeoutHandler(30)); + pipeline.addLast("timer", new TcpTimeoutHandler(session, server.getTimeout(), server.getTimeoutHandler())); if(session.getPacketProtocol().needsPacketEncryptor()) { pipeline.addLast("encryption", new TcpPacketEncryptor(session)); } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java b/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java new file mode 100644 index 00000000..849ad991 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java @@ -0,0 +1,24 @@ +package org.spacehq.packetlib.tcp; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.timeout.ReadTimeoutHandler; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.TimeoutHandler; + +public class TcpTimeoutHandler extends ReadTimeoutHandler { + private Session session; + private TimeoutHandler timeoutHandler; + + public TcpTimeoutHandler(Session session, int timeoutSeconds, TimeoutHandler timeoutHandler) { + super(timeoutSeconds); + this.session = session; + this.timeoutHandler = timeoutHandler; + } + + @Override + protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { + if(this.timeoutHandler != null) { + this.timeoutHandler.onTimeout(this.session); + } + } +} From 7b26b14f31dc8479179cd38567d84682afb8bd4e Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 27 Aug 2014 19:53:54 -0700 Subject: [PATCH 022/180] Expand on timeout control. --- .../java/org/spacehq/packetlib/Client.java | 26 ++-- .../java/org/spacehq/packetlib/Server.java | 26 ++-- .../java/org/spacehq/packetlib/Session.java | 42 ++++++ .../org/spacehq/packetlib/TimeoutHandler.java | 2 +- .../org/spacehq/packetlib/TimeoutType.java | 7 + .../packetlib/tcp/TcpServerSession.java | 5 +- .../org/spacehq/packetlib/tcp/TcpSession.java | 124 +++++++++++++++--- .../packetlib/tcp/TcpSessionFactory.java | 14 +- .../packetlib/tcp/TcpTimeoutHandler.java | 24 ---- 9 files changed, 196 insertions(+), 74 deletions(-) create mode 100644 src/main/java/org/spacehq/packetlib/TimeoutType.java delete mode 100644 src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java diff --git a/src/main/java/org/spacehq/packetlib/Client.java b/src/main/java/org/spacehq/packetlib/Client.java index 91bdc841..9a5ede93 100644 --- a/src/main/java/org/spacehq/packetlib/Client.java +++ b/src/main/java/org/spacehq/packetlib/Client.java @@ -58,39 +58,39 @@ public class Client { } /** - * Gets the session timeout for this client in seconds. + * Gets the connect timeout for this client in seconds. * - * @return The client's session timeout. + * @return The client's connect timeout. */ - public int getTimeout() { + public int getConnectTimeout() { return this.timeout; } /** - * Sets the session timeout for this client in seconds. Note: This will only be applied to sessions created after the timeout is set. + * Sets the connect timeout for this client in seconds. * - * @param timeout Timeout to set in seconds. + * @param timeout Connect timeout to set in seconds. */ - public void setTimeout(int timeout) { + public void setConnectTimeout(int timeout) { this.timeout = timeout; } /** - * Gets the session timeout handler for this client. + * Gets the connect timeout handler for this client. * - * @return The client's session timeout handler. + * @return The client's connect timeout handler. */ - public TimeoutHandler getTimeoutHandler() { + public TimeoutHandler getConnectTimeoutHandler() { return this.timeoutHandler; } /** - * Sets the session timeout handler for this client. Note: This will only be applied to sessions created after the timeout is set. + * Sets the connect timeout handler for this client. Note: Takes effect on connect() call. * - * @param timeout Timeout handler to set. + * @param timeoutHandler Connect timeout handler to set. */ - public void setTimeoutHandler(TimeoutHandler timeout) { - this.timeoutHandler = timeout; + public void setConnectTimeoutHandler(TimeoutHandler timeoutHandler) { + this.timeoutHandler = timeoutHandler; } } diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index 5e93d1c4..eff1103a 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -63,39 +63,39 @@ public class Server { } /** - * Gets the session timeout for this server in seconds. + * Gets the connect timeout for this server in seconds. * - * @return The client's session timeout. + * @return The client's connect timeout. */ - public int getTimeout() { + public int getConnectTimeout() { return this.timeout; } /** - * Sets the session timeout for this server in seconds. Note: This will only be applied to sessions created after the timeout is set. + * Sets the connect timeout for this server in seconds. * - * @param timeout Timeout to set in seconds. + * @param timeout Connect timeout to set in seconds. */ - public void setTimeout(int timeout) { + public void setConnectTimeout(int timeout) { this.timeout = timeout; } /** - * Gets the session timeout handler for this server. + * Gets the connect timeout handler for this server. * - * @return The client's session timeout handler. + * @return The client's connect timeout handler. */ - public TimeoutHandler getTimeoutHandler() { + public TimeoutHandler getConnectTimeoutHandler() { return this.timeoutHandler; } /** - * Sets the session timeout handler for this server. Note: This will only be applied to sessions created after the timeout is set. + * Sets the connect timeout handler for this server. * - * @param timeout Timeout handler to set. + * @param timeoutHandler Connect timeout handler to set. */ - public void setTimeoutHandler(TimeoutHandler timeout) { - this.timeoutHandler = timeout; + public void setConnectTimeoutHandler(TimeoutHandler timeoutHandler) { + this.timeoutHandler = timeoutHandler; } /** diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index ed82ddb6..b0d506cc 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -125,6 +125,48 @@ public interface Session { */ public void setCompressionThreshold(int threshold); + /** + * Gets the read timeout for this session in seconds. + * + * @return The session's read timeout. + */ + public int getReadTimeout(); + + /** + * Sets the read timeout for this session in seconds. + * + * @param timeout Read timeout to set in seconds. + */ + public void setReadTimeout(int timeout); + + /** + * Gets the write timeout for this session in seconds. + * + * @return The session's write timeout. + */ + public int getWriteTimeout(); + + /** + * Sets the write timeout for this session in seconds. + * + * @param timeout Write timeout to set in seconds. + */ + public void setWriteTimeout(int timeout); + + /** + * Gets the timeout handler for this session. + * + * @return The session's timeout handler. + */ + public TimeoutHandler getTimeoutHandler(); + + /** + * Sets the timeout handler for this session. + * + * @param timeout Timeout handler to set. + */ + public void setTimeoutHandler(TimeoutHandler timeout); + /** * Returns true if the session is connected. * diff --git a/src/main/java/org/spacehq/packetlib/TimeoutHandler.java b/src/main/java/org/spacehq/packetlib/TimeoutHandler.java index 996149e7..18c7b1f6 100644 --- a/src/main/java/org/spacehq/packetlib/TimeoutHandler.java +++ b/src/main/java/org/spacehq/packetlib/TimeoutHandler.java @@ -1,5 +1,5 @@ package org.spacehq.packetlib; public interface TimeoutHandler { - public void onTimeout(Session session); + public void onTimeout(Session session, TimeoutType type); } diff --git a/src/main/java/org/spacehq/packetlib/TimeoutType.java b/src/main/java/org/spacehq/packetlib/TimeoutType.java new file mode 100644 index 00000000..e128e469 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/TimeoutType.java @@ -0,0 +1,7 @@ +package org.spacehq.packetlib; + +public enum TimeoutType { + CONNECT, + READ, + WRITE; +} diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index 90752133..3529c52a 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -4,6 +4,7 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.TimeoutHandler; import org.spacehq.packetlib.packet.PacketProtocol; import java.util.Map; @@ -12,8 +13,8 @@ public class TcpServerSession extends TcpSession { private Server server; - public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server) { - super(host, port, protocol, group, bootstrap); + public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server, TimeoutHandler connectTimeoutHandler) { + super(host, port, protocol, group, bootstrap, connectTimeoutHandler); this.server = server; } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 3a920713..961e2fd9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -3,7 +3,12 @@ package org.spacehq.packetlib.tcp; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.TimeoutException; +import io.netty.handler.timeout.WriteTimeoutHandler; import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.TimeoutHandler; +import org.spacehq.packetlib.TimeoutType; import org.spacehq.packetlib.event.session.*; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; @@ -24,17 +29,22 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private boolean disconnected = false; private boolean writing = false; private int compressionThreshold = -1; + private int readTimeout = 30; + private int writeTimeout = 0; + private TimeoutHandler timeoutHandler = null; + private TimeoutHandler connectTimeoutHandler = null; private List packets = new ArrayList(); private Map flags = new HashMap(); private List listeners = new ArrayList(); - public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap) { + public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, TimeoutHandler connectTimeoutHandler) { this.host = host; this.port = port; this.protocol = protocol; this.group = group; this.bootstrap = bootstrap; + this.connectTimeoutHandler = connectTimeoutHandler; } @Override @@ -128,7 +138,12 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public void callEvent(SessionEvent event) { for(SessionListener listener : this.listeners) { - event.call(listener); + try { + event.call(listener); + } catch(Throwable t) { + System.err.println("[WARNING] Throwable caught while firing event."); + t.printStackTrace(); + } } } @@ -151,6 +166,38 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } + @Override + public int getReadTimeout() { + return this.readTimeout; + } + + @Override + public void setReadTimeout(int timeout) { + this.readTimeout = timeout; + this.refreshReadTimeoutHandler(); + } + + @Override + public int getWriteTimeout() { + return this.readTimeout; + } + + @Override + public void setWriteTimeout(int timeout) { + this.writeTimeout = timeout; + this.refreshWriteTimeoutHandler(); + } + + @Override + public TimeoutHandler getTimeoutHandler() { + return this.timeoutHandler; + } + + @Override + public void setTimeoutHandler(TimeoutHandler timeoutHandler) { + this.timeoutHandler = timeoutHandler; + } + @Override public boolean isConnected() { return this.channel != null && this.channel.isOpen() && !this.disconnected; @@ -211,31 +258,68 @@ public class TcpSession extends SimpleChannelInboundHandler implements S reason = "Connection closed."; } - try { - if(this.channel != null) { - if(this.channel.isOpen()) { - this.callEvent(new DisconnectingEvent(this, reason)); - } - - this.channel.close().syncUninterruptibly(); + if(this.channel != null) { + if(this.channel.isOpen()) { + this.callEvent(new DisconnectingEvent(this, reason)); } - this.callEvent(new DisconnectedEvent(this, reason)); - } catch(Throwable t) { - System.err.println("[WARNING] Throwable caught while firing disconnect events."); - t.printStackTrace(); + try { + this.channel.close().syncUninterruptibly(); + } catch(Throwable t) { + } } + this.callEvent(new DisconnectedEvent(this, reason)); if(this.group != null) { try { this.group.shutdownGracefully(); - } catch(Exception e) { + } catch(Throwable t) { } } this.channel = null; } + protected void refreshReadTimeoutHandler() { + this.refreshReadTimeoutHandler(this.channel); + } + + protected void refreshReadTimeoutHandler(Channel channel) { + if(channel != null) { + if(this.readTimeout <= 0) { + if(channel.pipeline().get("readTimeout") != null) { + channel.pipeline().remove("readTimeout"); + } + } else { + if(channel.pipeline().get("readTimeout") == null) { + channel.pipeline().addFirst("readTimeout", new ReadTimeoutHandler(this.readTimeout)); + } else { + channel.pipeline().replace("readTimeout", "readTimeout", new ReadTimeoutHandler(this.readTimeout)); + } + } + } + } + + protected void refreshWriteTimeoutHandler() { + this.refreshWriteTimeoutHandler(this.channel); + } + + protected void refreshWriteTimeoutHandler(Channel channel) { + if(channel != null) { + if(this.writeTimeout <= 0) { + if(channel.pipeline().get("writeTimeout") != null) { + channel.pipeline().remove("writeTimeout"); + } + } else { + if(channel.pipeline().get("writeTimeout") == null) { + channel.pipeline().addFirst("writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); + } else { + channel.pipeline().replace("writeTimeout", "writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); + } + } + } + } + @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { if(this.disconnected) { @@ -258,7 +342,17 @@ public class TcpSession extends SimpleChannelInboundHandler implements S public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { this.writing = false; if(!this.disconnected) { - if(cause instanceof ReadTimeoutException) { + if(cause instanceof TimeoutException) { + if(this.timeoutHandler != null) { + this.timeoutHandler.onTimeout(this, cause instanceof ReadTimeoutException ? TimeoutType.READ : TimeoutType.WRITE); + } + + this.disconnect("Connection timed out."); + } else if(cause instanceof ConnectTimeoutException) { + if(this.connectTimeoutHandler != null) { + this.connectTimeoutHandler.onTimeout(this, TimeoutType.CONNECT); + } + this.disconnect("Connection timed out."); } else { this.disconnect("Internal network exception: " + cause.toString()); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index 56cab804..d3296c97 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -36,7 +36,7 @@ public class TcpSessionFactory implements SessionFactory { bootstrap.channel(NioSocketChannel.class); } - final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap); + final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap, client.getConnectTimeoutHandler()); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { @@ -44,7 +44,8 @@ public class TcpSessionFactory implements SessionFactory { ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("timer", new TcpTimeoutHandler(session, client.getTimeout(), client.getTimeoutHandler())); + session.refreshReadTimeoutHandler(ch); + session.refreshWriteTimeoutHandler(ch); if(session.getPacketProtocol().needsPacketEncryptor()) { pipeline.addLast("encryption", new TcpPacketEncryptor(session)); } @@ -56,7 +57,7 @@ public class TcpSessionFactory implements SessionFactory { pipeline.addLast("codec", new TcpPacketCodec(session)); pipeline.addLast("manager", session); } - }).group(group).remoteAddress(client.getHost(), client.getPort()); + }).group(group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, client.getConnectTimeout() * 1000).remoteAddress(client.getHost(), client.getPort()); return session; } @@ -68,12 +69,13 @@ public class TcpSessionFactory implements SessionFactory { public void initChannel(Channel ch) throws Exception { InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); PacketProtocol protocol = server.createPacketProtocol(); - TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server, server.getConnectTimeoutHandler()); session.getPacketProtocol().newServerSession(server, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("timer", new TcpTimeoutHandler(session, server.getTimeout(), server.getTimeoutHandler())); + session.refreshReadTimeoutHandler(ch); + session.refreshWriteTimeoutHandler(ch); if(session.getPacketProtocol().needsPacketEncryptor()) { pipeline.addLast("encryption", new TcpPacketEncryptor(session)); } @@ -86,7 +88,7 @@ public class TcpSessionFactory implements SessionFactory { pipeline.addLast("manager", session); server.addSession(session); } - }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); + }).group(group).localAddress(server.getHost(), server.getPort()).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, server.getConnectTimeout() * 1000).bind().syncUninterruptibly().channel()); } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java b/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java deleted file mode 100644 index 849ad991..00000000 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpTimeoutHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.spacehq.packetlib.tcp; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.timeout.ReadTimeoutHandler; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.TimeoutHandler; - -public class TcpTimeoutHandler extends ReadTimeoutHandler { - private Session session; - private TimeoutHandler timeoutHandler; - - public TcpTimeoutHandler(Session session, int timeoutSeconds, TimeoutHandler timeoutHandler) { - super(timeoutSeconds); - this.session = session; - this.timeoutHandler = timeoutHandler; - } - - @Override - protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { - if(this.timeoutHandler != null) { - this.timeoutHandler.onTimeout(this.session); - } - } -} From 8fa57eb73a9e888068860f5c737f039e7cb6aaad Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 19:13:25 -0700 Subject: [PATCH 023/180] Call timeout handler if connect future results in a ConnectTimeoutException. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 961e2fd9..50294a99 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -63,6 +63,15 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } ChannelFuture future = this.bootstrap.connect(); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null) { + connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + } + } + }); + this.bootstrap = null; if(wait) { future.syncUninterruptibly(); From d418516fe311f0c43b9ce0a02129b5f565b18ed1 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 19:15:55 -0700 Subject: [PATCH 024/180] Minor message update. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 50294a99..0bf4fedc 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -58,7 +58,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S if(!this.disconnected) { return; } else { - throw new IllegalStateException("Session disconnected."); + throw new IllegalStateException("Session has already been disconnected."); } } From 9cbdc6a1aa728c6f5a8a867b9bb2d62700747ce3 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 19:19:57 -0700 Subject: [PATCH 025/180] More clarification to timeout disconnect messages. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 0bf4fedc..7d914b2d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -356,7 +356,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.timeoutHandler.onTimeout(this, cause instanceof ReadTimeoutException ? TimeoutType.READ : TimeoutType.WRITE); } - this.disconnect("Connection timed out."); + this.disconnect((cause instanceof ReadTimeoutException ? "Read" : "Write") + " timed out."); } else if(cause instanceof ConnectTimeoutException) { if(this.connectTimeoutHandler != null) { this.connectTimeoutHandler.onTimeout(this, TimeoutType.CONNECT); From 670f5fb219f749babdb8c4ef3a3398049d312974 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 19:46:05 -0700 Subject: [PATCH 026/180] Use try-catch for connect timeout exception if waiting. --- .../org/spacehq/packetlib/tcp/TcpSession.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 7d914b2d..34d7a959 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -63,24 +63,34 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } ChannelFuture future = this.bootstrap.connect(); - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null) { - connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); - } - } - }); - this.bootstrap = null; if(wait) { - future.syncUninterruptibly(); + try { + future.syncUninterruptibly(); + } catch(Exception e) { + if(e instanceof ConnectTimeoutException && connectTimeoutHandler != null) { + connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + } else { + System.err.println("Failed to establish connection."); + e.printStackTrace(); + } + } + while(this.channel == null && !this.disconnected) { try { Thread.sleep(5); } catch(InterruptedException e) { } } + } else { + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null) { + connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + } + } + }); } } From 7b3146c4d48f0299c3cbfad84e6ccf39c0c53735 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 20:14:14 -0700 Subject: [PATCH 027/180] Catch timeout exceptions throughout all of the connect method, tweak connect timeout application. --- .../org/spacehq/packetlib/tcp/TcpSession.java | 56 ++++++++++--------- .../packetlib/tcp/TcpSessionFactory.java | 7 ++- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 34d7a959..9d03402b 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; public class TcpSession extends SimpleChannelInboundHandler implements Session { @@ -62,35 +63,36 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } } - ChannelFuture future = this.bootstrap.connect(); - this.bootstrap = null; - if(wait) { - try { - future.syncUninterruptibly(); - } catch(Exception e) { - if(e instanceof ConnectTimeoutException && connectTimeoutHandler != null) { - connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); - } else { - System.err.println("Failed to establish connection."); - e.printStackTrace(); - } - } - - while(this.channel == null && !this.disconnected) { - try { - Thread.sleep(5); - } catch(InterruptedException e) { - } - } - } else { - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null) { - connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + final AtomicBoolean calledTimeout = new AtomicBoolean(false); + try { + ChannelFuture future = this.bootstrap.connect(); + this.bootstrap = null; + if(wait) { + while(this.channel == null && !this.disconnected) { + try { + Thread.sleep(5); + } catch(InterruptedException e) { } } - }); + } else { + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null && !calledTimeout.get()) { + connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + calledTimeout.set(true); + } + } + }); + } + } catch(Exception e) { + if(e instanceof ConnectTimeoutException && connectTimeoutHandler != null && !calledTimeout.get()) { + connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + calledTimeout.set(true); + } else { + System.err.println("Failed to establish connection."); + e.printStackTrace(); + } } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index d3296c97..fc61d99a 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -36,6 +36,7 @@ public class TcpSessionFactory implements SessionFactory { bootstrap.channel(NioSocketChannel.class); } + bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, client.getConnectTimeout() * 1000); final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap, client.getConnectTimeoutHandler()); bootstrap.handler(new ChannelInitializer() { @Override @@ -57,14 +58,14 @@ public class TcpSessionFactory implements SessionFactory { pipeline.addLast("codec", new TcpPacketCodec(session)); pipeline.addLast("manager", session); } - }).group(group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, client.getConnectTimeout() * 1000).remoteAddress(client.getHost(), client.getPort()); + }).group(group).remoteAddress(client.getHost(), client.getPort()); return session; } @Override public ConnectionListener createServerListener(final Server server) { final EventLoopGroup group = new NioEventLoopGroup(); - return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, server.getConnectTimeout() * 1000).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); @@ -88,7 +89,7 @@ public class TcpSessionFactory implements SessionFactory { pipeline.addLast("manager", session); server.addSession(session); } - }).group(group).localAddress(server.getHost(), server.getPort()).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, server.getConnectTimeout() * 1000).bind().syncUninterruptibly().channel()); + }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); } } From 11ce15cb033d96b1f4b5b5d3398d8d8df758d889 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 20:43:39 -0700 Subject: [PATCH 028/180] Ensure currently set timeout and handler is used. --- .../java/org/spacehq/packetlib/Client.java | 2 +- .../ConnectTimeoutHandlerContainer.java | 7 ++++++ .../java/org/spacehq/packetlib/Server.java | 2 +- .../packetlib/tcp/TcpServerSession.java | 5 ++-- .../org/spacehq/packetlib/tcp/TcpSession.java | 23 +++++++++---------- .../packetlib/tcp/TcpSessionFactory.java | 4 ++-- 6 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java diff --git a/src/main/java/org/spacehq/packetlib/Client.java b/src/main/java/org/spacehq/packetlib/Client.java index 9a5ede93..21c7ef59 100644 --- a/src/main/java/org/spacehq/packetlib/Client.java +++ b/src/main/java/org/spacehq/packetlib/Client.java @@ -5,7 +5,7 @@ import org.spacehq.packetlib.packet.PacketProtocol; /** * A client that may connect to a server. */ -public class Client { +public class Client implements ConnectTimeoutHandlerContainer { private String host; private int port; diff --git a/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java b/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java new file mode 100644 index 00000000..d5998064 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java @@ -0,0 +1,7 @@ +package org.spacehq.packetlib; + +public interface ConnectTimeoutHandlerContainer { + public int getConnectTimeout(); + + public TimeoutHandler getConnectTimeoutHandler(); +} diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index eff1103a..e8712d90 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -12,7 +12,7 @@ import java.util.Map; /** * A server that listens on a given host and port. */ -public class Server { +public class Server implements ConnectTimeoutHandlerContainer { private String host; private int port; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index 3529c52a..ab47dcc9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -4,7 +4,6 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.EventLoopGroup; import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.TimeoutHandler; import org.spacehq.packetlib.packet.PacketProtocol; import java.util.Map; @@ -13,8 +12,8 @@ public class TcpServerSession extends TcpSession { private Server server; - public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server, TimeoutHandler connectTimeoutHandler) { - super(host, port, protocol, group, bootstrap, connectTimeoutHandler); + public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server) { + super(host, port, protocol, group, bootstrap, server); this.server = server; } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 9d03402b..18ed2514 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -6,9 +6,7 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.TimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.TimeoutHandler; -import org.spacehq.packetlib.TimeoutType; +import org.spacehq.packetlib.*; import org.spacehq.packetlib.event.session.*; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; @@ -33,19 +31,19 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private int readTimeout = 30; private int writeTimeout = 0; private TimeoutHandler timeoutHandler = null; - private TimeoutHandler connectTimeoutHandler = null; + private ConnectTimeoutHandlerContainer container; private List packets = new ArrayList(); private Map flags = new HashMap(); private List listeners = new ArrayList(); - public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, TimeoutHandler connectTimeoutHandler) { + public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, ConnectTimeoutHandlerContainer container) { this.host = host; this.port = port; this.protocol = protocol; this.group = group; this.bootstrap = bootstrap; - this.connectTimeoutHandler = connectTimeoutHandler; + this.container = container; } @Override @@ -65,6 +63,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S final AtomicBoolean calledTimeout = new AtomicBoolean(false); try { + this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.container.getConnectTimeout()); ChannelFuture future = this.bootstrap.connect(); this.bootstrap = null; if(wait) { @@ -78,16 +77,16 @@ public class TcpSession extends SimpleChannelInboundHandler implements S future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.cause() instanceof ConnectTimeoutException && connectTimeoutHandler != null && !calledTimeout.get()) { - connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + if(channelFuture.cause() instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { + container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); calledTimeout.set(true); } } }); } } catch(Exception e) { - if(e instanceof ConnectTimeoutException && connectTimeoutHandler != null && !calledTimeout.get()) { - connectTimeoutHandler.onTimeout(TcpSession.this, TimeoutType.CONNECT); + if(e instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { + container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); calledTimeout.set(true); } else { System.err.println("Failed to establish connection."); @@ -370,8 +369,8 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.disconnect((cause instanceof ReadTimeoutException ? "Read" : "Write") + " timed out."); } else if(cause instanceof ConnectTimeoutException) { - if(this.connectTimeoutHandler != null) { - this.connectTimeoutHandler.onTimeout(this, TimeoutType.CONNECT); + if(this.container.getConnectTimeoutHandler() != null) { + this.container.getConnectTimeoutHandler().onTimeout(this, TimeoutType.CONNECT); } this.disconnect("Connection timed out."); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index fc61d99a..03700a0d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -37,7 +37,7 @@ public class TcpSessionFactory implements SessionFactory { } bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, client.getConnectTimeout() * 1000); - final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap, client.getConnectTimeoutHandler()); + final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap, client); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { @@ -70,7 +70,7 @@ public class TcpSessionFactory implements SessionFactory { public void initChannel(Channel ch) throws Exception { InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); PacketProtocol protocol = server.createPacketProtocol(); - TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server, server.getConnectTimeoutHandler()); + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); session.getPacketProtocol().newServerSession(server, session); ch.config().setOption(ChannelOption.IP_TOS, 0x18); ch.config().setOption(ChannelOption.TCP_NODELAY, false); From 65e3518aaf6598241e3ef6818335eb8f1a352152 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 14 Sep 2014 21:03:12 -0700 Subject: [PATCH 029/180] Timeout should be multiplied by 1000 for milliseconds. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 18ed2514..e337fc01 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -63,7 +63,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S final AtomicBoolean calledTimeout = new AtomicBoolean(false); try { - this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.container.getConnectTimeout()); + this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.container.getConnectTimeout() * 1000); ChannelFuture future = this.bootstrap.connect(); this.bootstrap = null; if(wait) { @@ -78,16 +78,16 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { if(channelFuture.cause() instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { - container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); calledTimeout.set(true); + container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); } } }); } } catch(Exception e) { if(e instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { - container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); calledTimeout.set(true); + container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); } else { System.err.println("Failed to establish connection."); e.printStackTrace(); From 4cf17e3dea8514ae3653aadca802cd736832d786 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 23 Nov 2014 16:15:20 -0800 Subject: [PATCH 030/180] Fix getWriteTimeout --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index e337fc01..d28ef619 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -199,7 +199,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public int getWriteTimeout() { - return this.readTimeout; + return this.writeTimeout; } @Override From 634e89ff04557bd5f00d04dd21550db24d0afa36 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sun, 25 Jan 2015 09:41:37 -0800 Subject: [PATCH 031/180] Add exception boolean to TcpSession to halt loops if an exception occurs. --- .../java/org/spacehq/packetlib/tcp/TcpSession.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index d28ef619..34c3407d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -27,6 +27,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private Channel channel; private boolean disconnected = false; private boolean writing = false; + private boolean exception = false; private int compressionThreshold = -1; private int readTimeout = 30; private int writeTimeout = 0; @@ -67,7 +68,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S ChannelFuture future = this.bootstrap.connect(); this.bootstrap = null; if(wait) { - while(this.channel == null && !this.disconnected) { + while(this.channel == null && !this.disconnected && !this.exception) { try { Thread.sleep(5); } catch(InterruptedException e) { @@ -244,7 +245,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S }); if(packet.isPriority()) { - while(this.writing) { + while(this.writing && !this.exception) { try { Thread.sleep(2); } catch(InterruptedException e) { @@ -261,7 +262,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S this.disconnected = true; if(this.writing) { - while(this.writing) { + while(this.writing && !this.exception) { try { Thread.sleep(2); } catch(InterruptedException e) { @@ -361,6 +362,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { this.writing = false; + this.exception = true; if(!this.disconnected) { if(cause instanceof TimeoutException) { if(this.timeoutHandler != null) { @@ -394,7 +396,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S @Override public void run() { try { - while(!disconnected) { + while(!disconnected && !exception) { while(packets.size() > 0) { callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); } From 3d3ebad1f4428a534739db8c9ddee890b1b58d90 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 17 Apr 2015 08:40:26 -0700 Subject: [PATCH 032/180] Listen for future errors and wait using awaitUninterruptibly in TcpSession.connect. --- .../org/spacehq/packetlib/tcp/TcpSession.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 34c3407d..1e24504d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -66,24 +66,22 @@ public class TcpSession extends SimpleChannelInboundHandler implements S try { this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.container.getConnectTimeout() * 1000); ChannelFuture future = this.bootstrap.connect(); - this.bootstrap = null; - if(wait) { - while(this.channel == null && !this.disconnected && !this.exception) { - try { - Thread.sleep(5); - } catch(InterruptedException e) { + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.cause() instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { + calledTimeout.set(true); + container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); + } else if(channelFuture.cause() != null) { + System.err.println("Failed to establish connection."); + channelFuture.cause().printStackTrace(); } } - } else { - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.cause() instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { - calledTimeout.set(true); - container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); - } - } - }); + }); + + this.bootstrap = null; + if(wait) { + future.awaitUninterruptibly(); } } catch(Exception e) { if(e instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { From 3687891770efbf55c36d94bd9c6096e2e9821f91 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 17 Apr 2015 08:47:10 -0700 Subject: [PATCH 033/180] Further improvements to exception handling. --- .../org/spacehq/packetlib/tcp/TcpSession.java | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 1e24504d..f0bf1105 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -69,12 +69,8 @@ public class TcpSession extends SimpleChannelInboundHandler implements S future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.cause() instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { - calledTimeout.set(true); - container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); - } else if(channelFuture.cause() != null) { - System.err.println("Failed to establish connection."); - channelFuture.cause().printStackTrace(); + if(!channelFuture.isSuccess() && channelFuture.cause() != null) { + exceptionCaught(null, channelFuture.cause()); } } }); @@ -84,13 +80,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S future.awaitUninterruptibly(); } } catch(Exception e) { - if(e instanceof ConnectTimeoutException && container.getConnectTimeoutHandler() != null && !calledTimeout.get()) { - calledTimeout.set(true); - container.getConnectTimeoutHandler().onTimeout(TcpSession.this, TimeoutType.CONNECT); - } else { - System.err.println("Failed to establish connection."); - e.printStackTrace(); - } + exceptionCaught(null, e); } } @@ -358,26 +348,31 @@ public class TcpSession extends SimpleChannelInboundHandler implements S } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { this.writing = false; this.exception = true; - if(!this.disconnected) { - if(cause instanceof TimeoutException) { - if(this.timeoutHandler != null) { - this.timeoutHandler.onTimeout(this, cause instanceof ReadTimeoutException ? TimeoutType.READ : TimeoutType.WRITE); - } - - this.disconnect((cause instanceof ReadTimeoutException ? "Read" : "Write") + " timed out."); - } else if(cause instanceof ConnectTimeoutException) { - if(this.container.getConnectTimeoutHandler() != null) { - this.container.getConnectTimeoutHandler().onTimeout(this, TimeoutType.CONNECT); - } - - this.disconnect("Connection timed out."); - } else { - this.disconnect("Internal network exception: " + cause.toString()); - cause.printStackTrace(); + if(cause instanceof TimeoutException) { + if(this.timeoutHandler != null) { + this.timeoutHandler.onTimeout(this, cause instanceof ReadTimeoutException ? TimeoutType.READ : TimeoutType.WRITE); } + + if(!this.disconnected) { + this.disconnect((cause instanceof ReadTimeoutException ? "Read" : "Write") + " timed out."); + } + } else if(cause instanceof ConnectTimeoutException) { + if(this.container.getConnectTimeoutHandler() != null) { + this.container.getConnectTimeoutHandler().onTimeout(this, TimeoutType.CONNECT); + } + + if(!this.disconnected) { + this.disconnect("Connection timed out."); + } + } else { + if(!this.disconnected) { + this.disconnect("Internal network exception: " + cause.toString()); + } + + cause.printStackTrace(); } this.disconnected = true; From aa1c3051a927b9c91814c7b80081a6f5c1e012f8 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 2 May 2015 14:14:05 -0700 Subject: [PATCH 034/180] Fix TcpSession CME. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index f0bf1105..ba44b904 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -6,7 +6,10 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.TimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; -import org.spacehq.packetlib.*; +import org.spacehq.packetlib.ConnectTimeoutHandlerContainer; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.TimeoutHandler; +import org.spacehq.packetlib.TimeoutType; import org.spacehq.packetlib.event.session.*; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; @@ -15,6 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; public class TcpSession extends SimpleChannelInboundHandler implements Session { @@ -36,7 +40,7 @@ public class TcpSession extends SimpleChannelInboundHandler implements S private List packets = new ArrayList(); private Map flags = new HashMap(); - private List listeners = new ArrayList(); + private List listeners = new CopyOnWriteArrayList(); public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, ConnectTimeoutHandlerContainer container) { this.host = host; From 83161ffa032cdcee8a0fd26e4824ed30c58f8daa Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 18 Jul 2015 18:55:00 -0700 Subject: [PATCH 035/180] Update to Netty 5.0.0.Alpha2 --- pom.xml | 6 +++++- .../org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java | 8 +++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 93eced0a..74fd50b5 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ io.netty netty-all - 5.0.0.Alpha1 + 5.0.0.Alpha2 @@ -77,6 +77,10 @@ org.apache.maven.plugins maven-compiler-plugin 2.3.2 + + 1.6 + 1.6 + diff --git a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java index 22e54409..63d82baf 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java @@ -1,7 +1,6 @@ package org.spacehq.packetlib.tcp; -import io.netty.bootstrap.ChannelFactory; -import io.netty.channel.EventLoop; +import io.netty.channel.ChannelFactory; import io.netty.channel.socket.oio.OioSocketChannel; import java.net.Proxy; @@ -16,8 +15,7 @@ public class ProxyOioChannelFactory implements ChannelFactory } @Override - public OioSocketChannel newChannel(EventLoop eventLoop) { - return new OioSocketChannel(eventLoop, new Socket(this.proxy)); + public OioSocketChannel newChannel() { + return new OioSocketChannel(new Socket(this.proxy)); } - } From 26e6ae38a57e2011303eb0ee94fd711070922a63 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Mon, 20 Jul 2015 11:02:42 -0700 Subject: [PATCH 036/180] General cleanup, fixes, and re-versioning. --- .gitignore | 5 +- LICENSE.txt | 2 +- README.md | 31 +- .../packetlib/test/ClientSessionListener.java | 54 +- .../spacehq/packetlib/test/PingPacket.java | 46 +- .../packetlib/test/PingServerTest.java | 38 +- .../packetlib/test/ServerListener.java | 52 +- .../packetlib/test/ServerSessionListener.java | 32 +- .../spacehq/packetlib/test/TestProtocol.java | 79 +-- pom.xml | 57 +- .../java/org/spacehq/packetlib/Client.java | 126 ++-- .../ConnectTimeoutHandlerContainer.java | 7 - .../spacehq/packetlib/ConnectionListener.java | 56 +- .../java/org/spacehq/packetlib/Server.java | 463 ++++++------ .../java/org/spacehq/packetlib/Session.java | 325 +++++---- .../org/spacehq/packetlib/SessionFactory.java | 30 +- .../org/spacehq/packetlib/TimeoutHandler.java | 5 - .../org/spacehq/packetlib/TimeoutType.java | 7 - .../packetlib/crypt/AESEncryption.java | 56 +- .../packetlib/crypt/PacketEncryption.java | 70 +- .../packetlib/event/server/ServerAdapter.java | 32 +- .../event/server/ServerBoundEvent.java | 39 +- .../event/server/ServerClosedEvent.java | 39 +- .../event/server/ServerClosingEvent.java | 39 +- .../packetlib/event/server/ServerEvent.java | 14 +- .../event/server/ServerListener.java | 62 +- .../event/server/SessionAddedEvent.java | 60 +- .../event/server/SessionRemovedEvent.java | 60 +- .../event/session/ConnectedEvent.java | 39 +- .../event/session/DisconnectedEvent.java | 78 ++- .../event/session/DisconnectingEvent.java | 78 ++- .../event/session/PacketReceivedEvent.java | 72 +- .../event/session/PacketSentEvent.java | 72 +- .../event/session/SessionAdapter.java | 32 +- .../packetlib/event/session/SessionEvent.java | 14 +- .../event/session/SessionListener.java | 62 +- .../org/spacehq/packetlib/io/NetInput.java | 276 ++++---- .../org/spacehq/packetlib/io/NetOutput.java | 226 +++--- .../packetlib/io/stream/StreamNetInput.java | 259 +++---- .../packetlib/io/stream/StreamNetOutput.java | 205 +++--- .../packetlib/packet/DefaultPacketHeader.java | 85 ++- .../org/spacehq/packetlib/packet/Packet.java | 42 +- .../packetlib/packet/PacketHeader.java | 106 ++- .../packetlib/packet/PacketProtocol.java | 240 +++---- .../packetlib/tcp/ProxyOioChannelFactory.java | 17 +- .../packetlib/tcp/TcpClientSession.java | 140 ++++ .../packetlib/tcp/TcpConnectionListener.java | 133 +++- .../spacehq/packetlib/tcp/TcpPacketCodec.java | 54 +- .../packetlib/tcp/TcpPacketCompression.java | 104 +-- .../packetlib/tcp/TcpPacketEncryptor.java | 82 ++- .../spacehq/packetlib/tcp/TcpPacketSizer.java | 78 +-- .../packetlib/tcp/TcpServerSession.java | 40 +- .../org/spacehq/packetlib/tcp/TcpSession.java | 656 ++++++++---------- .../packetlib/tcp/TcpSessionFactory.java | 106 +-- .../packetlib/tcp/io/ByteBufNetInput.java | 230 +++--- .../packetlib/tcp/io/ByteBufNetOutput.java | 174 +++-- 56 files changed, 2821 insertions(+), 2765 deletions(-) delete mode 100644 src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java delete mode 100644 src/main/java/org/spacehq/packetlib/TimeoutHandler.java delete mode 100644 src/main/java/org/spacehq/packetlib/TimeoutType.java create mode 100644 src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java diff --git a/.gitignore b/.gitignore index 13f68391..91cac5b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,13 @@ bin lib +target +testing .settings .classpath .project +.directory *.iml .idea -target - diff --git a/LICENSE.txt b/LICENSE.txt index cff88880..e69695f5 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2013-2014 Steveice10 +Copyright (C) 2013-2015 Steveice10 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index bcdf9a36..3714f38d 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,13 @@ -

PacketLib

-========== +# PacketLib +PacketLib is a library for packet-based networking between clients and servers It was made as a basis for other projects involving packet networking. +## Test Example +See examples/org/spacehq/packetlib/test -About PacketLib --------- - -PacketLib is a library for networking between clients and servers with packets. It was made as a basis for other projects involving packet networking. - - -Test Example --------- - -See examples/org/spacehq/packetlib/test/PingServerTest.java - - -Building the Source --------- - +## Building the Source PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -Snapshots (if any exist) can be downloaded [here](http://repo.spacehq.org/content/repositories/snapshots/org/spacehq/packetlib). -Releases (if any exist) can be downloaded [here](http://repo.spacehq.org/content/repositories/release/org/spacehq/packetlib). +Builds can be downloaded **[here](http://build.spacehq.org/job/PacketLib)**. -License ---------- - -PacketLib is licensed under the [MIT license](http://www.opensource.org/licenses/mit-license.html). +## License +PacketLib is licensed under the **[MIT license](http://www.opensource.org/licenses/mit-license.html)**. diff --git a/example/org/spacehq/packetlib/test/ClientSessionListener.java b/example/org/spacehq/packetlib/test/ClientSessionListener.java index 8ba28636..b4535257 100644 --- a/example/org/spacehq/packetlib/test/ClientSessionListener.java +++ b/example/org/spacehq/packetlib/test/ClientSessionListener.java @@ -1,34 +1,36 @@ package org.spacehq.packetlib.test; -import org.spacehq.packetlib.event.session.*; +import org.spacehq.packetlib.event.session.ConnectedEvent; +import org.spacehq.packetlib.event.session.DisconnectedEvent; +import org.spacehq.packetlib.event.session.DisconnectingEvent; +import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.event.session.SessionAdapter; public class ClientSessionListener extends SessionAdapter { + @Override + public void packetReceived(PacketReceivedEvent event) { + if(event.getPacket() instanceof PingPacket) { + PingPacket packet = event.getPacket(); + System.out.println("CLIENT RECV: " + packet.getPingId()); + if(packet.getPingId().equals("exit")) { + event.getSession().disconnect("Finished"); + } + } + } - @Override - public void packetReceived(PacketReceivedEvent event) { - if(event.getPacket() instanceof PingPacket) { - PingPacket packet = event.getPacket(); - System.out.println("CLIENT RECV: " + packet.getPingId()); - if(packet.getPingId().equals("exit")) { - event.getSession().disconnect("Finished"); - } - } - } + @Override + public void connected(ConnectedEvent event) { + event.getSession().send(new PingPacket("hello")); + event.getSession().send(new PingPacket("exit")); + } - @Override - public void connected(ConnectedEvent event) { - event.getSession().send(new PingPacket("hello")); - event.getSession().send(new PingPacket("exit")); - } - - @Override - public void disconnecting(DisconnectingEvent event) { - System.out.println("CLIENT Disconnecting: " + event.getReason()); - } - - @Override - public void disconnected(DisconnectedEvent event) { - System.out.println("CLIENT Disconnected: " + event.getReason()); - } + @Override + public void disconnecting(DisconnectingEvent event) { + System.out.println("CLIENT Disconnecting: " + event.getReason()); + } + @Override + public void disconnected(DisconnectedEvent event) { + System.out.println("CLIENT Disconnected: " + event.getReason()); + } } diff --git a/example/org/spacehq/packetlib/test/PingPacket.java b/example/org/spacehq/packetlib/test/PingPacket.java index 428e61d0..b24e8cd5 100644 --- a/example/org/spacehq/packetlib/test/PingPacket.java +++ b/example/org/spacehq/packetlib/test/PingPacket.java @@ -7,34 +7,32 @@ import org.spacehq.packetlib.packet.Packet; import java.io.IOException; public class PingPacket implements Packet { + private String id; - private String id; + @SuppressWarnings("unused") + private PingPacket() { + } - @SuppressWarnings("unused") - private PingPacket() { - } + public PingPacket(String id) { + this.id = id; + } - public PingPacket(String id) { - this.id = id; - } + public String getPingId() { + return this.id; + } - public String getPingId() { - return this.id; - } + @Override + public void read(NetInput in) throws IOException { + this.id = in.readString(); + } - @Override - public void read(NetInput in) throws IOException { - this.id = in.readString(); - } - - @Override - public void write(NetOutput out) throws IOException { - out.writeString(this.id); - } - - @Override - public boolean isPriority() { - return false; - } + @Override + public void write(NetOutput out) throws IOException { + out.writeString(this.id); + } + @Override + public boolean isPriority() { + return false; + } } diff --git a/example/org/spacehq/packetlib/test/PingServerTest.java b/example/org/spacehq/packetlib/test/PingServerTest.java index 41c5c6d5..37f92905 100644 --- a/example/org/spacehq/packetlib/test/PingServerTest.java +++ b/example/org/spacehq/packetlib/test/PingServerTest.java @@ -9,23 +9,29 @@ import javax.crypto.SecretKey; import java.security.NoSuchAlgorithmException; public class PingServerTest { + public static void main(String[] args) { + SecretKey key = null; + try { + KeyGenerator gen = KeyGenerator.getInstance("AES"); + gen.init(128); + key = gen.generateKey(); + } catch(NoSuchAlgorithmException e) { + System.err.println("AES algorithm not supported, exiting..."); + return; + } - public static void main(String[] args) { - SecretKey key = null; - try { - KeyGenerator gen = KeyGenerator.getInstance("AES"); - gen.init(128); - key = gen.generateKey(); - } catch(NoSuchAlgorithmException e) { - System.err.println("AES algorithm not supported, exiting..."); - return; - } + Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()).bind(); + server.addListener(new ServerListener(key)); - Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()).bind(); - server.addListener(new ServerListener(key)); - - Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); - client.getSession().connect(); - } + Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); + client.getSession().connect(); + while(server.isListening()) { + try { + Thread.sleep(500); + } catch(InterruptedException e) { + break; + } + } + } } diff --git a/example/org/spacehq/packetlib/test/ServerListener.java b/example/org/spacehq/packetlib/test/ServerListener.java index 6d70dead..3d6c648d 100644 --- a/example/org/spacehq/packetlib/test/ServerListener.java +++ b/example/org/spacehq/packetlib/test/ServerListener.java @@ -1,37 +1,39 @@ package org.spacehq.packetlib.test; -import org.spacehq.packetlib.event.server.*; +import org.spacehq.packetlib.event.server.ServerAdapter; +import org.spacehq.packetlib.event.server.ServerClosedEvent; +import org.spacehq.packetlib.event.server.ServerClosingEvent; +import org.spacehq.packetlib.event.server.SessionAddedEvent; +import org.spacehq.packetlib.event.server.SessionRemovedEvent; import javax.crypto.SecretKey; public class ServerListener extends ServerAdapter { + private SecretKey key; - private SecretKey key; + public ServerListener(SecretKey key) { + this.key = key; + } - public ServerListener(SecretKey key) { - this.key = key; - } + @Override + public void serverClosing(ServerClosingEvent event) { + System.out.println("CLOSING SERVER..."); + } - @Override - public void serverClosing(ServerClosingEvent event) { - System.out.println("CLOSING SERVER..."); - } + @Override + public void serverClosed(ServerClosedEvent event) { + System.out.println("SERVER CLOSED"); + } - @Override - public void serverClosed(ServerClosedEvent event) { - System.out.println("SERVER CLOSED"); - } - - @Override - public void sessionAdded(SessionAddedEvent event) { - System.out.println("SESSION ADDED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); - ((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key); - } - - @Override - public void sessionRemoved(SessionRemovedEvent event) { - System.out.println("SESSION REMOVED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); - event.getServer().close(); - } + @Override + public void sessionAdded(SessionAddedEvent event) { + System.out.println("SESSION ADDED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + ((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key); + } + @Override + public void sessionRemoved(SessionRemovedEvent event) { + System.out.println("SESSION REMOVED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + event.getServer().close(); + } } diff --git a/example/org/spacehq/packetlib/test/ServerSessionListener.java b/example/org/spacehq/packetlib/test/ServerSessionListener.java index 73b51d2c..83742bd7 100644 --- a/example/org/spacehq/packetlib/test/ServerSessionListener.java +++ b/example/org/spacehq/packetlib/test/ServerSessionListener.java @@ -6,23 +6,21 @@ import org.spacehq.packetlib.event.session.PacketReceivedEvent; import org.spacehq.packetlib.event.session.SessionAdapter; public class ServerSessionListener extends SessionAdapter { + @Override + public void packetReceived(PacketReceivedEvent event) { + if(event.getPacket() instanceof PingPacket) { + System.out.println("SERVER RECV: " + event.getPacket().getPingId()); + event.getSession().send(event.getPacket()); + } + } - @Override - public void packetReceived(PacketReceivedEvent event) { - if(event.getPacket() instanceof PingPacket) { - System.out.println("SERVER RECV: " + event.getPacket().getPingId()); - event.getSession().send(event.getPacket()); - } - } - - @Override - public void disconnecting(DisconnectingEvent event) { - System.out.println("SERVER Disconnecting: " + event.getReason()); - } - - @Override - public void disconnected(DisconnectedEvent event) { - System.out.println("SERVER Disconnected: " + event.getReason()); - } + @Override + public void disconnecting(DisconnectingEvent event) { + System.out.println("SERVER Disconnecting: " + event.getReason()); + } + @Override + public void disconnected(DisconnectedEvent event) { + System.out.println("SERVER Disconnected: " + event.getReason()); + } } diff --git a/example/org/spacehq/packetlib/test/TestProtocol.java b/example/org/spacehq/packetlib/test/TestProtocol.java index c000f8da..aa0f801d 100644 --- a/example/org/spacehq/packetlib/test/TestProtocol.java +++ b/example/org/spacehq/packetlib/test/TestProtocol.java @@ -13,55 +13,48 @@ import javax.crypto.SecretKey; import java.security.GeneralSecurityException; public class TestProtocol extends PacketProtocol { + private PacketHeader header = new DefaultPacketHeader(); + private AESEncryption encrypt; - private PacketHeader header = new DefaultPacketHeader(); - private AESEncryption encrypt; + @SuppressWarnings("unused") + private TestProtocol() { + } - @SuppressWarnings("unused") - private TestProtocol() { - } + public TestProtocol(SecretKey key) { + this.setSecretKey(key); + } - public TestProtocol(SecretKey key) { - this.setSecretKey(key); - } + public void setSecretKey(SecretKey key) { + this.register(0, PingPacket.class); + try { + this.encrypt = new AESEncryption(key); + } catch(GeneralSecurityException e) { + e.printStackTrace(); + } + } - public void setSecretKey(SecretKey key) { - this.register(0, PingPacket.class); - try { - this.encrypt = new AESEncryption(key); - } catch(GeneralSecurityException e) { - e.printStackTrace(); - } - } + @Override + public String getSRVRecordPrefix() { + return "_test"; + } - @Override - public boolean needsPacketSizer() { - return true; - } + @Override + public PacketHeader getPacketHeader() { + return this.header; + } - @Override - public boolean needsPacketEncryptor() { - return true; - } + @Override + public PacketEncryption getEncryption() { + return this.encrypt; + } - @Override - public PacketHeader getPacketHeader() { - return this.header; - } - - @Override - public PacketEncryption getEncryption() { - return this.encrypt; - } - - @Override - public void newClientSession(Client client, Session session) { - session.addListener(new ClientSessionListener()); - } - - @Override - public void newServerSession(Server server, Session session) { - session.addListener(new ServerSessionListener()); - } + @Override + public void newClientSession(Client client, Session session) { + session.addListener(new ClientSessionListener()); + } + @Override + public void newServerSession(Server server, Session session) { + session.addListener(new ServerSessionListener()); + } } diff --git a/pom.xml b/pom.xml index 74fd50b5..1a6a1475 100644 --- a/pom.xml +++ b/pom.xml @@ -4,13 +4,23 @@ 4.0.0 org.spacehq packetlib - 1.0-SNAPSHOT + 1.0 jar PacketLib A library for networking between a client and a server with packets. http://github.com/Steveice10/PacketLib/ + + scm:git:git@github.com:Steveice10/PacketLib.git + scm:git:git@github.com:Steveice10/PacketLib.git + git@github.com:Steveice10/PacketLib/ + + + + UTF-8 + + MIT @@ -19,25 +29,6 @@ - - scm:git:git@github.com:Steveice10/PacketLib.git - scm:git:git@github.com:Steveice10/PacketLib.git - git@github.com:Steveice10/PacketLib/ - - - - - spacehq - spacehq-releases - http://repo.spacehq.org/content/repositories/release/ - - - spacehq - spacehq-snapshots - http://repo.spacehq.org/content/repositories/snapshots/ - - - steveice10 @@ -46,14 +37,23 @@ - - UTF-8 - + + + spacehq + spacehq-releases + http://repo.spacehq.org/content/repositories/releases/ + + + spacehq + spacehq-snapshots + http://repo.spacehq.org/content/repositories/snapshots/ + + spacehq-releases - http://repo.spacehq.org/content/repositories/release/ + http://repo.spacehq.org/content/repositories/releases/ spacehq-snapshots @@ -76,23 +76,21 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 2.5.1 1.6 1.6 - org.apache.maven.plugins maven-jar-plugin - 2.3.2 + 2.6 - org.apache.maven.plugins maven-shade-plugin - 1.5 + 2.4.1 package @@ -102,6 +100,7 @@ + ${project.build.directory}/dependency-reduced-pom.xml *:* diff --git a/src/main/java/org/spacehq/packetlib/Client.java b/src/main/java/org/spacehq/packetlib/Client.java index 21c7ef59..03411ca1 100644 --- a/src/main/java/org/spacehq/packetlib/Client.java +++ b/src/main/java/org/spacehq/packetlib/Client.java @@ -5,92 +5,52 @@ import org.spacehq.packetlib.packet.PacketProtocol; /** * A client that may connect to a server. */ -public class Client implements ConnectTimeoutHandlerContainer { +public class Client { + private String host; + private int port; + private PacketProtocol protocol; + private Session session; - private String host; - private int port; - private PacketProtocol protocol; - private Session session; - private int timeout = 30; - private TimeoutHandler timeoutHandler; + public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.session = factory.createClientSession(this); + } - public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { - this.host = host; - this.port = port; - this.protocol = protocol; - this.session = factory.createClientSession(this); - } + /** + * Gets the host the client is connecting to. + * + * @return The host the client is connecting to. + */ + public String getHost() { + return this.host; + } - /** - * Gets the host the client is connecting to. - * - * @return The host the client is connecting to. - */ - public String getHost() { - return this.host; - } + /** + * Gets the port the client is connecting to. + * + * @return The port the client is connecting to. + */ + public int getPort() { + return this.port; + } - /** - * Gets the port the client is connecting to. - * - * @return The port the client is connecting to. - */ - public int getPort() { - return this.port; - } - - /** - * Gets the packet protocol of the client. - * - * @return The client's packet protocol. - */ - public PacketProtocol getPacketProtocol() { - return this.protocol; - } - - /** - * Gets the session of the client. - * - * @return The client's session. - */ - public Session getSession() { - return this.session; - } - - /** - * Gets the connect timeout for this client in seconds. - * - * @return The client's connect timeout. - */ - public int getConnectTimeout() { - return this.timeout; - } - - /** - * Sets the connect timeout for this client in seconds. - * - * @param timeout Connect timeout to set in seconds. - */ - public void setConnectTimeout(int timeout) { - this.timeout = timeout; - } - - /** - * Gets the connect timeout handler for this client. - * - * @return The client's connect timeout handler. - */ - public TimeoutHandler getConnectTimeoutHandler() { - return this.timeoutHandler; - } - - /** - * Sets the connect timeout handler for this client. Note: Takes effect on connect() call. - * - * @param timeoutHandler Connect timeout handler to set. - */ - public void setConnectTimeoutHandler(TimeoutHandler timeoutHandler) { - this.timeoutHandler = timeoutHandler; - } + /** + * Gets the packet protocol of the client. + * + * @return The client's packet protocol. + */ + public PacketProtocol getPacketProtocol() { + return this.protocol; + } + /** + * Gets the session of the client. + * + * @return The client's session. + */ + public Session getSession() { + return this.session; + } } diff --git a/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java b/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java deleted file mode 100644 index d5998064..00000000 --- a/src/main/java/org/spacehq/packetlib/ConnectTimeoutHandlerContainer.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.spacehq.packetlib; - -public interface ConnectTimeoutHandlerContainer { - public int getConnectTimeout(); - - public TimeoutHandler getConnectTimeoutHandler(); -} diff --git a/src/main/java/org/spacehq/packetlib/ConnectionListener.java b/src/main/java/org/spacehq/packetlib/ConnectionListener.java index 9113bb2a..3052aad0 100644 --- a/src/main/java/org/spacehq/packetlib/ConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/ConnectionListener.java @@ -1,34 +1,44 @@ package org.spacehq.packetlib; /** - * A listener for new sessions on a host and port. + * Listens for new sessions to connect. */ public interface ConnectionListener { + /** + * Gets the host the session is listening on. + * + * @return The listening host. + */ + public String getHost(); - /** - * Gets the host the session is listening on. - * - * @return The listening host. - */ - public String getHost(); + /** + * Gets the port the session is listening on. + * + * @return The listening port. + */ + public int getPort(); - /** - * Gets the port the session is listening on. - * - * @return The listening port. - */ - public int getPort(); + /** + * Returns true if the listener is listening. + * + * @return True if the listener is listening. + */ + public boolean isListening(); - /** - * Returns true if the listener is listening. - * - * @return True if the listener is listening. - */ - public boolean isListening(); + /** + * Binds the listener to its host and port. + */ + public void bind(); - /** - * Closes the listener. - */ - public void close(); + /** + * Closes the listener. + */ + public void close(); + /** + * Closes the listener. + * + * @param wait Whether to wait for the listener to finish closing. + */ + public void close(boolean wait); } diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index e8712d90..13f2df0f 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -1,6 +1,12 @@ package org.spacehq.packetlib; -import org.spacehq.packetlib.event.server.*; +import org.spacehq.packetlib.event.server.ServerBoundEvent; +import org.spacehq.packetlib.event.server.ServerClosedEvent; +import org.spacehq.packetlib.event.server.ServerClosingEvent; +import org.spacehq.packetlib.event.server.ServerEvent; +import org.spacehq.packetlib.event.server.ServerListener; +import org.spacehq.packetlib.event.server.SessionAddedEvent; +import org.spacehq.packetlib.event.server.SessionRemovedEvent; import org.spacehq.packetlib.packet.PacketProtocol; import java.lang.reflect.Constructor; @@ -10,276 +16,241 @@ import java.util.List; import java.util.Map; /** - * A server that listens on a given host and port. + * A server that listens for connections. */ -public class Server implements ConnectTimeoutHandlerContainer { +public class Server { + private String host; + private int port; + private Class protocol; + private SessionFactory factory; + private ConnectionListener listener; + private List sessions = new ArrayList(); - private String host; - private int port; - private Class protocol; - private SessionFactory factory; - private int timeout = 30; - private TimeoutHandler timeoutHandler; - private ConnectionListener listener; - private List sessions = new ArrayList(); + private Map flags = new HashMap(); + private List listeners = new ArrayList(); - private Map flags = new HashMap(); - private List listeners = new ArrayList(); + public Server(String host, int port, Class protocol, SessionFactory factory) { + this.host = host; + this.port = port; + this.protocol = protocol; + this.factory = factory; + } - public Server(String host, int port, Class protocol, SessionFactory factory) { - this.host = host; - this.port = port; - this.protocol = protocol; - this.factory = factory; - } + /** + * Binds and initializes the server. + * + * @return The server after being bound. + */ + public Server bind() { + this.listener = this.factory.createServerListener(this); + this.listener.bind(); - /** - * Binds and initializes the server. - * - * @return The server after being bound. - */ - public Server bind() { - this.listener = this.factory.createServerListener(this); - this.callEvent(new ServerBoundEvent(this)); - return this; - } + this.callEvent(new ServerBoundEvent(this)); + return this; + } - /** - * Gets the host this server is bound to. - * - * @return The server's host. - */ - public String getHost() { - return this.host; - } + /** + * Gets the host this server is bound to. + * + * @return The server's host. + */ + public String getHost() { + return this.host; + } - /** - * Gets the port this server is bound to. - * - * @return The server's port. - */ - public int getPort() { - return this.port; - } + /** + * Gets the port this server is bound to. + * + * @return The server's port. + */ + public int getPort() { + return this.port; + } - /** - * Gets the connect timeout for this server in seconds. - * - * @return The client's connect timeout. - */ - public int getConnectTimeout() { - return this.timeout; - } + /** + * Gets the packet protocol of the server. + * + * @return The server's packet protocol. + */ + public Class getPacketProtocol() { + return this.protocol; + } - /** - * Sets the connect timeout for this server in seconds. - * - * @param timeout Connect timeout to set in seconds. - */ - public void setConnectTimeout(int timeout) { - this.timeout = timeout; - } + /** + * Creates a new packet protocol instance from this server's protocol class. + * + * @return The created protocol instance. + * @throws IllegalStateException If the protocol does not have a no-params constructor or cannot be instantiated. + */ + public PacketProtocol createPacketProtocol() { + try { + Constructor constructor = this.protocol.getDeclaredConstructor(); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } - /** - * Gets the connect timeout handler for this server. - * - * @return The client's connect timeout handler. - */ - public TimeoutHandler getConnectTimeoutHandler() { - return this.timeoutHandler; - } + return constructor.newInstance(); + } catch(NoSuchMethodError e) { + throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); + } + } - /** - * Sets the connect timeout handler for this server. - * - * @param timeoutHandler Connect timeout handler to set. - */ - public void setConnectTimeoutHandler(TimeoutHandler timeoutHandler) { - this.timeoutHandler = timeoutHandler; - } + /** + * Gets this server's set flags. + * + * @return This server's flags. + */ + public Map getGlobalFlags() { + return new HashMap(this.flags); + } - /** - * Gets the packet protocol of the server. - * - * @return The server's packet protocol. - */ - public Class getPacketProtocol() { - return this.protocol; - } + /** + * Checks whether this server has a flag set. + * + * @param key Key of the flag to check for. + * @return Whether this server has a flag set. + */ + public boolean hasGlobalFlag(String key) { + return this.flags.containsKey(key); + } - /** - * Creates a new packet protocol instance from this server's protocol class. - * - * @return The created protocol instance. - * @throws IllegalStateException If the protocol does not have a no-params constructor or cannot be instantiated. - */ - public PacketProtocol createPacketProtocol() { - try { - Constructor constructor = this.protocol.getDeclaredConstructor(); - if(!constructor.isAccessible()) { - constructor.setAccessible(true); - } + /** + * Gets the value of the given flag as an instance of the given type. If this + * session belongs to a server, the server's flags will be checked for the flag + * as well. + * + * @param key Key of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getGlobalFlag(String key) { + Object value = this.flags.get(key); + if(value == null) { + return null; + } - return constructor.newInstance(); - } catch(NoSuchMethodError e) { - throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); - } - } + try { + return (T) value; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); + } + } - /** - * Gets this server's set flags. - * - * @return This server's flags. - */ - public Map getGlobalFlags() { - return new HashMap(this.flags); - } + /** + * Sets the value of a flag. The flag will be used in sessions if a session does + * not contain a value for the flag. + * + * @param key Key of the flag. + * @param value Value to set the flag to. + */ + public void setGlobalFlag(String key, Object value) { + this.flags.put(key, value); + } - /** - * Checks whether this server has a flag set. - * - * @param key Key of the flag to check for. - * @return Whether this server has a flag set. - */ - public boolean hasGlobalFlag(String key) { - return this.flags.containsKey(key); - } + /** + * Gets the listeners listening on this session. + * + * @return This server's listeners. + */ + public List getListeners() { + return new ArrayList(this.listeners); + } - /** - * Gets the value of the given flag as an instance of the given type. If this - * session belongs to a server, the server's flags will be checked for the flag - * as well. - * - * @param key Key of the flag. - * @return Value of the flag. - * @throws IllegalStateException If the flag's value isn't of the required type. - */ - @SuppressWarnings("unchecked") - public T getGlobalFlag(String key) { - Object value = this.flags.get(key); - if(value == null) { - return null; - } + /** + * Adds a listener to this server. + * + * @param listener Listener to add. + */ + public void addListener(ServerListener listener) { + this.listeners.add(listener); + } - try { - return (T) value; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); - } - } + /** + * Removes a listener from this server. + * + * @param listener Listener to remove. + */ + public void removeListener(ServerListener listener) { + this.listeners.remove(listener); + } - /** - * Sets the value of a flag. The flag will be used in sessions if a session does - * not contain a value for the flag. - * - * @param key Key of the flag. - * @param value Value to set the flag to. - */ - public void setGlobalFlag(String key, Object value) { - this.flags.put(key, value); - } + /** + * Calls an event on the listeners of this server. + * + * @param event Event to call. + */ + public void callEvent(ServerEvent event) { + for(ServerListener listener : this.listeners) { + event.call(listener); + } + } - /** - * Gets the listeners listening on this session. - * - * @return This server's listeners. - */ - public List getListeners() { - return new ArrayList(this.listeners); - } + /** + * Gets all sessions belonging to this server. + * + * @return Sessions belonging to this server. + */ + public List getSessions() { + return new ArrayList(this.sessions); + } - /** - * Adds a listener to this server. - * - * @param listener Listener to add. - */ - public void addListener(ServerListener listener) { - this.listeners.add(listener); - } + /** + * Adds the given session to this server. + * + * @param session Session to add. + */ + public void addSession(Session session) { + this.sessions.add(session); + this.callEvent(new SessionAddedEvent(this, session)); + } - /** - * Removes a listener from this server. - * - * @param listener Listener to remove. - */ - public void removeListener(ServerListener listener) { - this.listeners.remove(listener); - } + /** + * Removes the given session from this server. + * + * @param session Session to remove. + */ + public void removeSession(Session session) { + this.sessions.remove(session); + if(session.isConnected()) { + session.disconnect("Connection closed."); + } - /** - * Calls an event on the listeners of this server. - * - * @param event Event to call. - */ - public void callEvent(ServerEvent event) { - for(ServerListener listener : this.listeners) { - event.call(listener); - } - } + this.callEvent(new SessionRemovedEvent(this, session)); + } - /** - * Gets all sessions belonging to this server. - * - * @return Sessions belonging to this server. - */ - public List getSessions() { - return new ArrayList(this.sessions); - } + /** + * Gets whether the server is listening. + * + * @return Whether the server is listening. + */ + public boolean isListening() { + return this.listener.isListening(); + } - /** - * Adds the given session to this server. - * - * @param session Session to add. - */ - public void addSession(Session session) { - this.sessions.add(session); - this.callEvent(new SessionAddedEvent(this, session)); - } + /** + * Closes the server. + */ + public void close() { + this.close(false); + } - /** - * Removes the given session from this server. - * - * @param session Session to remove. - */ - public void removeSession(Session session) { - this.sessions.remove(session); - if(session.isConnected()) { - session.disconnect("Connection closed."); - } - - this.callEvent(new SessionRemovedEvent(this, session)); - } - - /** - * Gets whether the server is listening. - * - * @return Whether the server is listening. - */ - public boolean isListening() { - return this.listener.isListening(); - } - - /** - * Closes the server. - */ - public void close() { - // Close server in a separate thread to prevent stalling from closing a server inside an event or packet handling. - new Thread(new Runnable() { - @Override - public void run() { - callEvent(new ServerClosingEvent(Server.this)); - for(Session session : getSessions()) { - if(session.isConnected()) { - session.disconnect("Server closed."); - } - } - - listener.close(); - callEvent(new ServerClosedEvent(Server.this)); - } - }, "CloseServer").start(); - } + /** + * Closes the server. + * + * @param wait Whether to wait for the server to finish closing. + */ + public void close(boolean wait) { + this.callEvent(new ServerClosingEvent(this)); + for(Session session : this.getSessions()) { + if(session.isConnected()) { + session.disconnect("Server closed."); + } + } + this.listener.close(wait); + this.callEvent(new ServerClosedEvent(this)); + } } diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index b0d506cc..600b4eea 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -12,180 +12,203 @@ import java.util.Map; * A network session. */ public interface Session { + /** + * Connects this session to its host and port. + */ + public void connect(); - /** - * Connects this session to its host and port. - */ - public void connect(); + /** + * Connects this session to its host and port. + * + * @param wait Whether to wait for the connection to be established before returning. + */ + public void connect(boolean wait); - /** - * Connects this session to its host and port. - * - * @param wait Whether to wait for the connection to be established before returning. - */ - public void connect(boolean wait); + /** + * Gets the host the session is connected to. + * + * @return The connected host. + */ + public String getHost(); - /** - * Gets the host the session is connected to. - * - * @return The connected host. - */ - public String getHost(); + /** + * Gets the port the session is connected to. + * + * @return The connected port. + */ + public int getPort(); - /** - * Gets the port the session is connected to. - * - * @return The connected port. - */ - public int getPort(); + /** + * Gets the packet protocol of the session. + * + * @return The session's packet protocol. + */ + public PacketProtocol getPacketProtocol(); - /** - * Gets the packet protocol of the session. - * - * @return The session's packet protocol. - */ - public PacketProtocol getPacketProtocol(); + /** + * Gets this session's set flags. If this session belongs to a server, the server's + * flags will be included in the results. + * + * @return This session's flags. + */ + public Map getFlags(); - /** - * Gets this session's set flags. If this session belongs to a server, the server's - * flags will be included in the results. - * - * @return This session's flags. - */ - public Map getFlags(); + /** + * Checks whether this session has a flag set. If this session belongs to a server, + * the server's flags will also be checked. + * + * @param key Key of the flag to check for. + * @return Whether this session has a flag set. + */ + public boolean hasFlag(String key); - /** - * Checks whether this session has a flag set. If this session belongs to a server, - * the server's flags will also be checked. - * - * @param key Key of the flag to check for. - * @return Whether this session has a flag set. - */ - public boolean hasFlag(String key); + /** + * Gets the value of the given flag as an instance of the given type. If this + * session belongs to a server, the server's flags will be checked for the flag + * as well. + * + * @param key Key of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + public T getFlag(String key); - /** - * Gets the value of the given flag as an instance of the given type. If this - * session belongs to a server, the server's flags will be checked for the flag - * as well. - * - * @param key Key of the flag. - * @return Value of the flag. - * @throws IllegalStateException If the flag's value isn't of the required type. - */ - public T getFlag(String key); + /** + * Sets the value of a flag. This does not change a server's flags if this session + * belongs to a server. + * + * @param key Key of the flag. + * @param value Value to set the flag to. + */ + public void setFlag(String key, Object value); - /** - * Sets the value of a flag. This does not change a server's flags if this session - * belongs to a server. - * - * @param key Key of the flag. - * @param value Value to set the flag to. - */ - public void setFlag(String key, Object value); + /** + * Gets the listeners listening on this session. + * + * @return This session's listeners. + */ + public List getListeners(); - /** - * Gets the listeners listening on this session. - * - * @return This session's listeners. - */ - public List getListeners(); + /** + * Adds a listener to this session. + * + * @param listener Listener to add. + */ + public void addListener(SessionListener listener); - /** - * Adds a listener to this session. - * - * @param listener Listener to add. - */ - public void addListener(SessionListener listener); + /** + * Removes a listener from this session. + * + * @param listener Listener to remove. + */ + public void removeListener(SessionListener listener); - /** - * Removes a listener from this session. - * - * @param listener Listener to remove. - */ - public void removeListener(SessionListener listener); + /** + * Calls an event on the listeners of this session. + * + * @param event Event to call. + */ + public void callEvent(SessionEvent event); - /** - * Calls an event on the listeners of this session. - * - * @param event Event to call. - */ - public void callEvent(SessionEvent event); + /** + * Gets the compression packet length threshold for this session (-1 = disabled). + * + * @return This session's compression threshold. + */ + public int getCompressionThreshold(); - /** - * Gets the compression packet length threshold for this session (-1 = disabled). - * - * @return This session's compression threshold. - */ - public int getCompressionThreshold(); + /** + * Sets the compression packet length threshold for this session (-1 = disabled). + * + * @param threshold The new compression threshold. + */ + public void setCompressionThreshold(int threshold); - /** - * Sets the compression packet length threshold for this session (-1 = disabled). - * - * @param threshold The new compression threshold. - */ - public void setCompressionThreshold(int threshold); + /** + * Gets the connect timeout for this session in seconds. + * + * @return The session's connect timeout. + */ + public int getConnectTimeout(); - /** - * Gets the read timeout for this session in seconds. - * - * @return The session's read timeout. - */ - public int getReadTimeout(); + /** + * Sets the connect timeout for this session in seconds. + * + * @param timeout Connect timeout to set. + */ + public void setConnectTimeout(int timeout); - /** - * Sets the read timeout for this session in seconds. - * - * @param timeout Read timeout to set in seconds. - */ - public void setReadTimeout(int timeout); + /** + * Gets the read timeout for this session in seconds. + * + * @return The session's read timeout. + */ + public int getReadTimeout(); - /** - * Gets the write timeout for this session in seconds. - * - * @return The session's write timeout. - */ - public int getWriteTimeout(); + /** + * Sets the read timeout for this session in seconds. + * + * @param timeout Read timeout to set. + */ + public void setReadTimeout(int timeout); - /** - * Sets the write timeout for this session in seconds. - * - * @param timeout Write timeout to set in seconds. - */ - public void setWriteTimeout(int timeout); + /** + * Gets the write timeout for this session in seconds. + * + * @return The session's write timeout. + */ + public int getWriteTimeout(); - /** - * Gets the timeout handler for this session. - * - * @return The session's timeout handler. - */ - public TimeoutHandler getTimeoutHandler(); + /** + * Sets the write timeout for this session in seconds. + * + * @param timeout Write timeout to set. + */ + public void setWriteTimeout(int timeout); - /** - * Sets the timeout handler for this session. - * - * @param timeout Timeout handler to set. - */ - public void setTimeoutHandler(TimeoutHandler timeout); + /** + * Returns true if the session is connected. + * + * @return True if the session is connected. + */ + public boolean isConnected(); - /** - * Returns true if the session is connected. - * - * @return True if the session is connected. - */ - public boolean isConnected(); + /** + * Sends a packet. + * + * @param packet Packet to send. + */ + public void send(Packet packet); - /** - * Sends a packet. - * - * @param packet Packet to send. - */ - public void send(Packet packet); + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + */ + public void disconnect(String reason); - /** - * Disconnects the session. - * - * @param reason Reason for disconnecting. - */ - public void disconnect(String reason); + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + * @param wait Whether to wait for the session to be disconnected. + */ + public void disconnect(String reason, boolean wait); + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + * @param cause Throwable responsible for disconnecting. + */ + public void disconnect(String reason, Throwable cause); + + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + * @param cause Throwable responsible for disconnecting. + * @param wait Whether to wait for the session to be disconnected. + */ + public void disconnect(String reason, Throwable cause, boolean wait); } diff --git a/src/main/java/org/spacehq/packetlib/SessionFactory.java b/src/main/java/org/spacehq/packetlib/SessionFactory.java index 15c83c90..66140a71 100644 --- a/src/main/java/org/spacehq/packetlib/SessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/SessionFactory.java @@ -4,21 +4,19 @@ package org.spacehq.packetlib; * A factory for creating sessions. */ public interface SessionFactory { + /** + * Creates a client session. + * + * @param client Client to create the session for. + * @return The created session. + */ + public Session createClientSession(Client client); - /** - * Creates a client session. - * - * @param client Client to create the session for. - * @return The created session. - */ - public Session createClientSession(Client client); - - /** - * Creates a server network listener. - * - * @param server Server to create the listener for. - * @return The created listener. - */ - public ConnectionListener createServerListener(Server server); - + /** + * Creates a server network listener. + * + * @param server Server to create the listener for. + * @return The created listener. + */ + public ConnectionListener createServerListener(Server server); } diff --git a/src/main/java/org/spacehq/packetlib/TimeoutHandler.java b/src/main/java/org/spacehq/packetlib/TimeoutHandler.java deleted file mode 100644 index 18c7b1f6..00000000 --- a/src/main/java/org/spacehq/packetlib/TimeoutHandler.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.spacehq.packetlib; - -public interface TimeoutHandler { - public void onTimeout(Session session, TimeoutType type); -} diff --git a/src/main/java/org/spacehq/packetlib/TimeoutType.java b/src/main/java/org/spacehq/packetlib/TimeoutType.java deleted file mode 100644 index e128e469..00000000 --- a/src/main/java/org/spacehq/packetlib/TimeoutType.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.spacehq.packetlib; - -public enum TimeoutType { - CONNECT, - READ, - WRITE; -} diff --git a/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java b/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java index e5c8a20a..8d5d8fd7 100644 --- a/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java +++ b/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java @@ -9,35 +9,39 @@ import java.security.Key; * An encryption implementation using "AES/CFB8/NoPadding" encryption. */ public class AESEncryption implements PacketEncryption { + private Cipher inCipher; + private Cipher outCipher; - private Cipher inCipher; - private Cipher outCipher; + /** + * Creates a new AESEncryption instance. + * + * @param key Key to use when encrypting/decrypting data. + * @throws GeneralSecurityException If a security error occurs. + */ + public AESEncryption(Key key) throws GeneralSecurityException { + this.inCipher = Cipher.getInstance("AES/CFB8/NoPadding"); + this.inCipher.init(2, key, new IvParameterSpec(key.getEncoded())); + this.outCipher = Cipher.getInstance("AES/CFB8/NoPadding"); + this.outCipher.init(1, key, new IvParameterSpec(key.getEncoded())); + } - public AESEncryption(Key key) throws GeneralSecurityException { - this.inCipher = Cipher.getInstance("AES/CFB8/NoPadding"); - this.inCipher.init(2, key, new IvParameterSpec(key.getEncoded())); - this.outCipher = Cipher.getInstance("AES/CFB8/NoPadding"); - this.outCipher.init(1, key, new IvParameterSpec(key.getEncoded())); - } + @Override + public int getDecryptOutputSize(int length) { + return this.inCipher.getOutputSize(length); + } - @Override - public int getDecryptOutputSize(int length) { - return this.inCipher.getOutputSize(length); - } + @Override + public int getEncryptOutputSize(int length) { + return this.outCipher.getOutputSize(length); + } - @Override - public int getEncryptOutputSize(int length) { - return this.outCipher.getOutputSize(length); - } - - @Override - public int decrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { - return this.inCipher.update(input, inputOffset, inputLength, output, outputOffset); - } - - @Override - public int encrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { - return this.outCipher.update(input, inputOffset, inputLength, output, outputOffset); - } + @Override + public int decrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { + return this.inCipher.update(input, inputOffset, inputLength, output, outputOffset); + } + @Override + public int encrypt(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset) throws Exception { + return this.outCipher.update(input, inputOffset, inputLength, output, outputOffset); + } } diff --git a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java index 78014060..838cf227 100644 --- a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java +++ b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java @@ -4,43 +4,41 @@ package org.spacehq.packetlib.crypt; * An interface for encrypting packets. */ public interface PacketEncryption { + /** + * Gets the output size from decrypting. + * + * @param length Length of the data being decrypted. + */ + public int getDecryptOutputSize(int length); - /** - * Gets the output size from decrypting. - * - * @param length Length of the data being decrypted. - */ - public int getDecryptOutputSize(int length); + /** + * Gets the output size from encrypting. + * + * @param length Length of the data being encrypted. + */ + public int getEncryptOutputSize(int length); - /** - * Gets the output size from encrypting. - * - * @param length Length of the data being encrypted. - */ - public int getEncryptOutputSize(int length); - - /** - * Decrypts the given data. - * - * @param input Input data to decrypt. - * @param inputOffset Offset of the data to start decrypting at. - * @param inputLength Length of the data to be decrypted. - * @param output Array to output decrypted data to. - * @param outputOffset Offset of the output array to start at. - * @return The number of bytes stored in the output array. - */ - public int decrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; - - /** - * Encrypts the given data. - * - * @param input Input data to encrypt. - * @param inputOffset Offset of the data to start encrypting at. - * @param inputLength Length of the data to be encrypted. - * @param output Array to output encrypted data to. - * @param outputOffset Offset of the output array to start at. - * @return The number of bytes stored in the output array. - */ - public int encrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; + /** + * Decrypts the given data. + * + * @param input Input data to decrypt. + * @param inputOffset Offset of the data to start decrypting at. + * @param inputLength Length of the data to be decrypted. + * @param output Array to output decrypted data to. + * @param outputOffset Offset of the output array to start at. + * @return The number of bytes stored in the output array. + */ + public int decrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; + /** + * Encrypts the given data. + * + * @param input Input data to encrypt. + * @param inputOffset Offset of the data to start encrypting at. + * @param inputLength Length of the data to be encrypted. + * @param output Array to output encrypted data to. + * @param outputOffset Offset of the output array to start at. + * @return The number of bytes stored in the output array. + */ + public int encrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java b/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java index c2b996ad..6c6b6518 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java @@ -4,25 +4,23 @@ package org.spacehq.packetlib.event.server; * An adapter for picking server events to listen for. */ public class ServerAdapter implements ServerListener { + @Override + public void serverBound(ServerBoundEvent event) { + } - @Override - public void serverBound(ServerBoundEvent event) { - } + @Override + public void serverClosing(ServerClosingEvent event) { + } - @Override - public void serverClosing(ServerClosingEvent event) { - } + @Override + public void serverClosed(ServerClosedEvent event) { + } - @Override - public void serverClosed(ServerClosedEvent event) { - } - - @Override - public void sessionAdded(SessionAddedEvent event) { - } - - @Override - public void sessionRemoved(SessionRemovedEvent event) { - } + @Override + public void sessionAdded(SessionAddedEvent event) { + } + @Override + public void sessionRemoved(SessionRemovedEvent event) { + } } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java index 5661f72d..15fef805 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java @@ -6,25 +6,28 @@ import org.spacehq.packetlib.Server; * Called when the server is bound to its host and port. */ public class ServerBoundEvent implements ServerEvent { + private Server server; - private Server server; + /** + * Creates a new ServerBoundEvent instance. + * + * @param server Server being bound. + */ + public ServerBoundEvent(Server server) { + this.server = server; + } - public ServerBoundEvent(Server server) { - this.server = server; - } - - /** - * Gets the server involved in this event. - * - * @return The event's server. - */ - public Server getServer() { - return this.server; - } - - @Override - public void call(ServerListener listener) { - listener.serverBound(this); - } + /** + * Gets the server involved in this event. + * + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + @Override + public void call(ServerListener listener) { + listener.serverBound(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java index 909c8e8c..da8d9dcc 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java @@ -6,25 +6,28 @@ import org.spacehq.packetlib.Server; * Called when the server is closed. */ public class ServerClosedEvent implements ServerEvent { + private Server server; - private Server server; + /** + * Creates a new ServerClosedEvent instance. + * + * @param server Server being closed. + */ + public ServerClosedEvent(Server server) { + this.server = server; + } - public ServerClosedEvent(Server server) { - this.server = server; - } - - /** - * Gets the server involved in this event. - * - * @return The event's server. - */ - public Server getServer() { - return this.server; - } - - @Override - public void call(ServerListener listener) { - listener.serverClosed(this); - } + /** + * Gets the server involved in this event. + * + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + @Override + public void call(ServerListener listener) { + listener.serverClosed(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java index f08cc306..2d4cbff3 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java @@ -6,25 +6,28 @@ import org.spacehq.packetlib.Server; * Called when the server is about to close. */ public class ServerClosingEvent implements ServerEvent { + private Server server; - private Server server; + /** + * Creates a new ServerClosingEvent instance. + * + * @param server Server being closed. + */ + public ServerClosingEvent(Server server) { + this.server = server; + } - public ServerClosingEvent(Server server) { - this.server = server; - } - - /** - * Gets the server involved in this event. - * - * @return The event's server. - */ - public Server getServer() { - return this.server; - } - - @Override - public void call(ServerListener listener) { - listener.serverClosing(this); - } + /** + * Gets the server involved in this event. + * + * @return The event's server. + */ + public Server getServer() { + return this.server; + } + @Override + public void call(ServerListener listener) { + listener.serverClosing(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java b/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java index bd84abc6..cf858eef 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java @@ -4,12 +4,10 @@ package org.spacehq.packetlib.event.server; * An event relating to servers. */ public interface ServerEvent { - - /** - * Calls the event. - * - * @param listener Listener to call the event on. - */ - public void call(ServerListener listener); - + /** + * Calls the event. + * + * @param listener Listener to call the event on. + */ + public void call(ServerListener listener); } diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java b/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java index 54cb730e..45ea2e7b 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java +++ b/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java @@ -4,40 +4,38 @@ package org.spacehq.packetlib.event.server; * A listener for listening to server events. */ public interface ServerListener { + /** + * Called when a server is bound to its host and port. + * + * @param event Data relating to the event. + */ + public void serverBound(ServerBoundEvent event); - /** - * Called when a server is bound to its host and port. - * - * @param event Data relating to the event. - */ - public void serverBound(ServerBoundEvent event); + /** + * Called when a server is about to close. + * + * @param event Data relating to the event. + */ + public void serverClosing(ServerClosingEvent event); - /** - * Called when a server is about to close. - * - * @param event Data relating to the event. - */ - public void serverClosing(ServerClosingEvent event); + /** + * Called when a server is closed. + * + * @param event Data relating to the event. + */ + public void serverClosed(ServerClosedEvent event); - /** - * Called when a server is closed. - * - * @param event Data relating to the event. - */ - public void serverClosed(ServerClosedEvent event); - - /** - * Called when a session is added to the server. - * - * @param event Data relating to the event. - */ - public void sessionAdded(SessionAddedEvent event); - - /** - * Called when a session is removed and disconnected from the server. - * - * @param event Data relating to the event. - */ - public void sessionRemoved(SessionRemovedEvent event); + /** + * Called when a session is added to the server. + * + * @param event Data relating to the event. + */ + public void sessionAdded(SessionAddedEvent event); + /** + * Called when a session is removed and disconnected from the server. + * + * @param event Data relating to the event. + */ + public void sessionRemoved(SessionRemovedEvent event); } diff --git a/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java index 019409dd..1e526c61 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java @@ -7,36 +7,40 @@ import org.spacehq.packetlib.Session; * Called when a session is added to the server. */ public class SessionAddedEvent implements ServerEvent { + private Server server; + private Session session; - private Server server; - private Session session; + /** + * Creates a new SessionAddedEvent instance. + * + * @param server Server the session is being added to. + * @param session Session being added. + */ + public SessionAddedEvent(Server server, Session session) { + this.server = server; + this.session = session; + } - public SessionAddedEvent(Server server, Session session) { - this.server = server; - this.session = session; - } + /** + * Gets the server involved in this event. + * + * @return The event's server. + */ + public Server getServer() { + return this.server; + } - /** - * Gets the server involved in this event. - * - * @return The event's server. - */ - public Server getServer() { - return this.server; - } - - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - @Override - public void call(ServerListener listener) { - listener.sessionAdded(this); - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + @Override + public void call(ServerListener listener) { + listener.sessionAdded(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java b/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java index 78ba5ead..a2bd6571 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java @@ -7,36 +7,40 @@ import org.spacehq.packetlib.Session; * Called when a session is removed and disconnected from the server. */ public class SessionRemovedEvent implements ServerEvent { + private Server server; + private Session session; - private Server server; - private Session session; + /** + * Creates a new SessionRemovedEvent instance. + * + * @param server Server the session is being removed from. + * @param session Session being removed. + */ + public SessionRemovedEvent(Server server, Session session) { + this.server = server; + this.session = session; + } - public SessionRemovedEvent(Server server, Session session) { - this.server = server; - this.session = session; - } + /** + * Gets the server involved in this event. + * + * @return The event's server. + */ + public Server getServer() { + return this.server; + } - /** - * Gets the server involved in this event. - * - * @return The event's server. - */ - public Server getServer() { - return this.server; - } - - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - @Override - public void call(ServerListener listener) { - listener.sessionRemoved(this); - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + @Override + public void call(ServerListener listener) { + listener.sessionRemoved(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java index b9384ffd..0f71d6b8 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java @@ -6,25 +6,28 @@ import org.spacehq.packetlib.Session; * Called when the session connects. */ public class ConnectedEvent implements SessionEvent { + private Session session; - private Session session; + /** + * Creates a new ConnectedEvent instance. + * + * @param session Session being connected. + */ + public ConnectedEvent(Session session) { + this.session = session; + } - public ConnectedEvent(Session session) { - this.session = session; - } - - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - @Override - public void call(SessionListener listener) { - listener.connected(this); - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + @Override + public void call(SessionListener listener) { + listener.connected(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java index b3ce80a8..c9d44d53 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java @@ -6,36 +6,62 @@ import org.spacehq.packetlib.Session; * Called when the session is disconnected. */ public class DisconnectedEvent implements SessionEvent { + private Session session; + private String reason; + private Throwable cause; - private Session session; - private String reason; + /** + * Creates a new DisconnectedEvent instance. + * + * @param session Session being disconnected. + * @param reason Reason for the session to disconnect. + */ + public DisconnectedEvent(Session session, String reason) { + this(session, reason, null); + } - public DisconnectedEvent(Session session, String reason) { - this.session = session; - this.reason = reason; - } + /** + * Creates a new DisconnectedEvent instance. + * + * @param session Session being disconnected. + * @param reason Reason for the session to disconnect. + * @param cause Throwable that caused the disconnect. + */ + public DisconnectedEvent(Session session, String reason, Throwable cause) { + this.session = session; + this.reason = reason; + this.cause = cause; + } - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } - /** - * Gets the reason given for the session disconnecting. - * - * @return The event's reason. - */ - public String getReason() { - return this.reason; - } + /** + * Gets the reason given for the session disconnecting. + * + * @return The event's reason. + */ + public String getReason() { + return this.reason; + } - @Override - public void call(SessionListener listener) { - listener.disconnected(this); - } + /** + * Gets the Throwable responsible for the session disconnecting. + * + * @return The Throwable responsible for the disconnect, or null if the disconnect was not caused by a Throwable. + */ + public Throwable getCause() { + return this.cause; + } + @Override + public void call(SessionListener listener) { + listener.disconnected(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java b/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java index cd6e6425..53e25599 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java @@ -6,36 +6,62 @@ import org.spacehq.packetlib.Session; * Called when the session is about to disconnect. */ public class DisconnectingEvent implements SessionEvent { + private Session session; + private String reason; + private Throwable cause; - private Session session; - private String reason; + /** + * Creates a new DisconnectingEvent instance. + * + * @param session Session being disconnected. + * @param reason Reason for the session to disconnect. + */ + public DisconnectingEvent(Session session, String reason) { + this(session, reason, null); + } - public DisconnectingEvent(Session session, String reason) { - this.session = session; - this.reason = reason; - } + /** + * Creates a new DisconnectingEvent instance. + * + * @param session Session being disconnected. + * @param reason Reason for the session to disconnect. + * @param cause Throwable that caused the disconnect. + */ + public DisconnectingEvent(Session session, String reason, Throwable cause) { + this.session = session; + this.reason = reason; + this.cause = cause; + } - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } - /** - * Gets the reason given for the session disconnecting. - * - * @return The event's reason. - */ - public String getReason() { - return this.reason; - } + /** + * Gets the reason given for the session disconnecting. + * + * @return The event's reason. + */ + public String getReason() { + return this.reason; + } - @Override - public void call(SessionListener listener) { - listener.disconnecting(this); - } + /** + * Gets the Throwable responsible for the session disconnecting. + * + * @return The Throwable responsible for the disconnect, or null if the disconnect was not caused by a Throwable. + */ + public Throwable getCause() { + return this.cause; + } + @Override + public void call(SessionListener listener) { + listener.disconnecting(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java index e0a5d4c2..4f945123 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java @@ -7,42 +7,46 @@ import org.spacehq.packetlib.packet.Packet; * Called when the session receives a packet. */ public class PacketReceivedEvent implements SessionEvent { + private Session session; + private Packet packet; - private Session session; - private Packet packet; + /** + * Creates a new PacketReceivedEvent instance. + * + * @param session Session receiving a packet. + * @param packet Packet being received. + */ + public PacketReceivedEvent(Session session, Packet packet) { + this.session = session; + this.packet = packet; + } - public PacketReceivedEvent(Session session, Packet packet) { - this.session = session; - this.packet = packet; - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - /** - * Gets the packet involved in this event as the required type. - * - * @return The event's packet as the required type. - * @throws IllegalStateException If the packet's value isn't of the required type. - */ - @SuppressWarnings("unchecked") - public T getPacket() { - try { - return (T) this.packet; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); - } - } - - @Override - public void call(SessionListener listener) { - listener.packetReceived(this); - } + /** + * Gets the packet involved in this event as the required type. + * + * @return The event's packet as the required type. + * @throws IllegalStateException If the packet's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getPacket() { + try { + return (T) this.packet; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); + } + } + @Override + public void call(SessionListener listener) { + listener.packetReceived(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java index e82109ed..f9815ebb 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java @@ -7,42 +7,46 @@ import org.spacehq.packetlib.packet.Packet; * Called when the session has sent a packet. */ public class PacketSentEvent implements SessionEvent { + private Session session; + private Packet packet; - private Session session; - private Packet packet; + /** + * Creates a new PacketSentEvent instance. + * + * @param session Session sending the packet. + * @param packet Packet being sent. + */ + public PacketSentEvent(Session session, Packet packet) { + this.session = session; + this.packet = packet; + } - public PacketSentEvent(Session session, Packet packet) { - this.session = session; - this.packet = packet; - } + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - /** - * Gets the packet involved in this event as the required type. - * - * @return The event's packet as the required type. - * @throws IllegalStateException If the packet's value isn't of the required type. - */ - @SuppressWarnings("unchecked") - public T getPacket() { - try { - return (T) this.packet; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); - } - } - - @Override - public void call(SessionListener listener) { - listener.packetSent(this); - } + /** + * Gets the packet involved in this event as the required type. + * + * @return The event's packet as the required type. + * @throws IllegalStateException If the packet's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getPacket() { + try { + return (T) this.packet; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); + } + } + @Override + public void call(SessionListener listener) { + listener.packetSent(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java b/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java index 8821d138..7f8014dc 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java @@ -4,25 +4,23 @@ package org.spacehq.packetlib.event.session; * An adapter for picking session events to listen for. */ public class SessionAdapter implements SessionListener { + @Override + public void packetReceived(PacketReceivedEvent event) { + } - @Override - public void packetReceived(PacketReceivedEvent event) { - } + @Override + public void packetSent(PacketSentEvent event) { + } - @Override - public void packetSent(PacketSentEvent event) { - } + @Override + public void connected(ConnectedEvent event) { + } - @Override - public void connected(ConnectedEvent event) { - } - - @Override - public void disconnecting(DisconnectingEvent event) { - } - - @Override - public void disconnected(DisconnectedEvent event) { - } + @Override + public void disconnecting(DisconnectingEvent event) { + } + @Override + public void disconnected(DisconnectedEvent event) { + } } diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java b/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java index 88e343fa..20bc7c4f 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java @@ -4,12 +4,10 @@ package org.spacehq.packetlib.event.session; * An event relating to sessions. */ public interface SessionEvent { - - /** - * Calls the event. - * - * @param listener Listener to call the event on. - */ - public void call(SessionListener listener); - + /** + * Calls the event. + * + * @param listener Listener to call the event on. + */ + public void call(SessionListener listener); } diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java b/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java index edb03da5..b40a66d0 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java +++ b/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java @@ -4,40 +4,38 @@ package org.spacehq.packetlib.event.session; * A listener for listening to session events. */ public interface SessionListener { + /** + * Called when a session receives a packet. + * + * @param event Data relating to the event. + */ + public void packetReceived(PacketReceivedEvent event); - /** - * Called when a session receives a packet. - * - * @param event Data relating to the event. - */ - public void packetReceived(PacketReceivedEvent event); + /** + * Called when a session sends a packet. + * + * @param event Data relating to the event. + */ + public void packetSent(PacketSentEvent event); - /** - * Called when a session sends a packet. - * - * @param event Data relating to the event. - */ - public void packetSent(PacketSentEvent event); + /** + * Called when a session connects. + * + * @param event Data relating to the event. + */ + public void connected(ConnectedEvent event); - /** - * Called when a session connects. - * - * @param event Data relating to the event. - */ - public void connected(ConnectedEvent event); - - /** - * Called when a session is about to disconnect. - * - * @param event Data relating to the event. - */ - public void disconnecting(DisconnectingEvent event); - - /** - * Called when a session is disconnected. - * - * @param event Data relating to the event. - */ - public void disconnected(DisconnectedEvent event); + /** + * Called when a session is about to disconnect. + * + * @param event Data relating to the event. + */ + public void disconnecting(DisconnectingEvent event); + /** + * Called when a session is disconnected. + * + * @param event Data relating to the event. + */ + public void disconnected(DisconnectedEvent event); } diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index 365793e6..d6294b92 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -7,161 +7,159 @@ import java.util.UUID; * An interface for reading network data. */ public interface NetInput { + /** + * Reads the next boolean. + * + * @return The next boolean. + * @throws java.io.IOException If an I/O error occurs. + */ + public boolean readBoolean() throws IOException; - /** - * Reads the next boolean. - * - * @return The next boolean. - * @throws java.io.IOException If an I/O error occurs. - */ - public boolean readBoolean() throws IOException; + /** + * Reads the next byte. + * + * @return The next byte. + * @throws java.io.IOException If an I/O error occurs. + */ + public byte readByte() throws IOException; - /** - * Reads the next byte. - * - * @return The next byte. - * @throws java.io.IOException If an I/O error occurs. - */ - public byte readByte() throws IOException; + /** + * Reads the next unsigned byte. + * + * @return The next unsigned byte. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readUnsignedByte() throws IOException; - /** - * Reads the next unsigned byte. - * - * @return The next unsigned byte. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readUnsignedByte() throws IOException; + /** + * Reads the next short. + * + * @return The next short. + * @throws java.io.IOException If an I/O error occurs. + */ + public short readShort() throws IOException; - /** - * Reads the next short. - * - * @return The next short. - * @throws java.io.IOException If an I/O error occurs. - */ - public short readShort() throws IOException; + /** + * Reads the next unsigned short. + * + * @return The next unsigned short. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readUnsignedShort() throws IOException; - /** - * Reads the next unsigned short. - * - * @return The next unsigned short. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readUnsignedShort() throws IOException; + /** + * Reads the next char. + * + * @return The next char. + * @throws java.io.IOException If an I/O error occurs. + */ + public char readChar() throws IOException; - /** - * Reads the next char. - * - * @return The next char. - * @throws java.io.IOException If an I/O error occurs. - */ - public char readChar() throws IOException; + /** + * Reads the next integer. + * + * @return The next integer. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readInt() throws IOException; - /** - * Reads the next integer. - * - * @return The next integer. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readInt() throws IOException; + /** + * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * + * @return The next varint. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readVarInt() throws IOException; - /** - * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. - * - * @return The next varint. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readVarInt() throws IOException; + /** + * Reads the next long. + * + * @return The next long. + * @throws java.io.IOException If an I/O error occurs. + */ + public long readLong() throws IOException; - /** - * Reads the next long. - * - * @return The next long. - * @throws java.io.IOException If an I/O error occurs. - */ - public long readLong() throws IOException; + /** + * Reads the next varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. + * + * @return The next varlong. + * @throws java.io.IOException If an I/O error occurs. + */ + public long readVarLong() throws IOException; - /** - * Reads the next varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. - * - * @return The next varlong. - * @throws java.io.IOException If an I/O error occurs. - */ - public long readVarLong() throws IOException; + /** + * Reads the next float. + * + * @return The next float. + * @throws java.io.IOException If an I/O error occurs. + */ + public float readFloat() throws IOException; - /** - * Reads the next float. - * - * @return The next float. - * @throws java.io.IOException If an I/O error occurs. - */ - public float readFloat() throws IOException; + /** + * Reads the next double. + * + * @return The next double. + * @throws java.io.IOException If an I/O error occurs. + */ + public double readDouble() throws IOException; - /** - * Reads the next double. - * - * @return The next double. - * @throws java.io.IOException If an I/O error occurs. - */ - public double readDouble() throws IOException; + /** + * Reads the next byte array, getting the length from a prefixed length value. + * + * @return The next byte array. + * @throws java.io.IOException If an I/O error occurs. + */ + public byte[] readPrefixedBytes() throws IOException; - /** - * Reads the next byte array, getting the length from a prefixed length value. - * - * @return The next byte array. - * @throws java.io.IOException If an I/O error occurs. - */ - public byte[] readPrefixedBytes() throws IOException; + /** + * Reads the next byte array. + * + * @param length The length of the byte array. + * @return The next byte array. + * @throws java.io.IOException If an I/O error occurs. + */ + public byte[] readBytes(int length) throws IOException; - /** - * Reads the next byte array. - * - * @param length The length of the byte array. - * @return The next byte array. - * @throws java.io.IOException If an I/O error occurs. - */ - public byte[] readBytes(int length) throws IOException; + /** + * Reads as much data as possible into the given byte array. + * + * @param b Byte array to read to. + * @return The amount of bytes read, or -1 if no bytes could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readBytes(byte b[]) throws IOException; - /** - * Reads as much data as possible into the given byte array. - * - * @param b Byte array to read to. - * @return The amount of bytes read, or -1 if no bytes could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readBytes(byte b[]) throws IOException; + /** + * Reads the given amount of bytes into the given array at the given offset. + * + * @param b Byte array to read to. + * @param offset Offset of the array to read to. + * @param length Length of bytes to read. + * @return The amount of bytes read, or -1 if no bytes could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readBytes(byte b[], int offset, int length) throws IOException; - /** - * Reads the given amount of bytes into the given array at the given offset. - * - * @param b Byte array to read to. - * @param offset Offset of the array to read to. - * @param length Length of bytes to read. - * @return The amount of bytes read, or -1 if no bytes could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readBytes(byte b[], int offset, int length) throws IOException; + /** + * Reads the next string. + * + * @return The next string. + * @throws java.io.IOException If an I/O error occurs. + */ + public String readString() throws IOException; - /** - * Reads the next string. - * - * @return The next string. - * @throws java.io.IOException If an I/O error occurs. - */ - public String readString() throws IOException; - - /** - * Reads the next UUID. - * - * @return The next UUID. - * @throws java.io.IOException If an I/O error occurs. - */ - public UUID readUUID() throws IOException; - - /** - * Gets the number of available bytes. - * - * @return The number of available bytes. - */ - public int available() throws IOException; + /** + * Reads the next UUID. + * + * @return The next UUID. + * @throws java.io.IOException If an I/O error occurs. + */ + public UUID readUUID() throws IOException; + /** + * Gets the number of available bytes. + * + * @return The number of available bytes. + */ + public int available() throws IOException; } diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index 5e438e81..30dff1fa 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -7,133 +7,131 @@ import java.util.UUID; * An interface for writing network data. */ public interface NetOutput { + /** + * Writes a boolean. + * + * @param b Boolean to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeBoolean(boolean b) throws IOException; - /** - * Writes a boolean. - * - * @param b Boolean to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeBoolean(boolean b) throws IOException; + /** + * Writes a byte. + * + * @param b Byte to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeByte(int b) throws IOException; - /** - * Writes a byte. - * - * @param b Byte to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeByte(int b) throws IOException; + /** + * Writes a short. + * + * @param s Short to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeShort(int s) throws IOException; - /** - * Writes a short. - * - * @param s Short to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeShort(int s) throws IOException; + /** + * Writes a char. + * + * @param c Char to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeChar(int c) throws IOException; - /** - * Writes a char. - * - * @param c Char to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeChar(int c) throws IOException; + /** + * Writes a integer. + * + * @param i Integer to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeInt(int i) throws IOException; - /** - * Writes a integer. - * - * @param i Integer to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeInt(int i) throws IOException; + /** + * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. + * + * @return i Varint to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeVarInt(int i) throws IOException; - /** - * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. - * - * @return i Varint to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeVarInt(int i) throws IOException; + /** + * Writes a long. + * + * @param l Long to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeLong(long l) throws IOException; - /** - * Writes a long. - * - * @param l Long to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeLong(long l) throws IOException; + /** + * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. + * + * @return l Varlong to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeVarLong(long l) throws IOException; - /** - * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. - * - * @return l Varlong to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeVarLong(long l) throws IOException; + /** + * Writes a float. + * + * @param f Float to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeFloat(float f) throws IOException; - /** - * Writes a float. - * - * @param f Float to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeFloat(float f) throws IOException; + /** + * Writes a double. + * + * @param d Double to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeDouble(double d) throws IOException; - /** - * Writes a double. - * - * @param d Double to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeDouble(double d) throws IOException; + /** + * Writes a byte array, prefixing the written data with the array's length. + * + * @param b Byte array to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writePrefixedBytes(byte b[]) throws IOException; - /** - * Writes a byte array, prefixing the written data with the array's length. - * - * @param b Byte array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writePrefixedBytes(byte b[]) throws IOException; + /** + * Writes a byte array. + * + * @param b Byte array to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeBytes(byte b[]) throws IOException; - /** - * Writes a byte array. - * - * @param b Byte array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeBytes(byte b[]) throws IOException; + /** + * Writes a byte array, using the given amount of bytes. + * + * @param b Byte array to write. + * @param length Bytes to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeBytes(byte b[], int length) throws IOException; - /** - * Writes a byte array, using the given amount of bytes. - * - * @param b Byte array to write. - * @param length Bytes to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeBytes(byte b[], int length) throws IOException; + /** + * Writes a string. + * + * @param s String to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeString(String s) throws IOException; - /** - * Writes a string. - * - * @param s String to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeString(String s) throws IOException; - - /** - * Writes a UUID. - * - * @param uuid UUID to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeUUID(UUID uuid) throws IOException; - - /** - * Flushes the output. - * - * @throws java.io.IOException If an I/O error occurs. - */ - public void flush() throws IOException; + /** + * Writes a UUID. + * + * @param uuid UUID to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeUUID(UUID uuid) throws IOException; + /** + * Flushes the output. + * + * @throws java.io.IOException If an I/O error occurs. + */ + public void flush() throws IOException; } diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index f6273be3..c980e183 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -11,158 +11,161 @@ import java.util.UUID; * A NetInput implementation using an InputStream as a backend. */ public class StreamNetInput implements NetInput { + private InputStream in; - private InputStream in; + /** + * Creates a new StreamNetInput instance. + * + * @param in InputStream to read from. + */ + public StreamNetInput(InputStream in) { + this.in = in; + } - public StreamNetInput(InputStream in) { - this.in = in; - } + @Override + public boolean readBoolean() throws IOException { + return this.readByte() == 1; + } - @Override - public boolean readBoolean() throws IOException { - return this.readByte() == 1; - } + @Override + public byte readByte() throws IOException { + return (byte) this.readUnsignedByte(); + } - @Override - public byte readByte() throws IOException { - return (byte) this.readUnsignedByte(); - } + @Override + public int readUnsignedByte() throws IOException { + int b = this.in.read(); + if(b < 0) { + throw new EOFException(); + } - @Override - public int readUnsignedByte() throws IOException { - int b = this.in.read(); - if(b < 0) { - throw new EOFException(); - } + return b; + } - return b; - } + @Override + public short readShort() throws IOException { + return (short) this.readUnsignedShort(); + } - @Override - public short readShort() throws IOException { - return (short) this.readUnsignedShort(); - } + @Override + public int readUnsignedShort() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + return (ch1 << 8) + (ch2 << 0); + } - @Override - public int readUnsignedShort() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - return (ch1 << 8) + (ch2 << 0); - } + @Override + public char readChar() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + return (char) ((ch1 << 8) + (ch2 << 0)); + } - @Override - public char readChar() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - return (char) ((ch1 << 8) + (ch2 << 0)); - } + @Override + public int readInt() throws IOException { + int ch1 = this.readUnsignedByte(); + int ch2 = this.readUnsignedByte(); + int ch3 = this.readUnsignedByte(); + int ch4 = this.readUnsignedByte(); + return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); + } - @Override - public int readInt() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - int ch3 = this.readUnsignedByte(); - int ch4 = this.readUnsignedByte(); - return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); - } + @Override + public int readVarInt() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 5) { + throw new IOException("VarInt too long (length must be <= 5)"); + } + } - @Override - public int readVarInt() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 5) { - throw new IOException("VarInt too long (length must be <= 5)"); - } - } + return value | ((b & 0x7F) << (size * 7)); + } - return value | ((b & 0x7F) << (size * 7)); - } + @Override + public long readLong() throws IOException { + byte read[] = this.readBytes(8); + return ((long) read[0] << 56) + ((long) (read[1] & 255) << 48) + ((long) (read[2] & 255) << 40) + ((long) (read[3] & 255) << 32) + ((long) (read[4] & 255) << 24) + ((read[5] & 255) << 16) + ((read[6] & 255) << 8) + ((read[7] & 255) << 0); + } - @Override - public long readLong() throws IOException { - byte read[] = this.readBytes(8); - return ((long) read[0] << 56) + ((long) (read[1] & 255) << 48) + ((long) (read[2] & 255) << 40) + ((long) (read[3] & 255) << 32) + ((long) (read[4] & 255) << 24) + ((read[5] & 255) << 16) + ((read[6] & 255) << 8) + ((read[7] & 255) << 0); - } + @Override + public long readVarLong() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 10) { + throw new IOException("VarLong too long (length must be <= 10)"); + } + } - @Override - public long readVarLong() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 10) { - throw new IOException("VarLong too long (length must be <= 10)"); - } - } + return value | ((b & 0x7F) << (size * 7)); + } - return value | ((b & 0x7F) << (size * 7)); - } + @Override + public float readFloat() throws IOException { + return Float.intBitsToFloat(this.readInt()); + } - @Override - public float readFloat() throws IOException { - return Float.intBitsToFloat(this.readInt()); - } + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(this.readLong()); + } - @Override - public double readDouble() throws IOException { - return Double.longBitsToDouble(this.readLong()); - } + @Override + public byte[] readPrefixedBytes() throws IOException { + short length = this.readShort(); + return this.readBytes(length); + } - @Override - public byte[] readPrefixedBytes() throws IOException { - short length = this.readShort(); - return this.readBytes(length); - } + @Override + public byte[] readBytes(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } - @Override - public byte[] readBytes(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } + byte b[] = new byte[length]; + int n = 0; + while(n < length) { + int count = this.in.read(b, n, length - n); + if(count < 0) { + throw new EOFException(); + } - byte b[] = new byte[length]; - int n = 0; - while(n < length) { - int count = this.in.read(b, n, length - n); - if(count < 0) { - throw new EOFException(); - } + n += count; + } - n += count; - } + return b; + } - return b; - } + @Override + public int readBytes(byte[] b) throws IOException { + return this.in.read(b); + } - @Override - public int readBytes(byte[] b) throws IOException { - return this.in.read(b); - } + @Override + public int readBytes(byte[] b, int offset, int length) throws IOException { + return this.in.read(b, offset, length); + } - @Override - public int readBytes(byte[] b, int offset, int length) throws IOException { - return this.in.read(b, offset, length); - } + @Override + public String readString() throws IOException { + int length = this.readVarInt(); + byte bytes[] = this.readBytes(length); + return new String(bytes, "UTF-8"); + } - @Override - public String readString() throws IOException { - int length = this.readVarInt(); - byte bytes[] = this.readBytes(length); - return new String(bytes, "UTF-8"); - } - - @Override - public UUID readUUID() throws IOException { - return new UUID(this.readLong(), this.readLong()); - } - - @Override - public int available() throws IOException { - return this.in.available(); - } + @Override + public UUID readUUID() throws IOException { + return new UUID(this.readLong(), this.readLong()); + } + @Override + public int available() throws IOException { + return this.in.available(); + } } diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index 0b3cd7e5..9a05bd7e 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -10,125 +10,128 @@ import java.util.UUID; * A NetOutput implementation using an OutputStream as a backend. */ public class StreamNetOutput implements NetOutput { + private OutputStream out; - private OutputStream out; + /** + * Creates a new StreamNetOutput instance. + * + * @param out OutputStream to write to. + */ + public StreamNetOutput(OutputStream out) { + this.out = out; + } - public StreamNetOutput(OutputStream out) { - this.out = out; - } + @Override + public void writeBoolean(boolean b) throws IOException { + this.writeByte(b ? 1 : 0); + } - @Override - public void writeBoolean(boolean b) throws IOException { - this.writeByte(b ? 1 : 0); - } + @Override + public void writeByte(int b) throws IOException { + this.out.write(b); + } - @Override - public void writeByte(int b) throws IOException { - this.out.write(b); - } + @Override + public void writeShort(int s) throws IOException { + this.writeByte((byte) ((s >>> 8) & 0xFF)); + this.writeByte((byte) ((s >>> 0) & 0xFF)); + } - @Override - public void writeShort(int s) throws IOException { - this.writeByte((byte) ((s >>> 8) & 0xFF)); - this.writeByte((byte) ((s >>> 0) & 0xFF)); - } + @Override + public void writeChar(int c) throws IOException { + this.writeByte((byte) ((c >>> 8) & 0xFF)); + this.writeByte((byte) ((c >>> 0) & 0xFF)); + } - @Override - public void writeChar(int c) throws IOException { - this.writeByte((byte) ((c >>> 8) & 0xFF)); - this.writeByte((byte) ((c >>> 0) & 0xFF)); - } + @Override + public void writeInt(int i) throws IOException { + this.writeByte((byte) ((i >>> 24) & 0xFF)); + this.writeByte((byte) ((i >>> 16) & 0xFF)); + this.writeByte((byte) ((i >>> 8) & 0xFF)); + this.writeByte((byte) ((i >>> 0) & 0xFF)); + } - @Override - public void writeInt(int i) throws IOException { - this.writeByte((byte) ((i >>> 24) & 0xFF)); - this.writeByte((byte) ((i >>> 16) & 0xFF)); - this.writeByte((byte) ((i >>> 8) & 0xFF)); - this.writeByte((byte) ((i >>> 0) & 0xFF)); - } + @Override + public void writeVarInt(int i) throws IOException { + while((i & ~0x7F) != 0) { + this.writeByte((i & 0x7F) | 0x80); + i >>>= 7; + } - @Override - public void writeVarInt(int i) throws IOException { - while((i & ~0x7F) != 0) { - this.writeByte((i & 0x7F) | 0x80); - i >>>= 7; - } + this.writeByte(i); + } - this.writeByte(i); - } + @Override + public void writeLong(long l) throws IOException { + this.writeByte((byte) (l >>> 56)); + this.writeByte((byte) (l >>> 48)); + this.writeByte((byte) (l >>> 40)); + this.writeByte((byte) (l >>> 32)); + this.writeByte((byte) (l >>> 24)); + this.writeByte((byte) (l >>> 16)); + this.writeByte((byte) (l >>> 8)); + this.writeByte((byte) (l >>> 0)); + } - @Override - public void writeLong(long l) throws IOException { - this.writeByte((byte) (l >>> 56)); - this.writeByte((byte) (l >>> 48)); - this.writeByte((byte) (l >>> 40)); - this.writeByte((byte) (l >>> 32)); - this.writeByte((byte) (l >>> 24)); - this.writeByte((byte) (l >>> 16)); - this.writeByte((byte) (l >>> 8)); - this.writeByte((byte) (l >>> 0)); - } + @Override + public void writeVarLong(long l) throws IOException { + while((l & ~0x7F) != 0) { + this.writeByte((int) (l & 0x7F) | 0x80); + l >>>= 7; + } - @Override - public void writeVarLong(long l) throws IOException { - while((l & ~0x7F) != 0) { - this.writeByte((int) (l & 0x7F) | 0x80); - l >>>= 7; - } + this.writeByte((int) l); + } - this.writeByte((int) l); - } + @Override + public void writeFloat(float f) throws IOException { + this.writeInt(Float.floatToIntBits(f)); + } - @Override - public void writeFloat(float f) throws IOException { - this.writeInt(Float.floatToIntBits(f)); - } + @Override + public void writeDouble(double d) throws IOException { + this.writeLong(Double.doubleToLongBits(d)); + } - @Override - public void writeDouble(double d) throws IOException { - this.writeLong(Double.doubleToLongBits(d)); - } + @Override + public void writePrefixedBytes(byte b[]) throws IOException { + this.writeShort(b.length); + this.writeBytes(b); + } - @Override - public void writePrefixedBytes(byte b[]) throws IOException { - this.writeShort(b.length); - this.writeBytes(b); - } + @Override + public void writeBytes(byte b[]) throws IOException { + this.writeBytes(b, b.length); + } - @Override - public void writeBytes(byte b[]) throws IOException { - this.writeBytes(b, b.length); - } + @Override + public void writeBytes(byte b[], int length) throws IOException { + this.out.write(b, 0, length); + } - @Override - public void writeBytes(byte b[], int length) throws IOException { - this.out.write(b, 0, length); - } + @Override + public void writeString(String s) throws IOException { + if(s == null) { + throw new IllegalArgumentException("String cannot be null!"); + } - @Override - public void writeString(String s) throws IOException { - if(s == null) { - throw new IllegalArgumentException("String cannot be null!"); - } + byte[] bytes = s.getBytes("UTF-8"); + if(bytes.length > 32767) { + throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); + } else { + this.writeVarInt(bytes.length); + this.writeBytes(bytes); + } + } - byte[] bytes = s.getBytes("UTF-8"); - if(bytes.length > 32767) { - throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); - } else { - this.writeVarInt(bytes.length); - this.writeBytes(bytes); - } - } - - @Override - public void writeUUID(UUID uuid) throws IOException { - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - } - - @Override - public void flush() throws IOException { - this.out.flush(); - } + @Override + public void writeUUID(UUID uuid) throws IOException { + this.writeLong(uuid.getMostSignificantBits()); + this.writeLong(uuid.getLeastSignificantBits()); + } + @Override + public void flush() throws IOException { + this.out.flush(); + } } diff --git a/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java b/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java index 2e160ae3..99972adb 100644 --- a/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java +++ b/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java @@ -5,55 +5,52 @@ import org.spacehq.packetlib.io.NetOutput; import java.io.IOException; +/** + * The default packet header, using a varint packet length and id. + */ public class DefaultPacketHeader implements PacketHeader { + @Override + public boolean isLengthVariable() { + return true; + } - @Override - public boolean isLengthVariable() { - return true; - } + @Override + public int getLengthSize() { + return 5; + } - @Override - public int getLengthSize() { - return 5; - } + @Override + public int getLengthSize(int length) { + if((length & -128) == 0) { + return 1; + } else if((length & -16384) == 0) { + return 2; + } else if((length & -2097152) == 0) { + return 3; + } else if((length & -268435456) == 0) { + return 4; + } else { + return 5; + } + } - @Override - public int getLengthSize(int length) { - return varintLength(length); - } + @Override + public int readLength(NetInput in, int available) throws IOException { + return in.readVarInt(); + } - @Override - public int readLength(NetInput in, int available) throws IOException { - return in.readVarInt(); - } + @Override + public void writeLength(NetOutput out, int length) throws IOException { + out.writeVarInt(length); + } - @Override - public void writeLength(NetOutput out, int length) throws IOException { - out.writeVarInt(length); - } - - @Override - public int readPacketId(NetInput in) throws IOException { - return in.readVarInt(); - } - - @Override - public void writePacketId(NetOutput out, int packetId) throws IOException { - out.writeVarInt(packetId); - } - - private static int varintLength(int i) { - if((i & -128) == 0) { - return 1; - } else if((i & -16384) == 0) { - return 2; - } else if((i & -2097152) == 0) { - return 3; - } else if((i & -268435456) == 0) { - return 4; - } else { - return 5; - } - } + @Override + public int readPacketId(NetInput in) throws IOException { + return in.readVarInt(); + } + @Override + public void writePacketId(NetOutput out, int packetId) throws IOException { + out.writeVarInt(packetId); + } } diff --git a/src/main/java/org/spacehq/packetlib/packet/Packet.java b/src/main/java/org/spacehq/packetlib/packet/Packet.java index e993ee3d..a36d9a22 100644 --- a/src/main/java/org/spacehq/packetlib/packet/Packet.java +++ b/src/main/java/org/spacehq/packetlib/packet/Packet.java @@ -9,28 +9,26 @@ import java.io.IOException; * A network packet. */ public interface Packet { + /** + * Reads the packet from the given input buffer. + * + * @param in The input source to read from. + */ + public void read(NetInput in) throws IOException; - /** - * Reads the packet from the given input buffer. - * - * @param in The input source to read from. - */ - public void read(NetInput in) throws IOException; - - /** - * Writes the packet to the given output buffer. - * - * @param out The output destination to write to. - */ - public void write(NetOutput out) throws IOException; - - /** - * Gets whether the packet has handling and writing priority. - * If the result is true, the thread will wait for the packet to finish writing - * when writing and the packet will be handled immediately after reading it. - * - * @return Whether the packet has priority. - */ - public boolean isPriority(); + /** + * Writes the packet to the given output buffer. + * + * @param out The output destination to write to. + */ + public void write(NetOutput out) throws IOException; + /** + * Gets whether the packet has handling and writing priority. + * If the result is true, the thread will wait for the packet to finish writing + * when writing and the packet will be handled immediately after reading it. + * + * @return Whether the packet has priority. + */ + public boolean isPriority(); } diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java index 6e9203d4..3176a281 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java @@ -9,64 +9,62 @@ import java.io.IOException; * The header of a protocol's packets. */ public interface PacketHeader { + /** + * Gets whether the header's length value can vary in size. + * + * @return Whether the header's length value can vary in size. + */ + public boolean isLengthVariable(); - /** - * Gets whether the header's length value can vary in size. - * - * @return Whether the header's length value can vary in size. - */ - public boolean isLengthVariable(); + /** + * Gets the size of the header's length value. + * + * @return The length value's size. + */ + public int getLengthSize(); - /** - * Gets the size of the header's length value. - * - * @return The length value's size. - */ - public int getLengthSize(); + /** + * Gets the size of the header's length value. + * + * @param length Length value to get the size of. + * @return The length value's size. + */ + public int getLengthSize(int length); - /** - * Gets the size of the header's length value. - * - * @param length Length value to get the size of. - * @return The length value's size. - */ - public int getLengthSize(int length); + /** + * Reads the length of a packet from the given input. + * + * @param in Input to read from. + * @param available Number of available bytes in the NetInput. + * @return The resulting packet length. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readLength(NetInput in, int available) throws IOException; - /** - * Reads the length of a packet from the given input. - * - * @param in Input to read from. - * @param available Number of available bytes in the NetInput. - * @return The resulting packet length. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readLength(NetInput in, int available) throws IOException; + /** + * Writes the length of a packet to the given output. + * + * @param out Output to write to. + * @param length Length to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeLength(NetOutput out, int length) throws IOException; - /** - * Writes the length of a packet to the given output. - * - * @param out Output to write to. - * @param length Length to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writeLength(NetOutput out, int length) throws IOException; - - /** - * Reads the ID of a packet from the given input. - * - * @param in Input to read from. - * @return The resulting packet ID, or -1 if the packet should not be read yet. - * @throws java.io.IOException If an I/O error occurs. - */ - public int readPacketId(NetInput in) throws IOException; - - /** - * Writes the ID of a packet to the given output. - * - * @param out Output to write to. - * @param packetId Packet ID to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writePacketId(NetOutput out, int packetId) throws IOException; + /** + * Reads the ID of a packet from the given input. + * + * @param in Input to read from. + * @return The resulting packet ID, or -1 if the packet should not be read yet. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readPacketId(NetInput in) throws IOException; + /** + * Writes the ID of a packet to the given output. + * + * @param out Output to write to. + * @param packetId Packet ID to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writePacketId(NetOutput out, int packetId) throws IOException; } diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java index b4c8b5e0..d7d716f7 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java +++ b/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java @@ -14,143 +14,133 @@ import java.util.Map; * All implementations must have a no-params constructor for server protocol creation. */ public abstract class PacketProtocol { + private final Map> incoming = new HashMap>(); + private final Map, Integer> outgoing = new HashMap, Integer>(); - private final Map> incoming = new HashMap>(); - private final Map, Integer> outgoing = new HashMap, Integer>(); + /** + * Gets the prefix used when locating SRV records for this protocol. + * + * @return The protocol's SRV record prefix. + */ + public abstract String getSRVRecordPrefix(); - /** - * Gets whether this protocol will ever need a packet sizer. - * - * @return Whether this protocol will ever need a packet sizer. - */ - public abstract boolean needsPacketSizer(); + /** + * Gets the packet header of this protocol. + * + * @return The protocol's packet header. + */ + public abstract PacketHeader getPacketHeader(); - /** - * Gets whether this protocol will ever need a packet encryptor. - * - * @return Whether this protocol will ever need a packet encryptor. - */ - public abstract boolean needsPacketEncryptor(); + /** + * Gets this protocol's active packet encryption. + * + * @return The protocol's packet encryption, or null if packets should not be encrypted. + */ + public abstract PacketEncryption getEncryption(); - /** - * Gets the packet header of this protocol. - * - * @return The protocol's packet header. - */ - public abstract PacketHeader getPacketHeader(); + /** + * Called when a client session is created with this protocol. + * + * @param client The client that the session belongs to. + * @param session The created session. + */ + public abstract void newClientSession(Client client, Session session); - /** - * Gets this protocol's active packet encryption. - * - * @return The protocol's packet encryption, or null if packets should not be encrypted. - */ - public abstract PacketEncryption getEncryption(); + /** + * Called when a server session is created with this protocol. + * + * @param server The server that the session belongs to. + * @param session The created session. + */ + public abstract void newServerSession(Server server, Session session); - /** - * Called when a client is created with this protocol. - * - * @param client The client that the session belongs to. - * @param session The created session. - */ - public abstract void newClientSession(Client client, Session session); + /** + * Clears all currently registered packets. + */ + public final void clearPackets() { + this.incoming.clear(); + this.outgoing.clear(); + } - /** - * Called when a server's session is created with this protocol. - * - * @param server The server that the session belongs to. - * @param session The created session. - */ - public abstract void newServerSession(Server server, Session session); + /** + * Registers a packet to this protocol as both incoming and outgoing. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + */ + public final void register(int id, Class packet) { + this.registerIncoming(id, packet); + this.registerOutgoing(id, packet); + } - /** - * Clears all currently registered packets. - */ - public final void clearPackets() { - this.incoming.clear(); - this.outgoing.clear(); - } + /** + * Registers an incoming packet to this protocol. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + * @throws IllegalArgumentException If the packet fails a test creation. + */ + public final void registerIncoming(int id, Class packet) { + this.incoming.put(id, packet); + try { + this.createIncomingPacket(id); + } catch(IllegalStateException e) { + this.incoming.remove(id); + throw new IllegalArgumentException(e.getMessage(), e.getCause()); + } + } - /** - * Registers a packet to this protocol as both incoming and outgoing. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. - */ - public final void register(int id, Class packet) { - this.registerIncoming(id, packet); - this.registerOutgoing(id, packet); - } + /** + * Registers an outgoing packet to this protocol. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + */ + public final void registerOutgoing(int id, Class packet) { + this.outgoing.put(packet, id); + } - /** - * Registers an incoming packet to this protocol. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @throws IllegalArgumentException If the packet fails a test creation. - */ - public final void registerIncoming(int id, Class packet) { - this.incoming.put(id, packet); - try { - this.createIncomingPacket(id); - } catch(IllegalStateException e) { - this.incoming.remove(id); - throw new IllegalArgumentException(e.getMessage(), e.getCause()); - } - } + /** + * Creates a new instance of an incoming packet with the given id. + * + * @param id Id of the packet to create. + * @return The created packet. + * @throws IllegalArgumentException If the packet ID is invalid. + * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. + */ + public final Packet createIncomingPacket(int id) { + if(id < 0 || !this.incoming.containsKey(id) || this.incoming.get(id) == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } - /** - * Registers an outgoing packet to this protocol. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - */ - public final void registerOutgoing(int id, Class packet) { - this.outgoing.put(packet, id); - } + Class packet = this.incoming.get(id); + try { + Constructor constructor = packet.getDeclaredConstructor(); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } - /** - * Creates a new instance of an incoming packet with the given id. - * - * @param id Id of the packet to create. - * @return The created packet. - * @throws IllegalArgumentException If the packet ID is invalid. - * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. - */ - public final Packet createIncomingPacket(int id) { - if(id < 0 || !this.incoming.containsKey(id) || this.incoming.get(id) == null) { - throw new IllegalArgumentException("Invalid packet id: " + id); - } - - Class packet = this.incoming.get(id); - try { - Constructor constructor = packet.getDeclaredConstructor(); - if(!constructor.isAccessible()) { - constructor.setAccessible(true); - } - - return constructor.newInstance(); - } catch(NoSuchMethodError e) { - throw new IllegalStateException("Packet \"" + id + ", " + packet.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + packet.getName() + "\".", e); - } - } - - /** - * Gets the registered id of an outgoing packet class. - * - * @param packet Class of the packet to get the id for. - * @return The packet's registered id. - * @throws IllegalArgumentException If the packet is not registered. - */ - public final int getOutgoingId(Class packet) { - if(!this.outgoing.containsKey(packet) || this.outgoing.get(packet) == null) { - throw new IllegalArgumentException("Unregistered outgoing packet class: " + packet.getName()); - } - - return this.outgoing.get(packet); - } + return constructor.newInstance(); + } catch(NoSuchMethodError e) { + throw new IllegalStateException("Packet \"" + id + ", " + packet.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + packet.getName() + "\".", e); + } + } + /** + * Gets the registered id of an outgoing packet class. + * + * @param packet Class of the packet to get the id for. + * @return The packet's registered id. + * @throws IllegalArgumentException If the packet is not registered. + */ + public final int getOutgoingId(Class packet) { + if(!this.outgoing.containsKey(packet) || this.outgoing.get(packet) == null) { + throw new IllegalArgumentException("Unregistered outgoing packet class: " + packet.getName()); + } + return this.outgoing.get(packet); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java index 63d82baf..ff86eda9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java @@ -7,15 +7,14 @@ import java.net.Proxy; import java.net.Socket; public class ProxyOioChannelFactory implements ChannelFactory { + private Proxy proxy; - private Proxy proxy; + public ProxyOioChannelFactory(Proxy proxy) { + this.proxy = proxy; + } - public ProxyOioChannelFactory(Proxy proxy) { - this.proxy = proxy; - } - - @Override - public OioSocketChannel newChannel() { - return new OioSocketChannel(new Socket(this.proxy)); - } + @Override + public OioSocketChannel newChannel() { + return new OioSocketChannel(new Socket(this.proxy)); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java new file mode 100644 index 00000000..8dd72527 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -0,0 +1,140 @@ +package org.spacehq.packetlib.tcp; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.oio.OioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.util.concurrent.Future; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.packet.PacketProtocol; + +import javax.naming.directory.InitialDirContext; +import java.net.Proxy; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicBoolean; + +public class TcpClientSession extends TcpSession { + private Client client; + private Proxy proxy; + + private boolean connected; + private EventLoopGroup group; + + public TcpClientSession(String host, int port, PacketProtocol protocol, Client client, Proxy proxy) { + super(host, port, protocol); + this.client = client; + this.proxy = proxy; + } + + @Override + public void connect(boolean wait) { + if(this.disconnected) { + throw new IllegalStateException("Session has already been disconnected."); + } else if(this.connected) { + return; + } + + this.connected = true; + try { + final Bootstrap bootstrap = new Bootstrap(); + if(this.proxy != null) { + this.group = new OioEventLoopGroup(); + bootstrap.channelFactory(new ProxyOioChannelFactory(this.proxy)); + } else { + this.group = new NioEventLoopGroup(); + bootstrap.channel(NioSocketChannel.class); + } + + bootstrap.handler(new ChannelInitializer() { + @Override + public void initChannel(Channel channel) throws Exception { + getPacketProtocol().newClientSession(client, TcpClientSession.this); + + channel.config().setOption(ChannelOption.IP_TOS, 0x18); + channel.config().setOption(ChannelOption.TCP_NODELAY, false); + + ChannelPipeline pipeline = channel.pipeline(); + + refreshReadTimeoutHandler(channel); + refreshWriteTimeoutHandler(channel); + + pipeline.addLast("encryption", new TcpPacketEncryptor(TcpClientSession.this)); + pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); + pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this)); + pipeline.addLast("manager", TcpClientSession.this); + } + }).group(this.group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); + + final AtomicBoolean complete = new AtomicBoolean(false); + new Thread(new Runnable() { + @Override + public void run() { + try { + String host = getHost(); + int port = getPort(); + + try { + Hashtable environment = new Hashtable(); + environment.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); + environment.put("java.naming.provider.url", "dns:"); + + String[] result = new InitialDirContext(environment).getAttributes(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, new String[] { "SRV" }).get("srv").get().toString().split(" ", 4); + host = result[3]; + port = Integer.parseInt(result[2]); + } catch(Throwable t) { + } + + bootstrap.remoteAddress(host, port); + ChannelFuture future = bootstrap.connect(); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + complete.set(true); + if(!future.isSuccess() && future.cause() != null) { + exceptionCaught(null, future.cause()); + } + } + }); + } catch(Throwable t) { + complete.set(true); + } + } + }).start(); + + if(wait) { + while(!complete.get()) { + try { + Thread.sleep(5); + } catch(InterruptedException e) { + break; + } + } + } + } catch(Throwable t) { + exceptionCaught(null, t); + } + } + + @Override + public void disconnect(String reason, Throwable cause, boolean wait) { + super.disconnect(reason, cause, wait); + if(this.group != null) { + Future future = this.group.shutdownGracefully(); + if(wait) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + + this.group = null; + } + } +} diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index dc32b739..34ec1f5c 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -1,49 +1,116 @@ package org.spacehq.packetlib.tcp; +import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.util.concurrent.Future; import org.spacehq.packetlib.ConnectionListener; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.packet.PacketProtocol; + +import java.net.InetSocketAddress; public class TcpConnectionListener implements ConnectionListener { + private String host; + private int port; + private Server server; - private String host; - private int port; - private EventLoopGroup group; - private Channel channel; + private EventLoopGroup group; + private Channel channel; - public TcpConnectionListener(String host, int port, EventLoopGroup group, Channel channel) { - this.host = host; - this.port = port; - this.group = group; - this.channel = channel; - } + public TcpConnectionListener(String host, int port, Server server) { + this.host = host; + this.port = port; + this.server = server; + } - @Override - public String getHost() { - return this.host; - } + @Override + public String getHost() { + return this.host; + } - @Override - public int getPort() { - return this.port; - } + @Override + public int getPort() { + return this.port; + } - @Override - public boolean isListening() { - return this.channel.isOpen(); - } + @Override + public boolean isListening() { + return this.channel != null && this.channel.isOpen(); + } - @Override - public void close() { - if(this.channel.isOpen()) { - this.channel.close().syncUninterruptibly(); - } + @Override + public void bind() { + this.group = new NioEventLoopGroup(); + ChannelFuture future = new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + @Override + public void initChannel(Channel channel) throws Exception { + InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); + PacketProtocol protocol = server.createPacketProtocol(); - try { - this.group.shutdownGracefully().sync(); - } catch(InterruptedException e) { - e.printStackTrace(); - } - } + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, server); + session.getPacketProtocol().newServerSession(server, session); + channel.config().setOption(ChannelOption.IP_TOS, 0x18); + channel.config().setOption(ChannelOption.TCP_NODELAY, false); + + ChannelPipeline pipeline = channel.pipeline(); + + session.refreshReadTimeoutHandler(channel); + session.refreshWriteTimeoutHandler(channel); + + pipeline.addLast("encryption", new TcpPacketEncryptor(session)); + pipeline.addLast("sizer", new TcpPacketSizer(session)); + pipeline.addLast("codec", new TcpPacketCodec(session)); + pipeline.addLast("manager", session); + + server.addSession(session); + } + }).group(this.group).localAddress(this.host, this.port).bind(); + + try { + this.channel = future.await().channel(); + } catch(InterruptedException e) { + } + } + + @Override + public void close() { + this.close(false); + } + + @Override + public void close(boolean wait) { + if(this.channel != null) { + if(this.channel.isOpen()) { + ChannelFuture future = this.channel.close(); + if(wait) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + } + + this.channel = null; + } + + if(this.group != null) { + Future future = this.group.shutdownGracefully(); + if(wait) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + + this.group = null; + } + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java index 6d40c113..f445e7df 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java @@ -14,37 +14,35 @@ import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { + private Session session; - private Session session; + public TcpPacketCodec(Session session) { + this.session = session; + } - public TcpPacketCodec(Session session) { - this.session = session; - } + @Override + public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { + NetOutput out = new ByteBufNetOutput(buf); + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet.getClass())); + packet.write(out); + } - @Override - public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { - NetOutput out = new ByteBufNetOutput(buf); - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet.getClass())); - packet.write(out); - } + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + int initial = buf.readerIndex(); + NetInput in = new ByteBufNetInput(buf); + int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); + if(id == -1) { + buf.readerIndex(initial); + return; + } - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - int initial = buf.readerIndex(); - NetInput in = new ByteBufNetInput(buf); - int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); - if(id == -1) { - buf.readerIndex(initial); - return; - } - - Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); - packet.read(in); - if(packet.isPriority()) { - this.session.callEvent(new PacketReceivedEvent(this.session, packet)); - } - - out.add(packet); - } + Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); + packet.read(in); + if(packet.isPriority()) { + this.session.callEvent(new PacketReceivedEvent(this.session, packet)); + } + out.add(packet); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java index 02cbe076..6568f9dd 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java @@ -14,63 +14,63 @@ import java.util.zip.Deflater; import java.util.zip.Inflater; public class TcpPacketCompression extends ByteToMessageCodec { - private static final int MAX_COMPRESSED_SIZE = 2097152; + private static final int MAX_COMPRESSED_SIZE = 2097152; - private Session session; - private Deflater deflater = new Deflater(); - private Inflater inflater = new Inflater(); - private byte buf[] = new byte[8192]; + private Session session; + private Deflater deflater = new Deflater(); + private Inflater inflater = new Inflater(); + private byte buf[] = new byte[8192]; - public TcpPacketCompression(Session session) { - this.session = session; - } + public TcpPacketCompression(Session session) { + this.session = session; + } - @Override - public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - int readable = in.readableBytes(); - ByteBufNetOutput output = new ByteBufNetOutput(out); - if(readable < this.session.getCompressionThreshold()) { - output.writeVarInt(0); - out.writeBytes(in); - } else { - byte[] bytes = new byte[readable]; - in.readBytes(bytes); - output.writeVarInt(bytes.length); - this.deflater.setInput(bytes, 0, readable); - this.deflater.finish(); - while(!this.deflater.finished()) { - int length = this.deflater.deflate(this.buf); - output.writeBytes(this.buf, length); - } + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + int readable = in.readableBytes(); + ByteBufNetOutput output = new ByteBufNetOutput(out); + if(readable < this.session.getCompressionThreshold()) { + output.writeVarInt(0); + out.writeBytes(in); + } else { + byte[] bytes = new byte[readable]; + in.readBytes(bytes); + output.writeVarInt(bytes.length); + this.deflater.setInput(bytes, 0, readable); + this.deflater.finish(); + while(!this.deflater.finished()) { + int length = this.deflater.deflate(this.buf); + output.writeBytes(this.buf, length); + } - this.deflater.reset(); - } - } + this.deflater.reset(); + } + } - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - if(buf.readableBytes() != 0) { - ByteBufNetInput in = new ByteBufNetInput(buf); - int size = in.readVarInt(); - if(size == 0) { - out.add(buf.readBytes(buf.readableBytes())); - } else { - if(size < this.session.getCompressionThreshold()) { - throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); - } + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + if(buf.readableBytes() != 0) { + ByteBufNetInput in = new ByteBufNetInput(buf); + int size = in.readVarInt(); + if(size == 0) { + out.add(buf.readBytes(buf.readableBytes())); + } else { + if(size < this.session.getCompressionThreshold()) { + throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); + } - if(size > MAX_COMPRESSED_SIZE) { - throw new DecoderException("Badly compressed packet: size of " + size + " is larger than protocol maximum of " + MAX_COMPRESSED_SIZE + "."); - } + if(size > MAX_COMPRESSED_SIZE) { + throw new DecoderException("Badly compressed packet: size of " + size + " is larger than protocol maximum of " + MAX_COMPRESSED_SIZE + "."); + } - byte[] bytes = new byte[buf.readableBytes()]; - in.readBytes(bytes); - this.inflater.setInput(bytes); - byte[] inflated = new byte[size]; - this.inflater.inflate(inflated); - out.add(Unpooled.wrappedBuffer(inflated)); - this.inflater.reset(); - } - } - } + byte[] bytes = new byte[buf.readableBytes()]; + in.readBytes(bytes); + this.inflater.setInput(bytes); + byte[] inflated = new byte[size]; + this.inflater.inflate(inflated); + out.add(Unpooled.wrappedBuffer(inflated)); + this.inflater.reset(); + } + } + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java index da2a4a99..07daf966 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java @@ -8,52 +8,50 @@ import org.spacehq.packetlib.Session; import java.util.List; public class TcpPacketEncryptor extends ByteToMessageCodec { + private Session session; + private byte[] decryptedArray = new byte[0]; + private byte[] encryptedArray = new byte[0]; - private Session session; - private byte[] decryptedArray = new byte[0]; - private byte[] encryptedArray = new byte[0]; + public TcpPacketEncryptor(Session session) { + this.session = session; + } - public TcpPacketEncryptor(Session session) { - this.session = session; - } + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + if(this.session.getPacketProtocol().getEncryption() != null) { + int length = in.readableBytes(); + byte[] bytes = this.getBytes(in); + int outLength = this.session.getPacketProtocol().getEncryption().getEncryptOutputSize(length); + if(this.encryptedArray.length < outLength) { + this.encryptedArray = new byte[outLength]; + } - @Override - public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - if(this.session.getPacketProtocol().getEncryption() != null) { - int length = in.readableBytes(); - byte[] bytes = this.getBytes(in); - int outLength = this.session.getPacketProtocol().getEncryption().getEncryptOutputSize(length); - if(this.encryptedArray.length < outLength) { - this.encryptedArray = new byte[outLength]; - } + out.writeBytes(this.encryptedArray, 0, this.session.getPacketProtocol().getEncryption().encrypt(bytes, 0, length, this.encryptedArray, 0)); + } else { + out.writeBytes(in); + } + } - out.writeBytes(this.encryptedArray, 0, this.session.getPacketProtocol().getEncryption().encrypt(bytes, 0, length, this.encryptedArray, 0)); - } else { - out.writeBytes(in); - } - } + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + if(this.session.getPacketProtocol().getEncryption() != null) { + int length = buf.readableBytes(); + byte[] bytes = this.getBytes(buf); + ByteBuf result = ctx.alloc().heapBuffer(this.session.getPacketProtocol().getEncryption().getDecryptOutputSize(length)); + result.writerIndex(this.session.getPacketProtocol().getEncryption().decrypt(bytes, 0, length, result.array(), result.arrayOffset())); + out.add(result); + } else { + out.add(buf.readBytes(buf.readableBytes())); + } + } - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - if(this.session.getPacketProtocol().getEncryption() != null) { - int length = buf.readableBytes(); - byte[] bytes = this.getBytes(buf); - ByteBuf result = ctx.alloc().heapBuffer(this.session.getPacketProtocol().getEncryption().getDecryptOutputSize(length)); - result.writerIndex(this.session.getPacketProtocol().getEncryption().decrypt(bytes, 0, length, result.array(), result.arrayOffset())); - out.add(result); - } else { - out.add(buf.readBytes(buf.readableBytes())); - } - } - - private byte[] getBytes(ByteBuf buf) { - int length = buf.readableBytes(); - if(this.decryptedArray.length < length) { - this.decryptedArray = new byte[length]; - } - - buf.readBytes(this.decryptedArray, 0, length); - return this.decryptedArray; - } + private byte[] getBytes(ByteBuf buf) { + int length = buf.readableBytes(); + if(this.decryptedArray.length < length) { + this.decryptedArray = new byte[length]; + } + buf.readBytes(this.decryptedArray, 0, length); + return this.decryptedArray; + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java index fa2bdf75..90eef149 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java @@ -12,50 +12,48 @@ import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { + private Session session; - private Session session; + public TcpPacketSizer(Session session) { + this.session = session; + } - public TcpPacketSizer(Session session) { - this.session = session; - } + @Override + public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { + int length = in.readableBytes(); + out.ensureWritable(this.session.getPacketProtocol().getPacketHeader().getLengthSize(length) + length); + this.session.getPacketProtocol().getPacketHeader().writeLength(new ByteBufNetOutput(out), length); + out.writeBytes(in); + } - @Override - public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - int length = in.readableBytes(); - out.ensureWritable(this.session.getPacketProtocol().getPacketHeader().getLengthSize(length) + length); - this.session.getPacketProtocol().getPacketHeader().writeLength(new ByteBufNetOutput(out), length); - out.writeBytes(in); - } + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + int size = this.session.getPacketProtocol().getPacketHeader().getLengthSize(); + if(size > 0) { + buf.markReaderIndex(); + byte[] lengthBytes = new byte[size]; + for(int index = 0; index < lengthBytes.length; index++) { + if(!buf.isReadable()) { + buf.resetReaderIndex(); + return; + } - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - int size = this.session.getPacketProtocol().getPacketHeader().getLengthSize(); - if(size > 0) { - buf.markReaderIndex(); - byte[] lengthBytes = new byte[size]; - for(int index = 0; index < lengthBytes.length; index++) { - if(!buf.isReadable()) { - buf.resetReaderIndex(); - return; - } + lengthBytes[index] = buf.readByte(); + if((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { + int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); + if(buf.readableBytes() < length) { + buf.resetReaderIndex(); + return; + } - lengthBytes[index] = buf.readByte(); - if((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { - int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); - if(buf.readableBytes() < length) { - buf.resetReaderIndex(); - return; - } - - out.add(buf.readBytes(length)); - return; - } - } - - throw new CorruptedFrameException("Length is too long."); - } else { - out.add(buf.readBytes(buf.readableBytes())); - } - } + out.add(buf.readBytes(length)); + return; + } + } + throw new CorruptedFrameException("Length is too long."); + } else { + out.add(buf.readBytes(buf.readableBytes())); + } + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index ab47dcc9..024115fe 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -1,37 +1,29 @@ package org.spacehq.packetlib.tcp; -import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.EventLoopGroup; import org.spacehq.packetlib.Server; import org.spacehq.packetlib.packet.PacketProtocol; import java.util.Map; public class TcpServerSession extends TcpSession { + private Server server; - private Server server; + public TcpServerSession(String host, int port, PacketProtocol protocol, Server server) { + super(host, port, protocol); + this.server = server; + } - public TcpServerSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, Server server) { - super(host, port, protocol, group, bootstrap, server); - this.server = server; - } - - @Override - public void connect() { - } - - @Override - public Map getFlags() { - Map ret = super.getFlags(); - ret.putAll(this.server.getGlobalFlags()); - return ret; - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - this.server.removeSession(this); - } + @Override + public Map getFlags() { + Map ret = super.getFlags(); + ret.putAll(this.server.getGlobalFlags()); + return ret; + } + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + super.channelInactive(ctx); + this.server.removeSession(this); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index ba44b904..4faabb4c 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -1,417 +1,365 @@ package org.spacehq.packetlib.tcp; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.*; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ConnectTimeoutException; +import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.TimeoutException; +import io.netty.handler.timeout.WriteTimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; -import org.spacehq.packetlib.ConnectTimeoutHandlerContainer; import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.TimeoutHandler; -import org.spacehq.packetlib.TimeoutType; -import org.spacehq.packetlib.event.session.*; +import org.spacehq.packetlib.event.session.ConnectedEvent; +import org.spacehq.packetlib.event.session.DisconnectedEvent; +import org.spacehq.packetlib.event.session.DisconnectingEvent; +import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.event.session.PacketSentEvent; +import org.spacehq.packetlib.event.session.SessionEvent; +import org.spacehq.packetlib.event.session.SessionListener; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; +import java.net.ConnectException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -public class TcpSession extends SimpleChannelInboundHandler implements Session { +public abstract class TcpSession extends SimpleChannelInboundHandler implements Session { + private String host; + private int port; + private PacketProtocol protocol; + private Channel channel; + protected boolean disconnected = false; + private int compressionThreshold = -1; + private int connectTimeout = 30; + private int readTimeout = 30; + private int writeTimeout = 0; + private List packets = new ArrayList(); - private String host; - private int port; - private PacketProtocol protocol; - private Bootstrap bootstrap; - private EventLoopGroup group; - private Channel channel; - private boolean disconnected = false; - private boolean writing = false; - private boolean exception = false; - private int compressionThreshold = -1; - private int readTimeout = 30; - private int writeTimeout = 0; - private TimeoutHandler timeoutHandler = null; - private ConnectTimeoutHandlerContainer container; - private List packets = new ArrayList(); + private Map flags = new HashMap(); + private List listeners = new CopyOnWriteArrayList(); - private Map flags = new HashMap(); - private List listeners = new CopyOnWriteArrayList(); + public TcpSession(String host, int port, PacketProtocol protocol) { + this.host = host; + this.port = port; + this.protocol = protocol; + } - public TcpSession(String host, int port, PacketProtocol protocol, EventLoopGroup group, Bootstrap bootstrap, ConnectTimeoutHandlerContainer container) { - this.host = host; - this.port = port; - this.protocol = protocol; - this.group = group; - this.bootstrap = bootstrap; - this.container = container; - } + @Override + public void connect() { + this.connect(true); + } - @Override - public void connect() { - this.connect(true); - } + @Override + public void connect(boolean wait) { + } - @Override - public void connect(boolean wait) { - if(this.bootstrap == null) { - if(!this.disconnected) { - return; - } else { - throw new IllegalStateException("Session has already been disconnected."); - } - } + @Override + public String getHost() { + return this.host; + } - final AtomicBoolean calledTimeout = new AtomicBoolean(false); - try { - this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.container.getConnectTimeout() * 1000); - ChannelFuture future = this.bootstrap.connect(); - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(!channelFuture.isSuccess() && channelFuture.cause() != null) { - exceptionCaught(null, channelFuture.cause()); - } - } - }); + @Override + public int getPort() { + return this.port; + } - this.bootstrap = null; - if(wait) { - future.awaitUninterruptibly(); - } - } catch(Exception e) { - exceptionCaught(null, e); - } - } + @Override + public PacketProtocol getPacketProtocol() { + return this.protocol; + } - @Override - public String getHost() { - return this.host; - } + @Override + public Map getFlags() { + return new HashMap(this.flags); + } - @Override - public int getPort() { - return this.port; - } + @Override + public boolean hasFlag(String key) { + return this.getFlags().containsKey(key); + } - @Override - public PacketProtocol getPacketProtocol() { - return this.protocol; - } + @SuppressWarnings("unchecked") + @Override + public T getFlag(String key) { + Object value = this.getFlags().get(key); + if(value == null) { + return null; + } - @Override - public Map getFlags() { - return new HashMap(this.flags); - } + try { + return (T) value; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); + } + } - @Override - public boolean hasFlag(String key) { - return this.getFlags().containsKey(key); - } + @Override + public void setFlag(String key, Object value) { + this.flags.put(key, value); + } - @SuppressWarnings("unchecked") - @Override - public T getFlag(String key) { - Object value = this.getFlags().get(key); - if(value == null) { - return null; - } + @Override + public List getListeners() { + return new ArrayList(this.listeners); + } - try { - return (T) value; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); - } - } + @Override + public void addListener(SessionListener listener) { + this.listeners.add(listener); + } - @Override - public void setFlag(String key, Object value) { - this.flags.put(key, value); - } + @Override + public void removeListener(SessionListener listener) { + this.listeners.remove(listener); + } - @Override - public List getListeners() { - return new ArrayList(this.listeners); - } + @Override + public void callEvent(SessionEvent event) { + for(SessionListener listener : this.listeners) { + try { + event.call(listener); + } catch(Throwable t) { + System.err.println("[WARNING] Throwable caught while firing " + event.getClass().getSimpleName() + "."); + t.printStackTrace(); + } + } + } - @Override - public void addListener(SessionListener listener) { - this.listeners.add(listener); - } + @Override + public int getCompressionThreshold() { + return this.compressionThreshold; + } - @Override - public void removeListener(SessionListener listener) { - this.listeners.remove(listener); - } + @Override + public void setCompressionThreshold(int threshold) { + this.compressionThreshold = threshold; + if(this.channel != null) { + if(this.compressionThreshold >= 0) { + if(this.channel.pipeline().get("compression") == null) { + this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this)); + } + } else if(this.channel.pipeline().get("compression") != null) { + this.channel.pipeline().remove("compression"); + } + } + } - @Override - public void callEvent(SessionEvent event) { - for(SessionListener listener : this.listeners) { - try { - event.call(listener); - } catch(Throwable t) { - System.err.println("[WARNING] Throwable caught while firing event."); - t.printStackTrace(); - } - } - } + @Override + public int getConnectTimeout() { + return this.connectTimeout; + } - @Override - public int getCompressionThreshold() { - return this.compressionThreshold; - } + @Override + public void setConnectTimeout(int timeout) { + this.connectTimeout = timeout; + } - @Override - public void setCompressionThreshold(int threshold) { - this.compressionThreshold = threshold; - if(this.channel != null) { - if(this.compressionThreshold >= 0) { - if(this.channel.pipeline().get("compression") == null) { - this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this)); - } - } else if(this.channel.pipeline().get("compression") != null) { - this.channel.pipeline().remove("compression"); - } - } - } + @Override + public int getReadTimeout() { + return this.readTimeout; + } - @Override - public int getReadTimeout() { - return this.readTimeout; - } + @Override + public void setReadTimeout(int timeout) { + this.readTimeout = timeout; + this.refreshReadTimeoutHandler(); + } - @Override - public void setReadTimeout(int timeout) { - this.readTimeout = timeout; - this.refreshReadTimeoutHandler(); - } + @Override + public int getWriteTimeout() { + return this.writeTimeout; + } - @Override - public int getWriteTimeout() { - return this.writeTimeout; - } + @Override + public void setWriteTimeout(int timeout) { + this.writeTimeout = timeout; + this.refreshWriteTimeoutHandler(); + } - @Override - public void setWriteTimeout(int timeout) { - this.writeTimeout = timeout; - this.refreshWriteTimeoutHandler(); - } + @Override + public boolean isConnected() { + return this.channel != null && this.channel.isOpen() && !this.disconnected; + } - @Override - public TimeoutHandler getTimeoutHandler() { - return this.timeoutHandler; - } + @Override + public void send(final Packet packet) { + if(this.channel == null) { + return; + } - @Override - public void setTimeoutHandler(TimeoutHandler timeoutHandler) { - this.timeoutHandler = timeoutHandler; - } + ChannelFuture future = this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if(!future.isSuccess()) { + exceptionCaught(null, future.cause()); + } else { + callEvent(new PacketSentEvent(TcpSession.this, packet)); + } + } + }); - @Override - public boolean isConnected() { - return this.channel != null && this.channel.isOpen() && !this.disconnected; - } + if(packet.isPriority()) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + } - @Override - public void send(final Packet packet) { - this.writing = true; - if(this.channel == null) { - this.writing = false; - return; - } + @Override + public void disconnect(String reason) { + this.disconnect(reason, false); + } - this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - writing = false; - if(!future.isSuccess()) { - exceptionCaught(null, future.cause()); - } else { - callEvent(new PacketSentEvent(TcpSession.this, packet)); - } - } - }); + @Override + public void disconnect(String reason, boolean wait) { + this.disconnect(reason, null, wait); + } - if(packet.isPriority()) { - while(this.writing && !this.exception) { - try { - Thread.sleep(2); - } catch(InterruptedException e) { - } - } - } - } + @Override + public void disconnect(final String reason, final Throwable cause) { + this.disconnect(reason, cause, false); + } - @Override - public void disconnect(String reason) { - if(this.disconnected) { - return; - } + @Override + public void disconnect(final String reason, final Throwable cause, boolean wait) { + if(this.disconnected) { + return; + } - this.disconnected = true; - if(this.writing) { - while(this.writing && !this.exception) { - try { - Thread.sleep(2); - } catch(InterruptedException e) { - } - } + this.disconnected = true; + if(this.channel != null) { + if(this.channel.isOpen()) { + this.callEvent(new DisconnectingEvent(this, reason, cause)); + ChannelFuture future = this.channel.flush().close().addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); + } + }); - try { - Thread.sleep(250); - } catch(InterruptedException e) { - } - } + if(wait) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + } else { + this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); + } - if(reason == null) { - reason = "Connection closed."; - } + this.channel = null; + } + } - if(this.channel != null) { - if(this.channel.isOpen()) { - this.callEvent(new DisconnectingEvent(this, reason)); - } + protected void refreshReadTimeoutHandler() { + this.refreshReadTimeoutHandler(this.channel); + } - try { - this.channel.close().syncUninterruptibly(); - } catch(Throwable t) { - } - } + protected void refreshReadTimeoutHandler(Channel channel) { + if(channel != null) { + if(this.readTimeout <= 0) { + if(channel.pipeline().get("readTimeout") != null) { + channel.pipeline().remove("readTimeout"); + } + } else { + if(channel.pipeline().get("readTimeout") == null) { + channel.pipeline().addFirst("readTimeout", new ReadTimeoutHandler(this.readTimeout)); + } else { + channel.pipeline().replace("readTimeout", "readTimeout", new ReadTimeoutHandler(this.readTimeout)); + } + } + } + } - this.callEvent(new DisconnectedEvent(this, reason)); - if(this.group != null) { - try { - this.group.shutdownGracefully(); - } catch(Throwable t) { - } - } + protected void refreshWriteTimeoutHandler() { + this.refreshWriteTimeoutHandler(this.channel); + } - this.channel = null; - } + protected void refreshWriteTimeoutHandler(Channel channel) { + if(channel != null) { + if(this.writeTimeout <= 0) { + if(channel.pipeline().get("writeTimeout") != null) { + channel.pipeline().remove("writeTimeout"); + } + } else { + if(channel.pipeline().get("writeTimeout") == null) { + channel.pipeline().addFirst("writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); + } else { + channel.pipeline().replace("writeTimeout", "writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); + } + } + } + } - protected void refreshReadTimeoutHandler() { - this.refreshReadTimeoutHandler(this.channel); - } + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + if(this.disconnected) { + ctx.channel().close(); + return; + } - protected void refreshReadTimeoutHandler(Channel channel) { - if(channel != null) { - if(this.readTimeout <= 0) { - if(channel.pipeline().get("readTimeout") != null) { - channel.pipeline().remove("readTimeout"); - } - } else { - if(channel.pipeline().get("readTimeout") == null) { - channel.pipeline().addFirst("readTimeout", new ReadTimeoutHandler(this.readTimeout)); - } else { - channel.pipeline().replace("readTimeout", "readTimeout", new ReadTimeoutHandler(this.readTimeout)); - } - } - } - } + this.channel = ctx.channel(); + this.disconnected = false; + this.callEvent(new ConnectedEvent(this)); + new PacketHandleThread().start(); + } - protected void refreshWriteTimeoutHandler() { - this.refreshWriteTimeoutHandler(this.channel); - } + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + this.disconnect("Connection closed."); + } - protected void refreshWriteTimeoutHandler(Channel channel) { - if(channel != null) { - if(this.writeTimeout <= 0) { - if(channel.pipeline().get("writeTimeout") != null) { - channel.pipeline().remove("writeTimeout"); - } - } else { - if(channel.pipeline().get("writeTimeout") == null) { - channel.pipeline().addFirst("writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); - } else { - channel.pipeline().replace("writeTimeout", "writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); - } - } - } - } + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + String message = null; + if(cause instanceof ConnectTimeoutException || (cause instanceof ConnectException && cause.getMessage().contains("connection timed out"))) { + message = "Connection timed out."; + } else if(cause instanceof ReadTimeoutException) { + message = "Read timed out."; + } else if(cause instanceof WriteTimeoutException) { + message = "Write timed out."; + } else { + message = "Internal network exception."; + } - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - if(this.disconnected) { - ctx.channel().close().syncUninterruptibly(); - return; - } + this.disconnect(message, cause); + } - this.channel = ctx.channel(); - this.disconnected = false; - this.callEvent(new ConnectedEvent(this)); - new PacketHandleThread().start(); - } + @Override + protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { + if(!packet.isPriority()) { + this.packets.add(packet); + } + } - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - this.disconnect("Connection closed."); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - this.writing = false; - this.exception = true; - if(cause instanceof TimeoutException) { - if(this.timeoutHandler != null) { - this.timeoutHandler.onTimeout(this, cause instanceof ReadTimeoutException ? TimeoutType.READ : TimeoutType.WRITE); - } - - if(!this.disconnected) { - this.disconnect((cause instanceof ReadTimeoutException ? "Read" : "Write") + " timed out."); - } - } else if(cause instanceof ConnectTimeoutException) { - if(this.container.getConnectTimeoutHandler() != null) { - this.container.getConnectTimeoutHandler().onTimeout(this, TimeoutType.CONNECT); - } - - if(!this.disconnected) { - this.disconnect("Connection timed out."); - } - } else { - if(!this.disconnected) { - this.disconnect("Internal network exception: " + cause.toString()); - } - - cause.printStackTrace(); - } - - this.disconnected = true; - } - - @Override - protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { - if(!packet.isPriority()) { - this.packets.add(packet); - } - } - - private class PacketHandleThread extends Thread { - @Override - public void run() { - try { - while(!disconnected && !exception) { - while(packets.size() > 0) { - callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); - } - - try { - Thread.sleep(5); - } catch(InterruptedException e) { - } - } - } catch(Throwable t) { - try { - exceptionCaught(null, t); - } catch(Exception e) { - System.err.println("Exception while handling exception!"); - e.printStackTrace(); - } - } - } - } + private class PacketHandleThread extends Thread { + @Override + public void run() { + try { + while(!disconnected) { + while(packets.size() > 0) { + callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); + } + try { + Thread.sleep(5); + } catch(InterruptedException e) { + } + } + } catch(Throwable t) { + try { + exceptionCaught(null, t); + } catch(Exception e) { + System.err.println("Exception while handling exception!"); + e.printStackTrace(); + } + } + } + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java index 03700a0d..f8781d1d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java @@ -1,95 +1,33 @@ package org.spacehq.packetlib.tcp; -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.*; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.oio.OioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import org.spacehq.packetlib.*; -import org.spacehq.packetlib.packet.PacketProtocol; +import org.spacehq.packetlib.Client; +import org.spacehq.packetlib.ConnectionListener; +import org.spacehq.packetlib.Server; +import org.spacehq.packetlib.Session; +import org.spacehq.packetlib.SessionFactory; -import java.net.InetSocketAddress; import java.net.Proxy; +/** + * A session factory used to create TCP sessions. + */ public class TcpSessionFactory implements SessionFactory { + private Proxy clientProxy; - private Proxy clientProxy; + public TcpSessionFactory() { + } - public TcpSessionFactory() { - } + public TcpSessionFactory(Proxy clientProxy) { + this.clientProxy = clientProxy; + } - public TcpSessionFactory(Proxy clientProxy) { - this.clientProxy = clientProxy; - } - - @Override - public Session createClientSession(final Client client) { - Bootstrap bootstrap = new Bootstrap(); - EventLoopGroup group = null; - if(this.clientProxy != null) { - group = new OioEventLoopGroup(); - bootstrap.channelFactory(new ProxyOioChannelFactory(this.clientProxy)); - } else { - group = new NioEventLoopGroup(); - bootstrap.channel(NioSocketChannel.class); - } - - bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, client.getConnectTimeout() * 1000); - final TcpSession session = new TcpSession(client.getHost(), client.getPort(), client.getPacketProtocol(), group, bootstrap, client); - bootstrap.handler(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - session.getPacketProtocol().newClientSession(client, session); - ch.config().setOption(ChannelOption.IP_TOS, 0x18); - ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ChannelPipeline pipeline = ch.pipeline(); - session.refreshReadTimeoutHandler(ch); - session.refreshWriteTimeoutHandler(ch); - if(session.getPacketProtocol().needsPacketEncryptor()) { - pipeline.addLast("encryption", new TcpPacketEncryptor(session)); - } - - if(session.getPacketProtocol().needsPacketSizer()) { - pipeline.addLast("sizer", new TcpPacketSizer(session)); - } - - pipeline.addLast("codec", new TcpPacketCodec(session)); - pipeline.addLast("manager", session); - } - }).group(group).remoteAddress(client.getHost(), client.getPort()); - return session; - } - - @Override - public ConnectionListener createServerListener(final Server server) { - final EventLoopGroup group = new NioEventLoopGroup(); - return new TcpConnectionListener(server.getHost(), server.getPort(), group, new ServerBootstrap().option(ChannelOption.CONNECT_TIMEOUT_MILLIS, server.getConnectTimeout() * 1000).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { - @Override - public void initChannel(Channel ch) throws Exception { - InetSocketAddress address = (InetSocketAddress) ch.remoteAddress(); - PacketProtocol protocol = server.createPacketProtocol(); - TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, null, null, server); - session.getPacketProtocol().newServerSession(server, session); - ch.config().setOption(ChannelOption.IP_TOS, 0x18); - ch.config().setOption(ChannelOption.TCP_NODELAY, false); - ChannelPipeline pipeline = ch.pipeline(); - session.refreshReadTimeoutHandler(ch); - session.refreshWriteTimeoutHandler(ch); - if(session.getPacketProtocol().needsPacketEncryptor()) { - pipeline.addLast("encryption", new TcpPacketEncryptor(session)); - } - - if(session.getPacketProtocol().needsPacketSizer()) { - pipeline.addLast("sizer", new TcpPacketSizer(session)); - } - - pipeline.addLast("codec", new TcpPacketCodec(session)); - pipeline.addLast("manager", session); - server.addSession(session); - } - }).group(group).localAddress(server.getHost(), server.getPort()).bind().syncUninterruptibly().channel()); - } + @Override + public Session createClientSession(final Client client) { + return new TcpClientSession(client.getHost(), client.getPort(), client.getPacketProtocol(), client, this.clientProxy); + } + @Override + public ConnectionListener createServerListener(final Server server) { + return new TcpConnectionListener(server.getHost(), server.getPort(), server); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index f7b72b80..2fb2a605 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -10,145 +10,143 @@ import java.util.UUID; * A NetInput implementation using a ByteBuf as a backend. */ public class ByteBufNetInput implements NetInput { + private ByteBuf buf; - private ByteBuf buf; + public ByteBufNetInput(ByteBuf buf) { + this.buf = buf; + } - public ByteBufNetInput(ByteBuf buf) { - this.buf = buf; - } + @Override + public boolean readBoolean() throws IOException { + return this.buf.readBoolean(); + } - @Override - public boolean readBoolean() throws IOException { - return this.buf.readBoolean(); - } + @Override + public byte readByte() throws IOException { + return this.buf.readByte(); + } - @Override - public byte readByte() throws IOException { - return this.buf.readByte(); - } + @Override + public int readUnsignedByte() throws IOException { + return this.buf.readUnsignedByte(); + } - @Override - public int readUnsignedByte() throws IOException { - return this.buf.readUnsignedByte(); - } + @Override + public short readShort() throws IOException { + return this.buf.readShort(); + } - @Override - public short readShort() throws IOException { - return this.buf.readShort(); - } + @Override + public int readUnsignedShort() throws IOException { + return this.buf.readUnsignedShort(); + } - @Override - public int readUnsignedShort() throws IOException { - return this.buf.readUnsignedShort(); - } + @Override + public char readChar() throws IOException { + return this.buf.readChar(); + } - @Override - public char readChar() throws IOException { - return this.buf.readChar(); - } + @Override + public int readInt() throws IOException { + return this.buf.readInt(); + } - @Override - public int readInt() throws IOException { - return this.buf.readInt(); - } + @Override + public int readVarInt() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 5) { + throw new IOException("VarInt too long (length must be <= 5)"); + } + } - @Override - public int readVarInt() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 5) { - throw new IOException("VarInt too long (length must be <= 5)"); - } - } + return value | ((b & 0x7F) << (size * 7)); + } - return value | ((b & 0x7F) << (size * 7)); - } + @Override + public long readLong() throws IOException { + return this.buf.readLong(); + } - @Override - public long readLong() throws IOException { - return this.buf.readLong(); - } + @Override + public long readVarLong() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 10) { + throw new IOException("VarLong too long (length must be <= 10)"); + } + } - @Override - public long readVarLong() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 10) { - throw new IOException("VarLong too long (length must be <= 10)"); - } - } + return value | ((b & 0x7F) << (size * 7)); + } - return value | ((b & 0x7F) << (size * 7)); - } + @Override + public float readFloat() throws IOException { + return this.buf.readFloat(); + } - @Override - public float readFloat() throws IOException { - return this.buf.readFloat(); - } + @Override + public double readDouble() throws IOException { + return this.buf.readDouble(); + } - @Override - public double readDouble() throws IOException { - return this.buf.readDouble(); - } + @Override + public byte[] readPrefixedBytes() throws IOException { + short length = this.buf.readShort(); + return this.readBytes(length); + } - @Override - public byte[] readPrefixedBytes() throws IOException { - short length = this.buf.readShort(); - return this.readBytes(length); - } + @Override + public byte[] readBytes(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } - @Override - public byte[] readBytes(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } + byte b[] = new byte[length]; + this.buf.readBytes(b); + return b; + } - byte b[] = new byte[length]; - this.buf.readBytes(b); - return b; - } + @Override + public int readBytes(byte[] b) throws IOException { + return this.readBytes(b, 0, b.length); + } - @Override - public int readBytes(byte[] b) throws IOException { - return this.readBytes(b, 0, b.length); - } + @Override + public int readBytes(byte[] b, int offset, int length) throws IOException { + int readable = this.buf.readableBytes(); + if(readable <= 0) { + return -1; + } - @Override - public int readBytes(byte[] b, int offset, int length) throws IOException { - int readable = this.buf.readableBytes(); - if(readable <= 0) { - return -1; - } + if(readable < length) { + length = readable; + } - if(readable < length) { - length = readable; - } + this.buf.readBytes(b, offset, length); + return length; + } - this.buf.readBytes(b, offset, length); - return length; - } + @Override + public String readString() throws IOException { + int length = this.readVarInt(); + byte bytes[] = this.readBytes(length); + return new String(bytes, "UTF-8"); + } - @Override - public String readString() throws IOException { - int length = this.readVarInt(); - byte bytes[] = this.readBytes(length); - return new String(bytes, "UTF-8"); - } - - @Override - public UUID readUUID() throws IOException { - return new UUID(this.readLong(), this.readLong()); - } - - @Override - public int available() throws IOException { - return this.buf.readableBytes(); - } + @Override + public UUID readUUID() throws IOException { + return new UUID(this.readLong(), this.readLong()); + } + @Override + public int available() throws IOException { + return this.buf.readableBytes(); + } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 298ae63e..4983c0e1 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -10,112 +10,110 @@ import java.util.UUID; * A NetOutput implementation using a ByteBuf as a backend. */ public class ByteBufNetOutput implements NetOutput { + private ByteBuf buf; - private ByteBuf buf; + public ByteBufNetOutput(ByteBuf buf) { + this.buf = buf; + } - public ByteBufNetOutput(ByteBuf buf) { - this.buf = buf; - } + @Override + public void writeBoolean(boolean b) throws IOException { + this.buf.writeBoolean(b); + } - @Override - public void writeBoolean(boolean b) throws IOException { - this.buf.writeBoolean(b); - } + @Override + public void writeByte(int b) throws IOException { + this.buf.writeByte(b); + } - @Override - public void writeByte(int b) throws IOException { - this.buf.writeByte(b); - } + @Override + public void writeShort(int s) throws IOException { + this.buf.writeShort(s); + } - @Override - public void writeShort(int s) throws IOException { - this.buf.writeShort(s); - } + @Override + public void writeChar(int c) throws IOException { + this.buf.writeChar(c); + } - @Override - public void writeChar(int c) throws IOException { - this.buf.writeChar(c); - } + @Override + public void writeInt(int i) throws IOException { + this.buf.writeInt(i); + } - @Override - public void writeInt(int i) throws IOException { - this.buf.writeInt(i); - } + @Override + public void writeVarInt(int i) throws IOException { + while((i & ~0x7F) != 0) { + this.writeByte((i & 0x7F) | 0x80); + i >>>= 7; + } - @Override - public void writeVarInt(int i) throws IOException { - while((i & ~0x7F) != 0) { - this.writeByte((i & 0x7F) | 0x80); - i >>>= 7; - } + this.writeByte(i); + } - this.writeByte(i); - } + @Override + public void writeLong(long l) throws IOException { + this.buf.writeLong(l); + } - @Override - public void writeLong(long l) throws IOException { - this.buf.writeLong(l); - } + @Override + public void writeVarLong(long l) throws IOException { + while((l & ~0x7F) != 0) { + this.writeByte((int) (l & 0x7F) | 0x80); + l >>>= 7; + } - @Override - public void writeVarLong(long l) throws IOException { - while((l & ~0x7F) != 0) { - this.writeByte((int) (l & 0x7F) | 0x80); - l >>>= 7; - } + this.writeByte((int) l); + } - this.writeByte((int) l); - } + @Override + public void writeFloat(float f) throws IOException { + this.buf.writeFloat(f); + } - @Override - public void writeFloat(float f) throws IOException { - this.buf.writeFloat(f); - } + @Override + public void writeDouble(double d) throws IOException { + this.buf.writeDouble(d); + } - @Override - public void writeDouble(double d) throws IOException { - this.buf.writeDouble(d); - } + @Override + public void writePrefixedBytes(byte b[]) throws IOException { + this.buf.writeShort(b.length); + this.buf.writeBytes(b); + } - @Override - public void writePrefixedBytes(byte b[]) throws IOException { - this.buf.writeShort(b.length); - this.buf.writeBytes(b); - } + @Override + public void writeBytes(byte b[]) throws IOException { + this.buf.writeBytes(b); + } - @Override - public void writeBytes(byte b[]) throws IOException { - this.buf.writeBytes(b); - } + @Override + public void writeBytes(byte b[], int length) throws IOException { + this.buf.writeBytes(b, 0, length); + } - @Override - public void writeBytes(byte b[], int length) throws IOException { - this.buf.writeBytes(b, 0, length); - } + @Override + public void writeString(String s) throws IOException { + if(s == null) { + throw new IllegalArgumentException("String cannot be null!"); + } - @Override - public void writeString(String s) throws IOException { - if(s == null) { - throw new IllegalArgumentException("String cannot be null!"); - } + byte[] bytes = s.getBytes("UTF-8"); + if(bytes.length > 32767) { + throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); + } else { + this.writeVarInt(bytes.length); + this.writeBytes(bytes); + } + } - byte[] bytes = s.getBytes("UTF-8"); - if(bytes.length > 32767) { - throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); - } else { - this.writeVarInt(bytes.length); - this.writeBytes(bytes); - } - } - - @Override - public void writeUUID(UUID uuid) throws IOException { - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - } - - @Override - public void flush() throws IOException { - } + @Override + public void writeUUID(UUID uuid) throws IOException { + this.writeLong(uuid.getMostSignificantBits()); + this.writeLong(uuid.getLeastSignificantBits()); + } + @Override + public void flush() throws IOException { + } } From a2e4898749c9f415d38a87691621dbd507eb1fc0 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 21 Jul 2015 15:58:27 -0700 Subject: [PATCH 037/180] Update URLs. --- README.md | 3 ++- pom.xml | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3714f38d..153dbfff 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ See examples/org/spacehq/packetlib/test ## Building the Source PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -Builds can be downloaded **[here](http://build.spacehq.org/job/PacketLib)**. +Builds can be downloaded **[here](https://build.spacehq.org/job/PacketLib)**. +Javadocs can be found **[here](https://build.spacehq.org/job/PacketLib/javadoc)**. ## License PacketLib is licensed under the **[MIT license](http://www.opensource.org/licenses/mit-license.html)**. diff --git a/pom.xml b/pom.xml index 1a6a1475..87a2471f 100644 --- a/pom.xml +++ b/pom.xml @@ -41,23 +41,23 @@ spacehq spacehq-releases - http://repo.spacehq.org/content/repositories/releases/ + https://repo.spacehq.org/content/repositories/releases/ spacehq spacehq-snapshots - http://repo.spacehq.org/content/repositories/snapshots/ + https://repo.spacehq.org/content/repositories/snapshots/ spacehq-releases - http://repo.spacehq.org/content/repositories/releases/ + https://repo.spacehq.org/content/repositories/releases/ spacehq-snapshots - http://repo.spacehq.org/content/repositories/snapshots/ + https://repo.spacehq.org/content/repositories/snapshots/ From c68659008b6b359519f50d9d00a433246e6ab4ff Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Thu, 13 Aug 2015 19:31:00 -0700 Subject: [PATCH 038/180] Report exceptions from connection thread. --- src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index 8dd72527..3971d8e4 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -104,6 +104,7 @@ public class TcpClientSession extends TcpSession { }); } catch(Throwable t) { complete.set(true); + exceptionCaught(null, t); } } }).start(); From 4c06294c883e78581a686f3aafd287aa912ce9ae Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Thu, 20 Aug 2015 16:59:59 -0700 Subject: [PATCH 039/180] Ensure connection process has fully completed before ending wait loop. --- .../java/org/spacehq/packetlib/tcp/TcpClientSession.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index 3971d8e4..b31088c5 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -96,15 +96,17 @@ public class TcpClientSession extends TcpSession { future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { - complete.set(true); if(!future.isSuccess() && future.cause() != null) { exceptionCaught(null, future.cause()); } } - }); - } catch(Throwable t) { + }).await(); + complete.set(true); + } catch(Throwable t) { exceptionCaught(null, t); + + complete.set(true); } } }).start(); From ce140f43d619bfeafd8ae452b6e1fa3061d3671f Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 19:15:36 -0700 Subject: [PATCH 040/180] Cleanup, add wait flag to Server.bind, fix connection errors not throwing DisconnectedEvent. --- .../packetlib/test/ClientSessionListener.java | 19 ++- .../packetlib/test/PingServerTest.java | 3 +- .../packetlib/test/ServerListener.java | 10 +- .../packetlib/test/ServerSessionListener.java | 16 ++- .../spacehq/packetlib/ConnectionListener.java | 15 +++ .../java/org/spacehq/packetlib/Server.java | 20 ++- .../packetlib/tcp/TcpClientSession.java | 25 ++-- .../packetlib/tcp/TcpConnectionListener.java | 36 +++++- .../packetlib/tcp/TcpServerSession.java | 1 + .../org/spacehq/packetlib/tcp/TcpSession.java | 116 +++++++++--------- 10 files changed, 172 insertions(+), 89 deletions(-) diff --git a/example/org/spacehq/packetlib/test/ClientSessionListener.java b/example/org/spacehq/packetlib/test/ClientSessionListener.java index b4535257..28ef14ba 100644 --- a/example/org/spacehq/packetlib/test/ClientSessionListener.java +++ b/example/org/spacehq/packetlib/test/ClientSessionListener.java @@ -4,6 +4,7 @@ import org.spacehq.packetlib.event.session.ConnectedEvent; import org.spacehq.packetlib.event.session.DisconnectedEvent; import org.spacehq.packetlib.event.session.DisconnectingEvent; import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.event.session.PacketSentEvent; import org.spacehq.packetlib.event.session.SessionAdapter; public class ClientSessionListener extends SessionAdapter { @@ -11,17 +12,29 @@ public class ClientSessionListener extends SessionAdapter { public void packetReceived(PacketReceivedEvent event) { if(event.getPacket() instanceof PingPacket) { PingPacket packet = event.getPacket(); - System.out.println("CLIENT RECV: " + packet.getPingId()); - if(packet.getPingId().equals("exit")) { + + System.out.println("CLIENT Received: " + packet.getPingId()); + + if(packet.getPingId().equals("hello")) { + event.getSession().send(new PingPacket("exit")); + } else if(packet.getPingId().equals("exit")) { event.getSession().disconnect("Finished"); } } } + @Override + public void packetSent(PacketSentEvent event) { + if(event.getPacket() instanceof PingPacket) { + System.out.println("CLIENT Sent: " + event.getPacket().getPingId()); + } + } + @Override public void connected(ConnectedEvent event) { + System.out.println("CLIENT Connected"); + event.getSession().send(new PingPacket("hello")); - event.getSession().send(new PingPacket("exit")); } @Override diff --git a/example/org/spacehq/packetlib/test/PingServerTest.java b/example/org/spacehq/packetlib/test/PingServerTest.java index 37f92905..80fd2878 100644 --- a/example/org/spacehq/packetlib/test/PingServerTest.java +++ b/example/org/spacehq/packetlib/test/PingServerTest.java @@ -20,8 +20,9 @@ public class PingServerTest { return; } - Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()).bind(); + Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()); server.addListener(new ServerListener(key)); + server.bind(); Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); client.getSession().connect(); diff --git a/example/org/spacehq/packetlib/test/ServerListener.java b/example/org/spacehq/packetlib/test/ServerListener.java index 3d6c648d..84814c69 100644 --- a/example/org/spacehq/packetlib/test/ServerListener.java +++ b/example/org/spacehq/packetlib/test/ServerListener.java @@ -1,6 +1,7 @@ package org.spacehq.packetlib.test; import org.spacehq.packetlib.event.server.ServerAdapter; +import org.spacehq.packetlib.event.server.ServerBoundEvent; import org.spacehq.packetlib.event.server.ServerClosedEvent; import org.spacehq.packetlib.event.server.ServerClosingEvent; import org.spacehq.packetlib.event.server.SessionAddedEvent; @@ -15,6 +16,11 @@ public class ServerListener extends ServerAdapter { this.key = key; } + @Override + public void serverBound(ServerBoundEvent event) { + System.out.println("SERVER Bound: " + event.getServer().getHost() + ":" + event.getServer().getPort()); + } + @Override public void serverClosing(ServerClosingEvent event) { System.out.println("CLOSING SERVER..."); @@ -27,13 +33,13 @@ public class ServerListener extends ServerAdapter { @Override public void sessionAdded(SessionAddedEvent event) { - System.out.println("SESSION ADDED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + System.out.println("SERVER Session Added: " + event.getSession().getHost() + ":" + event.getSession().getPort()); ((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key); } @Override public void sessionRemoved(SessionRemovedEvent event) { - System.out.println("SESSION REMOVED: " + event.getSession().getHost() + ":" + event.getSession().getPort()); + System.out.println("SERVER Session Removed: " + event.getSession().getHost() + ":" + event.getSession().getPort()); event.getServer().close(); } } diff --git a/example/org/spacehq/packetlib/test/ServerSessionListener.java b/example/org/spacehq/packetlib/test/ServerSessionListener.java index 83742bd7..65b0f9c3 100644 --- a/example/org/spacehq/packetlib/test/ServerSessionListener.java +++ b/example/org/spacehq/packetlib/test/ServerSessionListener.java @@ -1,19 +1,33 @@ package org.spacehq.packetlib.test; +import org.spacehq.packetlib.event.session.ConnectedEvent; import org.spacehq.packetlib.event.session.DisconnectedEvent; import org.spacehq.packetlib.event.session.DisconnectingEvent; import org.spacehq.packetlib.event.session.PacketReceivedEvent; +import org.spacehq.packetlib.event.session.PacketSentEvent; import org.spacehq.packetlib.event.session.SessionAdapter; public class ServerSessionListener extends SessionAdapter { @Override public void packetReceived(PacketReceivedEvent event) { if(event.getPacket() instanceof PingPacket) { - System.out.println("SERVER RECV: " + event.getPacket().getPingId()); + System.out.println("SERVER Received: " + event.getPacket().getPingId()); event.getSession().send(event.getPacket()); } } + @Override + public void packetSent(PacketSentEvent event) { + if(event.getPacket() instanceof PingPacket) { + System.out.println("SERVER Sent: " + event.getPacket().getPingId()); + } + } + + @Override + public void connected(ConnectedEvent event) { + System.out.println("SERVER Connected"); + } + @Override public void disconnecting(DisconnectingEvent event) { System.out.println("SERVER Disconnecting: " + event.getReason()); diff --git a/src/main/java/org/spacehq/packetlib/ConnectionListener.java b/src/main/java/org/spacehq/packetlib/ConnectionListener.java index 3052aad0..8de8fb60 100644 --- a/src/main/java/org/spacehq/packetlib/ConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/ConnectionListener.java @@ -30,6 +30,21 @@ public interface ConnectionListener { */ public void bind(); + /** + * Binds the listener to its host and port. + * + * @param wait Whether to wait for the listener to finish binding. + */ + public void bind(boolean wait); + + /** + * Binds the listener to its host and port. + * + * @param wait Whether to wait for the listener to finish binding. + * @param callback Callback to call when the listener has finished binding. + */ + public void bind(boolean wait, Runnable callback); + /** * Closes the listener. */ diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index 13f2df0f..cad2d2d9 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -42,10 +42,24 @@ public class Server { * @return The server after being bound. */ public Server bind() { - this.listener = this.factory.createServerListener(this); - this.listener.bind(); + return this.bind(true); + } + + /** + * Binds and initializes the server. + * + * @param wait Whether to wait for the server to finish binding. + * @return The server after being bound. + */ + public Server bind(boolean wait) { + this.listener = this.factory.createServerListener(this); + this.listener.bind(wait, new Runnable() { + @Override + public void run() { + callEvent(new ServerBoundEvent(Server.this)); + } + }); - this.callEvent(new ServerBoundEvent(this)); return this; } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index b31088c5..6737b7df 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -18,13 +18,11 @@ import org.spacehq.packetlib.packet.PacketProtocol; import javax.naming.directory.InitialDirContext; import java.net.Proxy; import java.util.Hashtable; -import java.util.concurrent.atomic.AtomicBoolean; public class TcpClientSession extends TcpSession { private Client client; private Proxy proxy; - private boolean connected; private EventLoopGroup group; public TcpClientSession(String host, int port, PacketProtocol protocol, Client client, Proxy proxy) { @@ -37,11 +35,10 @@ public class TcpClientSession extends TcpSession { public void connect(boolean wait) { if(this.disconnected) { throw new IllegalStateException("Session has already been disconnected."); - } else if(this.connected) { + } else if(this.group != null) { return; } - this.connected = true; try { final Bootstrap bootstrap = new Bootstrap(); if(this.proxy != null) { @@ -72,8 +69,7 @@ public class TcpClientSession extends TcpSession { } }).group(this.group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); - final AtomicBoolean complete = new AtomicBoolean(false); - new Thread(new Runnable() { + Runnable connectTask = new Runnable() { @Override public void run() { try { @@ -92,6 +88,7 @@ public class TcpClientSession extends TcpSession { } bootstrap.remoteAddress(host, port); + ChannelFuture future = bootstrap.connect(); future.addListener(new ChannelFutureListener() { @Override @@ -101,24 +98,16 @@ public class TcpClientSession extends TcpSession { } } }).await(); - - complete.set(true); } catch(Throwable t) { exceptionCaught(null, t); - - complete.set(true); } } - }).start(); + }; if(wait) { - while(!complete.get()) { - try { - Thread.sleep(5); - } catch(InterruptedException e) { - break; - } - } + connectTask.run(); + } else { + new Thread(connectTask).start(); } } catch(Throwable t) { exceptionCaught(null, t); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index 34ec1f5c..f8c1bb41 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -3,6 +3,7 @@ package org.spacehq.packetlib.tcp; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; @@ -47,6 +48,20 @@ public class TcpConnectionListener implements ConnectionListener { @Override public void bind() { + this.bind(true); + } + + @Override + public void bind(boolean wait) { + this.bind(wait, null); + } + + @Override + public void bind(final boolean wait, final Runnable callback) { + if(this.group != null || this.channel != null) { + return; + } + this.group = new NioEventLoopGroup(); ChannelFuture future = new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { @Override @@ -72,11 +87,24 @@ public class TcpConnectionListener implements ConnectionListener { server.addSession(session); } - }).group(this.group).localAddress(this.host, this.port).bind(); + }).group(this.group).localAddress(this.host, this.port).bind().addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.isSuccess()) { + channel = channelFuture.channel(); + callback.run(); + } else if(channelFuture.cause() != null && !wait) { + System.err.println("[ERROR] Failed to asynchronously bind connection listener."); + channelFuture.cause().printStackTrace(); + } + } + }); - try { - this.channel = future.await().channel(); - } catch(InterruptedException e) { + if(wait) { + try { + future.sync(); + } catch(InterruptedException e) { + } } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index 024115fe..8662dfc8 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -24,6 +24,7 @@ public class TcpServerSession extends TcpSession { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); + this.server.removeSession(this); } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 4faabb4c..c3a15521 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -26,23 +26,29 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingQueue; public abstract class TcpSession extends SimpleChannelInboundHandler implements Session { private String host; private int port; private PacketProtocol protocol; - private Channel channel; - protected boolean disconnected = false; + private int compressionThreshold = -1; private int connectTimeout = 30; private int readTimeout = 30; private int writeTimeout = 0; - private List packets = new ArrayList(); private Map flags = new HashMap(); private List listeners = new CopyOnWriteArrayList(); + private Channel channel; + protected boolean disconnected = false; + + private BlockingQueue packets = new LinkedBlockingQueue(); + private Thread packetHandleThread; + public TcpSession(String host, int port, PacketProtocol protocol) { this.host = host; this.port = port; @@ -120,13 +126,12 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void callEvent(SessionEvent event) { - for(SessionListener listener : this.listeners) { - try { + try { + for(SessionListener listener : this.listeners) { event.call(listener); - } catch(Throwable t) { - System.err.println("[WARNING] Throwable caught while firing " + event.getClass().getSimpleName() + "."); - t.printStackTrace(); } + } catch(Throwable t) { + exceptionCaught(null, t); } } @@ -233,28 +238,32 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } this.disconnected = true; - if(this.channel != null) { - if(this.channel.isOpen()) { - this.callEvent(new DisconnectingEvent(this, reason, cause)); - ChannelFuture future = this.channel.flush().close().addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); - } - }); - if(wait) { - try { - future.await(); - } catch(InterruptedException e) { - } - } - } else { - this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); - } - - this.channel = null; + if(this.packetHandleThread != null) { + this.packetHandleThread.interrupt(); + this.packetHandleThread = null; } + + if(this.channel != null && this.channel.isOpen()) { + this.callEvent(new DisconnectingEvent(this, reason, cause)); + ChannelFuture future = this.channel.flush().close().addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); + } + }); + + if(wait) { + try { + future.await(); + } catch(InterruptedException e) { + } + } + } else { + this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); + } + + this.channel = null; } protected void refreshReadTimeoutHandler() { @@ -299,20 +308,38 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { - if(this.disconnected) { + if(this.disconnected || this.channel != null) { ctx.channel().close(); return; } this.channel = ctx.channel(); - this.disconnected = false; + + this.packetHandleThread = new Thread(new Runnable() { + @Override + public void run() { + try { + Packet packet; + while((packet = packets.take()) != null) { + callEvent(new PacketReceivedEvent(TcpSession.this, packet)); + } + } catch(InterruptedException e) { + } catch(Throwable t) { + exceptionCaught(null, t); + } + } + }); + + this.packetHandleThread.start(); + this.callEvent(new ConnectedEvent(this)); - new PacketHandleThread().start(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - this.disconnect("Connection closed."); + if(ctx.channel() == this.channel) { + this.disconnect("Connection closed."); + } } @Override @@ -337,29 +364,4 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp this.packets.add(packet); } } - - private class PacketHandleThread extends Thread { - @Override - public void run() { - try { - while(!disconnected) { - while(packets.size() > 0) { - callEvent(new PacketReceivedEvent(TcpSession.this, packets.remove(0))); - } - - try { - Thread.sleep(5); - } catch(InterruptedException e) { - } - } - } catch(Throwable t) { - try { - exceptionCaught(null, t); - } catch(Exception e) { - System.err.println("Exception while handling exception!"); - e.printStackTrace(); - } - } - } - } } From 9c1ac6aa9b6b6541c9b06f934a64389973186534 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 20:08:13 -0700 Subject: [PATCH 041/180] Ensure channel is set before returning from bind(). --- .../packetlib/tcp/TcpConnectionListener.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index f8c1bb41..c9e363a9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -87,24 +87,29 @@ public class TcpConnectionListener implements ConnectionListener { server.addSession(session); } - }).group(this.group).localAddress(this.host, this.port).bind().addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.isSuccess()) { - channel = channelFuture.channel(); - callback.run(); - } else if(channelFuture.cause() != null && !wait) { - System.err.println("[ERROR] Failed to asynchronously bind connection listener."); - channelFuture.cause().printStackTrace(); - } - } - }); + }).group(this.group).localAddress(this.host, this.port).bind(); if(wait) { try { future.sync(); } catch(InterruptedException e) { } + + channel = future.channel(); + callback.run(); + } else { + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if(channelFuture.isSuccess()) { + channel = channelFuture.channel(); + callback.run(); + } else if(channelFuture.cause() != null && !wait) { + System.err.println("[ERROR] Failed to asynchronously bind connection listener."); + channelFuture.cause().printStackTrace(); + } + } + }); } } From 83a5cb405ca0f4caa9caba12f74b02bbeb874e16 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 20:47:37 -0700 Subject: [PATCH 042/180] Minor fixes and cleanup. --- .../spacehq/packetlib/ConnectionListener.java | 8 +++ .../java/org/spacehq/packetlib/Server.java | 10 ++- .../packetlib/tcp/TcpClientSession.java | 2 +- .../packetlib/tcp/TcpConnectionListener.java | 64 ++++++++++++++++--- .../org/spacehq/packetlib/tcp/TcpSession.java | 8 +-- 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/ConnectionListener.java b/src/main/java/org/spacehq/packetlib/ConnectionListener.java index 8de8fb60..25027a20 100644 --- a/src/main/java/org/spacehq/packetlib/ConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/ConnectionListener.java @@ -56,4 +56,12 @@ public interface ConnectionListener { * @param wait Whether to wait for the listener to finish closing. */ public void close(boolean wait); + + /** + * Closes the listener. + * + * @param wait Whether to wait for the listener to finish closing. + * @param callback Callback to call when the listener has finished closing. + */ + public void close(boolean wait, Runnable callback); } diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index cad2d2d9..cde9f5b8 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -248,7 +248,7 @@ public class Server { * Closes the server. */ public void close() { - this.close(false); + this.close(true); } /** @@ -264,7 +264,11 @@ public class Server { } } - this.listener.close(wait); - this.callEvent(new ServerClosedEvent(this)); + this.listener.close(wait, new Runnable() { + @Override + public void run() { + callEvent(new ServerClosedEvent(Server.this)); + } + }); } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index 6737b7df..cd73dcd8 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -93,7 +93,7 @@ public class TcpClientSession extends TcpSession { future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { - if(!future.isSuccess() && future.cause() != null) { + if(!future.isSuccess()) { exceptionCaught(null, future.cause()); } } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index c9e363a9..32c9fafe 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -11,6 +11,7 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import org.spacehq.packetlib.ConnectionListener; import org.spacehq.packetlib.Server; import org.spacehq.packetlib.packet.PacketProtocol; @@ -57,7 +58,7 @@ public class TcpConnectionListener implements ConnectionListener { } @Override - public void bind(final boolean wait, final Runnable callback) { + public void bind(boolean wait, final Runnable callback) { if(this.group != null || this.channel != null) { return; } @@ -96,17 +97,23 @@ public class TcpConnectionListener implements ConnectionListener { } channel = future.channel(); - callback.run(); + if(callback != null) { + callback.run(); + } } else { future.addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if(channelFuture.isSuccess()) { - channel = channelFuture.channel(); - callback.run(); - } else if(channelFuture.cause() != null && !wait) { + public void operationComplete(ChannelFuture future) throws Exception { + if(future.isSuccess()) { + channel = future.channel(); + if(callback != null) { + callback.run(); + } + } else { System.err.println("[ERROR] Failed to asynchronously bind connection listener."); - channelFuture.cause().printStackTrace(); + if(future.cause() != null) { + future.cause().printStackTrace(); + } } } }); @@ -120,14 +127,39 @@ public class TcpConnectionListener implements ConnectionListener { @Override public void close(boolean wait) { + this.close(wait, null); + } + + @Override + public void close(boolean wait, final Runnable callback) { if(this.channel != null) { if(this.channel.isOpen()) { ChannelFuture future = this.channel.close(); if(wait) { try { - future.await(); + future.sync(); } catch(InterruptedException e) { } + + if(callback != null) { + callback.run(); + } + } else { + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if(future.isSuccess()) { + if(callback != null) { + callback.run(); + } + } else { + System.err.println("[ERROR] Failed to asynchronously close connection listener."); + if(future.cause() != null) { + future.cause().printStackTrace(); + } + } + } + }); } } @@ -138,9 +170,21 @@ public class TcpConnectionListener implements ConnectionListener { Future future = this.group.shutdownGracefully(); if(wait) { try { - future.await(); + future.sync(); } catch(InterruptedException e) { } + } else { + future.addListener(new GenericFutureListener() { + @Override + public void operationComplete(Future future) throws Exception { + if(!future.isSuccess()) { + System.err.println("[ERROR] Failed to asynchronously close connection listener."); + if(future.cause() != null) { + future.cause().printStackTrace(); + } + } + } + }); } this.group = null; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index c3a15521..cc74912f 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -200,10 +200,10 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp ChannelFuture future = this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { - if(!future.isSuccess()) { - exceptionCaught(null, future.cause()); - } else { + if(future.isSuccess()) { callEvent(new PacketSentEvent(TcpSession.this, packet)); + } else { + exceptionCaught(null, future.cause()); } } }); @@ -248,7 +248,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp this.callEvent(new DisconnectingEvent(this, reason, cause)); ChannelFuture future = this.channel.flush().close().addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { + public void operationComplete(ChannelFuture future) throws Exception { callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); } }); From 310de7c4906e0bef9d8a5a93325ec922f11b3b0c Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 20:52:17 -0700 Subject: [PATCH 043/180] Test. --- .../java/org/spacehq/packetlib/tcp/TcpClientSession.java | 3 +++ src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index cd73dcd8..d8b0f6a3 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -93,9 +93,11 @@ public class TcpClientSession extends TcpSession { future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { + System.err.println("Future start."); if(!future.isSuccess()) { exceptionCaught(null, future.cause()); } + System.err.println("Future end."); } }).await(); } catch(Throwable t) { @@ -106,6 +108,7 @@ public class TcpClientSession extends TcpSession { if(wait) { connectTask.run(); + System.err.println("Connect completed."); } else { new Thread(connectTask).start(); } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index cc74912f..04381734 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -308,13 +308,18 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.err.println("Channel active?"); if(this.disconnected || this.channel != null) { ctx.channel().close(); return; } + System.err.println("Channel active."); + this.channel = ctx.channel(); + System.err.println("Channel set."); + this.packetHandleThread = new Thread(new Runnable() { @Override public void run() { From 34c2a5c2914a6b7110a1f7b8c14e31ff474de62d Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 21:05:52 -0700 Subject: [PATCH 044/180] Ensure channel is set before returning from connect(). --- .../org/spacehq/packetlib/tcp/TcpClientSession.java | 12 +++++++++--- .../spacehq/packetlib/tcp/TcpConnectionListener.java | 2 -- .../org/spacehq/packetlib/tcp/TcpServerSession.java | 7 +++++++ .../java/org/spacehq/packetlib/tcp/TcpSession.java | 5 ----- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index d8b0f6a3..c525b741 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -93,13 +93,20 @@ public class TcpClientSession extends TcpSession { future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { - System.err.println("Future start."); if(!future.isSuccess()) { exceptionCaught(null, future.cause()); } - System.err.println("Future end."); } }).await(); + + if(future.isSuccess()) { + while(!isConnected()) { + try { + Thread.sleep(5); + } catch(InterruptedException e) { + } + } + } } catch(Throwable t) { exceptionCaught(null, t); } @@ -108,7 +115,6 @@ public class TcpClientSession extends TcpSession { if(wait) { connectTask.run(); - System.err.println("Connect completed."); } else { new Thread(connectTask).start(); } diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java index 32c9fafe..e0eb4a0d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java @@ -85,8 +85,6 @@ public class TcpConnectionListener implements ConnectionListener { pipeline.addLast("sizer", new TcpPacketSizer(session)); pipeline.addLast("codec", new TcpPacketCodec(session)); pipeline.addLast("manager", session); - - server.addSession(session); } }).group(this.group).localAddress(this.host, this.port).bind(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java index 8662dfc8..f9564bab 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java @@ -21,6 +21,13 @@ public class TcpServerSession extends TcpSession { return ret; } + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + + this.server.addSession(this); + } + @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 04381734..cc74912f 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -308,18 +308,13 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { - System.err.println("Channel active?"); if(this.disconnected || this.channel != null) { ctx.channel().close(); return; } - System.err.println("Channel active."); - this.channel = ctx.channel(); - System.err.println("Channel set."); - this.packetHandleThread = new Thread(new Runnable() { @Override public void run() { From fa806e58feee9ab66edf3c4f91c526c21fc9c520 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 21:14:17 -0700 Subject: [PATCH 045/180] Sync future instead of using listener. --- .../org/spacehq/packetlib/tcp/TcpClientSession.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index c525b741..e11ddfc7 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -3,7 +3,6 @@ package org.spacehq.packetlib.tcp; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; @@ -89,16 +88,7 @@ public class TcpClientSession extends TcpSession { bootstrap.remoteAddress(host, port); - ChannelFuture future = bootstrap.connect(); - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(!future.isSuccess()) { - exceptionCaught(null, future.cause()); - } - } - }).await(); - + ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { while(!isConnected()) { try { From b7a1cdf2cc08f32cb9520d02212f1f0b2066af75 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2015 21:16:20 -0700 Subject: [PATCH 046/180] Ensure we aren't waiting for a connection when we've been disconnected by the user. --- src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java index e11ddfc7..f1cac837 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java @@ -90,7 +90,7 @@ public class TcpClientSession extends TcpSession { ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { - while(!isConnected()) { + while(!isConnected() && !disconnected) { try { Thread.sleep(5); } catch(InterruptedException e) { From 494805306f3af515e0e78569319dd0d5ad07eb2c Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 22 Aug 2015 20:25:04 -0700 Subject: [PATCH 047/180] Remove prefixed byte array methods. --- src/main/java/org/spacehq/packetlib/io/NetInput.java | 8 -------- src/main/java/org/spacehq/packetlib/io/NetOutput.java | 8 -------- .../org/spacehq/packetlib/io/stream/StreamNetInput.java | 6 ------ .../org/spacehq/packetlib/io/stream/StreamNetOutput.java | 6 ------ .../org/spacehq/packetlib/tcp/io/ByteBufNetInput.java | 6 ------ .../org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java | 6 ------ 6 files changed, 40 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index d6294b92..1e792a93 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -103,14 +103,6 @@ public interface NetInput { */ public double readDouble() throws IOException; - /** - * Reads the next byte array, getting the length from a prefixed length value. - * - * @return The next byte array. - * @throws java.io.IOException If an I/O error occurs. - */ - public byte[] readPrefixedBytes() throws IOException; - /** * Reads the next byte array. * diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index 30dff1fa..95323a8c 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -87,14 +87,6 @@ public interface NetOutput { */ public void writeDouble(double d) throws IOException; - /** - * Writes a byte array, prefixing the written data with the array's length. - * - * @param b Byte array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - public void writePrefixedBytes(byte b[]) throws IOException; - /** * Writes a byte array. * diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index c980e183..4740d7a5 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -116,12 +116,6 @@ public class StreamNetInput implements NetInput { return Double.longBitsToDouble(this.readLong()); } - @Override - public byte[] readPrefixedBytes() throws IOException { - short length = this.readShort(); - return this.readBytes(length); - } - @Override public byte[] readBytes(int length) throws IOException { if(length < 0) { diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index 9a05bd7e..963212ce 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -93,12 +93,6 @@ public class StreamNetOutput implements NetOutput { this.writeLong(Double.doubleToLongBits(d)); } - @Override - public void writePrefixedBytes(byte b[]) throws IOException { - this.writeShort(b.length); - this.writeBytes(b); - } - @Override public void writeBytes(byte b[]) throws IOException { this.writeBytes(b, b.length); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index 2fb2a605..27223781 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -96,12 +96,6 @@ public class ByteBufNetInput implements NetInput { return this.buf.readDouble(); } - @Override - public byte[] readPrefixedBytes() throws IOException { - short length = this.buf.readShort(); - return this.readBytes(length); - } - @Override public byte[] readBytes(int length) throws IOException { if(length < 0) { diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 4983c0e1..5c8390ae 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -76,12 +76,6 @@ public class ByteBufNetOutput implements NetOutput { this.buf.writeDouble(d); } - @Override - public void writePrefixedBytes(byte b[]) throws IOException { - this.buf.writeShort(b.length); - this.buf.writeBytes(b); - } - @Override public void writeBytes(byte b[]) throws IOException { this.buf.writeBytes(b); From 62d5509768f1a5101754a933ffebc89a00d3bd2b Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 22 Aug 2015 21:43:32 -0700 Subject: [PATCH 048/180] Add additional array I/O methods, add ByteBuffer-backed NetInput and NetOutput implementations. --- .../org/spacehq/packetlib/io/NetInput.java | 87 ++++++ .../org/spacehq/packetlib/io/NetOutput.java | 51 ++++ .../io/buffer/ByteBufferNetInput.java | 261 ++++++++++++++++++ .../io/buffer/ByteBufferNetOutput.java | 153 ++++++++++ .../packetlib/io/stream/StreamNetInput.java | 99 +++++++ .../packetlib/io/stream/StreamNetOutput.java | 36 +++ .../packetlib/tcp/io/ByteBufNetInput.java | 111 ++++++++ .../packetlib/tcp/io/ByteBufNetOutput.java | 36 +++ 8 files changed, 834 insertions(+) create mode 100644 src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java create mode 100644 src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index 1e792a93..320b21ac 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -132,6 +132,93 @@ public interface NetInput { */ public int readBytes(byte b[], int offset, int length) throws IOException; + /** + * Reads the next short array. + * + * @param length The length of the short array. + * @return The next short array. + * @throws java.io.IOException If an I/O error occurs. + */ + public short[] readShorts(int length) throws IOException; + + /** + * Reads as much data as possible into the given short array. + * + * @param s Short array to read to. + * @return The amount of shorts read, or -1 if no shorts could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readShorts(short s[]) throws IOException; + + /** + * Reads the given amount of shorts into the given array at the given offset. + * + * @param s Short array to read to. + * @param offset Offset of the array to read to. + * @param length Length of bytes to read. + * @return The amount of shorts read, or -1 if no shorts could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readShorts(short s[], int offset, int length) throws IOException; + + /** + * Reads the next int array. + * + * @param length The length of the int array. + * @return The next int array. + * @throws java.io.IOException If an I/O error occurs. + */ + public int[] readInts(int length) throws IOException; + + /** + * Reads as much data as possible into the given int array. + * + * @param i Int array to read to. + * @return The amount of ints read, or -1 if no ints could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readInts(int i[]) throws IOException; + + /** + * Reads the given amount of ints into the given array at the given offset. + * + * @param i Int array to read to. + * @param offset Offset of the array to read to. + * @param length Length of bytes to read. + * @return The amount of ints read, or -1 if no ints could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readInts(int i[], int offset, int length) throws IOException; + + /** + * Reads the next long array. + * + * @param length The length of the long array. + * @return The next long array. + * @throws java.io.IOException If an I/O error occurs. + */ + public long[] readLongs(int length) throws IOException; + + /** + * Reads as much data as possible into the given long array. + * + * @param l Long array to read to. + * @return The amount of longs read, or -1 if no longs could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readLongs(long l[]) throws IOException; + + /** + * Reads the given amount of longs into the given array at the given offset. + * + * @param l Long array to read to. + * @param offset Offset of the array to read to. + * @param length Length of bytes to read. + * @return The amount of longs read, or -1 if no longs could be read. + * @throws java.io.IOException If an I/O error occurs. + */ + public int readLongs(long l[], int offset, int length) throws IOException; + /** * Reads the next string. * diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index 95323a8c..f30a60d0 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -104,6 +104,57 @@ public interface NetOutput { */ public void writeBytes(byte b[], int length) throws IOException; + /** + * Writes a short array. + * + * @param s Short array to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeShorts(short s[]) throws IOException; + + /** + * Writes a short array, using the given amount of bytes. + * + * @param s Short array to write. + * @param length Shorts to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeShorts(short s[], int length) throws IOException; + + /** + * Writes an int array. + * + * @param i Int array to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeInts(int i[]) throws IOException; + + /** + * Writes an int array, using the given amount of bytes. + * + * @param i Int array to write. + * @param length Ints to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeInts(int i[], int length) throws IOException; + + /** + * Writes a long array. + * + * @param l Long array to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeLongs(long l[]) throws IOException; + + /** + * Writes a long array, using the given amount of bytes. + * + * @param l Long array to write. + * @param length Longs to write. + * @throws java.io.IOException If an I/O error occurs. + */ + public void writeLongs(long l[], int length) throws IOException; + /** * Writes a string. * diff --git a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java new file mode 100644 index 00000000..af2e051b --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java @@ -0,0 +1,261 @@ +package org.spacehq.packetlib.io.buffer; + +import org.spacehq.packetlib.io.NetInput; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * A NetInput implementation using a ByteBuffer as a backend. + */ +public class ByteBufferNetInput implements NetInput { + private ByteBuffer buffer; + + public ByteBufferNetInput(ByteBuffer buffer) { + this.buffer = buffer; + } + + public ByteBuffer getByteBuffer() { + return this.buffer; + } + + @Override + public boolean readBoolean() throws IOException { + return this.buffer.get() == 1; + } + + @Override + public byte readByte() throws IOException { + return this.buffer.get(); + } + + @Override + public int readUnsignedByte() throws IOException { + return this.buffer.get() & 0xFF; + } + + @Override + public short readShort() throws IOException { + return this.buffer.getShort(); + } + + @Override + public int readUnsignedShort() throws IOException { + return this.buffer.getShort() & 0xFFFF; + } + + @Override + public char readChar() throws IOException { + return this.buffer.getChar(); + } + + @Override + public int readInt() throws IOException { + return this.buffer.getInt(); + } + + @Override + public int readVarInt() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 5) { + throw new IOException("VarInt too long (length must be <= 5)"); + } + } + + return value | ((b & 0x7F) << (size * 7)); + } + + @Override + public long readLong() throws IOException { + return this.buffer.getLong(); + } + + @Override + public long readVarLong() throws IOException { + int value = 0; + int size = 0; + int b; + while(((b = this.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if(size > 10) { + throw new IOException("VarLong too long (length must be <= 10)"); + } + } + + return value | ((b & 0x7F) << (size * 7)); + } + + @Override + public float readFloat() throws IOException { + return this.buffer.getFloat(); + } + + @Override + public double readDouble() throws IOException { + return this.buffer.getDouble(); + } + + @Override + public byte[] readBytes(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + byte b[] = new byte[length]; + this.buffer.get(b); + return b; + } + + @Override + public int readBytes(byte[] b) throws IOException { + return this.readBytes(b, 0, b.length); + } + + @Override + public int readBytes(byte[] b, int offset, int length) throws IOException { + int readable = this.buffer.remaining(); + if(readable <= 0) { + return -1; + } + + if(readable < length) { + length = readable; + } + + this.buffer.get(b, offset, length); + return length; + } + + @Override + public short[] readShorts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + short s[] = new short[length]; + for(int index = 0; index < length; index++) { + s[index] = this.readShort(); + } + + return s; + } + + @Override + public int readShorts(short[] s) throws IOException { + return this.readShorts(s, 0, s.length); + } + + @Override + public int readShorts(short[] s, int offset, int length) throws IOException { + int readable = this.buffer.remaining(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 2) { + length = readable / 2; + } + + for(int index = offset; index < offset + length; index++) { + s[index] = this.readShort(); + } + + return length; + } + + @Override + public int[] readInts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + int i[] = new int[length]; + for(int index = 0; index < length; index++) { + i[index] = this.readInt(); + } + + return i; + } + + @Override + public int readInts(int[] i) throws IOException { + return this.readInts(i, 0, i.length); + } + + @Override + public int readInts(int[] i, int offset, int length) throws IOException { + int readable = this.buffer.remaining(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 4) { + length = readable / 4; + } + + for(int index = offset; index < offset + length; index++) { + i[index] = this.readInt(); + } + + return length; + } + + @Override + public long[] readLongs(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + long l[] = new long[length]; + for(int index = 0; index < length; index++) { + l[index] = this.readLong(); + } + + return l; + } + + @Override + public int readLongs(long[] l) throws IOException { + return this.readLongs(l, 0, l.length); + } + + @Override + public int readLongs(long[] l, int offset, int length) throws IOException { + int readable = this.buffer.remaining(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 2) { + length = readable / 2; + } + + for(int index = offset; index < offset + length; index++) { + l[index] = this.readLong(); + } + + return length; + } + + @Override + public String readString() throws IOException { + int length = this.readVarInt(); + byte bytes[] = this.readBytes(length); + return new String(bytes, "UTF-8"); + } + + @Override + public UUID readUUID() throws IOException { + return new UUID(this.readLong(), this.readLong()); + } + + @Override + public int available() throws IOException { + return this.buffer.remaining(); + } +} diff --git a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java new file mode 100644 index 00000000..be46f7f2 --- /dev/null +++ b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java @@ -0,0 +1,153 @@ +package org.spacehq.packetlib.io.buffer; + +import org.spacehq.packetlib.io.NetOutput; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.UUID; + +/** + * A NetOutput implementation using a ByteBuf as a backend. + */ +public class ByteBufferNetOutput implements NetOutput { + private ByteBuffer buffer; + + public ByteBufferNetOutput(ByteBuffer buffer) { + this.buffer = buffer; + } + + public ByteBuffer getByteBuffer() { + return this.buffer; + } + + @Override + public void writeBoolean(boolean b) throws IOException { + this.buffer.put(b ? (byte) 1 : 0); + } + + @Override + public void writeByte(int b) throws IOException { + this.buffer.put((byte) b); + } + + @Override + public void writeShort(int s) throws IOException { + this.buffer.putShort((short) s); + } + + @Override + public void writeChar(int c) throws IOException { + this.buffer.putChar((char) c); + } + + @Override + public void writeInt(int i) throws IOException { + this.buffer.putInt(i); + } + + @Override + public void writeVarInt(int i) throws IOException { + while((i & ~0x7F) != 0) { + this.writeByte((i & 0x7F) | 0x80); + i >>>= 7; + } + + this.writeByte(i); + } + + @Override + public void writeLong(long l) throws IOException { + this.buffer.putLong(l); + } + + @Override + public void writeVarLong(long l) throws IOException { + while((l & ~0x7F) != 0) { + this.writeByte((int) (l & 0x7F) | 0x80); + l >>>= 7; + } + + this.writeByte((int) l); + } + + @Override + public void writeFloat(float f) throws IOException { + this.buffer.putFloat(f); + } + + @Override + public void writeDouble(double d) throws IOException { + this.buffer.putDouble(d); + } + + @Override + public void writeBytes(byte b[]) throws IOException { + this.buffer.put(b); + } + + @Override + public void writeBytes(byte b[], int length) throws IOException { + this.buffer.put(b, 0, length); + } + + @Override + public void writeShorts(short[] s) throws IOException { + this.writeShorts(s, s.length); + } + + @Override + public void writeShorts(short[] s, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeShort(s[index]); + } + } + + @Override + public void writeInts(int[] i) throws IOException { + this.writeInts(i, i.length); + } + + @Override + public void writeInts(int[] i, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeInt(i[index]); + } + } + + @Override + public void writeLongs(long[] l) throws IOException { + this.writeLongs(l, l.length); + } + + @Override + public void writeLongs(long[] l, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeLong(l[index]); + } + } + + @Override + public void writeString(String s) throws IOException { + if(s == null) { + throw new IllegalArgumentException("String cannot be null!"); + } + + byte[] bytes = s.getBytes("UTF-8"); + if(bytes.length > 32767) { + throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); + } else { + this.writeVarInt(bytes.length); + this.writeBytes(bytes); + } + } + + @Override + public void writeUUID(UUID uuid) throws IOException { + this.writeLong(uuid.getMostSignificantBits()); + this.writeLong(uuid.getLeastSignificantBits()); + } + + @Override + public void flush() throws IOException { + } +} diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index 4740d7a5..69d1d1b4 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -146,6 +146,105 @@ public class StreamNetInput implements NetInput { return this.in.read(b, offset, length); } + @Override + public short[] readShorts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + short s[] = new short[length]; + int read = this.readShorts(s); + if(read < length) { + throw new EOFException(); + } + + return s; + } + + @Override + public int readShorts(short[] s) throws IOException { + return this.readShorts(s, 0, s.length); + } + + @Override + public int readShorts(short[] s, int offset, int length) throws IOException { + for(int index = offset; index < offset + length; index++) { + try { + s[index] = this.readShort(); + } catch(EOFException e) { + return index - offset; + } + } + + return length; + } + + @Override + public int[] readInts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + int i[] = new int[length]; + int read = this.readInts(i); + if(read < length) { + throw new EOFException(); + } + + return i; + } + + @Override + public int readInts(int[] i) throws IOException { + return this.readInts(i, 0, i.length); + } + + @Override + public int readInts(int[] i, int offset, int length) throws IOException { + for(int index = offset; index < offset + length; index++) { + try { + i[index] = this.readInt(); + } catch(EOFException e) { + return index - offset; + } + } + + return length; + } + + @Override + public long[] readLongs(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + long l[] = new long[length]; + int read = this.readLongs(l); + if(read < length) { + throw new EOFException(); + } + + return l; + } + + @Override + public int readLongs(long[] l) throws IOException { + return this.readLongs(l, 0, l.length); + } + + @Override + public int readLongs(long[] l, int offset, int length) throws IOException { + for(int index = offset; index < offset + length; index++) { + try { + l[index] = this.readLong(); + } catch(EOFException e) { + return index - offset; + } + } + + return length; + } + @Override public String readString() throws IOException { int length = this.readVarInt(); diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java index 963212ce..29010791 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java @@ -103,6 +103,42 @@ public class StreamNetOutput implements NetOutput { this.out.write(b, 0, length); } + @Override + public void writeShorts(short[] s) throws IOException { + this.writeShorts(s, s.length); + } + + @Override + public void writeShorts(short[] s, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeShort(s[index]); + } + } + + @Override + public void writeInts(int[] i) throws IOException { + this.writeInts(i, i.length); + } + + @Override + public void writeInts(int[] i, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeInt(i[index]); + } + } + + @Override + public void writeLongs(long[] l) throws IOException { + this.writeLongs(l, l.length); + } + + @Override + public void writeLongs(long[] l, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeLong(l[index]); + } + } + @Override public void writeString(String s) throws IOException { if(s == null) { diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java index 27223781..85e33ff9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java @@ -127,6 +127,117 @@ public class ByteBufNetInput implements NetInput { return length; } + @Override + public short[] readShorts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + short s[] = new short[length]; + for(int index = 0; index < length; index++) { + s[index] = this.readShort(); + } + + return s; + } + + @Override + public int readShorts(short[] s) throws IOException { + return this.readShorts(s, 0, s.length); + } + + @Override + public int readShorts(short[] s, int offset, int length) throws IOException { + int readable = this.buf.readableBytes(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 2) { + length = readable / 2; + } + + for(int index = offset; index < offset + length; index++) { + s[index] = this.readShort(); + } + + return length; + } + + @Override + public int[] readInts(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + int i[] = new int[length]; + for(int index = 0; index < length; index++) { + i[index] = this.readInt(); + } + + return i; + } + + @Override + public int readInts(int[] i) throws IOException { + return this.readInts(i, 0, i.length); + } + + @Override + public int readInts(int[] i, int offset, int length) throws IOException { + int readable = this.buf.readableBytes(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 4) { + length = readable / 4; + } + + for(int index = offset; index < offset + length; index++) { + i[index] = this.readInt(); + } + + return length; + } + + @Override + public long[] readLongs(int length) throws IOException { + if(length < 0) { + throw new IllegalArgumentException("Array cannot have length less than 0."); + } + + long l[] = new long[length]; + for(int index = 0; index < length; index++) { + l[index] = this.readLong(); + } + + return l; + } + + @Override + public int readLongs(long[] l) throws IOException { + return this.readLongs(l, 0, l.length); + } + + @Override + public int readLongs(long[] l, int offset, int length) throws IOException { + int readable = this.buf.readableBytes(); + if(readable <= 0) { + return -1; + } + + if(readable < length * 2) { + length = readable / 2; + } + + for(int index = offset; index < offset + length; index++) { + l[index] = this.readLong(); + } + + return length; + } + @Override public String readString() throws IOException { int length = this.readVarInt(); diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java index 5c8390ae..cd245738 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java @@ -86,6 +86,42 @@ public class ByteBufNetOutput implements NetOutput { this.buf.writeBytes(b, 0, length); } + @Override + public void writeShorts(short[] s) throws IOException { + this.writeShorts(s, s.length); + } + + @Override + public void writeShorts(short[] s, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeShort(s[index]); + } + } + + @Override + public void writeInts(int[] i) throws IOException { + this.writeInts(i, i.length); + } + + @Override + public void writeInts(int[] i, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeInt(i[index]); + } + } + + @Override + public void writeLongs(long[] l) throws IOException { + this.writeLongs(l, l.length); + } + + @Override + public void writeLongs(long[] l, int length) throws IOException { + for(int index = 0; index < length; index++) { + this.writeLong(l[index]); + } + } + @Override public void writeString(String s) throws IOException { if(s == null) { From 885d03759dce99d1d0a4b49b156d447c0d97b70e Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Mon, 24 Aug 2015 20:15:51 -0700 Subject: [PATCH 049/180] Report when packets are not fully read. --- src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java index f445e7df..83192225 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java @@ -39,6 +39,11 @@ public class TcpPacketCodec extends ByteToMessageCodec { Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); packet.read(in); + + if(buf.readableBytes() > 0) { + throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); + } + if(packet.isPriority()) { this.session.callEvent(new PacketReceivedEvent(this.session, packet)); } From 1b5b2c37a0eb7c99d17af5c27ee0df948f90a1a1 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 13 Aug 2016 17:12:34 -0700 Subject: [PATCH 050/180] Fix readVarLong. --- .../org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java | 6 +++--- .../org/spacehq/packetlib/io/stream/StreamNetInput.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java index af2e051b..9c71c128 100644 --- a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java @@ -77,17 +77,17 @@ public class ByteBufferNetInput implements NetInput { @Override public long readVarLong() throws IOException { - int value = 0; + long value = 0; int size = 0; int b; while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); + value |= (long) (b & 0x7F) << (size++ * 7); if(size > 10) { throw new IOException("VarLong too long (length must be <= 10)"); } } - return value | ((b & 0x7F) << (size * 7)); + return value | ((long) (b & 0x7F) << (size * 7)); } @Override diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java index 69d1d1b4..3433f4fe 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java @@ -93,17 +93,17 @@ public class StreamNetInput implements NetInput { @Override public long readVarLong() throws IOException { - int value = 0; + long value = 0; int size = 0; int b; while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); + value |= (long) (b & 0x7F) << (size++ * 7); if(size > 10) { throw new IOException("VarLong too long (length must be <= 10)"); } } - return value | ((b & 0x7F) << (size * 7)); + return value | ((long) (b & 0x7F) << (size * 7)); } @Override From 333b7d247de62b23796158e54cc23a7e31e8a3d8 Mon Sep 17 00:00:00 2001 From: Jadon Fowler Date: Sun, 21 Aug 2016 18:00:17 -0700 Subject: [PATCH 051/180] Change Disconnect message to the Throwable's message Throwable#toString() returns a description of the Throwable that includes the name of the class appended to Throwable#getLocalizedMessage(), which can be used for debugging purposes. --- src/main/java/org/spacehq/packetlib/tcp/TcpSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index cc74912f..30dfeef9 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -352,7 +352,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } else if(cause instanceof WriteTimeoutException) { message = "Write timed out."; } else { - message = "Internal network exception."; + message = cause.toString(); } this.disconnect(message, cause); From 7be81ec106c0526c66808012ef59d4be3424c7fc Mon Sep 17 00:00:00 2001 From: Jadon Fowler Date: Tue, 23 Aug 2016 19:22:33 -0700 Subject: [PATCH 052/180] Set Java version to 1.7 in POM There are 1.7 classes being used, so we should specify that Java 1.7 is required. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 87a2471f..0b666a65 100644 --- a/pom.xml +++ b/pom.xml @@ -78,8 +78,8 @@ maven-compiler-plugin 2.5.1 - 1.6 - 1.6 + 1.7 + 1.7 From f846b96ab49928eed73f87e20c57da2599adaeca Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 15 Dec 2016 16:57:22 -0800 Subject: [PATCH 053/180] Generate source and javadoc jars. --- pom.xml | 24 +++++++++++++++++++ .../java/org/spacehq/packetlib/Server.java | 1 + .../java/org/spacehq/packetlib/Session.java | 1 + .../packetlib/crypt/PacketEncryption.java | 4 ++++ .../event/session/PacketReceivedEvent.java | 1 + .../event/session/PacketSentEvent.java | 1 + .../org/spacehq/packetlib/io/NetInput.java | 1 + .../org/spacehq/packetlib/io/NetOutput.java | 4 ++-- .../org/spacehq/packetlib/packet/Packet.java | 2 ++ 9 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0b666a65..4c27a824 100644 --- a/pom.xml +++ b/pom.xml @@ -87,6 +87,30 @@ maven-jar-plugin 2.6 + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + org.apache.maven.plugins maven-shade-plugin diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index cde9f5b8..ff27f752 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -135,6 +135,7 @@ public class Server { * session belongs to a server, the server's flags will be checked for the flag * as well. * + * @param Type of the flag. * @param key Key of the flag. * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index 600b4eea..215a0fb6 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -67,6 +67,7 @@ public interface Session { * session belongs to a server, the server's flags will be checked for the flag * as well. * + * @param Type of the flag. * @param key Key of the flag. * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. diff --git a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java index 838cf227..0e5f949f 100644 --- a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java +++ b/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java @@ -8,6 +8,7 @@ public interface PacketEncryption { * Gets the output size from decrypting. * * @param length Length of the data being decrypted. + * @return The output size from decrypting. */ public int getDecryptOutputSize(int length); @@ -15,6 +16,7 @@ public interface PacketEncryption { * Gets the output size from encrypting. * * @param length Length of the data being encrypted. + * @return The output size from encrypting. */ public int getEncryptOutputSize(int length); @@ -27,6 +29,7 @@ public interface PacketEncryption { * @param output Array to output decrypted data to. * @param outputOffset Offset of the output array to start at. * @return The number of bytes stored in the output array. + * @throws Exception If an error occurs. */ public int decrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; @@ -39,6 +42,7 @@ public interface PacketEncryption { * @param output Array to output encrypted data to. * @param outputOffset Offset of the output array to start at. * @return The number of bytes stored in the output array. + * @throws Exception If an error occurs. */ public int encrypt(byte input[], int inputOffset, int inputLength, byte output[], int outputOffset) throws Exception; } diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java index 4f945123..db43b86e 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java @@ -33,6 +33,7 @@ public class PacketReceivedEvent implements SessionEvent { /** * Gets the packet involved in this event as the required type. * + * @param Type of the packet. * @return The event's packet as the required type. * @throws IllegalStateException If the packet's value isn't of the required type. */ diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java index f9815ebb..765c387e 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java @@ -33,6 +33,7 @@ public class PacketSentEvent implements SessionEvent { /** * Gets the packet involved in this event as the required type. * + * @param Type of the packet. * @return The event's packet as the required type. * @throws IllegalStateException If the packet's value isn't of the required type. */ diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/org/spacehq/packetlib/io/NetInput.java index 320b21ac..fbc42327 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetInput.java @@ -239,6 +239,7 @@ public interface NetInput { * Gets the number of available bytes. * * @return The number of available bytes. + * @throws java.io.IOException If an I/O error occurs. */ public int available() throws IOException; } diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/org/spacehq/packetlib/io/NetOutput.java index f30a60d0..7e6b3dda 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/org/spacehq/packetlib/io/NetOutput.java @@ -50,7 +50,7 @@ public interface NetOutput { /** * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. * - * @return i Varint to write. + * @param i Varint to write. * @throws java.io.IOException If an I/O error occurs. */ public void writeVarInt(int i) throws IOException; @@ -66,7 +66,7 @@ public interface NetOutput { /** * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. * - * @return l Varlong to write. + * @param l Varlong to write. * @throws java.io.IOException If an I/O error occurs. */ public void writeVarLong(long l) throws IOException; diff --git a/src/main/java/org/spacehq/packetlib/packet/Packet.java b/src/main/java/org/spacehq/packetlib/packet/Packet.java index a36d9a22..baf51cb4 100644 --- a/src/main/java/org/spacehq/packetlib/packet/Packet.java +++ b/src/main/java/org/spacehq/packetlib/packet/Packet.java @@ -13,6 +13,7 @@ public interface Packet { * Reads the packet from the given input buffer. * * @param in The input source to read from. + * @throws IOException If an I/O error occurs. */ public void read(NetInput in) throws IOException; @@ -20,6 +21,7 @@ public interface Packet { * Writes the packet to the given output buffer. * * @param out The output destination to write to. + * @throws IOException If an I/O error occurs. */ public void write(NetOutput out) throws IOException; From b5bfe245173561a5cf74efdd88892b7fe1868de6 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 15 Dec 2016 17:05:24 -0800 Subject: [PATCH 054/180] Expose local and remote addresses of Sessions. --- src/main/java/org/spacehq/packetlib/Session.java | 16 ++++++++++++++++ .../org/spacehq/packetlib/tcp/TcpSession.java | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index 215a0fb6..f2981f65 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -5,6 +5,8 @@ import org.spacehq.packetlib.event.session.SessionListener; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; +import java.net.InetAddress; +import java.net.SocketAddress; import java.util.List; import java.util.Map; @@ -38,6 +40,20 @@ public interface Session { */ public int getPort(); + /** + * Gets the local address of the session. + * + * @return The local address, or null if the session is not connected. + */ + public SocketAddress getLocalAddress(); + + /** + * Gets the remote address of the session. + * + * @return The remote address, or null if the session is not connected. + */ + public SocketAddress getRemoteAddress(); + /** * Gets the packet protocol of the session. * diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 30dfeef9..5c119890 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -22,6 +22,8 @@ import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; import java.net.ConnectException; +import java.net.InetAddress; +import java.net.SocketAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -74,6 +76,16 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp return this.port; } + @Override + public SocketAddress getLocalAddress() { + return this.channel != null ? this.channel.localAddress() : null; + } + + @Override + public SocketAddress getRemoteAddress() { + return this.channel != null ? this.channel.remoteAddress() : null; + } + @Override public PacketProtocol getPacketProtocol() { return this.protocol; From cc4d9869bbae9bd6ace28f45c3798e23ec8d85c7 Mon Sep 17 00:00:00 2001 From: Kevin Rossouw <17238714@sun.ac.za> Date: Wed, 25 Jan 2017 16:47:00 +0200 Subject: [PATCH 055/180] Ported library to Netty 4.1.4 (Netty 5 has been discontinued) by modifying TcpSession.java and pom.xml. Fixed a bug in Server.java where isListening() would throw a NullPointerException if called before bind(). Removed unused imports of java.net.InetAddress in Session.java and TcpSession.java. Updated Maven plugin versions in pom.xml. --- pom.xml | 20 ++++++++++--------- .../java/org/spacehq/packetlib/Server.java | 2 +- .../java/org/spacehq/packetlib/Session.java | 1 - .../org/spacehq/packetlib/tcp/TcpSession.java | 3 +-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 4c27a824..86c9882f 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ io.netty netty-all - 5.0.0.Alpha2 + 4.1.4.Final @@ -76,20 +76,21 @@ org.apache.maven.plugins maven-compiler-plugin - 2.5.1 + 3.6.1 - 1.7 - 1.7 + 1.7 + 1.7 org.apache.maven.plugins maven-jar-plugin - 2.6 + 3.0.2 org.apache.maven.plugins - maven-source-plugin + maven-source-plugin + 3.0.1 attach-sources @@ -100,8 +101,9 @@ - org.apache.maven.plugins - maven-javadoc-plugin + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 attach-javadocs @@ -114,7 +116,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.4.1 + 2.4.3 package diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/org/spacehq/packetlib/Server.java index ff27f752..5300739c 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/org/spacehq/packetlib/Server.java @@ -242,7 +242,7 @@ public class Server { * @return Whether the server is listening. */ public boolean isListening() { - return this.listener.isListening(); + return this.listener != null && this.listener.isListening(); } /** diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/org/spacehq/packetlib/Session.java index f2981f65..acf7a43c 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/org/spacehq/packetlib/Session.java @@ -5,7 +5,6 @@ import org.spacehq.packetlib.event.session.SessionListener; import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; -import java.net.InetAddress; import java.net.SocketAddress; import java.util.List; import java.util.Map; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java index 5c119890..5773b29d 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java @@ -22,7 +22,6 @@ import org.spacehq.packetlib.packet.Packet; import org.spacehq.packetlib.packet.PacketProtocol; import java.net.ConnectException; -import java.net.InetAddress; import java.net.SocketAddress; import java.util.ArrayList; import java.util.HashMap; @@ -371,7 +370,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } @Override - protected void messageReceived(ChannelHandlerContext ctx, Packet packet) throws Exception { + protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception { if(!packet.isPriority()) { this.packets.add(packet); } From f51fda303ab2a8aee2a34bc81acd3602216d490d Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 25 Jan 2017 15:17:21 -0800 Subject: [PATCH 056/180] Fix pom.xml indentation. --- pom.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 86c9882f..85d4d07c 100644 --- a/pom.xml +++ b/pom.xml @@ -78,8 +78,8 @@ maven-compiler-plugin 3.6.1 - 1.7 - 1.7 + 1.7 + 1.7 @@ -89,8 +89,8 @@ org.apache.maven.plugins - maven-source-plugin - 3.0.1 + maven-source-plugin + 3.0.1 attach-sources @@ -101,9 +101,9 @@ - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 attach-javadocs From 4608261e99aacb57c8e185eb7dad61b627e07426 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 1 Mar 2017 16:09:48 -0800 Subject: [PATCH 057/180] Migrate away from spacehq.org --- README.md | 5 +--- .../packetlib/test/ClientSessionListener.java | 14 +++++----- .../packetlib/test/PingPacket.java | 8 +++--- .../packetlib/test/PingServerTest.java | 8 +++--- .../packetlib/test/ServerListener.java | 14 +++++----- .../packetlib/test/ServerSessionListener.java | 14 +++++----- .../packetlib/test/TestProtocol.java | 18 ++++++------- pom.xml | 26 +------------------ .../github/steveice10}/packetlib/Client.java | 4 +-- .../packetlib/ConnectionListener.java | 2 +- .../github/steveice10}/packetlib/Server.java | 18 ++++++------- .../github/steveice10}/packetlib/Session.java | 10 +++---- .../steveice10}/packetlib/SessionFactory.java | 2 +- .../packetlib/crypt/AESEncryption.java | 2 +- .../packetlib/crypt/PacketEncryption.java | 2 +- .../packetlib/event/server/ServerAdapter.java | 2 +- .../event/server/ServerBoundEvent.java | 4 +-- .../event/server/ServerClosedEvent.java | 4 +-- .../event/server/ServerClosingEvent.java | 4 +-- .../packetlib/event/server/ServerEvent.java | 2 +- .../event/server/ServerListener.java | 2 +- .../event/server/SessionAddedEvent.java | 6 ++--- .../event/server/SessionRemovedEvent.java | 6 ++--- .../event/session/ConnectedEvent.java | 4 +-- .../event/session/DisconnectedEvent.java | 4 +-- .../event/session/DisconnectingEvent.java | 4 +-- .../event/session/PacketReceivedEvent.java | 6 ++--- .../event/session/PacketSentEvent.java | 6 ++--- .../event/session/SessionAdapter.java | 2 +- .../packetlib/event/session/SessionEvent.java | 2 +- .../event/session/SessionListener.java | 2 +- .../steveice10}/packetlib/io/NetInput.java | 2 +- .../steveice10}/packetlib/io/NetOutput.java | 2 +- .../io/buffer/ByteBufferNetInput.java | 4 +-- .../io/buffer/ByteBufferNetOutput.java | 4 +-- .../packetlib/io/stream/StreamNetInput.java | 4 +-- .../packetlib/io/stream/StreamNetOutput.java | 4 +-- .../packetlib/packet/DefaultPacketHeader.java | 6 ++--- .../steveice10}/packetlib/packet/Packet.java | 6 ++--- .../packetlib/packet/PacketHeader.java | 6 ++--- .../packetlib/packet/PacketProtocol.java | 10 +++---- .../packetlib/tcp/ProxyOioChannelFactory.java | 2 +- .../packetlib/tcp/TcpClientSession.java | 6 ++--- .../packetlib/tcp/TcpConnectionListener.java | 8 +++--- .../packetlib/tcp/TcpPacketCodec.java | 16 ++++++------ .../packetlib/tcp/TcpPacketCompression.java | 8 +++--- .../packetlib/tcp/TcpPacketEncryptor.java | 4 +-- .../packetlib/tcp/TcpPacketSizer.java | 8 +++--- .../packetlib/tcp/TcpServerSession.java | 6 ++--- .../steveice10}/packetlib/tcp/TcpSession.java | 22 ++++++++-------- .../packetlib/tcp/TcpSessionFactory.java | 12 ++++----- .../packetlib/tcp/io/ByteBufNetInput.java | 4 +-- .../packetlib/tcp/io/ByteBufNetOutput.java | 4 +-- 53 files changed, 164 insertions(+), 191 deletions(-) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/ClientSessionListener.java (73%) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/PingPacket.java (74%) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/PingServerTest.java (83%) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/ServerListener.java (71%) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/ServerSessionListener.java (68%) rename example/{org/spacehq => com/github/steveice10}/packetlib/test/TestProtocol.java (70%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/Client.java (91%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/ConnectionListener.java (97%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/Server.java (92%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/Session.java (95%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/SessionFactory.java (92%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/crypt/AESEncryption.java (97%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/crypt/PacketEncryption.java (97%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerAdapter.java (90%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerBoundEvent.java (86%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerClosedEvent.java (85%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerClosingEvent.java (85%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerEvent.java (80%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/ServerListener.java (94%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/SessionAddedEvent.java (86%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/server/SessionRemovedEvent.java (86%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/ConnectedEvent.java (85%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/DisconnectedEvent.java (94%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/DisconnectingEvent.java (94%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/PacketReceivedEvent.java (89%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/PacketSentEvent.java (89%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/SessionAdapter.java (90%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/SessionEvent.java (80%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/event/session/SessionListener.java (94%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/NetInput.java (99%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/NetOutput.java (99%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/buffer/ByteBufferNetInput.java (98%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/buffer/ByteBufferNetOutput.java (97%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/stream/StreamNetInput.java (98%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/io/stream/StreamNetOutput.java (97%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/packet/DefaultPacketHeader.java (88%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/packet/Packet.java (85%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/packet/PacketHeader.java (92%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/packet/PacketProtocol.java (95%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/ProxyOioChannelFactory.java (91%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpClientSession.java (96%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpConnectionListener.java (96%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpPacketCodec.java (76%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpPacketCompression.java (92%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpPacketEncryptor.java (95%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpPacketSizer.java (90%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpServerSession.java (84%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpSession.java (94%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/TcpSessionFactory.java (70%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/io/ByteBufNetInput.java (98%) rename src/main/java/{org/spacehq => com/github/steveice10}/packetlib/tcp/io/ByteBufNetOutput.java (97%) diff --git a/README.md b/README.md index 153dbfff..118e10fc 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,10 @@ PacketLib is a library for packet-based networking between clients and servers It was made as a basis for other projects involving packet networking. ## Test Example -See examples/org/spacehq/packetlib/test +See examples/com/github/steveice10/packetlib/test ## Building the Source PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. -Builds can be downloaded **[here](https://build.spacehq.org/job/PacketLib)**. -Javadocs can be found **[here](https://build.spacehq.org/job/PacketLib/javadoc)**. - ## License PacketLib is licensed under the **[MIT license](http://www.opensource.org/licenses/mit-license.html)**. diff --git a/example/org/spacehq/packetlib/test/ClientSessionListener.java b/example/com/github/steveice10/packetlib/test/ClientSessionListener.java similarity index 73% rename from example/org/spacehq/packetlib/test/ClientSessionListener.java rename to example/com/github/steveice10/packetlib/test/ClientSessionListener.java index 28ef14ba..93f88ce7 100644 --- a/example/org/spacehq/packetlib/test/ClientSessionListener.java +++ b/example/com/github/steveice10/packetlib/test/ClientSessionListener.java @@ -1,11 +1,11 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.event.session.ConnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectingEvent; -import org.spacehq.packetlib.event.session.PacketReceivedEvent; -import org.spacehq.packetlib.event.session.PacketSentEvent; -import org.spacehq.packetlib.event.session.SessionAdapter; +import com.github.steveice10.packetlib.event.session.ConnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectingEvent; +import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; +import com.github.steveice10.packetlib.event.session.PacketSentEvent; +import com.github.steveice10.packetlib.event.session.SessionAdapter; public class ClientSessionListener extends SessionAdapter { @Override diff --git a/example/org/spacehq/packetlib/test/PingPacket.java b/example/com/github/steveice10/packetlib/test/PingPacket.java similarity index 74% rename from example/org/spacehq/packetlib/test/PingPacket.java rename to example/com/github/steveice10/packetlib/test/PingPacket.java index b24e8cd5..ec8ad0f9 100644 --- a/example/org/spacehq/packetlib/test/PingPacket.java +++ b/example/com/github/steveice10/packetlib/test/PingPacket.java @@ -1,8 +1,8 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.io.NetInput; -import org.spacehq.packetlib.io.NetOutput; -import org.spacehq.packetlib.packet.Packet; +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.packet.Packet; import java.io.IOException; diff --git a/example/org/spacehq/packetlib/test/PingServerTest.java b/example/com/github/steveice10/packetlib/test/PingServerTest.java similarity index 83% rename from example/org/spacehq/packetlib/test/PingServerTest.java rename to example/com/github/steveice10/packetlib/test/PingServerTest.java index 80fd2878..7daa2b04 100644 --- a/example/org/spacehq/packetlib/test/PingServerTest.java +++ b/example/com/github/steveice10/packetlib/test/PingServerTest.java @@ -1,8 +1,8 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.Client; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.tcp.TcpSessionFactory; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.tcp.TcpSessionFactory; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; diff --git a/example/org/spacehq/packetlib/test/ServerListener.java b/example/com/github/steveice10/packetlib/test/ServerListener.java similarity index 71% rename from example/org/spacehq/packetlib/test/ServerListener.java rename to example/com/github/steveice10/packetlib/test/ServerListener.java index 84814c69..a0694ae1 100644 --- a/example/org/spacehq/packetlib/test/ServerListener.java +++ b/example/com/github/steveice10/packetlib/test/ServerListener.java @@ -1,11 +1,11 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.event.server.ServerAdapter; -import org.spacehq.packetlib.event.server.ServerBoundEvent; -import org.spacehq.packetlib.event.server.ServerClosedEvent; -import org.spacehq.packetlib.event.server.ServerClosingEvent; -import org.spacehq.packetlib.event.server.SessionAddedEvent; -import org.spacehq.packetlib.event.server.SessionRemovedEvent; +import com.github.steveice10.packetlib.event.server.ServerAdapter; +import com.github.steveice10.packetlib.event.server.ServerBoundEvent; +import com.github.steveice10.packetlib.event.server.ServerClosedEvent; +import com.github.steveice10.packetlib.event.server.ServerClosingEvent; +import com.github.steveice10.packetlib.event.server.SessionAddedEvent; +import com.github.steveice10.packetlib.event.server.SessionRemovedEvent; import javax.crypto.SecretKey; diff --git a/example/org/spacehq/packetlib/test/ServerSessionListener.java b/example/com/github/steveice10/packetlib/test/ServerSessionListener.java similarity index 68% rename from example/org/spacehq/packetlib/test/ServerSessionListener.java rename to example/com/github/steveice10/packetlib/test/ServerSessionListener.java index 65b0f9c3..b147bf3c 100644 --- a/example/org/spacehq/packetlib/test/ServerSessionListener.java +++ b/example/com/github/steveice10/packetlib/test/ServerSessionListener.java @@ -1,11 +1,11 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.event.session.ConnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectingEvent; -import org.spacehq.packetlib.event.session.PacketReceivedEvent; -import org.spacehq.packetlib.event.session.PacketSentEvent; -import org.spacehq.packetlib.event.session.SessionAdapter; +import com.github.steveice10.packetlib.event.session.ConnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectingEvent; +import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; +import com.github.steveice10.packetlib.event.session.PacketSentEvent; +import com.github.steveice10.packetlib.event.session.SessionAdapter; public class ServerSessionListener extends SessionAdapter { @Override diff --git a/example/org/spacehq/packetlib/test/TestProtocol.java b/example/com/github/steveice10/packetlib/test/TestProtocol.java similarity index 70% rename from example/org/spacehq/packetlib/test/TestProtocol.java rename to example/com/github/steveice10/packetlib/test/TestProtocol.java index aa0f801d..e6ead1ae 100644 --- a/example/org/spacehq/packetlib/test/TestProtocol.java +++ b/example/com/github/steveice10/packetlib/test/TestProtocol.java @@ -1,13 +1,13 @@ -package org.spacehq.packetlib.test; +package com.github.steveice10.packetlib.test; -import org.spacehq.packetlib.Client; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.crypt.AESEncryption; -import org.spacehq.packetlib.crypt.PacketEncryption; -import org.spacehq.packetlib.packet.DefaultPacketHeader; -import org.spacehq.packetlib.packet.PacketHeader; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.crypt.AESEncryption; +import com.github.steveice10.packetlib.crypt.PacketEncryption; +import com.github.steveice10.packetlib.packet.DefaultPacketHeader; +import com.github.steveice10.packetlib.packet.PacketHeader; +import com.github.steveice10.packetlib.packet.PacketProtocol; import javax.crypto.SecretKey; import java.security.GeneralSecurityException; diff --git a/pom.xml b/pom.xml index 85d4d07c..6cacba9f 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - org.spacehq + com.github.steveice10 packetlib 1.0 jar @@ -37,30 +37,6 @@ - - - spacehq - spacehq-releases - https://repo.spacehq.org/content/repositories/releases/ - - - spacehq - spacehq-snapshots - https://repo.spacehq.org/content/repositories/snapshots/ - - - - - - spacehq-releases - https://repo.spacehq.org/content/repositories/releases/ - - - spacehq-snapshots - https://repo.spacehq.org/content/repositories/snapshots/ - - - io.netty diff --git a/src/main/java/org/spacehq/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java similarity index 91% rename from src/main/java/org/spacehq/packetlib/Client.java rename to src/main/java/com/github/steveice10/packetlib/Client.java index 03411ca1..0757196a 100644 --- a/src/main/java/org/spacehq/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib; +package com.github.steveice10.packetlib; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.packet.PacketProtocol; /** * A client that may connect to a server. diff --git a/src/main/java/org/spacehq/packetlib/ConnectionListener.java b/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/ConnectionListener.java rename to src/main/java/com/github/steveice10/packetlib/ConnectionListener.java index 25027a20..b2e85fd9 100644 --- a/src/main/java/org/spacehq/packetlib/ConnectionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib; +package com.github.steveice10.packetlib; /** * Listens for new sessions to connect. diff --git a/src/main/java/org/spacehq/packetlib/Server.java b/src/main/java/com/github/steveice10/packetlib/Server.java similarity index 92% rename from src/main/java/org/spacehq/packetlib/Server.java rename to src/main/java/com/github/steveice10/packetlib/Server.java index 5300739c..1c47b454 100644 --- a/src/main/java/org/spacehq/packetlib/Server.java +++ b/src/main/java/com/github/steveice10/packetlib/Server.java @@ -1,13 +1,13 @@ -package org.spacehq.packetlib; +package com.github.steveice10.packetlib; -import org.spacehq.packetlib.event.server.ServerBoundEvent; -import org.spacehq.packetlib.event.server.ServerClosedEvent; -import org.spacehq.packetlib.event.server.ServerClosingEvent; -import org.spacehq.packetlib.event.server.ServerEvent; -import org.spacehq.packetlib.event.server.ServerListener; -import org.spacehq.packetlib.event.server.SessionAddedEvent; -import org.spacehq.packetlib.event.server.SessionRemovedEvent; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.event.server.ServerBoundEvent; +import com.github.steveice10.packetlib.event.server.ServerClosedEvent; +import com.github.steveice10.packetlib.event.server.ServerEvent; +import com.github.steveice10.packetlib.event.server.ServerListener; +import com.github.steveice10.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.event.server.SessionAddedEvent; +import com.github.steveice10.packetlib.event.server.SessionRemovedEvent; +import com.github.steveice10.packetlib.event.server.ServerClosingEvent; import java.lang.reflect.Constructor; import java.util.ArrayList; diff --git a/src/main/java/org/spacehq/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java similarity index 95% rename from src/main/java/org/spacehq/packetlib/Session.java rename to src/main/java/com/github/steveice10/packetlib/Session.java index acf7a43c..c8994b1c 100644 --- a/src/main/java/org/spacehq/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -1,9 +1,9 @@ -package org.spacehq.packetlib; +package com.github.steveice10.packetlib; -import org.spacehq.packetlib.event.session.SessionEvent; -import org.spacehq.packetlib.event.session.SessionListener; -import org.spacehq.packetlib.packet.Packet; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.event.session.SessionListener; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.event.session.SessionEvent; import java.net.SocketAddress; import java.util.List; diff --git a/src/main/java/org/spacehq/packetlib/SessionFactory.java b/src/main/java/com/github/steveice10/packetlib/SessionFactory.java similarity index 92% rename from src/main/java/org/spacehq/packetlib/SessionFactory.java rename to src/main/java/com/github/steveice10/packetlib/SessionFactory.java index 66140a71..5155af3c 100644 --- a/src/main/java/org/spacehq/packetlib/SessionFactory.java +++ b/src/main/java/com/github/steveice10/packetlib/SessionFactory.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib; +package com.github.steveice10.packetlib; /** * A factory for creating sessions. diff --git a/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java b/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java rename to src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java index 8d5d8fd7..de75ace0 100644 --- a/src/main/java/org/spacehq/packetlib/crypt/AESEncryption.java +++ b/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.crypt; +package com.github.steveice10.packetlib.crypt; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; diff --git a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java b/src/main/java/com/github/steveice10/packetlib/crypt/PacketEncryption.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java rename to src/main/java/com/github/steveice10/packetlib/crypt/PacketEncryption.java index 0e5f949f..371ca240 100644 --- a/src/main/java/org/spacehq/packetlib/crypt/PacketEncryption.java +++ b/src/main/java/com/github/steveice10/packetlib/crypt/PacketEncryption.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.crypt; +package com.github.steveice10.packetlib.crypt; /** * An interface for encrypting packets. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerAdapter.java similarity index 90% rename from src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerAdapter.java index 6c6b6518..64c99bc3 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerAdapter.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; /** * An adapter for picking server events to listen for. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerBoundEvent.java similarity index 86% rename from src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerBoundEvent.java index 15fef805..54cb07a8 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerBoundEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerBoundEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; -import org.spacehq.packetlib.Server; +import com.github.steveice10.packetlib.Server; /** * Called when the server is bound to its host and port. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerClosedEvent.java similarity index 85% rename from src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerClosedEvent.java index da8d9dcc..c6251c2f 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerClosedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerClosedEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; -import org.spacehq.packetlib.Server; +import com.github.steveice10.packetlib.Server; /** * Called when the server is closed. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerClosingEvent.java similarity index 85% rename from src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerClosingEvent.java index 2d4cbff3..ebcb6d14 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerClosingEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerClosingEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; -import org.spacehq.packetlib.Server; +import com.github.steveice10.packetlib.Server; /** * Called when the server is about to close. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerEvent.java similarity index 80% rename from src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerEvent.java index cf858eef..2037d5bb 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerEvent.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; /** * An event relating to servers. diff --git a/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java b/src/main/java/com/github/steveice10/packetlib/event/server/ServerListener.java similarity index 94% rename from src/main/java/org/spacehq/packetlib/event/server/ServerListener.java rename to src/main/java/com/github/steveice10/packetlib/event/server/ServerListener.java index 45ea2e7b..6c32331f 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/ServerListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/ServerListener.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; /** * A listener for listening to server events. diff --git a/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/SessionAddedEvent.java similarity index 86% rename from src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/SessionAddedEvent.java index 1e526c61..3adb49c0 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/SessionAddedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/SessionAddedEvent.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.Session; /** * Called when a session is added to the server. diff --git a/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/server/SessionRemovedEvent.java similarity index 86% rename from src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/server/SessionRemovedEvent.java index a2bd6571..8bb49bc0 100644 --- a/src/main/java/org/spacehq/packetlib/event/server/SessionRemovedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/server/SessionRemovedEvent.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.event.server; +package com.github.steveice10.packetlib.event.server; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.Session; /** * Called when a session is removed and disconnected from the server. diff --git a/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/ConnectedEvent.java similarity index 85% rename from src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/ConnectedEvent.java index 0f71d6b8..1e312e70 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/ConnectedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/ConnectedEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Session; /** * Called when the session connects. diff --git a/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java similarity index 94% rename from src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java index c9d44d53..463ed042 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/DisconnectedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Session; /** * Called when the session is disconnected. diff --git a/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java similarity index 94% rename from src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java index 53e25599..0c9929e4 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/DisconnectingEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Session; /** * Called when the session is about to disconnect. diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java similarity index 89% rename from src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java index db43b86e..a724ec8d 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.packet.Packet; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.Session; /** * Called when the session receives a packet. diff --git a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java similarity index 89% rename from src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java index 765c387e..49fd306c 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.packet.Packet; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.Session; /** * Called when the session has sent a packet. diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java similarity index 90% rename from src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java rename to src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java index 7f8014dc..b5cb1cff 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; /** * An adapter for picking session events to listen for. diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionEvent.java similarity index 80% rename from src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java rename to src/main/java/com/github/steveice10/packetlib/event/session/SessionEvent.java index 20bc7c4f..bcd2b727 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionEvent.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; /** * An event relating to sessions. diff --git a/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java similarity index 94% rename from src/main/java/org/spacehq/packetlib/event/session/SessionListener.java rename to src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java index b40a66d0..ce6f5022 100644 --- a/src/main/java/org/spacehq/packetlib/event/session/SessionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.event.session; +package com.github.steveice10.packetlib.event.session; /** * A listener for listening to session events. diff --git a/src/main/java/org/spacehq/packetlib/io/NetInput.java b/src/main/java/com/github/steveice10/packetlib/io/NetInput.java similarity index 99% rename from src/main/java/org/spacehq/packetlib/io/NetInput.java rename to src/main/java/com/github/steveice10/packetlib/io/NetInput.java index fbc42327..b271c38a 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/NetInput.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.io; +package com.github.steveice10.packetlib.io; import java.io.IOException; import java.util.UUID; diff --git a/src/main/java/org/spacehq/packetlib/io/NetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java similarity index 99% rename from src/main/java/org/spacehq/packetlib/io/NetOutput.java rename to src/main/java/com/github/steveice10/packetlib/io/NetOutput.java index 7e6b3dda..d50a69f6 100644 --- a/src/main/java/org/spacehq/packetlib/io/NetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.io; +package com.github.steveice10.packetlib.io; import java.io.IOException; import java.util.UUID; diff --git a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java similarity index 98% rename from src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java rename to src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java index 9c71c128..15b4bbb6 100644 --- a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.io.buffer; +package com.github.steveice10.packetlib.io.buffer; -import org.spacehq.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetInput; import java.io.IOException; import java.nio.ByteBuffer; diff --git a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java rename to src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java index be46f7f2..a9e9e6ff 100644 --- a/src/main/java/org/spacehq/packetlib/io/buffer/ByteBufferNetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.io.buffer; +package com.github.steveice10.packetlib.io.buffer; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; import java.nio.ByteBuffer; diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java similarity index 98% rename from src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java rename to src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java index 3433f4fe..197f913a 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.io.stream; +package com.github.steveice10.packetlib.io.stream; -import org.spacehq.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetInput; import java.io.EOFException; import java.io.IOException; diff --git a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java rename to src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java index 29010791..bd6ae79a 100644 --- a/src/main/java/org/spacehq/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java @@ -1,6 +1,6 @@ -package org.spacehq.packetlib.io.stream; +package com.github.steveice10.packetlib.io.stream; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java b/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java similarity index 88% rename from src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java rename to src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java index 99972adb..e20dc812 100644 --- a/src/main/java/org/spacehq/packetlib/packet/DefaultPacketHeader.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.packet; +package com.github.steveice10.packetlib.packet; -import org.spacehq.packetlib.io.NetInput; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; diff --git a/src/main/java/org/spacehq/packetlib/packet/Packet.java b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java similarity index 85% rename from src/main/java/org/spacehq/packetlib/packet/Packet.java rename to src/main/java/com/github/steveice10/packetlib/packet/Packet.java index baf51cb4..22fa968f 100644 --- a/src/main/java/org/spacehq/packetlib/packet/Packet.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.packet; +package com.github.steveice10.packetlib.packet; -import org.spacehq.packetlib.io.NetInput; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java similarity index 92% rename from src/main/java/org/spacehq/packetlib/packet/PacketHeader.java rename to src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java index 3176a281..16f1db84 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketHeader.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.packet; +package com.github.steveice10.packetlib.packet; -import org.spacehq.packetlib.io.NetInput; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; diff --git a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java similarity index 95% rename from src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java rename to src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index d7d716f7..f33172cc 100644 --- a/src/main/java/org/spacehq/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -1,9 +1,9 @@ -package org.spacehq.packetlib.packet; +package com.github.steveice10.packetlib.packet; -import org.spacehq.packetlib.Client; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.crypt.PacketEncryption; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.crypt.PacketEncryption; import java.lang.reflect.Constructor; import java.util.HashMap; diff --git a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java similarity index 91% rename from src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java rename to src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java index ff86eda9..77130135 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/ProxyOioChannelFactory.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java @@ -1,4 +1,4 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; import io.netty.channel.ChannelFactory; import io.netty.channel.socket.oio.OioSocketChannel; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java similarity index 96% rename from src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index f1cac837..1b9e8cfe 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -1,5 +1,6 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -11,8 +12,7 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.concurrent.Future; -import org.spacehq.packetlib.Client; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.Client; import javax.naming.directory.InitialDirContext; import java.net.Proxy; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java similarity index 96% rename from src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java index e0eb4a0d..35650af8 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java @@ -1,5 +1,8 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.ConnectionListener; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -12,9 +15,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; -import org.spacehq.packetlib.ConnectionListener; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.packet.PacketProtocol; import java.net.InetSocketAddress; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java similarity index 76% rename from src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 83192225..8420fae3 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -1,15 +1,15 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.event.session.PacketReceivedEvent; -import org.spacehq.packetlib.io.NetInput; -import org.spacehq.packetlib.io.NetOutput; -import org.spacehq.packetlib.packet.Packet; -import org.spacehq.packetlib.tcp.io.ByteBufNetInput; -import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; import java.util.List; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java similarity index 92% rename from src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index 6568f9dd..69c4b7b1 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -1,13 +1,13 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.DecoderException; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.tcp.io.ByteBufNetInput; -import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; import java.util.List; import java.util.zip.Deflater; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java similarity index 95% rename from src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java index 07daf966..7f7d243e 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java @@ -1,9 +1,9 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; -import org.spacehq.packetlib.Session; +import com.github.steveice10.packetlib.Session; import java.util.List; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java similarity index 90% rename from src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index 90eef149..92bef3a0 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -1,13 +1,13 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.CorruptedFrameException; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.tcp.io.ByteBufNetInput; -import org.spacehq.packetlib.tcp.io.ByteBufNetOutput; +import com.github.steveice10.packetlib.Session; import java.util.List; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java similarity index 84% rename from src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java index f9564bab..b4bd2012 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java @@ -1,8 +1,8 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.channel.ChannelHandlerContext; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.packet.PacketProtocol; import java.util.Map; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java similarity index 94% rename from src/main/java/org/spacehq/packetlib/tcp/TcpSession.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 5773b29d..b1cd5b17 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -1,5 +1,11 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.event.session.DisconnectingEvent; +import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; +import com.github.steveice10.packetlib.event.session.SessionListener; +import com.github.steveice10.packetlib.packet.Packet; +import com.github.steveice10.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.event.session.SessionEvent; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -10,16 +16,10 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.event.session.ConnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectedEvent; -import org.spacehq.packetlib.event.session.DisconnectingEvent; -import org.spacehq.packetlib.event.session.PacketReceivedEvent; -import org.spacehq.packetlib.event.session.PacketSentEvent; -import org.spacehq.packetlib.event.session.SessionEvent; -import org.spacehq.packetlib.event.session.SessionListener; -import org.spacehq.packetlib.packet.Packet; -import org.spacehq.packetlib.packet.PacketProtocol; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.ConnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectedEvent; +import com.github.steveice10.packetlib.event.session.PacketSentEvent; import java.net.ConnectException; import java.net.SocketAddress; diff --git a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java similarity index 70% rename from src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java index f8781d1d..595b7100 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java @@ -1,10 +1,10 @@ -package org.spacehq.packetlib.tcp; +package com.github.steveice10.packetlib.tcp; -import org.spacehq.packetlib.Client; -import org.spacehq.packetlib.ConnectionListener; -import org.spacehq.packetlib.Server; -import org.spacehq.packetlib.Session; -import org.spacehq.packetlib.SessionFactory; +import com.github.steveice10.packetlib.SessionFactory; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.ConnectionListener; +import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.Session; import java.net.Proxy; diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java similarity index 98% rename from src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java rename to src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java index 85e33ff9..75708f71 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.tcp.io; +package com.github.steveice10.packetlib.tcp.io; +import com.github.steveice10.packetlib.io.NetInput; import io.netty.buffer.ByteBuf; -import org.spacehq.packetlib.io.NetInput; import java.io.IOException; import java.util.UUID; diff --git a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java similarity index 97% rename from src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java rename to src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java index cd245738..167890de 100644 --- a/src/main/java/org/spacehq/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java @@ -1,7 +1,7 @@ -package org.spacehq.packetlib.tcp.io; +package com.github.steveice10.packetlib.tcp.io; import io.netty.buffer.ByteBuf; -import org.spacehq.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; import java.util.UUID; From bdefaa60c3dbeaf6443271fc87aa874dfb03ef1a Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 1 Mar 2017 16:14:22 -0800 Subject: [PATCH 058/180] Bump version for development. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6cacba9f..103a585c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.steveice10 packetlib - 1.0 + 1.1-SNAPSHOT jar PacketLib From a17d4769e8459e7b6a7bba469c9c28aa178e020b Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 2 Mar 2017 00:01:58 -0800 Subject: [PATCH 059/180] Update license year. --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index e69695f5..afe6f3a9 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2013-2015 Steveice10 +Copyright (C) 2013-2017 Steveice10 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From e8a86dafcb99f4952c423ee9a2bf66de95c7c245 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 26 Jun 2017 15:58:08 -0700 Subject: [PATCH 060/180] Fire event before a packet is sent, allowing the operation to be modified or cancelled. --- .../event/session/PacketSendingEvent.java | 81 +++++++++++++++++++ .../event/session/SessionListener.java | 7 ++ .../steveice10/packetlib/tcp/TcpSession.java | 38 +++++---- 3 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/event/session/PacketSendingEvent.java diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketSendingEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSendingEvent.java new file mode 100644 index 00000000..c5814a4f --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSendingEvent.java @@ -0,0 +1,81 @@ +package com.github.steveice10.packetlib.event.session; + +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; + +/** + * Called when the session is sending a packet. + */ +public class PacketSendingEvent implements SessionEvent { + private Session session; + private Packet packet; + private boolean cancelled = false; + + /** + * Creates a new PacketSendingEvent instance. + * + * @param session Session sending the packet. + * @param packet Packet being sent. + */ + public PacketSendingEvent(Session session, Packet packet) { + this.session = session; + this.packet = packet; + } + + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the packet involved in this event as the required type. + * + * @param Type of the packet. + * @return The event's packet as the required type. + * @throws IllegalStateException If the packet's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getPacket() { + try { + return (T) this.packet; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); + } + } + + /** + * Sets the packet that should be sent as a result of this event. + * + * @param packet The packet to send. + */ + public void setPacket(Packet packet) { + this.packet = packet; + } + + /** + * Gets whether the event has been cancelled. + * + * @return Whether the event has been cancelled. + */ + public boolean isCancelled() { + return this.cancelled; + } + + /** + * Sets whether the event should be cancelled. + * + * @param cancelled Whether the event should be cancelled. + */ + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public void call(SessionListener listener) { + listener.packetSending(this); + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java index ce6f5022..23951cc8 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java @@ -11,6 +11,13 @@ public interface SessionListener { */ public void packetReceived(PacketReceivedEvent event); + /** + * Called when a session is sending a packet. + * + * @param event Data relating to the event. + */ + public void packetSending(PacketSendingEvent event); + /** * Called when a session sends a packet. * diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index b1cd5b17..65b9e51b 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -2,6 +2,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; +import com.github.steveice10.packetlib.event.session.PacketSendingEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.PacketProtocol; @@ -203,26 +204,33 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } @Override - public void send(final Packet packet) { + public void send(Packet packet) { if(this.channel == null) { return; } - ChannelFuture future = this.channel.writeAndFlush(packet).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(future.isSuccess()) { - callEvent(new PacketSentEvent(TcpSession.this, packet)); - } else { - exceptionCaught(null, future.cause()); - } - } - }); + PacketSendingEvent sendingEvent = new PacketSendingEvent(this, packet); + this.callEvent(sendingEvent); - if(packet.isPriority()) { - try { - future.await(); - } catch(InterruptedException e) { + if(!sendingEvent.isCancelled()) { + final Packet toSend = sendingEvent.getPacket(); + + ChannelFuture future = this.channel.writeAndFlush(toSend).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if(future.isSuccess()) { + callEvent(new PacketSentEvent(TcpSession.this, toSend)); + } else { + exceptionCaught(null, future.cause()); + } + } + }); + + if(toSend.isPriority()) { + try { + future.await(); + } catch(InterruptedException e) { + } } } } From c5880f0627f640c81e61c60b5c535b74b30b0c78 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 27 Jun 2017 13:12:02 -0700 Subject: [PATCH 061/180] Add packetSending stub to SessionAdapter. --- .../steveice10/packetlib/event/session/SessionAdapter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java index b5cb1cff..3d20e8ae 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java @@ -8,6 +8,10 @@ public class SessionAdapter implements SessionListener { public void packetReceived(PacketReceivedEvent event) { } + @Override + public void packetSending(PacketSendingEvent event) { + } + @Override public void packetSent(PacketSentEvent event) { } From ca0dec4a2d419352530e1816cd24379db4c0897b Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 1 Sep 2017 12:55:00 -0700 Subject: [PATCH 062/180] Format code. --- .../steveice10/packetlib/ConnectionListener.java | 4 ++-- .../java/com/github/steveice10/packetlib/Server.java | 4 ++-- .../java/com/github/steveice10/packetlib/Session.java | 2 +- .../packetlib/event/session/PacketReceivedEvent.java | 2 +- .../packetlib/event/session/PacketSentEvent.java | 2 +- .../steveice10/packetlib/tcp/TcpClientSession.java | 4 ++-- .../steveice10/packetlib/tcp/TcpPacketCodec.java | 2 +- .../steveice10/packetlib/tcp/TcpPacketEncryptor.java | 2 +- .../steveice10/packetlib/tcp/TcpPacketSizer.java | 2 +- .../github/steveice10/packetlib/tcp/TcpSession.java | 10 +++++----- .../steveice10/packetlib/tcp/TcpSessionFactory.java | 2 +- .../steveice10/packetlib/tcp/io/ByteBufNetOutput.java | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java b/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java index b2e85fd9..96cc5bd5 100644 --- a/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java @@ -40,7 +40,7 @@ public interface ConnectionListener { /** * Binds the listener to its host and port. * - * @param wait Whether to wait for the listener to finish binding. + * @param wait Whether to wait for the listener to finish binding. * @param callback Callback to call when the listener has finished binding. */ public void bind(boolean wait, Runnable callback); @@ -60,7 +60,7 @@ public interface ConnectionListener { /** * Closes the listener. * - * @param wait Whether to wait for the listener to finish closing. + * @param wait Whether to wait for the listener to finish closing. * @param callback Callback to call when the listener has finished closing. */ public void close(boolean wait, Runnable callback); diff --git a/src/main/java/com/github/steveice10/packetlib/Server.java b/src/main/java/com/github/steveice10/packetlib/Server.java index 1c47b454..b0e84bee 100644 --- a/src/main/java/com/github/steveice10/packetlib/Server.java +++ b/src/main/java/com/github/steveice10/packetlib/Server.java @@ -2,12 +2,12 @@ package com.github.steveice10.packetlib; import com.github.steveice10.packetlib.event.server.ServerBoundEvent; import com.github.steveice10.packetlib.event.server.ServerClosedEvent; +import com.github.steveice10.packetlib.event.server.ServerClosingEvent; import com.github.steveice10.packetlib.event.server.ServerEvent; import com.github.steveice10.packetlib.event.server.ServerListener; -import com.github.steveice10.packetlib.packet.PacketProtocol; import com.github.steveice10.packetlib.event.server.SessionAddedEvent; import com.github.steveice10.packetlib.event.server.SessionRemovedEvent; -import com.github.steveice10.packetlib.event.server.ServerClosingEvent; +import com.github.steveice10.packetlib.packet.PacketProtocol; import java.lang.reflect.Constructor; import java.util.ArrayList; diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index c8994b1c..ec07bf51 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -1,9 +1,9 @@ package com.github.steveice10.packetlib; +import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.PacketProtocol; -import com.github.steveice10.packetlib.event.session.SessionEvent; import java.net.SocketAddress; import java.util.List; diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java index a724ec8d..996e43b1 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib.event.session; -import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; /** * Called when the session receives a packet. diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java index 49fd306c..17bda0bd 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib.event.session; -import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; /** * Called when the session has sent a packet. diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 1b9e8cfe..dce75622 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -1,5 +1,6 @@ package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -12,7 +13,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.util.concurrent.Future; -import com.github.steveice10.packetlib.Client; import javax.naming.directory.InitialDirContext; import java.net.Proxy; @@ -80,7 +80,7 @@ public class TcpClientSession extends TcpSession { environment.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); environment.put("java.naming.provider.url", "dns:"); - String[] result = new InitialDirContext(environment).getAttributes(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, new String[] { "SRV" }).get("srv").get().toString().split(" ", 4); + String[] result = new InitialDirContext(environment).getAttributes(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, new String[] {"SRV"}).get("srv").get().toString().split(" ", 4); host = result[3]; port = Integer.parseInt(result[2]); } catch(Throwable t) { diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 8420fae3..88ed3dc3 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -1,10 +1,10 @@ package com.github.steveice10.packetlib.tcp; -import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.io.NetInput; import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java index 7f7d243e..a58e52eb 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java @@ -1,9 +1,9 @@ package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Session; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; -import com.github.steveice10.packetlib.Session; import java.util.List; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index 92bef3a0..65e633ca 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -1,5 +1,6 @@ package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import io.netty.buffer.ByteBuf; @@ -7,7 +8,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.CorruptedFrameException; -import com.github.steveice10.packetlib.Session; import java.util.List; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 65b9e51b..4fa23ef8 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -1,12 +1,16 @@ package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.ConnectedEvent; +import com.github.steveice10.packetlib.event.session.DisconnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.event.session.PacketSendingEvent; +import com.github.steveice10.packetlib.event.session.PacketSentEvent; +import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.PacketProtocol; -import com.github.steveice10.packetlib.event.session.SessionEvent; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -17,10 +21,6 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.event.session.ConnectedEvent; -import com.github.steveice10.packetlib.event.session.DisconnectedEvent; -import com.github.steveice10.packetlib.event.session.PacketSentEvent; import java.net.ConnectException; import java.net.SocketAddress; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java index 595b7100..d94bbb63 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java @@ -1,10 +1,10 @@ package com.github.steveice10.packetlib.tcp; -import com.github.steveice10.packetlib.SessionFactory; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.ConnectionListener; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.SessionFactory; import java.net.Proxy; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java index 167890de..bd60d186 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib.tcp.io; -import io.netty.buffer.ByteBuf; import com.github.steveice10.packetlib.io.NetOutput; +import io.netty.buffer.ByteBuf; import java.io.IOException; import java.util.UUID; From 73cd1fdb3863ba76b3eb8a8abc0a51afa755052a Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 14 Jan 2018 11:37:31 -0800 Subject: [PATCH 063/180] Bump version to 1.1 for release. --- LICENSE.txt | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index afe6f3a9..10a55911 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2013-2017 Steveice10 +Copyright (C) 2013-2018 Steveice10 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/pom.xml b/pom.xml index 103a585c..aca9ae02 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.steveice10 packetlib - 1.1-SNAPSHOT + 1.1 jar PacketLib From 0d32cd5ddd854113526d9ca6a597ee06808939b0 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 14 Jan 2018 11:38:28 -0800 Subject: [PATCH 064/180] Bump version for development. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aca9ae02..58c31785 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.steveice10 packetlib - 1.1 + 1.2-SNAPSHOT jar PacketLib From 880393f92ab2e112713b1d1262910e20883a190e Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Wed, 31 Jan 2018 22:49:08 -0800 Subject: [PATCH 065/180] Clean up pom.xml --- pom.xml | 78 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index 58c31785..a09d7850 100644 --- a/pom.xml +++ b/pom.xml @@ -2,6 +2,7 @@ 4.0.0 + com.github.steveice10 packetlib 1.2-SNAPSHOT @@ -37,6 +38,11 @@ + + GitHub + https://github.com/Steveice10/PacketLib/issues + + io.netty @@ -47,12 +53,26 @@ clean install - ${basedir}/src/main/java + + org.apache.maven.plugins + maven-clean-plugin + 3.0.0 + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.2 + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.7.0 1.7 1.7 @@ -60,8 +80,21 @@ org.apache.maven.plugins - maven-jar-plugin - 3.0.2 + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + aggregate + jar + + + + + public + false + org.apache.maven.plugins @@ -78,42 +111,13 @@ org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 - - - attach-javadocs - - jar - - - + maven-install-plugin + 2.5.2 org.apache.maven.plugins - maven-shade-plugin - 2.4.3 - - - package - - shade - - - - - ${project.build.directory}/dependency-reduced-pom.xml - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - + maven-deploy-plugin + 2.8.2 From a100a4fbbf38f03aef6cd3bc2c7f31aa40ba9216 Mon Sep 17 00:00:00 2001 From: sgdc3 Date: Thu, 1 Feb 2018 19:13:37 +0100 Subject: [PATCH 066/180] Pom enhancements --- pom.xml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a09d7850..d3e0f1bc 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ UTF-8 + 1.7 @@ -48,6 +49,7 @@ io.netty netty-all 4.1.4.Final + compile @@ -74,8 +76,19 @@ maven-compiler-plugin 3.7.0 - 1.7 - 1.7 + ${jdk.version} + ${jdk.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20.1 + + + true + + -Dfile.encoding=${project.build.sourceEncoding} @{argLine} From bc07f0f1360991504b381e90f14d5a8b5466974f Mon Sep 17 00:00:00 2001 From: sgdc3 Date: Thu, 1 Feb 2018 19:14:51 +0100 Subject: [PATCH 067/180] Bump netty version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d3e0f1bc..3d31e490 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ io.netty netty-all - 4.1.4.Final + 4.1.20.Final compile From 586157506d546ed3acb6d2a8cb99f9d10894d16d Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 6 Feb 2018 14:25:56 -0800 Subject: [PATCH 068/180] Bump version for release 1.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3d31e490..e9a29c20 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.2-SNAPSHOT + 1.2 jar PacketLib From ad0a450dc0a4d997d344fe5ea9cc60c6d871dcd3 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 6 Feb 2018 14:26:53 -0800 Subject: [PATCH 069/180] Bump version for development. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e9a29c20..f7f49b77 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.2 + 1.3-SNAPSHOT jar PacketLib From d81fdd0632d633e7ea1f1ccd5a5866e637dbfe73 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 3 Jun 2018 10:44:59 -0700 Subject: [PATCH 070/180] Update netty version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7f49b77..e724b670 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ io.netty netty-all - 4.1.20.Final + 4.1.25.Final compile From d6ed28cbd0cb73a438c2e05afcd89d4230a9c8bd Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 3 Jun 2018 10:45:28 -0700 Subject: [PATCH 071/180] Bump version to 1.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e724b670..488023cf 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.3-SNAPSHOT + 1.3 jar PacketLib From 26b127a4cdfc2f5f11f889884e7859bcfcc19f07 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 3 Jun 2018 10:46:04 -0700 Subject: [PATCH 072/180] Bump version to 1.4-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 488023cf..6f8a5780 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.3 + 1.4-SNAPSHOT jar PacketLib From 3e07b2ebf3c89524dc1f17e30e170e8bdc050a69 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 2 Jul 2018 15:23:35 -0700 Subject: [PATCH 073/180] Add argLine to properties. --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 6f8a5780..3ecd6786 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ UTF-8 1.7 + From 9ec1cc121da21a143cc67febc4f5e7914b3e7ce8 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 4 Jul 2018 13:37:09 -0700 Subject: [PATCH 074/180] Fix typo and link to example in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 118e10fc..dfa4ffd0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PacketLib -PacketLib is a library for packet-based networking between clients and servers It was made as a basis for other projects involving packet networking. +PacketLib is a library for packet-based networking between clients and servers. It was made as a basis for other projects involving packet networking. ## Test Example -See examples/com/github/steveice10/packetlib/test +See [examples/com/github/steveice10/packetlib/test](https://github.com/Steveice10/PacketLib/tree/master/example/com/github/steveice10/packetlib/test) ## Building the Source PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. From 2e53f6ba1fcf15f48b7678adbf29fdd8d879bf28 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 20 Aug 2018 12:22:08 -0700 Subject: [PATCH 075/180] Update surefire plugin to 2.22.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3ecd6786..d56fe89b 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20.1 + 2.22.0 true From 988d411d9646709ca190acd264492af9f9ed7e25 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 29 Aug 2018 19:24:08 -0700 Subject: [PATCH 076/180] Fix documentation mistake. --- .../com/github/steveice10/packetlib/packet/PacketHeader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java index 16f1db84..6129a7ab 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java @@ -35,7 +35,7 @@ public interface PacketHeader { * Reads the length of a packet from the given input. * * @param in Input to read from. - * @param available Number of available bytes in the NetInput. + * @param available Number of packet bytes available after the length. * @return The resulting packet length. * @throws java.io.IOException If an I/O error occurs. */ From 1d5a0ad81bfd99325a1db9991ced09ab773f55c8 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 6 Sep 2018 10:27:21 -0700 Subject: [PATCH 077/180] Use Cipher mode constants. --- .../com/github/steveice10/packetlib/crypt/AESEncryption.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java b/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java index de75ace0..7dc26a90 100644 --- a/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java +++ b/src/main/java/com/github/steveice10/packetlib/crypt/AESEncryption.java @@ -20,9 +20,9 @@ public class AESEncryption implements PacketEncryption { */ public AESEncryption(Key key) throws GeneralSecurityException { this.inCipher = Cipher.getInstance("AES/CFB8/NoPadding"); - this.inCipher.init(2, key, new IvParameterSpec(key.getEncoded())); + this.inCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(key.getEncoded())); this.outCipher = Cipher.getInstance("AES/CFB8/NoPadding"); - this.outCipher.init(1, key, new IvParameterSpec(key.getEncoded())); + this.outCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(key.getEncoded())); } @Override From 1431dfcaea6c46c0bd972409380b178215450966 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Tue, 27 Aug 2019 23:53:41 -0700 Subject: [PATCH 078/180] Add CI action. --- .github/workflows/maven.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 00000000..73ac2523 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,17 @@ +name: Java CI + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn package --file pom.xml From 32247f309878258beadecee597c90739da417e6d Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 20 Oct 2019 20:18:58 -0700 Subject: [PATCH 079/180] Remove dot from end of host in SRV records. --- .../com/github/steveice10/packetlib/tcp/TcpClientSession.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index dce75622..ae0e2223 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -83,6 +83,9 @@ public class TcpClientSession extends TcpSession { String[] result = new InitialDirContext(environment).getAttributes(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, new String[] {"SRV"}).get("srv").get().toString().split(" ", 4); host = result[3]; port = Integer.parseInt(result[2]); + if(host.endsWith(".")) { + host = host.substring(0, host.length() - 1); + } } catch(Throwable t) { } From c0fae1d4d5bab86e4e7ccd515e2e65623ca32c17 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 20 Oct 2019 20:20:01 -0700 Subject: [PATCH 080/180] Update netty version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d56fe89b..6292b67e 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ io.netty netty-all - 4.1.25.Final + 4.1.42.Final compile From a5712ac9b0261b7171f2dce473dd9eea4bf3fc7f Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 20 Oct 2019 20:20:46 -0700 Subject: [PATCH 081/180] Bump version to 1.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6292b67e..23952ecd 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.4-SNAPSHOT + 1.4 jar PacketLib From d05bdadbbfff0eb613049f29634fc2ecc3d3d280 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 20 Oct 2019 20:22:01 -0700 Subject: [PATCH 082/180] Bump version to 1.5-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 23952ecd..31fe4166 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.4 + 1.5-SNAPSHOT jar PacketLib From d725ce0d79bc6aeb148b2ca103076005ea7b60fe Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 26 Feb 2020 18:11:23 -0800 Subject: [PATCH 083/180] Implement proper NIO proxy support and remove synchronous support from send/disconnect. --- pom.xml | 2 +- .../steveice10/packetlib/ProxyInfo.java | 106 ++++++++++++++++++ .../github/steveice10/packetlib/Session.java | 30 +++-- .../steveice10/packetlib/packet/Packet.java | 6 +- .../packetlib/tcp/ProxyOioChannelFactory.java | 20 ---- .../packetlib/tcp/TcpClientSession.java | 65 +++++++---- .../steveice10/packetlib/tcp/TcpSession.java | 38 ++----- .../packetlib/tcp/TcpSessionFactory.java | 7 +- 8 files changed, 178 insertions(+), 96 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/ProxyInfo.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java diff --git a/pom.xml b/pom.xml index 31fe4166..36fa8cae 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ io.netty netty-all - 4.1.42.Final + 4.1.45.Final compile diff --git a/src/main/java/com/github/steveice10/packetlib/ProxyInfo.java b/src/main/java/com/github/steveice10/packetlib/ProxyInfo.java new file mode 100644 index 00000000..90e6544f --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/ProxyInfo.java @@ -0,0 +1,106 @@ +package com.github.steveice10.packetlib; + +import java.net.SocketAddress; + +/** + * Information describing a network proxy. + */ +public class ProxyInfo { + private Type type; + private SocketAddress address; + private boolean authenticated; + private String username; + private String password; + + /** + * Creates a new unauthenticated ProxyInfo instance. + * + * @param type Type of proxy. + * @param address Network address of the proxy. + */ + public ProxyInfo(Type type, SocketAddress address) { + this.type = type; + this.address = address; + this.authenticated = false; + } + + /** + * Creates a new authenticated ProxyInfo instance. + * + * @param type Type of proxy. + * @param address Network address of the proxy. + * @param username Username to authenticate with. + * @param password Password to authenticate with. + */ + public ProxyInfo(Type type, SocketAddress address, String username, String password) { + this(type, address); + this.authenticated = true; + this.username = username; + this.password = password; + } + + /** + * Gets the proxy's type. + * + * @return The proxy's type. + */ + public Type getType() { + return this.type; + } + + /** + * Gets the proxy's network address. + * + * @return The proxy's network address. + */ + public SocketAddress getAddress() { + return this.address; + } + + /** + * Gets whether the proxy is authenticated with. + * + * @return Whether to authenticate with the proxy. + */ + public boolean isAuthenticated() { + return this.authenticated; + } + + /** + * Gets the proxy's authentication username. + * + * @return The username to authenticate with. + */ + public String getUsername() { + return this.username; + } + + /** + * Gets the proxy's authentication password. + * + * @return The password to authenticate with. + */ + public String getPassword() { + return this.password; + } + + /** + * Supported proxy types. + */ + public enum Type { + /** + * HTTP proxy. + */ + HTTP, + + /** + * SOCKS4 proxy. + */ + SOCKS4, + + /** + * SOCKS5 proxy. + */ + SOCKS5; + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index ec07bf51..45a8a06f 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -89,6 +89,19 @@ public interface Session { */ public T getFlag(String key); + /** + * Gets the value of the given flag as an instance of the given type. If this + * session belongs to a server, the server's flags will be checked for the flag + * as well. If no flag is found, the specified default value will be returned. + * + * @param Type of the flag. + * @param key Key of the flag. + * @param def Default value of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + public T getFlag(String key, T def); + /** * Sets the value of a flag. This does not change a server's flags if this session * belongs to a server. @@ -203,14 +216,6 @@ public interface Session { */ public void disconnect(String reason); - /** - * Disconnects the session. - * - * @param reason Reason for disconnecting. - * @param wait Whether to wait for the session to be disconnected. - */ - public void disconnect(String reason, boolean wait); - /** * Disconnects the session. * @@ -218,13 +223,4 @@ public interface Session { * @param cause Throwable responsible for disconnecting. */ public void disconnect(String reason, Throwable cause); - - /** - * Disconnects the session. - * - * @param reason Reason for disconnecting. - * @param cause Throwable responsible for disconnecting. - * @param wait Whether to wait for the session to be disconnected. - */ - public void disconnect(String reason, Throwable cause, boolean wait); } diff --git a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java index 22fa968f..139bd7e4 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java @@ -26,9 +26,9 @@ public interface Packet { public void write(NetOutput out) throws IOException; /** - * Gets whether the packet has handling and writing priority. - * If the result is true, the thread will wait for the packet to finish writing - * when writing and the packet will be handled immediately after reading it. + * Gets whether the packet has handling priority. + * If the result is true, the packet will be handled immediately after being + * decoded. * * @return Whether the packet has priority. */ diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java deleted file mode 100644 index 77130135..00000000 --- a/src/main/java/com/github/steveice10/packetlib/tcp/ProxyOioChannelFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.steveice10.packetlib.tcp; - -import io.netty.channel.ChannelFactory; -import io.netty.channel.socket.oio.OioSocketChannel; - -import java.net.Proxy; -import java.net.Socket; - -public class ProxyOioChannelFactory implements ChannelFactory { - private Proxy proxy; - - public ProxyOioChannelFactory(Proxy proxy) { - this.proxy = proxy; - } - - @Override - public OioSocketChannel newChannel() { - return new OioSocketChannel(new Socket(this.proxy)); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index ae0e2223..fdbe422d 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; @@ -10,21 +11,22 @@ import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.proxy.HttpProxyHandler; +import io.netty.handler.proxy.Socks4ProxyHandler; +import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.util.concurrent.Future; import javax.naming.directory.InitialDirContext; -import java.net.Proxy; import java.util.Hashtable; public class TcpClientSession extends TcpSession { private Client client; - private Proxy proxy; + private ProxyInfo proxy; private EventLoopGroup group; - public TcpClientSession(String host, int port, PacketProtocol protocol, Client client, Proxy proxy) { + public TcpClientSession(String host, int port, PacketProtocol protocol, Client client, ProxyInfo proxy) { super(host, port, protocol); this.client = client; this.proxy = proxy; @@ -39,15 +41,10 @@ public class TcpClientSession extends TcpSession { } try { - final Bootstrap bootstrap = new Bootstrap(); - if(this.proxy != null) { - this.group = new OioEventLoopGroup(); - bootstrap.channelFactory(new ProxyOioChannelFactory(this.proxy)); - } else { - this.group = new NioEventLoopGroup(); - bootstrap.channel(NioSocketChannel.class); - } + this.group = new NioEventLoopGroup(); + final Bootstrap bootstrap = new Bootstrap(); + bootstrap.channel(NioSocketChannel.class); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) throws Exception { @@ -61,6 +58,37 @@ public class TcpClientSession extends TcpSession { refreshReadTimeoutHandler(channel); refreshWriteTimeoutHandler(channel); + if(proxy != null) { + switch(proxy.getType()) { + case HTTP: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); + } else { + pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress())); + } + + break; + case SOCKS4: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress(), proxy.getUsername())); + } else { + pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress())); + } + + break; + case SOCKS5: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); + } else { + pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress())); + } + + break; + default: + throw new UnsupportedOperationException("Unsupported proxy type: " + proxy.getType()); + } + } + pipeline.addLast("encryption", new TcpPacketEncryptor(TcpClientSession.this)); pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this)); @@ -117,17 +145,10 @@ public class TcpClientSession extends TcpSession { } @Override - public void disconnect(String reason, Throwable cause, boolean wait) { - super.disconnect(reason, cause, wait); + public void disconnect(String reason, Throwable cause) { + super.disconnect(reason, cause); if(this.group != null) { - Future future = this.group.shutdownGracefully(); - if(wait) { - try { - future.await(); - } catch(InterruptedException e) { - } - } - + this.group.shutdownGracefully(); this.group = null; } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 4fa23ef8..c801b341 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -104,9 +104,14 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @SuppressWarnings("unchecked") @Override public T getFlag(String key) { + return this.getFlag(key, null); + } + + @Override + public T getFlag(String key, T def) { Object value = this.getFlags().get(key); if(value == null) { - return null; + return def; } try { @@ -214,8 +219,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp if(!sendingEvent.isCancelled()) { final Packet toSend = sendingEvent.getPacket(); - - ChannelFuture future = this.channel.writeAndFlush(toSend).addListener(new ChannelFutureListener() { + this.channel.writeAndFlush(toSend).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if(future.isSuccess()) { @@ -225,33 +229,16 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } } }); - - if(toSend.isPriority()) { - try { - future.await(); - } catch(InterruptedException e) { - } - } } } @Override public void disconnect(String reason) { - this.disconnect(reason, false); - } - - @Override - public void disconnect(String reason, boolean wait) { - this.disconnect(reason, null, wait); + this.disconnect(reason, null); } @Override public void disconnect(final String reason, final Throwable cause) { - this.disconnect(reason, cause, false); - } - - @Override - public void disconnect(final String reason, final Throwable cause, boolean wait) { if(this.disconnected) { return; } @@ -265,19 +252,12 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp if(this.channel != null && this.channel.isOpen()) { this.callEvent(new DisconnectingEvent(this, reason, cause)); - ChannelFuture future = this.channel.flush().close().addListener(new ChannelFutureListener() { + this.channel.flush().close().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); } }); - - if(wait) { - try { - future.await(); - } catch(InterruptedException e) { - } - } } else { this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java index d94bbb63..0fad540e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java @@ -2,22 +2,21 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.ConnectionListener; +import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.SessionFactory; -import java.net.Proxy; - /** * A session factory used to create TCP sessions. */ public class TcpSessionFactory implements SessionFactory { - private Proxy clientProxy; + private ProxyInfo clientProxy; public TcpSessionFactory() { } - public TcpSessionFactory(Proxy clientProxy) { + public TcpSessionFactory(ProxyInfo clientProxy) { this.clientProxy = clientProxy; } From b23b6f8b4e98caf8ce0f3008e8ed9d16be3f54b9 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 20 Apr 2020 14:55:01 -0700 Subject: [PATCH 084/180] Bump version to 1.5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 36fa8cae..43918cf5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.5-SNAPSHOT + 1.5 jar PacketLib From 29f960a24c1d80459981a96cc43edbe9010dcac1 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 20 Apr 2020 14:55:30 -0700 Subject: [PATCH 085/180] Bump version to 1.6-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 43918cf5..a9168ef1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.5 + 1.6-SNAPSHOT jar PacketLib From b98e525016648e5c5760d09bdec7c187ae090425 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Tue, 21 Apr 2020 12:01:26 -0700 Subject: [PATCH 086/180] Change SRV lookup code to use dnsjava. --- pom.xml | 11 +++++++++ .../packetlib/tcp/TcpClientSession.java | 24 +++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index a9168ef1..ba13d261 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,17 @@ 4.1.45.Final compile + + dnsjava + dnsjava + 3.0.2 + + + + org.slf4j + slf4j-nop + 1.7.30 + diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index fdbe422d..7f993781 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -15,10 +15,11 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; -import io.netty.util.concurrent.Future; - -import javax.naming.directory.InitialDirContext; -import java.util.Hashtable; +import org.xbill.DNS.Lookup; +import org.xbill.DNS.Record; +import org.xbill.DNS.SRVRecord; +import org.xbill.DNS.TextParseException; +import org.xbill.DNS.Type; public class TcpClientSession extends TcpSession { private Client client; @@ -104,17 +105,14 @@ public class TcpClientSession extends TcpSession { int port = getPort(); try { - Hashtable environment = new Hashtable(); - environment.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); - environment.put("java.naming.provider.url", "dns:"); + Record[] records = new Lookup(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, Type.SRV).run(); + if(records.length > 0) { + SRVRecord srv = (SRVRecord) records[0]; - String[] result = new InitialDirContext(environment).getAttributes(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, new String[] {"SRV"}).get("srv").get().toString().split(" ", 4); - host = result[3]; - port = Integer.parseInt(result[2]); - if(host.endsWith(".")) { - host = host.substring(0, host.length() - 1); + host = srv.getTarget().toString().replaceFirst("\\.$", ""); + port = srv.getPort(); } - } catch(Throwable t) { + } catch(TextParseException e) { } bootstrap.remoteAddress(host, port); From 43b394dfdc1e1b17b3e698fc08d92ed6e15db6d6 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Tue, 21 Apr 2020 12:08:50 -0700 Subject: [PATCH 087/180] Check if DNS lookup result is null. --- .../com/github/steveice10/packetlib/tcp/TcpClientSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 7f993781..a67a19d0 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -106,7 +106,7 @@ public class TcpClientSession extends TcpSession { try { Record[] records = new Lookup(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, Type.SRV).run(); - if(records.length > 0) { + if(records != null && records.length > 0) { SRVRecord srv = (SRVRecord) records[0]; host = srv.getTarget().toString().replaceFirst("\\.$", ""); From 27cdf88b3663b06a1580ca0977c7dfcb1a4465c6 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Wed, 20 May 2020 23:33:27 -0400 Subject: [PATCH 088/180] Add BufferedPacket Add PacketProtocol.getOutgoingId(Packet) to get id from BufferedPacket Change TcpPacketCodec.encode to use Packet instance instead of its class --- .../packetlib/packet/BufferedPacket.java | 36 +++++++++++++++++++ .../packetlib/packet/PacketProtocol.java | 25 ++++++++++--- .../packetlib/tcp/TcpPacketCodec.java | 2 +- 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java diff --git a/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java new file mode 100644 index 00000000..66d1ba55 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java @@ -0,0 +1,36 @@ +package com.github.steveice10.packetlib.packet; + +import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.io.NetOutput; + +import java.io.EOFException; +import java.io.IOException; + +public class BufferedPacket implements Packet { + private Class packetClass; + private byte[] buf; + + public BufferedPacket(Class packetClass, byte[] buf) { + this.packetClass = packetClass; + this.buf = buf; + } + + public Class getPacketClass() { + return packetClass; + } + + @Override + public void read(NetInput in) throws IOException { + throw new EOFException("BufferedPacket can not be read"); + } + + @Override + public void write(NetOutput out) throws IOException { + out.writeBytes(buf); + } + + @Override + public boolean isPriority() { + return true; + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index f33172cc..7d5464a4 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -132,15 +132,30 @@ public abstract class PacketProtocol { /** * Gets the registered id of an outgoing packet class. * - * @param packet Class of the packet to get the id for. + * @param packetClass Class of the packet to get the id for. * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getOutgoingId(Class packet) { - if(!this.outgoing.containsKey(packet) || this.outgoing.get(packet) == null) { - throw new IllegalArgumentException("Unregistered outgoing packet class: " + packet.getName()); + public final int getOutgoingId(Class packetClass) { + if(!this.outgoing.containsKey(packetClass) || this.outgoing.get(packetClass) == null) { + throw new IllegalArgumentException("Unregistered outgoing packet class: " + packetClass.getName()); } - return this.outgoing.get(packet); + return this.outgoing.get(packetClass); + } + + /** + * Gets the registered id of an outgoing {@link Packet} instance. + * + * @param packet Instance of {@link Packet} to get the id for. + * @return The packet's registered id. + * @throws IllegalArgumentException If the packet is not registered. + */ + public final int getOutgoingId(Packet packet) { + if(packet instanceof BufferedPacket) { + return getOutgoingId(((BufferedPacket)packet).getPacketClass()); + } + + return getOutgoingId(packet.getClass()); } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 88ed3dc3..fcb4bc8a 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -23,7 +23,7 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { NetOutput out = new ByteBufNetOutput(buf); - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet.getClass())); + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); packet.write(out); } From 74ee4fa02b68249a6cb15e3824e77d0ee6f0fcbb Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Wed, 20 May 2020 23:37:46 -0400 Subject: [PATCH 089/180] Small optimization to PacketProtocol.getOutgoingId(Class) --- .../github/steveice10/packetlib/packet/PacketProtocol.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 7d5464a4..15b6586d 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -137,11 +137,12 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet is not registered. */ public final int getOutgoingId(Class packetClass) { - if(!this.outgoing.containsKey(packetClass) || this.outgoing.get(packetClass) == null) { + Integer packetId = this.outgoing.get(packetClass); + if(packetId == null) { throw new IllegalArgumentException("Unregistered outgoing packet class: " + packetClass.getName()); } - return this.outgoing.get(packetClass); + return packetId; } /** From 614d56cdc02749d0edd1f7228db729182f808008 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 23 May 2020 14:49:23 -0700 Subject: [PATCH 090/180] Add PacketErrorEvent, allowing packet I/O exceptions to be ignored. --- .../event/session/PacketErrorEvent.java | 68 +++++++++++++++++++ .../event/session/SessionAdapter.java | 4 ++ .../event/session/SessionListener.java | 7 ++ .../packetlib/tcp/TcpPacketCodec.java | 28 ++++++-- 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java new file mode 100644 index 00000000..735ca58b --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java @@ -0,0 +1,68 @@ +package com.github.steveice10.packetlib.event.session; + +import com.github.steveice10.packetlib.Session; + +/** + * Called when a session encounters an error while reading or writing packet data. + */ +public class PacketErrorEvent implements SessionEvent { + private Session session; + private Throwable cause; + private boolean suppress = false; + + /** + * Creates a new SessionErrorEvent instance. + * + * @param session Session that the error came from. + * @param cause Cause of the error. + */ + public PacketErrorEvent(Session session, Throwable cause) { + this.session = session; + this.cause = cause; + } + + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the Throwable responsible for the error. + * + * @return The Throwable responsible for the error. + */ + public Throwable getCause() { + return this.cause; + } + + /** + * Gets whether the error should be suppressed. If the error is not suppressed, + * it will be passed on through internal error handling and disconnect the session. + * + * The default value is false. + * + * @return Whether the error should be suppressed. + */ + public boolean shouldSuppress() { + return this.suppress; + } + + /** + * Sets whether the error should be suppressed. If the error is not suppressed, + * it will be passed on through internal error handling and disconnect the session. + * + * @param suppress Whether the error should be suppressed. + */ + public void setSuppress(boolean suppress) { + this.suppress = suppress; + } + + @Override + public void call(SessionListener listener) { + listener.packetError(this); + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java index 3d20e8ae..7dd5b211 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java @@ -16,6 +16,10 @@ public class SessionAdapter implements SessionListener { public void packetSent(PacketSentEvent event) { } + @Override + public void packetError(PacketErrorEvent event) { + } + @Override public void connected(ConnectedEvent event) { } diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java index 23951cc8..cf1f3a4c 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java @@ -25,6 +25,13 @@ public interface SessionListener { */ public void packetSent(PacketSentEvent event); + /** + * Called when a session encounters an error while reading or writing packet data. + * + * @param event Data relating to the event. + */ + public void packetError(PacketErrorEvent event); + /** * Called when a session connects. * diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index fcb4bc8a..08e3be9e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.PacketErrorEvent; import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.io.NetInput; import com.github.steveice10.packetlib.io.NetOutput; @@ -23,8 +24,16 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { NetOutput out = new ByteBufNetOutput(buf); - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); - packet.write(out); + try { + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); + packet.write(out); + } catch(Throwable t) { + PacketErrorEvent e = new PacketErrorEvent(this.session, t); + this.session.callEvent(e); + if(!e.shouldSuppress()) { + throw t; + } + } } @Override @@ -37,8 +46,19 @@ public class TcpPacketCodec extends ByteToMessageCodec { return; } - Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); - packet.read(in); + Packet packet; + try { + packet = this.session.getPacketProtocol().createIncomingPacket(id); + packet.read(in); + } catch(Throwable t) { + PacketErrorEvent e = new PacketErrorEvent(this.session, t); + this.session.callEvent(e); + if(!e.shouldSuppress()) { + throw t; + } + + return; + } if(buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); From c1f371725a15145fbd3a21d9819d346a104a5732 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 01:48:32 -0400 Subject: [PATCH 091/180] Update PacketProtocol Add reverse mapping for outgoing packet id<->class --- .../packetlib/packet/PacketProtocol.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 15b6586d..77613f00 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -17,6 +17,8 @@ public abstract class PacketProtocol { private final Map> incoming = new HashMap>(); private final Map, Integer> outgoing = new HashMap, Integer>(); + private final Map> outgoingClasses = new HashMap>(); + /** * Gets the prefix used when locating SRV records for this protocol. * @@ -60,6 +62,7 @@ public abstract class PacketProtocol { public final void clearPackets() { this.incoming.clear(); this.outgoing.clear(); + this.outgoingClasses.clear(); } /** @@ -99,6 +102,7 @@ public abstract class PacketProtocol { */ public final void registerOutgoing(int id, Class packet) { this.outgoing.put(packet, id); + this.outgoingClasses.put(id, packet); } /** @@ -106,15 +110,15 @@ public abstract class PacketProtocol { * * @param id Id of the packet to create. * @return The created packet. - * @throws IllegalArgumentException If the packet ID is invalid. + * @throws IllegalArgumentException If the packet ID less than zero or it is not registered. * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. */ public final Packet createIncomingPacket(int id) { - if(id < 0 || !this.incoming.containsKey(id) || this.incoming.get(id) == null) { + Class packet; + if(id < 0 || (packet = this.incoming.get(id)) == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - Class packet = this.incoming.get(id); try { Constructor constructor = packet.getDeclaredConstructor(); if(!constructor.isAccessible()) { @@ -159,4 +163,19 @@ public abstract class PacketProtocol { return getOutgoingId(packet.getClass()); } + + /** + * Gets the packet class for a packet id. + * @param id The packet id. + * @return The registered packet's class + * @throws IllegalArgumentException If the packet ID less than zero or it is not registered. + */ + public final Class getOutgoingClass(int id) { + Class packet; + if(id < 0 || (packet = this.outgoingClasses.get(id)) == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + return packet; + } } From e3208ef4e8d9ff4f68ac8b4aea63fed7cc068a39 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 01:55:28 -0400 Subject: [PATCH 092/180] Update pom to target Java 1.8 Fixes Maven warning about dnsjava using 1.8 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba13d261..ab2beefe 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ UTF-8 - 1.7 + 1.8 From 3072587bc7f2efffd8b366d61e9a37f1c75c793d Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 02:03:44 -0400 Subject: [PATCH 093/180] Update StreamNetInput Add mark, markSupported, skip --- .../packetlib/io/stream/StreamNetInput.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java index 197f913a..957f9e1f 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java @@ -261,4 +261,16 @@ public class StreamNetInput implements NetInput { public int available() throws IOException { return this.in.available(); } + + public void mark(int readLimit) { + this.in.mark(readLimit); + } + + public boolean markSupported() { + return this.in.markSupported(); + } + + public long skip(long n) throws IOException { + return this.in.skip(n); + } } From f2adf41dd21d4ba183f1c0fc001c349fd44daa34 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 02:42:11 -0400 Subject: [PATCH 094/180] Add reset method to StreamNetInput --- .../github/steveice10/packetlib/io/stream/StreamNetInput.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java index 957f9e1f..97c95e2b 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java @@ -270,6 +270,10 @@ public class StreamNetInput implements NetInput { return this.in.markSupported(); } + public void reset() throws IOException { + this.in.reset(); + } + public long skip(long n) throws IOException { return this.in.skip(n); } From 68542b8e58de1c269d89dd102c4c1f1638a084f8 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 05:13:13 -0400 Subject: [PATCH 095/180] Update PacketProtocol remove negative packet id checks from createIncomingPacket and getOutgoingClass update syntax --- .../packetlib/packet/PacketProtocol.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 77613f00..11556482 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -14,10 +14,10 @@ import java.util.Map; * All implementations must have a no-params constructor for server protocol creation. */ public abstract class PacketProtocol { - private final Map> incoming = new HashMap>(); - private final Map, Integer> outgoing = new HashMap, Integer>(); + private final Map> incoming = new HashMap<>(); + private final Map, Integer> outgoing = new HashMap<>(); - private final Map> outgoingClasses = new HashMap>(); + private final Map> outgoingClasses = new HashMap<>(); /** * Gets the prefix used when locating SRV records for this protocol. @@ -110,12 +110,12 @@ public abstract class PacketProtocol { * * @param id Id of the packet to create. * @return The created packet. - * @throws IllegalArgumentException If the packet ID less than zero or it is not registered. + * @throws IllegalArgumentException If the packet ID is not registered. * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. */ public final Packet createIncomingPacket(int id) { - Class packet; - if(id < 0 || (packet = this.incoming.get(id)) == null) { + Class packet = this.incoming.get(id); + if (packet == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } @@ -168,11 +168,11 @@ public abstract class PacketProtocol { * Gets the packet class for a packet id. * @param id The packet id. * @return The registered packet's class - * @throws IllegalArgumentException If the packet ID less than zero or it is not registered. + * @throws IllegalArgumentException If the packet ID is not registered. */ public final Class getOutgoingClass(int id) { - Class packet; - if(id < 0 || (packet = this.outgoingClasses.get(id)) == null) { + Class packet = this.outgoingClasses.get(id); + if(packet == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } From ff20c8f2a59269dbcd3dfa1bc31d96a7d5b32f37 Mon Sep 17 00:00:00 2001 From: ipbeegle Date: Mon, 25 May 2020 05:21:10 -0400 Subject: [PATCH 096/180] Change StreamNetInput, StreamNetOutput convert to using Java filter streams update syntax --- .../packetlib/io/stream/StreamNetInput.java | 39 +++++-------------- .../packetlib/io/stream/StreamNetOutput.java | 19 ++++----- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java index 97c95e2b..d96bf9f7 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java @@ -3,23 +3,23 @@ package com.github.steveice10.packetlib.io.stream; import com.github.steveice10.packetlib.io.NetInput; import java.io.EOFException; +import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.UUID; /** * A NetInput implementation using an InputStream as a backend. */ -public class StreamNetInput implements NetInput { - private InputStream in; - +public class StreamNetInput extends FilterInputStream implements NetInput { /** * Creates a new StreamNetInput instance. * * @param in InputStream to read from. */ public StreamNetInput(InputStream in) { - this.in = in; + super(in); } @Override @@ -34,7 +34,7 @@ public class StreamNetInput implements NetInput { @Override public int readUnsignedByte() throws IOException { - int b = this.in.read(); + int b = this.read(); if(b < 0) { throw new EOFException(); } @@ -125,7 +125,7 @@ public class StreamNetInput implements NetInput { byte b[] = new byte[length]; int n = 0; while(n < length) { - int count = this.in.read(b, n, length - n); + int count = this.read(b, n, length - n); if(count < 0) { throw new EOFException(); } @@ -138,12 +138,12 @@ public class StreamNetInput implements NetInput { @Override public int readBytes(byte[] b) throws IOException { - return this.in.read(b); + return this.read(b); } @Override public int readBytes(byte[] b, int offset, int length) throws IOException { - return this.in.read(b, offset, length); + return this.read(b, offset, length); } @Override @@ -249,32 +249,11 @@ public class StreamNetInput implements NetInput { public String readString() throws IOException { int length = this.readVarInt(); byte bytes[] = this.readBytes(length); - return new String(bytes, "UTF-8"); + return new String(bytes, StandardCharsets.UTF_8); } @Override public UUID readUUID() throws IOException { return new UUID(this.readLong(), this.readLong()); } - - @Override - public int available() throws IOException { - return this.in.available(); - } - - public void mark(int readLimit) { - this.in.mark(readLimit); - } - - public boolean markSupported() { - return this.in.markSupported(); - } - - public void reset() throws IOException { - this.in.reset(); - } - - public long skip(long n) throws IOException { - return this.in.skip(n); - } } diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java index bd6ae79a..78562929 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java @@ -2,23 +2,23 @@ package com.github.steveice10.packetlib.io.stream; import com.github.steveice10.packetlib.io.NetOutput; +import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.util.UUID; /** * A NetOutput implementation using an OutputStream as a backend. */ -public class StreamNetOutput implements NetOutput { - private OutputStream out; - +public class StreamNetOutput extends FilterOutputStream implements NetOutput { /** * Creates a new StreamNetOutput instance. * * @param out OutputStream to write to. */ public StreamNetOutput(OutputStream out) { - this.out = out; + super(out); } @Override @@ -28,7 +28,7 @@ public class StreamNetOutput implements NetOutput { @Override public void writeByte(int b) throws IOException { - this.out.write(b); + this.write(b); } @Override @@ -100,7 +100,7 @@ public class StreamNetOutput implements NetOutput { @Override public void writeBytes(byte b[], int length) throws IOException { - this.out.write(b, 0, length); + this.write(b, 0, length); } @Override @@ -145,7 +145,7 @@ public class StreamNetOutput implements NetOutput { throw new IllegalArgumentException("String cannot be null!"); } - byte[] bytes = s.getBytes("UTF-8"); + byte[] bytes = s.getBytes(StandardCharsets.UTF_8); if(bytes.length > 32767) { throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); } else { @@ -159,9 +159,4 @@ public class StreamNetOutput implements NetOutput { this.writeLong(uuid.getMostSignificantBits()); this.writeLong(uuid.getLeastSignificantBits()); } - - @Override - public void flush() throws IOException { - this.out.flush(); - } } From 5291bea6a03f9b97ae49f37bc91241ee7f7ce29a Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 10:49:39 -0700 Subject: [PATCH 097/180] Add flag for printing DNS resolution errors. --- .../com/github/steveice10/packetlib/BuiltinFlags.java | 8 ++++++++ .../github/steveice10/packetlib/tcp/TcpClientSession.java | 4 ++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java diff --git a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java new file mode 100644 index 00000000..e433e82f --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java @@ -0,0 +1,8 @@ +package com.github.steveice10.packetlib; + +public class BuiltinFlags { + public static final String PRINT_DNS_ERRORS = "print-dns-errors"; + + private BuiltinFlags() { + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index a67a19d0..a87288be 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -1,5 +1,6 @@ package com.github.steveice10.packetlib.tcp; +import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.packet.PacketProtocol; @@ -113,6 +114,9 @@ public class TcpClientSession extends TcpSession { port = srv.getPort(); } } catch(TextParseException e) { + if(getFlag(BuiltinFlags.PRINT_DNS_ERRORS, false)) { + e.printStackTrace(); + } } bootstrap.remoteAddress(host, port); From fd7772a9b031f839d4c2b13743175b5fa5f45f71 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 10:52:37 -0700 Subject: [PATCH 098/180] Improve implementation of flag methods. --- .../com/github/steveice10/packetlib/tcp/TcpSession.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index c801b341..e0d2e037 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -25,6 +25,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler; import java.net.ConnectException; import java.net.SocketAddress; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -93,12 +94,12 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public Map getFlags() { - return new HashMap(this.flags); + return Collections.unmodifiableMap(this.flags); } @Override public boolean hasFlag(String key) { - return this.getFlags().containsKey(key); + return this.flags.containsKey(key); } @SuppressWarnings("unchecked") @@ -109,7 +110,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public T getFlag(String key, T def) { - Object value = this.getFlags().get(key); + Object value = this.flags.get(key); if(value == null) { return def; } From 8eaefa9cfc6e67ff0152cc2d14f8f98d93dc72a5 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 10:55:04 -0700 Subject: [PATCH 099/180] Add javadocs to BuiltinFlags. --- .../java/com/github/steveice10/packetlib/BuiltinFlags.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java index e433e82f..f81c505b 100644 --- a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java +++ b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java @@ -1,6 +1,13 @@ package com.github.steveice10.packetlib; +/** + * Built-in PacketLib session flags. + */ public class BuiltinFlags { + /** + * When set to true, prints exceptions that occur when attempting + * to resolve DNS SRV records, rather than silently ignoring them. + */ public static final String PRINT_DNS_ERRORS = "print-dns-errors"; private BuiltinFlags() { From d82b1b688d5f13d420a52ebb74ee4ef385bd5f97 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 11:57:33 -0700 Subject: [PATCH 100/180] Change DNS error printing to a debug printing flag. --- .../com/github/steveice10/packetlib/BuiltinFlags.java | 5 ++--- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 ++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java index f81c505b..9937bd31 100644 --- a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java +++ b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java @@ -5,10 +5,9 @@ package com.github.steveice10.packetlib; */ public class BuiltinFlags { /** - * When set to true, prints exceptions that occur when attempting - * to resolve DNS SRV records, rather than silently ignoring them. + * When set to true, enables printing internal debug messages. */ - public static final String PRINT_DNS_ERRORS = "print-dns-errors"; + public static final String PRINT_DEBUG = "print-packetlib-debug"; private BuiltinFlags() { } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index a87288be..b796468f 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -102,6 +102,8 @@ public class TcpClientSession extends TcpSession { @Override public void run() { try { + boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); + String host = getHost(); int port = getPort(); @@ -112,9 +114,16 @@ public class TcpClientSession extends TcpSession { host = srv.getTarget().toString().replaceFirst("\\.$", ""); port = srv.getPort(); + + if(debug) { + System.out.println("[PacketLib] Found SRV record for \"" + host + ":" + port + "\"."); + } + } else if(debug) { + System.out.println("[PacketLib] No SRV records found."); } } catch(TextParseException e) { - if(getFlag(BuiltinFlags.PRINT_DNS_ERRORS, false)) { + if(debug) { + System.out.println("[PacketLib] Failed to resolve SRV record."); e.printStackTrace(); } } From 12d26014fa20056fdf68aaeac07fb4a7b518e1fb Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 15:22:11 -0700 Subject: [PATCH 101/180] Update dnsjava to 3.1.0 and add result to debug output. --- pom.xml | 2 +- .../github/steveice10/packetlib/tcp/TcpClientSession.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index ab2beefe..fedbc9db 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ dnsjava dnsjava - 3.0.2 + 3.1.0 diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index b796468f..4c41ed07 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -108,7 +108,8 @@ public class TcpClientSession extends TcpSession { int port = getPort(); try { - Record[] records = new Lookup(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, Type.SRV).run(); + Lookup lookup = new Lookup(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, Type.SRV); + Record[] records = lookup.run(); if(records != null && records.length > 0) { SRVRecord srv = (SRVRecord) records[0]; @@ -119,7 +120,7 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Found SRV record for \"" + host + ":" + port + "\"."); } } else if(debug) { - System.out.println("[PacketLib] No SRV records found."); + System.out.println("[PacketLib] No SRV records found; resolver returned \"" + lookup.getErrorString() + "\"."); } } catch(TextParseException e) { if(debug) { From be70b05e3cc56e8a9a3ee5d54c5015eaf2b92549 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 15:33:56 -0700 Subject: [PATCH 102/180] More improvements to flag methods. --- .../github/steveice10/packetlib/Server.java | 27 +++++++++++---- .../github/steveice10/packetlib/Session.java | 2 +- .../packetlib/tcp/TcpServerSession.java | 33 ++++++++++++++++++- .../steveice10/packetlib/tcp/TcpSession.java | 2 +- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Server.java b/src/main/java/com/github/steveice10/packetlib/Server.java index b0e84bee..281fa977 100644 --- a/src/main/java/com/github/steveice10/packetlib/Server.java +++ b/src/main/java/com/github/steveice10/packetlib/Server.java @@ -11,6 +11,7 @@ import com.github.steveice10.packetlib.packet.PacketProtocol; import java.lang.reflect.Constructor; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -117,7 +118,7 @@ public class Server { * @return This server's flags. */ public Map getGlobalFlags() { - return new HashMap(this.flags); + return Collections.unmodifiableMap(this.flags); } /** @@ -131,20 +132,32 @@ public class Server { } /** - * Gets the value of the given flag as an instance of the given type. If this - * session belongs to a server, the server's flags will be checked for the flag - * as well. + * Gets the value of the given flag as an instance of the given type. * * @param Type of the flag. * @param key Key of the flag. * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. */ - @SuppressWarnings("unchecked") public T getGlobalFlag(String key) { + return this.getGlobalFlag(key, null); + } + + /** + * Gets the value of the given flag as an instance of the given type. + * If the flag is not set, the specified default value will be returned. + * + * @param Type of the flag. + * @param key Key of the flag. + * @param def Default value of the flag. + * @return Value of the flag. + * @throws IllegalStateException If the flag's value isn't of the required type. + */ + @SuppressWarnings("unchecked") + public T getGlobalFlag(String key, T def) { Object value = this.flags.get(key); if(value == null) { - return null; + return def; } try { @@ -171,7 +184,7 @@ public class Server { * @return This server's listeners. */ public List getListeners() { - return new ArrayList(this.listeners); + return Collections.unmodifiableList(this.listeners); } /** diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index 45a8a06f..abe02332 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -92,7 +92,7 @@ public interface Session { /** * Gets the value of the given flag as an instance of the given type. If this * session belongs to a server, the server's flags will be checked for the flag - * as well. If no flag is found, the specified default value will be returned. + * as well. If the flag is not set, the specified default value will be returned. * * @param Type of the flag. * @param key Key of the flag. diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java index b4bd2012..6ebb21db 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java @@ -4,6 +4,7 @@ import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.channel.ChannelHandlerContext; +import java.util.HashMap; import java.util.Map; public class TcpServerSession extends TcpSession { @@ -16,11 +17,41 @@ public class TcpServerSession extends TcpSession { @Override public Map getFlags() { - Map ret = super.getFlags(); + Map ret = new HashMap<>(); ret.putAll(this.server.getGlobalFlags()); + ret.putAll(super.getFlags()); return ret; } + @Override + public boolean hasFlag(String key) { + if(super.hasFlag(key)) { + return true; + } + + return this.server.hasGlobalFlag(key); + } + + @Override + public T getFlag(String key) { + T ret = super.getFlag(key); + if(ret != null) { + return ret; + } + + return this.server.getGlobalFlag(key); + } + + @Override + public T getFlag(String key, T def) { + T ret = super.getFlag(key); + if(ret != null) { + return ret; + } + + return this.server.getGlobalFlag(key, def); + } + @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index e0d2e037..01496e23 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -129,7 +129,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public List getListeners() { - return new ArrayList(this.listeners); + return Collections.unmodifiableList(this.listeners); } @Override From 72bde6a3c05c90329a649b1447ed779098107182 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 30 May 2020 15:38:24 -0700 Subject: [PATCH 103/180] Fix stack overflow in flag methods. --- .../steveice10/packetlib/tcp/TcpServerSession.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java index 6ebb21db..4d0f205a 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java @@ -32,19 +32,9 @@ public class TcpServerSession extends TcpSession { return this.server.hasGlobalFlag(key); } - @Override - public T getFlag(String key) { - T ret = super.getFlag(key); - if(ret != null) { - return ret; - } - - return this.server.getGlobalFlag(key); - } - @Override public T getFlag(String key, T def) { - T ret = super.getFlag(key); + T ret = super.getFlag(key, null); if(ret != null) { return ret; } From b02502500126fd57b90a4ebb8bd143e38ed32b46 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 31 May 2020 17:15:44 -0700 Subject: [PATCH 104/180] Call PacketErrorEvent for more I/O errors. --- .../packetlib/tcp/TcpPacketCodec.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 08e3be9e..43425c48 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -23,8 +23,9 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { - NetOutput out = new ByteBufNetOutput(buf); try { + NetOutput out = new ByteBufNetOutput(buf); + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); packet.write(out); } catch(Throwable t) { @@ -38,18 +39,23 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - int initial = buf.readerIndex(); - NetInput in = new ByteBufNetInput(buf); - int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); - if(id == -1) { - buf.readerIndex(initial); - return; - } - Packet packet; try { + NetInput in = new ByteBufNetInput(buf); + + int initial = buf.readerIndex(); + int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); + if(id == -1) { + buf.readerIndex(initial); + return; + } + packet = this.session.getPacketProtocol().createIncomingPacket(id); packet.read(in); + + if(buf.readableBytes() > 0) { + throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); + } } catch(Throwable t) { PacketErrorEvent e = new PacketErrorEvent(this.session, t); this.session.callEvent(e); @@ -60,10 +66,6 @@ public class TcpPacketCodec extends ByteToMessageCodec { return; } - if(buf.readableBytes() > 0) { - throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); - } - if(packet.isPriority()) { this.session.callEvent(new PacketReceivedEvent(this.session, packet)); } From 8dbe3d081c2a4ea608577b97f3ec64f7efb19ea3 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 31 May 2020 17:23:22 -0700 Subject: [PATCH 105/180] Make sure bad packet data is skipped when errors are suppressed. --- .../steveice10/packetlib/tcp/TcpPacketCodec.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 43425c48..0a710016 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -23,12 +23,17 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { + int initial = buf.writerIndex(); + try { NetOutput out = new ByteBufNetOutput(buf); this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); packet.write(out); } catch(Throwable t) { + // Reset writer index to make sure incomplete data is not written out. + buf.writerIndex(initial); + PacketErrorEvent e = new PacketErrorEvent(this.session, t); this.session.callEvent(e); if(!e.shouldSuppress()) { @@ -39,11 +44,12 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { + int initial = buf.readerIndex(); + Packet packet; try { NetInput in = new ByteBufNetInput(buf); - int initial = buf.readerIndex(); int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); if(id == -1) { buf.readerIndex(initial); @@ -57,6 +63,9 @@ public class TcpPacketCodec extends ByteToMessageCodec { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); } } catch(Throwable t) { + // Advance buffer to end to make sure remaining data in this packet is skipped. + buf.readerIndex(buf.readerIndex() + buf.readableBytes()); + PacketErrorEvent e = new PacketErrorEvent(this.session, t); this.session.callEvent(e); if(!e.shouldSuppress()) { From 75f0f02d89b7878cb723d73a604358f4717e3125 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 31 May 2020 17:32:21 -0700 Subject: [PATCH 106/180] Move priority packet handling to channelRead0. --- .../steveice10/packetlib/tcp/TcpPacketCodec.java | 13 +++---------- .../github/steveice10/packetlib/tcp/TcpSession.java | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 0a710016..1f42e2c7 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -46,7 +46,6 @@ public class TcpPacketCodec extends ByteToMessageCodec { protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { int initial = buf.readerIndex(); - Packet packet; try { NetInput in = new ByteBufNetInput(buf); @@ -56,12 +55,14 @@ public class TcpPacketCodec extends ByteToMessageCodec { return; } - packet = this.session.getPacketProtocol().createIncomingPacket(id); + Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); packet.read(in); if(buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); } + + out.add(packet); } catch(Throwable t) { // Advance buffer to end to make sure remaining data in this packet is skipped. buf.readerIndex(buf.readerIndex() + buf.readableBytes()); @@ -71,14 +72,6 @@ public class TcpPacketCodec extends ByteToMessageCodec { if(!e.shouldSuppress()) { throw t; } - - return; } - - if(packet.isPriority()) { - this.session.callEvent(new PacketReceivedEvent(this.session, packet)); - } - - out.add(packet); } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 01496e23..f8dba5ca 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -359,8 +359,10 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } @Override - protected void channelRead0(ChannelHandlerContext ctx, Packet packet) throws Exception { - if(!packet.isPriority()) { + protected void channelRead0(ChannelHandlerContext ctx, Packet packet) { + if(packet.isPriority()) { + this.callEvent(new PacketReceivedEvent(this, packet)); + } else { this.packets.add(packet); } } From bfd0687b3ca34e01b943e8d595edf74272e85817 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Mon, 1 Jun 2020 14:07:46 -0700 Subject: [PATCH 107/180] Replace dnsjava with netty DNS support. --- pom.xml | 11 --- .../packetlib/tcp/TcpClientSession.java | 94 ++++++++++++------- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/pom.xml b/pom.xml index fedbc9db..e7fa299b 100644 --- a/pom.xml +++ b/pom.xml @@ -52,17 +52,6 @@ 4.1.45.Final compile - - dnsjava - dnsjava - 3.1.0 - - - - org.slf4j - slf4j-nop - 1.7.30 - diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 4c41ed07..19df3ca9 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -5,6 +5,7 @@ import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; @@ -12,15 +13,22 @@ import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.dns.DefaultDnsQuestion; +import io.netty.handler.codec.dns.DefaultDnsRawRecord; +import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; +import io.netty.handler.codec.dns.DnsMessage; +import io.netty.handler.codec.dns.DnsRecordType; +import io.netty.handler.codec.dns.DnsSection; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; -import org.xbill.DNS.Lookup; -import org.xbill.DNS.Record; -import org.xbill.DNS.SRVRecord; -import org.xbill.DNS.TextParseException; -import org.xbill.DNS.Type; +import io.netty.resolver.dns.DnsNameResolver; +import io.netty.resolver.dns.DnsNameResolverBuilder; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; public class TcpClientSession extends TcpSession { private Client client; @@ -102,34 +110,7 @@ public class TcpClientSession extends TcpSession { @Override public void run() { try { - boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); - - String host = getHost(); - int port = getPort(); - - try { - Lookup lookup = new Lookup(getPacketProtocol().getSRVRecordPrefix() + "._tcp." + host, Type.SRV); - Record[] records = lookup.run(); - if(records != null && records.length > 0) { - SRVRecord srv = (SRVRecord) records[0]; - - host = srv.getTarget().toString().replaceFirst("\\.$", ""); - port = srv.getPort(); - - if(debug) { - System.out.println("[PacketLib] Found SRV record for \"" + host + ":" + port + "\"."); - } - } else if(debug) { - System.out.println("[PacketLib] No SRV records found; resolver returned \"" + lookup.getErrorString() + "\"."); - } - } catch(TextParseException e) { - if(debug) { - System.out.println("[PacketLib] Failed to resolve SRV record."); - e.printStackTrace(); - } - } - - bootstrap.remoteAddress(host, port); + bootstrap.remoteAddress(resolveAddress()); ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { @@ -156,6 +137,53 @@ public class TcpClientSession extends TcpSession { } } + private SocketAddress resolveAddress() { + boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); + + String name = this.getPacketProtocol().getSRVRecordPrefix() + "._tcp." + this.getHost(); + if(debug) { + System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\"."); + } + + try { + final DnsNameResolver resolver = new DnsNameResolverBuilder(this.group.next()) + .channelType(NioDatagramChannel.class) + .build(); + + DnsMessage message = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get().content(); + if(message.count(DnsSection.ANSWER) > 0) { + DefaultDnsRawRecord record = message.recordAt(DnsSection.ANSWER, 0); + if(record.type() == DnsRecordType.SRV) { + ByteBuf buf = record.content(); + buf.skipBytes(4); // Skip priority and weight. + + int port = buf.readUnsignedShort(); + String host = DefaultDnsRecordDecoder.decodeName(buf); + if(host.endsWith(".")) { + host = host.substring(0, host.length() - 1); + } + + if(debug) { + System.out.println("[PacketLib] Found SRV record containing \"" + host + ":" + port + "\"."); + } + + return new InetSocketAddress(host, port); + } else if(debug) { + System.out.println("[PacketLib] Received non-SRV record in response."); + } + } else if(debug) { + System.out.println("[PacketLib] No SRV record found."); + } + } catch(Exception e) { + if(debug) { + System.out.println("[PacketLib] Failed to resolve SRV record."); + e.printStackTrace(); + } + } + + return new InetSocketAddress(this.getHost(), this.getPort()); + } + @Override public void disconnect(String reason, Throwable cause) { super.disconnect(reason, cause); From d8bfc98d056ebcac2c5ba8af1556a6e6b5d7c5e6 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Wed, 3 Jun 2020 12:15:47 -0700 Subject: [PATCH 108/180] Properly release DNS query resources. --- .../packetlib/tcp/TcpClientSession.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 19df3ca9..85191d25 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -6,6 +6,7 @@ import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; +import io.netty.channel.AddressedEnvelope; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; @@ -18,8 +19,8 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; import io.netty.handler.codec.dns.DefaultDnsRawRecord; import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; -import io.netty.handler.codec.dns.DnsMessage; import io.netty.handler.codec.dns.DnsRecordType; +import io.netty.handler.codec.dns.DnsResponse; import io.netty.handler.codec.dns.DnsSection; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; @@ -145,14 +146,14 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\"."); } - try { - final DnsNameResolver resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(NioDatagramChannel.class) - .build(); - - DnsMessage message = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get().content(); - if(message.count(DnsSection.ANSWER) > 0) { - DefaultDnsRawRecord record = message.recordAt(DnsSection.ANSWER, 0); + AddressedEnvelope envelope = null; + try(DnsNameResolver resolver = new DnsNameResolverBuilder(this.group.next()) + .channelType(NioDatagramChannel.class) + .build()) { + envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); + DnsResponse response = envelope.content(); + if(response.count(DnsSection.ANSWER) > 0) { + DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0); if(record.type() == DnsRecordType.SRV) { ByteBuf buf = record.content(); buf.skipBytes(4); // Skip priority and weight. @@ -179,6 +180,10 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Failed to resolve SRV record."); e.printStackTrace(); } + } finally { + if(envelope != null) { + envelope.release(); + } } return new InetSocketAddress(this.getHost(), this.getPort()); From dc9d37f35e9b8d805baaa13e066410c6b1729ee7 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 6 Jun 2020 14:20:24 -0700 Subject: [PATCH 109/180] Bump version to 1.6 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e7fa299b..19d103e9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.6-SNAPSHOT + 1.6 jar PacketLib From 9a11ceddd526110d2ea59a0410cbfbb266a1a053 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 6 Jun 2020 14:20:59 -0700 Subject: [PATCH 110/180] Bump version to 1.7-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 19d103e9..4b201fe3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.6 + 1.7-SNAPSHOT jar PacketLib From 42e417fc507f17004ae1c251645a89e6d1e46d7d Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 28 Jun 2020 13:43:40 -0700 Subject: [PATCH 111/180] Replace session host and port with resolved SRV record, bump version to 1.7. --- pom.xml | 2 +- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 +++++------ .../github/steveice10/packetlib/tcp/TcpSession.java | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 4b201fe3..0f1f8006 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.7-SNAPSHOT + 1.7 jar PacketLib diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 85191d25..873fb02b 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -29,7 +29,6 @@ import io.netty.resolver.dns.DnsNameResolver; import io.netty.resolver.dns.DnsNameResolverBuilder; import java.net.InetSocketAddress; -import java.net.SocketAddress; public class TcpClientSession extends TcpSession { private Client client; @@ -111,7 +110,8 @@ public class TcpClientSession extends TcpSession { @Override public void run() { try { - bootstrap.remoteAddress(resolveAddress()); + resolveAddress(); + bootstrap.remoteAddress(getHost(), getPort()); ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { @@ -138,7 +138,7 @@ public class TcpClientSession extends TcpSession { } } - private SocketAddress resolveAddress() { + private void resolveAddress() { boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); String name = this.getPacketProtocol().getSRVRecordPrefix() + "._tcp." + this.getHost(); @@ -168,7 +168,8 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Found SRV record containing \"" + host + ":" + port + "\"."); } - return new InetSocketAddress(host, port); + this.host = host; + this.port = port; } else if(debug) { System.out.println("[PacketLib] Received non-SRV record in response."); } @@ -185,8 +186,6 @@ public class TcpClientSession extends TcpSession { envelope.release(); } } - - return new InetSocketAddress(this.getHost(), this.getPort()); } @Override diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index f8dba5ca..e5f1347b 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -34,8 +34,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingQueue; public abstract class TcpSession extends SimpleChannelInboundHandler implements Session { - private String host; - private int port; + protected String host; + protected int port; private PacketProtocol protocol; private int compressionThreshold = -1; From bb12069f95e3c2edca9c875c3d49be072636ea30 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sun, 28 Jun 2020 13:44:07 -0700 Subject: [PATCH 112/180] Bump version to 1.8-SNAPSHOT. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0f1f8006..9ea0f3ea 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.7 + 1.8-SNAPSHOT jar PacketLib From ead6afae39f976dd115e7519f8276862f7251335 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Sat, 21 Nov 2020 12:59:51 -0800 Subject: [PATCH 113/180] Move DnsNameResolver creation into try-catch block. --- .../steveice10/packetlib/tcp/TcpClientSession.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 873fb02b..02505013 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -146,11 +146,14 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\"."); } + DnsNameResolver resolver = null; AddressedEnvelope envelope = null; - try(DnsNameResolver resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(NioDatagramChannel.class) - .build()) { + try { + resolver = new DnsNameResolverBuilder(this.group.next()) + .channelType(NioDatagramChannel.class) + .build(); envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); + DnsResponse response = envelope.content(); if(response.count(DnsSection.ANSWER) > 0) { DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0); @@ -185,6 +188,10 @@ public class TcpClientSession extends TcpSession { if(envelope != null) { envelope.release(); } + + if(resolver != null) { + resolver.close(); + } } } From a10416b8f3397ba35ca7b2b7af09ebcb4856d605 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Sat, 19 Dec 2020 05:01:22 +0200 Subject: [PATCH 114/180] Bump Netty to 4.1.56.Final --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9ea0f3ea..c83d9b85 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ io.netty netty-all - 4.1.45.Final + 4.1.56.Final compile From 7b9af65ed0ca06badc2c562154a0e9205ffc19cc Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Sat, 19 Dec 2020 05:02:55 +0200 Subject: [PATCH 115/180] Add netty-codec-haproxy dependency --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index c83d9b85..bc69d770 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,13 @@ 4.1.56.Final compile + + io.netty + netty-codec-haproxy + 4.1.56.Final + compile + true + From b94345387b0316b2fdddff1b4ee096cf3ad174e9 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Sat, 19 Dec 2020 05:05:34 +0200 Subject: [PATCH 116/180] Resolve remote address eagerly --- .../packetlib/tcp/TcpClientSession.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 02505013..44d527e5 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -28,7 +28,9 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.resolver.dns.DnsNameResolver; import io.netty.resolver.dns.DnsNameResolverBuilder; +import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.UnknownHostException; public class TcpClientSession extends TcpSession { private Client client; @@ -110,8 +112,8 @@ public class TcpClientSession extends TcpSession { @Override public void run() { try { - resolveAddress(); - bootstrap.remoteAddress(getHost(), getPort()); + InetSocketAddress remoteAddress = resolveAddress(); + bootstrap.remoteAddress(remoteAddress); ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { @@ -138,7 +140,7 @@ public class TcpClientSession extends TcpSession { } } - private void resolveAddress() { + private InetSocketAddress resolveAddress() { boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); String name = this.getPacketProtocol().getSRVRecordPrefix() + "._tcp." + this.getHost(); @@ -193,6 +195,21 @@ public class TcpClientSession extends TcpSession { resolver.close(); } } + + // Resolve host here + try { + InetAddress resolved = InetAddress.getByName(getHost()); + if (debug) { + System.out.printf("[PacketLib] Resolved %s -> %s%n", getHost(), resolved.getHostAddress()); + } + return new InetSocketAddress(resolved, getPort()); + } catch (UnknownHostException e) { + if (debug) { + System.out.println("[PacketLib] Failed to resolve host, letting Netty do it instead."); + e.printStackTrace(); + } + return InetSocketAddress.createUnresolved(getHost(), getPort()); + } } @Override From a651cb0b265901681885364e83fb64d79dcd4ac8 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Sat, 19 Dec 2020 05:08:02 +0200 Subject: [PATCH 117/180] Implement HAProxy PROXY protocol support for client --- .../steveice10/packetlib/BuiltinFlags.java | 4 +++ .../packetlib/tcp/TcpClientSession.java | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java index 9937bd31..b60bcafa 100644 --- a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java +++ b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java @@ -9,6 +9,10 @@ public class BuiltinFlags { */ public static final String PRINT_DEBUG = "print-packetlib-debug"; + public static final String ENABLE_CLIENT_PROXY_PROTOCOL = "enable-client-proxy-protocol"; + + public static final String CLIENT_PROXIED_ADDRESS = "client-proxied-address"; + private BuiltinFlags() { } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 44d527e5..4607184d 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -9,6 +9,8 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.AddressedEnvelope; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; @@ -22,12 +24,18 @@ import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; import io.netty.handler.codec.dns.DnsRecordType; import io.netty.handler.codec.dns.DnsResponse; import io.netty.handler.codec.dns.DnsSection; +import io.netty.handler.codec.haproxy.HAProxyCommand; +import io.netty.handler.codec.haproxy.HAProxyMessage; +import io.netty.handler.codec.haproxy.HAProxyMessageEncoder; +import io.netty.handler.codec.haproxy.HAProxyProtocolVersion; +import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.resolver.dns.DnsNameResolver; import io.netty.resolver.dns.DnsNameResolverBuilder; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; @@ -105,6 +113,26 @@ public class TcpClientSession extends TcpSession { pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this)); pipeline.addLast("manager", TcpClientSession.this); + + InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS); + if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) { + pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6; + InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); + ctx.channel().writeAndFlush(new HAProxyMessage( + HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol, + clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(), + clientAddress.getPort(), remoteAddress.getPort() + )); + ctx.pipeline().remove(this); + ctx.pipeline().remove("proxy-protocol-encoder"); + super.channelActive(ctx); + } + }); + pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE); + } } }).group(this.group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); From 30588f7be0e97730ddc986a5745e6866c9bf8bd1 Mon Sep 17 00:00:00 2001 From: VADemon Date: Mon, 21 Dec 2020 15:58:02 +0100 Subject: [PATCH 118/180] Add local address binding to Client --- .../github/steveice10/packetlib/Client.java | 30 +++++++++++++++++-- .../packetlib/tcp/TcpClientSession.java | 1 + 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java index 0757196a..35a4256d 100644 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -8,15 +8,23 @@ import com.github.steveice10.packetlib.packet.PacketProtocol; public class Client { private String host; private int port; + private String bindAddress; + private int bindPort; private PacketProtocol protocol; private Session session; - public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { + public Client(String host, int port, String bindAddress, int bindPort, PacketProtocol protocol, SessionFactory factory) { this.host = host; this.port = port; + this.bindAddress = bindAddress; + this.bindPort = bindPort; this.protocol = protocol; this.session = factory.createClientSession(this); } + + public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { + new Client(host, port, null, 0, protocol, factory); + } /** * Gets the host the client is connecting to. @@ -35,7 +43,25 @@ public class Client { public int getPort() { return this.port; } - + + /** + * Gets the the local address the client is connecting from. + * + * @return Client's local IP address or null if default. + */ + public String getBindAddress() { + return this.bindAddress; + } + + /** + * Gets the the local port the client is connecting from. + * + * @return Client's local port or 0 if default. + */ + public int getBindPort() { + return this.bindPort; + } + /** * Gets the packet protocol of the client. * diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 4607184d..d6ef23a3 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -142,6 +142,7 @@ public class TcpClientSession extends TcpSession { try { InetSocketAddress remoteAddress = resolveAddress(); bootstrap.remoteAddress(remoteAddress); + bootstrap.localAddress(client.getBindAddress(), client.getBindPort()); ChannelFuture future = bootstrap.connect().sync(); if(future.isSuccess()) { From 83201135ec8a660f7afcc8fd8a8806b305d68d05 Mon Sep 17 00:00:00 2001 From: VADemon Date: Wed, 23 Dec 2020 11:29:48 +0100 Subject: [PATCH 119/180] Use proper Client constructor --- src/main/java/com/github/steveice10/packetlib/Client.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java index 35a4256d..c5ba8da0 100644 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -23,7 +23,7 @@ public class Client { } public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { - new Client(host, port, null, 0, protocol, factory); + this(host, port, null, 0, protocol, factory); } /** From 1df02557d13a981e7179ff35ae7d89c873213723 Mon Sep 17 00:00:00 2001 From: VADemon Date: Wed, 23 Dec 2020 12:58:52 +0100 Subject: [PATCH 120/180] Local address binding: return bind addresses from Session if connected --- .../github/steveice10/packetlib/Client.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java index c5ba8da0..9a05244e 100644 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -1,6 +1,8 @@ package com.github.steveice10.packetlib; import com.github.steveice10.packetlib.packet.PacketProtocol; +import com.sun.istack.internal.Nullable; +import java.net.InetSocketAddress; /** * A client that may connect to a server. @@ -45,21 +47,28 @@ public class Client { } /** - * Gets the the local address the client is connecting from. + * Gets the the local address the client is connected from/will be binding to. * - * @return Client's local IP address or null if default. + * @return Client's local IP address, or null if default and not connected. */ + @Nullable public String getBindAddress() { - return this.bindAddress; + final Session session = this.getSession(); + return session.isConnected() + ? ((InetSocketAddress) session.getLocalAddress()).getAddress().getHostAddress() + : this.bindAddress; } /** - * Gets the the local port the client is connecting from. + * Gets the the local port the client is connected from/will be binding to. * - * @return Client's local port or 0 if default. + * @return Client's local port, or 0 if default and not connected. */ public int getBindPort() { - return this.bindPort; + final Session session = this.getSession(); + return session.isConnected() + ? ((InetSocketAddress) session.getLocalAddress()).getPort() + : this.bindPort; } /** From 126b0e67def045c6d0e143befb0a4183c14d145a Mon Sep 17 00:00:00 2001 From: VADemon Date: Wed, 23 Dec 2020 13:21:12 +0100 Subject: [PATCH 121/180] Use proper @Nullable annotation from spotbugs --- pom.xml | 5 +++++ src/main/java/com/github/steveice10/packetlib/Client.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bc69d770..6ff0adf0 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,11 @@ compile true + + com.github.spotbugs + spotbugs-annotations + 4.2.0 + diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java index 9a05244e..71759845 100644 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib; import com.github.steveice10.packetlib.packet.PacketProtocol; -import com.sun.istack.internal.Nullable; +import javax.annotation.Nullable; import java.net.InetSocketAddress; /** From 09d7774037d3b7eed98b5df4af900a9f5f1dc4ac Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 15 Jan 2021 12:07:12 -0800 Subject: [PATCH 122/180] Default client local address to 0.0.0.0. --- src/main/java/com/github/steveice10/packetlib/Client.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java index 71759845..cf4237a1 100644 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ b/src/main/java/com/github/steveice10/packetlib/Client.java @@ -25,7 +25,7 @@ public class Client { } public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { - this(host, port, null, 0, protocol, factory); + this(host, port, "0.0.0.0", 0, protocol, factory); } /** From f29aa03c92f3a69a4fc5968eca9c5a26ed1b6480 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 15 Jan 2021 12:44:04 -0800 Subject: [PATCH 123/180] Bump version to 1.8 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6ff0adf0..a7ffa2ff 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.8-SNAPSHOT + 1.8 jar PacketLib From 87206da886b7a0bc25ad9ff6a90e9dddd282ceb2 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 15 Jan 2021 12:44:41 -0800 Subject: [PATCH 124/180] Bump version to 2.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7ffa2ff..cd93e51e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 1.8 + 2.0-SNAPSHOT jar PacketLib From 19a9b2be35e46f5a20bc0f964f30e71ff8ead617 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 15 Jan 2021 12:42:00 -0800 Subject: [PATCH 125/180] Collapse Client and Server into *ClientSession and ConnectionListener. --- .../packetlib/test/PingServerTest.java | 21 +- .../packetlib/test/ServerListener.java | 2 +- .../packetlib/test/TestProtocol.java | 3 +- .../steveice10/packetlib/AbstractServer.java | 182 ++++++++++++++ .../github/steveice10/packetlib/Client.java | 91 ------- .../packetlib/ConnectionListener.java | 67 ----- .../github/steveice10/packetlib/Server.java | 229 ++++-------------- .../steveice10/packetlib/SessionFactory.java | 22 -- .../packetlib/packet/PacketProtocol.java | 4 +- .../packetlib/tcp/TcpClientSession.java | 160 ++++++------ ...ConnectionListener.java => TcpServer.java} | 82 ++----- .../packetlib/tcp/TcpServerSession.java | 4 +- .../steveice10/packetlib/tcp/TcpSession.java | 9 +- .../packetlib/tcp/TcpSessionFactory.java | 32 --- 14 files changed, 356 insertions(+), 552 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/AbstractServer.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/Client.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/ConnectionListener.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/SessionFactory.java rename src/main/java/com/github/steveice10/packetlib/tcp/{TcpConnectionListener.java => TcpServer.java} (69%) delete mode 100644 src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java diff --git a/example/com/github/steveice10/packetlib/test/PingServerTest.java b/example/com/github/steveice10/packetlib/test/PingServerTest.java index 7daa2b04..2db3b031 100644 --- a/example/com/github/steveice10/packetlib/test/PingServerTest.java +++ b/example/com/github/steveice10/packetlib/test/PingServerTest.java @@ -1,8 +1,9 @@ package com.github.steveice10.packetlib.test; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.Server; -import com.github.steveice10.packetlib.tcp.TcpSessionFactory; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.tcp.TcpClientSession; +import com.github.steveice10.packetlib.tcp.TcpServer; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; @@ -10,7 +11,7 @@ import java.security.NoSuchAlgorithmException; public class PingServerTest { public static void main(String[] args) { - SecretKey key = null; + SecretKey key; try { KeyGenerator gen = KeyGenerator.getInstance("AES"); gen.init(128); @@ -20,19 +21,11 @@ public class PingServerTest { return; } - Server server = new Server("127.0.0.1", 25565, TestProtocol.class, new TcpSessionFactory()); + Server server = new TcpServer("127.0.0.1", 25565, TestProtocol.class); server.addListener(new ServerListener(key)); server.bind(); - Client client = new Client("127.0.0.1", 25565, new TestProtocol(key), new TcpSessionFactory()); - client.getSession().connect(); - - while(server.isListening()) { - try { - Thread.sleep(500); - } catch(InterruptedException e) { - break; - } - } + Session client = new TcpClientSession("127.0.0.1", 25565, new TestProtocol(key)); + client.connect(); } } diff --git a/example/com/github/steveice10/packetlib/test/ServerListener.java b/example/com/github/steveice10/packetlib/test/ServerListener.java index a0694ae1..3c7dfcb2 100644 --- a/example/com/github/steveice10/packetlib/test/ServerListener.java +++ b/example/com/github/steveice10/packetlib/test/ServerListener.java @@ -40,6 +40,6 @@ public class ServerListener extends ServerAdapter { @Override public void sessionRemoved(SessionRemovedEvent event) { System.out.println("SERVER Session Removed: " + event.getSession().getHost() + ":" + event.getSession().getPort()); - event.getServer().close(); + event.getServer().close(false); } } diff --git a/example/com/github/steveice10/packetlib/test/TestProtocol.java b/example/com/github/steveice10/packetlib/test/TestProtocol.java index e6ead1ae..8a4baedc 100644 --- a/example/com/github/steveice10/packetlib/test/TestProtocol.java +++ b/example/com/github/steveice10/packetlib/test/TestProtocol.java @@ -1,6 +1,5 @@ package com.github.steveice10.packetlib.test; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.crypt.AESEncryption; @@ -49,7 +48,7 @@ public class TestProtocol extends PacketProtocol { } @Override - public void newClientSession(Client client, Session session) { + public void newClientSession(Session session) { session.addListener(new ClientSessionListener()); } diff --git a/src/main/java/com/github/steveice10/packetlib/AbstractServer.java b/src/main/java/com/github/steveice10/packetlib/AbstractServer.java new file mode 100644 index 00000000..1412ccab --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/AbstractServer.java @@ -0,0 +1,182 @@ +package com.github.steveice10.packetlib; + +import com.github.steveice10.packetlib.event.server.*; +import com.github.steveice10.packetlib.packet.PacketProtocol; + +import java.lang.reflect.Constructor; +import java.util.*; + +public abstract class AbstractServer implements Server { + private final String host; + private final int port; + private final Class protocol; + + private final List sessions = new ArrayList<>(); + + private final Map flags = new HashMap<>(); + private final List listeners = new ArrayList<>(); + + public AbstractServer(String host, int port, Class protocol) { + this.host = host; + this.port = port; + this.protocol = protocol; + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public int getPort() { + return this.port; + } + + @Override + public Class getPacketProtocol() { + return this.protocol; + } + + protected PacketProtocol createPacketProtocol() { + try { + Constructor constructor = this.protocol.getDeclaredConstructor(); + if(!constructor.isAccessible()) { + constructor.setAccessible(true); + } + + return constructor.newInstance(); + } catch(NoSuchMethodError e) { + throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); + } catch(Exception e) { + throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); + } + } + + @Override + public Map getGlobalFlags() { + return Collections.unmodifiableMap(this.flags); + } + + @Override + public boolean hasGlobalFlag(String key) { + return this.flags.containsKey(key); + } + + @Override + public T getGlobalFlag(String key) { + return this.getGlobalFlag(key, null); + } + + @SuppressWarnings("unchecked") + @Override + public T getGlobalFlag(String key, T def) { + Object value = this.flags.get(key); + if(value == null) { + return def; + } + + try { + return (T) value; + } catch(ClassCastException e) { + throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); + } + } + + @Override + public void setGlobalFlag(String key, Object value) { + this.flags.put(key, value); + } + + @Override + public List getListeners() { + return Collections.unmodifiableList(this.listeners); + } + + @Override + public void addListener(ServerListener listener) { + this.listeners.add(listener); + } + + @Override + public void removeListener(ServerListener listener) { + this.listeners.remove(listener); + } + + protected void callEvent(ServerEvent event) { + for(ServerListener listener : this.listeners) { + event.call(listener); + } + } + + @Override + public List getSessions() { + return new ArrayList<>(this.sessions); + } + + public void addSession(Session session) { + this.sessions.add(session); + this.callEvent(new SessionAddedEvent(this, session)); + } + + public void removeSession(Session session) { + this.sessions.remove(session); + if(session.isConnected()) { + session.disconnect("Connection closed."); + } + + this.callEvent(new SessionRemovedEvent(this, session)); + } + + @Override + public AbstractServer bind() { + return this.bind(true); + } + + @Override + public AbstractServer bind(boolean wait) { + return this.bind(wait, null); + } + + @Override + public AbstractServer bind(boolean wait, Runnable callback) { + this.bindImpl(wait, () -> { + callEvent(new ServerBoundEvent(AbstractServer.this)); + if(callback != null) { + callback.run(); + } + }); + + return this; + } + + protected abstract void bindImpl(boolean wait, Runnable callback); + + @Override + public void close() { + this.close(true); + } + + @Override + public void close(boolean wait) { + this.close(wait, null); + } + + @Override + public void close(boolean wait, Runnable callback) { + this.callEvent(new ServerClosingEvent(this)); + for(Session session : this.getSessions()) { + if(session.isConnected()) { + session.disconnect("Server closed."); + } + } + + this.closeImpl(wait, () -> { + callEvent(new ServerClosedEvent(AbstractServer.this)); + if(callback != null) { + callback.run(); + } + }); + } + + protected abstract void closeImpl(boolean wait, Runnable callback); +} diff --git a/src/main/java/com/github/steveice10/packetlib/Client.java b/src/main/java/com/github/steveice10/packetlib/Client.java deleted file mode 100644 index cf4237a1..00000000 --- a/src/main/java/com/github/steveice10/packetlib/Client.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.github.steveice10.packetlib; - -import com.github.steveice10.packetlib.packet.PacketProtocol; -import javax.annotation.Nullable; -import java.net.InetSocketAddress; - -/** - * A client that may connect to a server. - */ -public class Client { - private String host; - private int port; - private String bindAddress; - private int bindPort; - private PacketProtocol protocol; - private Session session; - - public Client(String host, int port, String bindAddress, int bindPort, PacketProtocol protocol, SessionFactory factory) { - this.host = host; - this.port = port; - this.bindAddress = bindAddress; - this.bindPort = bindPort; - this.protocol = protocol; - this.session = factory.createClientSession(this); - } - - public Client(String host, int port, PacketProtocol protocol, SessionFactory factory) { - this(host, port, "0.0.0.0", 0, protocol, factory); - } - - /** - * Gets the host the client is connecting to. - * - * @return The host the client is connecting to. - */ - public String getHost() { - return this.host; - } - - /** - * Gets the port the client is connecting to. - * - * @return The port the client is connecting to. - */ - public int getPort() { - return this.port; - } - - /** - * Gets the the local address the client is connected from/will be binding to. - * - * @return Client's local IP address, or null if default and not connected. - */ - @Nullable - public String getBindAddress() { - final Session session = this.getSession(); - return session.isConnected() - ? ((InetSocketAddress) session.getLocalAddress()).getAddress().getHostAddress() - : this.bindAddress; - } - - /** - * Gets the the local port the client is connected from/will be binding to. - * - * @return Client's local port, or 0 if default and not connected. - */ - public int getBindPort() { - final Session session = this.getSession(); - return session.isConnected() - ? ((InetSocketAddress) session.getLocalAddress()).getPort() - : this.bindPort; - } - - /** - * Gets the packet protocol of the client. - * - * @return The client's packet protocol. - */ - public PacketProtocol getPacketProtocol() { - return this.protocol; - } - - /** - * Gets the session of the client. - * - * @return The client's session. - */ - public Session getSession() { - return this.session; - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java b/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java deleted file mode 100644 index 96cc5bd5..00000000 --- a/src/main/java/com/github/steveice10/packetlib/ConnectionListener.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.github.steveice10.packetlib; - -/** - * Listens for new sessions to connect. - */ -public interface ConnectionListener { - /** - * Gets the host the session is listening on. - * - * @return The listening host. - */ - public String getHost(); - - /** - * Gets the port the session is listening on. - * - * @return The listening port. - */ - public int getPort(); - - /** - * Returns true if the listener is listening. - * - * @return True if the listener is listening. - */ - public boolean isListening(); - - /** - * Binds the listener to its host and port. - */ - public void bind(); - - /** - * Binds the listener to its host and port. - * - * @param wait Whether to wait for the listener to finish binding. - */ - public void bind(boolean wait); - - /** - * Binds the listener to its host and port. - * - * @param wait Whether to wait for the listener to finish binding. - * @param callback Callback to call when the listener has finished binding. - */ - public void bind(boolean wait, Runnable callback); - - /** - * Closes the listener. - */ - public void close(); - - /** - * Closes the listener. - * - * @param wait Whether to wait for the listener to finish closing. - */ - public void close(boolean wait); - - /** - * Closes the listener. - * - * @param wait Whether to wait for the listener to finish closing. - * @param callback Callback to call when the listener has finished closing. - */ - public void close(boolean wait, Runnable callback); -} diff --git a/src/main/java/com/github/steveice10/packetlib/Server.java b/src/main/java/com/github/steveice10/packetlib/Server.java index 281fa977..2dd8fb60 100644 --- a/src/main/java/com/github/steveice10/packetlib/Server.java +++ b/src/main/java/com/github/steveice10/packetlib/Server.java @@ -1,125 +1,49 @@ package com.github.steveice10.packetlib; -import com.github.steveice10.packetlib.event.server.ServerBoundEvent; -import com.github.steveice10.packetlib.event.server.ServerClosedEvent; -import com.github.steveice10.packetlib.event.server.ServerClosingEvent; -import com.github.steveice10.packetlib.event.server.ServerEvent; import com.github.steveice10.packetlib.event.server.ServerListener; -import com.github.steveice10.packetlib.event.server.SessionAddedEvent; -import com.github.steveice10.packetlib.event.server.SessionRemovedEvent; import com.github.steveice10.packetlib.packet.PacketProtocol; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; /** - * A server that listens for connections. + * Listens for new sessions to connect. */ -public class Server { - private String host; - private int port; - private Class protocol; - private SessionFactory factory; - private ConnectionListener listener; - private List sessions = new ArrayList(); - - private Map flags = new HashMap(); - private List listeners = new ArrayList(); - - public Server(String host, int port, Class protocol, SessionFactory factory) { - this.host = host; - this.port = port; - this.protocol = protocol; - this.factory = factory; - } +public interface Server { + /** + * Gets the host the session is listening on. + * + * @return The listening host. + */ + public String getHost(); /** - * Binds and initializes the server. + * Gets the port the session is listening on. * - * @return The server after being bound. + * @return The listening port. */ - public Server bind() { - return this.bind(true); - } - - /** - * Binds and initializes the server. - * - * @param wait Whether to wait for the server to finish binding. - * @return The server after being bound. - */ - public Server bind(boolean wait) { - this.listener = this.factory.createServerListener(this); - this.listener.bind(wait, new Runnable() { - @Override - public void run() { - callEvent(new ServerBoundEvent(Server.this)); - } - }); - - return this; - } - - /** - * Gets the host this server is bound to. - * - * @return The server's host. - */ - public String getHost() { - return this.host; - } - - /** - * Gets the port this server is bound to. - * - * @return The server's port. - */ - public int getPort() { - return this.port; - } + public int getPort(); /** * Gets the packet protocol of the server. * * @return The server's packet protocol. */ - public Class getPacketProtocol() { - return this.protocol; - } + public Class getPacketProtocol(); /** - * Creates a new packet protocol instance from this server's protocol class. + * Returns true if the listener is listening. * - * @return The created protocol instance. - * @throws IllegalStateException If the protocol does not have a no-params constructor or cannot be instantiated. + * @return True if the listener is listening. */ - public PacketProtocol createPacketProtocol() { - try { - Constructor constructor = this.protocol.getDeclaredConstructor(); - if(!constructor.isAccessible()) { - constructor.setAccessible(true); - } - - return constructor.newInstance(); - } catch(NoSuchMethodError e) { - throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); - } - } + public boolean isListening(); /** * Gets this server's set flags. * * @return This server's flags. */ - public Map getGlobalFlags() { - return Collections.unmodifiableMap(this.flags); - } + public Map getGlobalFlags(); /** * Checks whether this server has a flag set. @@ -127,9 +51,7 @@ public class Server { * @param key Key of the flag to check for. * @return Whether this server has a flag set. */ - public boolean hasGlobalFlag(String key) { - return this.flags.containsKey(key); - } + public boolean hasGlobalFlag(String key); /** * Gets the value of the given flag as an instance of the given type. @@ -139,9 +61,7 @@ public class Server { * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. */ - public T getGlobalFlag(String key) { - return this.getGlobalFlag(key, null); - } + public T getGlobalFlag(String key); /** * Gets the value of the given flag as an instance of the given type. @@ -154,18 +74,7 @@ public class Server { * @throws IllegalStateException If the flag's value isn't of the required type. */ @SuppressWarnings("unchecked") - public T getGlobalFlag(String key, T def) { - Object value = this.flags.get(key); - if(value == null) { - return def; - } - - try { - return (T) value; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); - } - } + public T getGlobalFlag(String key, T def); /** * Sets the value of a flag. The flag will be used in sessions if a session does @@ -174,115 +83,73 @@ public class Server { * @param key Key of the flag. * @param value Value to set the flag to. */ - public void setGlobalFlag(String key, Object value) { - this.flags.put(key, value); - } + public void setGlobalFlag(String key, Object value); /** * Gets the listeners listening on this session. * * @return This server's listeners. */ - public List getListeners() { - return Collections.unmodifiableList(this.listeners); - } + public List getListeners(); /** * Adds a listener to this server. * * @param listener Listener to add. */ - public void addListener(ServerListener listener) { - this.listeners.add(listener); - } + public void addListener(ServerListener listener); /** * Removes a listener from this server. * * @param listener Listener to remove. */ - public void removeListener(ServerListener listener) { - this.listeners.remove(listener); - } - - /** - * Calls an event on the listeners of this server. - * - * @param event Event to call. - */ - public void callEvent(ServerEvent event) { - for(ServerListener listener : this.listeners) { - event.call(listener); - } - } + public void removeListener(ServerListener listener); /** * Gets all sessions belonging to this server. * * @return Sessions belonging to this server. */ - public List getSessions() { - return new ArrayList(this.sessions); - } + public List getSessions(); /** - * Adds the given session to this server. + * Binds the listener to its host and port. + */ + public AbstractServer bind(); + + /** + * Binds the listener to its host and port. * - * @param session Session to add. + * @param wait Whether to wait for the listener to finish binding. */ - public void addSession(Session session) { - this.sessions.add(session); - this.callEvent(new SessionAddedEvent(this, session)); - } + public AbstractServer bind(boolean wait); /** - * Removes the given session from this server. + * Binds the listener to its host and port. * - * @param session Session to remove. + * @param wait Whether to wait for the listener to finish binding. + * @param callback Callback to call when the listener has finished binding. */ - public void removeSession(Session session) { - this.sessions.remove(session); - if(session.isConnected()) { - session.disconnect("Connection closed."); - } - - this.callEvent(new SessionRemovedEvent(this, session)); - } + public AbstractServer bind(boolean wait, Runnable callback); /** - * Gets whether the server is listening. + * Closes the listener. + */ + public void close(); + + /** + * Closes the listener. * - * @return Whether the server is listening. + * @param wait Whether to wait for the listener to finish closing. */ - public boolean isListening() { - return this.listener != null && this.listener.isListening(); - } + public void close(boolean wait); /** - * Closes the server. - */ - public void close() { - this.close(true); - } - - /** - * Closes the server. + * Closes the listener. * - * @param wait Whether to wait for the server to finish closing. + * @param wait Whether to wait for the listener to finish closing. + * @param callback Callback to call when the listener has finished closing. */ - public void close(boolean wait) { - this.callEvent(new ServerClosingEvent(this)); - for(Session session : this.getSessions()) { - if(session.isConnected()) { - session.disconnect("Server closed."); - } - } - - this.listener.close(wait, new Runnable() { - @Override - public void run() { - callEvent(new ServerClosedEvent(Server.this)); - } - }); - } + public void close(boolean wait, Runnable callback); } diff --git a/src/main/java/com/github/steveice10/packetlib/SessionFactory.java b/src/main/java/com/github/steveice10/packetlib/SessionFactory.java deleted file mode 100644 index 5155af3c..00000000 --- a/src/main/java/com/github/steveice10/packetlib/SessionFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.steveice10.packetlib; - -/** - * A factory for creating sessions. - */ -public interface SessionFactory { - /** - * Creates a client session. - * - * @param client Client to create the session for. - * @return The created session. - */ - public Session createClientSession(Client client); - - /** - * Creates a server network listener. - * - * @param server Server to create the listener for. - * @return The created listener. - */ - public ConnectionListener createServerListener(Server server); -} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 11556482..1cc93365 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -1,6 +1,5 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.crypt.PacketEncryption; @@ -43,10 +42,9 @@ public abstract class PacketProtocol { /** * Called when a client session is created with this protocol. * - * @param client The client that the session belongs to. * @param session The created session. */ - public abstract void newClientSession(Client client, Session session); + public abstract void newClientSession(Session session); /** * Called when a server session is created with this protocol. diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index d6ef23a3..725e6068 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -1,7 +1,6 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.ProxyInfo; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; @@ -41,14 +40,28 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; public class TcpClientSession extends TcpSession { - private Client client; + private String bindAddress; + private int bindPort; private ProxyInfo proxy; private EventLoopGroup group; - public TcpClientSession(String host, int port, PacketProtocol protocol, Client client, ProxyInfo proxy) { + public TcpClientSession(String host, int port, PacketProtocol protocol) { + this(host, port, protocol, null); + } + + public TcpClientSession(String host, int port, PacketProtocol protocol, ProxyInfo proxy) { + this(host, port, "0.0.0.0", 0, protocol, proxy); + } + + public TcpClientSession(String host, int port, String bindAddress, int bindPort, PacketProtocol protocol) { + this(host, port, bindAddress, bindPort, protocol, null); + } + + public TcpClientSession(String host, int port, String bindAddress, int bindPort, PacketProtocol protocol, ProxyInfo proxy) { super(host, port, protocol); - this.client = client; + this.bindAddress = bindAddress; + this.bindPort = bindPort; this.proxy = proxy; } @@ -67,8 +80,8 @@ public class TcpClientSession extends TcpSession { bootstrap.channel(NioSocketChannel.class); bootstrap.handler(new ChannelInitializer() { @Override - public void initChannel(Channel channel) throws Exception { - getPacketProtocol().newClientSession(client, TcpClientSession.this); + public void initChannel(Channel channel) { + getPacketProtocol().newClientSession(TcpClientSession.this); channel.config().setOption(ChannelOption.IP_TOS, 0x18); channel.config().setOption(ChannelOption.TCP_NODELAY, false); @@ -78,84 +91,34 @@ public class TcpClientSession extends TcpSession { refreshReadTimeoutHandler(channel); refreshWriteTimeoutHandler(channel); - if(proxy != null) { - switch(proxy.getType()) { - case HTTP: - if(proxy.isAuthenticated()) { - pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); - } else { - pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress())); - } - - break; - case SOCKS4: - if(proxy.isAuthenticated()) { - pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress(), proxy.getUsername())); - } else { - pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress())); - } - - break; - case SOCKS5: - if(proxy.isAuthenticated()) { - pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); - } else { - pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress())); - } - - break; - default: - throw new UnsupportedOperationException("Unsupported proxy type: " + proxy.getType()); - } - } + addProxy(pipeline); pipeline.addLast("encryption", new TcpPacketEncryptor(TcpClientSession.this)); pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this)); pipeline.addLast("manager", TcpClientSession.this); - InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS); - if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) { - pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6; - InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); - ctx.channel().writeAndFlush(new HAProxyMessage( - HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol, - clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(), - clientAddress.getPort(), remoteAddress.getPort() - )); - ctx.pipeline().remove(this); - ctx.pipeline().remove("proxy-protocol-encoder"); - super.channelActive(ctx); - } - }); - pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE); - } + addHAProxySupport(pipeline); } }).group(this.group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); - Runnable connectTask = new Runnable() { - @Override - public void run() { - try { - InetSocketAddress remoteAddress = resolveAddress(); - bootstrap.remoteAddress(remoteAddress); - bootstrap.localAddress(client.getBindAddress(), client.getBindPort()); + Runnable connectTask = () -> { + try { + InetSocketAddress remoteAddress = resolveAddress(); + bootstrap.remoteAddress(remoteAddress); + bootstrap.localAddress(bindAddress, bindPort); - ChannelFuture future = bootstrap.connect().sync(); - if(future.isSuccess()) { - while(!isConnected() && !disconnected) { - try { - Thread.sleep(5); - } catch(InterruptedException e) { - } + ChannelFuture future = bootstrap.connect().sync(); + if(future.isSuccess()) { + while(!isConnected() && !disconnected) { + try { + Thread.sleep(5); + } catch(InterruptedException e) { } } - } catch(Throwable t) { - exceptionCaught(null, t); } + } catch(Throwable t) { + exceptionCaught(null, t); } }; @@ -241,6 +204,61 @@ public class TcpClientSession extends TcpSession { } } + private void addProxy(ChannelPipeline pipeline) { + if(proxy != null) { + switch(proxy.getType()) { + case HTTP: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); + } else { + pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress())); + } + + break; + case SOCKS4: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress(), proxy.getUsername())); + } else { + pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress())); + } + + break; + case SOCKS5: + if(proxy.isAuthenticated()) { + pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); + } else { + pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress())); + } + + break; + default: + throw new UnsupportedOperationException("Unsupported proxy type: " + proxy.getType()); + } + } + } + + private void addHAProxySupport(ChannelPipeline pipeline) { + InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS); + if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) { + pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6; + InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); + ctx.channel().writeAndFlush(new HAProxyMessage( + HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol, + clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(), + clientAddress.getPort(), remoteAddress.getPort() + )); + ctx.pipeline().remove(this); + ctx.pipeline().remove("proxy-protocol-encoder"); + super.channelActive(ctx); + } + }); + pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE); + } + } + @Override public void disconnect(String reason, Throwable cause) { super.disconnect(reason, cause); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java similarity index 69% rename from src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java rename to src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 35650af8..3a1ab09d 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpConnectionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; -import com.github.steveice10.packetlib.ConnectionListener; +import com.github.steveice10.packetlib.AbstractServer; +import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.ServerBootstrap; @@ -18,28 +19,12 @@ import io.netty.util.concurrent.GenericFutureListener; import java.net.InetSocketAddress; -public class TcpConnectionListener implements ConnectionListener { - private String host; - private int port; - private Server server; - +public class TcpServer extends AbstractServer { private EventLoopGroup group; private Channel channel; - public TcpConnectionListener(String host, int port, Server server) { - this.host = host; - this.port = port; - this.server = server; - } - - @Override - public String getHost() { - return this.host; - } - - @Override - public int getPort() { - return this.port; + public TcpServer(String host, int port, Class protocol) { + super(host, port, protocol); } @Override @@ -48,17 +33,7 @@ public class TcpConnectionListener implements ConnectionListener { } @Override - public void bind() { - this.bind(true); - } - - @Override - public void bind(boolean wait) { - this.bind(wait, null); - } - - @Override - public void bind(boolean wait, final Runnable callback) { + public void bindImpl(boolean wait, final Runnable callback) { if(this.group != null || this.channel != null) { return; } @@ -68,10 +43,10 @@ public class TcpConnectionListener implements ConnectionListener { @Override public void initChannel(Channel channel) throws Exception { InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); - PacketProtocol protocol = server.createPacketProtocol(); + PacketProtocol protocol = createPacketProtocol(); - TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, server); - session.getPacketProtocol().newServerSession(server, session); + TcpSession session = new TcpServerSession(address.getHostName(), address.getPort(), protocol, TcpServer.this); + session.getPacketProtocol().newServerSession(TcpServer.this, session); channel.config().setOption(ChannelOption.IP_TOS, 0x18); channel.config().setOption(ChannelOption.TCP_NODELAY, false); @@ -86,7 +61,7 @@ public class TcpConnectionListener implements ConnectionListener { pipeline.addLast("codec", new TcpPacketCodec(session)); pipeline.addLast("manager", session); } - }).group(this.group).localAddress(this.host, this.port).bind(); + }).group(this.group).localAddress(this.getHost(), this.getPort()).bind(); if(wait) { try { @@ -119,17 +94,7 @@ public class TcpConnectionListener implements ConnectionListener { } @Override - public void close() { - this.close(false); - } - - @Override - public void close(boolean wait) { - this.close(wait, null); - } - - @Override - public void close(boolean wait, final Runnable callback) { + public void closeImpl(boolean wait, final Runnable callback) { if(this.channel != null) { if(this.channel.isOpen()) { ChannelFuture future = this.channel.close(); @@ -143,18 +108,15 @@ public class TcpConnectionListener implements ConnectionListener { callback.run(); } } else { - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(future.isSuccess()) { - if(callback != null) { - callback.run(); - } - } else { - System.err.println("[ERROR] Failed to asynchronously close connection listener."); - if(future.cause() != null) { - future.cause().printStackTrace(); - } + future.addListener((ChannelFutureListener) future1 -> { + if(future1.isSuccess()) { + if(callback != null) { + callback.run(); + } + } else { + System.err.println("[ERROR] Failed to asynchronously close connection listener."); + if(future1.cause() != null) { + future1.cause().printStackTrace(); } } }); @@ -174,8 +136,8 @@ public class TcpConnectionListener implements ConnectionListener { } else { future.addListener(new GenericFutureListener() { @Override - public void operationComplete(Future future) throws Exception { - if(!future.isSuccess()) { + public void operationComplete(Future future) { + if(!future.isSuccess() && getGlobalFlag(BuiltinFlags.PRINT_DEBUG, false)) { System.err.println("[ERROR] Failed to asynchronously close connection listener."); if(future.cause() != null) { future.cause().printStackTrace(); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java index 4d0f205a..8591fb92 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java @@ -8,9 +8,9 @@ import java.util.HashMap; import java.util.Map; public class TcpServerSession extends TcpSession { - private Server server; + private TcpServer server; - public TcpServerSession(String host, int port, PacketProtocol protocol, Server server) { + public TcpServerSession(String host, int port, PacketProtocol protocol, TcpServer server) { super(host, port, protocol); this.server = server; } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index e5f1347b..2ce8b375 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -253,12 +253,9 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp if(this.channel != null && this.channel.isOpen()) { this.callEvent(new DisconnectingEvent(this, reason, cause)); - this.channel.flush().close().addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - callEvent(new DisconnectedEvent(TcpSession.this, reason != null ? reason : "Connection closed.", cause)); - } - }); + this.channel.flush().close().addListener((ChannelFutureListener) future -> + callEvent(new DisconnectedEvent(TcpSession.this, + reason != null ? reason : "Connection closed.", cause))); } else { this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java deleted file mode 100644 index 0fad540e..00000000 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSessionFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.steveice10.packetlib.tcp; - -import com.github.steveice10.packetlib.Client; -import com.github.steveice10.packetlib.ConnectionListener; -import com.github.steveice10.packetlib.ProxyInfo; -import com.github.steveice10.packetlib.Server; -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.SessionFactory; - -/** - * A session factory used to create TCP sessions. - */ -public class TcpSessionFactory implements SessionFactory { - private ProxyInfo clientProxy; - - public TcpSessionFactory() { - } - - public TcpSessionFactory(ProxyInfo clientProxy) { - this.clientProxy = clientProxy; - } - - @Override - public Session createClientSession(final Client client) { - return new TcpClientSession(client.getHost(), client.getPort(), client.getPacketProtocol(), client, this.clientProxy); - } - - @Override - public ConnectionListener createServerListener(final Server server) { - return new TcpConnectionListener(server.getHost(), server.getPort(), server); - } -} From 312cff5f975be54cf2d92208ae2947dbda8b9f59 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 16 Mar 2021 20:07:03 -0400 Subject: [PATCH 126/180] Optimize SRV resolving only when required - Add an option to disable SRV resolving - Don't resolve SRV records if not a domain (in one instance this shortened loading times by five seconds) --- .../steveice10/packetlib/BuiltinFlags.java | 5 ++ .../packetlib/tcp/TcpClientSession.java | 84 ++++++++++--------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java index b60bcafa..0080943f 100644 --- a/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java +++ b/src/main/java/com/github/steveice10/packetlib/BuiltinFlags.java @@ -13,6 +13,11 @@ public class BuiltinFlags { public static final String CLIENT_PROXIED_ADDRESS = "client-proxied-address"; + /** + * When set to false, an SRV record resolve is not attempted. + */ + public static final String ATTEMPT_SRV_RESOLVE = "attempt-srv-resolve"; + private BuiltinFlags() { } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 725e6068..2f9690cc 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -40,6 +40,8 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; public class TcpClientSession extends TcpSession { + private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"; + private String bindAddress; private int bindPort; private ProxyInfo proxy; @@ -140,52 +142,56 @@ public class TcpClientSession extends TcpSession { System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\"."); } - DnsNameResolver resolver = null; - AddressedEnvelope envelope = null; - try { - resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(NioDatagramChannel.class) - .build(); - envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); + if(getFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, true) && (!this.host.matches(IP_REGEX) && !this.host.equalsIgnoreCase("localhost"))) { + DnsNameResolver resolver = null; + AddressedEnvelope envelope = null; + try { + resolver = new DnsNameResolverBuilder(this.group.next()) + .channelType(NioDatagramChannel.class) + .build(); + envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); - DnsResponse response = envelope.content(); - if(response.count(DnsSection.ANSWER) > 0) { - DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0); - if(record.type() == DnsRecordType.SRV) { - ByteBuf buf = record.content(); - buf.skipBytes(4); // Skip priority and weight. + DnsResponse response = envelope.content(); + if(response.count(DnsSection.ANSWER) > 0) { + DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0); + if(record.type() == DnsRecordType.SRV) { + ByteBuf buf = record.content(); + buf.skipBytes(4); // Skip priority and weight. - int port = buf.readUnsignedShort(); - String host = DefaultDnsRecordDecoder.decodeName(buf); - if(host.endsWith(".")) { - host = host.substring(0, host.length() - 1); + int port = buf.readUnsignedShort(); + String host = DefaultDnsRecordDecoder.decodeName(buf); + if(host.endsWith(".")) { + host = host.substring(0, host.length() - 1); + } + + if(debug) { + System.out.println("[PacketLib] Found SRV record containing \"" + host + ":" + port + "\"."); + } + + this.host = host; + this.port = port; + } else if(debug) { + System.out.println("[PacketLib] Received non-SRV record in response."); } - - if(debug) { - System.out.println("[PacketLib] Found SRV record containing \"" + host + ":" + port + "\"."); - } - - this.host = host; - this.port = port; } else if(debug) { - System.out.println("[PacketLib] Received non-SRV record in response."); + System.out.println("[PacketLib] No SRV record found."); + } + } catch(Exception e) { + if(debug) { + System.out.println("[PacketLib] Failed to resolve SRV record."); + e.printStackTrace(); + } + } finally { + if(envelope != null) { + envelope.release(); } - } else if(debug) { - System.out.println("[PacketLib] No SRV record found."); - } - } catch(Exception e) { - if(debug) { - System.out.println("[PacketLib] Failed to resolve SRV record."); - e.printStackTrace(); - } - } finally { - if(envelope != null) { - envelope.release(); - } - if(resolver != null) { - resolver.close(); + if(resolver != null) { + resolver.close(); + } } + } else if(debug) { + System.out.println("[PacketLib] Not resolving SRV record for " + this.host); } // Resolve host here From fa191ed83c75bb4c9125404e98c8419382bf8d92 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 13 May 2021 00:13:13 -0700 Subject: [PATCH 127/180] Release 2.0. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cd93e51e..c4c943fe 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.0-SNAPSHOT + 2.0 jar PacketLib From b343e2576580693324fcf1d69a4b124a9fa60b31 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 13 May 2021 00:13:54 -0700 Subject: [PATCH 128/180] Bump to snapshot version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c4c943fe..c1f0caeb 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.0 + 2.1-SNAPSHOT jar PacketLib From 14e98718c149bfeaf0a202ebd03e8807b5d77113 Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Thu, 13 May 2021 00:28:23 -0700 Subject: [PATCH 129/180] Update license year. --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 10a55911..8710b0b8 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (C) 2013-2018 Steveice10 +Copyright (C) 2013-2021 Steveice10 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From e6ca9ecc8dd64e0358f0c1c4f3373ee8981692b3 Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 17:17:49 +0200 Subject: [PATCH 130/180] Check is epoll available and use it if so --- .../steveice10/packetlib/tcp/TcpClientSession.java | 13 +++++++++---- .../github/steveice10/packetlib/tcp/TcpServer.java | 9 ++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 2f9690cc..cd9e5caf 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -14,9 +14,13 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioDatagramChannel; -import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; import io.netty.handler.codec.dns.DefaultDnsRawRecord; import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; @@ -47,6 +51,7 @@ public class TcpClientSession extends TcpSession { private ProxyInfo proxy; private EventLoopGroup group; + private final boolean epollAvailable = Epoll.isAvailable(); public TcpClientSession(String host, int port, PacketProtocol protocol) { this(host, port, protocol, null); @@ -76,10 +81,10 @@ public class TcpClientSession extends TcpSession { } try { - this.group = new NioEventLoopGroup(); + this.group = epollAvailable ? new EpollEventLoopGroup() : new NioEventLoopGroup(); final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(NioSocketChannel.class); + bootstrap.channel(epollAvailable ? EpollServerSocketChannel.class : NioServerSocketChannel.class); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { @@ -147,7 +152,7 @@ public class TcpClientSession extends TcpSession { AddressedEnvelope envelope = null; try { resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(NioDatagramChannel.class) + .channelType(epollAvailable ? EpollDatagramChannel.class : NioDatagramChannel.class) .build(); envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 3a1ab09d..43ebe3f7 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -2,7 +2,6 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.AbstractServer; import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -12,6 +11,9 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.util.concurrent.Future; @@ -38,8 +40,9 @@ public class TcpServer extends AbstractServer { return; } - this.group = new NioEventLoopGroup(); - ChannelFuture future = new ServerBootstrap().channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + final boolean epollAvailable = Epoll.isAvailable(); + this.group = epollAvailable ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + ChannelFuture future = new ServerBootstrap().channel(epollAvailable ? EpollServerSocketChannel.class : NioServerSocketChannel.class).childHandler(new ChannelInitializer() { @Override public void initChannel(Channel channel) throws Exception { InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); From e992437da651825a607630ba390a68c938b6a45b Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 17:25:59 +0200 Subject: [PATCH 131/180] Changew ServerSocketChannel implementation classes to SocketChannel implementation types --- .../github/steveice10/packetlib/tcp/TcpClientSession.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index cd9e5caf..f65aebcb 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -17,10 +17,10 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollEventLoopGroup; -import io.netty.channel.epoll.EpollServerSocketChannel; +import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioDatagramChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; import io.netty.handler.codec.dns.DefaultDnsRawRecord; import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; @@ -84,7 +84,7 @@ public class TcpClientSession extends TcpSession { this.group = epollAvailable ? new EpollEventLoopGroup() : new NioEventLoopGroup(); final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(epollAvailable ? EpollServerSocketChannel.class : NioServerSocketChannel.class); + bootstrap.channel(epollAvailable ? EpollSocketChannel.class : NioSocketChannel.class); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { From 5282527a3a492baea0e5dccf28f456827642ee28 Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 18:29:38 +0200 Subject: [PATCH 132/180] Update dependiences and add io_uring pool --- pom.xml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index c1f0caeb..34acaad8 100644 --- a/pom.xml +++ b/pom.xml @@ -49,20 +49,26 @@ io.netty netty-all - 4.1.56.Final + 4.1.66.Final compile io.netty netty-codec-haproxy - 4.1.56.Final + 4.1.66.Final compile true + + io.netty.incubator + netty-incubator-transport-native-io_uring + 0.0.8.Final + linux-x86_64 + com.github.spotbugs spotbugs-annotations - 4.2.0 + 4.3.0 From d23c3ac8feed79113708417e34d51d8f5f37382c Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 18:59:17 +0200 Subject: [PATCH 133/180] Implement IO_URING async syscalls interface --- .../packetlib/tcp/TcpClientSession.java | 34 +++++++++++++-- .../steveice10/packetlib/tcp/TcpServer.java | 42 ++++++++++++++----- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index f65aebcb..c38a1e5e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -19,8 +19,8 @@ import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; -import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; import io.netty.handler.codec.dns.DefaultDnsRawRecord; import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; @@ -35,6 +35,9 @@ import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; +import io.netty.incubator.channel.uring.IOUring; +import io.netty.incubator.channel.uring.IOUringEventLoopGroup; +import io.netty.incubator.channel.uring.IOUringSocketChannel; import io.netty.resolver.dns.DnsNameResolver; import io.netty.resolver.dns.DnsNameResolverBuilder; @@ -51,6 +54,7 @@ public class TcpClientSession extends TcpSession { private ProxyInfo proxy; private EventLoopGroup group; + private Class socketChannel; private final boolean epollAvailable = Epoll.isAvailable(); public TcpClientSession(String host, int port, PacketProtocol protocol) { @@ -72,6 +76,17 @@ public class TcpClientSession extends TcpSession { this.proxy = proxy; } + public enum TransportMethod { + NIO, EPOLL, IO_URING; + } + + private TransportMethod determineTransportMethod() { + if (IOUring.isAvailable()) return TransportMethod.IO_URING; + if (Epoll.isAvailable()) return TransportMethod.EPOLL; + return TransportMethod.NIO; + } + + @Override public void connect(boolean wait) { if(this.disconnected) { @@ -81,10 +96,23 @@ public class TcpClientSession extends TcpSession { } try { - this.group = epollAvailable ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + switch (determineTransportMethod()) { + case IO_URING: + this.group = new IOUringEventLoopGroup(); + this.socketChannel = IOUringSocketChannel.class; + break; + case EPOLL: + this.group = new EpollEventLoopGroup(); + this.socketChannel = EpollSocketChannel.class; + break; + case NIO: + this.group = new NioEventLoopGroup(); + this.socketChannel = EpollSocketChannel.class; + break; + } final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(epollAvailable ? EpollSocketChannel.class : NioSocketChannel.class); + bootstrap.channel(socketChannel); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 43ebe3f7..7373d6d8 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -4,18 +4,16 @@ import com.github.steveice10.packetlib.AbstractServer; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.*; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.incubator.channel.uring.IOUring; +import io.netty.incubator.channel.uring.IOUringEventLoopGroup; +import io.netty.incubator.channel.uring.IOUringServerSocketChannel; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; @@ -23,6 +21,7 @@ import java.net.InetSocketAddress; public class TcpServer extends AbstractServer { private EventLoopGroup group; + private Class serverSocketChannel; private Channel channel; public TcpServer(String host, int port, Class protocol) { @@ -34,15 +33,38 @@ public class TcpServer extends AbstractServer { return this.channel != null && this.channel.isOpen(); } + public enum TransportMethod { + NIO, EPOLL, IO_URING; + } + + private TransportMethod determineTransportMethod() { + if (IOUring.isAvailable()) return TransportMethod.IO_URING; + if (Epoll.isAvailable()) return TransportMethod.EPOLL; + return TransportMethod.NIO; + } + @Override public void bindImpl(boolean wait, final Runnable callback) { if(this.group != null || this.channel != null) { return; } - final boolean epollAvailable = Epoll.isAvailable(); - this.group = epollAvailable ? new EpollEventLoopGroup() : new NioEventLoopGroup(); - ChannelFuture future = new ServerBootstrap().channel(epollAvailable ? EpollServerSocketChannel.class : NioServerSocketChannel.class).childHandler(new ChannelInitializer() { + switch (determineTransportMethod()) { + case IO_URING: + this.group = new IOUringEventLoopGroup(); + this.serverSocketChannel = IOUringServerSocketChannel.class; + break; + case EPOLL: + this.group = new EpollEventLoopGroup(); + this.serverSocketChannel = EpollServerSocketChannel.class; + break; + case NIO: + this.group = new NioEventLoopGroup(); + this.serverSocketChannel = NioServerSocketChannel.class; + break; + } + + ChannelFuture future = new ServerBootstrap().channel(this.serverSocketChannel).childHandler(new ChannelInitializer() { @Override public void initChannel(Channel channel) throws Exception { InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); From bc42215a4a2cb79da44eaa2dfb685063497183ea Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 19:02:04 +0200 Subject: [PATCH 134/180] Fix mistake in socket channel initialization for Nio --- .../com/github/steveice10/packetlib/tcp/TcpClientSession.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index c38a1e5e..f0119c0c 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -21,6 +21,7 @@ import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; import io.netty.handler.codec.dns.DefaultDnsRawRecord; import io.netty.handler.codec.dns.DefaultDnsRecordDecoder; @@ -107,7 +108,7 @@ public class TcpClientSession extends TcpSession { break; case NIO: this.group = new NioEventLoopGroup(); - this.socketChannel = EpollSocketChannel.class; + this.socketChannel = NioSocketChannel.class; break; } From 09f620eb3199e75d748f7a433fb57d4162e8baf1 Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 19:44:00 +0200 Subject: [PATCH 135/180] Add io_uring DatagramChannel to DNS resolver queries --- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index f0119c0c..53220ee0 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -19,6 +19,7 @@ import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioSocketChannel; @@ -37,6 +38,7 @@ import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; import io.netty.incubator.channel.uring.IOUring; +import io.netty.incubator.channel.uring.IOUringDatagramChannel; import io.netty.incubator.channel.uring.IOUringEventLoopGroup; import io.netty.incubator.channel.uring.IOUringSocketChannel; import io.netty.resolver.dns.DnsNameResolver; @@ -56,7 +58,7 @@ public class TcpClientSession extends TcpSession { private EventLoopGroup group; private Class socketChannel; - private final boolean epollAvailable = Epoll.isAvailable(); + private Class datagramChannel; public TcpClientSession(String host, int port, PacketProtocol protocol) { this(host, port, protocol, null); @@ -101,19 +103,22 @@ public class TcpClientSession extends TcpSession { case IO_URING: this.group = new IOUringEventLoopGroup(); this.socketChannel = IOUringSocketChannel.class; + this.datagramChannel = IOUringDatagramChannel.class; break; case EPOLL: this.group = new EpollEventLoopGroup(); this.socketChannel = EpollSocketChannel.class; + this.datagramChannel = EpollDatagramChannel.class; break; case NIO: this.group = new NioEventLoopGroup(); this.socketChannel = NioSocketChannel.class; + this.datagramChannel = NioDatagramChannel.class; break; } final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(socketChannel); + bootstrap.channel(this.socketChannel); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { @@ -181,7 +186,7 @@ public class TcpClientSession extends TcpSession { AddressedEnvelope envelope = null; try { resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(epollAvailable ? EpollDatagramChannel.class : NioDatagramChannel.class) + .channelType(this.datagramChannel) .build(); envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); From d9a277ffb41b261169d411b251ab104809b23e00 Mon Sep 17 00:00:00 2001 From: TeksuSiK Date: Sun, 15 Aug 2021 21:12:25 +0200 Subject: [PATCH 136/180] Move determine transport method to helper --- .../packetlib/helper/TransportHelper.java | 16 +++++++++++++ .../packetlib/tcp/TcpClientSession.java | 16 ++----------- .../steveice10/packetlib/tcp/TcpServer.java | 23 ++++++++----------- 3 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java diff --git a/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java b/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java new file mode 100644 index 00000000..88a9e1ff --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java @@ -0,0 +1,16 @@ +package com.github.steveice10.packetlib.helper; + +import io.netty.channel.epoll.Epoll; +import io.netty.incubator.channel.uring.IOUring; + +public class TransportHelper { + public enum TransportMethod { + NIO, EPOLL, IO_URING; + } + + public static TransportMethod determineTransportMethod() { + if (IOUring.isAvailable()) return TransportMethod.IO_URING; + if (Epoll.isAvailable()) return TransportMethod.EPOLL; + return TransportMethod.NIO; + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 53220ee0..8348cce6 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -2,6 +2,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.ProxyInfo; +import com.github.steveice10.packetlib.helper.TransportHelper; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; @@ -14,7 +15,6 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; -import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollSocketChannel; @@ -37,7 +37,6 @@ import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.handler.proxy.HttpProxyHandler; import io.netty.handler.proxy.Socks4ProxyHandler; import io.netty.handler.proxy.Socks5ProxyHandler; -import io.netty.incubator.channel.uring.IOUring; import io.netty.incubator.channel.uring.IOUringDatagramChannel; import io.netty.incubator.channel.uring.IOUringEventLoopGroup; import io.netty.incubator.channel.uring.IOUringSocketChannel; @@ -79,17 +78,6 @@ public class TcpClientSession extends TcpSession { this.proxy = proxy; } - public enum TransportMethod { - NIO, EPOLL, IO_URING; - } - - private TransportMethod determineTransportMethod() { - if (IOUring.isAvailable()) return TransportMethod.IO_URING; - if (Epoll.isAvailable()) return TransportMethod.EPOLL; - return TransportMethod.NIO; - } - - @Override public void connect(boolean wait) { if(this.disconnected) { @@ -99,7 +87,7 @@ public class TcpClientSession extends TcpSession { } try { - switch (determineTransportMethod()) { + switch (TransportHelper.determineTransportMethod()) { case IO_URING: this.group = new IOUringEventLoopGroup(); this.socketChannel = IOUringSocketChannel.class; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 7373d6d8..97b56297 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -2,16 +2,21 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.AbstractServer; import com.github.steveice10.packetlib.BuiltinFlags; +import com.github.steveice10.packetlib.helper.TransportHelper; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.*; -import io.netty.channel.epoll.Epoll; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.incubator.channel.uring.IOUring; import io.netty.incubator.channel.uring.IOUringEventLoopGroup; import io.netty.incubator.channel.uring.IOUringServerSocketChannel; import io.netty.util.concurrent.Future; @@ -33,23 +38,13 @@ public class TcpServer extends AbstractServer { return this.channel != null && this.channel.isOpen(); } - public enum TransportMethod { - NIO, EPOLL, IO_URING; - } - - private TransportMethod determineTransportMethod() { - if (IOUring.isAvailable()) return TransportMethod.IO_URING; - if (Epoll.isAvailable()) return TransportMethod.EPOLL; - return TransportMethod.NIO; - } - @Override public void bindImpl(boolean wait, final Runnable callback) { if(this.group != null || this.channel != null) { return; } - switch (determineTransportMethod()) { + switch (TransportHelper.determineTransportMethod()) { case IO_URING: this.group = new IOUringEventLoopGroup(); this.serverSocketChannel = IOUringServerSocketChannel.class; From f750ba1537bec3dd17c565ac689a36a0c38d0ad1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:43:15 -0400 Subject: [PATCH 137/180] Add Discord link --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dfa4ffd0..9be904bc 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,9 @@ See [examples/com/github/steveice10/packetlib/test](https://github.com/Steveice1 ## Building the Source PacketLib uses Maven to manage dependencies. Simply run 'mvn clean install' in the source's directory. +## Support and development + +Please join us at https://discord.gg/geysermc under #mcprotocollib for discussion and support for this project. + ## License PacketLib is licensed under the **[MIT license](http://www.opensource.org/licenses/mit-license.html)**. From ccfb1aa94d25e4ad4fad52755d59fb88b10fd71c Mon Sep 17 00:00:00 2001 From: RK_01 <50594595+RaphiMC@users.noreply.github.com> Date: Tue, 26 Oct 2021 23:52:57 +0200 Subject: [PATCH 138/180] Fix memory leak by closing De-/Inflater (#36) --- .../steveice10/packetlib/tcp/TcpPacketCompression.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index 69c4b7b1..f0f777aa 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -25,6 +25,14 @@ public class TcpPacketCompression extends ByteToMessageCodec { this.session = session; } + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + super.handlerRemoved(ctx); + + this.deflater.end(); + this.inflater.end(); + } + @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int readable = in.readableBytes(); From 2776c24e05e289043b7ecc86fa67abee46b1342c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 12 Nov 2021 11:12:52 -0500 Subject: [PATCH 139/180] Merge in Geyser changes to master (#38) * Use TCP_NODELAY and Epoll where possible * Add KQueue and respect disableNativeEventLoop property * Inject * works? * Make it pretty * Don't create a TCP EventLoopGroup unless needed * Add method for determining if we connected internally * fix datagrams * Support HAProxy probably * Set a bunch of things as final * Allow setting direct ByteBufs preferred * Expose channel; don't do packets on another thread * Don't set channel to null and do some more optimizing * Remove custom thread factory * Remove unused SocketChannelWrapper class * Remove all local channel classes * Allow for packets to be handled on a separate thread Co-authored-by: creeper123123321 <7974274+creeper123123321@users.noreply.github.com> --- .../packetlib/helper/TransportHelper.java | 20 ++- .../steveice10/packetlib/packet/Packet.java | 6 +- .../packetlib/tcp/TcpClientSession.java | 152 +++++++++--------- .../packetlib/tcp/TcpPacketCodec.java | 2 +- .../packetlib/tcp/TcpPacketCompression.java | 8 +- .../packetlib/tcp/TcpPacketEncryptor.java | 2 +- .../packetlib/tcp/TcpPacketSizer.java | 2 +- .../steveice10/packetlib/tcp/TcpServer.java | 31 ++-- .../steveice10/packetlib/tcp/TcpSession.java | 130 +++++++-------- 9 files changed, 178 insertions(+), 175 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java b/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java index 88a9e1ff..87a75bfa 100644 --- a/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java +++ b/src/main/java/com/github/steveice10/packetlib/helper/TransportHelper.java @@ -1,16 +1,30 @@ package com.github.steveice10.packetlib.helper; import io.netty.channel.epoll.Epoll; +import io.netty.channel.kqueue.KQueue; import io.netty.incubator.channel.uring.IOUring; public class TransportHelper { public enum TransportMethod { - NIO, EPOLL, IO_URING; + NIO, EPOLL, KQUEUE, IO_URING } public static TransportMethod determineTransportMethod() { - if (IOUring.isAvailable()) return TransportMethod.IO_URING; - if (Epoll.isAvailable()) return TransportMethod.EPOLL; + if (isClassAvailable("io.netty.incubator.channel.uring.IOUring") && IOUring.isAvailable()) return TransportMethod.IO_URING; + if (isClassAvailable("io.netty.channel.epoll.Epoll") && Epoll.isAvailable()) return TransportMethod.EPOLL; + if (isClassAvailable("io.netty.channel.kqueue.KQueue") && KQueue.isAvailable()) return TransportMethod.KQUEUE; return TransportMethod.NIO; } + + /** + * Used so implementations can opt to remove these dependencies if so desired + */ + private static boolean isClassAvailable(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } } diff --git a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java index 139bd7e4..36d586f3 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java @@ -23,7 +23,7 @@ public interface Packet { * @param out The output destination to write to. * @throws IOException If an I/O error occurs. */ - public void write(NetOutput out) throws IOException; + void write(NetOutput out) throws IOException; /** * Gets whether the packet has handling priority. @@ -32,5 +32,7 @@ public interface Packet { * * @return Whether the packet has priority. */ - public boolean isPriority(); + default boolean isPriority() { + return false; + } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 8348cce6..39aa48c8 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -8,7 +8,6 @@ import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.AddressedEnvelope; import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; @@ -20,7 +19,10 @@ import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramChannel; -import io.netty.channel.socket.SocketChannel; +import io.netty.channel.*; +import io.netty.channel.kqueue.KQueueDatagramChannel; +import io.netty.channel.kqueue.KQueueEventLoopGroup; +import io.netty.channel.kqueue.KQueueSocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.dns.DefaultDnsQuestion; @@ -42,22 +44,17 @@ import io.netty.incubator.channel.uring.IOUringEventLoopGroup; import io.netty.incubator.channel.uring.IOUringSocketChannel; import io.netty.resolver.dns.DnsNameResolver; import io.netty.resolver.dns.DnsNameResolverBuilder; - -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; +import java.net.*; public class TcpClientSession extends TcpSession { private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"; + private static Class CHANNEL_CLASS; + private static Class DATAGRAM_CHANNEL_CLASS; + private static EventLoopGroup EVENT_LOOP_GROUP; - private String bindAddress; - private int bindPort; - private ProxyInfo proxy; - - private EventLoopGroup group; - private Class socketChannel; - private Class datagramChannel; + private final String bindAddress; + private final int bindPort; + private final ProxyInfo proxy; public TcpClientSession(String host, int port, PacketProtocol protocol) { this(host, port, protocol, null); @@ -82,38 +79,31 @@ public class TcpClientSession extends TcpSession { public void connect(boolean wait) { if(this.disconnected) { throw new IllegalStateException("Session has already been disconnected."); - } else if(this.group != null) { - return; + } + + boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); + + if (CHANNEL_CLASS == null) { + createTcpEventLoopGroup(); } try { - switch (TransportHelper.determineTransportMethod()) { - case IO_URING: - this.group = new IOUringEventLoopGroup(); - this.socketChannel = IOUringSocketChannel.class; - this.datagramChannel = IOUringDatagramChannel.class; - break; - case EPOLL: - this.group = new EpollEventLoopGroup(); - this.socketChannel = EpollSocketChannel.class; - this.datagramChannel = EpollDatagramChannel.class; - break; - case NIO: - this.group = new NioEventLoopGroup(); - this.socketChannel = NioSocketChannel.class; - this.datagramChannel = NioDatagramChannel.class; - break; - } - final Bootstrap bootstrap = new Bootstrap(); - bootstrap.channel(this.socketChannel); + bootstrap.channel(CHANNEL_CLASS); bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { getPacketProtocol().newClientSession(TcpClientSession.this); channel.config().setOption(ChannelOption.IP_TOS, 0x18); - channel.config().setOption(ChannelOption.TCP_NODELAY, false); + try { + channel.config().setOption(ChannelOption.TCP_NODELAY, true); + } catch (ChannelException e) { + if(debug) { + System.out.println("Exception while trying to set TCP_NODELAY"); + e.printStackTrace(); + } + } ChannelPipeline pipeline = channel.pipeline(); @@ -129,33 +119,17 @@ public class TcpClientSession extends TcpSession { addHAProxySupport(pipeline); } - }).group(this.group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); + }).group(EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); - Runnable connectTask = () -> { - try { - InetSocketAddress remoteAddress = resolveAddress(); - bootstrap.remoteAddress(remoteAddress); - bootstrap.localAddress(bindAddress, bindPort); + InetSocketAddress remoteAddress = resolveAddress(); + bootstrap.remoteAddress(remoteAddress); + bootstrap.localAddress(bindAddress, bindPort); - ChannelFuture future = bootstrap.connect().sync(); - if(future.isSuccess()) { - while(!isConnected() && !disconnected) { - try { - Thread.sleep(5); - } catch(InterruptedException e) { - } - } - } - } catch(Throwable t) { - exceptionCaught(null, t); + bootstrap.connect().addListener((future) -> { + if (!future.isSuccess()) { + exceptionCaught(null, future.cause()); } - }; - - if(wait) { - connectTask.run(); - } else { - new Thread(connectTask).start(); - } + }); } catch(Throwable t) { exceptionCaught(null, t); } @@ -165,7 +139,7 @@ public class TcpClientSession extends TcpSession { boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); String name = this.getPacketProtocol().getSRVRecordPrefix() + "._tcp." + this.getHost(); - if(debug) { + if (debug) { System.out.println("[PacketLib] Attempting SRV lookup for \"" + name + "\"."); } @@ -173,21 +147,21 @@ public class TcpClientSession extends TcpSession { DnsNameResolver resolver = null; AddressedEnvelope envelope = null; try { - resolver = new DnsNameResolverBuilder(this.group.next()) - .channelType(this.datagramChannel) + resolver = new DnsNameResolverBuilder(EVENT_LOOP_GROUP.next()) + .channelType(DATAGRAM_CHANNEL_CLASS) .build(); envelope = resolver.query(new DefaultDnsQuestion(name, DnsRecordType.SRV)).get(); DnsResponse response = envelope.content(); - if(response.count(DnsSection.ANSWER) > 0) { + if (response.count(DnsSection.ANSWER) > 0) { DefaultDnsRawRecord record = response.recordAt(DnsSection.ANSWER, 0); - if(record.type() == DnsRecordType.SRV) { + if (record.type() == DnsRecordType.SRV) { ByteBuf buf = record.content(); buf.skipBytes(4); // Skip priority and weight. int port = buf.readUnsignedShort(); String host = DefaultDnsRecordDecoder.decodeName(buf); - if(host.endsWith(".")) { + if (host.endsWith(".")) { host = host.substring(0, host.length() - 1); } @@ -197,23 +171,23 @@ public class TcpClientSession extends TcpSession { this.host = host; this.port = port; - } else if(debug) { + } else if (debug) { System.out.println("[PacketLib] Received non-SRV record in response."); } - } else if(debug) { + } else if (debug) { System.out.println("[PacketLib] No SRV record found."); } } catch(Exception e) { - if(debug) { + if (debug) { System.out.println("[PacketLib] Failed to resolve SRV record."); e.printStackTrace(); } } finally { - if(envelope != null) { + if (envelope != null) { envelope.release(); } - if(resolver != null) { + if (resolver != null) { resolver.close(); } } @@ -241,7 +215,7 @@ public class TcpClientSession extends TcpSession { if(proxy != null) { switch(proxy.getType()) { case HTTP: - if(proxy.isAuthenticated()) { + if (proxy.isAuthenticated()) { pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); } else { pipeline.addFirst("proxy", new HttpProxyHandler(proxy.getAddress())); @@ -249,7 +223,7 @@ public class TcpClientSession extends TcpSession { break; case SOCKS4: - if(proxy.isAuthenticated()) { + if (proxy.isAuthenticated()) { pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress(), proxy.getUsername())); } else { pipeline.addFirst("proxy", new Socks4ProxyHandler(proxy.getAddress())); @@ -257,7 +231,7 @@ public class TcpClientSession extends TcpSession { break; case SOCKS5: - if(proxy.isAuthenticated()) { + if (proxy.isAuthenticated()) { pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress(), proxy.getUsername(), proxy.getPassword())); } else { pipeline.addFirst("proxy", new Socks5ProxyHandler(proxy.getAddress())); @@ -295,9 +269,33 @@ public class TcpClientSession extends TcpSession { @Override public void disconnect(String reason, Throwable cause) { super.disconnect(reason, cause); - if(this.group != null) { - this.group.shutdownGracefully(); - this.group = null; + } + + private static void createTcpEventLoopGroup() { + if (CHANNEL_CLASS != null) { + return; + } + + switch (TransportHelper.determineTransportMethod()) { + case IO_URING: + EVENT_LOOP_GROUP = new IOUringEventLoopGroup(); + CHANNEL_CLASS = IOUringSocketChannel.class; + DATAGRAM_CHANNEL_CLASS = IOUringDatagramChannel.class; + break; + case EPOLL: + EVENT_LOOP_GROUP = new EpollEventLoopGroup(); + CHANNEL_CLASS = EpollSocketChannel.class; + DATAGRAM_CHANNEL_CLASS = EpollDatagramChannel.class; + break; + case KQUEUE: + EVENT_LOOP_GROUP = new KQueueEventLoopGroup(); + CHANNEL_CLASS = KQueueSocketChannel.class; + DATAGRAM_CHANNEL_CLASS = KQueueDatagramChannel.class; + case NIO: + EVENT_LOOP_GROUP = new NioEventLoopGroup(); + CHANNEL_CLASS = NioSocketChannel.class; + DATAGRAM_CHANNEL_CLASS = NioDatagramChannel.class; + break; } } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 1f42e2c7..ac918eeb 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -15,7 +15,7 @@ import io.netty.handler.codec.ByteToMessageCodec; import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { - private Session session; + private final Session session; public TcpPacketCodec(Session session) { this.session = session; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index f0f777aa..faa4ca86 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -16,10 +16,10 @@ import java.util.zip.Inflater; public class TcpPacketCompression extends ByteToMessageCodec { private static final int MAX_COMPRESSED_SIZE = 2097152; - private Session session; - private Deflater deflater = new Deflater(); - private Inflater inflater = new Inflater(); - private byte buf[] = new byte[8192]; + private final Session session; + private final Deflater deflater = new Deflater(); + private final Inflater inflater = new Inflater(); + private final byte[] buf = new byte[8192]; public TcpPacketCompression(Session session) { this.session = session; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java index a58e52eb..e71159d1 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java @@ -8,7 +8,7 @@ import io.netty.handler.codec.ByteToMessageCodec; import java.util.List; public class TcpPacketEncryptor extends ByteToMessageCodec { - private Session session; + private final Session session; private byte[] decryptedArray = new byte[0]; private byte[] encryptedArray = new byte[0]; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index 65e633ca..0aeeb4d7 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -12,7 +12,7 @@ import io.netty.handler.codec.CorruptedFrameException; import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { - private Session session; + private final Session session; public TcpPacketSizer(Session session) { this.session = session; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 97b56297..d84e9fac 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -14,6 +14,7 @@ import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; +import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -61,7 +62,7 @@ public class TcpServer extends AbstractServer { ChannelFuture future = new ServerBootstrap().channel(this.serverSocketChannel).childHandler(new ChannelInitializer() { @Override - public void initChannel(Channel channel) throws Exception { + public void initChannel(Channel channel) { InetSocketAddress address = (InetSocketAddress) channel.remoteAddress(); PacketProtocol protocol = createPacketProtocol(); @@ -69,7 +70,10 @@ public class TcpServer extends AbstractServer { session.getPacketProtocol().newServerSession(TcpServer.this, session); channel.config().setOption(ChannelOption.IP_TOS, 0x18); - channel.config().setOption(ChannelOption.TCP_NODELAY, false); + try { + channel.config().setOption(ChannelOption.TCP_NODELAY, true); + } catch (ChannelException ignored) { + } ChannelPipeline pipeline = channel.pipeline(); @@ -94,19 +98,16 @@ public class TcpServer extends AbstractServer { callback.run(); } } else { - future.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(future.isSuccess()) { - channel = future.channel(); - if(callback != null) { - callback.run(); - } - } else { - System.err.println("[ERROR] Failed to asynchronously bind connection listener."); - if(future.cause() != null) { - future.cause().printStackTrace(); - } + future.addListener((ChannelFutureListener) future1 -> { + if(future1.isSuccess()) { + channel = future1.channel(); + if(callback != null) { + callback.run(); + } + } else { + System.err.println("[ERROR] Failed to asynchronously bind connection listener."); + if(future1.cause() != null) { + future1.cause().printStackTrace(); } } }); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 2ce8b375..6997431a 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -11,17 +11,13 @@ import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.PacketProtocol; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ConnectTimeoutException; -import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.*; import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; +import javax.annotation.Nullable; import java.net.ConnectException; import java.net.SocketAddress; import java.util.ArrayList; @@ -34,24 +30,28 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingQueue; public abstract class TcpSession extends SimpleChannelInboundHandler implements Session { + /** + * Controls whether non-priority packets are handled in a separate event loop + */ + public static boolean USE_EVENT_LOOP_FOR_PACKETS = true; + private static EventLoopGroup PACKET_EVENT_LOOP; + protected String host; protected int port; - private PacketProtocol protocol; + private final PacketProtocol protocol; + private final EventLoop eventLoop = createEventLoop(); private int compressionThreshold = -1; private int connectTimeout = 30; private int readTimeout = 30; private int writeTimeout = 0; - private Map flags = new HashMap(); - private List listeners = new CopyOnWriteArrayList(); + private final Map flags = new HashMap<>(); + private final List listeners = new CopyOnWriteArrayList<>(); private Channel channel; protected boolean disconnected = false; - private BlockingQueue packets = new LinkedBlockingQueue(); - private Thread packetHandleThread; - public TcpSession(String host, int port, PacketProtocol protocol) { this.host = host; this.port = port; @@ -102,22 +102,22 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp return this.flags.containsKey(key); } - @SuppressWarnings("unchecked") @Override public T getFlag(String key) { return this.getFlag(key, null); } + @SuppressWarnings("unchecked") @Override public T getFlag(String key, T def) { Object value = this.flags.get(key); - if(value == null) { + if (value == null) { return def; } try { return (T) value; - } catch(ClassCastException e) { + } catch (ClassCastException e) { throw new IllegalStateException("Tried to get flag \"" + key + "\" as the wrong type. Actual type: " + value.getClass().getName()); } } @@ -145,7 +145,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void callEvent(SessionEvent event) { try { - for(SessionListener listener : this.listeners) { + for (SessionListener listener : this.listeners) { event.call(listener); } } catch(Throwable t) { @@ -161,12 +161,12 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void setCompressionThreshold(int threshold) { this.compressionThreshold = threshold; - if(this.channel != null) { - if(this.compressionThreshold >= 0) { - if(this.channel.pipeline().get("compression") == null) { + if (this.channel != null) { + if (this.compressionThreshold >= 0) { + if (this.channel.pipeline().get("compression") == null) { this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this)); } - } else if(this.channel.pipeline().get("compression") != null) { + } else if (this.channel.pipeline().get("compression") != null) { this.channel.pipeline().remove("compression"); } } @@ -218,16 +218,13 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp PacketSendingEvent sendingEvent = new PacketSendingEvent(this, packet); this.callEvent(sendingEvent); - if(!sendingEvent.isCancelled()) { + if (!sendingEvent.isCancelled()) { final Packet toSend = sendingEvent.getPacket(); - this.channel.writeAndFlush(toSend).addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if(future.isSuccess()) { - callEvent(new PacketSentEvent(TcpSession.this, toSend)); - } else { - exceptionCaught(null, future.cause()); - } + this.channel.writeAndFlush(toSend).addListener((ChannelFutureListener) future -> { + if(future.isSuccess()) { + callEvent(new PacketSentEvent(TcpSession.this, toSend)); + } else { + exceptionCaught(null, future.cause()); } }); } @@ -240,18 +237,13 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void disconnect(final String reason, final Throwable cause) { - if(this.disconnected) { + if (this.disconnected) { return; } this.disconnected = true; - if(this.packetHandleThread != null) { - this.packetHandleThread.interrupt(); - this.packetHandleThread = null; - } - - if(this.channel != null && this.channel.isOpen()) { + if (this.channel != null && this.channel.isOpen()) { this.callEvent(new DisconnectingEvent(this, reason, cause)); this.channel.flush().close().addListener((ChannelFutureListener) future -> callEvent(new DisconnectedEvent(TcpSession.this, @@ -259,8 +251,21 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } else { this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); } + } - this.channel = null; + private @Nullable EventLoop createEventLoop() { + if (!USE_EVENT_LOOP_FOR_PACKETS) { + return null; + } + + if (PACKET_EVENT_LOOP == null) { + PACKET_EVENT_LOOP = new DefaultEventLoopGroup(); + } + return PACKET_EVENT_LOOP.next(); + } + + public Channel getChannel() { + return this.channel; } protected void refreshReadTimeoutHandler() { @@ -268,13 +273,13 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } protected void refreshReadTimeoutHandler(Channel channel) { - if(channel != null) { - if(this.readTimeout <= 0) { - if(channel.pipeline().get("readTimeout") != null) { + if (channel != null) { + if (this.readTimeout <= 0) { + if (channel.pipeline().get("readTimeout") != null) { channel.pipeline().remove("readTimeout"); } } else { - if(channel.pipeline().get("readTimeout") == null) { + if (channel.pipeline().get("readTimeout") == null) { channel.pipeline().addFirst("readTimeout", new ReadTimeoutHandler(this.readTimeout)); } else { channel.pipeline().replace("readTimeout", "readTimeout", new ReadTimeoutHandler(this.readTimeout)); @@ -288,13 +293,13 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } protected void refreshWriteTimeoutHandler(Channel channel) { - if(channel != null) { - if(this.writeTimeout <= 0) { - if(channel.pipeline().get("writeTimeout") != null) { + if (channel != null) { + if (this.writeTimeout <= 0) { + if (channel.pipeline().get("writeTimeout") != null) { channel.pipeline().remove("writeTimeout"); } } else { - if(channel.pipeline().get("writeTimeout") == null) { + if (channel.pipeline().get("writeTimeout") == null) { channel.pipeline().addFirst("writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); } else { channel.pipeline().replace("writeTimeout", "writeTimeout", new WriteTimeoutHandler(this.writeTimeout)); @@ -305,48 +310,31 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { - if(this.disconnected || this.channel != null) { + if (this.disconnected || this.channel != null) { ctx.channel().close(); return; } this.channel = ctx.channel(); - this.packetHandleThread = new Thread(new Runnable() { - @Override - public void run() { - try { - Packet packet; - while((packet = packets.take()) != null) { - callEvent(new PacketReceivedEvent(TcpSession.this, packet)); - } - } catch(InterruptedException e) { - } catch(Throwable t) { - exceptionCaught(null, t); - } - } - }); - - this.packetHandleThread.start(); - this.callEvent(new ConnectedEvent(this)); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - if(ctx.channel() == this.channel) { + if (ctx.channel() == this.channel) { this.disconnect("Connection closed."); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - String message = null; - if(cause instanceof ConnectTimeoutException || (cause instanceof ConnectException && cause.getMessage().contains("connection timed out"))) { + String message; + if (cause instanceof ConnectTimeoutException || (cause instanceof ConnectException && cause.getMessage().contains("connection timed out"))) { message = "Connection timed out."; - } else if(cause instanceof ReadTimeoutException) { + } else if (cause instanceof ReadTimeoutException) { message = "Read timed out."; - } else if(cause instanceof WriteTimeoutException) { + } else if (cause instanceof WriteTimeoutException) { message = "Write timed out."; } else { message = cause.toString(); @@ -357,10 +345,10 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override protected void channelRead0(ChannelHandlerContext ctx, Packet packet) { - if(packet.isPriority()) { - this.callEvent(new PacketReceivedEvent(this, packet)); + if (!packet.isPriority() && eventLoop != null) { + eventLoop.execute(() -> this.callEvent(new PacketReceivedEvent(this, packet))); } else { - this.packets.add(packet); + this.callEvent(new PacketReceivedEvent(this, packet)); } } } From 489979d2bc7a5025789d508ba73d86a4fb72503f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Fri, 12 Nov 2021 23:04:14 -0500 Subject: [PATCH 140/180] Require packets to have a NetInput constructor This permits packets to have final fields, and prevents setAccessible and no-args constructor requirements. --- .../packetlib/packet/BufferedPacket.java | 11 +---- .../steveice10/packetlib/packet/Packet.java | 10 +---- .../packetlib/packet/PacketProtocol.java | 42 ++++++++++--------- .../packetlib/tcp/TcpPacketCodec.java | 15 ++++--- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java index 66d1ba55..2da5d875 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java @@ -1,14 +1,12 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.io.NetInput; import com.github.steveice10.packetlib.io.NetOutput; -import java.io.EOFException; import java.io.IOException; public class BufferedPacket implements Packet { - private Class packetClass; - private byte[] buf; + private final Class packetClass; + private final byte[] buf; public BufferedPacket(Class packetClass, byte[] buf) { this.packetClass = packetClass; @@ -19,11 +17,6 @@ public class BufferedPacket implements Packet { return packetClass; } - @Override - public void read(NetInput in) throws IOException { - throw new EOFException("BufferedPacket can not be read"); - } - @Override public void write(NetOutput out) throws IOException { out.writeBytes(buf); diff --git a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java index 36d586f3..8a2815a0 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java @@ -6,17 +6,9 @@ import com.github.steveice10.packetlib.io.NetOutput; import java.io.IOException; /** - * A network packet. + * A network packet. Any given packet must have a constructor that takes in a {@link NetInput}. */ public interface Packet { - /** - * Reads the packet from the given input buffer. - * - * @param in The input source to read from. - * @throws IOException If an I/O error occurs. - */ - public void read(NetInput in) throws IOException; - /** * Writes the packet to the given output buffer. * diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 1cc93365..d3faf220 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -3,17 +3,21 @@ package com.github.steveice10.packetlib.packet; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.crypt.PacketEncryption; +import com.github.steveice10.packetlib.io.NetInput; +import java.io.IOException; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; /** * A protocol for packet sending and receiving. * All implementations must have a no-params constructor for server protocol creation. */ public abstract class PacketProtocol { - private final Map> incoming = new HashMap<>(); + private final Map> incoming = new HashMap<>(); private final Map, Integer> outgoing = new HashMap<>(); private final Map> outgoingClasses = new HashMap<>(); @@ -83,13 +87,13 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet fails a test creation. */ public final void registerIncoming(int id, Class packet) { - this.incoming.put(id, packet); + Constructor constructor; try { - this.createIncomingPacket(id); - } catch(IllegalStateException e) { - this.incoming.remove(id); - throw new IllegalArgumentException(e.getMessage(), e.getCause()); + constructor = packet.getConstructor(NetInput.class); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Packet does not have a constructor that takes in NetInput!"); } + this.incoming.put(id, constructor); } /** @@ -104,30 +108,28 @@ public abstract class PacketProtocol { } /** - * Creates a new instance of an incoming packet with the given id. + * Creates a new instance of an incoming packet with the given id and read the incoming input. * * @param id Id of the packet to create. * @return The created packet. + * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. - * @throws IllegalStateException If the packet does not have a no-params constructor or cannot be instantiated. */ - public final Packet createIncomingPacket(int id) { - Class packet = this.incoming.get(id); - if (packet == null) { + public final Packet createIncomingPacket(int id, NetInput in) throws IOException { + Constructor constructor = this.incoming.get(id); + if (constructor == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } try { - Constructor constructor = packet.getDeclaredConstructor(); - if(!constructor.isAccessible()) { - constructor.setAccessible(true); + return constructor.newInstance(in); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException("Packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\" could not be instantiated."); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); } - - return constructor.newInstance(); - } catch(NoSuchMethodError e) { - throw new IllegalStateException("Packet \"" + id + ", " + packet.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + packet.getName() + "\".", e); + throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\".", e); } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index ac918eeb..bda5a3f5 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -30,13 +30,13 @@ public class TcpPacketCodec extends ByteToMessageCodec { this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); packet.write(out); - } catch(Throwable t) { + } catch (Throwable t) { // Reset writer index to make sure incomplete data is not written out. buf.writerIndex(initial); PacketErrorEvent e = new PacketErrorEvent(this.session, t); this.session.callEvent(e); - if(!e.shouldSuppress()) { + if (!e.shouldSuppress()) { throw t; } } @@ -50,26 +50,25 @@ public class TcpPacketCodec extends ByteToMessageCodec { NetInput in = new ByteBufNetInput(buf); int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); - if(id == -1) { + if (id == -1) { buf.readerIndex(initial); return; } - Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); - packet.read(in); + Packet packet = this.session.getPacketProtocol().createIncomingPacket(id, in); - if(buf.readableBytes() > 0) { + if (buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); } out.add(packet); - } catch(Throwable t) { + } catch (Throwable t) { // Advance buffer to end to make sure remaining data in this packet is skipped. buf.readerIndex(buf.readerIndex() + buf.readableBytes()); PacketErrorEvent e = new PacketErrorEvent(this.session, t); this.session.callEvent(e); - if(!e.shouldSuppress()) { + if (!e.shouldSuppress()) { throw t; } } From e295601d7cfe1ce33c4b6bcfeef654c3c4225736 Mon Sep 17 00:00:00 2001 From: Redned Date: Fri, 12 Nov 2021 22:59:08 -0600 Subject: [PATCH 141/180] Replace reflection usage with packet factories --- pom.xml | 2 +- .../packetlib/packet/PacketDefinition.java | 47 +++++++ .../packetlib/packet/PacketFactory.java | 23 +++ .../packetlib/packet/PacketProtocol.java | 133 ++++++++++++++---- 4 files changed, 174 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java create mode 100644 src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java diff --git a/pom.xml b/pom.xml index 34acaad8..0a793851 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.1-SNAPSHOT + 2.2-SNAPSHOT jar PacketLib diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java new file mode 100644 index 00000000..b483be85 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java @@ -0,0 +1,47 @@ +package com.github.steveice10.packetlib.packet; + +/** + * Represents a definition of a packet with various + * information about it, such as it's id, class and + * factory for construction. + * + * @param the packet type + */ +public class PacketDefinition { + private final int id; + private final Class packetClass; + private final PacketFactory factory; + + public PacketDefinition(final int id, final Class packetClass, final PacketFactory factory) { + this.id = id; + this.packetClass = packetClass; + this.factory = factory; + } + + /** + * Returns the id of the packet. + * + * @return the id of the packet + */ + public int getId() { + return this.id; + } + + /** + * Returns the class of the packet. + * + * @return the class of the packet + */ + public Class getPacketClass() { + return this.packetClass; + } + + /** + * Returns the {@link PacketFactory} of the packet. + * + * @return the packet factory of the packet + */ + public PacketFactory getFactory() { + return this.factory; + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java new file mode 100644 index 00000000..ec55ceb3 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java @@ -0,0 +1,23 @@ +package com.github.steveice10.packetlib.packet; + +import com.github.steveice10.packetlib.io.NetInput; + +import java.io.IOException; + +/** + * Factory for constructing {@link Packet}s. + * + * @param the packet type + */ +@FunctionalInterface +public interface PacketFactory { + + /** + * Constructs a new {@link Packet} from the + * given {@link NetInput}. + * + * @param input the input + * @return a new packet from the input + */ + T construct(NetInput input) throws IOException; +} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index d3faf220..c559694b 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -9,18 +9,18 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.Map; -import java.util.function.Function; /** * A protocol for packet sending and receiving. - * All implementations must have a no-params constructor for server protocol creation. + * All implementations must have a constructor that takes in a {@link NetInput}. */ public abstract class PacketProtocol { - private final Map> incoming = new HashMap<>(); - private final Map, Integer> outgoing = new HashMap<>(); + private final Map> incoming = new HashMap<>(); + private final Map> outgoing = new HashMap<>(); - private final Map> outgoingClasses = new HashMap<>(); + private final Map, Integer> outgoingIds = new IdentityHashMap<>(); /** * Gets the prefix used when locating SRV records for this protocol. @@ -64,7 +64,7 @@ public abstract class PacketProtocol { public final void clearPackets() { this.incoming.clear(); this.outgoing.clear(); - this.outgoingClasses.clear(); + this.outgoingIds.clear(); } /** @@ -73,38 +73,90 @@ public abstract class PacketProtocol { * @param id Id to register the packet to. * @param packet Packet to register. * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + * + * @deprecated replaced with {@link #register(int, Class, PacketFactory)} */ + @Deprecated public final void register(int id, Class packet) { this.registerIncoming(id, packet); this.registerOutgoing(id, packet); } + /** + * Registers a packet to this protocol as both incoming and outgoing. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param factory The packet factory. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + */ + public final void register(int id, Class packet, PacketFactory factory) { + this.registerIncoming(id, packet, factory); + this.registerOutgoing(id, packet, factory); + } + /** * Registers an incoming packet to this protocol. * * @param id Id to register the packet to. * @param packet Packet to register. * @throws IllegalArgumentException If the packet fails a test creation. + * + * @deprecated replaced with {@link #registerIncoming(int, Class, PacketFactory)} */ - public final void registerIncoming(int id, Class packet) { - Constructor constructor; + @Deprecated + public final void registerIncoming(int id, Class packet) { + Constructor constructor; try { constructor = packet.getConstructor(NetInput.class); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Packet does not have a constructor that takes in NetInput!"); } - this.incoming.put(id, constructor); + this.registerIncoming(id, packet, (input) -> this.constructPacketWithReflection(constructor, id, input)); + } + + /** + * Registers an incoming packet to this protocol. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param factory The packet factory. + * @throws IllegalArgumentException If the packet fails a test creation. + */ + public final void registerIncoming(int id, Class packet, PacketFactory factory) { + this.incoming.put(id, new PacketDefinition<>(id, packet, factory)); } /** * Registers an outgoing packet to this protocol. * * @param id Id to register the packet to. - * @param packet Packet to register. + * @param packet Packet to register. + * + * @deprecated replaced with {@link #registerOutgoing(int, Class, PacketFactory)} */ - public final void registerOutgoing(int id, Class packet) { - this.outgoing.put(packet, id); - this.outgoingClasses.put(id, packet); + @Deprecated + public final void registerOutgoing(int id, Class packet) { + Constructor constructor; + try { + constructor = packet.getConstructor(NetInput.class); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Packet does not have a constructor that takes in NetInput!"); + } + + this.registerOutgoing(id, packet, input -> this.constructPacketWithReflection(constructor, id, input)); + } + + /** + * Registers an outgoing packet to this protocol. + * + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param factory The packet factory. + */ + public final void registerOutgoing(int id, Class packet, PacketFactory factory) { + this.outgoing.put(id, new PacketDefinition<>(id, packet, factory)); + this.outgoingIds.put(packet, id); } /** @@ -116,21 +168,29 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet ID is not registered. */ public final Packet createIncomingPacket(int id, NetInput in) throws IOException { - Constructor constructor = this.incoming.get(id); - if (constructor == null) { + PacketDefinition definition = this.incoming.get(id); + if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - try { - return constructor.newInstance(in); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalStateException("Packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\" could not be instantiated."); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } - throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\".", e); + return definition.getFactory().construct(in); + } + + /** + * Creates a new instance of an outgoing packet with the given id and read the outgoing input. + * + * @param id Id of the packet to create. + * @return The created packet. + * @throws IOException if there was an IO error whilst reading the packet. + * @throws IllegalArgumentException If the packet ID is not registered. + */ + public final Packet createOutgoingPacket(int id, NetInput in) throws IOException { + PacketDefinition definition = this.outgoing.get(id); + if (definition == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); } + + return definition.getFactory().construct(in); } /** @@ -141,7 +201,7 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet is not registered. */ public final int getOutgoingId(Class packetClass) { - Integer packetId = this.outgoing.get(packetClass); + Integer packetId = this.outgoingIds.get(packetClass); if(packetId == null) { throw new IllegalArgumentException("Unregistered outgoing packet class: " + packetClass.getName()); } @@ -157,8 +217,8 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet is not registered. */ public final int getOutgoingId(Packet packet) { - if(packet instanceof BufferedPacket) { - return getOutgoingId(((BufferedPacket)packet).getPacketClass()); + if (packet instanceof BufferedPacket) { + return getOutgoingId(((BufferedPacket) packet).getPacketClass()); } return getOutgoingId(packet.getClass()); @@ -171,11 +231,24 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet ID is not registered. */ public final Class getOutgoingClass(int id) { - Class packet = this.outgoingClasses.get(id); - if(packet == null) { + PacketDefinition definition = this.outgoing.get(id); + if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - return packet; + return definition.getPacketClass(); + } + + private T constructPacketWithReflection(Constructor constructor, int id, NetInput in) throws IOException { + try { + return constructor.newInstance(in); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException("Packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\" could not be instantiated."); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } + throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\".", e); + } } } From 98d9d91ca43deb9c66487f5040302d452f19c930 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Fri, 12 Nov 2021 23:06:14 -0600 Subject: [PATCH 142/180] Remove deprecations here and any reflection usage Methods were less than a day old --- .../packetlib/packet/PacketProtocol.java | 70 ------------------- 1 file changed, 70 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index c559694b..84e9b386 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -6,8 +6,6 @@ import com.github.steveice10.packetlib.crypt.PacketEncryption; import com.github.steveice10.packetlib.io.NetInput; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; @@ -67,21 +65,6 @@ public abstract class PacketProtocol { this.outgoingIds.clear(); } - /** - * Registers a packet to this protocol as both incoming and outgoing. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. - * - * @deprecated replaced with {@link #register(int, Class, PacketFactory)} - */ - @Deprecated - public final void register(int id, Class packet) { - this.registerIncoming(id, packet); - this.registerOutgoing(id, packet); - } - /** * Registers a packet to this protocol as both incoming and outgoing. * @@ -95,26 +78,6 @@ public abstract class PacketProtocol { this.registerOutgoing(id, packet, factory); } - /** - * Registers an incoming packet to this protocol. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @throws IllegalArgumentException If the packet fails a test creation. - * - * @deprecated replaced with {@link #registerIncoming(int, Class, PacketFactory)} - */ - @Deprecated - public final void registerIncoming(int id, Class packet) { - Constructor constructor; - try { - constructor = packet.getConstructor(NetInput.class); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("Packet does not have a constructor that takes in NetInput!"); - } - this.registerIncoming(id, packet, (input) -> this.constructPacketWithReflection(constructor, id, input)); - } - /** * Registers an incoming packet to this protocol. * @@ -127,26 +90,6 @@ public abstract class PacketProtocol { this.incoming.put(id, new PacketDefinition<>(id, packet, factory)); } - /** - * Registers an outgoing packet to this protocol. - * - * @param id Id to register the packet to. - * @param packet Packet to register. - * - * @deprecated replaced with {@link #registerOutgoing(int, Class, PacketFactory)} - */ - @Deprecated - public final void registerOutgoing(int id, Class packet) { - Constructor constructor; - try { - constructor = packet.getConstructor(NetInput.class); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException("Packet does not have a constructor that takes in NetInput!"); - } - - this.registerOutgoing(id, packet, input -> this.constructPacketWithReflection(constructor, id, input)); - } - /** * Registers an outgoing packet to this protocol. * @@ -238,17 +181,4 @@ public abstract class PacketProtocol { return definition.getPacketClass(); } - - private T constructPacketWithReflection(Constructor constructor, int id, NetInput in) throws IOException { - try { - return constructor.newInstance(in); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalStateException("Packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\" could not be instantiated."); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } - throw new IllegalStateException("Failed to instantiate packet \"" + id + ", " + constructor.getDeclaringClass().getName() + "\".", e); - } - } } From 6c0f107702ffdef27a88566780a947f0176507a7 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:10:31 -0600 Subject: [PATCH 143/180] Don't bump version as we are still on snapshot --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0a793851..34acaad8 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.2-SNAPSHOT + 2.1-SNAPSHOT jar PacketLib From 459e5287ccf4d8b598bbaa06e09bfacf716e53c7 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:15:43 -0600 Subject: [PATCH 144/180] Update examples to reflect changes done --- .../github/steveice10/packetlib/test/PingPacket.java | 11 +++-------- .../steveice10/packetlib/test/TestProtocol.java | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/example/com/github/steveice10/packetlib/test/PingPacket.java b/example/com/github/steveice10/packetlib/test/PingPacket.java index ec8ad0f9..bd9f6cc1 100644 --- a/example/com/github/steveice10/packetlib/test/PingPacket.java +++ b/example/com/github/steveice10/packetlib/test/PingPacket.java @@ -7,10 +7,10 @@ import com.github.steveice10.packetlib.packet.Packet; import java.io.IOException; public class PingPacket implements Packet { - private String id; + private final String id; - @SuppressWarnings("unused") - private PingPacket() { + public PingPacket(NetInput in) throws IOException { + this.id = in.readString(); } public PingPacket(String id) { @@ -21,11 +21,6 @@ public class PingPacket implements Packet { return this.id; } - @Override - public void read(NetInput in) throws IOException { - this.id = in.readString(); - } - @Override public void write(NetOutput out) throws IOException { out.writeString(this.id); diff --git a/example/com/github/steveice10/packetlib/test/TestProtocol.java b/example/com/github/steveice10/packetlib/test/TestProtocol.java index 8a4baedc..45b44b5b 100644 --- a/example/com/github/steveice10/packetlib/test/TestProtocol.java +++ b/example/com/github/steveice10/packetlib/test/TestProtocol.java @@ -12,7 +12,7 @@ import javax.crypto.SecretKey; import java.security.GeneralSecurityException; public class TestProtocol extends PacketProtocol { - private PacketHeader header = new DefaultPacketHeader(); + private final PacketHeader header = new DefaultPacketHeader(); private AESEncryption encrypt; @SuppressWarnings("unused") @@ -24,7 +24,7 @@ public class TestProtocol extends PacketProtocol { } public void setSecretKey(SecretKey key) { - this.register(0, PingPacket.class); + this.register(0, PingPacket.class, PingPacket::new); try { this.encrypt = new AESEncryption(key); } catch(GeneralSecurityException e) { From 37e2fc7bb39830abbf1768c7bd05b6c5ded4b5aa Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:28:19 -0600 Subject: [PATCH 145/180] Add open collab repo and deploy on Jenkins --- Jenkinsfile | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pom.xml | 23 +++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..85b439f5 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,52 @@ +pipeline { + agent any + tools { + maven 'Maven 3' + jdk 'Java 8' + } + options { + buildDiscarder(logRotator(artifactNumToKeepStr: '20')) + } + stages { + stage ('Build') { + steps { + sh 'mvn clean package' + } + post { + success { + archiveArtifacts artifacts: 'target/*.jar', excludes: 'target/*-sources.jar', fingerprint: true + } + } + } + + stage ('Deploy') { + when { + branch "master" + } + + steps { + rtMavenDeployer( + id: "maven-deployer", + serverId: "opencollab-artifactory", + releaseRepo: "maven-releases", + snapshotRepo: "maven-snapshots" + ) + rtMavenResolver( + id: "maven-resolver", + serverId: "opencollab-artifactory", + releaseRepo: "maven-deploy-release", + snapshotRepo: "maven-deploy-snapshot" + ) + rtMavenRun( + pom: 'pom.xml', + goals: 'javadoc:jar source:jar install -pl :connector -am -DskipTests', + deployerId: "maven-deployer", + resolverId: "maven-resolver" + ) + rtPublishBuildInfo( + serverId: "opencollab-artifactory" + ) + } + } + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 34acaad8..0fb7ef86 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,29 @@ https://github.com/Steveice10/PacketLib/issues + + + opencollab-release-repo + https://repo.opencollab.dev/maven-releases/ + + true + + + false + + + + opencollab-snapshot-repo + https://repo.opencollab.dev/maven-snapshots/ + + false + + + true + + + + io.netty From 7488f8f702776b179acdb62f6db1dc7b31c3e266 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:30:31 -0600 Subject: [PATCH 146/180] Remove connector referece --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 85b439f5..eb43d212 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,7 +39,7 @@ pipeline { ) rtMavenRun( pom: 'pom.xml', - goals: 'javadoc:jar source:jar install -pl :connector -am -DskipTests', + goals: 'javadoc:jar source:jar install -pl -am -DskipTests', deployerId: "maven-deployer", resolverId: "maven-resolver" ) From d89ca0581efc1035350ac7fedebce9dea48210b0 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:31:45 -0600 Subject: [PATCH 147/180] Remove pl too --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index eb43d212..43595238 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,7 +39,7 @@ pipeline { ) rtMavenRun( pom: 'pom.xml', - goals: 'javadoc:jar source:jar install -pl -am -DskipTests', + goals: 'javadoc:jar source:jar install -am -DskipTests', deployerId: "maven-deployer", resolverId: "maven-resolver" ) From 30a14ca088efd94cc05c5b6d53bc705eaa73fb03 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:32:07 -0600 Subject: [PATCH 148/180] Aaaand am --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 43595238..c3093b7a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,7 +39,7 @@ pipeline { ) rtMavenRun( pom: 'pom.xml', - goals: 'javadoc:jar source:jar install -am -DskipTests', + goals: 'javadoc:jar source:jar install -DskipTests', deployerId: "maven-deployer", resolverId: "maven-resolver" ) From 3fdf9ea1d5fea95068809416df687e1f707da380 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 12:41:51 -0600 Subject: [PATCH 149/180] Allow for registering with packet definition directly --- .../packetlib/packet/PacketProtocol.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 84e9b386..e54f03fc 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -78,6 +78,17 @@ public abstract class PacketProtocol { this.registerOutgoing(id, packet, factory); } + /** + * Registers a packet to this protocol as both incoming and outgoing. + * + * @param definition The packet definition. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + */ + public final void register(PacketDefinition definition) { + this.registerIncoming(definition); + this.registerOutgoing(definition); + } + /** * Registers an incoming packet to this protocol. * @@ -87,7 +98,16 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet fails a test creation. */ public final void registerIncoming(int id, Class packet, PacketFactory factory) { - this.incoming.put(id, new PacketDefinition<>(id, packet, factory)); + this.registerIncoming(new PacketDefinition<>(id, packet, factory)); + } + + /** + * Registers an incoming packet to this protocol. + * + * @param definition The packet definition. + */ + public final void registerIncoming(PacketDefinition definition) { + this.incoming.put(definition.getId(), definition); } /** @@ -98,8 +118,17 @@ public abstract class PacketProtocol { * @param factory The packet factory. */ public final void registerOutgoing(int id, Class packet, PacketFactory factory) { - this.outgoing.put(id, new PacketDefinition<>(id, packet, factory)); - this.outgoingIds.put(packet, id); + this.registerOutgoing(new PacketDefinition<>(id, packet, factory)); + } + + /** + * Registers an outgoing packet to this protocol. + * + * @param definition The packet definition. + */ + public final void registerOutgoing(PacketDefinition definition) { + this.outgoing.put(definition.getId(), definition); + this.outgoingIds.put(definition.getPacketClass(), definition.getId()); } /** From b1c85550f65656d88da73d01da1167806e68988e Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 14:53:46 -0600 Subject: [PATCH 150/180] Update incoming & outgoing naming to serverbound & clientbound Also determine which map to pull the packet from based on whether we're working with a client or server. --- .../packetlib/packet/PacketProtocol.java | 163 ++++++++++++------ .../packetlib/tcp/TcpPacketCodec.java | 6 +- 2 files changed, 110 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index e54f03fc..54d4952e 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -15,10 +15,11 @@ import java.util.Map; * All implementations must have a constructor that takes in a {@link NetInput}. */ public abstract class PacketProtocol { - private final Map> incoming = new HashMap<>(); - private final Map> outgoing = new HashMap<>(); + private final Map> serverbound = new HashMap<>(); + private final Map> clientbound = new HashMap<>(); - private final Map, Integer> outgoingIds = new IdentityHashMap<>(); + private final Map, Integer> clientboundIds = new IdentityHashMap<>(); + private final Map, Integer> serverboundIds = new IdentityHashMap<>(); /** * Gets the prefix used when locating SRV records for this protocol. @@ -60,87 +61,89 @@ public abstract class PacketProtocol { * Clears all currently registered packets. */ public final void clearPackets() { - this.incoming.clear(); - this.outgoing.clear(); - this.outgoingIds.clear(); + this.serverbound.clear(); + this.clientbound.clear(); + this.clientboundIds.clear(); + this.serverboundIds.clear(); } /** - * Registers a packet to this protocol as both incoming and outgoing. + * Registers a packet to this protocol as both serverbound and clientbound. * * @param id Id to register the packet to. * @param packet Packet to register. * @param factory The packet factory. - * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound. */ public final void register(int id, Class packet, PacketFactory factory) { - this.registerIncoming(id, packet, factory); - this.registerOutgoing(id, packet, factory); + this.registerServerbound(id, packet, factory); + this.registerClientbound(id, packet, factory); } /** - * Registers a packet to this protocol as both incoming and outgoing. + * Registers a packet to this protocol as both serverbound and clientbound. * * @param definition The packet definition. - * @throws IllegalArgumentException If the packet fails a test creation when being registered as incoming. + * @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound. */ public final void register(PacketDefinition definition) { - this.registerIncoming(definition); - this.registerOutgoing(definition); + this.registerServerbound(definition); + this.registerClientbound(definition); } /** - * Registers an incoming packet to this protocol. + * Registers a serverbound packet to this protocol. * * @param id Id to register the packet to. * @param packet Packet to register. * @param factory The packet factory. * @throws IllegalArgumentException If the packet fails a test creation. */ - public final void registerIncoming(int id, Class packet, PacketFactory factory) { - this.registerIncoming(new PacketDefinition<>(id, packet, factory)); + public final void registerServerbound(int id, Class packet, PacketFactory factory) { + this.registerServerbound(new PacketDefinition<>(id, packet, factory)); } /** - * Registers an incoming packet to this protocol. + * Registers a serverbound packet to this protocol. * * @param definition The packet definition. */ - public final void registerIncoming(PacketDefinition definition) { - this.incoming.put(definition.getId(), definition); + public final void registerServerbound(PacketDefinition definition) { + this.serverbound.put(definition.getId(), definition); + this.serverboundIds.put(definition.getPacketClass(), definition.getId()); } /** - * Registers an outgoing packet to this protocol. + * Registers a clientbound packet to this protocol. * * @param id Id to register the packet to. * @param packet Packet to register. * @param factory The packet factory. */ - public final void registerOutgoing(int id, Class packet, PacketFactory factory) { - this.registerOutgoing(new PacketDefinition<>(id, packet, factory)); + public final void registerClientbound(int id, Class packet, PacketFactory factory) { + this.registerClientbound(new PacketDefinition<>(id, packet, factory)); } /** - * Registers an outgoing packet to this protocol. + * Registers a clientbound packet to this protocol. * * @param definition The packet definition. */ - public final void registerOutgoing(PacketDefinition definition) { - this.outgoing.put(definition.getId(), definition); - this.outgoingIds.put(definition.getPacketClass(), definition.getId()); + public final void registerClientbound(PacketDefinition definition) { + this.clientbound.put(definition.getId(), definition); + this.clientboundIds.put(definition.getPacketClass(), definition.getId()); } /** - * Creates a new instance of an incoming packet with the given id and read the incoming input. + * Creates a new instance of a clientbound packet with the given id and read the clientbound input. * * @param id Id of the packet to create. * @return The created packet. * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Packet createIncomingPacket(int id, NetInput in) throws IOException { - PacketDefinition definition = this.incoming.get(id); + public final Packet createClientboundPacket(int id, NetInput in) throws IOException { + PacketDefinition definition = this.clientbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } @@ -149,51 +152,34 @@ public abstract class PacketProtocol { } /** - * Creates a new instance of an outgoing packet with the given id and read the outgoing input. - * - * @param id Id of the packet to create. - * @return The created packet. - * @throws IOException if there was an IO error whilst reading the packet. - * @throws IllegalArgumentException If the packet ID is not registered. - */ - public final Packet createOutgoingPacket(int id, NetInput in) throws IOException { - PacketDefinition definition = this.outgoing.get(id); - if (definition == null) { - throw new IllegalArgumentException("Invalid packet id: " + id); - } - - return definition.getFactory().construct(in); - } - - /** - * Gets the registered id of an outgoing packet class. + * Gets the registered id of a clientbound packet class. * * @param packetClass Class of the packet to get the id for. * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getOutgoingId(Class packetClass) { - Integer packetId = this.outgoingIds.get(packetClass); + public final int getClientboundId(Class packetClass) { + Integer packetId = this.clientboundIds.get(packetClass); if(packetId == null) { - throw new IllegalArgumentException("Unregistered outgoing packet class: " + packetClass.getName()); + throw new IllegalArgumentException("Unregistered clientbound packet class: " + packetClass.getName()); } return packetId; } /** - * Gets the registered id of an outgoing {@link Packet} instance. + * Gets the registered id of a clientbound {@link Packet} instance. * * @param packet Instance of {@link Packet} to get the id for. * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getOutgoingId(Packet packet) { + public final int getClientboundId(Packet packet) { if (packet instanceof BufferedPacket) { - return getOutgoingId(((BufferedPacket) packet).getPacketClass()); + return getClientboundId(((BufferedPacket) packet).getPacketClass()); } - return getOutgoingId(packet.getClass()); + return getClientboundId(packet.getClass()); } /** @@ -202,8 +188,71 @@ public abstract class PacketProtocol { * @return The registered packet's class * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Class getOutgoingClass(int id) { - PacketDefinition definition = this.outgoing.get(id); + public final Class getClientboundClass(int id) { + PacketDefinition definition = this.clientbound.get(id); + if (definition == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + return definition.getPacketClass(); + } + + /** + * Creates a new instance of a serverbound packet with the given id and read the serverbound input. + * + * @param id Id of the packet to create. + * @return The created packet. + * @throws IOException if there was an IO error whilst reading the packet. + * @throws IllegalArgumentException If the packet ID is not registered. + */ + public final Packet createServerboundPacket(int id, NetInput in) throws IOException { + PacketDefinition definition = this.serverbound.get(id); + if (definition == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + return definition.getFactory().construct(in); + } + + /** + * Gets the registered id of a serverbound packet class. + * + * @param packetClass Class of the packet to get the id for. + * @return The packet's registered id. + * @throws IllegalArgumentException If the packet is not registered. + */ + public final int getServerboundId(Class packetClass) { + Integer packetId = this.serverboundIds.get(packetClass); + if(packetId == null) { + throw new IllegalArgumentException("Unregistered serverbound packet class: " + packetClass.getName()); + } + + return packetId; + } + + /** + * Gets the registered id of a server {@link Packet} instance. + * + * @param packet Instance of {@link Packet} to get the id for. + * @return The packet's registered id. + * @throws IllegalArgumentException If the packet is not registered. + */ + public final int getServerboundId(Packet packet) { + if (packet instanceof BufferedPacket) { + return getServerboundId(((BufferedPacket) packet).getPacketClass()); + } + + return getServerboundId(packet.getClass()); + } + + /** + * Gets the packet class for a packet id. + * @param id The packet id. + * @return The registered packet's class + * @throws IllegalArgumentException If the packet ID is not registered. + */ + public final Class getServerboundClass(int id) { + PacketDefinition definition = this.serverbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index bda5a3f5..72ac701e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -16,9 +16,11 @@ import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { private final Session session; + private final boolean client; public TcpPacketCodec(Session session) { this.session = session; + this.client = session instanceof TcpClientSession; } @Override @@ -28,7 +30,7 @@ public class TcpPacketCodec extends ByteToMessageCodec { try { NetOutput out = new ByteBufNetOutput(buf); - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.client ? this.session.getPacketProtocol().getServerboundId(packet) : this.session.getPacketProtocol().getClientboundId(packet)); packet.write(out); } catch (Throwable t) { // Reset writer index to make sure incomplete data is not written out. @@ -55,7 +57,7 @@ public class TcpPacketCodec extends ByteToMessageCodec { return; } - Packet packet = this.session.getPacketProtocol().createIncomingPacket(id, in); + Packet packet = this.client ? this.session.getPacketProtocol().createClientboundPacket(id, in) : this.session.getPacketProtocol().createServerboundPacket(id, in); if (buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); From 816c0db6d760586ab8f159226917bf43ff638274 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 14:55:06 -0600 Subject: [PATCH 151/180] Fix javadoc --- .../com/github/steveice10/packetlib/packet/PacketProtocol.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 54d4952e..2e934855 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -231,7 +231,7 @@ public abstract class PacketProtocol { } /** - * Gets the registered id of a server {@link Packet} instance. + * Gets the registered id of a serverbound {@link Packet} instance. * * @param packet Instance of {@link Packet} to get the id for. * @return The packet's registered id. From ec983f14476ec4e40d09499586df2be886995b89 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 16:41:57 -0600 Subject: [PATCH 152/180] Remove final for some packet methods --- .../packetlib/packet/PacketProtocol.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 2e934855..3fa6b876 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -142,7 +142,7 @@ public abstract class PacketProtocol { * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Packet createClientboundPacket(int id, NetInput in) throws IOException { + public Packet createClientboundPacket(int id, NetInput in) throws IOException { PacketDefinition definition = this.clientbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); @@ -158,7 +158,7 @@ public abstract class PacketProtocol { * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getClientboundId(Class packetClass) { + public int getClientboundId(Class packetClass) { Integer packetId = this.clientboundIds.get(packetClass); if(packetId == null) { throw new IllegalArgumentException("Unregistered clientbound packet class: " + packetClass.getName()); @@ -174,7 +174,7 @@ public abstract class PacketProtocol { * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getClientboundId(Packet packet) { + public int getClientboundId(Packet packet) { if (packet instanceof BufferedPacket) { return getClientboundId(((BufferedPacket) packet).getPacketClass()); } @@ -188,7 +188,7 @@ public abstract class PacketProtocol { * @return The registered packet's class * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Class getClientboundClass(int id) { + public Class getClientboundClass(int id) { PacketDefinition definition = this.clientbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); @@ -205,7 +205,7 @@ public abstract class PacketProtocol { * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Packet createServerboundPacket(int id, NetInput in) throws IOException { + public Packet createServerboundPacket(int id, NetInput in) throws IOException { PacketDefinition definition = this.serverbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); @@ -221,7 +221,7 @@ public abstract class PacketProtocol { * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getServerboundId(Class packetClass) { + public int getServerboundId(Class packetClass) { Integer packetId = this.serverboundIds.get(packetClass); if(packetId == null) { throw new IllegalArgumentException("Unregistered serverbound packet class: " + packetClass.getName()); @@ -237,7 +237,7 @@ public abstract class PacketProtocol { * @return The packet's registered id. * @throws IllegalArgumentException If the packet is not registered. */ - public final int getServerboundId(Packet packet) { + public int getServerboundId(Packet packet) { if (packet instanceof BufferedPacket) { return getServerboundId(((BufferedPacket) packet).getPacketClass()); } @@ -251,7 +251,7 @@ public abstract class PacketProtocol { * @return The registered packet's class * @throws IllegalArgumentException If the packet ID is not registered. */ - public final Class getServerboundClass(int id) { + public Class getServerboundClass(int id) { PacketDefinition definition = this.serverbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); From 1188c1486fdec7fa25b939f9363669dfa6c29af5 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 13 Nov 2021 19:59:20 -0600 Subject: [PATCH 153/180] Replace reflection usage with a supplier --- .../steveice10/packetlib/AbstractServer.java | 25 ++++-------- .../github/steveice10/packetlib/Server.java | 39 ++++++++++--------- .../steveice10/packetlib/tcp/TcpServer.java | 3 +- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/AbstractServer.java b/src/main/java/com/github/steveice10/packetlib/AbstractServer.java index 1412ccab..781b9517 100644 --- a/src/main/java/com/github/steveice10/packetlib/AbstractServer.java +++ b/src/main/java/com/github/steveice10/packetlib/AbstractServer.java @@ -3,23 +3,23 @@ package com.github.steveice10.packetlib; import com.github.steveice10.packetlib.event.server.*; import com.github.steveice10.packetlib.packet.PacketProtocol; -import java.lang.reflect.Constructor; import java.util.*; +import java.util.function.Supplier; public abstract class AbstractServer implements Server { private final String host; private final int port; - private final Class protocol; + private final Supplier protocolSupplier; private final List sessions = new ArrayList<>(); private final Map flags = new HashMap<>(); private final List listeners = new ArrayList<>(); - public AbstractServer(String host, int port, Class protocol) { + public AbstractServer(String host, int port, Supplier protocolSupplier) { this.host = host; this.port = port; - this.protocol = protocol; + this.protocolSupplier = protocolSupplier; } @Override @@ -33,23 +33,12 @@ public abstract class AbstractServer implements Server { } @Override - public Class getPacketProtocol() { - return this.protocol; + public Supplier getPacketProtocol() { + return this.protocolSupplier; } protected PacketProtocol createPacketProtocol() { - try { - Constructor constructor = this.protocol.getDeclaredConstructor(); - if(!constructor.isAccessible()) { - constructor.setAccessible(true); - } - - return constructor.newInstance(); - } catch(NoSuchMethodError e) { - throw new IllegalStateException("PacketProtocol \"" + this.protocol.getName() + "\" does not have a no-params constructor for instantiation."); - } catch(Exception e) { - throw new IllegalStateException("Failed to instantiate PacketProtocol " + this.protocol.getName() + ".", e); - } + return this.protocolSupplier.get(); } @Override diff --git a/src/main/java/com/github/steveice10/packetlib/Server.java b/src/main/java/com/github/steveice10/packetlib/Server.java index 2dd8fb60..3891d819 100644 --- a/src/main/java/com/github/steveice10/packetlib/Server.java +++ b/src/main/java/com/github/steveice10/packetlib/Server.java @@ -5,6 +5,7 @@ import com.github.steveice10.packetlib.packet.PacketProtocol; import java.util.List; import java.util.Map; +import java.util.function.Supplier; /** * Listens for new sessions to connect. @@ -15,35 +16,35 @@ public interface Server { * * @return The listening host. */ - public String getHost(); + String getHost(); /** * Gets the port the session is listening on. * * @return The listening port. */ - public int getPort(); + int getPort(); /** * Gets the packet protocol of the server. * * @return The server's packet protocol. */ - public Class getPacketProtocol(); + Supplier getPacketProtocol(); /** * Returns true if the listener is listening. * * @return True if the listener is listening. */ - public boolean isListening(); + boolean isListening(); /** * Gets this server's set flags. * * @return This server's flags. */ - public Map getGlobalFlags(); + Map getGlobalFlags(); /** * Checks whether this server has a flag set. @@ -51,7 +52,7 @@ public interface Server { * @param key Key of the flag to check for. * @return Whether this server has a flag set. */ - public boolean hasGlobalFlag(String key); + boolean hasGlobalFlag(String key); /** * Gets the value of the given flag as an instance of the given type. @@ -61,7 +62,7 @@ public interface Server { * @return Value of the flag. * @throws IllegalStateException If the flag's value isn't of the required type. */ - public T getGlobalFlag(String key); + T getGlobalFlag(String key); /** * Gets the value of the given flag as an instance of the given type. @@ -74,7 +75,7 @@ public interface Server { * @throws IllegalStateException If the flag's value isn't of the required type. */ @SuppressWarnings("unchecked") - public T getGlobalFlag(String key, T def); + T getGlobalFlag(String key, T def); /** * Sets the value of a flag. The flag will be used in sessions if a session does @@ -83,47 +84,47 @@ public interface Server { * @param key Key of the flag. * @param value Value to set the flag to. */ - public void setGlobalFlag(String key, Object value); + void setGlobalFlag(String key, Object value); /** * Gets the listeners listening on this session. * * @return This server's listeners. */ - public List getListeners(); + List getListeners(); /** * Adds a listener to this server. * * @param listener Listener to add. */ - public void addListener(ServerListener listener); + void addListener(ServerListener listener); /** * Removes a listener from this server. * * @param listener Listener to remove. */ - public void removeListener(ServerListener listener); + void removeListener(ServerListener listener); /** * Gets all sessions belonging to this server. * * @return Sessions belonging to this server. */ - public List getSessions(); + List getSessions(); /** * Binds the listener to its host and port. */ - public AbstractServer bind(); + AbstractServer bind(); /** * Binds the listener to its host and port. * * @param wait Whether to wait for the listener to finish binding. */ - public AbstractServer bind(boolean wait); + AbstractServer bind(boolean wait); /** * Binds the listener to its host and port. @@ -131,19 +132,19 @@ public interface Server { * @param wait Whether to wait for the listener to finish binding. * @param callback Callback to call when the listener has finished binding. */ - public AbstractServer bind(boolean wait, Runnable callback); + AbstractServer bind(boolean wait, Runnable callback); /** * Closes the listener. */ - public void close(); + void close(); /** * Closes the listener. * * @param wait Whether to wait for the listener to finish closing. */ - public void close(boolean wait); + void close(boolean wait); /** * Closes the listener. @@ -151,5 +152,5 @@ public interface Server { * @param wait Whether to wait for the listener to finish closing. * @param callback Callback to call when the listener has finished closing. */ - public void close(boolean wait, Runnable callback); + void close(boolean wait, Runnable callback); } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index d84e9fac..182c130f 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -24,13 +24,14 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import java.net.InetSocketAddress; +import java.util.function.Supplier; public class TcpServer extends AbstractServer { private EventLoopGroup group; private Class serverSocketChannel; private Channel channel; - public TcpServer(String host, int port, Class protocol) { + public TcpServer(String host, int port, Supplier protocol) { super(host, port, protocol); } From 2a8d18a3f825ab4737ed442c57b30f7cbd473703 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 15 Nov 2021 14:38:17 -0500 Subject: [PATCH 154/180] Add an option to read from enum --- .../steveice10/packetlib/io/NetInput.java | 67 ++++++++++++------- .../steveice10/packetlib/io/NetOutput.java | 52 ++++++++------ 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/io/NetInput.java b/src/main/java/com/github/steveice10/packetlib/io/NetInput.java index b271c38a..dcfa44f1 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/NetInput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/NetInput.java @@ -13,7 +13,7 @@ public interface NetInput { * @return The next boolean. * @throws java.io.IOException If an I/O error occurs. */ - public boolean readBoolean() throws IOException; + boolean readBoolean() throws IOException; /** * Reads the next byte. @@ -21,7 +21,7 @@ public interface NetInput { * @return The next byte. * @throws java.io.IOException If an I/O error occurs. */ - public byte readByte() throws IOException; + byte readByte() throws IOException; /** * Reads the next unsigned byte. @@ -29,7 +29,7 @@ public interface NetInput { * @return The next unsigned byte. * @throws java.io.IOException If an I/O error occurs. */ - public int readUnsignedByte() throws IOException; + int readUnsignedByte() throws IOException; /** * Reads the next short. @@ -45,7 +45,7 @@ public interface NetInput { * @return The next unsigned short. * @throws java.io.IOException If an I/O error occurs. */ - public int readUnsignedShort() throws IOException; + int readUnsignedShort() throws IOException; /** * Reads the next char. @@ -53,7 +53,7 @@ public interface NetInput { * @return The next char. * @throws java.io.IOException If an I/O error occurs. */ - public char readChar() throws IOException; + char readChar() throws IOException; /** * Reads the next integer. @@ -61,7 +61,7 @@ public interface NetInput { * @return The next integer. * @throws java.io.IOException If an I/O error occurs. */ - public int readInt() throws IOException; + int readInt() throws IOException; /** * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. @@ -69,7 +69,7 @@ public interface NetInput { * @return The next varint. * @throws java.io.IOException If an I/O error occurs. */ - public int readVarInt() throws IOException; + int readVarInt() throws IOException; /** * Reads the next long. @@ -77,7 +77,7 @@ public interface NetInput { * @return The next long. * @throws java.io.IOException If an I/O error occurs. */ - public long readLong() throws IOException; + long readLong() throws IOException; /** * Reads the next varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. @@ -85,7 +85,7 @@ public interface NetInput { * @return The next varlong. * @throws java.io.IOException If an I/O error occurs. */ - public long readVarLong() throws IOException; + long readVarLong() throws IOException; /** * Reads the next float. @@ -93,7 +93,7 @@ public interface NetInput { * @return The next float. * @throws java.io.IOException If an I/O error occurs. */ - public float readFloat() throws IOException; + float readFloat() throws IOException; /** * Reads the next double. @@ -101,7 +101,7 @@ public interface NetInput { * @return The next double. * @throws java.io.IOException If an I/O error occurs. */ - public double readDouble() throws IOException; + double readDouble() throws IOException; /** * Reads the next byte array. @@ -110,7 +110,7 @@ public interface NetInput { * @return The next byte array. * @throws java.io.IOException If an I/O error occurs. */ - public byte[] readBytes(int length) throws IOException; + byte[] readBytes(int length) throws IOException; /** * Reads as much data as possible into the given byte array. @@ -119,7 +119,7 @@ public interface NetInput { * @return The amount of bytes read, or -1 if no bytes could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readBytes(byte b[]) throws IOException; + int readBytes(byte b[]) throws IOException; /** * Reads the given amount of bytes into the given array at the given offset. @@ -130,7 +130,7 @@ public interface NetInput { * @return The amount of bytes read, or -1 if no bytes could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readBytes(byte b[], int offset, int length) throws IOException; + int readBytes(byte b[], int offset, int length) throws IOException; /** * Reads the next short array. @@ -139,7 +139,7 @@ public interface NetInput { * @return The next short array. * @throws java.io.IOException If an I/O error occurs. */ - public short[] readShorts(int length) throws IOException; + short[] readShorts(int length) throws IOException; /** * Reads as much data as possible into the given short array. @@ -148,7 +148,7 @@ public interface NetInput { * @return The amount of shorts read, or -1 if no shorts could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readShorts(short s[]) throws IOException; + int readShorts(short s[]) throws IOException; /** * Reads the given amount of shorts into the given array at the given offset. @@ -159,7 +159,7 @@ public interface NetInput { * @return The amount of shorts read, or -1 if no shorts could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readShorts(short s[], int offset, int length) throws IOException; + int readShorts(short s[], int offset, int length) throws IOException; /** * Reads the next int array. @@ -168,7 +168,7 @@ public interface NetInput { * @return The next int array. * @throws java.io.IOException If an I/O error occurs. */ - public int[] readInts(int length) throws IOException; + int[] readInts(int length) throws IOException; /** * Reads as much data as possible into the given int array. @@ -177,7 +177,7 @@ public interface NetInput { * @return The amount of ints read, or -1 if no ints could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readInts(int i[]) throws IOException; + int readInts(int i[]) throws IOException; /** * Reads the given amount of ints into the given array at the given offset. @@ -188,7 +188,7 @@ public interface NetInput { * @return The amount of ints read, or -1 if no ints could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readInts(int i[], int offset, int length) throws IOException; + int readInts(int i[], int offset, int length) throws IOException; /** * Reads the next long array. @@ -197,7 +197,7 @@ public interface NetInput { * @return The next long array. * @throws java.io.IOException If an I/O error occurs. */ - public long[] readLongs(int length) throws IOException; + long[] readLongs(int length) throws IOException; /** * Reads as much data as possible into the given long array. @@ -206,7 +206,7 @@ public interface NetInput { * @return The amount of longs read, or -1 if no longs could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readLongs(long l[]) throws IOException; + int readLongs(long l[]) throws IOException; /** * Reads the given amount of longs into the given array at the given offset. @@ -217,7 +217,7 @@ public interface NetInput { * @return The amount of longs read, or -1 if no longs could be read. * @throws java.io.IOException If an I/O error occurs. */ - public int readLongs(long l[], int offset, int length) throws IOException; + int readLongs(long l[], int offset, int length) throws IOException; /** * Reads the next string. @@ -225,7 +225,7 @@ public interface NetInput { * @return The next string. * @throws java.io.IOException If an I/O error occurs. */ - public String readString() throws IOException; + String readString() throws IOException; /** * Reads the next UUID. @@ -233,7 +233,22 @@ public interface NetInput { * @return The next UUID. * @throws java.io.IOException If an I/O error occurs. */ - public UUID readUUID() throws IOException; + UUID readUUID() throws IOException; + + /** + * Reads the next enum. + * + * @param values the collection of enums to read from + * @return the next enum. + * @throws IOException If an I/O error occurs. + */ + default > T readEnum(T[] values) throws IOException { + int index = readVarInt(); + if (index >= values.length) { + throw new IndexOutOfBoundsException("Enum class " + values.getClass() + " does not have a value with index " + index); + } + return values[index]; + } /** * Gets the number of available bytes. @@ -241,5 +256,5 @@ public interface NetInput { * @return The number of available bytes. * @throws java.io.IOException If an I/O error occurs. */ - public int available() throws IOException; + int available() throws IOException; } diff --git a/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java index d50a69f6..dcc3299c 100644 --- a/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java +++ b/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java @@ -13,7 +13,7 @@ public interface NetOutput { * @param b Boolean to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeBoolean(boolean b) throws IOException; + void writeBoolean(boolean b) throws IOException; /** * Writes a byte. @@ -21,7 +21,7 @@ public interface NetOutput { * @param b Byte to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeByte(int b) throws IOException; + void writeByte(int b) throws IOException; /** * Writes a short. @@ -29,7 +29,7 @@ public interface NetOutput { * @param s Short to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeShort(int s) throws IOException; + void writeShort(int s) throws IOException; /** * Writes a char. @@ -37,7 +37,7 @@ public interface NetOutput { * @param c Char to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeChar(int c) throws IOException; + void writeChar(int c) throws IOException; /** * Writes a integer. @@ -45,7 +45,7 @@ public interface NetOutput { * @param i Integer to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeInt(int i) throws IOException; + void writeInt(int i) throws IOException; /** * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. @@ -53,7 +53,7 @@ public interface NetOutput { * @param i Varint to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeVarInt(int i) throws IOException; + void writeVarInt(int i) throws IOException; /** * Writes a long. @@ -61,7 +61,7 @@ public interface NetOutput { * @param l Long to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeLong(long l) throws IOException; + void writeLong(long l) throws IOException; /** * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. @@ -69,7 +69,7 @@ public interface NetOutput { * @param l Varlong to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeVarLong(long l) throws IOException; + void writeVarLong(long l) throws IOException; /** * Writes a float. @@ -77,7 +77,7 @@ public interface NetOutput { * @param f Float to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeFloat(float f) throws IOException; + void writeFloat(float f) throws IOException; /** * Writes a double. @@ -85,7 +85,7 @@ public interface NetOutput { * @param d Double to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeDouble(double d) throws IOException; + void writeDouble(double d) throws IOException; /** * Writes a byte array. @@ -93,7 +93,7 @@ public interface NetOutput { * @param b Byte array to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeBytes(byte b[]) throws IOException; + void writeBytes(byte b[]) throws IOException; /** * Writes a byte array, using the given amount of bytes. @@ -102,7 +102,7 @@ public interface NetOutput { * @param length Bytes to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeBytes(byte b[], int length) throws IOException; + void writeBytes(byte b[], int length) throws IOException; /** * Writes a short array. @@ -110,7 +110,7 @@ public interface NetOutput { * @param s Short array to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeShorts(short s[]) throws IOException; + void writeShorts(short s[]) throws IOException; /** * Writes a short array, using the given amount of bytes. @@ -119,7 +119,7 @@ public interface NetOutput { * @param length Shorts to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeShorts(short s[], int length) throws IOException; + void writeShorts(short s[], int length) throws IOException; /** * Writes an int array. @@ -127,7 +127,7 @@ public interface NetOutput { * @param i Int array to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeInts(int i[]) throws IOException; + void writeInts(int i[]) throws IOException; /** * Writes an int array, using the given amount of bytes. @@ -136,7 +136,7 @@ public interface NetOutput { * @param length Ints to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeInts(int i[], int length) throws IOException; + void writeInts(int i[], int length) throws IOException; /** * Writes a long array. @@ -144,7 +144,7 @@ public interface NetOutput { * @param l Long array to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeLongs(long l[]) throws IOException; + void writeLongs(long l[]) throws IOException; /** * Writes a long array, using the given amount of bytes. @@ -153,7 +153,7 @@ public interface NetOutput { * @param length Longs to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeLongs(long l[], int length) throws IOException; + void writeLongs(long l[], int length) throws IOException; /** * Writes a string. @@ -161,7 +161,7 @@ public interface NetOutput { * @param s String to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeString(String s) throws IOException; + void writeString(String s) throws IOException; /** * Writes a UUID. @@ -169,12 +169,22 @@ public interface NetOutput { * @param uuid UUID to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeUUID(UUID uuid) throws IOException; + void writeUUID(UUID uuid) throws IOException; + + /** + * Writes an enum. + * + * @param e Enum to write. + * @throws IOException + */ + default void writeEnum(Enum e) throws IOException { + writeVarInt(e.ordinal()); + } /** * Flushes the output. * * @throws java.io.IOException If an I/O error occurs. */ - public void flush() throws IOException; + void flush() throws IOException; } From a61bcb97f781e1d70b90e024734737f3d0270508 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 24 Nov 2021 11:21:14 -0500 Subject: [PATCH 155/180] Use a constructor parameter to determine clientsideness in packet encoder --- .../com/github/steveice10/packetlib/tcp/TcpClientSession.java | 2 +- .../com/github/steveice10/packetlib/tcp/TcpPacketCodec.java | 4 ++-- .../java/com/github/steveice10/packetlib/tcp/TcpServer.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 39aa48c8..ee5a92d9 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -114,7 +114,7 @@ public class TcpClientSession extends TcpSession { pipeline.addLast("encryption", new TcpPacketEncryptor(TcpClientSession.this)); pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); - pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this)); + pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this, true)); pipeline.addLast("manager", TcpClientSession.this); addHAProxySupport(pipeline); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 72ac701e..7a38e025 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -18,9 +18,9 @@ public class TcpPacketCodec extends ByteToMessageCodec { private final Session session; private final boolean client; - public TcpPacketCodec(Session session) { + public TcpPacketCodec(Session session, boolean client) { this.session = session; - this.client = session instanceof TcpClientSession; + this.client = client; } @Override diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 182c130f..c57f3fb6 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -83,7 +83,7 @@ public class TcpServer extends AbstractServer { pipeline.addLast("encryption", new TcpPacketEncryptor(session)); pipeline.addLast("sizer", new TcpPacketSizer(session)); - pipeline.addLast("codec", new TcpPacketCodec(session)); + pipeline.addLast("codec", new TcpPacketCodec(session, false)); pipeline.addLast("manager", session); } }).group(this.group).localAddress(this.getHost(), this.getPort()).bind(); From 67fb81e027f1f6f80ed8e390cef3aca7e6663d76 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 24 Nov 2021 19:29:19 -0500 Subject: [PATCH 156/180] Reduce unnecessary checks and only add encryption when enabled --- .../github/steveice10/packetlib/Session.java | 8 ++++ .../packetlib/packet/PacketProtocol.java | 7 ---- .../packetlib/tcp/TcpClientSession.java | 10 +++-- .../packetlib/tcp/TcpPacketEncryptor.java | 41 ++++++++----------- .../packetlib/tcp/TcpPacketSizer.java | 41 +++++++++---------- .../steveice10/packetlib/tcp/TcpServer.java | 7 +++- .../steveice10/packetlib/tcp/TcpSession.java | 6 +++ 7 files changed, 62 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index abe02332..da961c47 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -1,5 +1,6 @@ package com.github.steveice10.packetlib; +import com.github.steveice10.packetlib.crypt.PacketEncryption; import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; @@ -153,6 +154,13 @@ public interface Session { */ public void setCompressionThreshold(int threshold); + /** + * Enables encryption for this session. + * + * @param encryption the encryption to encrypt with + */ + void enableEncryption(PacketEncryption encryption); + /** * Gets the connect timeout for this session in seconds. * diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 3fa6b876..edf74226 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -35,13 +35,6 @@ public abstract class PacketProtocol { */ public abstract PacketHeader getPacketHeader(); - /** - * Gets this protocol's active packet encryption. - * - * @return The protocol's packet encryption, or null if packets should not be encrypted. - */ - public abstract PacketEncryption getEncryption(); - /** * Called when a client session is created with this protocol. * diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index ee5a92d9..e9f27c7f 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -93,7 +93,8 @@ public class TcpClientSession extends TcpSession { bootstrap.handler(new ChannelInitializer() { @Override public void initChannel(Channel channel) { - getPacketProtocol().newClientSession(TcpClientSession.this); + PacketProtocol protocol = getPacketProtocol(); + protocol.newClientSession(TcpClientSession.this); channel.config().setOption(ChannelOption.IP_TOS, 0x18); try { @@ -112,8 +113,11 @@ public class TcpClientSession extends TcpSession { addProxy(pipeline); - pipeline.addLast("encryption", new TcpPacketEncryptor(TcpClientSession.this)); - pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this)); + int size = protocol.getPacketHeader().getLengthSize(); + if (size > 0) { + pipeline.addLast("sizer", new TcpPacketSizer(TcpClientSession.this, size)); + } + pipeline.addLast("codec", new TcpPacketCodec(TcpClientSession.this, true)); pipeline.addLast("manager", TcpClientSession.this); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java index e71159d1..0220f40d 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.crypt.PacketEncryption; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; @@ -8,46 +9,38 @@ import io.netty.handler.codec.ByteToMessageCodec; import java.util.List; public class TcpPacketEncryptor extends ByteToMessageCodec { - private final Session session; + private final PacketEncryption encryption; private byte[] decryptedArray = new byte[0]; private byte[] encryptedArray = new byte[0]; - public TcpPacketEncryptor(Session session) { - this.session = session; + public TcpPacketEncryptor(PacketEncryption encryption) { + this.encryption = encryption; } @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - if(this.session.getPacketProtocol().getEncryption() != null) { - int length = in.readableBytes(); - byte[] bytes = this.getBytes(in); - int outLength = this.session.getPacketProtocol().getEncryption().getEncryptOutputSize(length); - if(this.encryptedArray.length < outLength) { - this.encryptedArray = new byte[outLength]; - } - - out.writeBytes(this.encryptedArray, 0, this.session.getPacketProtocol().getEncryption().encrypt(bytes, 0, length, this.encryptedArray, 0)); - } else { - out.writeBytes(in); + int length = in.readableBytes(); + byte[] bytes = this.getBytes(in); + int outLength = this.encryption.getEncryptOutputSize(length); + if( this.encryptedArray.length < outLength) { + this.encryptedArray = new byte[outLength]; } + + out.writeBytes(this.encryptedArray, 0, this.encryption.encrypt(bytes, 0, length, this.encryptedArray, 0)); } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - if(this.session.getPacketProtocol().getEncryption() != null) { - int length = buf.readableBytes(); - byte[] bytes = this.getBytes(buf); - ByteBuf result = ctx.alloc().heapBuffer(this.session.getPacketProtocol().getEncryption().getDecryptOutputSize(length)); - result.writerIndex(this.session.getPacketProtocol().getEncryption().decrypt(bytes, 0, length, result.array(), result.arrayOffset())); - out.add(result); - } else { - out.add(buf.readBytes(buf.readableBytes())); - } + int length = buf.readableBytes(); + byte[] bytes = this.getBytes(buf); + ByteBuf result = ctx.alloc().heapBuffer(this.encryption.getDecryptOutputSize(length)); + result.writerIndex(this.encryption.decrypt(bytes, 0, length, result.array(), result.arrayOffset())); + out.add(result); } private byte[] getBytes(ByteBuf buf) { int length = buf.readableBytes(); - if(this.decryptedArray.length < length) { + if (this.decryptedArray.length < length) { this.decryptedArray = new byte[length]; } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index 0aeeb4d7..da6eb8bc 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -13,9 +13,11 @@ import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { private final Session session; + private final int size; - public TcpPacketSizer(Session session) { + public TcpPacketSizer(Session session, int size) { this.session = session; + this.size = size; } @Override @@ -28,32 +30,27 @@ public class TcpPacketSizer extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { - int size = this.session.getPacketProtocol().getPacketHeader().getLengthSize(); - if(size > 0) { - buf.markReaderIndex(); - byte[] lengthBytes = new byte[size]; - for(int index = 0; index < lengthBytes.length; index++) { - if(!buf.isReadable()) { + buf.markReaderIndex(); + byte[] lengthBytes = new byte[size]; + for (int index = 0; index < lengthBytes.length; index++) { + if (!buf.isReadable()) { + buf.resetReaderIndex(); + return; + } + + lengthBytes[index] = buf.readByte(); + if ((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { + int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); + if (buf.readableBytes() < length) { buf.resetReaderIndex(); return; } - lengthBytes[index] = buf.readByte(); - if((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { - int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); - if(buf.readableBytes() < length) { - buf.resetReaderIndex(); - return; - } - - out.add(buf.readBytes(length)); - return; - } + out.add(buf.readBytes(length)); + return; } - - throw new CorruptedFrameException("Length is too long."); - } else { - out.add(buf.readBytes(buf.readableBytes())); } + + throw new CorruptedFrameException("Length is too long."); } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index c57f3fb6..7cd0ee86 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -81,8 +81,11 @@ public class TcpServer extends AbstractServer { session.refreshReadTimeoutHandler(channel); session.refreshWriteTimeoutHandler(channel); - pipeline.addLast("encryption", new TcpPacketEncryptor(session)); - pipeline.addLast("sizer", new TcpPacketSizer(session)); + int size = protocol.getPacketHeader().getLengthSize(); + if (size > 0) { + pipeline.addLast("sizer", new TcpPacketSizer(session, size)); + } + pipeline.addLast("codec", new TcpPacketCodec(session, false)); pipeline.addLast("manager", session); } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 6997431a..173439d0 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.crypt.PacketEncryption; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; @@ -172,6 +173,11 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } } + @Override + public void enableEncryption(PacketEncryption encryption) { + channel.pipeline().addBefore("sizer", "encryption", new TcpPacketEncryptor(encryption)); + } + @Override public int getConnectTimeout() { return this.connectTimeout; From 9e38c6192726b926e3fd5d20f7aaecfe7535406e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 24 Nov 2021 23:32:14 -0500 Subject: [PATCH 157/180] Remove allocations for packet receive and send events These were just replaced with functions that call the session and packet. --- .../packetlib/test/ClientSessionListener.java | 27 +++++----- .../packetlib/test/PingServerTest.java | 2 +- .../packetlib/test/ServerListener.java | 1 + .../packetlib/test/ServerSessionListener.java | 18 +++---- .../packetlib/test/TestProtocol.java | 3 +- .../github/steveice10/packetlib/Session.java | 16 +++++- .../event/session/PacketReceivedEvent.java | 53 ------------------- .../event/session/PacketSentEvent.java | 53 ------------------- .../event/session/SessionAdapter.java | 7 ++- .../event/session/SessionListener.java | 11 ++-- .../packetlib/tcp/TcpPacketCodec.java | 1 - .../steveice10/packetlib/tcp/TcpSession.java | 38 +++++++++---- 12 files changed, 82 insertions(+), 148 deletions(-) delete mode 100644 src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java diff --git a/example/com/github/steveice10/packetlib/test/ClientSessionListener.java b/example/com/github/steveice10/packetlib/test/ClientSessionListener.java index 93f88ce7..39ef0b38 100644 --- a/example/com/github/steveice10/packetlib/test/ClientSessionListener.java +++ b/example/com/github/steveice10/packetlib/test/ClientSessionListener.java @@ -1,32 +1,32 @@ package com.github.steveice10.packetlib.test; +import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; -import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; -import com.github.steveice10.packetlib.event.session.PacketSentEvent; import com.github.steveice10.packetlib.event.session.SessionAdapter; +import com.github.steveice10.packetlib.packet.Packet; public class ClientSessionListener extends SessionAdapter { @Override - public void packetReceived(PacketReceivedEvent event) { - if(event.getPacket() instanceof PingPacket) { - PingPacket packet = event.getPacket(); + public void packetReceived(Session session, Packet packet) { + if (packet instanceof PingPacket) { + String id = ((PingPacket) packet).getPingId(); - System.out.println("CLIENT Received: " + packet.getPingId()); + System.out.println("CLIENT Received: " + id); - if(packet.getPingId().equals("hello")) { - event.getSession().send(new PingPacket("exit")); - } else if(packet.getPingId().equals("exit")) { - event.getSession().disconnect("Finished"); + if (id.equals("hello")) { + session.send(new PingPacket("exit")); + } else if (id.equals("exit")) { + session.disconnect("Finished"); } } } @Override - public void packetSent(PacketSentEvent event) { - if(event.getPacket() instanceof PingPacket) { - System.out.println("CLIENT Sent: " + event.getPacket().getPingId()); + public void packetSent(Session session, Packet packet) { + if (packet instanceof PingPacket) { + System.out.println("CLIENT Sent: " + ((PingPacket) packet).getPingId()); } } @@ -34,6 +34,7 @@ public class ClientSessionListener extends SessionAdapter { public void connected(ConnectedEvent event) { System.out.println("CLIENT Connected"); + event.getSession().enableEncryption(((TestProtocol) event.getSession().getPacketProtocol()).getEncryption()); event.getSession().send(new PingPacket("hello")); } diff --git a/example/com/github/steveice10/packetlib/test/PingServerTest.java b/example/com/github/steveice10/packetlib/test/PingServerTest.java index 2db3b031..6ee4f0c3 100644 --- a/example/com/github/steveice10/packetlib/test/PingServerTest.java +++ b/example/com/github/steveice10/packetlib/test/PingServerTest.java @@ -21,7 +21,7 @@ public class PingServerTest { return; } - Server server = new TcpServer("127.0.0.1", 25565, TestProtocol.class); + Server server = new TcpServer("127.0.0.1", 25565, TestProtocol::new); server.addListener(new ServerListener(key)); server.bind(); diff --git a/example/com/github/steveice10/packetlib/test/ServerListener.java b/example/com/github/steveice10/packetlib/test/ServerListener.java index 3c7dfcb2..34911bfc 100644 --- a/example/com/github/steveice10/packetlib/test/ServerListener.java +++ b/example/com/github/steveice10/packetlib/test/ServerListener.java @@ -35,6 +35,7 @@ public class ServerListener extends ServerAdapter { public void sessionAdded(SessionAddedEvent event) { System.out.println("SERVER Session Added: " + event.getSession().getHost() + ":" + event.getSession().getPort()); ((TestProtocol) event.getSession().getPacketProtocol()).setSecretKey(this.key); + event.getSession().enableEncryption(((TestProtocol) event.getSession().getPacketProtocol()).getEncryption()); } @Override diff --git a/example/com/github/steveice10/packetlib/test/ServerSessionListener.java b/example/com/github/steveice10/packetlib/test/ServerSessionListener.java index b147bf3c..81a44cde 100644 --- a/example/com/github/steveice10/packetlib/test/ServerSessionListener.java +++ b/example/com/github/steveice10/packetlib/test/ServerSessionListener.java @@ -1,25 +1,25 @@ package com.github.steveice10.packetlib.test; +import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; -import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; -import com.github.steveice10.packetlib.event.session.PacketSentEvent; import com.github.steveice10.packetlib.event.session.SessionAdapter; +import com.github.steveice10.packetlib.packet.Packet; public class ServerSessionListener extends SessionAdapter { @Override - public void packetReceived(PacketReceivedEvent event) { - if(event.getPacket() instanceof PingPacket) { - System.out.println("SERVER Received: " + event.getPacket().getPingId()); - event.getSession().send(event.getPacket()); + public void packetReceived(Session session, Packet packet) { + if (packet instanceof PingPacket) { + System.out.println("SERVER Received: " + ((PingPacket) packet).getPingId()); + session.send(packet); } } @Override - public void packetSent(PacketSentEvent event) { - if(event.getPacket() instanceof PingPacket) { - System.out.println("SERVER Sent: " + event.getPacket().getPingId()); + public void packetSent(Session session, Packet packet) { + if (packet instanceof PingPacket) { + System.out.println("SERVER Sent: " + ((PingPacket) packet).getPingId()); } } diff --git a/example/com/github/steveice10/packetlib/test/TestProtocol.java b/example/com/github/steveice10/packetlib/test/TestProtocol.java index 45b44b5b..c182a27e 100644 --- a/example/com/github/steveice10/packetlib/test/TestProtocol.java +++ b/example/com/github/steveice10/packetlib/test/TestProtocol.java @@ -16,7 +16,7 @@ public class TestProtocol extends PacketProtocol { private AESEncryption encrypt; @SuppressWarnings("unused") - private TestProtocol() { + public TestProtocol() { } public TestProtocol(SecretKey key) { @@ -42,7 +42,6 @@ public class TestProtocol extends PacketProtocol { return this.header; } - @Override public PacketEncryption getEncryption() { return this.encrypt; } diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index da961c47..96a4501c 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -138,7 +138,21 @@ public interface Session { * * @param event Event to call. */ - public void callEvent(SessionEvent event); + void callEvent(SessionEvent event); + + /** + * Notifies all listeners that a packet was just received. + * + * @param packet Packet to notify. + */ + void callPacketReceived(Packet packet); + + /** + * Notifies all listeners that a packet was just sent. + * + * @param packet Packet to notify. + */ + void callPacketSent(Packet packet); /** * Gets the compression packet length threshold for this session (-1 = disabled). diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java deleted file mode 100644 index 996e43b1..00000000 --- a/src/main/java/com/github/steveice10/packetlib/event/session/PacketReceivedEvent.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.github.steveice10.packetlib.event.session; - -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.packet.Packet; - -/** - * Called when the session receives a packet. - */ -public class PacketReceivedEvent implements SessionEvent { - private Session session; - private Packet packet; - - /** - * Creates a new PacketReceivedEvent instance. - * - * @param session Session receiving a packet. - * @param packet Packet being received. - */ - public PacketReceivedEvent(Session session, Packet packet) { - this.session = session; - this.packet = packet; - } - - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - /** - * Gets the packet involved in this event as the required type. - * - * @param Type of the packet. - * @return The event's packet as the required type. - * @throws IllegalStateException If the packet's value isn't of the required type. - */ - @SuppressWarnings("unchecked") - public T getPacket() { - try { - return (T) this.packet; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); - } - } - - @Override - public void call(SessionListener listener) { - listener.packetReceived(this); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java deleted file mode 100644 index 17bda0bd..00000000 --- a/src/main/java/com/github/steveice10/packetlib/event/session/PacketSentEvent.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.github.steveice10.packetlib.event.session; - -import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.packet.Packet; - -/** - * Called when the session has sent a packet. - */ -public class PacketSentEvent implements SessionEvent { - private Session session; - private Packet packet; - - /** - * Creates a new PacketSentEvent instance. - * - * @param session Session sending the packet. - * @param packet Packet being sent. - */ - public PacketSentEvent(Session session, Packet packet) { - this.session = session; - this.packet = packet; - } - - /** - * Gets the session involved in this event. - * - * @return The event's session. - */ - public Session getSession() { - return this.session; - } - - /** - * Gets the packet involved in this event as the required type. - * - * @param Type of the packet. - * @return The event's packet as the required type. - * @throws IllegalStateException If the packet's value isn't of the required type. - */ - @SuppressWarnings("unchecked") - public T getPacket() { - try { - return (T) this.packet; - } catch(ClassCastException e) { - throw new IllegalStateException("Tried to get packet as the wrong type. Actual type: " + this.packet.getClass().getName()); - } - } - - @Override - public void call(SessionListener listener) { - listener.packetSent(this); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java index 7dd5b211..83de67b3 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java @@ -1,11 +1,14 @@ package com.github.steveice10.packetlib.event.session; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; + /** * An adapter for picking session events to listen for. */ public class SessionAdapter implements SessionListener { @Override - public void packetReceived(PacketReceivedEvent event) { + public void packetReceived(Session session, Packet packet) { } @Override @@ -13,7 +16,7 @@ public class SessionAdapter implements SessionListener { } @Override - public void packetSent(PacketSentEvent event) { + public void packetSent(Session session, Packet packet) { } @Override diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java index cf1f3a4c..6ffd3f0c 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java @@ -1,5 +1,8 @@ package com.github.steveice10.packetlib.event.session; +import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.packet.Packet; + /** * A listener for listening to session events. */ @@ -7,9 +10,9 @@ public interface SessionListener { /** * Called when a session receives a packet. * - * @param event Data relating to the event. + * @param packet the packet that was just received. */ - public void packetReceived(PacketReceivedEvent event); + void packetReceived(Session session, Packet packet); /** * Called when a session is sending a packet. @@ -21,9 +24,9 @@ public interface SessionListener { /** * Called when a session sends a packet. * - * @param event Data relating to the event. + * @param packet Packet just sent. */ - public void packetSent(PacketSentEvent event); + void packetSent(Session session, Packet packet); /** * Called when a session encounters an error while reading or writing packet data. diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 7a38e025..963bd062 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -2,7 +2,6 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.event.session.PacketErrorEvent; -import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.io.NetInput; import com.github.steveice10.packetlib.io.NetOutput; import com.github.steveice10.packetlib.packet.Packet; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 173439d0..c752483c 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -5,9 +5,7 @@ import com.github.steveice10.packetlib.crypt.PacketEncryption; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectingEvent; -import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.event.session.PacketSendingEvent; -import com.github.steveice10.packetlib.event.session.PacketSentEvent; import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; @@ -21,14 +19,11 @@ import io.netty.handler.timeout.WriteTimeoutHandler; import javax.annotation.Nullable; import java.net.ConnectException; import java.net.SocketAddress; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.LinkedBlockingQueue; public abstract class TcpSession extends SimpleChannelInboundHandler implements Session { /** @@ -149,7 +144,29 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp for (SessionListener listener : this.listeners) { event.call(listener); } - } catch(Throwable t) { + } catch (Throwable t) { + exceptionCaught(null, t); + } + } + + @Override + public void callPacketReceived(Packet packet) { + try { + for (SessionListener listener : this.listeners) { + listener.packetReceived(this, packet); + } + } catch (Throwable t) { + exceptionCaught(null, t); + } + } + + @Override + public void callPacketSent(Packet packet) { + try { + for (SessionListener listener : this.listeners) { + listener.packetSent(this, packet); + } + } catch (Throwable t) { exceptionCaught(null, t); } } @@ -175,6 +192,9 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void enableEncryption(PacketEncryption encryption) { + if (channel == null) { + throw new IllegalStateException("Connect the client before initializing encryption!"); + } channel.pipeline().addBefore("sizer", "encryption", new TcpPacketEncryptor(encryption)); } @@ -228,7 +248,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp final Packet toSend = sendingEvent.getPacket(); this.channel.writeAndFlush(toSend).addListener((ChannelFutureListener) future -> { if(future.isSuccess()) { - callEvent(new PacketSentEvent(TcpSession.this, toSend)); + callPacketSent(toSend); } else { exceptionCaught(null, future.cause()); } @@ -352,9 +372,9 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override protected void channelRead0(ChannelHandlerContext ctx, Packet packet) { if (!packet.isPriority() && eventLoop != null) { - eventLoop.execute(() -> this.callEvent(new PacketReceivedEvent(this, packet))); + eventLoop.execute(() -> this.callPacketReceived(packet)); } else { - this.callEvent(new PacketReceivedEvent(this, packet)); + this.callPacketReceived(packet); } } } From 4cb1588e3f1a5f7bd52c924dd8c91a5c8a60ce0f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 20 Dec 2021 20:38:15 -0500 Subject: [PATCH 158/180] Add option to validate decompression --- .../com/github/steveice10/packetlib/Session.java | 5 +++-- .../packetlib/tcp/TcpPacketCompression.java | 16 ++++++++++------ .../steveice10/packetlib/tcp/TcpSession.java | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index 96a4501c..9cfda95e 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -159,14 +159,15 @@ public interface Session { * * @return This session's compression threshold. */ - public int getCompressionThreshold(); + int getCompressionThreshold(); /** * Sets the compression packet length threshold for this session (-1 = disabled). * * @param threshold The new compression threshold. + * @param validateDecompression whether to validate that the decompression fits within size checks. */ - public void setCompressionThreshold(int threshold); + void setCompressionThreshold(int threshold, boolean validateDecompression); /** * Enables encryption for this session. diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index faa4ca86..8d2a10aa 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -20,9 +20,11 @@ public class TcpPacketCompression extends ByteToMessageCodec { private final Deflater deflater = new Deflater(); private final Inflater inflater = new Inflater(); private final byte[] buf = new byte[8192]; + private final boolean validateDecompression; - public TcpPacketCompression(Session session) { + public TcpPacketCompression(Session session, boolean validateDecompression) { this.session = session; + this.validateDecompression = validateDecompression; } @Override @@ -63,12 +65,14 @@ public class TcpPacketCompression extends ByteToMessageCodec { if(size == 0) { out.add(buf.readBytes(buf.readableBytes())); } else { - if(size < this.session.getCompressionThreshold()) { - throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); - } + if (validateDecompression) { // This is sectioned off as of at least Java Edition 1.18 + if (size < this.session.getCompressionThreshold()) { + throw new DecoderException("Badly compressed packet: size of " + size + " is below threshold of " + this.session.getCompressionThreshold() + "."); + } - if(size > MAX_COMPRESSED_SIZE) { - throw new DecoderException("Badly compressed packet: size of " + size + " is larger than protocol maximum of " + MAX_COMPRESSED_SIZE + "."); + if (size > MAX_COMPRESSED_SIZE) { + throw new DecoderException("Badly compressed packet: size of " + size + " is larger than protocol maximum of " + MAX_COMPRESSED_SIZE + "."); + } } byte[] bytes = new byte[buf.readableBytes()]; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index c752483c..0a9ddf1e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -177,12 +177,12 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp } @Override - public void setCompressionThreshold(int threshold) { + public void setCompressionThreshold(int threshold, boolean validateDecompression) { this.compressionThreshold = threshold; if (this.channel != null) { if (this.compressionThreshold >= 0) { if (this.channel.pipeline().get("compression") == null) { - this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this)); + this.channel.pipeline().addBefore("codec", "compression", new TcpPacketCompression(this, validateDecompression)); } } else if (this.channel.pipeline().get("compression") != null) { this.channel.pipeline().remove("compression"); From 6c9483e95176b139c371db52a7c76a46b14556ae Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 20 Dec 2021 20:40:50 -0500 Subject: [PATCH 159/180] Release 2.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0fb7ef86..f557f2f3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.1-SNAPSHOT + 2.1 jar PacketLib From 50b53e89027f969ae0d871a2856ab95b1ff652ad Mon Sep 17 00:00:00 2001 From: Oskar Date: Wed, 5 Jan 2022 05:43:57 +0100 Subject: [PATCH 160/180] Add switch case for KQueue in TcpServer#bindImpl (#42) --- .../java/com/github/steveice10/packetlib/tcp/TcpServer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java index 7cd0ee86..6b935f35 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServer.java @@ -15,6 +15,8 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.*; +import io.netty.channel.kqueue.KQueueEventLoopGroup; +import io.netty.channel.kqueue.KQueueServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.ServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -55,6 +57,10 @@ public class TcpServer extends AbstractServer { this.group = new EpollEventLoopGroup(); this.serverSocketChannel = EpollServerSocketChannel.class; break; + case KQUEUE: + this.group = new KQueueEventLoopGroup(); + this.serverSocketChannel = KQueueServerSocketChannel.class; + break; case NIO: this.group = new NioEventLoopGroup(); this.serverSocketChannel = NioServerSocketChannel.class; From a09d0fd00a9f03ac78b1dcbfb77aed8fab74dc52 Mon Sep 17 00:00:00 2001 From: Oskar Date: Wed, 5 Jan 2022 05:45:41 +0100 Subject: [PATCH 161/180] Sync the future on wait (#43) --- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index e9f27c7f..0e993517 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -129,9 +129,14 @@ public class TcpClientSession extends TcpSession { bootstrap.remoteAddress(remoteAddress); bootstrap.localAddress(bindAddress, bindPort); - bootstrap.connect().addListener((future) -> { - if (!future.isSuccess()) { - exceptionCaught(null, future.cause()); + ChannelFuture future = bootstrap.connect(); + if (wait) { + future.sync(); + } + + future.addListener((futureListener) -> { + if (!futureListener.isSuccess()) { + exceptionCaught(null, futureListener.cause()); } }); } catch(Throwable t) { From 4e4d8af6878030bbcfe910f6351bc690ebb05434 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 8 Jan 2022 22:12:55 -0500 Subject: [PATCH 162/180] Temp revert "Sync the future on wait (#43)" for snapshot This reverts commit a09d0fd00a9f03ac78b1dcbfb77aed8fab74dc52. --- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 0e993517..e9f27c7f 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -129,14 +129,9 @@ public class TcpClientSession extends TcpSession { bootstrap.remoteAddress(remoteAddress); bootstrap.localAddress(bindAddress, bindPort); - ChannelFuture future = bootstrap.connect(); - if (wait) { - future.sync(); - } - - future.addListener((futureListener) -> { - if (!futureListener.isSuccess()) { - exceptionCaught(null, futureListener.cause()); + bootstrap.connect().addListener((future) -> { + if (!future.isSuccess()) { + exceptionCaught(null, future.cause()); } }); } catch(Throwable t) { From cc069e6d981d742ba75fbdf81c91cefeaeeccfd8 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 8 Jan 2022 22:13:57 -0500 Subject: [PATCH 163/180] Bump to 2.2-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f557f2f3..948f46aa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 2.1 + 2.2-SNAPSHOT jar PacketLib From d908cccadfcf077d1c36ec954f35c53d8777b461 Mon Sep 17 00:00:00 2001 From: Oskar Date: Wed, 5 Jan 2022 05:45:41 +0100 Subject: [PATCH 164/180] Sync the future on wait (#43) --- .../steveice10/packetlib/tcp/TcpClientSession.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index e9f27c7f..0e993517 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -129,9 +129,14 @@ public class TcpClientSession extends TcpSession { bootstrap.remoteAddress(remoteAddress); bootstrap.localAddress(bindAddress, bindPort); - bootstrap.connect().addListener((future) -> { - if (!future.isSuccess()) { - exceptionCaught(null, future.cause()); + ChannelFuture future = bootstrap.connect(); + if (wait) { + future.sync(); + } + + future.addListener((futureListener) -> { + if (!futureListener.isSuccess()) { + exceptionCaught(null, futureListener.cause()); } }); } catch(Throwable t) { From 7ff2c930df3d06776098f72c0b64011485687ab5 Mon Sep 17 00:00:00 2001 From: Hugo Planque <12386279+HookWoods@users.noreply.github.com> Date: Tue, 1 Feb 2022 16:42:20 +0100 Subject: [PATCH 165/180] Fix Kqueue init (#44) --- .../com/github/steveice10/packetlib/tcp/TcpClientSession.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index 0e993517..ff23ec42 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -300,6 +300,7 @@ public class TcpClientSession extends TcpSession { EVENT_LOOP_GROUP = new KQueueEventLoopGroup(); CHANNEL_CLASS = KQueueSocketChannel.class; DATAGRAM_CHANNEL_CLASS = KQueueDatagramChannel.class; + break; case NIO: EVENT_LOOP_GROUP = new NioEventLoopGroup(); CHANNEL_CLASS = NioSocketChannel.class; From 3a51f530c63a242638eade3f4bd31de54c933deb Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 29 May 2022 12:40:39 -0500 Subject: [PATCH 166/180] PacketLib 3.0 Changes: - Removed NetInput/NetOutput and replaced them with ByteBuf - Added PacketSerializer to PacketDefinition - Added packet codecs which implementations can supply with custom readers/writers for buffers --- .../steveice10/packetlib/test/PingPacket.java | 11 +- .../packetlib/test/TestProtocol.java | 4 + pom.xml | 17 +- .../github/steveice10/packetlib/Session.java | 9 + .../codec/BasePacketCodecHelper.java | 162 +++++++++++ .../packetlib/codec/PacketCodecHelper.java | 20 ++ .../{packet => codec}/PacketDefinition.java | 27 +- .../packetlib/codec/PacketSerializer.java | 13 + .../steveice10/packetlib/io/NetInput.java | 260 ----------------- .../steveice10/packetlib/io/NetOutput.java | 190 ------------- .../io/buffer/ByteBufferNetInput.java | 261 ------------------ .../io/buffer/ByteBufferNetOutput.java | 153 ---------- .../packetlib/io/stream/StreamNetInput.java | 259 ----------------- .../packetlib/io/stream/StreamNetOutput.java | 162 ----------- .../packetlib/packet/BufferedPacket.java | 27 +- .../packetlib/packet/DefaultPacketHeader.java | 20 +- .../steveice10/packetlib/packet/Packet.java | 14 +- .../packetlib/packet/PacketFactory.java | 23 -- .../packetlib/packet/PacketHeader.java | 30 +- .../packetlib/packet/PacketProtocol.java | 114 +++++--- .../packetlib/tcp/TcpClientSession.java | 8 + .../packetlib/tcp/TcpPacketCodec.java | 27 +- .../packetlib/tcp/TcpPacketCompression.java | 17 +- .../packetlib/tcp/TcpPacketEncryptor.java | 1 - .../packetlib/tcp/TcpPacketSizer.java | 9 +- .../packetlib/tcp/TcpServerSession.java | 11 +- .../packetlib/tcp/io/ByteBufNetInput.java | 257 ----------------- .../packetlib/tcp/io/ByteBufNetOutput.java | 149 ---------- 28 files changed, 411 insertions(+), 1844 deletions(-) create mode 100644 src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java create mode 100644 src/main/java/com/github/steveice10/packetlib/codec/PacketCodecHelper.java rename src/main/java/com/github/steveice10/packetlib/{packet => codec}/PacketDefinition.java (50%) create mode 100644 src/main/java/com/github/steveice10/packetlib/codec/PacketSerializer.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/NetInput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/NetOutput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java delete mode 100644 src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java diff --git a/example/com/github/steveice10/packetlib/test/PingPacket.java b/example/com/github/steveice10/packetlib/test/PingPacket.java index bd9f6cc1..6c0d7e16 100644 --- a/example/com/github/steveice10/packetlib/test/PingPacket.java +++ b/example/com/github/steveice10/packetlib/test/PingPacket.java @@ -1,7 +1,6 @@ package com.github.steveice10.packetlib.test; -import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.packet.Packet; import java.io.IOException; @@ -9,8 +8,8 @@ import java.io.IOException; public class PingPacket implements Packet { private final String id; - public PingPacket(NetInput in) throws IOException { - this.id = in.readString(); + public PingPacket(ByteBuf buf, PacketCodecHelper codecHelper) throws IOException { + this.id = codecHelper.readString(buf); } public PingPacket(String id) { @@ -22,8 +21,8 @@ public class PingPacket implements Packet { } @Override - public void write(NetOutput out) throws IOException { - out.writeString(this.id); + public void write(ByteBuf buf, PacketCodecHelper codecHelper) throws IOException { + codecHelper.writeString(buf, this.id); } @Override diff --git a/example/com/github/steveice10/packetlib/test/TestProtocol.java b/example/com/github/steveice10/packetlib/test/TestProtocol.java index c182a27e..ff7e8cbb 100644 --- a/example/com/github/steveice10/packetlib/test/TestProtocol.java +++ b/example/com/github/steveice10/packetlib/test/TestProtocol.java @@ -23,6 +23,10 @@ public class TestProtocol extends PacketProtocol { this.setSecretKey(key); } + public PacketCodecHelper createHelper() { + return new BasePacketCodecHelper(); + } + public void setSecretKey(SecretKey key) { this.register(0, PingPacket.class, PingPacket::new); try { diff --git a/pom.xml b/pom.xml index 948f46aa..fb1e1655 100644 --- a/pom.xml +++ b/pom.xml @@ -5,17 +5,17 @@ com.github.steveice10 packetlib - 2.2-SNAPSHOT + 3.0-SNAPSHOT jar PacketLib A library for networking between a client and a server with packets. - http://github.com/Steveice10/PacketLib/ + http://github.com/GeyserMC/PacketLib/ - scm:git:git@github.com:Steveice10/PacketLib.git - scm:git:git@github.com:Steveice10/PacketLib.git - git@github.com:Steveice10/PacketLib/ + scm:git:git@github.com:GeyserMC/PacketLib.git + scm:git:git@github.com:GeyserMC/PacketLib.git + git@github.com:GeyserMC/PacketLib/ @@ -34,15 +34,14 @@ - steveice10 - Steveice10 - Steveice10@gmail.com + geysermc + GeyserMC GitHub - https://github.com/Steveice10/PacketLib/issues + https://github.com/GeyserMC/PacketLib/issues diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index 9cfda95e..1627c455 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -1,5 +1,6 @@ package com.github.steveice10.packetlib; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.crypt.PacketEncryption; import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; @@ -14,6 +15,7 @@ import java.util.Map; * A network session. */ public interface Session { + /** * Connects this session to its host and port. */ @@ -61,6 +63,13 @@ public interface Session { */ public PacketProtocol getPacketProtocol(); + /** + * Gets the session's {@link PacketCodecHelper}. + * + * @return The session's packet codec helper. + */ + PacketCodecHelper getCodecHelper(); + /** * Gets this session's set flags. If this session belongs to a server, the server's * flags will be included in the results. diff --git a/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java b/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java new file mode 100644 index 00000000..5ae506e2 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java @@ -0,0 +1,162 @@ +package com.github.steveice10.packetlib.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +import java.nio.charset.StandardCharsets; + +public class BasePacketCodecHelper implements PacketCodecHelper { + + @Override + public void writeVarInt(ByteBuf buf, int value) { + this.writeVarLong(buf, value & 0xFFFFFFFFL); + } + + @Override + public int readVarInt(ByteBuf buf) { + int value = 0; + int size = 0; + int b; + while (((b = buf.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if (size > 5) { + throw new IllegalArgumentException("VarInt too long (length must be <= 5)"); + } + } + + return value | ((b & 0x7F) << (size * 7)); + } + + // Based off of Andrew Steinborn's blog post: + // https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/ + @Override + public void writeVarLong(ByteBuf buf, long value) { + // Peel the one and two byte count cases explicitly as they are the most common VarInt sizes + // that the server will write, to improve inlining. + if ((value & ~0x7FL) == 0) { + buf.writeByte((byte) value); + } else if ((value & ~0x3FFFL) == 0) { + int w = (int) ((value & 0x7FL | 0x80L) << 8 | + (value >>> 7)); + buf.writeShort(w); + } else { + writeVarLongFull(buf, value); + } + } + + private static void writeVarLongFull(ByteBuf buf, long value) { + if ((value & ~0x7FL) == 0) { + buf.writeByte((byte) value); + } else if ((value & ~0x3FFFL) == 0) { + int w = (int) ((value & 0x7FL | 0x80L) << 8 | + (value >>> 7)); + buf.writeShort(w); + } else if ((value & ~0x1FFFFFL) == 0) { + int w = (int) ((value & 0x7FL | 0x80L) << 16 | + ((value >>> 7) & 0x7FL | 0x80L) << 8 | + (value >>> 14)); + buf.writeMedium(w); + } else if ((value & ~0xFFFFFFFL) == 0) { + int w = (int) ((value & 0x7F | 0x80) << 24 | + (((value >>> 7) & 0x7F | 0x80) << 16) | + ((value >>> 14) & 0x7F | 0x80) << 8 | + (value >>> 21)); + buf.writeInt(w); + } else if ((value & ~0x7FFFFFFFFL) == 0) { + int w = (int) ((value & 0x7F | 0x80) << 24 | + ((value >>> 7) & 0x7F | 0x80) << 16 | + ((value >>> 14) & 0x7F | 0x80) << 8 | + ((value >>> 21) & 0x7F | 0x80)); + buf.writeInt(w); + buf.writeByte((int) (value >>> 28)); + } else if ((value & ~0x3FFFFFFFFFFL) == 0) { + int w = (int) ((value & 0x7F | 0x80) << 24 | + ((value >>> 7) & 0x7F | 0x80) << 16 | + ((value >>> 14) & 0x7F | 0x80) << 8 | + ((value >>> 21) & 0x7F | 0x80)); + int w2 = (int) (((value >>> 28) & 0x7FL | 0x80L) << 8 | + (value >>> 35)); + buf.writeInt(w); + buf.writeShort(w2); + } else if ((value & ~0x1FFFFFFFFFFFFL) == 0) { + int w = (int) ((value & 0x7F | 0x80) << 24 | + ((value >>> 7) & 0x7F | 0x80) << 16 | + ((value >>> 14) & 0x7F | 0x80) << 8 | + ((value >>> 21) & 0x7F | 0x80)); + int w2 = (int) ((((value >>> 28) & 0x7FL | 0x80L) << 16 | + ((value >>> 35) & 0x7FL | 0x80L) << 8) | + (value >>> 42)); + buf.writeInt(w); + buf.writeMedium(w2); + } else if ((value & ~0xFFFFFFFFFFFFFFL) == 0) { + long w = (value & 0x7F | 0x80) << 56 | + ((value >>> 7) & 0x7F | 0x80) << 48 | + ((value >>> 14) & 0x7F | 0x80) << 40 | + ((value >>> 21) & 0x7F | 0x80) << 32 | + ((value >>> 28) & 0x7FL | 0x80L) << 24 | + ((value >>> 35) & 0x7FL | 0x80L) << 16 | + ((value >>> 42) & 0x7FL | 0x80L) << 8 | + (value >>> 49); + buf.writeLong(w); + } else if ((value & ~0x7FFFFFFFFFFFFFFFL) == 0) { + long w = (value & 0x7F | 0x80) << 56 | + ((value >>> 7) & 0x7F | 0x80) << 48 | + ((value >>> 14) & 0x7F | 0x80) << 40 | + ((value >>> 21) & 0x7F | 0x80) << 32 | + ((value >>> 28) & 0x7FL | 0x80L) << 24 | + ((value >>> 35) & 0x7FL | 0x80L) << 16 | + ((value >>> 42) & 0x7FL | 0x80L) << 8 | + (value >>> 49); + buf.writeLong(w); + buf.writeByte((byte) (value >>> 56)); + } else { + long w = (value & 0x7F | 0x80) << 56 | + ((value >>> 7) & 0x7F | 0x80) << 48 | + ((value >>> 14) & 0x7F | 0x80) << 40 | + ((value >>> 21) & 0x7F | 0x80) << 32 | + ((value >>> 28) & 0x7FL | 0x80L) << 24 | + ((value >>> 35) & 0x7FL | 0x80L) << 16 | + ((value >>> 42) & 0x7FL | 0x80L) << 8 | + (value >>> 49); + int w2 = (int) (((value >>> 56) & 0x7FL | 0x80L) << 8 | + (value >>> 63)); + buf.writeLong(w); + buf.writeShort(w2); + } + } + + @Override + public long readVarLong(ByteBuf buf) { + int value = 0; + int size = 0; + int b; + while (((b = buf.readByte()) & 0x80) == 0x80) { + value |= (b & 0x7F) << (size++ * 7); + if (size > 10) { + throw new IllegalArgumentException("VarLong too long (length must be <= 10)"); + } + } + + return value | ((b & 0x7FL) << (size * 7)); + } + + public String readString(ByteBuf buf) { + return this.readString(buf, Integer.MAX_VALUE); + } + + @Override + public String readString(ByteBuf buf, int maxLength) { + int length = this.readVarInt(buf); + if (length > maxLength) { + throw new IllegalArgumentException("String is longer than maximum allowed length"); + } + + return (String) buf.readCharSequence(length, StandardCharsets.UTF_8); + } + + @Override + public void writeString(ByteBuf buf, String value) { + this.writeVarInt(buf, ByteBufUtil.utf8Bytes(value)); + buf.writeCharSequence(value, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/codec/PacketCodecHelper.java b/src/main/java/com/github/steveice10/packetlib/codec/PacketCodecHelper.java new file mode 100644 index 00000000..2fdc67c0 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/codec/PacketCodecHelper.java @@ -0,0 +1,20 @@ +package com.github.steveice10.packetlib.codec; + +import io.netty.buffer.ByteBuf; + +public interface PacketCodecHelper { + + void writeVarInt(ByteBuf buf, int value); + + int readVarInt(ByteBuf buf); + + void writeVarLong(ByteBuf buf, long value); + + long readVarLong(ByteBuf buf); + + String readString(ByteBuf buf); + + String readString(ByteBuf buf, int maxLength); + + void writeString(ByteBuf buf, String value); +} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java b/src/main/java/com/github/steveice10/packetlib/codec/PacketDefinition.java similarity index 50% rename from src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java rename to src/main/java/com/github/steveice10/packetlib/codec/PacketDefinition.java index b483be85..fccc0b48 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketDefinition.java +++ b/src/main/java/com/github/steveice10/packetlib/codec/PacketDefinition.java @@ -1,4 +1,9 @@ -package com.github.steveice10.packetlib.packet; +package com.github.steveice10.packetlib.codec; + +import com.github.steveice10.packetlib.packet.Packet; +import io.netty.buffer.ByteBuf; + +import java.io.IOException; /** * Represents a definition of a packet with various @@ -7,15 +12,15 @@ package com.github.steveice10.packetlib.packet; * * @param the packet type */ -public class PacketDefinition { +public class PacketDefinition { private final int id; private final Class packetClass; - private final PacketFactory factory; + private final PacketSerializer serializer; - public PacketDefinition(final int id, final Class packetClass, final PacketFactory factory) { + public PacketDefinition(final int id, final Class packetClass, final PacketSerializer serializer) { this.id = id; this.packetClass = packetClass; - this.factory = factory; + this.serializer = serializer; } /** @@ -37,11 +42,15 @@ public class PacketDefinition { } /** - * Returns the {@link PacketFactory} of the packet. + * Returns the {@link PacketSerializer} of the packet. * - * @return the packet factory of the packet + * @return the packet serializer of the packet */ - public PacketFactory getFactory() { - return this.factory; + public PacketSerializer getSerializer() { + return this.serializer; + } + + public T newInstance(ByteBuf buf, H helper) throws IOException { + return this.serializer.deserialize(buf, helper, this); } } diff --git a/src/main/java/com/github/steveice10/packetlib/codec/PacketSerializer.java b/src/main/java/com/github/steveice10/packetlib/codec/PacketSerializer.java new file mode 100644 index 00000000..5d70e73d --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/codec/PacketSerializer.java @@ -0,0 +1,13 @@ +package com.github.steveice10.packetlib.codec; + +import com.github.steveice10.packetlib.packet.Packet; +import io.netty.buffer.ByteBuf; + +import java.io.IOException; + +public interface PacketSerializer { + + void serialize(ByteBuf buf, H helper, T packet) throws IOException; + + T deserialize(ByteBuf buf, H helper, PacketDefinition definition) throws IOException; +} diff --git a/src/main/java/com/github/steveice10/packetlib/io/NetInput.java b/src/main/java/com/github/steveice10/packetlib/io/NetInput.java deleted file mode 100644 index dcfa44f1..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/NetInput.java +++ /dev/null @@ -1,260 +0,0 @@ -package com.github.steveice10.packetlib.io; - -import java.io.IOException; -import java.util.UUID; - -/** - * An interface for reading network data. - */ -public interface NetInput { - /** - * Reads the next boolean. - * - * @return The next boolean. - * @throws java.io.IOException If an I/O error occurs. - */ - boolean readBoolean() throws IOException; - - /** - * Reads the next byte. - * - * @return The next byte. - * @throws java.io.IOException If an I/O error occurs. - */ - byte readByte() throws IOException; - - /** - * Reads the next unsigned byte. - * - * @return The next unsigned byte. - * @throws java.io.IOException If an I/O error occurs. - */ - int readUnsignedByte() throws IOException; - - /** - * Reads the next short. - * - * @return The next short. - * @throws java.io.IOException If an I/O error occurs. - */ - public short readShort() throws IOException; - - /** - * Reads the next unsigned short. - * - * @return The next unsigned short. - * @throws java.io.IOException If an I/O error occurs. - */ - int readUnsignedShort() throws IOException; - - /** - * Reads the next char. - * - * @return The next char. - * @throws java.io.IOException If an I/O error occurs. - */ - char readChar() throws IOException; - - /** - * Reads the next integer. - * - * @return The next integer. - * @throws java.io.IOException If an I/O error occurs. - */ - int readInt() throws IOException; - - /** - * Reads the next varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. - * - * @return The next varint. - * @throws java.io.IOException If an I/O error occurs. - */ - int readVarInt() throws IOException; - - /** - * Reads the next long. - * - * @return The next long. - * @throws java.io.IOException If an I/O error occurs. - */ - long readLong() throws IOException; - - /** - * Reads the next varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. - * - * @return The next varlong. - * @throws java.io.IOException If an I/O error occurs. - */ - long readVarLong() throws IOException; - - /** - * Reads the next float. - * - * @return The next float. - * @throws java.io.IOException If an I/O error occurs. - */ - float readFloat() throws IOException; - - /** - * Reads the next double. - * - * @return The next double. - * @throws java.io.IOException If an I/O error occurs. - */ - double readDouble() throws IOException; - - /** - * Reads the next byte array. - * - * @param length The length of the byte array. - * @return The next byte array. - * @throws java.io.IOException If an I/O error occurs. - */ - byte[] readBytes(int length) throws IOException; - - /** - * Reads as much data as possible into the given byte array. - * - * @param b Byte array to read to. - * @return The amount of bytes read, or -1 if no bytes could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readBytes(byte b[]) throws IOException; - - /** - * Reads the given amount of bytes into the given array at the given offset. - * - * @param b Byte array to read to. - * @param offset Offset of the array to read to. - * @param length Length of bytes to read. - * @return The amount of bytes read, or -1 if no bytes could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readBytes(byte b[], int offset, int length) throws IOException; - - /** - * Reads the next short array. - * - * @param length The length of the short array. - * @return The next short array. - * @throws java.io.IOException If an I/O error occurs. - */ - short[] readShorts(int length) throws IOException; - - /** - * Reads as much data as possible into the given short array. - * - * @param s Short array to read to. - * @return The amount of shorts read, or -1 if no shorts could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readShorts(short s[]) throws IOException; - - /** - * Reads the given amount of shorts into the given array at the given offset. - * - * @param s Short array to read to. - * @param offset Offset of the array to read to. - * @param length Length of bytes to read. - * @return The amount of shorts read, or -1 if no shorts could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readShorts(short s[], int offset, int length) throws IOException; - - /** - * Reads the next int array. - * - * @param length The length of the int array. - * @return The next int array. - * @throws java.io.IOException If an I/O error occurs. - */ - int[] readInts(int length) throws IOException; - - /** - * Reads as much data as possible into the given int array. - * - * @param i Int array to read to. - * @return The amount of ints read, or -1 if no ints could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readInts(int i[]) throws IOException; - - /** - * Reads the given amount of ints into the given array at the given offset. - * - * @param i Int array to read to. - * @param offset Offset of the array to read to. - * @param length Length of bytes to read. - * @return The amount of ints read, or -1 if no ints could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readInts(int i[], int offset, int length) throws IOException; - - /** - * Reads the next long array. - * - * @param length The length of the long array. - * @return The next long array. - * @throws java.io.IOException If an I/O error occurs. - */ - long[] readLongs(int length) throws IOException; - - /** - * Reads as much data as possible into the given long array. - * - * @param l Long array to read to. - * @return The amount of longs read, or -1 if no longs could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readLongs(long l[]) throws IOException; - - /** - * Reads the given amount of longs into the given array at the given offset. - * - * @param l Long array to read to. - * @param offset Offset of the array to read to. - * @param length Length of bytes to read. - * @return The amount of longs read, or -1 if no longs could be read. - * @throws java.io.IOException If an I/O error occurs. - */ - int readLongs(long l[], int offset, int length) throws IOException; - - /** - * Reads the next string. - * - * @return The next string. - * @throws java.io.IOException If an I/O error occurs. - */ - String readString() throws IOException; - - /** - * Reads the next UUID. - * - * @return The next UUID. - * @throws java.io.IOException If an I/O error occurs. - */ - UUID readUUID() throws IOException; - - /** - * Reads the next enum. - * - * @param values the collection of enums to read from - * @return the next enum. - * @throws IOException If an I/O error occurs. - */ - default > T readEnum(T[] values) throws IOException { - int index = readVarInt(); - if (index >= values.length) { - throw new IndexOutOfBoundsException("Enum class " + values.getClass() + " does not have a value with index " + index); - } - return values[index]; - } - - /** - * Gets the number of available bytes. - * - * @return The number of available bytes. - * @throws java.io.IOException If an I/O error occurs. - */ - int available() throws IOException; -} diff --git a/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java deleted file mode 100644 index dcc3299c..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/NetOutput.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.github.steveice10.packetlib.io; - -import java.io.IOException; -import java.util.UUID; - -/** - * An interface for writing network data. - */ -public interface NetOutput { - /** - * Writes a boolean. - * - * @param b Boolean to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeBoolean(boolean b) throws IOException; - - /** - * Writes a byte. - * - * @param b Byte to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeByte(int b) throws IOException; - - /** - * Writes a short. - * - * @param s Short to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeShort(int s) throws IOException; - - /** - * Writes a char. - * - * @param c Char to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeChar(int c) throws IOException; - - /** - * Writes a integer. - * - * @param i Integer to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeInt(int i) throws IOException; - - /** - * Writes a varint. A varint is a form of integer where only necessary bytes are written. This is done to save bandwidth. - * - * @param i Varint to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeVarInt(int i) throws IOException; - - /** - * Writes a long. - * - * @param l Long to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeLong(long l) throws IOException; - - /** - * Writes a varlong. A varlong is a form of long where only necessary bytes are written. This is done to save bandwidth. - * - * @param l Varlong to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeVarLong(long l) throws IOException; - - /** - * Writes a float. - * - * @param f Float to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeFloat(float f) throws IOException; - - /** - * Writes a double. - * - * @param d Double to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeDouble(double d) throws IOException; - - /** - * Writes a byte array. - * - * @param b Byte array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeBytes(byte b[]) throws IOException; - - /** - * Writes a byte array, using the given amount of bytes. - * - * @param b Byte array to write. - * @param length Bytes to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeBytes(byte b[], int length) throws IOException; - - /** - * Writes a short array. - * - * @param s Short array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeShorts(short s[]) throws IOException; - - /** - * Writes a short array, using the given amount of bytes. - * - * @param s Short array to write. - * @param length Shorts to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeShorts(short s[], int length) throws IOException; - - /** - * Writes an int array. - * - * @param i Int array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeInts(int i[]) throws IOException; - - /** - * Writes an int array, using the given amount of bytes. - * - * @param i Int array to write. - * @param length Ints to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeInts(int i[], int length) throws IOException; - - /** - * Writes a long array. - * - * @param l Long array to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeLongs(long l[]) throws IOException; - - /** - * Writes a long array, using the given amount of bytes. - * - * @param l Long array to write. - * @param length Longs to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeLongs(long l[], int length) throws IOException; - - /** - * Writes a string. - * - * @param s String to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeString(String s) throws IOException; - - /** - * Writes a UUID. - * - * @param uuid UUID to write. - * @throws java.io.IOException If an I/O error occurs. - */ - void writeUUID(UUID uuid) throws IOException; - - /** - * Writes an enum. - * - * @param e Enum to write. - * @throws IOException - */ - default void writeEnum(Enum e) throws IOException { - writeVarInt(e.ordinal()); - } - - /** - * Flushes the output. - * - * @throws java.io.IOException If an I/O error occurs. - */ - void flush() throws IOException; -} diff --git a/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java deleted file mode 100644 index 15b4bbb6..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetInput.java +++ /dev/null @@ -1,261 +0,0 @@ -package com.github.steveice10.packetlib.io.buffer; - -import com.github.steveice10.packetlib.io.NetInput; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.UUID; - -/** - * A NetInput implementation using a ByteBuffer as a backend. - */ -public class ByteBufferNetInput implements NetInput { - private ByteBuffer buffer; - - public ByteBufferNetInput(ByteBuffer buffer) { - this.buffer = buffer; - } - - public ByteBuffer getByteBuffer() { - return this.buffer; - } - - @Override - public boolean readBoolean() throws IOException { - return this.buffer.get() == 1; - } - - @Override - public byte readByte() throws IOException { - return this.buffer.get(); - } - - @Override - public int readUnsignedByte() throws IOException { - return this.buffer.get() & 0xFF; - } - - @Override - public short readShort() throws IOException { - return this.buffer.getShort(); - } - - @Override - public int readUnsignedShort() throws IOException { - return this.buffer.getShort() & 0xFFFF; - } - - @Override - public char readChar() throws IOException { - return this.buffer.getChar(); - } - - @Override - public int readInt() throws IOException { - return this.buffer.getInt(); - } - - @Override - public int readVarInt() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 5) { - throw new IOException("VarInt too long (length must be <= 5)"); - } - } - - return value | ((b & 0x7F) << (size * 7)); - } - - @Override - public long readLong() throws IOException { - return this.buffer.getLong(); - } - - @Override - public long readVarLong() throws IOException { - long value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (long) (b & 0x7F) << (size++ * 7); - if(size > 10) { - throw new IOException("VarLong too long (length must be <= 10)"); - } - } - - return value | ((long) (b & 0x7F) << (size * 7)); - } - - @Override - public float readFloat() throws IOException { - return this.buffer.getFloat(); - } - - @Override - public double readDouble() throws IOException { - return this.buffer.getDouble(); - } - - @Override - public byte[] readBytes(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - byte b[] = new byte[length]; - this.buffer.get(b); - return b; - } - - @Override - public int readBytes(byte[] b) throws IOException { - return this.readBytes(b, 0, b.length); - } - - @Override - public int readBytes(byte[] b, int offset, int length) throws IOException { - int readable = this.buffer.remaining(); - if(readable <= 0) { - return -1; - } - - if(readable < length) { - length = readable; - } - - this.buffer.get(b, offset, length); - return length; - } - - @Override - public short[] readShorts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - short s[] = new short[length]; - for(int index = 0; index < length; index++) { - s[index] = this.readShort(); - } - - return s; - } - - @Override - public int readShorts(short[] s) throws IOException { - return this.readShorts(s, 0, s.length); - } - - @Override - public int readShorts(short[] s, int offset, int length) throws IOException { - int readable = this.buffer.remaining(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 2) { - length = readable / 2; - } - - for(int index = offset; index < offset + length; index++) { - s[index] = this.readShort(); - } - - return length; - } - - @Override - public int[] readInts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - int i[] = new int[length]; - for(int index = 0; index < length; index++) { - i[index] = this.readInt(); - } - - return i; - } - - @Override - public int readInts(int[] i) throws IOException { - return this.readInts(i, 0, i.length); - } - - @Override - public int readInts(int[] i, int offset, int length) throws IOException { - int readable = this.buffer.remaining(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 4) { - length = readable / 4; - } - - for(int index = offset; index < offset + length; index++) { - i[index] = this.readInt(); - } - - return length; - } - - @Override - public long[] readLongs(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - long l[] = new long[length]; - for(int index = 0; index < length; index++) { - l[index] = this.readLong(); - } - - return l; - } - - @Override - public int readLongs(long[] l) throws IOException { - return this.readLongs(l, 0, l.length); - } - - @Override - public int readLongs(long[] l, int offset, int length) throws IOException { - int readable = this.buffer.remaining(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 2) { - length = readable / 2; - } - - for(int index = offset; index < offset + length; index++) { - l[index] = this.readLong(); - } - - return length; - } - - @Override - public String readString() throws IOException { - int length = this.readVarInt(); - byte bytes[] = this.readBytes(length); - return new String(bytes, "UTF-8"); - } - - @Override - public UUID readUUID() throws IOException { - return new UUID(this.readLong(), this.readLong()); - } - - @Override - public int available() throws IOException { - return this.buffer.remaining(); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java deleted file mode 100644 index a9e9e6ff..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/buffer/ByteBufferNetOutput.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.github.steveice10.packetlib.io.buffer; - -import com.github.steveice10.packetlib.io.NetOutput; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.UUID; - -/** - * A NetOutput implementation using a ByteBuf as a backend. - */ -public class ByteBufferNetOutput implements NetOutput { - private ByteBuffer buffer; - - public ByteBufferNetOutput(ByteBuffer buffer) { - this.buffer = buffer; - } - - public ByteBuffer getByteBuffer() { - return this.buffer; - } - - @Override - public void writeBoolean(boolean b) throws IOException { - this.buffer.put(b ? (byte) 1 : 0); - } - - @Override - public void writeByte(int b) throws IOException { - this.buffer.put((byte) b); - } - - @Override - public void writeShort(int s) throws IOException { - this.buffer.putShort((short) s); - } - - @Override - public void writeChar(int c) throws IOException { - this.buffer.putChar((char) c); - } - - @Override - public void writeInt(int i) throws IOException { - this.buffer.putInt(i); - } - - @Override - public void writeVarInt(int i) throws IOException { - while((i & ~0x7F) != 0) { - this.writeByte((i & 0x7F) | 0x80); - i >>>= 7; - } - - this.writeByte(i); - } - - @Override - public void writeLong(long l) throws IOException { - this.buffer.putLong(l); - } - - @Override - public void writeVarLong(long l) throws IOException { - while((l & ~0x7F) != 0) { - this.writeByte((int) (l & 0x7F) | 0x80); - l >>>= 7; - } - - this.writeByte((int) l); - } - - @Override - public void writeFloat(float f) throws IOException { - this.buffer.putFloat(f); - } - - @Override - public void writeDouble(double d) throws IOException { - this.buffer.putDouble(d); - } - - @Override - public void writeBytes(byte b[]) throws IOException { - this.buffer.put(b); - } - - @Override - public void writeBytes(byte b[], int length) throws IOException { - this.buffer.put(b, 0, length); - } - - @Override - public void writeShorts(short[] s) throws IOException { - this.writeShorts(s, s.length); - } - - @Override - public void writeShorts(short[] s, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeShort(s[index]); - } - } - - @Override - public void writeInts(int[] i) throws IOException { - this.writeInts(i, i.length); - } - - @Override - public void writeInts(int[] i, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeInt(i[index]); - } - } - - @Override - public void writeLongs(long[] l) throws IOException { - this.writeLongs(l, l.length); - } - - @Override - public void writeLongs(long[] l, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeLong(l[index]); - } - } - - @Override - public void writeString(String s) throws IOException { - if(s == null) { - throw new IllegalArgumentException("String cannot be null!"); - } - - byte[] bytes = s.getBytes("UTF-8"); - if(bytes.length > 32767) { - throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); - } else { - this.writeVarInt(bytes.length); - this.writeBytes(bytes); - } - } - - @Override - public void writeUUID(UUID uuid) throws IOException { - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - } - - @Override - public void flush() throws IOException { - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java deleted file mode 100644 index d96bf9f7..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetInput.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.github.steveice10.packetlib.io.stream; - -import com.github.steveice10.packetlib.io.NetInput; - -import java.io.EOFException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -/** - * A NetInput implementation using an InputStream as a backend. - */ -public class StreamNetInput extends FilterInputStream implements NetInput { - /** - * Creates a new StreamNetInput instance. - * - * @param in InputStream to read from. - */ - public StreamNetInput(InputStream in) { - super(in); - } - - @Override - public boolean readBoolean() throws IOException { - return this.readByte() == 1; - } - - @Override - public byte readByte() throws IOException { - return (byte) this.readUnsignedByte(); - } - - @Override - public int readUnsignedByte() throws IOException { - int b = this.read(); - if(b < 0) { - throw new EOFException(); - } - - return b; - } - - @Override - public short readShort() throws IOException { - return (short) this.readUnsignedShort(); - } - - @Override - public int readUnsignedShort() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - return (ch1 << 8) + (ch2 << 0); - } - - @Override - public char readChar() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - return (char) ((ch1 << 8) + (ch2 << 0)); - } - - @Override - public int readInt() throws IOException { - int ch1 = this.readUnsignedByte(); - int ch2 = this.readUnsignedByte(); - int ch3 = this.readUnsignedByte(); - int ch4 = this.readUnsignedByte(); - return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0); - } - - @Override - public int readVarInt() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 5) { - throw new IOException("VarInt too long (length must be <= 5)"); - } - } - - return value | ((b & 0x7F) << (size * 7)); - } - - @Override - public long readLong() throws IOException { - byte read[] = this.readBytes(8); - return ((long) read[0] << 56) + ((long) (read[1] & 255) << 48) + ((long) (read[2] & 255) << 40) + ((long) (read[3] & 255) << 32) + ((long) (read[4] & 255) << 24) + ((read[5] & 255) << 16) + ((read[6] & 255) << 8) + ((read[7] & 255) << 0); - } - - @Override - public long readVarLong() throws IOException { - long value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (long) (b & 0x7F) << (size++ * 7); - if(size > 10) { - throw new IOException("VarLong too long (length must be <= 10)"); - } - } - - return value | ((long) (b & 0x7F) << (size * 7)); - } - - @Override - public float readFloat() throws IOException { - return Float.intBitsToFloat(this.readInt()); - } - - @Override - public double readDouble() throws IOException { - return Double.longBitsToDouble(this.readLong()); - } - - @Override - public byte[] readBytes(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - byte b[] = new byte[length]; - int n = 0; - while(n < length) { - int count = this.read(b, n, length - n); - if(count < 0) { - throw new EOFException(); - } - - n += count; - } - - return b; - } - - @Override - public int readBytes(byte[] b) throws IOException { - return this.read(b); - } - - @Override - public int readBytes(byte[] b, int offset, int length) throws IOException { - return this.read(b, offset, length); - } - - @Override - public short[] readShorts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - short s[] = new short[length]; - int read = this.readShorts(s); - if(read < length) { - throw new EOFException(); - } - - return s; - } - - @Override - public int readShorts(short[] s) throws IOException { - return this.readShorts(s, 0, s.length); - } - - @Override - public int readShorts(short[] s, int offset, int length) throws IOException { - for(int index = offset; index < offset + length; index++) { - try { - s[index] = this.readShort(); - } catch(EOFException e) { - return index - offset; - } - } - - return length; - } - - @Override - public int[] readInts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - int i[] = new int[length]; - int read = this.readInts(i); - if(read < length) { - throw new EOFException(); - } - - return i; - } - - @Override - public int readInts(int[] i) throws IOException { - return this.readInts(i, 0, i.length); - } - - @Override - public int readInts(int[] i, int offset, int length) throws IOException { - for(int index = offset; index < offset + length; index++) { - try { - i[index] = this.readInt(); - } catch(EOFException e) { - return index - offset; - } - } - - return length; - } - - @Override - public long[] readLongs(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - long l[] = new long[length]; - int read = this.readLongs(l); - if(read < length) { - throw new EOFException(); - } - - return l; - } - - @Override - public int readLongs(long[] l) throws IOException { - return this.readLongs(l, 0, l.length); - } - - @Override - public int readLongs(long[] l, int offset, int length) throws IOException { - for(int index = offset; index < offset + length; index++) { - try { - l[index] = this.readLong(); - } catch(EOFException e) { - return index - offset; - } - } - - return length; - } - - @Override - public String readString() throws IOException { - int length = this.readVarInt(); - byte bytes[] = this.readBytes(length); - return new String(bytes, StandardCharsets.UTF_8); - } - - @Override - public UUID readUUID() throws IOException { - return new UUID(this.readLong(), this.readLong()); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java b/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java deleted file mode 100644 index 78562929..00000000 --- a/src/main/java/com/github/steveice10/packetlib/io/stream/StreamNetOutput.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.github.steveice10.packetlib.io.stream; - -import com.github.steveice10.packetlib.io.NetOutput; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -/** - * A NetOutput implementation using an OutputStream as a backend. - */ -public class StreamNetOutput extends FilterOutputStream implements NetOutput { - /** - * Creates a new StreamNetOutput instance. - * - * @param out OutputStream to write to. - */ - public StreamNetOutput(OutputStream out) { - super(out); - } - - @Override - public void writeBoolean(boolean b) throws IOException { - this.writeByte(b ? 1 : 0); - } - - @Override - public void writeByte(int b) throws IOException { - this.write(b); - } - - @Override - public void writeShort(int s) throws IOException { - this.writeByte((byte) ((s >>> 8) & 0xFF)); - this.writeByte((byte) ((s >>> 0) & 0xFF)); - } - - @Override - public void writeChar(int c) throws IOException { - this.writeByte((byte) ((c >>> 8) & 0xFF)); - this.writeByte((byte) ((c >>> 0) & 0xFF)); - } - - @Override - public void writeInt(int i) throws IOException { - this.writeByte((byte) ((i >>> 24) & 0xFF)); - this.writeByte((byte) ((i >>> 16) & 0xFF)); - this.writeByte((byte) ((i >>> 8) & 0xFF)); - this.writeByte((byte) ((i >>> 0) & 0xFF)); - } - - @Override - public void writeVarInt(int i) throws IOException { - while((i & ~0x7F) != 0) { - this.writeByte((i & 0x7F) | 0x80); - i >>>= 7; - } - - this.writeByte(i); - } - - @Override - public void writeLong(long l) throws IOException { - this.writeByte((byte) (l >>> 56)); - this.writeByte((byte) (l >>> 48)); - this.writeByte((byte) (l >>> 40)); - this.writeByte((byte) (l >>> 32)); - this.writeByte((byte) (l >>> 24)); - this.writeByte((byte) (l >>> 16)); - this.writeByte((byte) (l >>> 8)); - this.writeByte((byte) (l >>> 0)); - } - - @Override - public void writeVarLong(long l) throws IOException { - while((l & ~0x7F) != 0) { - this.writeByte((int) (l & 0x7F) | 0x80); - l >>>= 7; - } - - this.writeByte((int) l); - } - - @Override - public void writeFloat(float f) throws IOException { - this.writeInt(Float.floatToIntBits(f)); - } - - @Override - public void writeDouble(double d) throws IOException { - this.writeLong(Double.doubleToLongBits(d)); - } - - @Override - public void writeBytes(byte b[]) throws IOException { - this.writeBytes(b, b.length); - } - - @Override - public void writeBytes(byte b[], int length) throws IOException { - this.write(b, 0, length); - } - - @Override - public void writeShorts(short[] s) throws IOException { - this.writeShorts(s, s.length); - } - - @Override - public void writeShorts(short[] s, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeShort(s[index]); - } - } - - @Override - public void writeInts(int[] i) throws IOException { - this.writeInts(i, i.length); - } - - @Override - public void writeInts(int[] i, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeInt(i[index]); - } - } - - @Override - public void writeLongs(long[] l) throws IOException { - this.writeLongs(l, l.length); - } - - @Override - public void writeLongs(long[] l, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeLong(l[index]); - } - } - - @Override - public void writeString(String s) throws IOException { - if(s == null) { - throw new IllegalArgumentException("String cannot be null!"); - } - - byte[] bytes = s.getBytes(StandardCharsets.UTF_8); - if(bytes.length > 32767) { - throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); - } else { - this.writeVarInt(bytes.length); - this.writeBytes(bytes); - } - } - - @Override - public void writeUUID(UUID uuid) throws IOException { - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java index 2da5d875..9aea7ee3 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/BufferedPacket.java @@ -1,10 +1,11 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; +import com.github.steveice10.packetlib.codec.PacketDefinition; +import com.github.steveice10.packetlib.codec.PacketSerializer; +import io.netty.buffer.ByteBuf; -import java.io.IOException; - -public class BufferedPacket implements Packet { +public class BufferedPacket implements Packet, PacketSerializer { private final Class packetClass; private final byte[] buf; @@ -17,13 +18,21 @@ public class BufferedPacket implements Packet { return packetClass; } - @Override - public void write(NetOutput out) throws IOException { - out.writeBytes(buf); - } - @Override public boolean isPriority() { return true; } + + @Override + public void serialize(ByteBuf buf, PacketCodecHelper helper, BufferedPacket packet) { + buf.writeBytes(this.buf); + } + + @Override + public BufferedPacket deserialize(ByteBuf buf, PacketCodecHelper helper, PacketDefinition definition) { + byte[] array = new byte[buf.readableBytes()]; + buf.readBytes(array); + + return new BufferedPacket(definition.getPacketClass(), array); + } } diff --git a/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java b/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java index e20dc812..f7218680 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/DefaultPacketHeader.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; +import io.netty.buffer.ByteBuf; import java.io.IOException; @@ -35,22 +35,22 @@ public class DefaultPacketHeader implements PacketHeader { } @Override - public int readLength(NetInput in, int available) throws IOException { - return in.readVarInt(); + public int readLength(ByteBuf buf, PacketCodecHelper codecHelper, int available) throws IOException { + return codecHelper.readVarInt(buf); } @Override - public void writeLength(NetOutput out, int length) throws IOException { - out.writeVarInt(length); + public void writeLength(ByteBuf buf, PacketCodecHelper codecHelper, int length) throws IOException { + codecHelper.writeVarInt(buf, length); } @Override - public int readPacketId(NetInput in) throws IOException { - return in.readVarInt(); + public int readPacketId(ByteBuf buf, PacketCodecHelper codecHelper) throws IOException { + return codecHelper.readVarInt(buf); } @Override - public void writePacketId(NetOutput out, int packetId) throws IOException { - out.writeVarInt(packetId); + public void writePacketId(ByteBuf buf, PacketCodecHelper codecHelper, int packetId) throws IOException { + codecHelper.writeVarInt(buf, packetId); } } diff --git a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java index 8a2815a0..0850f291 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/Packet.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/Packet.java @@ -1,21 +1,11 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; - -import java.io.IOException; +import io.netty.buffer.ByteBuf; /** - * A network packet. Any given packet must have a constructor that takes in a {@link NetInput}. + * A network packet. Any given packet must have a constructor that takes in a {@link ByteBuf}. */ public interface Packet { - /** - * Writes the packet to the given output buffer. - * - * @param out The output destination to write to. - * @throws IOException If an I/O error occurs. - */ - void write(NetOutput out) throws IOException; /** * Gets whether the packet has handling priority. diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java deleted file mode 100644 index ec55ceb3..00000000 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketFactory.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.steveice10.packetlib.packet; - -import com.github.steveice10.packetlib.io.NetInput; - -import java.io.IOException; - -/** - * Factory for constructing {@link Packet}s. - * - * @param the packet type - */ -@FunctionalInterface -public interface PacketFactory { - - /** - * Constructs a new {@link Packet} from the - * given {@link NetInput}. - * - * @param input the input - * @return a new packet from the input - */ - T construct(NetInput input) throws IOException; -} diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java index 6129a7ab..c2f51144 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketHeader.java @@ -1,7 +1,7 @@ package com.github.steveice10.packetlib.packet; -import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; +import io.netty.buffer.ByteBuf; import java.io.IOException; @@ -34,37 +34,41 @@ public interface PacketHeader { /** * Reads the length of a packet from the given input. * - * @param in Input to read from. - * @param available Number of packet bytes available after the length. + * @param buf Buffer to read from. + * @param codecHelper The codec helper. + * @param available Number of packet bytes available after the length. * @return The resulting packet length. * @throws java.io.IOException If an I/O error occurs. */ - public int readLength(NetInput in, int available) throws IOException; + public int readLength(ByteBuf buf, PacketCodecHelper codecHelper, int available) throws IOException; /** * Writes the length of a packet to the given output. * - * @param out Output to write to. - * @param length Length to write. + * @param buf Buffer to write to. + * @param codecHelper The codec helper. + * @param length Length to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writeLength(NetOutput out, int length) throws IOException; + public void writeLength(ByteBuf buf, PacketCodecHelper codecHelper, int length) throws IOException; /** * Reads the ID of a packet from the given input. * - * @param in Input to read from. + * @param buf Buffer to read from. + * @param codecHelper The codec helper. * @return The resulting packet ID, or -1 if the packet should not be read yet. * @throws java.io.IOException If an I/O error occurs. */ - public int readPacketId(NetInput in) throws IOException; + public int readPacketId(ByteBuf buf, PacketCodecHelper codecHelper) throws IOException; /** * Writes the ID of a packet to the given output. * - * @param out Output to write to. - * @param packetId Packet ID to write. + * @param buf Buffer to write to. + * @param codecHelper The codec helper. + * @param packetId Packet ID to write. * @throws java.io.IOException If an I/O error occurs. */ - public void writePacketId(NetOutput out, int packetId) throws IOException; + public void writePacketId(ByteBuf buf, PacketCodecHelper codecHelper, int packetId) throws IOException; } diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index edf74226..8727eda8 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -2,8 +2,10 @@ package com.github.steveice10.packetlib.packet; import com.github.steveice10.packetlib.Server; import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.crypt.PacketEncryption; -import com.github.steveice10.packetlib.io.NetInput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; +import com.github.steveice10.packetlib.codec.PacketDefinition; +import com.github.steveice10.packetlib.codec.PacketSerializer; +import io.netty.buffer.ByteBuf; import java.io.IOException; import java.util.HashMap; @@ -12,11 +14,11 @@ import java.util.Map; /** * A protocol for packet sending and receiving. - * All implementations must have a constructor that takes in a {@link NetInput}. + * All implementations must have a constructor that takes in a {@link ByteBuf}. */ public abstract class PacketProtocol { - private final Map> serverbound = new HashMap<>(); - private final Map> clientbound = new HashMap<>(); + private final Map> serverbound = new HashMap<>(); + private final Map> clientbound = new HashMap<>(); private final Map, Integer> clientboundIds = new IdentityHashMap<>(); private final Map, Integer> serverboundIds = new IdentityHashMap<>(); @@ -35,6 +37,14 @@ public abstract class PacketProtocol { */ public abstract PacketHeader getPacketHeader(); + /** + * Creates a new {@link PacketCodecHelper} that can be used + * for each session. + * + * @return A new {@link PacketCodecHelper}. + */ + public abstract PacketCodecHelper createHelper(); + /** * Called when a client session is created with this protocol. * @@ -63,14 +73,14 @@ public abstract class PacketProtocol { /** * Registers a packet to this protocol as both serverbound and clientbound. * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @param factory The packet factory. + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param serializer The packet serializer. * @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound. */ - public final void register(int id, Class packet, PacketFactory factory) { - this.registerServerbound(id, packet, factory); - this.registerClientbound(id, packet, factory); + public final void register(int id, Class packet, PacketSerializer serializer) { + this.registerServerbound(id, packet, serializer); + this.registerClientbound(id, packet, serializer); } /** @@ -79,7 +89,7 @@ public abstract class PacketProtocol { * @param definition The packet definition. * @throws IllegalArgumentException If the packet fails a test creation when being registered as serverbound. */ - public final void register(PacketDefinition definition) { + public final void register(PacketDefinition definition) { this.registerServerbound(definition); this.registerClientbound(definition); } @@ -87,13 +97,13 @@ public abstract class PacketProtocol { /** * Registers a serverbound packet to this protocol. * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @param factory The packet factory. + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param serializer The packet serializer. * @throws IllegalArgumentException If the packet fails a test creation. */ - public final void registerServerbound(int id, Class packet, PacketFactory factory) { - this.registerServerbound(new PacketDefinition<>(id, packet, factory)); + public final void registerServerbound(int id, Class packet, PacketSerializer serializer) { + this.registerServerbound(new PacketDefinition<>(id, packet, serializer)); } /** @@ -101,7 +111,7 @@ public abstract class PacketProtocol { * * @param definition The packet definition. */ - public final void registerServerbound(PacketDefinition definition) { + public final void registerServerbound(PacketDefinition definition) { this.serverbound.put(definition.getId(), definition); this.serverboundIds.put(definition.getPacketClass(), definition.getId()); } @@ -109,12 +119,12 @@ public abstract class PacketProtocol { /** * Registers a clientbound packet to this protocol. * - * @param id Id to register the packet to. - * @param packet Packet to register. - * @param factory The packet factory. + * @param id Id to register the packet to. + * @param packet Packet to register. + * @param serializer The packet serializer. */ - public final void registerClientbound(int id, Class packet, PacketFactory factory) { - this.registerClientbound(new PacketDefinition<>(id, packet, factory)); + public final void registerClientbound(int id, Class packet, PacketSerializer serializer) { + this.registerClientbound(new PacketDefinition<>(id, packet, serializer)); } /** @@ -122,7 +132,7 @@ public abstract class PacketProtocol { * * @param definition The packet definition. */ - public final void registerClientbound(PacketDefinition definition) { + public final void registerClientbound(PacketDefinition definition) { this.clientbound.put(definition.getId(), definition); this.clientboundIds.put(definition.getPacketClass(), definition.getId()); } @@ -130,18 +140,21 @@ public abstract class PacketProtocol { /** * Creates a new instance of a clientbound packet with the given id and read the clientbound input. * - * @param id Id of the packet to create. + * @param id Id of the packet to create. + * @param buf The buffer to read the packet from. + * @param codecHelper The codec helper. * @return The created packet. * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. */ - public Packet createClientboundPacket(int id, NetInput in) throws IOException { - PacketDefinition definition = this.clientbound.get(id); + @SuppressWarnings("unchecked") + public Packet createClientboundPacket(int id, ByteBuf buf, H codecHelper) throws IOException { + PacketDefinition definition = (PacketDefinition) this.clientbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - return definition.getFactory().construct(in); + return definition.newInstance(buf, codecHelper); } /** @@ -182,7 +195,7 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet ID is not registered. */ public Class getClientboundClass(int id) { - PacketDefinition definition = this.clientbound.get(id); + PacketDefinition definition = this.clientbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } @@ -193,18 +206,21 @@ public abstract class PacketProtocol { /** * Creates a new instance of a serverbound packet with the given id and read the serverbound input. * - * @param id Id of the packet to create. + * @param id Id of the packet to create. + * @param buf The buffer to read the packet from. + * @param codecHelper The codec helper. * @return The created packet. * @throws IOException if there was an IO error whilst reading the packet. * @throws IllegalArgumentException If the packet ID is not registered. */ - public Packet createServerboundPacket(int id, NetInput in) throws IOException { - PacketDefinition definition = this.serverbound.get(id); + @SuppressWarnings("unchecked") + public Packet createServerboundPacket(int id, ByteBuf buf, H codecHelper) throws IOException { + PacketDefinition definition = (PacketDefinition) this.serverbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } - return definition.getFactory().construct(in); + return definition.newInstance(buf, codecHelper); } /** @@ -245,11 +261,41 @@ public abstract class PacketProtocol { * @throws IllegalArgumentException If the packet ID is not registered. */ public Class getServerboundClass(int id) { - PacketDefinition definition = this.serverbound.get(id); + PacketDefinition definition = this.serverbound.get(id); if (definition == null) { throw new IllegalArgumentException("Invalid packet id: " + id); } return definition.getPacketClass(); } + + /** + * Gets the serverbound packet definition for the given packet id. + * + * @param id The packet id. + * @return The registered packet's class + */ + public PacketDefinition getServerboundDefinition(int id) { + PacketDefinition definition = this.serverbound.get(id); + if (definition == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + return definition; + } + + /** + * Gets the clientbound packet definition for the given packet id. + * + * @param id The packet id. + * @return The registered packet's class + */ + public PacketDefinition getClientboundDefinition(int id) { + PacketDefinition definition = this.clientbound.get(id); + if (definition == null) { + throw new IllegalArgumentException("Invalid packet id: " + id); + } + + return definition; + } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index ff23ec42..fee4aa93 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -2,6 +2,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.ProxyInfo; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.helper.TransportHelper; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.bootstrap.Bootstrap; @@ -55,6 +56,7 @@ public class TcpClientSession extends TcpSession { private final String bindAddress; private final int bindPort; private final ProxyInfo proxy; + private final PacketCodecHelper codecHelper; public TcpClientSession(String host, int port, PacketProtocol protocol) { this(host, port, protocol, null); @@ -73,6 +75,7 @@ public class TcpClientSession extends TcpSession { this.bindAddress = bindAddress; this.bindPort = bindPort; this.proxy = proxy; + this.codecHelper = protocol.createHelper(); } @Override @@ -144,6 +147,11 @@ public class TcpClientSession extends TcpSession { } } + @Override + public PacketCodecHelper getCodecHelper() { + return this.codecHelper; + } + private InetSocketAddress resolveAddress() { boolean debug = getFlag(BuiltinFlags.PRINT_DEBUG, false); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 963bd062..151988a5 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -1,12 +1,11 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; +import com.github.steveice10.packetlib.codec.PacketDefinition; import com.github.steveice10.packetlib.event.session.PacketErrorEvent; -import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; +import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; @@ -15,22 +14,28 @@ import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { private final Session session; + private final PacketProtocol packetProtocol; + private final PacketCodecHelper codecHelper; private final boolean client; public TcpPacketCodec(Session session, boolean client) { this.session = session; + this.packetProtocol = session.getPacketProtocol(); + this.codecHelper = session.getCodecHelper(); this.client = client; } + @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { int initial = buf.writerIndex(); try { - NetOutput out = new ByteBufNetOutput(buf); - - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.client ? this.session.getPacketProtocol().getServerboundId(packet) : this.session.getPacketProtocol().getClientboundId(packet)); - packet.write(out); + int packetId = this.client ? this.packetProtocol.getServerboundId(packet) : this.packetProtocol.getClientboundId(packet); + PacketDefinition definition = this.client ? this.packetProtocol.getServerboundDefinition(packetId) : this.packetProtocol.getClientboundDefinition(packetId); + + this.packetProtocol.getPacketHeader().writePacketId(buf, this.codecHelper, packetId); + definition.getSerializer().serialize(buf, this.codecHelper, packet); } catch (Throwable t) { // Reset writer index to make sure incomplete data is not written out. buf.writerIndex(initial); @@ -48,15 +53,13 @@ public class TcpPacketCodec extends ByteToMessageCodec { int initial = buf.readerIndex(); try { - NetInput in = new ByteBufNetInput(buf); - - int id = this.session.getPacketProtocol().getPacketHeader().readPacketId(in); + int id = this.packetProtocol.getPacketHeader().readPacketId(buf, this.codecHelper); if (id == -1) { buf.readerIndex(initial); return; } - Packet packet = this.client ? this.session.getPacketProtocol().createClientboundPacket(id, in) : this.session.getPacketProtocol().createServerboundPacket(id, in); + Packet packet = this.client ? this.packetProtocol.createClientboundPacket(id, buf, this.codecHelper) : this.packetProtocol.createServerboundPacket(id, buf, this.codecHelper); if (buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index 8d2a10aa..fa7c9cb9 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -1,8 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -17,6 +16,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { private static final int MAX_COMPRESSED_SIZE = 2097152; private final Session session; + private final PacketCodecHelper codecHelper; private final Deflater deflater = new Deflater(); private final Inflater inflater = new Inflater(); private final byte[] buf = new byte[8192]; @@ -24,6 +24,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { public TcpPacketCompression(Session session, boolean validateDecompression) { this.session = session; + this.codecHelper = session.getCodecHelper(); this.validateDecompression = validateDecompression; } @@ -38,19 +39,18 @@ public class TcpPacketCompression extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int readable = in.readableBytes(); - ByteBufNetOutput output = new ByteBufNetOutput(out); if(readable < this.session.getCompressionThreshold()) { - output.writeVarInt(0); + this.codecHelper.writeVarInt(out, 0); out.writeBytes(in); } else { byte[] bytes = new byte[readable]; in.readBytes(bytes); - output.writeVarInt(bytes.length); + this.codecHelper.writeVarInt(out, bytes.length); this.deflater.setInput(bytes, 0, readable); this.deflater.finish(); while(!this.deflater.finished()) { int length = this.deflater.deflate(this.buf); - output.writeBytes(this.buf, length); + out.writeBytes(this.buf, 0, length); } this.deflater.reset(); @@ -60,8 +60,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { if(buf.readableBytes() != 0) { - ByteBufNetInput in = new ByteBufNetInput(buf); - int size = in.readVarInt(); + int size = this.codecHelper.readVarInt(buf); if(size == 0) { out.add(buf.readBytes(buf.readableBytes())); } else { @@ -76,7 +75,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { } byte[] bytes = new byte[buf.readableBytes()]; - in.readBytes(bytes); + buf.readBytes(bytes); this.inflater.setInput(bytes); byte[] inflated = new byte[size]; this.inflater.inflate(inflated); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java index 0220f40d..8f5e7d59 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketEncryptor.java @@ -1,6 +1,5 @@ package com.github.steveice10.packetlib.tcp; -import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.crypt.PacketEncryption; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index da6eb8bc..509eef9b 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -1,8 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -13,10 +12,12 @@ import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { private final Session session; + private final PacketCodecHelper codecHelper; private final int size; public TcpPacketSizer(Session session, int size) { this.session = session; + this.codecHelper = session.getCodecHelper(); this.size = size; } @@ -24,7 +25,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int length = in.readableBytes(); out.ensureWritable(this.session.getPacketProtocol().getPacketHeader().getLengthSize(length) + length); - this.session.getPacketProtocol().getPacketHeader().writeLength(new ByteBufNetOutput(out), length); + this.session.getPacketProtocol().getPacketHeader().writeLength(out, this.codecHelper, length); out.writeBytes(in); } @@ -40,7 +41,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { lengthBytes[index] = buf.readByte(); if ((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { - int length = this.session.getPacketProtocol().getPacketHeader().readLength(new ByteBufNetInput(Unpooled.wrappedBuffer(lengthBytes)), buf.readableBytes()); + int length = this.session.getPacketProtocol().getPacketHeader().readLength(Unpooled.wrappedBuffer(lengthBytes), this.codecHelper, buf.readableBytes()); if (buf.readableBytes() < length) { buf.resetReaderIndex(); return; diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java index 8591fb92..26c88a53 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpServerSession.java @@ -1,6 +1,6 @@ package com.github.steveice10.packetlib.tcp; -import com.github.steveice10.packetlib.Server; +import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.packet.PacketProtocol; import io.netty.channel.ChannelHandlerContext; @@ -8,11 +8,18 @@ import java.util.HashMap; import java.util.Map; public class TcpServerSession extends TcpSession { - private TcpServer server; + private final TcpServer server; + private final PacketCodecHelper codecHelper; public TcpServerSession(String host, int port, PacketProtocol protocol, TcpServer server) { super(host, port, protocol); this.server = server; + this.codecHelper = protocol.createHelper(); + } + + @Override + public PacketCodecHelper getCodecHelper() { + return this.codecHelper; } @Override diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java deleted file mode 100644 index 75708f71..00000000 --- a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetInput.java +++ /dev/null @@ -1,257 +0,0 @@ -package com.github.steveice10.packetlib.tcp.io; - -import com.github.steveice10.packetlib.io.NetInput; -import io.netty.buffer.ByteBuf; - -import java.io.IOException; -import java.util.UUID; - -/** - * A NetInput implementation using a ByteBuf as a backend. - */ -public class ByteBufNetInput implements NetInput { - private ByteBuf buf; - - public ByteBufNetInput(ByteBuf buf) { - this.buf = buf; - } - - @Override - public boolean readBoolean() throws IOException { - return this.buf.readBoolean(); - } - - @Override - public byte readByte() throws IOException { - return this.buf.readByte(); - } - - @Override - public int readUnsignedByte() throws IOException { - return this.buf.readUnsignedByte(); - } - - @Override - public short readShort() throws IOException { - return this.buf.readShort(); - } - - @Override - public int readUnsignedShort() throws IOException { - return this.buf.readUnsignedShort(); - } - - @Override - public char readChar() throws IOException { - return this.buf.readChar(); - } - - @Override - public int readInt() throws IOException { - return this.buf.readInt(); - } - - @Override - public int readVarInt() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 5) { - throw new IOException("VarInt too long (length must be <= 5)"); - } - } - - return value | ((b & 0x7F) << (size * 7)); - } - - @Override - public long readLong() throws IOException { - return this.buf.readLong(); - } - - @Override - public long readVarLong() throws IOException { - int value = 0; - int size = 0; - int b; - while(((b = this.readByte()) & 0x80) == 0x80) { - value |= (b & 0x7F) << (size++ * 7); - if(size > 10) { - throw new IOException("VarLong too long (length must be <= 10)"); - } - } - - return value | ((b & 0x7F) << (size * 7)); - } - - @Override - public float readFloat() throws IOException { - return this.buf.readFloat(); - } - - @Override - public double readDouble() throws IOException { - return this.buf.readDouble(); - } - - @Override - public byte[] readBytes(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - byte b[] = new byte[length]; - this.buf.readBytes(b); - return b; - } - - @Override - public int readBytes(byte[] b) throws IOException { - return this.readBytes(b, 0, b.length); - } - - @Override - public int readBytes(byte[] b, int offset, int length) throws IOException { - int readable = this.buf.readableBytes(); - if(readable <= 0) { - return -1; - } - - if(readable < length) { - length = readable; - } - - this.buf.readBytes(b, offset, length); - return length; - } - - @Override - public short[] readShorts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - short s[] = new short[length]; - for(int index = 0; index < length; index++) { - s[index] = this.readShort(); - } - - return s; - } - - @Override - public int readShorts(short[] s) throws IOException { - return this.readShorts(s, 0, s.length); - } - - @Override - public int readShorts(short[] s, int offset, int length) throws IOException { - int readable = this.buf.readableBytes(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 2) { - length = readable / 2; - } - - for(int index = offset; index < offset + length; index++) { - s[index] = this.readShort(); - } - - return length; - } - - @Override - public int[] readInts(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - int i[] = new int[length]; - for(int index = 0; index < length; index++) { - i[index] = this.readInt(); - } - - return i; - } - - @Override - public int readInts(int[] i) throws IOException { - return this.readInts(i, 0, i.length); - } - - @Override - public int readInts(int[] i, int offset, int length) throws IOException { - int readable = this.buf.readableBytes(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 4) { - length = readable / 4; - } - - for(int index = offset; index < offset + length; index++) { - i[index] = this.readInt(); - } - - return length; - } - - @Override - public long[] readLongs(int length) throws IOException { - if(length < 0) { - throw new IllegalArgumentException("Array cannot have length less than 0."); - } - - long l[] = new long[length]; - for(int index = 0; index < length; index++) { - l[index] = this.readLong(); - } - - return l; - } - - @Override - public int readLongs(long[] l) throws IOException { - return this.readLongs(l, 0, l.length); - } - - @Override - public int readLongs(long[] l, int offset, int length) throws IOException { - int readable = this.buf.readableBytes(); - if(readable <= 0) { - return -1; - } - - if(readable < length * 2) { - length = readable / 2; - } - - for(int index = offset; index < offset + length; index++) { - l[index] = this.readLong(); - } - - return length; - } - - @Override - public String readString() throws IOException { - int length = this.readVarInt(); - byte bytes[] = this.readBytes(length); - return new String(bytes, "UTF-8"); - } - - @Override - public UUID readUUID() throws IOException { - return new UUID(this.readLong(), this.readLong()); - } - - @Override - public int available() throws IOException { - return this.buf.readableBytes(); - } -} diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java b/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java deleted file mode 100644 index bd60d186..00000000 --- a/src/main/java/com/github/steveice10/packetlib/tcp/io/ByteBufNetOutput.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.github.steveice10.packetlib.tcp.io; - -import com.github.steveice10.packetlib.io.NetOutput; -import io.netty.buffer.ByteBuf; - -import java.io.IOException; -import java.util.UUID; - -/** - * A NetOutput implementation using a ByteBuf as a backend. - */ -public class ByteBufNetOutput implements NetOutput { - private ByteBuf buf; - - public ByteBufNetOutput(ByteBuf buf) { - this.buf = buf; - } - - @Override - public void writeBoolean(boolean b) throws IOException { - this.buf.writeBoolean(b); - } - - @Override - public void writeByte(int b) throws IOException { - this.buf.writeByte(b); - } - - @Override - public void writeShort(int s) throws IOException { - this.buf.writeShort(s); - } - - @Override - public void writeChar(int c) throws IOException { - this.buf.writeChar(c); - } - - @Override - public void writeInt(int i) throws IOException { - this.buf.writeInt(i); - } - - @Override - public void writeVarInt(int i) throws IOException { - while((i & ~0x7F) != 0) { - this.writeByte((i & 0x7F) | 0x80); - i >>>= 7; - } - - this.writeByte(i); - } - - @Override - public void writeLong(long l) throws IOException { - this.buf.writeLong(l); - } - - @Override - public void writeVarLong(long l) throws IOException { - while((l & ~0x7F) != 0) { - this.writeByte((int) (l & 0x7F) | 0x80); - l >>>= 7; - } - - this.writeByte((int) l); - } - - @Override - public void writeFloat(float f) throws IOException { - this.buf.writeFloat(f); - } - - @Override - public void writeDouble(double d) throws IOException { - this.buf.writeDouble(d); - } - - @Override - public void writeBytes(byte b[]) throws IOException { - this.buf.writeBytes(b); - } - - @Override - public void writeBytes(byte b[], int length) throws IOException { - this.buf.writeBytes(b, 0, length); - } - - @Override - public void writeShorts(short[] s) throws IOException { - this.writeShorts(s, s.length); - } - - @Override - public void writeShorts(short[] s, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeShort(s[index]); - } - } - - @Override - public void writeInts(int[] i) throws IOException { - this.writeInts(i, i.length); - } - - @Override - public void writeInts(int[] i, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeInt(i[index]); - } - } - - @Override - public void writeLongs(long[] l) throws IOException { - this.writeLongs(l, l.length); - } - - @Override - public void writeLongs(long[] l, int length) throws IOException { - for(int index = 0; index < length; index++) { - this.writeLong(l[index]); - } - } - - @Override - public void writeString(String s) throws IOException { - if(s == null) { - throw new IllegalArgumentException("String cannot be null!"); - } - - byte[] bytes = s.getBytes("UTF-8"); - if(bytes.length > 32767) { - throw new IOException("String too big (was " + s.length() + " bytes encoded, max " + 32767 + ")"); - } else { - this.writeVarInt(bytes.length); - this.writeBytes(bytes); - } - } - - @Override - public void writeUUID(UUID uuid) throws IOException { - this.writeLong(uuid.getMostSignificantBits()); - this.writeLong(uuid.getLeastSignificantBits()); - } - - @Override - public void flush() throws IOException { - } -} From 8b4a2aaac83f8ee2ddd9c9ce99a8a66a95ec96d1 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 29 May 2022 19:51:36 -0500 Subject: [PATCH 167/180] Don't rely on this data always being the same here --- .../packetlib/tcp/TcpPacketCodec.java | 20 +++++++++---------- .../packetlib/tcp/TcpPacketCompression.java | 8 +++----- .../packetlib/tcp/TcpPacketSizer.java | 6 ++---- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index 151988a5..4384e94f 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -14,14 +14,10 @@ import java.util.List; public class TcpPacketCodec extends ByteToMessageCodec { private final Session session; - private final PacketProtocol packetProtocol; - private final PacketCodecHelper codecHelper; private final boolean client; public TcpPacketCodec(Session session, boolean client) { this.session = session; - this.packetProtocol = session.getPacketProtocol(); - this.codecHelper = session.getCodecHelper(); this.client = client; } @@ -30,12 +26,14 @@ public class TcpPacketCodec extends ByteToMessageCodec { public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { int initial = buf.writerIndex(); + PacketProtocol packetProtocol = this.session.getPacketProtocol(); + PacketCodecHelper codecHelper = this.session.getCodecHelper(); try { - int packetId = this.client ? this.packetProtocol.getServerboundId(packet) : this.packetProtocol.getClientboundId(packet); - PacketDefinition definition = this.client ? this.packetProtocol.getServerboundDefinition(packetId) : this.packetProtocol.getClientboundDefinition(packetId); + int packetId = this.client ? packetProtocol.getServerboundId(packet) : packetProtocol.getClientboundId(packet); + PacketDefinition definition = this.client ? packetProtocol.getServerboundDefinition(packetId) : packetProtocol.getClientboundDefinition(packetId); - this.packetProtocol.getPacketHeader().writePacketId(buf, this.codecHelper, packetId); - definition.getSerializer().serialize(buf, this.codecHelper, packet); + packetProtocol.getPacketHeader().writePacketId(buf, codecHelper, packetId); + definition.getSerializer().serialize(buf, codecHelper, packet); } catch (Throwable t) { // Reset writer index to make sure incomplete data is not written out. buf.writerIndex(initial); @@ -52,14 +50,16 @@ public class TcpPacketCodec extends ByteToMessageCodec { protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { int initial = buf.readerIndex(); + PacketProtocol packetProtocol = this.session.getPacketProtocol(); + PacketCodecHelper codecHelper = this.session.getCodecHelper(); try { - int id = this.packetProtocol.getPacketHeader().readPacketId(buf, this.codecHelper); + int id = packetProtocol.getPacketHeader().readPacketId(buf, codecHelper); if (id == -1) { buf.readerIndex(initial); return; } - Packet packet = this.client ? this.packetProtocol.createClientboundPacket(id, buf, this.codecHelper) : this.packetProtocol.createServerboundPacket(id, buf, this.codecHelper); + Packet packet = this.client ? packetProtocol.createClientboundPacket(id, buf, codecHelper) : packetProtocol.createServerboundPacket(id, buf, codecHelper); if (buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read."); diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java index fa7c9cb9..4d2c2bf4 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCompression.java @@ -16,7 +16,6 @@ public class TcpPacketCompression extends ByteToMessageCodec { private static final int MAX_COMPRESSED_SIZE = 2097152; private final Session session; - private final PacketCodecHelper codecHelper; private final Deflater deflater = new Deflater(); private final Inflater inflater = new Inflater(); private final byte[] buf = new byte[8192]; @@ -24,7 +23,6 @@ public class TcpPacketCompression extends ByteToMessageCodec { public TcpPacketCompression(Session session, boolean validateDecompression) { this.session = session; - this.codecHelper = session.getCodecHelper(); this.validateDecompression = validateDecompression; } @@ -40,12 +38,12 @@ public class TcpPacketCompression extends ByteToMessageCodec { public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int readable = in.readableBytes(); if(readable < this.session.getCompressionThreshold()) { - this.codecHelper.writeVarInt(out, 0); + this.session.getCodecHelper().writeVarInt(out, 0); out.writeBytes(in); } else { byte[] bytes = new byte[readable]; in.readBytes(bytes); - this.codecHelper.writeVarInt(out, bytes.length); + this.session.getCodecHelper().writeVarInt(out, bytes.length); this.deflater.setInput(bytes, 0, readable); this.deflater.finish(); while(!this.deflater.finished()) { @@ -60,7 +58,7 @@ public class TcpPacketCompression extends ByteToMessageCodec { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List out) throws Exception { if(buf.readableBytes() != 0) { - int size = this.codecHelper.readVarInt(buf); + int size = this.session.getCodecHelper().readVarInt(buf); if(size == 0) { out.add(buf.readBytes(buf.readableBytes())); } else { diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java index 509eef9b..a114d9df 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketSizer.java @@ -12,12 +12,10 @@ import java.util.List; public class TcpPacketSizer extends ByteToMessageCodec { private final Session session; - private final PacketCodecHelper codecHelper; private final int size; public TcpPacketSizer(Session session, int size) { this.session = session; - this.codecHelper = session.getCodecHelper(); this.size = size; } @@ -25,7 +23,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { int length = in.readableBytes(); out.ensureWritable(this.session.getPacketProtocol().getPacketHeader().getLengthSize(length) + length); - this.session.getPacketProtocol().getPacketHeader().writeLength(out, this.codecHelper, length); + this.session.getPacketProtocol().getPacketHeader().writeLength(out, this.session.getCodecHelper(), length); out.writeBytes(in); } @@ -41,7 +39,7 @@ public class TcpPacketSizer extends ByteToMessageCodec { lengthBytes[index] = buf.readByte(); if ((this.session.getPacketProtocol().getPacketHeader().isLengthVariable() && lengthBytes[index] >= 0) || index == size - 1) { - int length = this.session.getPacketProtocol().getPacketHeader().readLength(Unpooled.wrappedBuffer(lengthBytes), this.codecHelper, buf.readableBytes()); + int length = this.session.getPacketProtocol().getPacketHeader().readLength(Unpooled.wrappedBuffer(lengthBytes), this.session.getCodecHelper(), buf.readableBytes()); if (buf.readableBytes() < length) { buf.resetReaderIndex(); return; From dfb471df99a9e361979d3c8be8ea753715902f8f Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sat, 4 Jun 2022 10:05:39 -0400 Subject: [PATCH 168/180] Use Fastutil --- pom.xml | 17 ++++++++++++----- .../packetlib/packet/PacketProtocol.java | 6 ++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index fb1e1655..41436a3f 100644 --- a/pom.xml +++ b/pom.xml @@ -87,11 +87,18 @@ 0.0.8.Final linux-x86_64 - - com.github.spotbugs - spotbugs-annotations - 4.3.0 - + + com.github.spotbugs + spotbugs-annotations + 4.3.0 + provided + + + com.nukkitx.fastutil + fastutil-int-object-maps + 8.5.2 + compile + diff --git a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java index 8727eda8..131f0d0e 100644 --- a/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java +++ b/src/main/java/com/github/steveice10/packetlib/packet/PacketProtocol.java @@ -6,6 +6,8 @@ import com.github.steveice10.packetlib.codec.PacketCodecHelper; import com.github.steveice10.packetlib.codec.PacketDefinition; import com.github.steveice10.packetlib.codec.PacketSerializer; import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.io.IOException; import java.util.HashMap; @@ -17,8 +19,8 @@ import java.util.Map; * All implementations must have a constructor that takes in a {@link ByteBuf}. */ public abstract class PacketProtocol { - private final Map> serverbound = new HashMap<>(); - private final Map> clientbound = new HashMap<>(); + private final Int2ObjectMap> serverbound = new Int2ObjectOpenHashMap<>(); + private final Int2ObjectMap> clientbound = new Int2ObjectOpenHashMap<>(); private final Map, Integer> clientboundIds = new IdentityHashMap<>(); private final Map, Integer> serverboundIds = new IdentityHashMap<>(); From 57342e7e407bb40dfd976ec48adf01e972ba4a6d Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 5 Jun 2022 12:21:45 -0500 Subject: [PATCH 169/180] PacketLib 3.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 41436a3f..a071c583 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 3.0-SNAPSHOT + 3.0 jar PacketLib From 4fbb472fccccf08e4f0e2c75972f5410fea0757f Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sun, 18 Dec 2022 14:55:43 +0100 Subject: [PATCH 170/180] Bump to 3.0.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a071c583..04dbd428 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 3.0 + 3.0.1-SNAPSHOT jar PacketLib From d9b9b1fbf9303ddcf76f7597295844485af95078 Mon Sep 17 00:00:00 2001 From: Kevin Ludwig <32491319+valaphee@users.noreply.github.com> Date: Sun, 18 Dec 2022 14:59:03 +0100 Subject: [PATCH 171/180] Merge pull request #46 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Set string max length to Short.MAX_VALUE (32767), Fix multibyte strin… --- .../packetlib/codec/BasePacketCodecHelper.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java b/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java index 5ae506e2..544e098c 100644 --- a/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java +++ b/src/main/java/com/github/steveice10/packetlib/codec/BasePacketCodecHelper.java @@ -141,17 +141,21 @@ public class BasePacketCodecHelper implements PacketCodecHelper { } public String readString(ByteBuf buf) { - return this.readString(buf, Integer.MAX_VALUE); + return this.readString(buf, Short.MAX_VALUE); } @Override public String readString(ByteBuf buf, int maxLength) { int length = this.readVarInt(buf); - if (length > maxLength) { + if (length > maxLength * 3) { + throw new IllegalArgumentException("String buffer is longer than maximum allowed length"); + } + String string = (String) buf.readCharSequence(length, StandardCharsets.UTF_8); + if (string.length() > maxLength) { throw new IllegalArgumentException("String is longer than maximum allowed length"); } - return (String) buf.readCharSequence(length, StandardCharsets.UTF_8); + return string; } @Override From e21e6c4e86bd9755afaa2dda9fd0f2a52eae7f7e Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sun, 18 Dec 2022 15:01:06 +0100 Subject: [PATCH 172/180] Release 3.0.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 04dbd428..773beda9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 packetlib - 3.0.1-SNAPSHOT + 3.0.1 jar PacketLib From d52d258becc115d9c3c70ec05c25d4134d67d9cf Mon Sep 17 00:00:00 2001 From: D3ATHBRINGER13 <53559772+D3ATHBRINGER13@users.noreply.github.com> Date: Sat, 25 Feb 2023 16:07:16 +0000 Subject: [PATCH 173/180] Update to 1.19.4-pre1. The new netty pipeline is still to be implemented. --- pom.xml | 2 +- .../mc/protocol/ServerListener.java | 8 +- .../mc/protocol/codec/MinecraftCodec.java | 280 +++++++++--------- .../protocol/codec/MinecraftCodecHelper.java | 58 +++- .../mc/protocol/data/MagicValues.java | 1 - .../data/game/chunk/ChunkBiomeData.java | 12 + .../game/entity/metadata/MetadataType.java | 14 +- .../game/entity/metadata/SnifferState.java | 17 ++ .../data/game/entity/player/Animation.java | 1 - .../game/level/particle/ParticleType.java | 3 + .../data/game/level/sound/BuiltinSound.java | 68 ++++- .../mc/protocol/data/status/PlayerInfo.java | 4 +- .../ClientboundDelimiterPacket.java | 14 + .../ClientboundServerDataPacket.java | 31 +- .../entity/ClientboundDamageEventPacket.java | 40 +++ .../ClientboundHurtAnimationPacket.java | 27 ++ .../ClientboundPlayerPositionPacket.java | 7 +- .../level/ClientboundChunksBiomesPacket.java | 33 +++ .../ClientboundSectionBlocksUpdatePacket.java | 2 +- .../ClientboundStatusResponsePacket.java | 21 +- .../mc/protocol/MinecraftProtocolTest.java | 4 +- .../ClientboundSetEntityDataPacketTest.java | 9 +- .../ClientboundStatusResponsePacketTest.java | 8 +- src/test/resources/networkCodec.nbt | Bin 2657 -> 3625 bytes 24 files changed, 465 insertions(+), 199 deletions(-) create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/ChunkBiomeData.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/SnifferState.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDelimiterPacket.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundHurtAnimationPacket.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java diff --git a/pom.xml b/pom.xml index 2e855a10..08e35251 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.steveice10 mcprotocollib - 1.19.3-SNAPSHOT + 1.19.4-SNAPSHOT jar MCProtocolLib diff --git a/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java b/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java index 3f27b22f..9adaab0b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java +++ b/src/main/java/com/github/steveice10/mc/protocol/ServerListener.java @@ -30,7 +30,11 @@ import com.github.steveice10.packetlib.packet.Packet; import net.kyori.adventure.text.Component; import javax.crypto.SecretKey; -import java.security.*; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.util.ArrayList; import java.util.Arrays; import java.util.Random; import java.util.UUID; @@ -125,7 +129,7 @@ public class ServerListener extends SessionAdapter { if (builder == null) { builder = $ -> new ServerStatusInfo( new VersionInfo(protocol.getCodec().getMinecraftVersion(), protocol.getCodec().getProtocolVersion()), - new PlayerInfo(0, 20, new GameProfile[0]), + new PlayerInfo(0, 20, new ArrayList<>()), Component.text("A Minecraft Server"), null, false diff --git a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java index 9e7ab48f..00d2d279 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java +++ b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java @@ -13,6 +13,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCo import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomChatCompletionsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDeleteChatPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDisconnectPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDisguisedChatPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundKeepAlivePacket; @@ -36,7 +37,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUp import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateRecipesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateTagsPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundAnimatePacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundDamageEventPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundHurtAnimationPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosRotPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityRotPacket; @@ -79,6 +82,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEntityDataPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundBlockUpdatePacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundChunksBiomesPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundForgetLevelChunkPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundGameEventPacket; @@ -195,9 +199,9 @@ public class MinecraftCodec { } public static final PacketCodec CODEC = PacketCodec.builder() - .protocolVersion(761) + .protocolVersion((1 << 30) | 120) .helper(() -> new MinecraftCodecHelper(LEVEL_EVENTS, SOUND_NAMES)) - .minecraftVersion("1.19.3") + .minecraftVersion("1.19.4 Pre-release 1") .state(ProtocolState.HANDSHAKE, PacketStateCodec.builder() .registerServerboundPacket(0x00, ClientIntentionPacket.class, ClientIntentionPacket::new) ) @@ -216,146 +220,150 @@ public class MinecraftCodec { .registerServerboundPacket(0x00, ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new) .registerServerboundPacket(0x01, ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new) ).state(ProtocolState.GAME, PacketStateCodec.builder() - .registerClientboundPacket(0x00, ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new) - .registerClientboundPacket(0x01, ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new) - .registerClientboundPacket(0x02, ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new) - .registerClientboundPacket(0x03, ClientboundAnimatePacket.class, ClientboundAnimatePacket::new) - .registerClientboundPacket(0x04, ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new) - .registerClientboundPacket(0x05, ClientboundBlockChangedAckPacket.class, ClientboundBlockChangedAckPacket::new) - .registerClientboundPacket(0x06, ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new) - .registerClientboundPacket(0x07, ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new) - .registerClientboundPacket(0x08, ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new) - .registerClientboundPacket(0x09, ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new) - .registerClientboundPacket(0x0A, ClientboundBossEventPacket.class, ClientboundBossEventPacket::new) - .registerClientboundPacket(0x0B, ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new) - .registerClientboundPacket(0x0C, ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new) - .registerClientboundPacket(0x0D, ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new) - .registerClientboundPacket(0x0E, ClientboundCommandsPacket.class, ClientboundCommandsPacket::new) - .registerClientboundPacket(0x0F, ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new) - .registerClientboundPacket(0x10, ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new) - .registerClientboundPacket(0x11, ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new) - .registerClientboundPacket(0x12, ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new) - .registerClientboundPacket(0x13, ClientboundCooldownPacket.class, ClientboundCooldownPacket::new) - .registerClientboundPacket(0x14, ClientboundCustomChatCompletionsPacket.class, ClientboundCustomChatCompletionsPacket::new) - .registerClientboundPacket(0x15, ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) - .registerClientboundPacket(0x16, ClientboundDeleteChatPacket.class, ClientboundDeleteChatPacket::new) - .registerClientboundPacket(0x17, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) - .registerClientboundPacket(0x18, ClientboundDisguisedChatPacket.class, ClientboundDisguisedChatPacket::new) - .registerClientboundPacket(0x19, ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new) - .registerClientboundPacket(0x1A, ClientboundExplodePacket.class, ClientboundExplodePacket::new) - .registerClientboundPacket(0x1B, ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new) - .registerClientboundPacket(0x1C, ClientboundGameEventPacket.class, ClientboundGameEventPacket::new) - .registerClientboundPacket(0x1D, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new) - .registerClientboundPacket(0x1E, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new) - .registerClientboundPacket(0x1F, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new) - .registerClientboundPacket(0x20, ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new) - .registerClientboundPacket(0x21, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new) - .registerClientboundPacket(0x22, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new) - .registerClientboundPacket(0x23, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new) - .registerClientboundPacket(0x24, ClientboundLoginPacket.class, ClientboundLoginPacket::new) - .registerClientboundPacket(0x25, ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new) - .registerClientboundPacket(0x26, ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new) - .registerClientboundPacket(0x27, ClientboundMoveEntityPosPacket.class, ClientboundMoveEntityPosPacket::new) - .registerClientboundPacket(0x28, ClientboundMoveEntityPosRotPacket.class, ClientboundMoveEntityPosRotPacket::new) - .registerClientboundPacket(0x29, ClientboundMoveEntityRotPacket.class, ClientboundMoveEntityRotPacket::new) - .registerClientboundPacket(0x2A, ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new) - .registerClientboundPacket(0x2B, ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new) - .registerClientboundPacket(0x2C, ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new) - .registerClientboundPacket(0x2D, ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new) - .registerClientboundPacket(0x2E, ClientboundPingPacket.class, ClientboundPingPacket::new) - .registerClientboundPacket(0x2F, ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new) - .registerClientboundPacket(0x30, ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new) - .registerClientboundPacket(0x31, ClientboundPlayerChatPacket.class, ClientboundPlayerChatPacket::new) - .registerClientboundPacket(0x32, ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new) - .registerClientboundPacket(0x33, ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new) - .registerClientboundPacket(0x34, ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new) - .registerClientboundPacket(0x35, ClientboundPlayerInfoRemovePacket.class, ClientboundPlayerInfoRemovePacket::new) - .registerClientboundPacket(0x36, ClientboundPlayerInfoUpdatePacket.class, ClientboundPlayerInfoUpdatePacket::new) - .registerClientboundPacket(0x37, ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new) - .registerClientboundPacket(0x38, ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new) - .registerClientboundPacket(0x39, ClientboundRecipePacket.class, ClientboundRecipePacket::new) - .registerClientboundPacket(0x3A, ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new) - .registerClientboundPacket(0x3B, ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new) - .registerClientboundPacket(0x3C, ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new) - .registerClientboundPacket(0x3D, ClientboundRespawnPacket.class, ClientboundRespawnPacket::new) - .registerClientboundPacket(0x3E, ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new) - .registerClientboundPacket(0x3F, ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new) - .registerClientboundPacket(0x40, ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new) - .registerClientboundPacket(0x41, ClientboundServerDataPacket.class, ClientboundServerDataPacket::new) - .registerClientboundPacket(0x42, ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new) - .registerClientboundPacket(0x43, ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new) - .registerClientboundPacket(0x44, ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new) - .registerClientboundPacket(0x45, ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new) - .registerClientboundPacket(0x46, ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new) - .registerClientboundPacket(0x47, ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new) - .registerClientboundPacket(0x48, ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new) - .registerClientboundPacket(0x49, ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new) - .registerClientboundPacket(0x4A, ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new) - .registerClientboundPacket(0x4B, ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new) - .registerClientboundPacket(0x4C, ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new) - .registerClientboundPacket(0x4D, ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new) - .registerClientboundPacket(0x4E, ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new) - .registerClientboundPacket(0x4F, ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new) - .registerClientboundPacket(0x50, ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new) - .registerClientboundPacket(0x51, ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new) - .registerClientboundPacket(0x52, ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new) - .registerClientboundPacket(0x53, ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new) - .registerClientboundPacket(0x54, ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new) - .registerClientboundPacket(0x55, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new) - .registerClientboundPacket(0x56, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new) - .registerClientboundPacket(0x57, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new) - .registerClientboundPacket(0x58, ClientboundSetSimulationDistancePacket.class, ClientboundSetSimulationDistancePacket::new) - .registerClientboundPacket(0x59, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new) - .registerClientboundPacket(0x5A, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new) - .registerClientboundPacket(0x5B, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new) - .registerClientboundPacket(0x5C, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new) - .registerClientboundPacket(0x5D, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new) - .registerClientboundPacket(0x5E, ClientboundSoundPacket.class, ClientboundSoundPacket::new) - .registerClientboundPacket(0x5F, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new) - .registerClientboundPacket(0x60, ClientboundSystemChatPacket.class, ClientboundSystemChatPacket::new) - .registerClientboundPacket(0x61, ClientboundTabListPacket.class, ClientboundTabListPacket::new) - .registerClientboundPacket(0x62, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new) - .registerClientboundPacket(0x63, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new) - .registerClientboundPacket(0x64, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new) - .registerClientboundPacket(0x65, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new) - .registerClientboundPacket(0x66, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new) - .registerClientboundPacket(0x67, ClientboundUpdateEnabledFeaturesPacket.class, ClientboundUpdateEnabledFeaturesPacket::new) - .registerClientboundPacket(0x68, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new) - .registerClientboundPacket(0x69, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new) - .registerClientboundPacket(0x6A, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) + .registerClientboundPacket(0x00, ClientboundDelimiterPacket.class, ClientboundDelimiterPacket::new) + .registerClientboundPacket(0x01, ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new) + .registerClientboundPacket(0x02, ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new) + .registerClientboundPacket(0x03, ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new) + .registerClientboundPacket(0x04, ClientboundAnimatePacket.class, ClientboundAnimatePacket::new) + .registerClientboundPacket(0x05, ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new) + .registerClientboundPacket(0x06, ClientboundBlockChangedAckPacket.class, ClientboundBlockChangedAckPacket::new) + .registerClientboundPacket(0x07, ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new) + .registerClientboundPacket(0x08, ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new) + .registerClientboundPacket(0x09, ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new) + .registerClientboundPacket(0x0A, ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new) + .registerClientboundPacket(0x0B, ClientboundBossEventPacket.class, ClientboundBossEventPacket::new) + .registerClientboundPacket(0x0C, ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new) + .registerClientboundPacket(0x0D, ClientboundChunksBiomesPacket.class, ClientboundChunksBiomesPacket::new) + .registerClientboundPacket(0x0E, ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new) + .registerClientboundPacket(0x0F, ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new) + .registerClientboundPacket(0x10, ClientboundCommandsPacket.class, ClientboundCommandsPacket::new) + .registerClientboundPacket(0x11, ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new) + .registerClientboundPacket(0x12, ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new) + .registerClientboundPacket(0x13, ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new) + .registerClientboundPacket(0x14, ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new) + .registerClientboundPacket(0x15, ClientboundCooldownPacket.class, ClientboundCooldownPacket::new) + .registerClientboundPacket(0x16, ClientboundCustomChatCompletionsPacket.class, ClientboundCustomChatCompletionsPacket::new) + .registerClientboundPacket(0x17, ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) + .registerClientboundPacket(0x18, ClientboundDamageEventPacket.class, ClientboundDamageEventPacket::new) + .registerClientboundPacket(0x19, ClientboundDeleteChatPacket.class, ClientboundDeleteChatPacket::new) + .registerClientboundPacket(0x1A, ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) + .registerClientboundPacket(0x1B, ClientboundDisguisedChatPacket.class, ClientboundDisguisedChatPacket::new) + .registerClientboundPacket(0x1C, ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new) + .registerClientboundPacket(0x1D, ClientboundExplodePacket.class, ClientboundExplodePacket::new) + .registerClientboundPacket(0x1E, ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new) + .registerClientboundPacket(0x1F, ClientboundGameEventPacket.class, ClientboundGameEventPacket::new) + .registerClientboundPacket(0x20, ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new) + .registerClientboundPacket(0x21, ClientboundHurtAnimationPacket.class, ClientboundHurtAnimationPacket::new) + .registerClientboundPacket(0x22, ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new) + .registerClientboundPacket(0x23, ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new) + .registerClientboundPacket(0x24, ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new) + .registerClientboundPacket(0x25, ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new) + .registerClientboundPacket(0x26, ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new) + .registerClientboundPacket(0x27, ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new) + .registerClientboundPacket(0x28, ClientboundLoginPacket.class, ClientboundLoginPacket::new) + .registerClientboundPacket(0x29, ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new) + .registerClientboundPacket(0x2A, ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new) + .registerClientboundPacket(0x2B, ClientboundMoveEntityPosPacket.class, ClientboundMoveEntityPosPacket::new) + .registerClientboundPacket(0x2C, ClientboundMoveEntityPosRotPacket.class, ClientboundMoveEntityPosRotPacket::new) + .registerClientboundPacket(0x2D, ClientboundMoveEntityRotPacket.class, ClientboundMoveEntityRotPacket::new) + .registerClientboundPacket(0x2E, ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new) + .registerClientboundPacket(0x2F, ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new) + .registerClientboundPacket(0x30, ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new) + .registerClientboundPacket(0x31, ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new) + .registerClientboundPacket(0x32, ClientboundPingPacket.class, ClientboundPingPacket::new) + .registerClientboundPacket(0x33, ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new) + .registerClientboundPacket(0x34, ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new) + .registerClientboundPacket(0x35, ClientboundPlayerChatPacket.class, ClientboundPlayerChatPacket::new) + .registerClientboundPacket(0x36, ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new) + .registerClientboundPacket(0x37, ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new) + .registerClientboundPacket(0x38, ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new) + .registerClientboundPacket(0x39, ClientboundPlayerInfoRemovePacket.class, ClientboundPlayerInfoRemovePacket::new) + .registerClientboundPacket(0x3A, ClientboundPlayerInfoUpdatePacket.class, ClientboundPlayerInfoUpdatePacket::new) + .registerClientboundPacket(0x3B, ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new) + .registerClientboundPacket(0x3C, ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new) + .registerClientboundPacket(0x3D, ClientboundRecipePacket.class, ClientboundRecipePacket::new) + .registerClientboundPacket(0x3E, ClientboundRemoveEntitiesPacket.class, ClientboundRemoveEntitiesPacket::new) + .registerClientboundPacket(0x3F, ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new) + .registerClientboundPacket(0x40, ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new) + .registerClientboundPacket(0x41, ClientboundRespawnPacket.class, ClientboundRespawnPacket::new) + .registerClientboundPacket(0x42, ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new) + .registerClientboundPacket(0x43, ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new) + .registerClientboundPacket(0x44, ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new) + .registerClientboundPacket(0x45, ClientboundServerDataPacket.class, ClientboundServerDataPacket::new) + .registerClientboundPacket(0x46, ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new) + .registerClientboundPacket(0x47, ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new) + .registerClientboundPacket(0x48, ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new) + .registerClientboundPacket(0x49, ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new) + .registerClientboundPacket(0x4A, ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new) + .registerClientboundPacket(0x4B, ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new) + .registerClientboundPacket(0x4C, ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new) + .registerClientboundPacket(0x4D, ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new) + .registerClientboundPacket(0x4E, ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new) + .registerClientboundPacket(0x4F, ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new) + .registerClientboundPacket(0x50, ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new) + .registerClientboundPacket(0x51, ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new) + .registerClientboundPacket(0x52, ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new) + .registerClientboundPacket(0x53, ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new) + .registerClientboundPacket(0x54, ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new) + .registerClientboundPacket(0x55, ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new) + .registerClientboundPacket(0x56, ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new) + .registerClientboundPacket(0x57, ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new) + .registerClientboundPacket(0x58, ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new) + .registerClientboundPacket(0x59, ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new) + .registerClientboundPacket(0x5A, ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new) + .registerClientboundPacket(0x5B, ClientboundSetScorePacket.class, ClientboundSetScorePacket::new) + .registerClientboundPacket(0x5C, ClientboundSetSimulationDistancePacket.class, ClientboundSetSimulationDistancePacket::new) + .registerClientboundPacket(0x5D, ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new) + .registerClientboundPacket(0x5E, ClientboundSetTimePacket.class, ClientboundSetTimePacket::new) + .registerClientboundPacket(0x5F, ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new) + .registerClientboundPacket(0x60, ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new) + .registerClientboundPacket(0x61, ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new) + .registerClientboundPacket(0x62, ClientboundSoundPacket.class, ClientboundSoundPacket::new) + .registerClientboundPacket(0x63, ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new) + .registerClientboundPacket(0x64, ClientboundSystemChatPacket.class, ClientboundSystemChatPacket::new) + .registerClientboundPacket(0x65, ClientboundTabListPacket.class, ClientboundTabListPacket::new) + .registerClientboundPacket(0x66, ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new) + .registerClientboundPacket(0x67, ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new) + .registerClientboundPacket(0x68, ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new) + .registerClientboundPacket(0x69, ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new) + .registerClientboundPacket(0x6A, ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new) + .registerClientboundPacket(0x6B, ClientboundUpdateEnabledFeaturesPacket.class, ClientboundUpdateEnabledFeaturesPacket::new) + .registerClientboundPacket(0x6C, ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new) + .registerClientboundPacket(0x6D, ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new) + .registerClientboundPacket(0x6E, ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) .registerServerboundPacket(0x00, ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new) .registerServerboundPacket(0x01, ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new) .registerServerboundPacket(0x02, ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new) .registerServerboundPacket(0x03, ServerboundChatAckPacket.class, ServerboundChatAckPacket::new) .registerServerboundPacket(0x04, ServerboundChatCommandPacket.class, ServerboundChatCommandPacket::new) .registerServerboundPacket(0x05, ServerboundChatPacket.class, ServerboundChatPacket::new) - .registerServerboundPacket(0x06, ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new) - .registerServerboundPacket(0x07, ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new) - .registerServerboundPacket(0x08, ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new) - .registerServerboundPacket(0x09, ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new) - .registerServerboundPacket(0x0A, ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new) - .registerServerboundPacket(0x0B, ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new) - .registerServerboundPacket(0x0C, ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) - .registerServerboundPacket(0x0D, ServerboundEditBookPacket.class, ServerboundEditBookPacket::new) - .registerServerboundPacket(0x0E, ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new) - .registerServerboundPacket(0x0F, ServerboundInteractPacket.class, ServerboundInteractPacket::new) - .registerServerboundPacket(0x10, ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new) - .registerServerboundPacket(0x11, ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new) - .registerServerboundPacket(0x12, ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new) - .registerServerboundPacket(0x13, ServerboundMovePlayerPosPacket.class, ServerboundMovePlayerPosPacket::new) - .registerServerboundPacket(0x14, ServerboundMovePlayerPosRotPacket.class, ServerboundMovePlayerPosRotPacket::new) - .registerServerboundPacket(0x15, ServerboundMovePlayerRotPacket.class, ServerboundMovePlayerRotPacket::new) - .registerServerboundPacket(0x16, ServerboundMovePlayerStatusOnlyPacket.class, ServerboundMovePlayerStatusOnlyPacket::new) - .registerServerboundPacket(0x17, ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new) - .registerServerboundPacket(0x18, ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new) - .registerServerboundPacket(0x19, ServerboundPickItemPacket.class, ServerboundPickItemPacket::new) - .registerServerboundPacket(0x1A, ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new) - .registerServerboundPacket(0x1B, ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new) - .registerServerboundPacket(0x1C, ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new) - .registerServerboundPacket(0x1D, ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new) - .registerServerboundPacket(0x1E, ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new) - .registerServerboundPacket(0x1F, ServerboundPongPacket.class, ServerboundPongPacket::new) - .registerServerboundPacket(0x20, ServerboundChatSessionUpdatePacket.class, ServerboundChatSessionUpdatePacket::new) + .registerServerboundPacket(0x06, ServerboundChatSessionUpdatePacket.class, ServerboundChatSessionUpdatePacket::new) + .registerServerboundPacket(0x07, ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new) + .registerServerboundPacket(0x08, ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new) + .registerServerboundPacket(0x09, ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new) + .registerServerboundPacket(0x0A, ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new) + .registerServerboundPacket(0x0B, ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new) + .registerServerboundPacket(0x0C, ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new) + .registerServerboundPacket(0x0D, ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) + .registerServerboundPacket(0x0E, ServerboundEditBookPacket.class, ServerboundEditBookPacket::new) + .registerServerboundPacket(0x0F, ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new) + .registerServerboundPacket(0x10, ServerboundInteractPacket.class, ServerboundInteractPacket::new) + .registerServerboundPacket(0x11, ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new) + .registerServerboundPacket(0x12, ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new) + .registerServerboundPacket(0x13, ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new) + .registerServerboundPacket(0x14, ServerboundMovePlayerPosPacket.class, ServerboundMovePlayerPosPacket::new) + .registerServerboundPacket(0x15, ServerboundMovePlayerPosRotPacket.class, ServerboundMovePlayerPosRotPacket::new) + .registerServerboundPacket(0x16, ServerboundMovePlayerRotPacket.class, ServerboundMovePlayerRotPacket::new) + .registerServerboundPacket(0x17, ServerboundMovePlayerStatusOnlyPacket.class, ServerboundMovePlayerStatusOnlyPacket::new) + .registerServerboundPacket(0x18, ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new) + .registerServerboundPacket(0x19, ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new) + .registerServerboundPacket(0x1A, ServerboundPickItemPacket.class, ServerboundPickItemPacket::new) + .registerServerboundPacket(0x1B, ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new) + .registerServerboundPacket(0x1C, ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new) + .registerServerboundPacket(0x1D, ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new) + .registerServerboundPacket(0x1E, ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new) + .registerServerboundPacket(0x1F, ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new) + .registerServerboundPacket(0x20, ServerboundPongPacket.class, ServerboundPongPacket::new) .registerServerboundPacket(0x21, ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new) .registerServerboundPacket(0x22, ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new) .registerServerboundPacket(0x23, ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new) diff --git a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java index fe092df7..520742cf 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java +++ b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java @@ -8,18 +8,39 @@ import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage; import com.github.steveice10.mc.protocol.data.game.chunk.ChunkSection; import com.github.steveice10.mc.protocol.data.game.chunk.DataPalette; import com.github.steveice10.mc.protocol.data.game.chunk.NibbleArray3d; -import com.github.steveice10.mc.protocol.data.game.chunk.palette.*; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.ListPalette; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.MapPalette; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.PaletteType; +import com.github.steveice10.mc.protocol.data.game.chunk.palette.SingletonPalette; import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.mc.protocol.data.game.entity.EntityEvent; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.*; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.SnifferState; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.data.game.entity.player.BlockBreakStage; import com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType; import com.github.steveice10.mc.protocol.data.game.level.LightUpdateData; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; -import com.github.steveice10.mc.protocol.data.game.level.particle.*; +import com.github.steveice10.mc.protocol.data.game.level.particle.BlockParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.DustColorTransitionParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.DustParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.FallingDustParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.ItemParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; +import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; +import com.github.steveice10.mc.protocol.data.game.level.particle.SculkChargeParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.ShriekParticleData; +import com.github.steveice10.mc.protocol.data.game.level.particle.VibrationParticleData; import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.BlockPositionSource; import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.EntityPositionSource; import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.PositionSource; @@ -37,6 +58,7 @@ import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.packetlib.codec.BasePacketCodecHelper; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.math.vector.Vector4f; import io.netty.buffer.ByteBuf; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import lombok.RequiredArgsConstructor; @@ -53,7 +75,11 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.function.*; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.ObjIntConsumer; +import java.util.function.ToIntFunction; @RequiredArgsConstructor public class MinecraftCodecHelper extends BasePacketCodecHelper { @@ -269,6 +295,22 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { buf.writeFloat(rot.getZ()); } + public Vector4f readQuaternion(ByteBuf buf) { + float x = buf.readFloat(); + float y = buf.readFloat(); + float z = buf.readFloat(); + float w = buf.readFloat(); + + return Vector4f.from(x, y, z, w); + } + + public void writeQuaternion(ByteBuf buf, Vector4f vec4) { + buf.writeFloat(vec4.getX()); + buf.writeFloat(vec4.getY()); + buf.writeFloat(vec4.getZ()); + buf.writeFloat(vec4.getW()); + } + public Direction readDirection(ByteBuf buf) { return Direction.from(this.readVarInt(buf)); } @@ -293,6 +335,14 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { this.writeEnum(buf, type); } + public SnifferState readSnifferState(ByteBuf buf) { + return SnifferState.from(this.readVarInt(buf)); + } + + public void writeSnifferState(ByteBuf buf, SnifferState state) { + this.writeEnum(buf, state); + } + private void writeEnum(ByteBuf buf, Enum e) { this.writeVarInt(buf, e.ordinal()); } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java index ce51d7b3..09fbee03 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java @@ -159,7 +159,6 @@ public class MagicValues { register(Difficulty.HARD, 3); register(Animation.SWING_ARM, 0); - register(Animation.DAMAGE, 1); register(Animation.LEAVE_BED, 2); register(Animation.SWING_OFFHAND, 3); register(Animation.CRITICAL_HIT, 4); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/ChunkBiomeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/ChunkBiomeData.java new file mode 100644 index 00000000..8d440db1 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/chunk/ChunkBiomeData.java @@ -0,0 +1,12 @@ +package com.github.steveice10.mc.protocol.data.game.chunk; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class ChunkBiomeData { + private final int x; + private final int z; + private final byte[] buffer; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java index 19118a9b..08b8301c 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java @@ -1,13 +1,19 @@ package com.github.steveice10.mc.protocol.data.game.entity.metadata; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.*; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.LongEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType; import com.github.steveice10.mc.protocol.data.game.level.particle.Particle; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.math.vector.Vector4f; import io.netty.buffer.ByteBuf; import lombok.Getter; import net.kyori.adventure.text.Component; @@ -36,7 +42,8 @@ public class MetadataType { public static final MetadataType> OPTIONAL_POSITION = new MetadataType<>(optionalReader(MinecraftCodecHelper::readPosition), optionalWriter(MinecraftCodecHelper::writePosition), ObjectEntityMetadata::new); public static final MetadataType DIRECTION = new MetadataType<>(MinecraftCodecHelper::readDirection, MinecraftCodecHelper::writeDirection, ObjectEntityMetadata::new); public static final MetadataType> OPTIONAL_UUID = new MetadataType<>(optionalReader(MinecraftCodecHelper::readUUID), optionalWriter(MinecraftCodecHelper::writeUUID), ObjectEntityMetadata::new); - public static final OptionalIntMetadataType BLOCK_STATE = new OptionalIntMetadataType(ObjectEntityMetadata::new); + public static final IntMetadataType BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); + public static final MetadataType> OPTIONAL_BLOCK_STATE = new MetadataType<>(optionalReader(MinecraftCodecHelper::readVarInt), optionalWriter(MinecraftCodecHelper::writeVarInt), ObjectEntityMetadata::new); public static final MetadataType NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readTag, MinecraftCodecHelper::writeTag, ObjectEntityMetadata::new); public static final MetadataType PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new); public static final MetadataType VILLAGER_DATA = new MetadataType<>(MinecraftCodecHelper::readVillagerData, MinecraftCodecHelper::writeVillagerData, ObjectEntityMetadata::new); @@ -46,6 +53,9 @@ public class MetadataType { public static final IntMetadataType FROG_VARIANT = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); public static final MetadataType> OPTIONAL_GLOBAL_POS = new MetadataType<>(optionalReader(MinecraftCodecHelper::readGlobalPos), optionalWriter(MinecraftCodecHelper::writeGlobalPos), ObjectEntityMetadata::new); public static final MetadataType PAINTING_VARIANT = new MetadataType<>(MinecraftCodecHelper::readPaintingType, MinecraftCodecHelper::writePaintingType, ObjectEntityMetadata::new); + public static final MetadataType SNIFFER_STATE = new MetadataType<>(MinecraftCodecHelper::readSnifferState, MinecraftCodecHelper::writeSnifferState, ObjectEntityMetadata::new); + public static final MetadataType VECTOR3 = new MetadataType<>(MinecraftCodecHelper::readRotation, MinecraftCodecHelper::writeRotation, ObjectEntityMetadata::new); + public static final MetadataType QUATERNION = new MetadataType<>(MinecraftCodecHelper::readQuaternion, MinecraftCodecHelper::writeQuaternion, ObjectEntityMetadata::new); protected final int id; protected final Reader reader; diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/SnifferState.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/SnifferState.java new file mode 100644 index 00000000..c79f6ae3 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/SnifferState.java @@ -0,0 +1,17 @@ +package com.github.steveice10.mc.protocol.data.game.entity.metadata; + +public enum SnifferState { + IDLING, + FEELING_HAPPY, + SCENTING, + SNIFFING, + SEARCHING, + DIGGING, + RISING; + + private static final SnifferState[] VALUES = values(); + + public static SnifferState from(int id) { + return VALUES[id]; + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/player/Animation.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/player/Animation.java index bb9516dc..1b3c4175 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/player/Animation.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/player/Animation.java @@ -2,7 +2,6 @@ package com.github.steveice10.mc.protocol.data.game.entity.player; public enum Animation { SWING_ARM, - DAMAGE, LEAVE_BED, SWING_OFFHAND, CRITICAL_HIT, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/particle/ParticleType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/particle/ParticleType.java index 91a768b7..61b4291b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/particle/ParticleType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/particle/ParticleType.java @@ -30,6 +30,9 @@ public enum ParticleType { FIREWORK, FISHING, FLAME, + DRIPPING_CHERRY_LEAVES, + FALLING_CHERRY_LEAVES, + LANDING_CHERRY_LEAVES, SCULK_SOUL, SCULK_CHARGE, SCULK_CHARGE_POP, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java index 099fcefc..6ff15bf8 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/sound/BuiltinSound.java @@ -173,6 +173,8 @@ public enum BuiltinSound implements Sound { ITEM_BOTTLE_FILL("item.bottle.fill"), ITEM_BOTTLE_FILL_DRAGONBREATH("item.bottle.fill_dragonbreath"), BLOCK_BREWING_STAND_BREW("block.brewing_stand.brew"), + ITEM_BRUSH_BRUSHING("item.brush.brushing"), + ITEM_BRUSH_BRUSH_SAND_COMPLETED("item.brush.brush_sand_completed"), BLOCK_BUBBLE_COLUMN_BUBBLE_POP("block.bubble_column.bubble_pop"), BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT("block.bubble_column.upwards_ambient"), BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE("block.bubble_column.upwards_inside"), @@ -238,6 +240,36 @@ public enum BuiltinSound implements Sound { BLOCK_CHAIN_HIT("block.chain.hit"), BLOCK_CHAIN_PLACE("block.chain.place"), BLOCK_CHAIN_STEP("block.chain.step"), + BLOCK_CHERRY_WOOD_BREAK("block.cherry_wood.break"), + BLOCK_CHERRY_WOOD_FALL("block.cherry_wood.fall"), + BLOCK_CHERRY_WOOD_HIT("block.cherry_wood.hit"), + BLOCK_CHERRY_WOOD_PLACE("block.cherry_wood.place"), + BLOCK_CHERRY_WOOD_STEP("block.cherry_wood.step"), + BLOCK_CHERRY_SAPLING_BREAK("block.cherry_sapling.break"), + BLOCK_CHERRY_SAPLING_FALL("block.cherry_sapling.fall"), + BLOCK_CHERRY_SAPLING_HIT("block.cherry_sapling.hit"), + BLOCK_CHERRY_SAPLING_PLACE("block.cherry_sapling.place"), + BLOCK_CHERRY_SAPLING_STEP("block.cherry_sapling.step"), + BLOCK_CHERRY_LEAVES_BREAK("block.cherry_leaves.break"), + BLOCK_CHERRY_LEAVES_FALL("block.cherry_leaves.fall"), + BLOCK_CHERRY_LEAVES_HIT("block.cherry_leaves.hit"), + BLOCK_CHERRY_LEAVES_PLACE("block.cherry_leaves.place"), + BLOCK_CHERRY_LEAVES_STEP("block.cherry_leaves.step"), + BLOCK_CHERRY_WOOD_HANGING_SIGN_STEP("block.cherry_wood_hanging_sign.step"), + BLOCK_CHERRY_WOOD_HANGING_SIGN_BREAK("block.cherry_wood_hanging_sign.break"), + BLOCK_CHERRY_WOOD_HANGING_SIGN_FALL("block.cherry_wood_hanging_sign.fall"), + BLOCK_CHERRY_WOOD_HANGING_SIGN_HIT("block.cherry_wood_hanging_sign.hit"), + BLOCK_CHERRY_WOOD_HANGING_SIGN_PLACE("block.cherry_wood_hanging_sign.place"), + BLOCK_CHERRY_WOOD_DOOR_CLOSE("block.cherry_wood_door.close"), + BLOCK_CHERRY_WOOD_DOOR_OPEN("block.cherry_wood_door.open"), + BLOCK_CHERRY_WOOD_TRAPDOOR_CLOSE("block.cherry_wood_trapdoor.close"), + BLOCK_CHERRY_WOOD_TRAPDOOR_OPEN("block.cherry_wood_trapdoor.open"), + BLOCK_CHERRY_WOOD_BUTTON_CLICK_OFF("block.cherry_wood_button.click_off"), + BLOCK_CHERRY_WOOD_BUTTON_CLICK_ON("block.cherry_wood_button.click_on"), + BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_OFF("block.cherry_wood_pressure_plate.click_off"), + BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_ON("block.cherry_wood_pressure_plate.click_on"), + BLOCK_CHERRY_WOOD_FENCE_GATE_CLOSE("block.cherry_wood_fence_gate.close"), + BLOCK_CHERRY_WOOD_FENCE_GATE_OPEN("block.cherry_wood_fence_gate.open"), BLOCK_CHEST_CLOSE("block.chest.close"), BLOCK_CHEST_LOCKED("block.chest.locked"), BLOCK_CHEST_OPEN("block.chest.open"), @@ -300,6 +332,12 @@ public enum BuiltinSound implements Sound { ITEM_CROSSBOW_QUICK_CHARGE_2("item.crossbow.quick_charge_2"), ITEM_CROSSBOW_QUICK_CHARGE_3("item.crossbow.quick_charge_3"), ITEM_CROSSBOW_SHOOT("item.crossbow.shoot"), + BLOCK_DECORATED_POT_BREAK("block.decorated_pot.break"), + BLOCK_DECORATED_POT_FALL("block.decorated_pot.fall"), + BLOCK_DECORATED_POT_HIT("block.decorated_pot.hit"), + BLOCK_DECORATED_POT_STEP("block.decorated_pot.step"), + BLOCK_DECORATED_POT_PLACE("block.decorated_pot.place"), + BLOCK_DECORATED_POT_SHATTER("block.decorated_pot.shatter"), BLOCK_DEEPSLATE_BRICKS_BREAK("block.deepslate_bricks.break"), BLOCK_DEEPSLATE_BRICKS_FALL("block.deepslate_bricks.fall"), BLOCK_DEEPSLATE_BRICKS_HIT("block.deepslate_bricks.hit"), @@ -442,6 +480,11 @@ public enum BuiltinSound implements Sound { ENTITY_FOX_SNIFF("entity.fox.sniff"), ENTITY_FOX_SPIT("entity.fox.spit"), ENTITY_FOX_TELEPORT("entity.fox.teleport"), + BLOCK_SUSPICIOUS_SAND_BREAK("block.suspicious_sand.break"), + BLOCK_SUSPICIOUS_SAND_STEP("block.suspicious_sand.step"), + BLOCK_SUSPICIOUS_SAND_PLACE("block.suspicious_sand.place"), + BLOCK_SUSPICIOUS_SAND_HIT("block.suspicious_sand.hit"), + BLOCK_SUSPICIOUS_SAND_FALL("block.suspicious_sand.fall"), BLOCK_FROGLIGHT_BREAK("block.froglight.break"), BLOCK_FROGLIGHT_FALL("block.froglight.fall"), BLOCK_FROGLIGHT_HIT("block.froglight.hit"), @@ -708,6 +751,11 @@ public enum BuiltinSound implements Sound { BLOCK_MOSS_CARPET_HIT("block.moss_carpet.hit"), BLOCK_MOSS_CARPET_PLACE("block.moss_carpet.place"), BLOCK_MOSS_CARPET_STEP("block.moss_carpet.step"), + BLOCK_PINK_PETALS_BREAK("block.pink_petals.break"), + BLOCK_PINK_PETALS_FALL("block.pink_petals.fall"), + BLOCK_PINK_PETALS_HIT("block.pink_petals.hit"), + BLOCK_PINK_PETALS_PLACE("block.pink_petals.place"), + BLOCK_PINK_PETALS_STEP("block.pink_petals.step"), BLOCK_MOSS_BREAK("block.moss.break"), BLOCK_MOSS_FALL("block.moss.fall"), BLOCK_MOSS_HIT("block.moss.hit"), @@ -766,6 +814,7 @@ public enum BuiltinSound implements Sound { MUSIC_OVERWORLD_JUNGLE_AND_FOREST("music.overworld.jungle_and_forest"), MUSIC_OVERWORLD_OLD_GROWTH_TAIGA("music.overworld.old_growth_taiga"), MUSIC_OVERWORLD_MEADOW("music.overworld.meadow"), + MUSIC_OVERWORLD_CHERRY_GROVE("music.overworld.cherry_grove"), MUSIC_NETHER_NETHER_WASTES("music.nether.nether_wastes"), MUSIC_OVERWORLD_FROZEN_PEAKS("music.overworld.frozen_peaks"), MUSIC_OVERWORLD_SNOWY_SLOPES("music.overworld.snowy_slopes"), @@ -795,6 +844,7 @@ public enum BuiltinSound implements Sound { BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON("block.nether_wood_pressure_plate.click_on"), BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE("block.nether_wood_fence_gate.close"), BLOCK_NETHER_WOOD_FENCE_GATE_OPEN("block.nether_wood_fence_gate.open"), + INTENTIONALLY_EMPTY("intentionally_empty"), BLOCK_PACKED_MUD_BREAK("block.packed_mud.break"), BLOCK_PACKED_MUD_FALL("block.packed_mud.fall"), BLOCK_PACKED_MUD_HIT("block.packed_mud.hit"), @@ -1167,6 +1217,18 @@ public enum BuiltinSound implements Sound { ENTITY_SLIME_SQUISH_SMALL("entity.slime.squish_small"), BLOCK_SMITHING_TABLE_USE("block.smithing_table.use"), BLOCK_SMOKER_SMOKE("block.smoker.smoke"), + ENTITY_SNIFFER_STEP("entity.sniffer.step"), + ENTITY_SNIFFER_EAT("entity.sniffer.eat"), + ENTITY_SNIFFER_IDLE("entity.sniffer.idle"), + ENTITY_SNIFFER_HURT("entity.sniffer.hurt"), + ENTITY_SNIFFER_DEATH("entity.sniffer.death"), + ENTITY_SNIFFER_DROP_SEED("entity.sniffer.drop_seed"), + ENTITY_SNIFFER_SCENTING("entity.sniffer.scenting"), + ENTITY_SNIFFER_SNIFFING("entity.sniffer.sniffing"), + ENTITY_SNIFFER_SEARCHING("entity.sniffer.searching"), + ENTITY_SNIFFER_DIGGING("entity.sniffer.digging"), + ENTITY_SNIFFER_DIGGING_STOP("entity.sniffer.digging_stop"), + ENTITY_SNIFFER_HAPPY("entity.sniffer.happy"), ENTITY_SNOWBALL_THROW("entity.snowball.throw"), BLOCK_SNOW_BREAK("block.snow.break"), BLOCK_SNOW_FALL("block.snow.fall"), @@ -1356,14 +1418,14 @@ public enum BuiltinSound implements Sound { BLOCK_WOODEN_DOOR_OPEN("block.wooden_door.open"), BLOCK_WOODEN_TRAPDOOR_CLOSE("block.wooden_trapdoor.close"), BLOCK_WOODEN_TRAPDOOR_OPEN("block.wooden_trapdoor.open"), - BLOCK_WOOD_BREAK("block.wood.break"), BLOCK_WOODEN_BUTTON_CLICK_OFF("block.wooden_button.click_off"), BLOCK_WOODEN_BUTTON_CLICK_ON("block.wooden_button.click_on"), + BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF("block.wooden_pressure_plate.click_off"), + BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON("block.wooden_pressure_plate.click_on"), + BLOCK_WOOD_BREAK("block.wood.break"), BLOCK_WOOD_FALL("block.wood.fall"), BLOCK_WOOD_HIT("block.wood.hit"), BLOCK_WOOD_PLACE("block.wood.place"), - BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF("block.wooden_pressure_plate.click_off"), - BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON("block.wooden_pressure_plate.click_on"), BLOCK_WOOD_STEP("block.wood.step"), BLOCK_WOOL_BREAK("block.wool.break"), BLOCK_WOOL_FALL("block.wool.fall"), diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/status/PlayerInfo.java b/src/main/java/com/github/steveice10/mc/protocol/data/status/PlayerInfo.java index 14bb2bca..c65976b9 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/status/PlayerInfo.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/status/PlayerInfo.java @@ -7,11 +7,13 @@ import lombok.Data; import lombok.NonNull; import lombok.Setter; +import java.util.List; + @Data @Setter(AccessLevel.NONE) @AllArgsConstructor public class PlayerInfo { private int maxPlayers; private int onlinePlayers; - private @NonNull GameProfile[] players; + private @NonNull List players; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDelimiterPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDelimiterPacket.java new file mode 100644 index 00000000..10e120c1 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundDelimiterPacket.java @@ -0,0 +1,14 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; + +public class ClientboundDelimiterPacket implements MinecraftPacket { + public ClientboundDelimiterPacket(ByteBuf in, MinecraftCodecHelper helper) { + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java index 32b714d8..dfa47f75 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java @@ -2,7 +2,6 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -16,38 +15,20 @@ import java.io.IOException; @With @AllArgsConstructor public class ClientboundServerDataPacket implements MinecraftPacket { - private final @Nullable Component motd; - private final @Nullable String iconBase64; + private final Component motd; + private final byte @Nullable[] iconBytes; private final boolean enforcesSecureChat; public ClientboundServerDataPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { - if (in.readBoolean()) { - this.motd = helper.readComponent(in); - } else { - this.motd = null; - } - - if (in.readBoolean()) { - this.iconBase64 = helper.readString(in); - } else { - this.iconBase64 = null; - } - + this.motd = helper.readComponent(in); + this.iconBytes = helper.readNullable(in, helper::readByteArray); this.enforcesSecureChat = in.readBoolean(); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException { - out.writeBoolean(this.motd != null); - if (this.motd != null) { - helper.writeString(out, DefaultComponentSerializer.get().serialize(this.motd)); - } - - out.writeBoolean(this.iconBase64 != null); - if (this.iconBase64 != null) { - helper.writeString(out, this.iconBase64); - } - + helper.writeComponent(out, this.motd); + helper.writeNullable(out, this.iconBytes, helper::writeByteArray); out.writeBoolean(this.enforcesSecureChat); } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java new file mode 100644 index 00000000..82f121dd --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java @@ -0,0 +1,40 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.nukkitx.math.vector.Vector3d; +import io.netty.buffer.ByteBuf; +import org.jetbrains.annotations.Nullable; + +public class ClientboundDamageEventPacket implements MinecraftPacket { + private final int entityId; + private final int sourceTypeId; + private final int sourceCauseId; + private final int sourceDirectId; + private final @Nullable Vector3d sourcePosition; + + public ClientboundDamageEventPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.entityId = helper.readVarInt(in); + this.sourceTypeId = helper.readVarInt(in); + this.sourceCauseId = helper.readVarInt(in) - 1; + this.sourceDirectId = helper.readVarInt(in) - 1; + this.sourcePosition = in.readBoolean() ? Vector3d.from(in.readDouble(), in.readDouble(), in.readDouble()) : null; + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.entityId); + helper.writeVarInt(out, this.sourceTypeId); + helper.writeVarInt(out, this.sourceCauseId + 1); + helper.writeVarInt(out, this.sourceDirectId + 1); + + if (this.sourcePosition != null) { + out.writeBoolean(true); + out.writeDouble(this.sourcePosition.getX()); + out.writeDouble(this.sourcePosition.getY()); + out.writeDouble(this.sourcePosition.getZ()); + } else { + out.writeBoolean(false); + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundHurtAnimationPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundHurtAnimationPacket.java new file mode 100644 index 00000000..76486f6a --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundHurtAnimationPacket.java @@ -0,0 +1,27 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundHurtAnimationPacket implements MinecraftPacket { + private final int id; + private final float yaw; + + public ClientboundHurtAnimationPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.id = helper.readVarInt(in); + this.yaw = in.readFloat(); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.id); + out.writeFloat(this.yaw); + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundPlayerPositionPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundPlayerPositionPacket.java index 17ffa863..05204c4a 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundPlayerPositionPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/player/ClientboundPlayerPositionPacket.java @@ -25,11 +25,10 @@ public class ClientboundPlayerPositionPacket implements MinecraftPacket { private final float yaw; private final float pitch; private final int teleportId; - private final boolean dismountVehicle; private final @NonNull List relative; - public ClientboundPlayerPositionPacket(double x, double y, double z, float yaw, float pitch, int teleportId, boolean dismountVehicle, PositionElement... relative) { - this(x, y, z, yaw, pitch, teleportId, dismountVehicle, Arrays.asList(relative != null ? relative : new PositionElement[0])); + public ClientboundPlayerPositionPacket(double x, double y, double z, float yaw, float pitch, int teleportId, PositionElement... relative) { + this(x, y, z, yaw, pitch, teleportId, Arrays.asList(relative != null ? relative : new PositionElement[0])); } public ClientboundPlayerPositionPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { @@ -49,7 +48,6 @@ public class ClientboundPlayerPositionPacket implements MinecraftPacket { } this.teleportId = helper.readVarInt(in); - this.dismountVehicle = in.readBoolean(); } @Override @@ -68,6 +66,5 @@ public class ClientboundPlayerPositionPacket implements MinecraftPacket { out.writeByte(flags); helper.writeVarInt(out, this.teleportId); - out.writeBoolean(this.dismountVehicle); } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java new file mode 100644 index 00000000..f61724b6 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java @@ -0,0 +1,33 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.github.steveice10.mc.protocol.data.game.chunk.ChunkBiomeData; +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; +import java.util.List; + +public class ClientboundChunksBiomesPacket implements MinecraftPacket { + private final List chunkBiomeData; + + public ClientboundChunksBiomesPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.chunkBiomeData = new ArrayList<>(); + + int length = helper.readVarInt(in); + for (int i = 0; i < length; i++) { + long raw = in.readLong(); + this.chunkBiomeData.add(new ChunkBiomeData((int)raw, (int)(raw >> 32), helper.readByteArray(in))); + } + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.chunkBiomeData.size()); + for (ChunkBiomeData entry : this.chunkBiomeData) { + long raw = (long)entry.getX() & 0xFFFFFFFFL | ((long)entry.getZ() & 0xFFFFFFFFL) << 32; + out.writeLong(raw); + helper.writeByteArray(out, entry.getBuffer()); + } + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSectionBlocksUpdatePacket.java index 89ba5c30..86a50910 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSectionBlocksUpdatePacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSectionBlocksUpdatePacket.java @@ -62,7 +62,7 @@ public class ClientboundSectionBlocksUpdatePacket implements MinecraftPacket { helper.writeVarInt(out, this.entries.length); for (BlockChangeEntry entry : this.entries) { short position = (short) ((entry.getPosition().getX() - (this.chunkX << 4)) << 8 | (entry.getPosition().getZ() - (this.chunkZ << 4)) << 4 | (entry.getPosition().getY() - (this.chunkY << 4))); - helper.writeVarLong(out, (long) entry.getBlock() << 12 | position); + helper.writeVarLong(out, (long) entry.getBlock() << 12 | (long) position); } } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java index a0575afd..adf95cde 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacket.java @@ -21,6 +21,8 @@ import net.kyori.adventure.text.Component; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; @Data @With @@ -30,24 +32,23 @@ public class ClientboundStatusResponsePacket implements MinecraftPacket { public ClientboundStatusResponsePacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException { JsonObject obj = new Gson().fromJson(helper.readString(in), JsonObject.class); - JsonObject ver = obj.get("version").getAsJsonObject(); - VersionInfo version = new VersionInfo(ver.get("name").getAsString(), ver.get("protocol").getAsInt()); + JsonElement desc = obj.get("description"); + Component description = DefaultComponentSerializer.get().serializer().fromJson(desc, Component.class); JsonObject plrs = obj.get("players").getAsJsonObject(); - GameProfile[] profiles = new GameProfile[0]; + List profiles = new ArrayList<>(); if (plrs.has("sample")) { JsonArray prof = plrs.get("sample").getAsJsonArray(); if (prof.size() > 0) { - profiles = new GameProfile[prof.size()]; for (int index = 0; index < prof.size(); index++) { JsonObject o = prof.get(index).getAsJsonObject(); - profiles[index] = new GameProfile(o.get("id").getAsString(), o.get("name").getAsString()); + profiles.add(new GameProfile(o.get("id").getAsString(), o.get("name").getAsString())); } } } PlayerInfo players = new PlayerInfo(plrs.get("max").getAsInt(), plrs.get("online").getAsInt(), profiles); - JsonElement desc = obj.get("description"); - Component description = DefaultComponentSerializer.get().serializer().fromJson(desc, Component.class); + JsonObject ver = obj.get("version").getAsJsonObject(); + VersionInfo version = new VersionInfo(ver.get("name").getAsString(), ver.get("protocol").getAsInt()); byte[] icon = null; if (obj.has("favicon")) { icon = this.stringToIcon(obj.get("favicon").getAsString()); @@ -66,7 +67,7 @@ public class ClientboundStatusResponsePacket implements MinecraftPacket { JsonObject plrs = new JsonObject(); plrs.addProperty("max", this.info.getPlayerInfo().getMaxPlayers()); plrs.addProperty("online", this.info.getPlayerInfo().getOnlinePlayers()); - if (this.info.getPlayerInfo().getPlayers().length > 0) { + if (this.info.getPlayerInfo().getPlayers().size() > 0) { JsonArray array = new JsonArray(); for (GameProfile profile : this.info.getPlayerInfo().getPlayers()) { JsonObject o = new JsonObject(); @@ -78,9 +79,9 @@ public class ClientboundStatusResponsePacket implements MinecraftPacket { plrs.add("sample", array); } - obj.add("version", ver); - obj.add("players", plrs); obj.add("description", new Gson().fromJson(DefaultComponentSerializer.get().serialize(this.info.getDescription()), JsonElement.class)); + obj.add("players", plrs); + obj.add("version", ver); if (this.info.getIconPng() != null) { obj.addProperty("favicon", this.iconToString(this.info.getIconPng())); } diff --git a/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java b/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java index 0e1a8291..664aaad1 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/MinecraftProtocolTest.java @@ -1,6 +1,5 @@ package com.github.steveice10.mc.protocol; -import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.status.PlayerInfo; @@ -27,6 +26,7 @@ import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.zip.GZIPInputStream; @@ -46,7 +46,7 @@ public class MinecraftProtocolTest { private static final ServerStatusInfo SERVER_INFO = new ServerStatusInfo( new VersionInfo(MinecraftCodec.CODEC.getMinecraftVersion(), MinecraftCodec.CODEC.getProtocolVersion()), - new PlayerInfo(100, 0, new GameProfile[0]), + new PlayerInfo(100, 0, new ArrayList<>()), Component.text("Hello world!"), null, false diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java index 71e10784..7fb97b39 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundSetEntityDataPacketTest.java @@ -2,7 +2,12 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound.level; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.*; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.LongEntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.packet.PacketTest; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityDataPacket; @@ -27,7 +32,7 @@ public class ClientboundSetEntityDataPacketTest extends PacketTest { new FloatEntityMetadata(3, MetadataType.FLOAT, 3.0f), new LongEntityMetadata(8, MetadataType.LONG, 123456789L), new ObjectEntityMetadata<>(5, MetadataType.POSITION, Vector3i.from(0, 1, 0)), - new ObjectEntityMetadata<>(2, MetadataType.BLOCK_STATE, OptionalInt.of(60)), + new ObjectEntityMetadata<>(2, MetadataType.BLOCK_STATE, 60), new ObjectEntityMetadata<>(6, MetadataType.DIRECTION, Direction.EAST), new ObjectEntityMetadata<>(7, MetadataType.OPTIONAL_VARINT, OptionalInt.of(1038)) }), diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacketTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacketTest.java index d4a12366..4c1064e3 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacketTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/status/clientbound/ClientboundStatusResponsePacketTest.java @@ -9,6 +9,8 @@ import com.github.steveice10.mc.protocol.packet.PacketTest; import net.kyori.adventure.text.Component; import org.junit.Before; +import java.util.ArrayList; +import java.util.Collections; import java.util.UUID; public class ClientboundStatusResponsePacketTest extends PacketTest { @@ -17,9 +19,9 @@ public class ClientboundStatusResponsePacketTest extends PacketTest { this.setPackets(new ClientboundStatusResponsePacket( new ServerStatusInfo( new VersionInfo(MinecraftCodec.CODEC.getMinecraftVersion(), MinecraftCodec.CODEC.getProtocolVersion()), - new PlayerInfo(100, 10, new GameProfile[]{ - new GameProfile(UUID.randomUUID(), "Username") - }), + new PlayerInfo(100, 10, new ArrayList<>( + Collections.singleton(new GameProfile(UUID.randomUUID(), "Username")) + )), Component.text("Description"), null, false diff --git a/src/test/resources/networkCodec.nbt b/src/test/resources/networkCodec.nbt index 26f80ad0e86460289f0b6a9a24b3de4f5cf13c35..705b6f6d93d9191fc9776561f167a42f76edcb68 100644 GIT binary patch literal 3625 zcmV+^4%YD>iwFP!00000|Lt8(j2uT5uJP>b&dz$h{@wN3PS%d&IB~)TSbp+nZ!n4x zQUVb<6)4Hc6YV9dS*Nh5l#@?kT?<~LimRRhn$g;+z?VCP9VeyA#O+rIB+$u zx~HeBx@)Fqe|j@JJ2^OUch7sTzVFq0uc}^mDhO53vP~UQ^KjjN#`magxY+lJ=akWm z-*w5L+w-W@##W1<;GYUwNjzp_c#2{x5;N$2QqHOPxmpwZhWK$LLw7IweFc6!2M;>f zCg_;@U=bamW+;A+Si~ldUqLhCP8luv9(K5eeaakTi*(U3aeZBgUiZlze;!p_?14}) zmzP1t5j4w*V-gR|)tKXhED$^IV9yI=Xe2JH64%3L$taQ$iiRZNM{MR3qsD9-J7zSt z!YE@~iY*C*?7`r6A~GJ;gYl?r-iXFzPzU~tI*n*>M@AXkrQWakx=lF84YF=h?pnCJ z9*L`<68F0n_*1FIEast^hKIWaG)sMK(OLnG3)ur;VJ*MGBv^{OgC!ETBUpUwHHg2z zu$+lu;kcWe0W+hZA=!Z)hqatq@Plz7{<0J$35F;+WKxty8Sg3CDs1aRTCq>(*bO@A z^0PY`G}kfwF%24opN+?BQWyyrg5^9n@Bum5%|!4?S&_Ag*I}MzYBF8{Ex5E{QODr8 zPEY~OIoNM`*eaCJBDSj(o-r)iXa-gm(VER14nr}xi#v`{wODN{ybpicGUC1{ zxptuNtoW^msmTjPbj)H6TEmvnB;iO3_h!-Y8e^VGVYtNLaFcBQJE}HT)j{@#N7|%c zx15NTwj5e#o?YpYP(+JxPfSaz#c7*_ur1p7j&f~ITrG(wyZ7(k{{RebS>RC}?Ab8# z1z~-SP~fE@Tr##ho*%24aT_(gfe@ zMkE%=#3G5<^Z;j2rB3g_vp$5mkgOFqlWR0aT#F}0ozhauJFP9<~%Nkf&2Mo{1l&WIWh z{*#h^sN`(@T5HD^^n$HqK{-;RUFe%0Zh)k!C$Q8kbN0}XqoJ;wfvVV;CD|C(aWrcW zX}Xt#XF%^B8deHqYO|#2b;bHXvozRC9|0|(BsM@QPsknDVxl;YOqkon9GdS-i*-r+ zSaob!k(zQYE-)ih=x6StxMj4lN3r8`t*?qFggWfBY2VQKoT8i1G1Q76@kLftae z+Q}qt1_eZ9*J3Up&G+@_9mwiJspm7JBO!Dwm-)5;y1opmUR4m0QefR9Sv zcxZ1!?rf-78*>}PAs($oMjg)unYo@8t)DcRZ`3WQ1S1RUpy78xiog=@}xzv12h(_L9)0O`;ZV;ynQwo zAc~+UHsArB0U*r4jfTe}OIG*6lC!EMuE%bJM^dXFQO@my5mM}6YCJoi&vem*6PAc) z(g8FS;s&c5$`<#9TpYCms=iu(RVdQd389dL!#9N3on?nChP_JdkZ!*v6 zuOS}RTNXaFmvc0fIKU!#=j2L0F(Oo=KTPnbN#cFJM{+S>uBRooU`^g-hdAlcYRd=V z$>rzOeJhlciACb5L*)(lNAsE2p%QIk3vU^Gs}%$DSS~~@gsNT@WA_Ik2P znXNmGRv(Zzx;Hf&4OMJfqVYuAeiboYMDu)0^m2&C6X)IgMYPcHFz3B1-+$w!B3i67 ziwgV0Yj2BdOC8ZbX4F}ucePa709o@{J9Nw#|CIK7clkEnnE|W8JC79@F-4lD6>ZZCx=V zgD;qjmH3cxn2HEcMf$qMmp z)(_=y41d+GCt)b2!D~NQf1o_`RW)(=WTKnudFi$lint&BmEU@oW zwv_4UXru+oJNMohYsAntqQZ)bSd%uI%E8F-DP}3mmQ~Dbs-7jCm_n9H%Rug?R`@zSL#A;%5x1pMQ*F*We-KK|!`GZAzlWtg5V)|z{p~|?AYiq4 zQ{An7AU8)(wKK+!9-EQj;fL=qLVlwRJ3(Dy@D8?J&09j*y%43~r+HUTfs#?S+!H%e z-+T9}hTWI$ej|h3XYSq}V|Ei2)u4Q16Kuwxlv&Gd8eSaCTWCT~Q}EbV{y4@YC8pq@ zmK8v(=`m&-Fq^D+OZH-BmYK}d48AO*c25pm(q?Pe_Gff3_v1u!Y5x*UukBDVW6%5M z73sU|n^$FJ_8gAVDp)S>SIfI<{C>8)E0y0vJFNT;`kWkAOk9$%vP=W2iH_eiblvZl z55juq@O8hhX$f@UqTyrO=zkaE;oRuEHkdxiqQIC8_P+VE31siaTPk}>A)%js-1SZ_WDzw={3vPf<(vrE^<+2~u=qQLeNWU7I#!rRJvm|Eq9Vr)wxL);^xw zsn=M)ta3dO`QMU@)a4{%YO;J{dQdp*pfH4tTg;93NzOY8?YAc|D!i|{xLOa&pP*tb%iv;}--gFXH-hcS+}!-?fGxqKCA-@d zyqbnJsbD)BgHMbgZs+eKKdXHoc~R0i;@33Jf9Zu>ru8Uj=Dxcq?P7Dlk(0zndp>y( z_Q@vm@PQ9$L6yU^&z!E>ck`+J`{IF=PGdVV=xR?SUH8=7pj3=0x_FbtUoHJ~W;T8O zrxS?SjbSymoK0I!?`;OP&fb`AN)6kTQkp0}GdWEZx80{Tq+Y(fl0hnd%{(xqsD+$x+NdDpz8aRQ&JJ}<-XX4^aM@?3#d@k(e@F)#l$LE`SzV(^EvsL&KRbml1>dR; vJ_WVsrl_S*JFi16ak_kcdQLj*bh*Q{A7HpK{Q$!@u|??r{B83UrGx+gZPgUz literal 2657 zcmV-n3ZC^JiwFP!00000|Lt5&j2uT5uJP>b&dz4Nws&o3?Idf*aZH>r0hXWGiM>WB za7hq1PN=Eru9+!scU7yZXU5}zaDw25#1SJA%wK>52cMCMZwSc|ClKO<5H}&c-90_+@pyjhzO237)o*zg!6+=d>e#Mnn&a9Cci zO3_sh-SAdH#f3}=^$_D_A>$BO=7?B`ffbVyPskEtR|#aSCnG`P30-2)$Rq6Z{|wusq#U|uYIF0|0$jleYvY2|d|1_^U zh;!ILRSR?1hTUo)t^!Kj>)OJ%N+z`_14|7Cy9Ka}J!oUI0OlMP+VUDyfu;Cxums}9 zg2jWZfxPL$axR3$L(nnOTxKZ?Hk+ze&`A#d;=tIM_(Gb|QHLmvV>D072QxPMWN0*U zsE4AtZ#j#h8=)pWArpx1aYXiN(9@wo78YuADN(I+LkFnEZYjV=sfx6XScfv(N~m}R zu;${1jfufw9f1N^A<%0vXctOg9Xd5E#uzqkG<#YW!Hz=-7p558g&ktlY-;ZN_r*^K z_ePaL1(P}^xYl9>>?rOTUN#0w6~GolzBEY8CS``Wyw8OyPcvG4#S2An*rp9^LfdE}-;%3u;DfWR z8`(DxwUHfgaWwp+ErRQmIh8&MMX)aJ$z)@t0g(IdvI`YPbl27 zg)4O+bA;t4Ov znPFd}A@mj^^a7P$pwOFW<`SsX@eMKD6M^8f_QkKLq=N*~K@#cL&iIcPQ%D!L*8;NS zSe2}TPF6uBOUYJ8bt_Pqrw(O^#TZlL#^QD|Q$n4LQ8<*QxPb{AopeVACYYnZjB=e8 zm@`G{?$@xSBwgOzxNk0 zYRwEsVMc;3$ z(&>v}(|1yiATyhWnD7M?Ig!@ZJmk2DNtZ`^a(W8N7VVHawC%mVcpsx9p>(k_!GtGN zx;R3@0m%@AZv1iq5qj(XM+!n$MZFFYI;FG%TBL5%j?h`h>QIiAkCh^w6WZxUa4M$Z zBp(=p)3<)IcsPNys8c3i*c55n#rt6uTgp+2aa(D3%x~3xpG=w&k zcL+WSwjE8>fb;-Gp^UEjbQ`zuU&U9C9rqy+{qE_ z!FQ~A$(DQddOc)MnawzmG?+lh&}dwF9BKUC-3tjczJ2rSBWS#Q^ZI}85jzhIK6U|iR%s#GmLX;s z9j|F5#oAMOtj#pmb`qI##YMw|xB&y6)~CVK#o;_D%Jub1qv;zzTRfVs-qvZ#5K!D@ zEi*#Y;e{gVn~O-)ExmQ15v44QHCi^t?9@GW0I3I@dYw8ArXypvpuYY7crac0>Yrx@ z(}#M4MQ>;-`ym{*At3{Zj^;h6*tT3BBH8uz5Nrid9m}DLLDj*;;vM9AMiblip!d5u zZhrdd;z4yavXgLIoe({r1eI7tw2^IhbIX^Rv zpJOUNmMzcf2h^N;nB>2v^gF@#-+eo_3HH9cwqQtRo!TNsEo2!{Ku_m@j=NT%iGV(n z13Km;#z9bw32=ON8cF!f@FW~)la_hMJ$HEc%YU4kbBDtkbiIQQ0U6I_?>s${Lk)dp z(ztl{&f-duBoNmnQ4 z`DqmU^C`(pRVj^^_9CveZs}VoTE|VP_zbthSL)7<*^+$hUd4zfdkv=-rhF{?(rbU1 z&tu_=Bh?Tzn*l)Q^S3aD?CokWy*On*n&sZ^m9#B@SfSue$_5LO3;9k->|GW47N0>) z1WAC>$0nM*mv%;>^o2kDYd({=a+cq2?V~tSFHIJy6QhuN^EdyUPo$nz-|9iGkqp}7WrELT#&TP0yEGZ4jv+?c;g;Da$3$`= zH@@rjx{BnjVTq1mSFV4M{wllSvk8fb_P+bu zAN>CB?|mL*aFyM1d2+5Y(qJidLgzsg$LT=kqVNcu?>L{GrQ<|2ntS%87Lb2Rv0e^++91H++H) zsI&}Ch8<2x!~;J!4G)a%RrWnFs?vkH;Q55CuZbMxgBM2%7~cs+1&KT1$v7X`y>Pc! zoSYYq#%_XcsD9s!wrqpT)4**p40QuXd~F(zcwvYm#+7 zWPm1aG_~XCujfF;I^z;32kXc7-^g)_wZ6F{?#ie$FxSAkl7kgHtRi8mL0QiRFkOAp PVFKX)Li8fU&u9Pu&Ug~u From ea82b973902f86ded487658ff5d4621a255468ad Mon Sep 17 00:00:00 2001 From: D3ATHBRINGER13 <53559772+D3ATHBRINGER13@users.noreply.github.com> Date: Sat, 25 Feb 2023 18:27:33 +0000 Subject: [PATCH 174/180] Update enums. --- .../mc/protocol/data/MagicValues.java | 14 ++++--- .../data/game/command/CommandParser.java | 1 + .../data/game/entity/EntityEvent.java | 3 +- .../data/game/entity/type/EntityType.java | 35 +++++++++-------- .../data/game/inventory/ContainerType.java | 1 + .../game/level/block/BlockEntityType.java | 4 +- .../protocol/data/game/recipe/RecipeType.java | 4 +- ...Data.java => LegacyUpgradeRecipeData.java} | 2 +- .../data/SmithingTransformRecipeData.java | 16 ++++++++ .../recipe/data/SmithingTrimRecipeData.java | 14 +++++++ .../ClientboundUpdateRecipesPacket.java | 38 ++++++++++++++++++- .../clientbound/ServerDeclareRecipesTest.java | 5 ++- 12 files changed, 109 insertions(+), 28 deletions(-) rename src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/{SmithingRecipeData.java => LegacyUpgradeRecipeData.java} (88%) create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTransformRecipeData.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTrimRecipeData.java diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java index 09fbee03..c132aa6b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/MagicValues.java @@ -259,10 +259,11 @@ public class MagicValues { register(ContainerType.LOOM, 17); register(ContainerType.MERCHANT, 18); register(ContainerType.SHULKER_BOX, 19); - register(ContainerType.SMITHING, 20); - register(ContainerType.SMOKER, 21); - register(ContainerType.CARTOGRAPHY, 22); - register(ContainerType.STONECUTTER, 23); + register(ContainerType.LEGACY_SMITHING, 20); + register(ContainerType.SMITHING, 21); + register(ContainerType.SMOKER, 22); + register(ContainerType.CARTOGRAPHY, 23); + register(ContainerType.STONECUTTER, 24); register(BrewingStandProperty.BREW_TIME, 0); @@ -472,6 +473,8 @@ public class MagicValues { register(RecipeType.CAMPFIRE_COOKING, "minecraft:campfire_cooking"); register(RecipeType.STONECUTTING, "minecraft:stonecutting"); register(RecipeType.SMITHING, "minecraft:smithing"); + register(RecipeType.SMITHING_TRANSFORM, "minecraft:smithing_transform"); + register(RecipeType.SMITHING_TRIM, "minecraft:smithing_trim"); register(CommandType.ROOT, 0); register(CommandType.LITERAL, 1); @@ -524,7 +527,8 @@ public class MagicValues { register(CommandParser.RESOURCE_KEY, 44); register(CommandParser.TEMPLATE_MIRROR, 45); register(CommandParser.TEMPLATE_ROTATION, 46); - register(CommandParser.UUID, 47); + register(CommandParser.HEIGHTMAP, 47); + register(CommandParser.UUID, 48); register(StringProperties.SINGLE_WORD, 0); register(StringProperties.QUOTABLE_PHRASE, 1); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java index 549b5767..acc0791e 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/CommandParser.java @@ -48,5 +48,6 @@ public enum CommandParser { RESOURCE_KEY, TEMPLATE_MIRROR, TEMPLATE_ROTATION, + HEIGHTMAP, UUID; } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/EntityEvent.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/EntityEvent.java index 24323a83..f4943b0c 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/EntityEvent.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/EntityEvent.java @@ -63,7 +63,8 @@ public enum EntityEvent { GOAT_STOP_LOWERING_HEAD, MAKE_POOF_PARTICLES, WARDEN_RECEIVE_SIGNAL, - WARDEN_SONIC_BOOM; + WARDEN_SONIC_BOOM, + SNIFFER_MAKE_SOUND; private static final EntityEvent[] VALUES = values(); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java index accd0b37..dc018942 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/type/EntityType.java @@ -9,32 +9,39 @@ public enum EntityType { BAT, BEE, BLAZE, + BLOCK_DISPLAY, BOAT, - CHEST_BOAT, - CAT, CAMEL, + CAT, CAVE_SPIDER, + CHEST_BOAT, + CHEST_MINECART, CHICKEN, COD, + COMMAND_BLOCK_MINECART, COW, CREEPER, DOLPHIN, DONKEY, DRAGON_FIREBALL, DROWNED, + EGG, ELDER_GUARDIAN, END_CRYSTAL, ENDER_DRAGON, + ENDER_PEARL, ENDERMAN, ENDERMITE, EVOKER, EVOKER_FANGS, + EXPERIENCE_BOTTLE, EXPERIENCE_ORB, EYE_OF_ENDER, FALLING_BLOCK, FIREWORK_ROCKET, FOX, FROG, + FURNACE_MINECART, GHAST, GIANT, GLOW_ITEM_FRAME, @@ -42,11 +49,14 @@ public enum EntityType { GOAT, GUARDIAN, HOGLIN, + HOPPER_MINECART, HORSE, HUSK, ILLUSIONER, + INTERACTION, IRON_GOLEM, ITEM, + ITEM_DISPLAY, ITEM_FRAME, FIREBALL, LEASH_KNOT, @@ -56,14 +66,8 @@ public enum EntityType { MAGMA_CUBE, MARKER, MINECART, - CHEST_MINECART, - COMMAND_BLOCK_MINECART, - FURNACE_MINECART, - HOPPER_MINECART, - SPAWNER_MINECART, - TNT_MINECART, - MULE, MOOSHROOM, + MULE, OCELOT, PAINTING, PANDA, @@ -74,7 +78,7 @@ public enum EntityType { PIGLIN_BRUTE, PILLAGER, POLAR_BEAR, - TNT, + POTION, PUFFERFISH, RABBIT, RAVAGER, @@ -87,20 +91,21 @@ public enum EntityType { SKELETON_HORSE, SLIME, SMALL_FIREBALL, + SNIFFER, SNOW_GOLEM, SNOWBALL, + SPAWNER_MINECART, SPECTRAL_ARROW, SPIDER, SQUID, STRAY, STRIDER, TADPOLE, - EGG, - ENDER_PEARL, - EXPERIENCE_BOTTLE, - POTION, - TRIDENT, + TEXT_DISPLAY, + TNT, + TNT_MINECART, TRADER_LLAMA, + TRIDENT, TROPICAL_FISH, TURTLE, VEX, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/inventory/ContainerType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/inventory/ContainerType.java index e89e186c..7e125d9b 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/inventory/ContainerType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/inventory/ContainerType.java @@ -21,6 +21,7 @@ public enum ContainerType { LOOM, MERCHANT, SHULKER_BOX, + LEGACY_SMITHING, SMITHING, SMOKER, CARTOGRAPHY, diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java index 51957c53..ae79baf5 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/BlockEntityType.java @@ -38,7 +38,9 @@ public enum BlockEntityType { SCULK_SENSOR, SCULK_CATALYST, SCULK_SHRIEKER, - CHISELED_BOOKSHELF; + CHISELED_BOOKSHELF, + SUSPICIOUS_SAND, + DECORATED_POT; private static final BlockEntityType[] VALUES = values(); diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java index 3322f58a..fc2b8cab 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java @@ -21,5 +21,7 @@ public enum RecipeType { SMOKING, CAMPFIRE_COOKING, STONECUTTING, - SMITHING + SMITHING, + SMITHING_TRANSFORM, + SMITHING_TRIM } diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/LegacyUpgradeRecipeData.java similarity index 88% rename from src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingRecipeData.java rename to src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/LegacyUpgradeRecipeData.java index c536d6ef..327f7fdd 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingRecipeData.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/LegacyUpgradeRecipeData.java @@ -8,7 +8,7 @@ import lombok.NonNull; @Data @AllArgsConstructor -public class SmithingRecipeData implements RecipeData { +public class LegacyUpgradeRecipeData implements RecipeData { private final @NonNull Ingredient base; private final @NonNull Ingredient addition; private final ItemStack result; diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTransformRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTransformRecipeData.java new file mode 100644 index 00000000..22ee325c --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTransformRecipeData.java @@ -0,0 +1,16 @@ +package com.github.steveice10.mc.protocol.data.game.recipe.data; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; + +@Data +@AllArgsConstructor +public class SmithingTransformRecipeData implements RecipeData { + private final @NonNull Ingredient template; + private final @NonNull Ingredient base; + private final @NonNull Ingredient addition; + private final ItemStack result; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTrimRecipeData.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTrimRecipeData.java new file mode 100644 index 00000000..5e822402 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/data/SmithingTrimRecipeData.java @@ -0,0 +1,14 @@ +package com.github.steveice10.mc.protocol.data.game.recipe.data; + +import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; + +@Data +@AllArgsConstructor +public class SmithingTrimRecipeData implements RecipeData { + private final @NonNull Ingredient template; + private final @NonNull Ingredient base; + private final @NonNull Ingredient addition; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java index f919708e..5123ca25 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java @@ -86,7 +86,24 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { Ingredient addition = helper.readRecipeIngredient(in); ItemStack result = helper.readItemStack(in); - data = new SmithingRecipeData(base, addition, result); + data = new LegacyUpgradeRecipeData(base, addition, result); + break; + } + case SMITHING_TRANSFORM: { + Ingredient template = helper.readRecipeIngredient(in); + Ingredient base = helper.readRecipeIngredient(in); + Ingredient addition = helper.readRecipeIngredient(in); + ItemStack result = helper.readItemStack(in); + + data = new SmithingTransformRecipeData(template, base, addition, result); + break; + } + case SMITHING_TRIM: { + Ingredient template = helper.readRecipeIngredient(in); + Ingredient base = helper.readRecipeIngredient(in); + Ingredient addition = helper.readRecipeIngredient(in); + + data = new SmithingTrimRecipeData(template, base, addition); break; } default: { @@ -161,13 +178,30 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { break; } case SMITHING: { - SmithingRecipeData data = (SmithingRecipeData) recipe.getData(); + LegacyUpgradeRecipeData data = (LegacyUpgradeRecipeData) recipe.getData(); helper.writeRecipeIngredient(out, data.getBase()); helper.writeRecipeIngredient(out, data.getAddition()); helper.writeItemStack(out, data.getResult()); break; } + case SMITHING_TRANSFORM: { + SmithingTransformRecipeData data = (SmithingTransformRecipeData) recipe.getData(); + + helper.writeRecipeIngredient(out, data.getTemplate()); + helper.writeRecipeIngredient(out, data.getBase()); + helper.writeRecipeIngredient(out, data.getAddition()); + helper.writeItemStack(out, data.getResult()); + break; + } + case SMITHING_TRIM: { + SmithingTrimRecipeData data = (SmithingTrimRecipeData) recipe.getData(); + + helper.writeRecipeIngredient(out, data.getTemplate()); + helper.writeRecipeIngredient(out, data.getBase()); + helper.writeRecipeIngredient(out, data.getAddition()); + break; + } default: { SimpleCraftingRecipeData data = (SimpleCraftingRecipeData) recipe.getData(); diff --git a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java index 839585fd..0e994590 100644 --- a/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java +++ b/src/test/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java @@ -8,7 +8,8 @@ import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.mc.protocol.data.game.recipe.data.CookedRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData; -import com.github.steveice10.mc.protocol.data.game.recipe.data.SmithingRecipeData; +import com.github.steveice10.mc.protocol.data.game.recipe.data.LegacyUpgradeRecipeData; +import com.github.steveice10.mc.protocol.data.game.recipe.data.SmithingTransformRecipeData; import com.github.steveice10.mc.protocol.data.game.recipe.data.StoneCuttingRecipeData; import com.github.steveice10.mc.protocol.packet.PacketTest; import org.junit.Before; @@ -93,7 +94,7 @@ public class ServerDeclareRecipesTest extends PacketTest { new Recipe( RecipeType.SMITHING, "Recipe5", - new SmithingRecipeData( + new LegacyUpgradeRecipeData( new Ingredient(new ItemStack[]{ new ItemStack(10) }), From 65f00c4387ca34372f1d4714468f7457a37f4423 Mon Sep 17 00:00:00 2001 From: D3ATHBRINGER13 <53559772+D3ATHBRINGER13@users.noreply.github.com> Date: Sat, 25 Feb 2023 23:39:15 +0000 Subject: [PATCH 175/180] Prevent the use of boxing --- .../mc/protocol/data/game/entity/metadata/MetadataType.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java index 08b8301c..5fb9ec63 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/entity/metadata/MetadataType.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.OptionalInt; import java.util.UUID; @Getter @@ -43,7 +44,7 @@ public class MetadataType { public static final MetadataType DIRECTION = new MetadataType<>(MinecraftCodecHelper::readDirection, MinecraftCodecHelper::writeDirection, ObjectEntityMetadata::new); public static final MetadataType> OPTIONAL_UUID = new MetadataType<>(optionalReader(MinecraftCodecHelper::readUUID), optionalWriter(MinecraftCodecHelper::writeUUID), ObjectEntityMetadata::new); public static final IntMetadataType BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); - public static final MetadataType> OPTIONAL_BLOCK_STATE = new MetadataType<>(optionalReader(MinecraftCodecHelper::readVarInt), optionalWriter(MinecraftCodecHelper::writeVarInt), ObjectEntityMetadata::new); + public static final IntMetadataType OPTIONAL_BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); public static final MetadataType NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readTag, MinecraftCodecHelper::writeTag, ObjectEntityMetadata::new); public static final MetadataType PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new); public static final MetadataType VILLAGER_DATA = new MetadataType<>(MinecraftCodecHelper::readVillagerData, MinecraftCodecHelper::writeVillagerData, ObjectEntityMetadata::new); From 12e372303e5c0b9c2185cbb564d99e2a0232b1d6 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:38:29 +0000 Subject: [PATCH 176/180] Exclude packetlib from javadoc for now --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index c88a5ea2..d8e85398 100644 --- a/pom.xml +++ b/pom.xml @@ -220,6 +220,7 @@ public false + com.github.steveice10.packetlib:com.github.steveice10.packetlib.*:com.github.steveice10.packetlib.*.* From 81131c469d2d6b965bf9225461435727c6bba820 Mon Sep 17 00:00:00 2001 From: Kas-tle <26531652+Kas-tle@users.noreply.github.com> Date: Fri, 10 Mar 2023 00:14:13 +0000 Subject: [PATCH 177/180] No longer depend on packetlib --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index d8e85398..30d8a35d 100644 --- a/pom.xml +++ b/pom.xml @@ -87,12 +87,6 @@ 1.4 compile - - com.github.steveice10 - packetlib - 3.0.1 - compile - com.github.GeyserMC mcauthlib @@ -220,7 +214,6 @@ public false - com.github.steveice10.packetlib:com.github.steveice10.packetlib.*:com.github.steveice10.packetlib.*.* From 8252330c7d07b6811bfaf0bdd98c8832ed9e69dd Mon Sep 17 00:00:00 2001 From: D3ATHBRINGER13 <53559772+D3ATHBRINGER13@users.noreply.github.com> Date: Sat, 11 Mar 2023 01:01:09 +0000 Subject: [PATCH 178/180] Some minor fixes --- .../data/game/command/properties/TimeProperties.java | 10 ++++++++++ .../data/game/level/block/value/NoteBlockValue.java | 4 ++++ .../game/level/block/value/NoteBlockValueType.java | 11 +++++++++++ .../mc/protocol/data/game/recipe/RecipeType.java | 3 ++- .../ingame/clientbound/ClientboundCommandsPacket.java | 6 ++++++ .../level/ClientboundBlockEventPacket.java | 5 ++++- 6 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/command/properties/TimeProperties.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValue.java create mode 100644 src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValueType.java diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/command/properties/TimeProperties.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/properties/TimeProperties.java new file mode 100644 index 00000000..0895fd0a --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/command/properties/TimeProperties.java @@ -0,0 +1,10 @@ +package com.github.steveice10.mc.protocol.data.game.command.properties; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class TimeProperties implements CommandProperties { + private final int min; +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValue.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValue.java new file mode 100644 index 00000000..267613c9 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValue.java @@ -0,0 +1,4 @@ +package com.github.steveice10.mc.protocol.data.game.level.block.value; + +public class NoteBlockValue implements BlockValue { +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValueType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValueType.java new file mode 100644 index 00000000..0983fdc7 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/level/block/value/NoteBlockValueType.java @@ -0,0 +1,11 @@ +package com.github.steveice10.mc.protocol.data.game.level.block.value; + +public enum NoteBlockValueType implements BlockValueType { + PLAY_NOTE; + + private static final NoteBlockValueType[] VALUES = values(); + + public static NoteBlockValueType from(int id) { + return VALUES[id]; + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java index 9b950371..64adee74 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java +++ b/src/main/java/com/github/steveice10/mc/protocol/data/game/recipe/RecipeType.java @@ -29,7 +29,8 @@ public enum RecipeType { STONECUTTING, SMITHING, SMITHING_TRANSFORM, - SMITHING_TRIM; + SMITHING_TRIM, + CRAFTING_DECORATED_POT; private final String resourceLocation; diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java index d5278cf1..1b343fea 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundCommandsPacket.java @@ -130,6 +130,9 @@ public class ClientboundCommandsPacket implements MinecraftPacket { case SCORE_HOLDER: properties = new ScoreHolderProperties(in.readBoolean()); break; + case TIME: + properties = new TimeProperties(in.readInt()); + break; case RESOURCE_OR_TAG: case RESOURCE_OR_TAG_KEY: case RESOURCE: @@ -298,6 +301,9 @@ public class ClientboundCommandsPacket implements MinecraftPacket { case SCORE_HOLDER: out.writeBoolean(((ScoreHolderProperties) node.getProperties()).isAllowMultiple()); break; + case TIME: + out.writeInt(((TimeProperties) node.getProperties()).getMin()); + break; case RESOURCE: case RESOURCE_OR_TAG: helper.writeString(out, ((ResourceProperties) node.getProperties()).getRegistryKey()); diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundBlockEventPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundBlockEventPacket.java index 5c79e02d..0a3a6833 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundBlockEventPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundBlockEventPacket.java @@ -40,7 +40,10 @@ public class ClientboundBlockEventPacket implements MinecraftPacket { this.blockId = helper.readVarInt(in); // TODO: Handle this in MinecraftCodecHelper - if (this.blockId == STICKY_PISTON || this.blockId == PISTON) { + if (this.blockId == NOTE_BLOCK) { + this.type = NoteBlockValueType.from(type); + this.value = new NoteBlockValue(); + } else if (this.blockId == STICKY_PISTON || this.blockId == PISTON) { this.type = PistonValueType.from(type); this.value = new PistonValue(Direction.from(Math.abs((value & 7) % 6))); } else if (this.blockId == MOB_SPAWNER) { From 60547d54fd5b67a596183cfc4198c462ca750331 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 12 Mar 2023 23:51:36 -0400 Subject: [PATCH 179/180] Various changes --- .../mc/protocol/ClientListener.java | 4 +-- .../clientbound/ClientboundBundlePacket.java | 20 +++++++++++++ .../entity/ClientboundDamageEventPacket.java | 4 +++ .../level/ClientboundChunksBiomesPacket.java | 4 +++ .../github/steveice10/packetlib/Session.java | 21 +++++++++++-- .../event/session/DisconnectedEvent.java | 21 ++++--------- .../event/session/DisconnectingEvent.java | 21 ++++--------- .../packetlib/tcp/TcpBundlerUnpacker.java | 30 +++++++++++++++++++ .../packetlib/tcp/TcpClientSession.java | 2 ++ .../steveice10/packetlib/tcp/TcpSession.java | 17 +++++++++-- 10 files changed, 107 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundBundlePacket.java create mode 100644 src/main/java/com/github/steveice10/packetlib/tcp/TcpBundlerUnpacker.java diff --git a/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java b/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java index 94c5ea29..48b85d8f 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java +++ b/src/main/java/com/github/steveice10/mc/protocol/ClientListener.java @@ -86,7 +86,7 @@ public class ClientListener extends SessionAdapter { } else if (packet instanceof ClientboundGameProfilePacket) { protocol.setState(ProtocolState.GAME); } else if (packet instanceof ClientboundLoginDisconnectPacket) { - session.disconnect(((ClientboundLoginDisconnectPacket) packet).getReason().toString()); + session.disconnect(((ClientboundLoginDisconnectPacket) packet).getReason()); } else if (packet instanceof ClientboundLoginCompressionPacket) { session.setCompressionThreshold(((ClientboundLoginCompressionPacket) packet).getThreshold(), false); } @@ -112,7 +112,7 @@ public class ClientListener extends SessionAdapter { if (packet instanceof ClientboundKeepAlivePacket && session.getFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, true)) { session.send(new ServerboundKeepAlivePacket(((ClientboundKeepAlivePacket) packet).getPingId())); } else if (packet instanceof ClientboundDisconnectPacket) { - session.disconnect(((ClientboundDisconnectPacket) packet).getReason().toString()); + session.disconnect(((ClientboundDisconnectPacket) packet).getReason()); } } } diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundBundlePacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundBundlePacket.java new file mode 100644 index 00000000..7389b000 --- /dev/null +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundBundlePacket.java @@ -0,0 +1,20 @@ +package com.github.steveice10.mc.protocol.packet.ingame.clientbound; + +import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.io.IOException; +import java.util.List; + +@Data +@AllArgsConstructor +public class ClientboundBundlePacket implements MinecraftPacket { + private final List packets; + + @Override + public void serialize(ByteBuf buf, MinecraftCodecHelper helper) throws IOException { + } +} diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java index 82f121dd..d7f80fa8 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/entity/ClientboundDamageEventPacket.java @@ -4,8 +4,12 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.nukkitx.math.vector.Vector3d; import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; import org.jetbrains.annotations.Nullable; +@Data +@AllArgsConstructor public class ClientboundDamageEventPacket implements MinecraftPacket { private final int entityId; private final int sourceTypeId; diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java index f61724b6..eba47102 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/level/ClientboundChunksBiomesPacket.java @@ -4,10 +4,14 @@ import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; import com.github.steveice10.mc.protocol.data.game.chunk.ChunkBiomeData; import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; import java.util.ArrayList; import java.util.List; +@Data +@AllArgsConstructor public class ClientboundChunksBiomesPacket implements MinecraftPacket { private final List chunkBiomeData; diff --git a/src/main/java/com/github/steveice10/packetlib/Session.java b/src/main/java/com/github/steveice10/packetlib/Session.java index 1627c455..e1d1163d 100644 --- a/src/main/java/com/github/steveice10/packetlib/Session.java +++ b/src/main/java/com/github/steveice10/packetlib/Session.java @@ -6,6 +6,8 @@ import com.github.steveice10.packetlib.event.session.SessionEvent; import com.github.steveice10.packetlib.event.session.SessionListener; import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.PacketProtocol; +import net.kyori.adventure.text.Component; +import org.jetbrains.annotations.Nullable; import java.net.SocketAddress; import java.util.List; @@ -246,7 +248,7 @@ public interface Session { * * @param reason Reason for disconnecting. */ - public void disconnect(String reason); + void disconnect(@Nullable String reason); /** * Disconnects the session. @@ -254,5 +256,20 @@ public interface Session { * @param reason Reason for disconnecting. * @param cause Throwable responsible for disconnecting. */ - public void disconnect(String reason, Throwable cause); + void disconnect(@Nullable String reason, Throwable cause); + + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + */ + void disconnect(@Nullable Component reason); + + /** + * Disconnects the session. + * + * @param reason Reason for disconnecting. + * @param cause Throwable responsible for disconnecting. + */ + void disconnect(@Nullable Component reason, Throwable cause); } diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java index 463ed042..35aacba9 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectedEvent.java @@ -1,24 +1,15 @@ package com.github.steveice10.packetlib.event.session; import com.github.steveice10.packetlib.Session; +import net.kyori.adventure.text.Component; /** * Called when the session is disconnected. */ public class DisconnectedEvent implements SessionEvent { - private Session session; - private String reason; - private Throwable cause; - - /** - * Creates a new DisconnectedEvent instance. - * - * @param session Session being disconnected. - * @param reason Reason for the session to disconnect. - */ - public DisconnectedEvent(Session session, String reason) { - this(session, reason, null); - } + private final Session session; + private final Component reason; + private final Throwable cause; /** * Creates a new DisconnectedEvent instance. @@ -27,7 +18,7 @@ public class DisconnectedEvent implements SessionEvent { * @param reason Reason for the session to disconnect. * @param cause Throwable that caused the disconnect. */ - public DisconnectedEvent(Session session, String reason, Throwable cause) { + public DisconnectedEvent(Session session, Component reason, Throwable cause) { this.session = session; this.reason = reason; this.cause = cause; @@ -47,7 +38,7 @@ public class DisconnectedEvent implements SessionEvent { * * @return The event's reason. */ - public String getReason() { + public Component getReason() { return this.reason; } diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java index 0c9929e4..267959e9 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/DisconnectingEvent.java @@ -1,24 +1,15 @@ package com.github.steveice10.packetlib.event.session; import com.github.steveice10.packetlib.Session; +import net.kyori.adventure.text.Component; /** * Called when the session is about to disconnect. */ public class DisconnectingEvent implements SessionEvent { - private Session session; - private String reason; - private Throwable cause; - - /** - * Creates a new DisconnectingEvent instance. - * - * @param session Session being disconnected. - * @param reason Reason for the session to disconnect. - */ - public DisconnectingEvent(Session session, String reason) { - this(session, reason, null); - } + private final Session session; + private final Component reason; + private final Throwable cause; /** * Creates a new DisconnectingEvent instance. @@ -27,7 +18,7 @@ public class DisconnectingEvent implements SessionEvent { * @param reason Reason for the session to disconnect. * @param cause Throwable that caused the disconnect. */ - public DisconnectingEvent(Session session, String reason, Throwable cause) { + public DisconnectingEvent(Session session, Component reason, Throwable cause) { this.session = session; this.reason = reason; this.cause = cause; @@ -47,7 +38,7 @@ public class DisconnectingEvent implements SessionEvent { * * @return The event's reason. */ - public String getReason() { + public Component getReason() { return this.reason; } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpBundlerUnpacker.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpBundlerUnpacker.java new file mode 100644 index 00000000..0a4602b0 --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpBundlerUnpacker.java @@ -0,0 +1,30 @@ +package com.github.steveice10.packetlib.tcp; + +import com.github.steveice10.mc.protocol.codec.MinecraftPacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundBundlePacket; +import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.ArrayList; +import java.util.List; + +public class TcpBundlerUnpacker extends MessageToMessageDecoder { + private List currentPackets; + + @Override + protected void decode(ChannelHandlerContext ctx, MinecraftPacket packet, List out) throws Exception { + if (currentPackets != null) { + if (packet.getClass() == ClientboundDelimiterPacket.class) { + out.add(new ClientboundBundlePacket(currentPackets)); + currentPackets = null; + } else { + currentPackets.add(packet); + } + } else { + if (packet.getClass() == ClientboundDelimiterPacket.class) { + currentPackets = new ArrayList<>(2); + } + } + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java index fee4aa93..37d848a3 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpClientSession.java @@ -315,5 +315,7 @@ public class TcpClientSession extends TcpSession { DATAGRAM_CHANNEL_CLASS = NioDatagramChannel.class; break; } + + Runtime.getRuntime().addShutdownHook(new Thread(() -> EVENT_LOOP_GROUP.shutdownGracefully())); } } diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java index 0a9ddf1e..94352489 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpSession.java @@ -15,6 +15,7 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutException; import io.netty.handler.timeout.WriteTimeoutHandler; +import net.kyori.adventure.text.Component; import javax.annotation.Nullable; import java.net.ConnectException; @@ -258,11 +259,21 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void disconnect(String reason) { + this.disconnect(Component.text(reason)); + } + + @Override + public void disconnect(String reason, Throwable cause) { + this.disconnect(Component.text(reason), cause); + } + + @Override + public void disconnect(Component reason) { this.disconnect(reason, null); } @Override - public void disconnect(final String reason, final Throwable cause) { + public void disconnect(final Component reason, final Throwable cause) { if (this.disconnected) { return; } @@ -273,9 +284,9 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp this.callEvent(new DisconnectingEvent(this, reason, cause)); this.channel.flush().close().addListener((ChannelFutureListener) future -> callEvent(new DisconnectedEvent(TcpSession.this, - reason != null ? reason : "Connection closed.", cause))); + reason != null ? reason : Component.text("Connection closed."), cause))); } else { - this.callEvent(new DisconnectedEvent(this, reason != null ? reason : "Connection closed.", cause)); + this.callEvent(new DisconnectedEvent(this, reason != null ? reason : Component.text("Connection closed."), cause)); } } From 70b0fa1bd42c28c3d7db886a92e613709dc9e1e2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:48:11 -0400 Subject: [PATCH 180/180] Prepare for release protocol --- .../github/steveice10/mc/protocol/codec/MinecraftCodec.java | 4 ++-- .../scoreboard/ClientboundSetPlayerTeamPacket.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java index 00d2d279..cbe25e13 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java +++ b/src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodec.java @@ -199,9 +199,9 @@ public class MinecraftCodec { } public static final PacketCodec CODEC = PacketCodec.builder() - .protocolVersion((1 << 30) | 120) + .protocolVersion(762) .helper(() -> new MinecraftCodecHelper(LEVEL_EVENTS, SOUND_NAMES)) - .minecraftVersion("1.19.4 Pre-release 1") + .minecraftVersion("1.19.4") .state(ProtocolState.HANDSHAKE, PacketStateCodec.builder() .registerServerboundPacket(0x00, ClientIntentionPacket.class, ClientIntentionPacket::new) ) diff --git a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetPlayerTeamPacket.java b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetPlayerTeamPacket.java index d36b29a9..edd4b73e 100644 --- a/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetPlayerTeamPacket.java +++ b/src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetPlayerTeamPacket.java @@ -2,7 +2,6 @@ package com.github.steveice10.mc.protocol.packet.ingame.clientbound.scoreboard; import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper; import com.github.steveice10.mc.protocol.codec.MinecraftPacket; -import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer; import com.github.steveice10.mc.protocol.data.game.scoreboard.CollisionRule; import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamAction; @@ -11,6 +10,7 @@ import io.netty.buffer.ByteBuf; import lombok.*; import net.kyori.adventure.text.Component; +import javax.annotation.Nullable; import java.io.IOException; import java.util.Arrays; @@ -26,8 +26,8 @@ public class ClientboundSetPlayerTeamPacket implements MinecraftPacket { private final Component suffix; private final boolean friendlyFire; private final boolean seeFriendlyInvisibles; - private final NameTagVisibility nameTagVisibility; - private final CollisionRule collisionRule; + private final @Nullable NameTagVisibility nameTagVisibility; + private final @Nullable CollisionRule collisionRule; private final TeamColor color; private final String[] players;