All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ml.karmaconfigs.remote.messaging.worker.tcp.TCPClient Maven / Gradle / Ivy

Go to download

This API helps you to send messages between a server and a client. It's supposed to work with computers out of the same network, but I haven't tested it.

The newest version!
package ml.karmaconfigs.remote.messaging.worker.tcp;

/*
 * GNU LESSER GENERAL PUBLIC LICENSE
 * Version 2.1, February 1999
 * 

* Copyright (C) 1991, 1999 Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. *

* [This is the first released version of the Lesser GPL. It also counts * as the successor of the GNU Library Public License, version 2, hence * the version number 2.1.] */ import ml.karmaconfigs.api.common.Console; import ml.karmaconfigs.api.common.timer.scheduler.LateScheduler; import ml.karmaconfigs.api.common.timer.scheduler.worker.AsyncLateScheduler; import ml.karmaconfigs.api.common.utils.PrefixConsoleData; import ml.karmaconfigs.api.common.utils.enums.Level; import ml.karmaconfigs.api.common.utils.string.StringUtils; import ml.karmaconfigs.remote.messaging.platform.Client; import ml.karmaconfigs.remote.messaging.listener.RemoteListener; import ml.karmaconfigs.remote.messaging.listener.event.client.ServerConnectEvent; import ml.karmaconfigs.remote.messaging.listener.event.client.ServerDisconnectEvent; import ml.karmaconfigs.remote.messaging.listener.event.client.ServerMessageEvent; import ml.karmaconfigs.remote.messaging.remote.RemoteServer; import ml.karmaconfigs.remote.messaging.util.WorkLevel; import ml.karmaconfigs.remote.messaging.util.message.*; import ml.karmaconfigs.remote.messaging.util.message.type.MergeType; import ml.karmaconfigs.remote.messaging.worker.tcp.remote.TCPRemoteServer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Remote message client interface */ public final class TCPClient extends Client { private final Set data_queue = Collections.newSetFromMap(new ConcurrentHashMap<>()); private RemoteServer remote = null; private String client_name = "client_" + new Random().nextInt(Integer.MAX_VALUE); private String server = "127.0.0.1"; private String key = ""; private int sv_port = 49305; private int client = 49300; private boolean debug = false; private boolean operative = false; private boolean instant_close = false; private boolean award_connection = false; private boolean tryingConnect = true; private SocketChannel socket; private final Console console = new Console(this); /** * Initialize a default client that * will connect to local server at * default port 49305 */ public TCPClient() { PrefixConsoleData data = console.getData(); data.setOkPrefix("&3[TCP Client (&aOK&3)]&b "); data.setInfoPrefix("&3[TCP Client (&7INFO&3)]&b "); data.setWarnPrefix("&3[TCP Client (&eWARNING&3)]&b "); data.setGravePrefix("&3[TCP Client (&4ERROR&3)]&b "); } /** * Initialize a client that will connect * to the specified server at specified port * * @param server_host the server * @param server_port the server port */ public TCPClient(final String server_host, final int server_port) { server = server_host; sv_port = server_port; PrefixConsoleData data = console.getData(); data.setOkPrefix("&3[TCP Client (&aOK&3)]&b "); data.setInfoPrefix("&3[TCP Client (&7INFO&3)]&b "); data.setWarnPrefix("&3[TCP Client (&eWARNING&3)]&b "); data.setGravePrefix("&3[TCP Client (&4ERROR&3)]&b "); } /** * Initialize a client with a custom port * that will connect to the specified server at the * specified port * * @param client_port the client port * @param server_host the server * @param server_port the server port */ public TCPClient(final int client_port, final String server_host, final int server_port) { client = client_port; server = server_host; sv_port = server_port; PrefixConsoleData data = console.getData(); data.setOkPrefix("&3[TCP Client (&aOK&3)]&b "); data.setInfoPrefix("&3[TCP Client (&7INFO&3)]&b "); data.setWarnPrefix("&3[TCP Client (&eWARNING&3)]&b "); data.setGravePrefix("&3[TCP Client (&4ERROR&3)]&b "); } /** * Set the client debug status * * @param status the client debug status * @return this instance */ @Override public Client debug(final boolean status) { debug = status; return this; } /** * Try to connect to the server * * @return a completable future when the client connects */ @Override public LateScheduler connect() { if (!operative) { LateScheduler result = new AsyncLateScheduler<>(); Thread thread = new Thread(() -> { try { if (debug) { console.send("Initializing the connection with the server", Level.INFO); } socket = SocketChannel.open().bind(new InetSocketAddress(client)); socket.configureBlocking(false); socket.connect(new InetSocketAddress(server, sv_port)); while (!socket.finishConnect()) { if (tryingConnect) { if (debug) { console.send("Trying to establish a connection with {0}/{1}", Level.INFO, server, sv_port); } tryingConnect = false; } } award_connection = true; tryingConnect = true; if (debug) { console.send("The connection has been established but the client is still waiting for server confirmation, data can be started to be sent", Level.WARNING, server, sv_port); } while (award_connection) { if (instant_close) { close(); tryingConnect = false; award_connection = false; operative = false; } if (tryingConnect) { MessageOutput output = new MessageDataOutput(); output.write("MAC", getMAC()); output.write("COMMAND_ENABLED", true); output.write("COMMAND", "connect"); output.write("ARGUMENT", client_name); if (!StringUtils.isNullOrEmpty(key)) { output.write("ACCESS_KEY", key); } byte[] compile = output.compile(); ByteBuffer tmp = ByteBuffer.wrap(compile); socket.write(tmp); tryingConnect = false; } ByteBuffer tmpBuffer = ByteBuffer.allocate(5120); int read = socket.read(tmpBuffer); if (read != 0) { ByteBuffer readBuffer = DataFixer.fixBuffer(tmpBuffer); if (!operative) { MessageInput input = new MessageDataInput(readBuffer.array()); if (input.getBoolean("COMMAND_ENABLED")) { String sequence = input.getString("COMMAND"); String mac = input.getString("MAC"); if (sequence != null && mac != null) { if (sequence.equalsIgnoreCase("accept")) { remote = new TCPRemoteServer(mac, InetAddress.getByName(server), sv_port, socket); if (debug) { console.send("Connection has been validated by the server", Level.OK); } for (byte[] data : data_queue) { ByteBuffer tmp = ByteBuffer.wrap(data); socket.write(tmp); data_queue.remove(data); } award_connection = false; operative = true; ServerConnectEvent event = new ServerConnectEvent(remote, this); RemoteListener.callClientEvent(event); } else { String argument = input.getString("ARGUMENT"); if (argument != null) { if (argument.equalsIgnoreCase("connect")) { instant_close = true; result.complete(false); String reason = input.getString("COMMAND_ARGUMENT"); if (reason != null) { console.send("Connection has been declined by the server ({0})", Level.GRAVE, reason); } } } } } } } } } result.complete(true); while (operative) { ByteBuffer tmpBuffer = ByteBuffer.allocate(4056); int read = socket.read(tmpBuffer); if (read == 0) { for (byte[] queue : data_queue) { ByteBuffer tmp = ByteBuffer.wrap(queue); socket.write(tmp); data_queue.remove(queue); } } else { ByteBuffer readBuffer = DataFixer.fixBuffer(tmpBuffer); MessageInput input = new MessageDataInput(readBuffer.array()); String mac = input.getString("MAC"); boolean isCommand = input.getBoolean("COMMAND_ENABLED"); if (remote.getMAC().equals(mac)) { if (isCommand) { String command = input.getString("COMMAND"); String argument = input.getString("ARGUMENT"); if (command != null && argument != null) { String data; switch (command.toLowerCase()) { case "success": switch (argument.toLowerCase()) { case "rename": client_name = input.getString("ARGUMENT_DATA"); if (client_name != null && debug) { console.send("Server accepted the new client name: {0}", Level.OK, client_name); } break; case "message": data = input.getString("ARGUMENT_DATA"); if (data != null && debug) { console.send("{0} to server: {1}", Level.INFO, data, new String(readBuffer.array())); } break; case "unknown": data = input.getString("ARGUMENT_DATA"); if (data != null && debug) { String[] arg_data = data.split(","); console.send("{0} ran custom command: {1} ( {2} )", Level.WARNING, arg_data[0], arg_data[1], arg_data[2]); } break; default: if (debug) { console.send("Unknown command from server: {0} ( {1} )", Level.GRAVE, command, argument); } break; } break; case "failed": switch (argument.toLowerCase()) { case "connect": data = input.getString("ARGUMENT_DATA"); if (data != null) { String[] connect_data = data.split(","); String name = connect_data[0]; String reason = connect_data[1]; console.send("Server declined connection as {0}, because: {1}", Level.GRAVE, name, reason); ServerDisconnectEvent connectEvent = new ServerDisconnectEvent(remote, this, reason); RemoteListener.callClientEvent(connectEvent); } break; case "rename": data = input.getString("ARGUMENT_DATA"); if (data != null) { String[] rename_data = data.split(","); console.send("Failed to change client name to {0}: {1}", Level.GRAVE, rename_data[0], rename_data[1]); } break; case "disconnect": data = input.getString("ARGUMENT_DATA"); if (data != null) { console.send("Failed while trying to disconnect the server ( you've been disconnected anyway ): {0}", Level.GRAVE, data); ServerDisconnectEvent disconnectEvent = new ServerDisconnectEvent(remote, this, "no server reason..."); RemoteListener.callClientEvent(disconnectEvent); } break; case "message": data = input.getString("ARGUMENT_DATA"); if (data != null) { console.send("Failed while trying to send a message to server: {0}", Level.GRAVE, data); } break; case "unknown": data = input.getString("ARGUMENT_DATA"); if (data != null) { String[] unknown_data = data.split(","); console.send("Failed while trying to execute custom command {0} with argument {1}: {2}", Level.GRAVE, unknown_data[0], unknown_data[1], unknown_data[2]); } break; default: if (debug) { console.send("Unknown command from server: {0} ( {1} )", Level.WARNING, command, argument); } break; } break; case "disconnect": String reason = input.getString("ARGUMENT_DATA"); if (reason != null) { console.send("Connection killed by server: {0}", Level.GRAVE, reason); } ServerDisconnectEvent event = new ServerDisconnectEvent(remote, this, reason); RemoteListener.callClientEvent(event); close(); break; } } } else { ServerMessageEvent event = new ServerMessageEvent(remote, this, input); RemoteListener.callClientEvent(event); } } } } } catch (Throwable ex) { result.complete(false, ex); } }); thread.start(); return result; } return null; } /** * Try to connect to the server * * @param accessKey the server access key * @return a completable future when the client connects */ @Override public LateScheduler connect(final String accessKey) { if (!operative) { key = accessKey; return connect(); } return null; } /** * Get the client name * * @return the client name */ @Override public String getName() { return client_name; } /** * Get the client MAC address * * @return the client MAC address */ @Override public String getMAC() { try { NetworkInterface network = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()); byte[] macArray = network.getHardwareAddress(); StringBuilder str = new StringBuilder(); for (int i = 0; i < macArray.length; i++) { str.append(String.format("%02X%s", macArray[i], (i < macArray.length - 1) ? ":" : "")); } return str.toString(); } catch (Throwable ex) { System.out.println("Failed to locate MAC address..."); System.exit(1); return null; } } /** * Get the client address * * @return the client address */ @Override public InetAddress getHost() { return InetAddress.getLoopbackAddress(); } /** * Get the client port * * @return the client port */ @Override public int getPort() { return client; } /** * Send a message to the client * * @param message the message to send * @return if the message could be sent */ @Override public boolean sendMessage(MessageOutput message) { return false; } /** * Get the connected remote server * * @return the connected remote server */ @Override public RemoteServer getServer() { return remote; } /** * Get the client work level * * @return the client work level */ @Override public WorkLevel getWorkLevel() { return WorkLevel.TCP; } /** * Get if the client is trying to connect to the * server * * @return if the client is trying to connect to * the server */ @Override public boolean isConnecting() { return tryingConnect || award_connection; } /** * Get if the client is completely connected * to the server * * @return if the client is connected */ @Override public boolean isConnected() { try { ByteBuffer tmp = ByteBuffer.allocate(1024); return socket != null && socket.read(tmp) != -1; } catch (Throwable ex) { return false; } } /** * Rename the client on the server interface * * @param name the client name */ @Override public void rename(final String name) { if (award_connection || operative) { client_name = name; MessageOutput output = new MessageDataOutput(); output.write("MAC", getMAC()); output.write("COMMAND_ENABLED", true); output.write("COMMAND", "rename"); output.write("ARGUMENT", client_name); try { if (debug) { console.send("Trying to inform the server about the name change request to {0}", Level.INFO, name); } byte[] compile = output.compile(); ByteBuffer tmp = ByteBuffer.wrap(compile); socket.write(tmp); } catch (Throwable ex) { data_queue.add(output.compile()); } } } /** * Send data to the server * * @param data the data to send */ @Override public void send(final byte[] data) { if (award_connection || operative) { MessageOutput output = new MessageDataOutput(data, MergeType.DIFFERENCE); output.write("MAC", getMAC()); output.write("COMMAND_ENABLED", false); try { byte[] compile = output.compile(); ByteBuffer tmp = ByteBuffer.wrap(compile); socket.write(tmp); } catch (Throwable ex) { data_queue.add(output.compile()); } } } /** * Close the connection */ @Override public void close() { if (operative) { try { MessageOutput output = new MessageDataOutput(); output.write("MAC", getMAC()); output.write("COMMAND_ENABLED", true); output.write("COMMAND", "disconnect"); output.write("ARGUMENT", "Client disconnect request"); data_queue.add(output.compile()); } catch (Throwable ex) { ex.printStackTrace(); } } else { instant_close = true; } } /** * Karma source name * * @return the source name */ @Override public String name() { return "TCP Client"; } /** * Karma source version * * @return the source version */ @Override public String version() { return "0"; } /** * Karma source description * * @return the source description */ @Override public String description() { return "TCP client to connect to a TCP server that has been created with RemoteMessaging API"; } /** * Karma source authors * * @return the source authors */ @Override public String[] authors() { return new String[]{"KarmaDev"}; } /** * Karma source update URL * * @return the source update URL */ @Override public String updateURL() { return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy