diff --git a/api/src/main/java/fr/atlasworld/network/api/networking/HandshakeInformation.java b/api/src/main/java/fr/atlasworld/network/api/networking/HandshakeInformation.java new file mode 100644 index 0000000..0b37257 --- /dev/null +++ b/api/src/main/java/fr/atlasworld/network/api/networking/HandshakeInformation.java @@ -0,0 +1,87 @@ +package fr.atlasworld.network.api.networking; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import org.jetbrains.annotations.NotNull; +/** + * Represents information exchanged during the handshake. + * + * @param the type of the handshake value + */ +public final class HandshakeInformation { + private final @NotNull T value; + private final @NotNull Function factory; + + public HandshakeInformation(@NotNull T value, @NotNull Function factory) { + Preconditions.checkArgument(value != null && factory != null, "Handshake information and string factory may not be null!"); + + this.value = value; + this.factory = factory; + } + + public @NotNull T getValue() { + return value; + } + + /** + * Returns a string representation of the current data. + * This will use the provided function to transform the object into string + * before sending it through the handshake packet. + * + * @return A string representation of the object. + */ + public String asString() { + return this.factory.apply(this.value); + } + + @Override + public String toString() { + return "handshake_data[data:" + this.asString() + "]"; + } + + // Static Fields + + /** + * Returns a new instance of HandshakeInformation with the provided information. + * + * @param information The information to be included in the handshake. + * @return A new instance of HandshakeInformation with the provided information and resource key. + */ + public static HandshakeInformation text(@NotNull String information) { + return new HandshakeInformation<>(information, data -> data); + } + + /** + * Returns a new instance of HandshakeInformation with the provided information. + * + * @param information The information to be included in the handshake. + * @return A new instance of HandshakeInformation with the provided information and resource key. + */ + public static HandshakeInformation integer(int information) { + return new HandshakeInformation<>(information, String::valueOf); + } + + /** + * Returns a new instance of HandshakeInformation with the provided information. + * + * @param information The information to be included in the handshake. + * @return A new instance of HandshakeInformation with the provided information and resource key. + */ + public static HandshakeInformation asLong(long information) { + return new HandshakeInformation<>(information, String::valueOf); + } + + + /** + * Returns a new instance of HandshakeInformation with the provided value. + *

+ * String transformation will use the default {@link Object#toString()} method. + * + * @param value The value to be included in the handshake. + * @param The type of the value. + * @return A new instance of HandshakeInformation with the provided value. + */ + public static HandshakeInformation of(@NotNull T value) { + return new HandshakeInformation<>(value, Object::toString); + } +} diff --git a/api/src/main/java/fr/atlasworld/network/api/networking/Socket.java b/api/src/main/java/fr/atlasworld/network/api/networking/Socket.java index ca59ec5..763f383 100644 --- a/api/src/main/java/fr/atlasworld/network/api/networking/Socket.java +++ b/api/src/main/java/fr/atlasworld/network/api/networking/Socket.java @@ -1,12 +1,6 @@ package fr.atlasworld.network.api.networking; -import com.google.gson.JsonElement; import fr.atlasworld.network.api.concurrent.action.FutureAction; -import fr.atlasworld.network.api.module.Module; -import fr.atlasworld.network.api.networking.packet.NetworkPacket; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Supplier; /** * Abstract API Socket. Handles networking for AtlasNetwork @@ -27,31 +21,4 @@ public interface Socket { * @return true if running */ boolean running(); - - /** - * Register information that will be sent to the client when the handshake process starts. - * Client will receive a json object containing all the system information. - * Your data can be found as {@code "your_module_id": }. - *

- * Don't send any private or user information! At this state encryption is not yet established with the client. - * - * @param module the id of the module will be used as key when sending data to the client. - * @param data data to attach to the request - */ - void registerHandshakeInfo(Module module, JsonElement data); - - /** - * Register a packet in the active state registry. - * - * @param module module that registers the packet. - * @param builder builder of the packet. - */ - void registerPacket(@NotNull Module module, @NotNull Supplier builder); - - /** - * Unregister packet from the active state registry. - * - * @param key key of the packet. - */ - void unregisterPacket(@NotNull String key); } diff --git a/api/src/main/java/fr/atlasworld/network/api/networking/event/HandshakeDataInjectionEvent.java b/api/src/main/java/fr/atlasworld/network/api/networking/event/HandshakeDataInjectionEvent.java new file mode 100644 index 0000000..eeafd55 --- /dev/null +++ b/api/src/main/java/fr/atlasworld/network/api/networking/event/HandshakeDataInjectionEvent.java @@ -0,0 +1,48 @@ +package fr.atlasworld.network.api.networking.event; + +import fr.atlasworld.network.api.event.Event; +import fr.atlasworld.network.api.module.Module; +import fr.atlasworld.network.api.networking.HandshakeInformation; +import fr.atlasworld.network.api.registry.ResourceKey; +import org.jetbrains.annotations.NotNull; + +/** + * Event called when modules are supposed to inject their data into the handshake packet. + * The packet is in plaintext nor is the client trusted at this state. + * Don't send any sensitive information through here. + */ +public interface HandshakeDataInjectionEvent extends Event { + + /** + * Injects the provided information into the handshake using the specified key. + * + * @param key The key associated with the information. + * @param information The information to be injected into the handshake. + */ + void inject(@NotNull String key, @NotNull HandshakeInformation information); + + /** + * Injects the provided information into the handshake using the specified module. + * + * @param module The module associated with the information. + * @param information The information to be injected into the handshake. + */ + void inject(@NotNull Module module, @NotNull HandshakeInformation information); + + /** + * Injects the provided information into the handshake packet associated with the given resource key. + * + * @param key The resource key that identifies the handshake packet. + * @param information The information to be injected into the handshake packet. + */ + void inject(@NotNull ResourceKey key, @NotNull HandshakeInformation information); + + /** + * Clears the data of the handshake packet. + *

+ * Important internal data such as Protocol version or System version are not stored in the handshake packet. + * So you can clear the data without worrying breaking AtlasNetwork's protocol. + * But don't forget you may not be the only one injecting data in the packet and this could lead to unexpected issues. + */ + void clear(); +} diff --git a/api/src/main/java/fr/atlasworld/network/api/networking/event/PacketRegistrationEvent.java b/api/src/main/java/fr/atlasworld/network/api/networking/event/PacketRegistrationEvent.java new file mode 100644 index 0000000..9f271fd --- /dev/null +++ b/api/src/main/java/fr/atlasworld/network/api/networking/event/PacketRegistrationEvent.java @@ -0,0 +1,7 @@ +package fr.atlasworld.network.api.networking.event; + +import fr.atlasworld.network.api.networking.packet.NetworkPacket; +import fr.atlasworld.network.api.registry.event.RegistrationEvent; + +public interface PacketRegistrationEvent extends RegistrationEvent { +} diff --git a/api/src/main/java/fr/atlasworld/network/api/networking/packet/NetworkPacket.java b/api/src/main/java/fr/atlasworld/network/api/networking/packet/NetworkPacket.java index e3cc6e4..f2afd19 100644 --- a/api/src/main/java/fr/atlasworld/network/api/networking/packet/NetworkPacket.java +++ b/api/src/main/java/fr/atlasworld/network/api/networking/packet/NetworkPacket.java @@ -9,11 +9,6 @@ */ public interface NetworkPacket { - /** - * Get the unique identifier of the packet. - */ - @NotNull String getKey(); - /** * Decodes and process received requests. * diff --git a/api/src/test/java/fr/atlasworld/network/api/test/TestModule.java b/api/src/test/java/fr/atlasworld/network/api/test/TestModule.java index 8201a7a..5b07f44 100644 --- a/api/src/test/java/fr/atlasworld/network/api/test/TestModule.java +++ b/api/src/test/java/fr/atlasworld/network/api/test/TestModule.java @@ -11,6 +11,7 @@ import fr.atlasworld.network.api.test.command.TestCommands; import fr.atlasworld.network.api.test.configuration.TestConfiguration; import fr.atlasworld.network.api.test.configuration.TestConfigurationSchema; +import fr.atlasworld.network.api.test.event.NetworkListener; import fr.atlasworld.network.api.test.event.ServerListener; import fr.atlasworld.network.api.test.services.database.LocalDatabaseService; import org.jetbrains.annotations.NotNull; @@ -39,6 +40,7 @@ protected void onActivate(@NotNull ModuleActivationContext ctx) { FileManager fileManager = ctx.getServer().getFileManager(); ctx.getServer().getModuleManager().registerListener(this, new ServerListener()); + ctx.getServer().getModuleManager().registerListener(this, new NetworkListener()); ctx.getServer().getModuleManager().registerListener(this, new TestCommands()); ConfigurationReader testConfReader = diff --git a/api/src/test/java/fr/atlasworld/network/api/test/event/NetworkListener.java b/api/src/test/java/fr/atlasworld/network/api/test/event/NetworkListener.java new file mode 100644 index 0000000..f5402a9 --- /dev/null +++ b/api/src/test/java/fr/atlasworld/network/api/test/event/NetworkListener.java @@ -0,0 +1,17 @@ +package fr.atlasworld.network.api.test.event; + +import fr.atlasworld.network.api.event.EventHandler; +import fr.atlasworld.network.api.event.EventListener; +import fr.atlasworld.network.api.networking.HandshakeInformation; +import fr.atlasworld.network.api.networking.event.HandshakeDataInjectionEvent; +import fr.atlasworld.network.api.test.TestModule; + +public class NetworkListener implements EventListener { + + @EventHandler + private void onHandshake(HandshakeDataInjectionEvent event) { + event.inject("my_unique_id", HandshakeInformation.text("my_custom_info")); + + TestModule.LOGGER.info("Successfully injected handshake data."); + } +} diff --git a/api/src/test/java/fr/atlasworld/network/api/test/networking/TestPackets.java b/api/src/test/java/fr/atlasworld/network/api/test/networking/TestPackets.java new file mode 100644 index 0000000..2636e1a --- /dev/null +++ b/api/src/test/java/fr/atlasworld/network/api/test/networking/TestPackets.java @@ -0,0 +1,14 @@ +package fr.atlasworld.network.api.test.networking; + +import fr.atlasworld.network.api.networking.packet.NetworkPacket; +import fr.atlasworld.network.api.registry.Register; +import fr.atlasworld.network.api.registry.RegistryObject; +import fr.atlasworld.network.api.test.TestModule; +import fr.atlasworld.network.api.test.networking.packets.MyCustomPacket; + +public class TestPackets { + private static final Register PACKETS = new Register<>(TestModule.MODULE); + + public static final RegistryObject MY_CUSTOM_PACKET = PACKETS.register(MyCustomPacket.KEY.getKey(), + MyCustomPacket::new); +} diff --git a/api/src/test/java/fr/atlasworld/network/api/test/networking/packets/MyCustomPacket.java b/api/src/test/java/fr/atlasworld/network/api/test/networking/packets/MyCustomPacket.java new file mode 100644 index 0000000..51b3ecf --- /dev/null +++ b/api/src/test/java/fr/atlasworld/network/api/test/networking/packets/MyCustomPacket.java @@ -0,0 +1,58 @@ +package fr.atlasworld.network.api.test.networking.packets; + +import fr.atlasworld.network.api.networking.ConnectionSource; +import fr.atlasworld.network.api.networking.exception.packet.PacketExecutionException; +import fr.atlasworld.network.api.networking.packet.NetworkPacket; +import fr.atlasworld.network.api.networking.packet.PacketByteBuf; +import fr.atlasworld.network.api.registry.ResourceKey; +import fr.atlasworld.network.api.test.TestModule; +import org.jetbrains.annotations.NotNull; + +public class MyCustomPacket implements NetworkPacket { + public static final ResourceKey KEY = new ResourceKey(TestModule.MODULE, "myCustomPacket"); + + private int myInt; + private String myString; + private boolean myBoolean; + + @Override + public @NotNull String getKey() { + return KEY.toString(); + } + + public MyCustomPacket() { + + } + + public MyCustomPacket(int myInt, String myString, boolean myBoolean) { + this.myInt = myInt; + this.myString = myString; + this.myBoolean = myBoolean; + } + + @Override + public void decode(@NotNull ConnectionSource source, @NotNull PacketByteBuf buffer) throws PacketExecutionException { + this.myInt = buffer.readInt(); + this.myString = buffer.readString(); + this.myBoolean = buffer.readBoolean(); + } + + @Override + public void encode(@NotNull PacketByteBuf buffer) throws PacketExecutionException { + buffer.writeInt(this.myInt); + buffer.writeString(buffer.readString()); + buffer.writeBoolean(buffer.readBoolean()); + } + + public int getMyInt() { + return myInt; + } + + public String getMyString() { + return myString; + } + + public boolean isMyBoolean() { + return myBoolean; + } +} diff --git a/src/main/java/fr/atlasworld/network/core/AtlasNetwork.java b/src/main/java/fr/atlasworld/network/core/AtlasNetwork.java index 94ed273..1716e03 100644 --- a/src/main/java/fr/atlasworld/network/core/AtlasNetwork.java +++ b/src/main/java/fr/atlasworld/network/core/AtlasNetwork.java @@ -101,6 +101,7 @@ public void start() { // Events Listener SystemModuleManager.INSTANCE.registerListener(this, new Commands()); + this.socket.register(); // Register Packets and Handshake info this.console.register(); // Register commands & stuff LOGGER.info("Starting AtlasNetwork.."); diff --git a/src/main/java/fr/atlasworld/network/core/console/SystemConsole.java b/src/main/java/fr/atlasworld/network/core/console/SystemConsole.java index e32a495..4073cda 100644 --- a/src/main/java/fr/atlasworld/network/core/console/SystemConsole.java +++ b/src/main/java/fr/atlasworld/network/core/console/SystemConsole.java @@ -35,7 +35,7 @@ public SystemConsole(CommandDispatcher dispatcher) { public void register() { SystemModuleManager.INSTANCE.callEvent(new CommandRegistrationEventImpl()); - NetworkRegistries.COMMAND.getAllEntries() + NetworkRegistries.COMMANDS.getAllEntries() .forEach(command -> this.dispatcher.register(command.getCommand())); } diff --git a/src/main/java/fr/atlasworld/network/core/console/event/CommandRegistrationEventImpl.java b/src/main/java/fr/atlasworld/network/core/console/event/CommandRegistrationEventImpl.java index 1099cfc..834cdcd 100644 --- a/src/main/java/fr/atlasworld/network/core/console/event/CommandRegistrationEventImpl.java +++ b/src/main/java/fr/atlasworld/network/core/console/event/CommandRegistrationEventImpl.java @@ -3,23 +3,13 @@ import fr.atlasworld.network.api.command.Command; import fr.atlasworld.network.api.command.CommandSource; import fr.atlasworld.network.api.command.event.CommandRegistrationEvent; -import fr.atlasworld.network.api.registry.Register; -import fr.atlasworld.network.api.registry.Registry; import fr.atlasworld.network.core.registry.NetworkRegistries; +import fr.atlasworld.network.core.registry.event.SimpleRegistrationEvent; -public class CommandRegistrationEventImpl implements CommandRegistrationEvent { - @Override - public void register(Register> register) { - register.getEntries().forEach((key, value) -> { - NetworkRegistries.COMMAND.register(key, value.get()); - }); +public class CommandRegistrationEventImpl extends SimpleRegistrationEvent> + implements CommandRegistrationEvent { - register.getObjects().values().forEach(regObj -> - regObj.updateReference(NetworkRegistries.COMMAND)); - } - - @Override - public Registry> getRegistry() { - return NetworkRegistries.COMMAND; + public CommandRegistrationEventImpl() { + super(NetworkRegistries.COMMANDS); } } diff --git a/src/main/java/fr/atlasworld/network/core/logging/LogUtils.java b/src/main/java/fr/atlasworld/network/core/logging/LogUtils.java index 51ba6ef..b4bd913 100644 --- a/src/main/java/fr/atlasworld/network/core/logging/LogUtils.java +++ b/src/main/java/fr/atlasworld/network/core/logging/LogUtils.java @@ -11,6 +11,8 @@ public class LogUtils { private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); private static final Logger LOGGER = LogUtils.getLogger(); + public static final Logger CODE_LINTING_LOGGER = LoggerFactory.getLogger("Code-Linting"); + public static Logger getLogger() { return LoggerFactory.getLogger(STACK_WALKER.getCallerClass().getSimpleName()); } diff --git a/src/main/java/fr/atlasworld/network/core/networking/event/HandshakeDataInjectionEventImpl.java b/src/main/java/fr/atlasworld/network/core/networking/event/HandshakeDataInjectionEventImpl.java new file mode 100644 index 0000000..b140326 --- /dev/null +++ b/src/main/java/fr/atlasworld/network/core/networking/event/HandshakeDataInjectionEventImpl.java @@ -0,0 +1,47 @@ +package fr.atlasworld.network.core.networking.event; + +import com.google.common.base.Preconditions; +import com.google.gson.JsonObject; +import fr.atlasworld.network.api.module.Module; +import fr.atlasworld.network.api.networking.HandshakeInformation; +import fr.atlasworld.network.api.networking.event.HandshakeDataInjectionEvent; +import fr.atlasworld.network.api.registry.ResourceKey; +import fr.atlasworld.network.core.logging.LogUtils; +import org.jetbrains.annotations.NotNull; + +public class HandshakeDataInjectionEventImpl implements HandshakeDataInjectionEvent { + private final JsonObject dataStore; + + public HandshakeDataInjectionEventImpl(JsonObject dataStore) { + this.dataStore = dataStore; + } + + @Override + public void inject(@NotNull String key, @NotNull HandshakeInformation information) { + Preconditions.checkArgument(key != null && information != null, "Key and information may not be null!"); + + if (this.dataStore.has(key)) + LogUtils.CODE_LINTING_LOGGER.debug("WARN: Handshake information with '{}' has already been registered. Overriding data.", key); + + this.dataStore.addProperty(key, information.asString()); + } + + @Override + public void inject(@NotNull Module module, @NotNull HandshakeInformation information) { + Preconditions.checkArgument(module != null, "Module may not be null!"); + + this.inject(module.getMeta().getId(), information); + } + + @Override + public void inject(@NotNull ResourceKey key, @NotNull HandshakeInformation information) { + Preconditions.checkArgument(key != null, "Key may not be null!"); + + this.inject(key.toString(), information); + } + + @Override + public void clear() { + + } +} diff --git a/src/main/java/fr/atlasworld/network/core/networking/event/PacketRegistrationEventImpl.java b/src/main/java/fr/atlasworld/network/core/networking/event/PacketRegistrationEventImpl.java new file mode 100644 index 0000000..3d4eeab --- /dev/null +++ b/src/main/java/fr/atlasworld/network/core/networking/event/PacketRegistrationEventImpl.java @@ -0,0 +1,30 @@ +package fr.atlasworld.network.core.networking.event; + +import fr.atlasworld.network.api.networking.event.PacketRegistrationEvent; +import fr.atlasworld.network.api.networking.packet.NetworkPacket; +import fr.atlasworld.network.api.registry.Register; +import fr.atlasworld.network.api.registry.Registry; +import fr.atlasworld.network.core.registry.NetworkRegistries; + +public class PacketRegistrationEventImpl implements PacketRegistrationEvent { + + @Override + public void register(Register register) { + register.getEntries().forEach((key, value) -> { + NetworkPacket packet = value.get(); + + if (!packet.getKey().equals(key.toString())) + throw new IllegalArgumentException("Packet key and registered key does not match!"); + + NetworkRegistries.PACKETS.register(key, value); + }); + + register.getObjects().values().forEach(regObj -> + regObj.updateReference(NetworkRegistries.PACKETS)); + } + + @Override + public Registry getRegistry() { + return NetworkRegistries.PACKETS; + } +} diff --git a/src/main/java/fr/atlasworld/network/core/networking/handler/PacketHandler.java b/src/main/java/fr/atlasworld/network/core/networking/handler/PacketHandler.java new file mode 100644 index 0000000..222c833 --- /dev/null +++ b/src/main/java/fr/atlasworld/network/core/networking/handler/PacketHandler.java @@ -0,0 +1,6 @@ +package fr.atlasworld.network.core.networking.handler; + +import io.netty.channel.ChannelInboundHandlerAdapter; + +public class PacketHandler extends ChannelInboundHandlerAdapter { +} diff --git a/src/main/java/fr/atlasworld/network/core/networking/handler/SocketInitializer.java b/src/main/java/fr/atlasworld/network/core/networking/handler/SocketInitializer.java index 9fe398a..f0a07bc 100644 --- a/src/main/java/fr/atlasworld/network/core/networking/handler/SocketInitializer.java +++ b/src/main/java/fr/atlasworld/network/core/networking/handler/SocketInitializer.java @@ -14,7 +14,6 @@ import fr.atlasworld.network.core.networking.security.encryption.SystemEncryptionManager; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; -import io.netty.handler.timeout.IdleStateHandler; import org.jetbrains.annotations.NotNull; public class SocketInitializer extends ChannelInitializer { diff --git a/src/main/java/fr/atlasworld/network/core/networking/packet/RequestFailPacket.java b/src/main/java/fr/atlasworld/network/core/networking/packet/RequestFailPacket.java index 158267e..0649a56 100644 --- a/src/main/java/fr/atlasworld/network/core/networking/packet/RequestFailPacket.java +++ b/src/main/java/fr/atlasworld/network/core/networking/packet/RequestFailPacket.java @@ -4,11 +4,13 @@ import fr.atlasworld.network.api.networking.exception.NetworkingException; import fr.atlasworld.network.api.networking.packet.NetworkPacket; import fr.atlasworld.network.api.networking.packet.PacketByteBuf; +import fr.atlasworld.network.api.registry.ResourceKey; import fr.atlasworld.network.core.logging.LogUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; public class RequestFailPacket implements NetworkPacket { + private static final Logger LOGGER = LogUtils.getLogger(); private String message; @@ -27,11 +29,6 @@ public RequestFailPacket(NetworkingException cause) { this.closeConnection = cause.closeConnection(); } - @Override - public @NotNull String getKey() { - return "request_fail"; - } - @Override public void decode(@NotNull ConnectionSource source, @NotNull PacketByteBuf buffer) { this.message = buffer.readString(); diff --git a/src/main/java/fr/atlasworld/network/core/networking/packet/SystemInfoPacket.java b/src/main/java/fr/atlasworld/network/core/networking/packet/SystemInfoPacket.java index d1872fe..406845f 100644 --- a/src/main/java/fr/atlasworld/network/core/networking/packet/SystemInfoPacket.java +++ b/src/main/java/fr/atlasworld/network/core/networking/packet/SystemInfoPacket.java @@ -4,40 +4,37 @@ import fr.atlasworld.network.api.networking.ConnectionSource; import fr.atlasworld.network.api.networking.packet.NetworkPacket; import fr.atlasworld.network.api.networking.packet.PacketByteBuf; +import fr.atlasworld.network.api.registry.ResourceKey; +import fr.atlasworld.network.api.server.AtlasNetworkServer; import fr.atlasworld.network.api.util.NetworkVersion; import fr.atlasworld.network.core.AtlasNetwork; -import fr.atlasworld.network.core.networking.socket.SystemSocket; +import fr.atlasworld.network.core.networking.event.HandshakeDataInjectionEventImpl; import org.jetbrains.annotations.NotNull; import java.security.PublicKey; public class SystemInfoPacket implements NetworkPacket { + public static final SystemInfoPacket INSTANCE; static { AtlasNetwork server = AtlasNetwork.getInstance(); NetworkVersion version = server.getVersion(); - SystemSocket socket = server.getSocket(); PublicKey publicKey = server.getSecurityManager().getSessionPublicKey(); - INSTANCE = new SystemInfoPacket(version.getProtocolVersion(), version.getVersion(), socket.getHandshakeInfo(), publicKey); + INSTANCE = new SystemInfoPacket(version.getProtocolVersion(), version.getVersion(), publicKey, server); } private final int protocolVersion; private final String systemVersion; - private final JsonObject handshakeInformation; private final PublicKey publicKey; + private final AtlasNetworkServer server; - private SystemInfoPacket(int protocolVersion, String systemVersion, JsonObject handshakeInformation, PublicKey publicKey) { + private SystemInfoPacket(int protocolVersion, String systemVersion, PublicKey publicKey, AtlasNetworkServer server) { this.protocolVersion = protocolVersion; this.systemVersion = systemVersion; - this.handshakeInformation = handshakeInformation; this.publicKey = publicKey; - } - - @Override - public @NotNull String getKey() { - return "sys_info"; + this.server = server; } @Override @@ -47,9 +44,13 @@ public void decode(@NotNull ConnectionSource source, @NotNull PacketByteBuf buf) @Override public void encode(@NotNull PacketByteBuf buffer) { + JsonObject handshakeInformation = new JsonObject(); + + this.server.getModuleManager().callEvent(new HandshakeDataInjectionEventImpl(handshakeInformation)); + buffer.writeInt(this.protocolVersion) .writeString(this.systemVersion) - .writeString(this.handshakeInformation.toString()) + .writeString(handshakeInformation.toString()) .writeBytes(this.publicKey.getEncoded()); } @@ -61,10 +62,6 @@ public String getSystemVersion() { return systemVersion; } - public JsonObject getHandshakeInformation() { - return handshakeInformation; - } - public PublicKey getPublicKey() { return publicKey; } diff --git a/src/main/java/fr/atlasworld/network/core/networking/packet/registry/SystemPacketRegistry.java b/src/main/java/fr/atlasworld/network/core/networking/packet/registry/SystemPacketRegistry.java deleted file mode 100644 index 1f1702d..0000000 --- a/src/main/java/fr/atlasworld/network/core/networking/packet/registry/SystemPacketRegistry.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.atlasworld.network.core.networking.packet.registry; - -import fr.atlasworld.network.api.networking.ConnectionSource; -import fr.atlasworld.network.api.networking.exception.packet.PacketExecutionException; -import fr.atlasworld.network.api.networking.exception.packet.UnknownPacketException; -import fr.atlasworld.network.api.networking.packet.NetworkPacket; -import fr.atlasworld.network.api.networking.packet.PacketByteBuf; -import fr.atlasworld.network.api.networking.packet.PacketRegistry; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -public class SystemPacketRegistry implements PacketRegistry { - - private final Map> registeredMap = new ConcurrentHashMap<>(); - - @Override - public void register(@NotNull Supplier supplier) { - NetworkPacket packet = supplier.get(); - - if (this.registeredMap.containsKey(packet.getKey())) - throw new IllegalArgumentException(packet.getKey() + " has already been registered."); - - this.registeredMap.put(packet.getKey(), supplier); - } - - - @Override - public void unregister(@NotNull String key) { - if (!this.registeredMap.containsKey(key)) - throw new IllegalArgumentException(key + " is not registered."); - - this.registeredMap.remove(key); - } - - /** - * Handles and processes the packet. - *

- * Side Effect: The buffer index will be changed and released. - * - * @param buffer buffer to process. - * @param source source connection. - * @throws PacketExecutionException if an unhandled exception got thrown while processing packet. - * @throws UnknownPacketException if the received packet is unknown. - */ - public void handle(PacketByteBuf buffer, ConnectionSource source) throws UnknownPacketException, PacketExecutionException { - final String id = buffer.readString(); - - if (!this.registeredMap.containsKey(id)) - throw new UnknownPacketException(id); - - try { - NetworkPacket packet = this.registeredMap.get(id).get(); - packet.decode(source, buffer); - } catch (Throwable cause) { - throw new PacketExecutionException("Packet could not be processed.", cause, PacketExecutionException.SERVER_ERROR, id); - } - } -} diff --git a/src/main/java/fr/atlasworld/network/core/networking/socket/SystemSocket.java b/src/main/java/fr/atlasworld/network/core/networking/socket/SystemSocket.java index 32333e0..9334bae 100644 --- a/src/main/java/fr/atlasworld/network/core/networking/socket/SystemSocket.java +++ b/src/main/java/fr/atlasworld/network/core/networking/socket/SystemSocket.java @@ -1,20 +1,15 @@ package fr.atlasworld.network.core.networking.socket; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import fr.atlasworld.network.api.concurrent.action.FutureAction; import fr.atlasworld.network.api.concurrent.action.SimpleFutureAction; -import fr.atlasworld.network.api.module.Module; import fr.atlasworld.network.api.networking.Socket; -import fr.atlasworld.network.api.networking.packet.NetworkPacket; -import fr.atlasworld.network.api.networking.packet.PacketRegistry; -import fr.atlasworld.network.api.security.SecurityManager; +import fr.atlasworld.network.api.networking.event.PacketRegistrationEvent; import fr.atlasworld.network.api.server.AtlasNetworkServer; import fr.atlasworld.network.core.concurrent.action.ActionUtilities; import fr.atlasworld.network.core.file.configuration.SocketConfiguration; import fr.atlasworld.network.core.logging.LogUtils; +import fr.atlasworld.network.core.networking.event.PacketRegistrationEventImpl; import fr.atlasworld.network.core.networking.handler.SocketInitializer; -import fr.atlasworld.network.core.networking.packet.registry.SystemPacketRegistry; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; @@ -22,24 +17,22 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; -import java.util.function.Supplier; - public class SystemSocket implements Socket { - public static final PacketRegistry PACKET_REGISTRY = new SystemPacketRegistry(); private static final Logger LOGGER = LogUtils.getLogger(); private final SocketConfiguration socketConfiguration; private final EventLoopGroup bossGroup, workerGroup; private final ServerBootstrap bootstrap; - private final JsonObject handshakeInfo; + private final AtlasNetworkServer server; private boolean running = false; private Channel channel; public SystemSocket(AtlasNetworkServer server) { - this.socketConfiguration = server.getFileManager() + this.server = server; + + this.socketConfiguration = this.server.getFileManager() .registerConfiguration(new SocketConfiguration.SocketConfigurationSchema()) .readElseDefault(); @@ -56,9 +49,12 @@ public SystemSocket(AtlasNetworkServer server) { .childOption(ChannelOption.AUTO_CLOSE, false) // Do not close on failure .group(this.bossGroup, this.workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new SocketInitializer(server, server.getSecurityManager())); + .childHandler(new SocketInitializer(this.server, this.server.getSecurityManager())); + } - this.handshakeInfo = new JsonObject(); + public void register() { + PacketRegistrationEvent event = new PacketRegistrationEventImpl(); + this.server.getModuleManager().callEvent(event); } public FutureAction start() { @@ -111,34 +107,4 @@ public FutureAction stop() { public boolean running() { return this.running; } - - @Override - public void registerHandshakeInfo(Module module, JsonElement data) { - if (this.running) - throw new IllegalStateException("Handshake information must be registered before the socket started."); - - String id = module.getMeta().getId(); - if (this.handshakeInfo.has(id)) - throw new IllegalArgumentException("Handshake information has already been registered for '" + id + "'."); - - this.handshakeInfo.add(id, data); - } - - public JsonObject getHandshakeInfo() { - return handshakeInfo; - } - - @Override - public void registerPacket(@NotNull Module module, @NotNull Supplier builder) { - NetworkPacket packet = builder.get(); - - PACKET_REGISTRY.register(builder); - - module.deactivationFuture().whenDone(((unused, throwable) -> this.unregisterPacket(packet.getKey()))); - } - - @Override - public void unregisterPacket(@NotNull String key) { - PACKET_REGISTRY.unregister(key); - } } diff --git a/src/main/java/fr/atlasworld/network/core/registry/NetworkRegistries.java b/src/main/java/fr/atlasworld/network/core/registry/NetworkRegistries.java index ead1329..e26f106 100644 --- a/src/main/java/fr/atlasworld/network/core/registry/NetworkRegistries.java +++ b/src/main/java/fr/atlasworld/network/core/registry/NetworkRegistries.java @@ -2,9 +2,13 @@ import fr.atlasworld.network.api.command.Command; import fr.atlasworld.network.api.command.CommandSource; +import fr.atlasworld.network.api.networking.HandshakeInformation; +import fr.atlasworld.network.api.networking.packet.NetworkPacket; import fr.atlasworld.network.api.registry.ResourceKey; import fr.atlasworld.network.api.registry.SimpleRegistry; +import fr.atlasworld.network.core.registry.registries.PacketRegistry; public class NetworkRegistries { - public static final SimpleRegistry> COMMAND = new SimpleRegistry<>(new ResourceKey("core", "command")); + public static final SimpleRegistry> COMMANDS = new SimpleRegistry<>(new ResourceKey("core", "command")); + public static final PacketRegistry PACKETS = new PacketRegistry(); } diff --git a/src/main/java/fr/atlasworld/network/core/registry/event/SimpleRegistrationEvent.java b/src/main/java/fr/atlasworld/network/core/registry/event/SimpleRegistrationEvent.java new file mode 100644 index 0000000..4bddb80 --- /dev/null +++ b/src/main/java/fr/atlasworld/network/core/registry/event/SimpleRegistrationEvent.java @@ -0,0 +1,29 @@ +package fr.atlasworld.network.core.registry.event; + +import fr.atlasworld.network.api.registry.Register; +import fr.atlasworld.network.api.registry.Registry; +import fr.atlasworld.network.api.registry.SimpleRegistry; +import fr.atlasworld.network.api.registry.event.RegistrationEvent; + +public class SimpleRegistrationEvent implements RegistrationEvent { + private final SimpleRegistry registry; + + protected SimpleRegistrationEvent(SimpleRegistry registry) { + this.registry = registry; + } + + @Override + public void register(Register register) { + register.getEntries().forEach((key, value) -> { + this.registry.register(key, value.get()); + }); + + register.getObjects().values().forEach(regObj -> + regObj.updateReference(this.registry)); + } + + @Override + public Registry getRegistry() { + return this.registry; + } +} diff --git a/src/main/java/fr/atlasworld/network/core/registry/registries/PacketRegistry.java b/src/main/java/fr/atlasworld/network/core/registry/registries/PacketRegistry.java new file mode 100644 index 0000000..819d571 --- /dev/null +++ b/src/main/java/fr/atlasworld/network/core/registry/registries/PacketRegistry.java @@ -0,0 +1,54 @@ +package fr.atlasworld.network.core.registry.registries; + +import fr.atlasworld.network.api.networking.packet.NetworkPacket; +import fr.atlasworld.network.api.registry.Registry; +import fr.atlasworld.network.api.registry.ResourceKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +public class PacketRegistry implements Registry { + public static final ResourceKey REGISTRY_KEY = new ResourceKey("networking", "packets"); + + private final Map> registeredPackets; + + public PacketRegistry() { + this.registeredPackets = new HashMap<>(); + } + + @Override + public @NotNull ResourceKey getRegistryKey() { + return PacketRegistry.REGISTRY_KEY; + } + + @Override + public boolean contains(ResourceKey resourceKey) { + return this.registeredPackets.containsKey(resourceKey); + } + + @Override + public @Nullable NetworkPacket get(ResourceKey resourceKey) { + if (!this.contains(resourceKey)) + return null; + + return this.registeredPackets.get(resourceKey).get(); + } + + @Override + public @NotNull Optional asOptional(ResourceKey resourceKey) { + return Optional.ofNullable(this.get(resourceKey)); + } + + public void register(ResourceKey key, Supplier sup) { + this.registeredPackets.put(key, sup); + } + + public Collection> getAllEntries() { + return this.registeredPackets.values(); + } +}