#3760: Fix possible NPE when trying to get encoder/decoder protocol

This commit is contained in:
BoomEaro 2024-11-17 11:43:31 +11:00 committed by md_5
parent 4886c4be01
commit 7a42f12716
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
3 changed files with 81 additions and 34 deletions

View File

@ -5,7 +5,6 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Data; import lombok.Data;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -32,7 +31,7 @@ public class ServerConnection implements Server
private final boolean forgeServer = false; private final boolean forgeServer = false;
@Getter @Getter
private final Queue<KeepAliveData> keepAlives = new ArrayDeque<>(); private final Queue<KeepAliveData> keepAlives = new ArrayDeque<>();
private final Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>(); private final Queue<DefinedPacket> packetQueue = new ArrayDeque<>();
private final Unsafe unsafe = new Unsafe() private final Unsafe unsafe = new Unsafe()
{ {
@ -45,23 +44,37 @@ public class ServerConnection implements Server
public void sendPacketQueued(DefinedPacket packet) public void sendPacketQueued(DefinedPacket packet)
{ {
Protocol encodeProtocol = ch.getEncodeProtocol(); ch.scheduleIfNecessary( () ->
if ( !encodeProtocol.TO_SERVER.hasPacket( packet.getClass(), ch.getEncodeVersion() ) )
{ {
packetQueue.add( packet ); if ( ch.isClosed() )
} else {
{ return;
unsafe().sendPacket( packet ); }
} Protocol encodeProtocol = ch.getEncodeProtocol();
if ( !encodeProtocol.TO_SERVER.hasPacket( packet.getClass(), ch.getEncodeVersion() ) )
{
packetQueue.add( packet );
} else
{
unsafe().sendPacket( packet );
}
} );
} }
public void sendQueuedPackets() public void sendQueuedPackets()
{ {
DefinedPacket packet; ch.scheduleIfNecessary( () ->
while ( ( packet = packetQueue.poll() ) != null )
{ {
unsafe().sendPacket( packet ); if ( ch.isClosed() )
} {
return;
}
DefinedPacket packet;
while ( ( packet = packetQueue.poll() ) != null )
{
unsafe().sendPacket( packet );
}
} );
} }
@Override @Override

View File

@ -11,6 +11,7 @@ import io.netty.channel.ChannelOption;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.ArrayDeque;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -21,7 +22,6 @@ import java.util.Objects;
import java.util.Queue; import java.util.Queue;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level; import java.util.logging.Level;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
@ -146,7 +146,7 @@ public final class UserConnection implements ProxiedPlayer
@Setter @Setter
private ForgeServerHandler forgeServerHandler; private ForgeServerHandler forgeServerHandler;
/*========================================================================*/ /*========================================================================*/
private final Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>(); private final Queue<DefinedPacket> packetQueue = new ArrayDeque<>();
private final Unsafe unsafe = new Unsafe() private final Unsafe unsafe = new Unsafe()
{ {
@Override @Override
@ -186,23 +186,37 @@ public final class UserConnection implements ProxiedPlayer
public void sendPacketQueued(DefinedPacket packet) public void sendPacketQueued(DefinedPacket packet)
{ {
Protocol encodeProtocol = ch.getEncodeProtocol(); ch.scheduleIfNecessary( () ->
if ( !encodeProtocol.TO_CLIENT.hasPacket( packet.getClass(), getPendingConnection().getVersion() ) )
{ {
packetQueue.add( packet ); if ( ch.isClosed() )
} else {
{ return;
unsafe().sendPacket( packet ); }
} Protocol encodeProtocol = ch.getEncodeProtocol();
if ( !encodeProtocol.TO_CLIENT.hasPacket( packet.getClass(), getPendingConnection().getVersion() ) )
{
packetQueue.add( packet );
} else
{
unsafe().sendPacket( packet );
}
} );
} }
public void sendQueuedPackets() public void sendQueuedPackets()
{ {
DefinedPacket packet; ch.scheduleIfNecessary( () ->
while ( ( packet = packetQueue.poll() ) != null )
{ {
unsafe().sendPacket( packet ); if ( ch.isClosed() )
} {
return;
}
DefinedPacket packet;
while ( ( packet = packetQueue.poll() ) != null )
{
unsafe().sendPacket( packet );
}
} );
} }
@Deprecated @Deprecated

View File

@ -42,23 +42,22 @@ public class ChannelWrapper
public Protocol getDecodeProtocol() public Protocol getDecodeProtocol()
{ {
return ch.pipeline().get( MinecraftDecoder.class ).getProtocol(); return getMinecraftDecoder().getProtocol();
} }
public void setDecodeProtocol(Protocol protocol) public void setDecodeProtocol(Protocol protocol)
{ {
ch.pipeline().get( MinecraftDecoder.class ).setProtocol( protocol ); getMinecraftDecoder().setProtocol( protocol );
} }
public Protocol getEncodeProtocol() public Protocol getEncodeProtocol()
{ {
return ch.pipeline().get( MinecraftEncoder.class ).getProtocol(); return getMinecraftEncoder().getProtocol();
} }
public void setEncodeProtocol(Protocol protocol) public void setEncodeProtocol(Protocol protocol)
{ {
ch.pipeline().get( MinecraftEncoder.class ).setProtocol( protocol ); getMinecraftEncoder().setProtocol( protocol );
} }
public void setProtocol(Protocol protocol) public void setProtocol(Protocol protocol)
@ -69,13 +68,23 @@ public class ChannelWrapper
public void setVersion(int protocol) public void setVersion(int protocol)
{ {
ch.pipeline().get( MinecraftDecoder.class ).setProtocolVersion( protocol ); getMinecraftDecoder().setProtocolVersion( protocol );
ch.pipeline().get( MinecraftEncoder.class ).setProtocolVersion( protocol ); getMinecraftEncoder().setProtocolVersion( protocol );
}
public MinecraftDecoder getMinecraftDecoder()
{
return ch.pipeline().get( MinecraftDecoder.class );
}
public MinecraftEncoder getMinecraftEncoder()
{
return ch.pipeline().get( MinecraftEncoder.class );
} }
public int getEncodeVersion() public int getEncodeVersion()
{ {
return ch.pipeline().get( MinecraftEncoder.class ).getProtocolVersion(); return getMinecraftEncoder().getProtocolVersion();
} }
public void write(Object packet) public void write(Object packet)
@ -223,4 +232,15 @@ public class ChannelWrapper
packetCompressor.setCompose( compressorCompose ); packetCompressor.setCompose( compressorCompose );
} }
} }
public void scheduleIfNecessary(Runnable task)
{
if ( ch.eventLoop().inEventLoop() )
{
task.run();
return;
}
ch.eventLoop().execute( task );
}
} }