From f90a7324e4589230a908d039e117702688b96ce6 Mon Sep 17 00:00:00 2001 From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com> Date: Sat, 24 Dec 2022 22:15:56 +0000 Subject: [PATCH] Improved pending data read logic. --- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- .../l2jmobius/commons/network/NetClient.java | 42 +++++++ .../l2jmobius/commons/network/ReadThread.java | 107 ++++++++++++++++-- 62 files changed, 4247 insertions(+), 372 deletions(-) diff --git a/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_01.0_Ertheia/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_02.5_Underground/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_03.0_Helios/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_04.0_GrandCrusade/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_05.0_Salvation/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_05.5_EtinasFate/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_06.0_Fafurion/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_07.0_PreludeOfWar/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_08.2_Homunculus/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_09.2_ReturnOfTheQueenAnt/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_10.3_MasterClass/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_C4_ScionsOfDestiny/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_C6_Interlude/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_CT_0_Interlude/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_CT_2.4_Epilogue/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_CT_2.6_HighFive/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_1.0/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_1.5_AgeOfSplendor/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.5_Zaken/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.7_Antharas/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.8_SevenSigns/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.9.5_Saviors/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_2.9_SecretOfEmpire/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Classic_Interlude/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } } diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/NetClient.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/NetClient.java index a787018b3b..c1fb2b83d5 100644 --- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/NetClient.java +++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/NetClient.java @@ -1,5 +1,6 @@ package org.l2jmobius.commons.network; +import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -17,6 +18,8 @@ public class NetClient private SocketChannel _channel; private NetConfig _netConfig; private Queue _pendingPacketData; + private ByteBuffer _pendingByteBuffer; + private int _pendingPacketSize; /** * Initialize the client. @@ -77,6 +80,11 @@ public class NetClient { _pendingPacketData.clear(); } + + if (_pendingByteBuffer != null) + { + _pendingByteBuffer = null; + } } /** @@ -124,6 +132,40 @@ public class NetClient return _pendingPacketData; } + /** + * @return the pending read ByteBuffer. + */ + public ByteBuffer getPendingByteBuffer() + { + return _pendingByteBuffer; + } + + /** + * Set the pending read ByteBuffer. + * @param pendingByteBuffer the pending read ByteBuffer. + */ + public void setPendingByteBuffer(ByteBuffer pendingByteBuffer) + { + _pendingByteBuffer = pendingByteBuffer; + } + + /** + * @return the expected pending packet size. + */ + public int getPendingPacketSize() + { + return _pendingPacketSize; + } + + /** + * Set the expected pending packet size. + * @param pendingPacketSize the expected packet size. + */ + public void setPendingPacketSize(int pendingPacketSize) + { + _pendingPacketSize = pendingPacketSize; + } + /** * @return the Encryption of this client. */ diff --git a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/ReadThread.java b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/ReadThread.java index 9cf00e3486..baef290f2f 100644 --- a/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/ReadThread.java +++ b/L2J_Mobius_Essence_6.3_Crusader/java/org/l2jmobius/commons/network/ReadThread.java @@ -13,6 +13,7 @@ import java.util.Set; public class ReadThread implements Runnable { private final ByteBuffer _sizeBuffer = ByteBuffer.allocate(2); // Reusable size buffer. + private final ByteBuffer _pendingSizeBuffer = ByteBuffer.allocate(1); // Reusable pending size buffer. private final Set _pool; public ReadThread(Set pool) @@ -45,6 +46,45 @@ public class ReadThread implements Runnable continue ITERATE; } + // Continue read if there is a pending ByteBuffer. + final ByteBuffer pendingByteBuffer = client.getPendingByteBuffer(); + if (pendingByteBuffer != null) + { + // Allocate an additional ByteBuffer based on pending packet size. + final int pendingPacketSize = client.getPendingPacketSize(); + final ByteBuffer additionalData = ByteBuffer.allocate(pendingPacketSize - pendingByteBuffer.position()); + switch (channel.read(additionalData)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue ITERATE; + } + // Data was read. + default: + { + // Merge additional read data. + pendingByteBuffer.put(pendingByteBuffer.position(), additionalData, 0, additionalData.position()); + pendingByteBuffer.position(pendingByteBuffer.position() + additionalData.position()); + + // Read was complete. + if (pendingByteBuffer.position() >= pendingPacketSize) + { + // Add packet data to client. + client.addPacketData(pendingByteBuffer.array()); + client.setPendingByteBuffer(null); + } + } + } + continue ITERATE; + } + // Read incoming packet size (short). _sizeBuffer.clear(); switch (channel.read(_sizeBuffer)) @@ -60,6 +100,54 @@ public class ReadThread implements Runnable { continue ITERATE; } + // Need to read two bytes to calculate size. + case 1: + { + int attempt = 0; // Keep it under 10 attempts (100ms). + COMPLETE_SIZE_READ: while ((attempt++ < 10) && (_sizeBuffer.position() < 2)) + { + // Wait for pending data. + try + { + Thread.sleep(10); + } + catch (Exception ignored) + { + } + + // Try to read the missing extra byte. + _pendingSizeBuffer.clear(); + switch (channel.read(_pendingSizeBuffer)) + { + // Disconnected. + case -1: + { + onDisconnection(client); + continue ITERATE; + } + // Nothing read. + case 0: + { + continue COMPLETE_SIZE_READ; + } + // Merge additional read byte. + default: + { + _sizeBuffer.put(1, _pendingSizeBuffer, 0, 1); + _sizeBuffer.position(2); + } + } + } + + // Read failed. + if (_sizeBuffer.position() < 2) + { + onDisconnection(client); + continue ITERATE; + } + + // Fallthrough. + } // Read actual packet bytes. default: { @@ -82,21 +170,16 @@ public class ReadThread implements Runnable // Send data read to the client packet queue. default: { - // Continue read if data length is less than expected. + // Read was not complete. if (packetByteBuffer.position() < packetSize) { - int attempt = 0; // Keep it under 10 attempts. - while ((attempt++ < 10) && (packetByteBuffer.position() < packetSize)) - { - final ByteBuffer additionalData = ByteBuffer.allocate(packetSize - packetByteBuffer.position()); - channel.read(additionalData); - packetByteBuffer.put(packetByteBuffer.position(), additionalData, 0, additionalData.position()); - packetByteBuffer.position(packetByteBuffer.position() + additionalData.position()); - } + client.setPendingByteBuffer(packetByteBuffer); + client.setPendingPacketSize(packetSize); + } + else // Add packet data to client. + { + client.addPacketData(packetByteBuffer.array()); } - - // Add packet data to client. - client.addPacketData(packetByteBuffer.array()); } } }