Removed never used NET library

This commit is contained in:
Marc Baloup 2023-06-18 00:36:57 +02:00
parent 69b72ef90d
commit c984b63cee
12 changed files with 0 additions and 1033 deletions

View File

@ -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` 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-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-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-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-cli` Utility and helper classes for a standalone CLI Java application.
- `pandalib-core` A catch-all module for some helper classes that didnt have their own module yet; - `pandalib-core` A catch-all module for some helper classes that didnt have their own module yet;

View File

@ -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.
Its still in development (actually not touched since years), and its 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

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>pandalib-parent</artifactId>
<groupId>fr.pandacube.lib</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pandalib-net</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>fr.pandacube.lib</groupId>
<artifactId>pandalib-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
</dependencies>
</project>

View File

@ -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;
}
}

View File

@ -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 <b>backed</b> 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<String> 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<String> getListOfString() {
int size = getInt();
if (size < 0)
return null;
List<String> 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();
}
}

View File

@ -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]);
}
}

View File

@ -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);
}
}

View File

@ -1,16 +0,0 @@
package fr.pandacube.lib.net;
import com.google.common.annotations.Beta;
@Beta
@FunctionalInterface
public interface PPacketListener<P extends PPacket> {
/**
* 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);
}

View File

@ -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<TCPServerClientConnection> clients = Collections.synchronizedList(new ArrayList<>());
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final List<PPacketListener<PPacket>> globalPacketListeners = Collections.synchronizedList(new ArrayList<>());
private final List<PSocketConnectionListener> 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<PPacket> l) {
globalPacketListeners.add(l);
}
public boolean removePacketListener(PPacketListener<PPacket> 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<PSocket> getClients() {
synchronized (clients) {
return new ArrayList<>(clients);
}
}
@Override
public String toString() {
return this.getClass().getName() + "{thread=" + getName() + ", socket=" + socket + "}";
}
}

View File

@ -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}.
* <br>
* This class provides a simple way to exchange data between client and server :
* <ul>
* <li>Maintained connection with the server</li>
* <li>Login with a password (send in the first packet)</li>
* <li>Binary packet id</li>
* <li>Binary data</li>
* <li>Input stream in a separate Thread</li>
* </ul>
*
*/
@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<PPacketListener<PPacket>> packetListeners = Collections.synchronizedList(new ArrayList<>());
private final List<PSocketConnectionListener> connectionListeners = Collections.synchronizedList(new ArrayList<>());
private final Map<Integer, PPacketListener<PPacketAnswer>> 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<PPacketAnswer> 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<PPacket> l) {
packetListeners.add(l);
}
public boolean removePacketListener(PPacketListener<PPacket> 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 + "}";
}
}

View File

@ -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);
}

View File

@ -68,7 +68,6 @@
<module>pandalib-commands</module> <module>pandalib-commands</module>
<module>pandalib-core</module> <module>pandalib-core</module>
<module>pandalib-db</module> <module>pandalib-db</module>
<module>pandalib-net</module>
<module>pandalib-netapi</module> <module>pandalib-netapi</module>
<module>pandalib-paper</module> <module>pandalib-paper</module>
<module>pandalib-paper-permissions</module> <module>pandalib-paper-permissions</module>