Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public enum ProtocolVersion {
MINECRAFT_1_19_3(761, "1.19.3"),
MINECRAFT_1_19_4(762, "1.19.4"),
MINECRAFT_1_20(763, "1.20", "1.20.1"),
MINECRAFT_1_20_2(-1 /*764*/, 144, "1.20.2");
MINECRAFT_1_20_2(-1 /*764*/, 145, "1.20.2");

private static final int SNAPSHOT_BIT = 30;

Expand Down
Empty file.
Empty file.
Empty file modified native/src/main/resources/linux_aarch64/velocity-compress.so
100755 → 100644
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified native/src/main/resources/linux_x86_64/velocity-compress.so
100755 → 100644
Empty file.
Empty file modified native/src/main/resources/macos_arm64/velocity-cipher.dylib
100755 → 100644
Empty file.
Empty file modified native/src/main/resources/macos_arm64/velocity-compress.dylib
100755 → 100644
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.VelocityConnectionEvent;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder;
Expand All @@ -60,6 +61,9 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
Expand All @@ -78,7 +82,8 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
private final Channel channel;
private SocketAddress remoteAddress;
private StateRegistry state;
private @Nullable MinecraftSessionHandler sessionHandler;
private Map<StateRegistry, MinecraftSessionHandler> sessionHandlers;
private @Nullable MinecraftSessionHandler activeSessionHandler;
private ProtocolVersion protocolVersion;
private @Nullable MinecraftConnectionAssociation association;
public final VelocityServer server;
Expand All @@ -96,12 +101,14 @@ public MinecraftConnection(Channel channel, VelocityServer server) {
this.remoteAddress = channel.remoteAddress();
this.server = server;
this.state = StateRegistry.HANDSHAKE;

this.sessionHandlers = new HashMap<>();
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.connected();
if (activeSessionHandler != null) {
activeSessionHandler.connected();
}

if (association != null && server.getConfiguration().isLogPlayerConnections()) {
Expand All @@ -111,12 +118,12 @@ public void channelActive(ChannelHandlerContext ctx) throws Exception {

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.disconnected();
if (activeSessionHandler != null) {
activeSessionHandler.disconnected();
}

if (association != null && !knownDisconnect
&& !(sessionHandler instanceof StatusSessionHandler)
&& !(activeSessionHandler instanceof StatusSessionHandler)
&& server.getConfiguration().isLogPlayerConnections()) {
logger.info("{} has disconnected", association);
}
Expand All @@ -125,12 +132,12 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
if (sessionHandler == null) {
if (activeSessionHandler == null) {
// No session handler available, do nothing
return;
}

if (sessionHandler.beforeHandle()) {
if (activeSessionHandler.beforeHandle()) {
return;
}

Expand All @@ -140,15 +147,15 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

if (msg instanceof MinecraftPacket) {
MinecraftPacket pkt = (MinecraftPacket) msg;
if (!pkt.handle(sessionHandler)) {
sessionHandler.handleGeneric((MinecraftPacket) msg);
if (!pkt.handle(activeSessionHandler)) {
activeSessionHandler.handleGeneric((MinecraftPacket) msg);
}
} else if (msg instanceof HAProxyMessage) {
HAProxyMessage proxyMessage = (HAProxyMessage) msg;
this.remoteAddress = new InetSocketAddress(proxyMessage.sourceAddress(),
proxyMessage.sourcePort());
} else if (msg instanceof ByteBuf) {
sessionHandler.handleUnknown((ByteBuf) msg);
activeSessionHandler.handleUnknown((ByteBuf) msg);
}
} finally {
ReferenceCountUtil.release(msg);
Expand All @@ -157,34 +164,34 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.readCompleted();
if (activeSessionHandler != null) {
activeSessionHandler.readCompleted();
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (ctx.channel().isActive()) {
if (sessionHandler != null) {
if (activeSessionHandler != null) {
try {
sessionHandler.exception(cause);
activeSessionHandler.exception(cause);
} catch (Exception ex) {
logger.error("{}: exception handling exception in {}",
(association != null ? association : channel.remoteAddress()), sessionHandler, cause);
(association != null ? association : channel.remoteAddress()), activeSessionHandler, cause);
}
}

if (association != null) {
if (cause instanceof ReadTimeoutException) {
logger.error("{}: read timed out", association);
} else {
boolean frontlineHandler = sessionHandler instanceof InitialLoginSessionHandler
|| sessionHandler instanceof HandshakeSessionHandler
|| sessionHandler instanceof StatusSessionHandler;
boolean frontlineHandler = activeSessionHandler instanceof InitialLoginSessionHandler
|| activeSessionHandler instanceof HandshakeSessionHandler
|| activeSessionHandler instanceof StatusSessionHandler;
boolean isQuietDecoderException = cause instanceof QuietDecoderException;
boolean willLog = !isQuietDecoderException && !frontlineHandler;
if (willLog) {
logger.error("{}: exception encountered in {}", association, sessionHandler, cause);
logger.error("{}: exception encountered in {}", association, activeSessionHandler, cause);
} else {
knownDisconnect = true;
}
Expand All @@ -197,8 +204,8 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E

@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
if (sessionHandler != null) {
sessionHandler.writabilityChanged();
if (activeSessionHandler != null) {
activeSessionHandler.writabilityChanged();
}
}

Expand Down Expand Up @@ -341,12 +348,8 @@ public void setAutoReading(boolean autoReading) {
}
}

/**
* Changes the state of the Minecraft connection.
*
* @param state the new state
*/
public void setState(StateRegistry state) {
// Ideally only used by the state switch
private void setState(StateRegistry state) {
ensureInEventLoop();

this.state = state;
Expand Down Expand Up @@ -382,25 +385,73 @@ public void setProtocolVersion(ProtocolVersion protocolVersion) {
}
}

public @Nullable MinecraftSessionHandler getSessionHandler() {
return sessionHandler;
public @Nullable MinecraftSessionHandler getActiveSessionHandler() {
return activeSessionHandler;
}

public @Nullable MinecraftSessionHandler getSessionHandlerForRegistry(StateRegistry registry) {
return this.sessionHandlers.getOrDefault(registry, null);
}

/**
* Sets the session handler for this connection.
*
* @param registry the registry of the handler
* @param sessionHandler the handler to use
*/
public void setSessionHandler(MinecraftSessionHandler sessionHandler) {
public void setActiveSessionHandler(StateRegistry registry, MinecraftSessionHandler sessionHandler) {
Preconditions.checkNotNull(registry);
ensureInEventLoop();

if (this.sessionHandler != null) {
this.sessionHandler.deactivated();
if (this.activeSessionHandler != null) {
this.activeSessionHandler.deactivated();
}
this.sessionHandler = sessionHandler;
this.sessionHandlers.put(registry, sessionHandler);
this.activeSessionHandler = sessionHandler;
setState(registry);
sessionHandler.activated();
}

/**
* Switches the active session handler to the respective registry one.
*
* @param registry the registry of the handler
* @return true if successful and handler is present
*/
public boolean setActiveSessionHandler(StateRegistry registry) {
Preconditions.checkNotNull(registry);
ensureInEventLoop();

MinecraftSessionHandler handler = getSessionHandlerForRegistry(registry);
if (handler != null) {
boolean flag = true;
if (this.activeSessionHandler != null
&& (flag = !Objects.equals(handler, this.activeSessionHandler))) {
this.activeSessionHandler.deactivated();
}
this.activeSessionHandler = handler;
setState(registry);
if (flag) {
handler.activated();
}
}
return handler != null;
}

/**
* Adds a secondary session handler for this connection.
*
* @param registry the registry of the handler
* @param sessionHandler the handler to use
*/
public void addSessionHandler(StateRegistry registry, MinecraftSessionHandler sessionHandler) {
Preconditions.checkNotNull(registry);
Preconditions.checkArgument(registry != state, "Handler would overwrite handler");
ensureInEventLoop();

this.sessionHandlers.put(registry, sessionHandler);
}

private void ensureOpen() {
Preconditions.checkState(!isClosed(), "Connection is closed.");
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
*/
public class BackendPlaySessionHandler implements MinecraftSessionHandler {

private static final Pattern PLAUSIBLE_SHA1_HASH = Pattern.compile("^[a-z0-9]{40}$");
private static final Logger logger = LogManager.getLogger(BackendPlaySessionHandler.class);
private static final boolean BACKPRESSURE_LOG = Boolean
.getBoolean("velocity.log-server-backpressure");
Expand All @@ -86,7 +85,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
this.serverConn = serverConn;
this.playerConnection = serverConn.getPlayer().getConnection();

MinecraftSessionHandler psh = playerConnection.getSessionHandler();
MinecraftSessionHandler psh = playerConnection.getActiveSessionHandler();
if (!(psh instanceof ClientPlaySessionHandler)) {
throw new IllegalStateException(
"Initializing BackendPlaySessionHandler with no backing client play session handler!");
Expand All @@ -103,9 +102,10 @@ public void activated() {

if (server.getConfiguration().isBungeePluginChannelEnabled()) {
MinecraftConnection serverMc = serverConn.ensureConnected();
serverMc.write(PluginMessageUtil.constructChannelsPacket(serverMc.getProtocolVersion(),
ImmutableList.of(getBungeeCordChannel(serverMc.getProtocolVersion()))
));
if (serverMc.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_20_2) < 0)
serverMc.write(PluginMessageUtil.constructChannelsPacket(serverMc.getProtocolVersion(),
ImmutableList.of(getBungeeCordChannel(serverMc.getProtocolVersion()))
));
}
}

Expand Down Expand Up @@ -144,21 +144,8 @@ public boolean handle(BossBar packet) {

@Override
public boolean handle(ResourcePackRequest packet) {
ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(
Preconditions.checkNotNull(packet.getUrl()))
.setPrompt(packet.getPrompt())
.setShouldForce(packet.isRequired())
.setOrigin(ResourcePackInfo.Origin.DOWNSTREAM_SERVER);

String hash = packet.getHash();
if (hash != null && !hash.isEmpty()) {
if (PLAUSIBLE_SHA1_HASH.matcher(hash).matches()) {
builder.setHash(ByteBufUtil.decodeHexDump(hash));
}
}

ServerResourcePackSendEvent event = new ServerResourcePackSendEvent(
builder.build(), this.serverConn);
packet.toServerPromptedPack(), this.serverConn);

server.getEventManager().fire(event).thenAcceptAsync(serverResourcePackSendEvent -> {
if (playerConnection.isClosed()) {
Expand Down
Loading