mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
remove packet thread (only 1 network thread now)
This commit is contained in:
parent
e5450616e0
commit
838a6231c1
@ -95,7 +95,6 @@ public class Connection {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case HANDSHAKING:
|
case HANDSHAKING:
|
||||||
// connection established, starting threads and logging in
|
// connection established, starting threads and logging in
|
||||||
network.startPacketThread();
|
|
||||||
startHandlingThread();
|
startHandlingThread();
|
||||||
ConnectionState next = ((reason == ConnectionReason.CONNECT) ? ConnectionState.LOGIN : ConnectionState.STATUS);
|
ConnectionState next = ((reason == ConnectionReason.CONNECT) ? ConnectionState.LOGIN : ConnectionState.STATUS);
|
||||||
network.sendPacket(new PacketHandshake(getHost(), getPort(), next, (next == ConnectionState.STATUS) ? -1 : getVersion().getVersionNumber()));
|
network.sendPacket(new PacketHandshake(getHost(), getPort(), next, (next == ConnectionState.STATUS) ? -1 : getVersion().getVersionNumber()));
|
||||||
|
@ -38,15 +38,12 @@ import java.util.List;
|
|||||||
public class Network {
|
public class Network {
|
||||||
final Connection connection;
|
final Connection connection;
|
||||||
final List<ServerboundPacket> queue;
|
final List<ServerboundPacket> queue;
|
||||||
final List<byte[]> binQueue;
|
|
||||||
final List<byte[]> binQueueIn;
|
|
||||||
Thread socketThread;
|
Thread socketThread;
|
||||||
int compressionThreshold = -1;
|
int compressionThreshold = -1;
|
||||||
Socket socket;
|
Socket socket;
|
||||||
OutputStream outputStream;
|
OutputStream outputStream;
|
||||||
InputStream cipherInputStream;
|
InputStream cipherInputStream;
|
||||||
InputStream inputStream;
|
InputStream inputStream;
|
||||||
Thread packetThread;
|
|
||||||
boolean encryptionEnabled = false;
|
boolean encryptionEnabled = false;
|
||||||
SecretKey secretKey;
|
SecretKey secretKey;
|
||||||
boolean connected;
|
boolean connected;
|
||||||
@ -54,8 +51,6 @@ public class Network {
|
|||||||
public Network(Connection c) {
|
public Network(Connection c) {
|
||||||
this.connection = c;
|
this.connection = c;
|
||||||
this.queue = new ArrayList<>();
|
this.queue = new ArrayList<>();
|
||||||
this.binQueue = new ArrayList<>();
|
|
||||||
this.binQueueIn = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connect() {
|
public void connect() {
|
||||||
@ -86,21 +81,48 @@ public class Network {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (binQueue.size() > 0) {
|
|
||||||
// something to send it, send it
|
|
||||||
byte[] b = binQueue.get(0);
|
|
||||||
|
|
||||||
// send, flush and remove
|
while (queue.size() > 0) {
|
||||||
outputStream.write(b);
|
ServerboundPacket p = queue.get(0);
|
||||||
|
p.log();
|
||||||
|
queue.remove(0);
|
||||||
|
byte[] data = p.write(connection.getVersion()).getOutBytes();
|
||||||
|
if (compressionThreshold != -1) {
|
||||||
|
// compression is enabled
|
||||||
|
// check if there is a need to compress it and if so, do it!
|
||||||
|
OutByteBuffer outRawBuffer = new OutByteBuffer(connection.getVersion());
|
||||||
|
if (data.length >= compressionThreshold) {
|
||||||
|
// compress it
|
||||||
|
byte[] compressed = Util.compress(data);
|
||||||
|
OutByteBuffer buffer = new OutByteBuffer(connection.getVersion());
|
||||||
|
buffer.writeVarInt(compressed.length);
|
||||||
|
buffer.writeBytes(compressed);
|
||||||
|
outRawBuffer.writeVarInt(buffer.getBytes().size());
|
||||||
|
outRawBuffer.writeBytes(buffer.getOutBytes());
|
||||||
|
} else {
|
||||||
|
outRawBuffer.writeVarInt(data.length + 1); // 1 for the compressed length (0)
|
||||||
|
outRawBuffer.writeVarInt(0);
|
||||||
|
outRawBuffer.writeBytes(data);
|
||||||
|
}
|
||||||
|
data = outRawBuffer.getOutBytes();
|
||||||
|
} else {
|
||||||
|
// append packet length
|
||||||
|
OutByteBuffer bufferWithLengthPrefix = new OutByteBuffer(connection.getVersion());
|
||||||
|
bufferWithLengthPrefix.writeVarInt(data.length);
|
||||||
|
bufferWithLengthPrefix.writeBytes(data);
|
||||||
|
data = bufferWithLengthPrefix.getOutBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.write(data);
|
||||||
outputStream.flush();
|
outputStream.flush();
|
||||||
binQueue.remove(0);
|
if (p instanceof PacketEncryptionResponse) {
|
||||||
|
// enable encryption
|
||||||
// check if should enable encryption
|
secretKey = ((PacketEncryptionResponse) p).getSecretKey();
|
||||||
if (!encryptionEnabled && secretKey != null) {
|
|
||||||
enableEncryption(secretKey);
|
enableEncryption(secretKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// everything sent for now, waiting for data
|
// everything sent for now, waiting for data
|
||||||
|
|
||||||
if (inputStream.available() > 0) { // available seems not to work in CipherInputStream
|
if (inputStream.available() > 0) { // available seems not to work in CipherInputStream
|
||||||
@ -118,9 +140,65 @@ public class Network {
|
|||||||
}
|
}
|
||||||
} while ((read & 0b10000000) != 0);
|
} while ((read & 0b10000000) != 0);
|
||||||
|
|
||||||
byte[] raw = cipherInputStream.readNBytes(length);
|
byte[] data = cipherInputStream.readNBytes(length);
|
||||||
binQueueIn.add(raw);
|
|
||||||
packetThread.interrupt();
|
|
||||||
|
if (compressionThreshold != -1) {
|
||||||
|
// compression is enabled
|
||||||
|
// check if there is a need to decompress it and if so, do it!
|
||||||
|
InByteBuffer rawBuffer = new InByteBuffer(data, connection.getVersion());
|
||||||
|
int packetSize = rawBuffer.readVarInt();
|
||||||
|
byte[] left = rawBuffer.readBytesLeft();
|
||||||
|
if (packetSize == 0) {
|
||||||
|
// no need
|
||||||
|
data = left;
|
||||||
|
} else {
|
||||||
|
// need to decompress data
|
||||||
|
data = Util.decompress(left, connection.getVersion()).readBytesLeft();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InPacketBuffer inPacketBuffer = new InPacketBuffer(data, connection.getVersion());
|
||||||
|
try {
|
||||||
|
Packets.Clientbound p = connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
|
||||||
|
Class<? extends ClientboundPacket> clazz = Protocol.getPacketByPacket(p);
|
||||||
|
|
||||||
|
if (clazz == null) {
|
||||||
|
Log.warn(String.format("[IN] Received unknown packet (id=0x%x, name=%s, length=%d, dataLength=%d, version=%s, state=%s)", inPacketBuffer.getCommand(), ((p != null) ? p.name() : "UNKNOWN"), inPacketBuffer.getLength(), inPacketBuffer.getBytesLeft(), connection.getVersion().name(), connection.getConnectionState().name()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ClientboundPacket packet = clazz.getConstructor().newInstance();
|
||||||
|
boolean success;
|
||||||
|
if (packet instanceof PacketChunkData) {
|
||||||
|
// this packets need to know if we are in an dimension with skylight...
|
||||||
|
success = ((PacketChunkData) (packet)).read(inPacketBuffer, connection.getPlayer().getWorld().getDimension());
|
||||||
|
} else {
|
||||||
|
success = packet.read(inPacketBuffer);
|
||||||
|
}
|
||||||
|
if (inPacketBuffer.getBytesLeft() > 0 || !success) {
|
||||||
|
// warn not all data used
|
||||||
|
Log.warn(String.format("[IN] Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", ((p != null) ? p.name() : "null"), inPacketBuffer.getPosition(), inPacketBuffer.getBytesLeft(), inPacketBuffer.getLength(), success));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet instanceof PacketLoginSuccess) {
|
||||||
|
// login was okay, setting play status to avoid miss timing issues
|
||||||
|
connection.setConnectionState(ConnectionState.PLAY);
|
||||||
|
} else if (packet instanceof PacketLoginSetCompression) {
|
||||||
|
// instantly set compression. because handling is to slow...
|
||||||
|
compressionThreshold = ((PacketLoginSetCompression) packet).getThreshold();
|
||||||
|
}
|
||||||
|
connection.handle(packet);
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
// safety first, but will not occur
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.protocol("Received broken packet!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Util.sleep(1);
|
Util.sleep(1);
|
||||||
|
|
||||||
@ -138,130 +216,10 @@ public class Network {
|
|||||||
socketThread.start();
|
socketThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startPacketThread() {
|
|
||||||
// compressed data, makes packets to binary data
|
|
||||||
// read data
|
|
||||||
// safety first, but will not occur
|
|
||||||
packetThread = new Thread(() -> {
|
|
||||||
// compressed data, makes packets to binary data
|
|
||||||
while (connection.getConnectionState() != ConnectionState.DISCONNECTING) {
|
|
||||||
|
|
||||||
while (queue.size() > 0) {
|
|
||||||
ServerboundPacket p = queue.get(0);
|
|
||||||
p.log();
|
|
||||||
queue.remove(0);
|
|
||||||
byte[] data = p.write(connection.getVersion()).getOutBytes();
|
|
||||||
if (compressionThreshold != -1) {
|
|
||||||
// compression is enabled
|
|
||||||
// check if there is a need to compress it and if so, do it!
|
|
||||||
OutByteBuffer outRawBuffer = new OutByteBuffer(connection.getVersion());
|
|
||||||
if (data.length >= compressionThreshold) {
|
|
||||||
// compress it
|
|
||||||
byte[] compressed = Util.compress(data);
|
|
||||||
OutByteBuffer buffer = new OutByteBuffer(connection.getVersion());
|
|
||||||
buffer.writeVarInt(compressed.length);
|
|
||||||
buffer.writeBytes(compressed);
|
|
||||||
outRawBuffer.writeVarInt(buffer.getBytes().size());
|
|
||||||
outRawBuffer.writeBytes(buffer.getOutBytes());
|
|
||||||
} else {
|
|
||||||
outRawBuffer.writeVarInt(data.length + 1); // 1 for the compressed length (0)
|
|
||||||
outRawBuffer.writeVarInt(0);
|
|
||||||
outRawBuffer.writeBytes(data);
|
|
||||||
}
|
|
||||||
data = outRawBuffer.getOutBytes();
|
|
||||||
} else {
|
|
||||||
// append packet length
|
|
||||||
OutByteBuffer bufferWithLengthPrefix = new OutByteBuffer(connection.getVersion());
|
|
||||||
bufferWithLengthPrefix.writeVarInt(data.length);
|
|
||||||
bufferWithLengthPrefix.writeBytes(data);
|
|
||||||
data = bufferWithLengthPrefix.getOutBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binQueue.add(data);
|
|
||||||
if (p instanceof PacketEncryptionResponse) {
|
|
||||||
// enable encryption
|
|
||||||
secretKey = ((PacketEncryptionResponse) p).getSecretKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (binQueueIn.size() > 0) {
|
|
||||||
|
|
||||||
// read data
|
|
||||||
byte[] data = binQueueIn.get(0);
|
|
||||||
binQueueIn.remove(0);
|
|
||||||
if (compressionThreshold != -1) {
|
|
||||||
// compression is enabled
|
|
||||||
// check if there is a need to decompress it and if so, do it!
|
|
||||||
InByteBuffer rawBuffer = new InByteBuffer(data, connection.getVersion());
|
|
||||||
int packetSize = rawBuffer.readVarInt();
|
|
||||||
byte[] left = rawBuffer.readBytesLeft();
|
|
||||||
if (packetSize == 0) {
|
|
||||||
// no need
|
|
||||||
data = left;
|
|
||||||
} else {
|
|
||||||
// need to decompress data
|
|
||||||
data = Util.decompress(left, connection.getVersion()).readBytesLeft();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InPacketBuffer inPacketBuffer = new InPacketBuffer(data, connection.getVersion());
|
|
||||||
try {
|
|
||||||
Packets.Clientbound p = connection.getVersion().getProtocol().getPacketByCommand(connection.getConnectionState(), inPacketBuffer.getCommand());
|
|
||||||
Class<? extends ClientboundPacket> clazz = Protocol.getPacketByPacket(p);
|
|
||||||
|
|
||||||
if (clazz == null) {
|
|
||||||
Log.warn(String.format("[IN] Received unknown packet (id=0x%x, name=%s, length=%d, dataLength=%d, version=%s, state=%s)", inPacketBuffer.getCommand(), ((p != null) ? p.name() : "UNKNOWN"), inPacketBuffer.getLength(), inPacketBuffer.getBytesLeft(), connection.getVersion().name(), connection.getConnectionState().name()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
ClientboundPacket packet = clazz.getConstructor().newInstance();
|
|
||||||
boolean success;
|
|
||||||
if (packet instanceof PacketChunkData) {
|
|
||||||
// this packets need to know if we are in an dimension with skylight...
|
|
||||||
success = ((PacketChunkData) (packet)).read(inPacketBuffer, connection.getPlayer().getWorld().getDimension());
|
|
||||||
} else {
|
|
||||||
success = packet.read(inPacketBuffer);
|
|
||||||
}
|
|
||||||
if (inPacketBuffer.getBytesLeft() > 0 || !success) {
|
|
||||||
// warn not all data used
|
|
||||||
Log.warn(String.format("[IN] Could not parse packet %s (used=%d, available=%d, total=%d, success=%s)", ((p != null) ? p.name() : "null"), inPacketBuffer.getPosition(), inPacketBuffer.getBytesLeft(), inPacketBuffer.getLength(), success));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packet instanceof PacketLoginSuccess) {
|
|
||||||
// login was okay, setting play status to avoid miss timing issues
|
|
||||||
connection.setConnectionState(ConnectionState.PLAY);
|
|
||||||
} else if (packet instanceof PacketLoginSetCompression) {
|
|
||||||
// instantly set compression. because handling is to slow...
|
|
||||||
compressionThreshold = ((PacketLoginSetCompression) packet).getThreshold();
|
|
||||||
}
|
|
||||||
connection.handle(packet);
|
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
|
||||||
// safety first, but will not occur
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.protocol("Received broken packet!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// sleep, wait for an interrupt from other thread
|
|
||||||
//noinspection BusyWait
|
|
||||||
Thread.sleep(100);
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
packetThread.setName("Packet-Thread");
|
|
||||||
packetThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendPacket(ServerboundPacket p) {
|
public void sendPacket(ServerboundPacket p) {
|
||||||
queue.add(p);
|
queue.add(p);
|
||||||
packetThread.interrupt();
|
socketThread.interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableEncryption(SecretKey secretKey) {
|
public void enableEncryption(SecretKey secretKey) {
|
||||||
@ -278,7 +236,7 @@ public class Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
packetThread.interrupt();
|
socketThread.interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,7 @@ public class Util {
|
|||||||
public static void sleep(int ms) {
|
public static void sleep(int ms) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(ms);
|
Thread.sleep(ms);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException ignored) {
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user