package net.ME1312.SubServers.Bungee.Network; import net.ME1312.SubServers.Bungee.Library.Exception.IllegalPacketException; import net.ME1312.SubServers.Bungee.Library.Util; import net.ME1312.SubServers.Bungee.Library.Version.Version; import net.ME1312.SubServers.Bungee.Network.Packet.*; import net.ME1312.SubServers.Bungee.SubPlugin; import org.json.JSONObject; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; /** * SubDataServer Class */ public final class SubDataServer { private static int MAX_QUEUE = 64; private static HashMap, String> pOut = new HashMap, String>(); private static HashMap> pIn = new HashMap>(); private static List allowedAddresses = new ArrayList(); private static boolean defaults = false; private HashMap clients = new HashMap(); private ServerSocket server; private Encryption encryption; protected SubPlugin plugin; public enum Encryption { NONE, AES, AES_128, AES_192, AES_256, } /** * SubData Server Instance * * @param plugin SubPlugin * @param port Port * @param address Bind * @param encryption Encryption Type * @throws IOException */ public SubDataServer(SubPlugin plugin, int port, InetAddress address, Encryption encryption) throws IOException { if (Util.isNull(plugin, port, encryption, MAX_QUEUE)) throw new NullPointerException(); if (address == null) { server = new ServerSocket(port, MAX_QUEUE); allowConnection(InetAddress.getByName("127.0.0.1")); } else { server = new ServerSocket(port, MAX_QUEUE, address); allowConnection(address); } this.plugin = plugin; this.encryption = encryption; if (!defaults) loadDefaults(); } private void loadDefaults() { defaults = true; for (String s : plugin.config.get().getSection("Settings").getSection("SubData").getStringList("Allowed-Connections", new ArrayList())) { try { allowedAddresses.add(InetAddress.getByName(s)); } catch (Exception e) { e.printStackTrace(); } } plugin.getPluginManager().registerListener(null, new PacketOutRunEvent(plugin)); registerPacket(new PacketAuthorization(plugin), "Authorization"); registerPacket(new PacketCommandServer(plugin), "SubCommandServer"); registerPacket(new PacketCreateServer(plugin), "SubCreateServer"); registerPacket(new PacketDownloadHostInfo(plugin), "SubDownloadHostInfo"); registerPacket(new PacketDownloadLang(plugin), "SubDownloadLang"); registerPacket(new PacketDownloadNetworkList(plugin), "SubDownloadNetworkList"); registerPacket(new PacketDownloadPlayerList(plugin), "SubDownloadPlayerList"); registerPacket(new PacketDownloadProxyInfo(plugin), "SubDownloadProxyInfo"); registerPacket(new PacketDownloadServerInfo(plugin), "SubDownloadServerInfo"); registerPacket(new PacketDownloadServerList(plugin), "SubDownloadServerList"); registerPacket(new PacketEditServer(plugin), "SubEditServer"); registerPacket(new PacketExAddServer(), "SubExAddServer"); registerPacket(new PacketExConfigureHost(plugin), "SubExConfigureHost"); registerPacket(new PacketExCreateServer(null), "SubExCreateServer"); registerPacket(new PacketExDeleteServer(), "SubExDeleteServer"); registerPacket(new PacketExRemoveServer(), "SubExRemoveServer"); registerPacket(new PacketExUpdateServer(plugin), "SubExUpdateServer"); registerPacket(new PacketInExLogMessage(), "SubExLogMessage"); registerPacket(new PacketInExRequestQueue(plugin), "SubExRequestQueue"); registerPacket(new PacketLinkExHost(plugin), "SubLinkExHost"); registerPacket(new PacketLinkServer(plugin), "SubLinkServer"); registerPacket(new PacketListenLog(plugin), "SubListenLog"); registerPacket(new PacketStartServer(plugin), "SubStartServer"); registerPacket(new PacketStopServer(plugin), "SubStopServer"); registerPacket(new PacketTeleportPlayer(plugin), "SubTeleportPlayer"); registerPacket(PacketAuthorization.class, "Authorization"); registerPacket(PacketCommandServer.class, "SubCommandServer"); registerPacket(PacketCreateServer.class, "SubCreateServer"); registerPacket(PacketDownloadHostInfo.class, "SubDownloadHostInfo"); registerPacket(PacketDownloadLang.class, "SubDownloadLang"); registerPacket(PacketDownloadNetworkList.class, "SubDownloadNetworkList"); registerPacket(PacketDownloadPlayerList.class, "SubDownloadPlayerList"); registerPacket(PacketDownloadProxyInfo.class, "SubDownloadProxyInfo"); registerPacket(PacketDownloadServerInfo.class, "SubDownloadServerInfo"); registerPacket(PacketDownloadServerList.class, "SubDownloadServerList"); registerPacket(PacketEditServer.class, "SubEditServer"); registerPacket(PacketExAddServer.class, "SubExAddServer"); registerPacket(PacketExConfigureHost.class, "SubExConfigureHost"); registerPacket(PacketExCreateServer.class, "SubExCreateServer"); registerPacket(PacketExDeleteServer.class, "SubExDeleteServer"); registerPacket(PacketExRemoveServer.class, "SubExRemoveServer"); registerPacket(PacketExUpdateServer.class, "SubExUpdateServer"); registerPacket(PacketLinkExHost.class, "SubLinkExHost"); registerPacket(PacketLinkServer.class, "SubLinkServer"); registerPacket(PacketListenLog.class, "SubListenLog"); registerPacket(PacketOutRunEvent.class, "SubRunEvent"); registerPacket(PacketOutReset.class, "SubReset"); registerPacket(PacketStartServer.class, "SubStartServer"); registerPacket(PacketStopServer.class, "SubStopServer"); registerPacket(PacketTeleportPlayer.class, "SubTeleportPlayer"); } /** * Gets the Server Socket * * @return Server Socket */ public ServerSocket getServer() { return server; } /** * Gets the Server's Encryption method * * @return Encryption method */ public Encryption getEncryption() { return encryption; } /** * Add a Client to the Network * * @param socket Client to add * @throws IOException */ public Client addClient(Socket socket) throws IOException { if (Util.isNull(socket)) throw new NullPointerException(); if (allowedAddresses.contains(socket.getInetAddress())) { Client client = new Client(this, socket); System.out.println("SubData > " + client.getAddress().toString() + " has connected"); clients.put(client.getAddress().toString(), client); return client; } else { System.out.println("SubData > " + socket.getInetAddress().toString() + " attempted to connect, but isn't white-listed"); socket.close(); return null; } } /** * Grabs a Client from the Network * * @param socket Socket to search * @return Client */ public Client getClient(Socket socket) { if (Util.isNull(socket)) throw new NullPointerException(); return clients.get(new InetSocketAddress(socket.getInetAddress(), socket.getPort()).toString()); } /** * Grabs a Client from the Network * * @param address Address to search * @return Client */ public Client getClient(InetSocketAddress address) { if (Util.isNull(address)) throw new NullPointerException(); return clients.get(address.toString()); } /** * Grabs a Client from the Network * * @param address Address to search * @return Client */ public Client getClient(String address) { if (Util.isNull(address)) throw new NullPointerException(); return clients.get(address); } /** * Grabs all the Clients on the Network * * @return Client List */ public Collection getClients() { return clients.values(); } /** * Remove a Client from the Network * * @param client Client to Kick * @throws IOException */ public void removeClient(Client client) throws IOException { if (Util.isNull(client)) throw new NullPointerException(); SocketAddress address = client.getAddress(); if (clients.keySet().contains(address.toString())) { clients.remove(address.toString()); client.disconnect(); System.out.println("SubData > " + client.getAddress().toString() + " has disconnected"); } } /** * Remove a Client from the Network * * @param address Address to Kick * @throws IOException */ public void removeClient(InetSocketAddress address) throws IOException { if (Util.isNull(address)) throw new NullPointerException(); Client client = clients.get(address.toString()); if (clients.keySet().contains(address.toString())) { clients.remove(address.toString()); client.disconnect(); System.out.println("SubData > " + client.getAddress().toString() + " has disconnected"); } } /** * Remove a Client from the Network * * @param address Address to Kick * @throws IOException */ public void removeClient(String address) throws IOException { if (Util.isNull(address)) throw new NullPointerException(); Client client = clients.get(address); if (clients.keySet().contains(address)) { clients.remove(address); client.disconnect(); System.out.println("SubData > " + client.getAddress().toString() + " has disconnected"); } } /** * Register PacketIn to the Network * * @param packet PacketIn to register * @param handle Handle to Bind */ public static void registerPacket(PacketIn packet, String handle) { if (Util.isNull(packet, handle)) throw new NullPointerException(); List list = (pIn.keySet().contains(handle))?pIn.get(handle):new ArrayList(); if (!list.contains(packet)) { list.add(packet); pIn.put(handle, list); } } /** * Unregister PacketIn from the Network * * @param packet PacketIn to unregister */ public static void unregisterPacket(PacketIn packet) { if (Util.isNull(packet)) throw new NullPointerException(); List search = new ArrayList(); search.addAll(pIn.keySet()); for (String handle : search) if (pIn.get(handle).contains(packet)) { List list = pIn.get(handle); list.remove(packet); if (list.isEmpty()) { pIn.remove(handle); } else { pIn.put(handle, list); } } } /** * Register PacketOut to the Network * * @param packet PacketOut to register * @param handle Handle to bind */ public static void registerPacket(Class packet, String handle) { if (Util.isNull(packet, handle)) throw new NullPointerException(); pOut.put(packet, handle); } /** * Unregister PacketOut to the Network * * @param packet PacketOut to unregister */ public static void unregisterPacket(Class packet) { if (Util.isNull(packet)) throw new NullPointerException(); pOut.remove(packet); } /** * Grab PacketIn Instances via handle * * @param handle Handle * @return PacketIn */ public static List getPacket(String handle) { if (Util.isNull(handle)) throw new NullPointerException(); return new ArrayList(pIn.get(handle)); } /** * Broadcast a Packet to everything on the Network
* Warning: There are usually different types of applications on the network at once, they may not recognise the same packet handles * * @param packet Packet to send */ public void broadcastPacket(PacketOut packet) { if (Util.isNull(packet)) throw new NullPointerException(); List clients = new ArrayList(); clients.addAll(getClients()); for (Client client : clients) { client.sendPacket(packet); } } /** * Allow Connections from an Address * * @param address Address to allow */ public static void allowConnection(InetAddress address) { if (Util.isNull(address)) throw new NullPointerException(); if (!allowedAddresses.contains(address)) allowedAddresses.add(address); } /** * Deny Connections from an Address * * @param address Address to deny */ public static void denyConnection(InetAddress address) { if (Util.isNull(address)) throw new NullPointerException(); allowedAddresses.remove(address); } /** * JSON Encode PacketOut * * @param packet PacketOut * @return JSON Formatted Packet * @throws IllegalPacketException */ protected static JSONObject encodePacket(Client client, PacketOut packet) throws IllegalPacketException, InvocationTargetException { JSONObject json = new JSONObject(); if (!pOut.keySet().contains(packet.getClass())) throw new IllegalPacketException(packet.getClass().getCanonicalName() + ": Unknown PacketOut Channel: " + packet.getClass().getCanonicalName()); if (packet.getVersion().toString() == null) throw new NullPointerException(packet.getClass().getCanonicalName() + ": PacketOut getVersion() cannot be null: " + packet.getClass().getCanonicalName()); try { JSONObject contents = packet.generate(); json.put("h", pOut.get(packet.getClass())); json.put("v", packet.getVersion().toString()); if (contents != null) json.put("c", contents); return json; } catch (Throwable e) { throw new InvocationTargetException(e, packet.getClass().getCanonicalName() + ": Exception while encoding packet"); } } /** * JSON Decode PacketIn * * @param json JSON to Decode * @return PacketIn * @throws IllegalPacketException */ protected static List decodePacket(Client client, JSONObject json) throws IllegalPacketException { if (!json.keySet().contains("h") || !json.keySet().contains("v")) throw new IllegalPacketException(client.getAddress().toString() + ": Unknown Packet Format: " + json.toString()); if (!pIn.keySet().contains(json.getString("h"))) throw new IllegalPacketException(client.getAddress().toString() + ": Unknown PacketIn Channel: " + json.getString("h")); List list = new ArrayList(); for (PacketIn packet : pIn.get(json.getString("h"))) { if (new Version(json.getString("v")).equals(packet.getVersion())) { list.add(packet); } else { new IllegalPacketException(client.getAddress().toString() + ": Packet Version Mismatch in " + json.getString("h") + ": " + json.getString("v") + " =/= " + packet.getVersion().toString()).printStackTrace(); } } return list; } /** * Drops All Connections and Stops the SubData Listener * * @throws IOException */ public void destroy() throws IOException { while(clients.size() > 0) { removeClient((Client) clients.values().toArray()[0]); } server.close(); System.out.println("SubServers > The SubData Listener has been closed"); plugin.subdata = null; } }