mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-09 01:47:54 +01:00
Fix connection crash
Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
parent
548cee55e0
commit
66b567597a
@ -8,8 +8,7 @@ import java.nio.ByteBuffer;
|
|||||||
* Represents a packet which is already framed. (packet id+payload) + optional compression
|
* Represents a packet which is already framed. (packet id+payload) + optional compression
|
||||||
* Can be used if you want to send the exact same buffer to multiple clients without processing it more than once.
|
* Can be used if you want to send the exact same buffer to multiple clients without processing it more than once.
|
||||||
*/
|
*/
|
||||||
public class FramedPacket {
|
public final class FramedPacket {
|
||||||
|
|
||||||
private final ByteBuffer body;
|
private final ByteBuffer body;
|
||||||
|
|
||||||
public FramedPacket(@NotNull ByteBuffer body) {
|
public FramedPacket(@NotNull ByteBuffer body) {
|
||||||
|
@ -64,16 +64,12 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
private PlayerSkin bungeeSkin;
|
private PlayerSkin bungeeSkin;
|
||||||
|
|
||||||
private final ByteBuffer tickBuffer = ByteBuffer.allocateDirect(Server.SOCKET_BUFFER_SIZE);
|
private final ByteBuffer tickBuffer = ByteBuffer.allocateDirect(Server.SOCKET_BUFFER_SIZE);
|
||||||
private ByteBuffer cacheBuffer;
|
private volatile ByteBuffer cacheBuffer;
|
||||||
|
|
||||||
public NettyPlayerConnection(@NotNull SocketChannel channel) {
|
public NettyPlayerConnection(@NotNull SocketChannel channel, SocketAddress remoteAddress) {
|
||||||
super();
|
super();
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
try {
|
this.remoteAddress = remoteAddress;
|
||||||
this.remoteAddress = channel.getRemoteAddress();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processPackets(Worker.Context workerContext, PacketProcessor packetProcessor) {
|
public void processPackets(Worker.Context workerContext, PacketProcessor packetProcessor) {
|
||||||
@ -133,8 +129,8 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
readBuffer.limit(limit).position(packetEnd);
|
readBuffer.limit(limit).position(packetEnd);
|
||||||
} catch (BufferUnderflowException e) {
|
} catch (BufferUnderflowException e) {
|
||||||
readBuffer.reset();
|
readBuffer.reset();
|
||||||
this.cacheBuffer = ByteBuffer.allocateDirect(readBuffer.remaining());
|
this.cacheBuffer = ByteBuffer.allocateDirect(readBuffer.remaining())
|
||||||
this.cacheBuffer.put(readBuffer).flip();
|
.put(readBuffer).flip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +187,7 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
serverPacket = ((ComponentHoldingServerPacket) serverPacket).copyWithOperator(component ->
|
serverPacket = ((ComponentHoldingServerPacket) serverPacket).copyWithOperator(component ->
|
||||||
GlobalTranslator.render(component, Objects.requireNonNullElseGet(getPlayer().getLocale(), MinestomAdventure::getDefaultLocale)));
|
GlobalTranslator.render(component, Objects.requireNonNullElseGet(getPlayer().getLocale(), MinestomAdventure::getDefaultLocale)));
|
||||||
}
|
}
|
||||||
attemptWrite(PacketUtils.createFramedPacket(serverPacket));
|
attemptWrite(serverPacket);
|
||||||
} else {
|
} else {
|
||||||
// Player is probably not logged yet
|
// Player is probably not logged yet
|
||||||
writeAndFlush(serverPacket);
|
writeAndFlush(serverPacket);
|
||||||
@ -209,16 +205,33 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
|
|
||||||
public void writeAndFlush(@NotNull ServerPacket packet) {
|
public void writeAndFlush(@NotNull ServerPacket packet) {
|
||||||
synchronized (tickBuffer) {
|
synchronized (tickBuffer) {
|
||||||
PacketUtils.writeFramedPacket(tickBuffer, packet, compressed);
|
attemptWrite(packet);
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void attemptWrite(ServerPacket packet) {
|
||||||
|
synchronized (tickBuffer) {
|
||||||
|
final int position = tickBuffer.position();
|
||||||
|
try {
|
||||||
|
PacketUtils.writeFramedPacket(tickBuffer, packet, compressed);
|
||||||
|
} catch (BufferOverflowException e) {
|
||||||
|
try {
|
||||||
|
this.channel.write(tickBuffer.position(position).flip());
|
||||||
|
this.tickBuffer.clear();
|
||||||
|
PacketUtils.writeFramedPacket(tickBuffer, packet, compressed);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
disconnect();
|
||||||
|
MinecraftServer.getExceptionManager().handleException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void attemptWrite(ByteBuffer buffer) {
|
public void attemptWrite(ByteBuffer buffer) {
|
||||||
buffer.flip();
|
|
||||||
synchronized (tickBuffer) {
|
synchronized (tickBuffer) {
|
||||||
try {
|
try {
|
||||||
this.tickBuffer.put(buffer);
|
this.tickBuffer.put(buffer.flip());
|
||||||
} catch (BufferOverflowException e) {
|
} catch (BufferOverflowException e) {
|
||||||
try {
|
try {
|
||||||
this.channel.write(tickBuffer.flip());
|
this.channel.write(tickBuffer.flip());
|
||||||
@ -235,13 +248,12 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
synchronized (tickBuffer) {
|
synchronized (tickBuffer) {
|
||||||
this.tickBuffer.flip();
|
if (tickBuffer.position() == 0) {
|
||||||
if (tickBuffer.remaining() == 0) {
|
|
||||||
// Nothing to write
|
// Nothing to write
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.channel.write(tickBuffer);
|
this.channel.write(tickBuffer.flip());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
}
|
||||||
@ -402,9 +414,6 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseTickBuffer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getNonce() {
|
public byte[] getNonce() {
|
||||||
return nonce;
|
return nonce;
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,7 @@ public class Worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void receiveConnection(SocketChannel channel) throws IOException {
|
public void receiveConnection(SocketChannel channel) throws IOException {
|
||||||
var connection = new NettyPlayerConnection(channel);
|
this.connectionMap.put(channel, new NettyPlayerConnection(channel, channel.getRemoteAddress()));
|
||||||
this.connectionMap.put(channel, connection);
|
|
||||||
register(channel);
|
register(channel);
|
||||||
this.selector.wakeup();
|
this.selector.wakeup();
|
||||||
}
|
}
|
||||||
@ -91,7 +90,7 @@ public class Worker {
|
|||||||
private void disconnect(NettyPlayerConnection connection, SocketChannel channel) throws IOException {
|
private void disconnect(NettyPlayerConnection connection, SocketChannel channel) throws IOException {
|
||||||
// Client close
|
// Client close
|
||||||
channel.close();
|
channel.close();
|
||||||
connectionMap.remove(channel);
|
this.connectionMap.remove(channel);
|
||||||
// Remove the connection
|
// Remove the connection
|
||||||
connection.refreshOnline(false);
|
connection.refreshOnline(false);
|
||||||
Player player = connection.getPlayer();
|
Player player = connection.getPlayer();
|
||||||
|
@ -89,7 +89,8 @@ public final class PacketUtils {
|
|||||||
// Send grouped packet...
|
// Send grouped packet...
|
||||||
final boolean success = PACKET_LISTENER_MANAGER.processServerPacket(packet, players);
|
final boolean success = PACKET_LISTENER_MANAGER.processServerPacket(packet, players);
|
||||||
if (success) {
|
if (success) {
|
||||||
final ByteBuffer finalBuffer = createFramedPacket(packet);
|
ByteBuffer finalBuffer = ByteBuffer.allocate(2_000_000);
|
||||||
|
writeFramedPacket(finalBuffer, packet, MinecraftServer.getCompressionThreshold() > 0);
|
||||||
final FramedPacket framedPacket = new FramedPacket(finalBuffer);
|
final FramedPacket framedPacket = new FramedPacket(finalBuffer);
|
||||||
// Send packet to all players
|
// Send packet to all players
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
@ -98,7 +99,6 @@ public final class PacketUtils {
|
|||||||
// Verify if the player should receive the packet
|
// Verify if the player should receive the packet
|
||||||
if (playerValidator != null && !playerValidator.isValid(player))
|
if (playerValidator != null && !playerValidator.isValid(player))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||||
if (playerConnection instanceof NettyPlayerConnection) {
|
if (playerConnection instanceof NettyPlayerConnection) {
|
||||||
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) playerConnection;
|
final NettyPlayerConnection nettyPlayerConnection = (NettyPlayerConnection) playerConnection;
|
||||||
@ -114,8 +114,7 @@ public final class PacketUtils {
|
|||||||
// Verify if the player should receive the packet
|
// Verify if the player should receive the packet
|
||||||
if (playerValidator != null && !playerValidator.isValid(player))
|
if (playerValidator != null && !playerValidator.isValid(player))
|
||||||
continue;
|
continue;
|
||||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
player.getPlayerConnection().sendPacket(packet, false);
|
||||||
playerConnection.sendPacket(packet, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,11 +153,11 @@ public final class PacketUtils {
|
|||||||
// Packet large enough, compress
|
// Packet large enough, compress
|
||||||
final int limitCache = buffer.limit();
|
final int limitCache = buffer.limit();
|
||||||
buffer.position(contentStart).limit(contentStart + packetSize);
|
buffer.position(contentStart).limit(contentStart + packetSize);
|
||||||
var uncompressedCopy = ByteBuffer.allocate(packetSize).put(buffer);
|
var uncompressedCopy = ByteBuffer.allocate(packetSize).put(buffer).flip();
|
||||||
buffer.position(contentStart).limit(limitCache);
|
buffer.position(contentStart).limit(limitCache);
|
||||||
|
|
||||||
var deflater = COMPRESSOR.get();
|
var deflater = COMPRESSOR.get();
|
||||||
deflater.setInput(uncompressedCopy.flip());
|
deflater.setInput(uncompressedCopy);
|
||||||
deflater.finish();
|
deflater.finish();
|
||||||
deflater.deflate(buffer);
|
deflater.deflate(buffer);
|
||||||
deflater.reset();
|
deflater.reset();
|
||||||
@ -170,17 +169,4 @@ public final class PacketUtils {
|
|||||||
Utils.writeVarIntHeader(buffer, uncompressedIndex, 0);
|
Utils.writeVarIntHeader(buffer, uncompressedIndex, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a "framed packet" (packet which can be send and understood by a Minecraft client)
|
|
||||||
* from a server packet, directly into an output buffer.
|
|
||||||
* <p>
|
|
||||||
* Can be used if you want to store a raw buffer and send it later without the additional writing cost.
|
|
||||||
* Compression is applied if {@link MinecraftServer#getCompressionThreshold()} is greater than 0.
|
|
||||||
*/
|
|
||||||
public static @NotNull ByteBuffer createFramedPacket(@NotNull ServerPacket serverPacket) {
|
|
||||||
ByteBuffer packetBuf = ByteBuffer.allocate(2_000_000);
|
|
||||||
writeFramedPacket(packetBuf, serverPacket, MinecraftServer.getCompressionThreshold() > 0);
|
|
||||||
return packetBuf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user