diff --git a/Readme.md b/Readme.md index 9e3f120..6425169 100644 --- a/Readme.md +++ b/Readme.md @@ -18,7 +18,6 @@ that are detailed in their respective Readme file (if any). - `pandalib-players` A library to handle classes representing online or offline players; - `pandalib-players-permissible` An extension of `pandalib-players` with support for the permission system `pandalib-permissions`; - `pandalib-netapi` A poorly designed, but working TCP network library; -- `pandalib-net` A better-designed, packet-based TCP network library (_still in development_); - `pandalib-commands` An abstract command manager working on top of [Brigadier](https://github.com/Mojang/brigadier); - `pandalib-cli` Utility and helper classes for a standalone CLI Java application. - `pandalib-core` A catch-all module for some helper classes that didn’t have their own module yet; diff --git a/pandalib-net/Readme.md b/pandalib-net/Readme.md deleted file mode 100644 index 2e33d79..0000000 --- a/pandalib-net/Readme.md +++ /dev/null @@ -1,12 +0,0 @@ -# pandalib-net - -A TCP network library that uses the standard Java socket API, to ease the ommunication between the different processes -running the server network Pandacube. - -It’s still in development (actually not touched since years), and it’s supposed to be a replacement for the old -`pandalib-netapi`. This module is then marked as Beta using the Google Guava annotation. - -- Packet based communication -- Supports Request/Answer packets -- Uses binary packet id and data -* Input streams are handled in separate Threads \ No newline at end of file diff --git a/pandalib-net/pom.xml b/pandalib-net/pom.xml deleted file mode 100644 index 55bff8a..0000000 --- a/pandalib-net/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - pandalib-parent - fr.pandacube.lib - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - pandalib-net - jar - - - - fr.pandacube.lib - pandalib-util - ${project.version} - - - com.google.guava - guava - 31.0.1-jre - - - - \ No newline at end of file diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/Array8Bit.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/Array8Bit.java deleted file mode 100644 index cb094b7..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/Array8Bit.java +++ /dev/null @@ -1,65 +0,0 @@ -package fr.pandacube.lib.net; - -import java.util.Arrays; - -import com.google.common.annotations.Beta; - -@Beta -public class Array8Bit { - - public static final int BIT_COUNT = Byte.SIZE; - - private boolean[] values = new boolean[BIT_COUNT]; - - public Array8Bit(byte b) { - fromByte(b); - } - - /** - * @param bits (index 0 is the lowest significant bit) - */ - public Array8Bit(boolean[] bits) { - if (bits == null || bits.length != BIT_COUNT) - throw new IllegalArgumentException("bits is null or bits.length != "+BIT_COUNT); - values = Arrays.copyOf(bits, BIT_COUNT); - } - - /** - * i = 0 is the lowest significant bit - */ - public boolean getBit(int i) { - return values[i]; - } - - /** - * i = 0 is the lowest significant bit - */ - public void setBit(int i, boolean b) { - values[i] = b; - } - - - - public void fromByte(byte b) { - int mask = 1; - for (int i = 0; i < BIT_COUNT; i++) { - values[i] = (b & mask) != 0; - mask <<= 1; - } - } - - - - public byte toByte() { - byte b = 0; - for (int i=BIT_COUNT-1; i>=0; i--) { - b <<= 1; - if (values[i]) b |= 1; - } - return b; - } - - - - -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/ByteBuffer.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/ByteBuffer.java deleted file mode 100644 index 7373325..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/ByteBuffer.java +++ /dev/null @@ -1,275 +0,0 @@ -package fr.pandacube.lib.net; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.common.annotations.Beta; - -@Beta -public final class ByteBuffer implements Cloneable { - - public static final Charset NETWORK_CHARSET = StandardCharsets.UTF_8; - - private java.nio.ByteBuffer buff; - - public ByteBuffer() { - this(16); - } - - public ByteBuffer(int initSize) { - buff = java.nio.ByteBuffer.allocate(initSize); - } - - /** - * Create a ByteBuffer that is initially backed by the provided byte array. - * The position of this buffer will be 0. - * If this ByteBuffer needs a biffer array, the provided array is replaced by a new one, - * making the provided array not related to this ByteBuffer anymore. - * @param data array of byte that serve as a backend for this ByteBuffer. - */ - public ByteBuffer(byte[] data) { - buff = java.nio.ByteBuffer.wrap(data); - } - - private void askForBufferExtension(int needed) { - while (buff.remaining() < needed) { - java.nio.ByteBuffer newBuff = java.nio.ByteBuffer.wrap(Arrays.copyOf(buff.array(), buff.array().length * 2)); - newBuff.position(buff.position()); - buff = newBuff; - } - } - - /** - * This clone method also clone the underlying array. - */ - @SuppressWarnings("MethodDoesntCallSuperMethod") - @Override - public ByteBuffer clone() { - return new ByteBuffer(Arrays.copyOf(buff.array(), buff.array().length)); - } - - /** - * @see java.nio.ByteBuffer#get() - */ - public byte getByte() { - return buff.get(); - } - - /** - * @see java.nio.ByteBuffer#get(byte[]) - */ - public byte[] getByteArray(byte[] b) { - buff.get(b); - return b; - } - - /** - * Return the next byte array wich is preceded with his size as integer, - * or null if the founded size is negative. - */ - public byte[] getSizedByteArray() { - int size = getInt(); - if (size < 0) return null; - return getByteArray(new byte[size]); - } - - /** - * @see java.nio.ByteBuffer#getChar() - */ - public char getChar() { - return buff.getChar(); - } - - /** - * @see java.nio.ByteBuffer#getShort() - */ - public short getShort() { - return buff.getShort(); - } - - /** - * @see java.nio.ByteBuffer#getInt() - */ - public int getInt() { - return buff.getInt(); - } - - /** - * @see java.nio.ByteBuffer#getLong() - */ - public long getLong() { - return buff.getLong(); - } - - /** - * @see java.nio.ByteBuffer#getFloat() - */ - public float getFloat() { - return buff.getFloat(); - } - - /** - * @see java.nio.ByteBuffer#getDouble() - */ - public double getDouble() { - return buff.getDouble(); - } - - /** - * @see java.nio.ByteBuffer#put(byte) - */ - public ByteBuffer putByte(byte b) { - askForBufferExtension(Byte.BYTES); - buff.put(b); - return this; - } - - /** - * @see java.nio.ByteBuffer#put(byte[]) - */ - public ByteBuffer putByteArray(byte[] b) { - askForBufferExtension(b.length * Byte.BYTES); - buff.put(b); - return this; - } - - public ByteBuffer putSizedByteArray(byte[] b) { - if (b == null) { - return putInt(-1); - } - putInt(b.length); - return putByteArray(b); - } - - /** - * @see java.nio.ByteBuffer#putChar(char) - */ - public ByteBuffer putChar(char value) { - askForBufferExtension(Character.BYTES); - buff.putChar(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#putShort(short) - */ - public ByteBuffer putShort(short value) { - askForBufferExtension(Short.BYTES); - buff.putShort(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#putInt(int) - */ - public ByteBuffer putInt(int value) { - askForBufferExtension(Integer.BYTES); - buff.putInt(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#putLong(long) - */ - public ByteBuffer putLong(long value) { - askForBufferExtension(Long.BYTES); - buff.putLong(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#putFloat(float) - */ - public ByteBuffer putFloat(float value) { - askForBufferExtension(Float.BYTES); - buff.putFloat(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#putDouble(double) - */ - public ByteBuffer putDouble(double value) { - askForBufferExtension(Double.BYTES); - buff.putDouble(value); - return this; - } - - /** - * @see java.nio.ByteBuffer#position() - */ - public int getPosition() { - return buff.position(); - } - - /** - * @see java.nio.ByteBuffer#position(int) - */ - public void setPosition(int p) { - buff.position(p); - } - - /** - * @see java.nio.ByteBuffer#capacity() - */ - public int capacity() { - return buff.capacity(); - } - - /** - * - * @param s null String are supported - */ - public ByteBuffer putString(String s) { - if (s == null) { - return putInt(-1); - } - return putSizedByteArray(s.getBytes(NETWORK_CHARSET)); - } - - /** - * returned string can be null - */ - public String getString() { - byte[] binaryString = getSizedByteArray(); - return (binaryString == null) ? null : new String(binaryString, NETWORK_CHARSET); - } - - /** - * - * @param list The list can be null, and any String can be null too. - */ - public ByteBuffer putListOfString(List list) { - if (list == null) { - return putInt(-1); - } - putInt(list.size()); - for (String str : list) - putString(str); - return this; - } - - /** - * @return a List of String. The list can be null, and any element can be null too. - */ - public List getListOfString() { - int size = getInt(); - if (size < 0) - return null; - List list = new ArrayList<>(); - for (int i = 0; i < size; i++) - list.add(getString()); - return list; - } - - /** - * @see java.nio.ByteBuffer#array() - */ - public byte[] array() { - return buff.array(); - } - -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacket.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacket.java deleted file mode 100644 index c54d330..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacket.java +++ /dev/null @@ -1,60 +0,0 @@ -package fr.pandacube.lib.net; - -import java.util.Arrays; - -import com.google.common.annotations.Beta; - -@Beta -public class PPacket { - public final String name; - /* package */ int id; - public final byte[] content; - - /** - * Construct a new PPacket based on the content of the provided buffer before his position. - * @param n the name of the packet. - * @param buff the buffer where the data comes from. Only the content before {@link ByteBuffer#getPosition()} is copied. - */ - public PPacket(String n, ByteBuffer buff) { - this(n, Arrays.copyOf(buff.array(), buff.getPosition())); - } - - public PPacket(String n, byte[] c) { - name = n; - content = c; - } - - /* package */ PPacket(String n, int i, byte[] c) { - this(n, c); - id = i; - } - - public ByteBuffer getContentAsBuffer() { - return new ByteBuffer(content); - } - - - - - - - - - public static PPacket buildSingleStringContentPacket(String name, String content) { - return new PPacket(name, new ByteBuffer().putString(content)); - } - - - - - - /* package */ static PPacket buildLoginPacket(String password) { - return buildSingleStringContentPacket("login", password); - } - /* package */ static PPacket buildBadFormatPacket(String message) { - return buildSingleStringContentPacket("bad_format", message); - } - /* package */ static PPacket buildLoginBadPacket() { - return new PPacket("login_bad", new byte[0]); - } -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketAnswer.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketAnswer.java deleted file mode 100644 index eb40387..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketAnswer.java +++ /dev/null @@ -1,47 +0,0 @@ -package fr.pandacube.lib.net; - -import java.util.Arrays; - -import com.google.common.annotations.Beta; - -@Beta -public class PPacketAnswer extends PPacket { - /* package */ final int answer; - - /** - * Construct a new PPacketAnswer based on the content of the provided buffer before his position. - * @param n the name of the packet. - * @param buff the buffer where the data comes from. Only the content before {@link ByteBuffer#getPosition()} is copied. - */ - public PPacketAnswer(PPacket answered, String n, ByteBuffer buff) { - this(answered, n, Arrays.copyOf(buff.array(), buff.getPosition())); - } - - public PPacketAnswer(PPacket answered, String n, byte[] c) { - super(n, c); - answer = answered.id; - } - - /* package */ PPacketAnswer(String n, int i, int a, byte[] c) { - super(n, i, c); - answer = a; - } - - - - - public static PPacketAnswer buildSingleStringContentPacketAnswer(PPacket answered, String name, String content) { - ByteBuffer pwBuff = new ByteBuffer().putString(content); - return new PPacketAnswer(answered, name, Arrays.copyOf(pwBuff.array(), pwBuff.getPosition())); - } - - - - - /* package */ static PPacketAnswer buildLoginOkPacket(PPacket loginPacket) { - return new PPacketAnswer(loginPacket, "login_ok", new byte[0]); - } - /* package */ static PPacketAnswer buildExceptionPacket(PPacket answered, String message) { - return buildSingleStringContentPacketAnswer(answered, "exception", message); - } -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketListener.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketListener.java deleted file mode 100644 index cc6e5d9..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PPacketListener.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.pandacube.lib.net; - -import com.google.common.annotations.Beta; - -@Beta -@FunctionalInterface -public interface PPacketListener

{ - - /** - * Called when we receive a packet (except responses) - * @param connection the connection from where the packet comes - * @param packet the received packet - */ - void onPacketReceive(PSocket connection, P packet); - -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PServer.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PServer.java deleted file mode 100644 index 751dd88..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PServer.java +++ /dev/null @@ -1,157 +0,0 @@ -package fr.pandacube.lib.net; - -import java.io.Closeable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import com.google.common.annotations.Beta; - -import fr.pandacube.lib.util.Log; - -@Beta -public class PServer extends Thread implements Closeable { - private static final AtomicInteger connectionCounterId = new AtomicInteger(0); - - private final int port; - private ServerSocket socket; - private final String socketName; - - private final List clients = Collections.synchronizedList(new ArrayList<>()); - - private final AtomicBoolean isClosed = new AtomicBoolean(false); - - - private final List> globalPacketListeners = Collections.synchronizedList(new ArrayList<>()); - private final List clientConnectionListeners = Collections.synchronizedList(new ArrayList<>()); - - - - private final String password; - - public PServer(int port, String sckName, String password) { - super("PServer " + sckName); - setDaemon(true); - if (port <= 0 || port > 65535) throw new IllegalArgumentException("le numéro de port est invalide"); - socketName = sckName; - this.port = port; - this.password = password; - } - - @Override - public void run() { - - try { - - socket = new ServerSocket(); - socket.setReceiveBufferSize(PSocket.NETWORK_TCP_BUFFER_SIZE); - socket.setPerformancePreferences(0, 1, 0); - socket.bind(new InetSocketAddress(port)); - - while (true) { - Socket socketClient = socket.accept(); - socketClient.setSendBufferSize(PSocket.NETWORK_TCP_BUFFER_SIZE); - socketClient.setSoTimeout(PSocket.NETWORK_TIMEOUT); - - TCPServerClientConnection co = new TCPServerClientConnection(socketClient, - connectionCounterId.getAndIncrement()); - co.start(); - } - } catch (SocketException ignored) { - } catch (Exception e) { - Log.warning("Plus aucune connexion ne peux être acceptée", e); - } - } - - - - public void addPacketListener(PPacketListener l) { - globalPacketListeners.add(l); - } - - public boolean removePacketListener(PPacketListener l) { - return globalPacketListeners.remove(l); - } - - public void addConnectionListener(PSocketConnectionListener l) { - clientConnectionListeners.add(l); - } - - public void removeConnectionListener(PSocketConnectionListener l) { - clientConnectionListeners.remove(l); - } - - protected class TCPServerClientConnection extends PSocket { - - boolean loggedIn; - - private TCPServerClientConnection(Socket s, int coId) { - super(s, "Conn#" + coId + " via PServer " + socketName, password); - addConnectionListener(new PSocketConnectionListener() { - @Override - public void onDisconnect(PSocket connection) { - try { - clientConnectionListeners.forEach(l -> l.onDisconnect(connection)); - } finally { - clients.remove((TCPServerClientConnection)connection); - } - } - @Override - public void onConnect(PSocket connection) { - clients.add((TCPServerClientConnection)connection); - clientConnectionListeners.forEach(l -> l.onConnect(connection)); - } - }); - addPacketListener((conn, packet) -> - globalPacketListeners.forEach(l -> { - try { - l.onPacketReceive(conn, packet); - } catch (Exception e) { - Log.severe("Exception while calling PPacketListener.onPacketReceive().", e); - sendSilently(PPacketAnswer.buildExceptionPacket(packet, e.toString())); - } - }) - ); - } - - } - - @Override - public void close() { - try { - if (isClosed.get()) return; - isClosed.set(true); - - clients.forEach(PSocket::close); - - socket.close(); - } catch (IOException ignored) {} - } - - public boolean isClosed() { - return isClosed.get() || socket.isClosed(); - } - - - - public List getClients() { - synchronized (clients) { - return new ArrayList<>(clients); - } - } - - - - @Override - public String toString() { - return this.getClass().getName() + "{thread=" + getName() + ", socket=" + socket + "}"; - } - -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocket.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocket.java deleted file mode 100644 index f7bd9a1..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocket.java +++ /dev/null @@ -1,350 +0,0 @@ -package fr.pandacube.lib.net; - -import java.io.BufferedOutputStream; -import java.io.Closeable; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -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.Objects; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.google.common.annotations.Beta; - -import fr.pandacube.lib.util.Log; - -/** - * A wrapper for a {@link Socket}. The connection must point to a software using {@link PServer} - * as wrapper for the target {@link ServerSocket}. - *
- * This class provides a simple way to exchange data between client and server : - *

    - *
  • Maintained connection with the server
  • - *
  • Login with a password (send in the first packet)
  • - *
  • Binary packet id
  • - *
  • Binary data
  • - *
  • Input stream in a separate Thread
  • - *
- * - */ -@Beta -public class PSocket extends Thread implements Closeable { - - public static final int NETWORK_TCP_BUFFER_SIZE = 1024 * 1024; - - public static final int NETWORK_TIMEOUT = 0; // no timeout (milli-seconds) - - private boolean server = false; - private Socket socket; - private final SocketAddress addr; - private DataInputStream in; - private DataOutputStream out; - private final Object outSynchronizer = new Object(); - private String password; - - private final AtomicBoolean isClosed = new AtomicBoolean(false); - - private final List> packetListeners = Collections.synchronizedList(new ArrayList<>()); - private final List connectionListeners = Collections.synchronizedList(new ArrayList<>()); - private final Map> answersCallbacks = Collections.synchronizedMap(new HashMap<>()); - - private int nextSendId = 0; - - /** - * Create a new PSocket that will connect to the specified SocketAddress. - * @param a The target server to connect to - * @param connName the name of the connection, used to name the Thread used to receive the packet. - * @param pass the password to send to the server. - */ - public PSocket(SocketAddress a, String connName, String pass) { - super("PSocket " + connName); - setDaemon(true); - if (a == null) throw new IllegalArgumentException("les arguments ne peuvent pas être null"); - addr = a; - } - - - /* package */ PSocket(Socket s, String connName, String pass) { - this(s.getRemoteSocketAddress(), connName, pass); - socket = s; - server = true; - } - - - - @Override - public void run() { - - try { - if (socket == null) { - socket = new Socket(); - socket.setReceiveBufferSize(NETWORK_TCP_BUFFER_SIZE); - socket.setSendBufferSize(NETWORK_TCP_BUFFER_SIZE); - - socket.setSoTimeout(10000); // initial timeout before login - - socket.connect(addr); - - in = new DataInputStream(socket.getInputStream()); - out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); - } - - // password check - if (server) { - PPacket packet = readPacket(); - if (packet == null || packet instanceof PPacketAnswer || !"login".equals(packet.name)) { - send(PPacket.buildLoginBadPacket()); - close(); - return; - } - try { - String receivedPassword = new ByteBuffer(packet.content).getString(); - if (!Objects.equals(receivedPassword, password)) { - send(PPacket.buildLoginBadPacket()); - close(); - return; - } - } catch(Exception e) { - send(PPacket.buildLoginBadPacket()); - close(); - return; - } - send(PPacketAnswer.buildLoginOkPacket(packet)); - // login ok at this point - } - else { - send(PPacket.buildLoginPacket(password)); - PPacket packet = readPacket(); - if (packet == null) { - Log.severe("bad packet received from server. Disconnecting."); - close(); - return; - } - if (packet.name.equals("login_bad")) { - Log.severe("Wrong password to connect to server. Disconnecting."); - close(); - return; - } - if (!packet.name.equals("login_ok")) { - Log.severe("Unexpected packet from server. Disconnecting."); - close(); - return; - } - // login ok at this point - } - password = null; - - socket.setSoTimeout(NETWORK_TIMEOUT); - - Log.info(getName() + " connected."); - - connectionListeners.forEach(l -> { - try { - l.onConnect(this); - } catch (Exception e) { - Log.severe("Exception while calling PSocketConnectionListener.onConnect().", e); - } - }); - - while (!socket.isClosed()) { - PPacket packet = readPacket(); - - if (packet == null) { - send(PPacket.buildBadFormatPacket("Bad format for the last packet received. Closing connection.")); - break; - } - - if (packet instanceof PPacketAnswer) { - try { - answersCallbacks.remove(((PPacketAnswer)packet).answer).onPacketReceive(this, (PPacketAnswer)packet); - } catch (Exception e) { - Log.severe("Exception while calling PPacketListener.onPacketReceive().", e); - send(PPacketAnswer.buildExceptionPacket(packet, e.toString())); - } - } - else { - packetListeners.forEach(l -> { - try { - l.onPacketReceive(this, packet); - } catch (Exception e) { - Log.severe("Exception while calling PPacketListener.onPacketReceive().", e); - sendSilently(PPacketAnswer.buildExceptionPacket(packet, e.toString())); - } - }); - } - } - - } catch (Exception e) { - Log.severe(e); - } - close(); - } - - - /** - * Return the packet read in the socket, or null if the packet is in a bad format. - * @return the packet - * - */ - private PPacket readPacket() throws IOException { - byte nSize = in.readByte(); - if (nSize == 0) { - return null; - } - boolean answer = nSize < 0; - if (answer) - nSize *= -1; - - - byte[] nBytes = new byte[nSize]; - in.readFully(nBytes); - String name = new String(nBytes, ByteBuffer.NETWORK_CHARSET); - - - int packetId = in.readInt(); - - - int answerId = (answer) ? in.readInt() : -1; - - - int cSize = in.readInt(); - if (cSize < 0 || cSize > 0xFFFFFF) { // can't be more that 16 MiB - return null; - } - - - byte[] content = new byte[cSize]; - in.readFully(content); - - return answer ? new PPacketAnswer(name, packetId, answerId, content) : new PPacket(name, packetId, content); - } - - - - - - - /** - * Send the provided packet, without waiting for an answer. - */ - public void send(PPacket packet) throws IOException { - if (packet == null) - throw new IllegalArgumentException("packet can't be null"); - if (packet.name == null) - throw new IllegalArgumentException("packet.name can't be null"); - if (packet.content == null) - throw new IllegalArgumentException("packet.content can't be null"); - - byte[] nameBytes = packet.name.getBytes(ByteBuffer.NETWORK_CHARSET); - if (nameBytes.length > 127) - throw new IllegalArgumentException("packet.name must take fewer than 128 bytes when converted to UTF-8"); - byte nameSize = (byte)nameBytes.length; - - boolean answer = packet instanceof PPacketAnswer; - - if (answer) nameSize *= -1; - - synchronized (outSynchronizer) { - int packetId = nextSendId++; - - packet.id = packetId; - - out.write(new byte[] {nameSize}); - out.write(nameBytes); - out.write(packetId); - if (answer) - out.write(((PPacketAnswer)packet).answer); - out.write(packet.content.length); - out.write(packet.content); - out.flush(); - } - } - - public void sendSilently(PPacket packet) { - try { - send(packet); - } catch (IOException ignored) {} - } - - - - public void send(PPacket packet, PPacketListener answerCallback) throws IOException { - synchronized (answersCallbacks) { - /* - * This synch block ensure that the callback will be put in the listeners Map before - * we receve the answer (in case this is really really fast) - */ - send(packet); - answersCallbacks.put(packet.id, answerCallback); - } - } - - - - - - - - - public void addPacketListener(PPacketListener l) { - packetListeners.add(l); - } - - public boolean removePacketListener(PPacketListener l) { - return packetListeners.remove(l); - } - - - public void addConnectionListener(PSocketConnectionListener l) { - connectionListeners.add(l); - } - - public void removeConnectionListener(PSocketConnectionListener l) { - connectionListeners.remove(l); - } - - @Override - public void close() { - try { - synchronized (outSynchronizer) { - if (isClosed.get()) return; - - Log.info(getName() + " closing..."); - - connectionListeners.forEach(l -> { - try { - l.onDisconnect(this); - } catch (Exception e) { - Log.severe("Exception while calling PSocketConnectionListener.onDisconnect().", e); - } - }); - - socket.close(); - isClosed.set(true); - } - } catch (IOException e) { - Log.warning(e); - } - } - - public SocketAddress getRemoteAddress() { - return addr; - } - - public boolean isClosed() { - return isClosed.get() || socket.isClosed(); - } - - @Override - public String toString() { - return this.getClass().getName() + "{thread=" + getName() + ", socket=" + socket + "}"; - } - -} diff --git a/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocketConnectionListener.java b/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocketConnectionListener.java deleted file mode 100644 index 75cd30d..0000000 --- a/pandalib-net/src/main/java/fr/pandacube/lib/net/PSocketConnectionListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.pandacube.lib.net; - -import com.google.common.annotations.Beta; - -@Beta -public interface PSocketConnectionListener { - - /** - * Called when a socket is connected - * @param connection the connection - */ - void onConnect(PSocket connection); - - /** - * Called just before a socket is disconnected - * @param connection the connection - */ - void onDisconnect(PSocket connection); - -} diff --git a/pom.xml b/pom.xml index 8650fd0..335a214 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,6 @@ pandalib-commands pandalib-core pandalib-db - pandalib-net pandalib-netapi pandalib-paper pandalib-paper-permissions