diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 03ecfc710..857354ebd 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -19,7 +19,7 @@ import com.velocitypowered.proxy.command.ShutdownCommand; import com.velocitypowered.proxy.command.VelocityCommand; import com.velocitypowered.proxy.config.VelocityConfiguration; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; -import com.velocitypowered.proxy.connection.http.NettyHttpClient; +import com.velocitypowered.proxy.network.http.NettyHttpClient; import com.velocitypowered.proxy.command.VelocityCommandManager; import com.velocitypowered.proxy.config.AnnotatedConfig; import com.velocitypowered.proxy.messages.VelocityChannelRegistrar; @@ -39,9 +39,7 @@ import net.kyori.text.serializer.GsonComponentSerializer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.IOException; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.security.KeyPair; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index 6db9f4104..df990b50e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -101,14 +101,29 @@ public class LoginSessionHandler implements MinecraftSessionHandler { // The player disconnected after we authenticated them. return; } - + + // Go ahead and enable encryption. Once the client sends EncryptionResponse, encryption is + // enabled. try { inbound.enableEncryption(decryptedSharedSecret); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } - initializePlayer(VelocityServer.GSON.fromJson(profileResponse, GameProfile.class), true); + if (profileResponse.getCode() == 200) { + // All went well, initialize the session. + initializePlayer(VelocityServer.GSON.fromJson(profileResponse.getBody(), GameProfile.class), true); + } else if (profileResponse.getCode() == 204) { + // Apparently an offline-mode user logged onto this online-mode proxy. The client has enabled + // encryption, so we need to do that as well. + logger.warn("An offline-mode client ({} from {}) tried to connect!", login.getUsername(), playerIp); + inbound.closeWith(Disconnect.create(TextComponent.of("This server only accepts connections from online-mode clients."))); + } else { + // Something else went wrong + logger.error("Got an unexpected error code {} whilst contacting Mojang to log in {} ({})", + profileResponse.getCode(), login.getUsername(), playerIp); + inbound.close(); + } }, inbound.getChannel().eventLoop()) .exceptionally(exception -> { logger.error("Unable to enable encryption", exception); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/http/NettyHttpClient.java b/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java similarity index 94% rename from proxy/src/main/java/com/velocitypowered/proxy/connection/http/NettyHttpClient.java rename to proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java index 0e9952f32..24ab295da 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/http/NettyHttpClient.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/http/NettyHttpClient.java @@ -1,4 +1,4 @@ -package com.velocitypowered.proxy.connection.http; +package com.velocitypowered.proxy.network.http; import com.velocitypowered.proxy.VelocityServer; import io.netty.bootstrap.Bootstrap; @@ -46,7 +46,7 @@ public class NettyHttpClient { }; } - public CompletableFuture get(URL url) { + public CompletableFuture get(URL url) { String host = url.getHost(); int port = url.getPort(); boolean ssl = url.getProtocol().equals("https"); @@ -54,7 +54,7 @@ public class NettyHttpClient { port = ssl ? 443 : 80; } - CompletableFuture reply = new CompletableFuture<>(); + CompletableFuture reply = new CompletableFuture<>(); InetSocketAddress address = new InetSocketAddress(host, port); poolMap.get(address) .acquire() diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponse.java b/proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponse.java new file mode 100644 index 000000000..90f21141b --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponse.java @@ -0,0 +1,27 @@ +package com.velocitypowered.proxy.network.http; + +public class SimpleHttpResponse { + private final int code; + private final String body; + + SimpleHttpResponse(int code, String body) { + this.code = code; + this.body = body; + } + + public int getCode() { + return code; + } + + public String getBody() { + return body; + } + + @Override + public String toString() { + return "SimpleHttpResponse{" + + "code=" + code + + ", body='" + body + '\'' + + '}'; + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/http/SimpleHttpResponseCollector.java b/proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponseCollector.java similarity index 76% rename from proxy/src/main/java/com/velocitypowered/proxy/connection/http/SimpleHttpResponseCollector.java rename to proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponseCollector.java index a2285af6f..1e54c2706 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/http/SimpleHttpResponseCollector.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/http/SimpleHttpResponseCollector.java @@ -1,4 +1,4 @@ -package com.velocitypowered.proxy.connection.http; +package com.velocitypowered.proxy.network.http; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -10,10 +10,11 @@ import java.util.concurrent.CompletableFuture; class SimpleHttpResponseCollector extends ChannelInboundHandlerAdapter { private final StringBuilder buffer = new StringBuilder(1024); - private final CompletableFuture reply; + private final CompletableFuture reply; + private int httpCode; private boolean canKeepAlive; - SimpleHttpResponseCollector(CompletableFuture reply) { + SimpleHttpResponseCollector(CompletableFuture reply) { this.reply = reply; } @@ -23,11 +24,7 @@ class SimpleHttpResponseCollector extends ChannelInboundHandlerAdapter { if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; HttpResponseStatus status = response.status(); - if (status != HttpResponseStatus.OK) { - reply.completeExceptionally(new RuntimeException("Unexpected status code " + status.code())); - return; - } - + this.httpCode = status.code(); this.canKeepAlive = HttpUtil.isKeepAlive(response); } @@ -38,7 +35,7 @@ class SimpleHttpResponseCollector extends ChannelInboundHandlerAdapter { if (!canKeepAlive) { ctx.close(); } - reply.complete(buffer.toString()); + reply.complete(new SimpleHttpResponse(httpCode, buffer.toString())); } } } finally {