mirror of
https://github.com/PaperMC/Velocity.git
synced 2026-04-19 19:08:16 +02:00
use outbound only queueing when reentering configuration (#1747)
* use outbound only queueing and guard serverbound forwarding during reconfiguration
This commit is contained in:
@@ -33,6 +33,7 @@ import com.velocitypowered.natives.encryption.VelocityCipher;
|
|||||||
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
|
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
|
||||||
import com.velocitypowered.natives.util.Natives;
|
import com.velocitypowered.natives.util.Natives;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
|
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
|
||||||
import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
|
import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
|
||||||
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
|
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
|
||||||
@@ -368,6 +369,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
|||||||
public void setState(StateRegistry state) {
|
public void setState(StateRegistry state) {
|
||||||
ensureInEventLoop();
|
ensureInEventLoop();
|
||||||
|
|
||||||
|
final StateRegistry previousState = this.state;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
final MinecraftVarintFrameDecoder frameDecoder = this.channel.pipeline()
|
final MinecraftVarintFrameDecoder frameDecoder = this.channel.pipeline()
|
||||||
.get(MinecraftVarintFrameDecoder.class);
|
.get(MinecraftVarintFrameDecoder.class);
|
||||||
@@ -388,7 +390,13 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
if (state == StateRegistry.CONFIG) {
|
if (state == StateRegistry.CONFIG) {
|
||||||
// Activate the play packet queue
|
// Activate the play packet queue
|
||||||
addPlayPacketQueueHandler();
|
if (previousState == StateRegistry.PLAY
|
||||||
|
&& this.pendingConfigurationSwitch
|
||||||
|
&& this.association instanceof ConnectedPlayer) {
|
||||||
|
addPlayPacketQueueOutboundHandler();
|
||||||
|
} else {
|
||||||
|
addPlayPacketQueueHandler();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Remove the queue
|
// Remove the queue
|
||||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) != null) {
|
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) != null) {
|
||||||
@@ -404,13 +412,23 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
|||||||
* Adds the play packet queue handler.
|
* Adds the play packet queue handler.
|
||||||
*/
|
*/
|
||||||
public void addPlayPacketQueueHandler() {
|
public void addPlayPacketQueueHandler() {
|
||||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) == null) {
|
addPlayPacketQueueOutboundHandler();
|
||||||
this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE_OUTBOUND,
|
|
||||||
new PlayPacketQueueOutboundHandler(this.protocolVersion, channel.pipeline().get(MinecraftEncoder.class).getDirection()));
|
|
||||||
}
|
|
||||||
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_INBOUND) == null) {
|
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_INBOUND) == null) {
|
||||||
this.channel.pipeline().addAfter(Connections.MINECRAFT_DECODER, Connections.PLAY_PACKET_QUEUE_INBOUND,
|
this.channel.pipeline().addAfter(Connections.MINECRAFT_DECODER, Connections.PLAY_PACKET_QUEUE_INBOUND,
|
||||||
new PlayPacketQueueInboundHandler(this.protocolVersion, channel.pipeline().get(MinecraftDecoder.class).getDirection()));
|
new PlayPacketQueueInboundHandler(this.protocolVersion,
|
||||||
|
channel.pipeline().get(MinecraftDecoder.class).getDirection()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds only the outbound play packet queue handler.
|
||||||
|
*/
|
||||||
|
public void addPlayPacketQueueOutboundHandler() {
|
||||||
|
if (this.channel.pipeline().get(Connections.PLAY_PACKET_QUEUE_OUTBOUND) == null) {
|
||||||
|
this.channel.pipeline().addAfter(Connections.MINECRAFT_ENCODER, Connections.PLAY_PACKET_QUEUE_OUTBOUND,
|
||||||
|
new PlayPacketQueueOutboundHandler(this.protocolVersion,
|
||||||
|
channel.pipeline().get(MinecraftEncoder.class).getDirection()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -470,7 +470,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConnection smc = serverConnection.getConnection();
|
MinecraftConnection smc = serverConnection.getConnection();
|
||||||
if (smc != null && serverConnection.getPhase().consideredComplete()) {
|
final boolean stateAllowsForward = smc != null
|
||||||
|
&& !smc.isClosed()
|
||||||
|
&& serverConnection.getPhase().consideredComplete()
|
||||||
|
&& smc.getState() == StateRegistry.PLAY;
|
||||||
|
if (stateAllowsForward) {
|
||||||
if (packet instanceof PluginMessagePacket) {
|
if (packet instanceof PluginMessagePacket) {
|
||||||
((PluginMessagePacket) packet).retain();
|
((PluginMessagePacket) packet).retain();
|
||||||
}
|
}
|
||||||
@@ -487,7 +491,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConnection smc = serverConnection.getConnection();
|
MinecraftConnection smc = serverConnection.getConnection();
|
||||||
if (smc != null && !smc.isClosed() && serverConnection.getPhase().consideredComplete()) {
|
final boolean stateAllowsForward = smc != null
|
||||||
|
&& !smc.isClosed()
|
||||||
|
&& serverConnection.getPhase().consideredComplete()
|
||||||
|
&& smc.getState() == StateRegistry.PLAY;
|
||||||
|
if (stateAllowsForward) {
|
||||||
smc.write(buf.retain());
|
smc.write(buf.retain());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1349,11 +1349,17 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
final Long sentTime = serverConnection.getPendingPings().remove(packet.getRandomId());
|
final Long sentTime = serverConnection.getPendingPings().remove(packet.getRandomId());
|
||||||
if (sentTime != null) {
|
if (sentTime != null) {
|
||||||
final MinecraftConnection smc = serverConnection.getConnection();
|
final MinecraftConnection smc = serverConnection.getConnection();
|
||||||
if (smc != null) {
|
final StateRegistry clientState = connection.getState();
|
||||||
|
final boolean stateAllowsForward = smc != null
|
||||||
|
&& !smc.isClosed()
|
||||||
|
&& clientState == smc.getState()
|
||||||
|
&& (clientState == StateRegistry.CONFIG || clientState == StateRegistry.PLAY);
|
||||||
|
if (stateAllowsForward) {
|
||||||
setPing(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - sentTime));
|
setPing(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - sentTime));
|
||||||
smc.write(packet);
|
smc.write(packet);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
// We removed this, and so this is ours
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1363,7 +1369,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
* Switches the connection to the client into config state.
|
* Switches the connection to the client into config state.
|
||||||
*/
|
*/
|
||||||
public void switchToConfigState() {
|
public void switchToConfigState() {
|
||||||
server.getEventManager().fire(new PlayerEnterConfigurationEvent(this, getConnectionInFlightOrConnectedServer()))
|
final VelocityServerConnection targetServer = getConnectionInFlightOrConnectedServer();
|
||||||
|
server.getEventManager().fire(new PlayerEnterConfigurationEvent(this, targetServer))
|
||||||
.completeOnTimeout(null, 5, TimeUnit.SECONDS).thenRunAsync(() -> {
|
.completeOnTimeout(null, 5, TimeUnit.SECONDS).thenRunAsync(() -> {
|
||||||
// if the connection was closed earlier, there is a risk that the player is no longer connected
|
// if the connection was closed earlier, there is a risk that the player is no longer connected
|
||||||
if (!connection.getChannel().isActive()) {
|
if (!connection.getChannel().isActive()) {
|
||||||
@@ -1378,7 +1385,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player,
|
|||||||
connection.pendingConfigurationSwitch = true;
|
connection.pendingConfigurationSwitch = true;
|
||||||
connection.getChannel().pipeline().get(MinecraftEncoder.class).setState(StateRegistry.CONFIG);
|
connection.getChannel().pipeline().get(MinecraftEncoder.class).setState(StateRegistry.CONFIG);
|
||||||
// Make sure we don't send any play packets to the player after update start
|
// Make sure we don't send any play packets to the player after update start
|
||||||
connection.addPlayPacketQueueHandler();
|
connection.addPlayPacketQueueOutboundHandler();
|
||||||
}, connection.eventLoop()).exceptionally((ex) -> {
|
}, connection.eventLoop()).exceptionally((ex) -> {
|
||||||
logger.error("Error switching player connection to config state", ex);
|
logger.error("Error switching player connection to config state", ex);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user