3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-17 05:20:14 +01:00

Implement RegisteredServer#ping()

Dieser Commit ist enthalten in:
Andrew Steinborn 2018-09-16 13:59:44 -04:00
Ursprung 1f8152c3a5
Commit 291069af80
3 geänderte Dateien mit 115 neuen und 5 gelöschten Zeilen

Datei anzeigen

@ -99,8 +99,6 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
if (association != null) {
logger.error("{}: exception encountered", association, cause);
} else {
logger.error("{} encountered an exception", ctx.channel().remoteAddress(), cause);
}
ctx.close();

Datei anzeigen

@ -8,13 +8,31 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintFrameDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftVarintLengthEncoder;
import com.velocitypowered.proxy.server.ping.PingSessionHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.timeout.ReadTimeoutHandler;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static com.velocitypowered.proxy.network.Connections.*;
import static com.velocitypowered.proxy.network.Connections.HANDLER;
import static com.velocitypowered.proxy.network.Connections.MINECRAFT_ENCODER;
public class VelocityRegisteredServer implements RegisteredServer {
private final VelocityServer server;
private final ServerInfo serverInfo;
@ -43,9 +61,36 @@ public class VelocityRegisteredServer implements RegisteredServer {
@Override
public CompletableFuture<ServerPing> ping() {
CompletableFuture<ServerPing> p = new CompletableFuture<>();
p.completeExceptionally(new UnsupportedOperationException("Not currently implemented."));
return p;
CompletableFuture<ServerPing> pingFuture = new CompletableFuture<>();
server.initializeGenericBootstrap()
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline()
.addLast(READ_TIMEOUT, new ReadTimeoutHandler(server.getConfiguration().getReadTimeout(), TimeUnit.SECONDS))
.addLast(FRAME_DECODER, new MinecraftVarintFrameDecoder())
.addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE)
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolConstants.Direction.CLIENTBOUND))
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolConstants.Direction.SERVERBOUND));
MinecraftConnection connection = new MinecraftConnection(ch, server);
connection.setState(StateRegistry.HANDSHAKE);
ch.pipeline().addLast(HANDLER, connection);
}
})
.connect(serverInfo.getAddress())
.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
MinecraftConnection conn = future.channel().pipeline().get(MinecraftConnection.class);
conn.setSessionHandler(new PingSessionHandler(pingFuture, VelocityRegisteredServer.this, conn));
} else {
pingFuture.completeExceptionally(future.cause());
}
}
});
return pingFuture;
}
public void addPlayer(ConnectedPlayer player) {

Datei anzeigen

@ -0,0 +1,67 @@
package com.velocitypowered.proxy.server.ping;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.Handshake;
import com.velocitypowered.proxy.protocol.packet.StatusRequest;
import com.velocitypowered.proxy.protocol.packet.StatusResponse;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
public class PingSessionHandler implements MinecraftSessionHandler {
private final CompletableFuture<ServerPing> result;
private final RegisteredServer server;
private final MinecraftConnection connection;
private boolean completed = false;
public PingSessionHandler(CompletableFuture<ServerPing> result, RegisteredServer server, MinecraftConnection connection) {
this.result = result;
this.server = server;
this.connection = connection;
}
@Override
public void activated() {
Handshake handshake = new Handshake();
handshake.setNextStatus(StateRegistry.STATUS_ID);
handshake.setServerAddress(server.getServerInfo().getAddress().getHostString());
handshake.setPort(server.getServerInfo().getAddress().getPort());
handshake.setProtocolVersion(ProtocolConstants.MINIMUM_GENERIC_VERSION);
connection.write(handshake);
connection.setState(StateRegistry.STATUS);
connection.write(new StatusRequest());
}
@Override
public void handle(MinecraftPacket packet) {
Preconditions.checkState(packet instanceof StatusResponse, "Did not get status response back from connection");
// All good!
completed = true;
connection.close();
ServerPing ping = VelocityServer.GSON.fromJson(((StatusResponse) packet).getStatus(), ServerPing.class);
result.complete(ping);
}
@Override
public void disconnected() {
if (!completed) {
result.completeExceptionally(new IOException("Unexpectedly disconnected from remote server"));
}
}
@Override
public void exception(Throwable throwable) {
result.completeExceptionally(throwable);
}
}