diff --git a/client-fabric/src/eu/e99/svc/client/fabric/FabricSimplerVoiceChat.java b/client-fabric/src/eu/e99/svc/client/fabric/FabricSimplerVoiceChat.java index 088dd7b..e69b612 100644 --- a/client-fabric/src/eu/e99/svc/client/fabric/FabricSimplerVoiceChat.java +++ b/client-fabric/src/eu/e99/svc/client/fabric/FabricSimplerVoiceChat.java @@ -1,18 +1,45 @@ package eu.e99.svc.client.fabric; import net.fabricmc.api.ClientModInitializer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.session.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.SSLSocketFactory; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + public class FabricSimplerVoiceChat implements ClientModInitializer { public static final String NAMESPACE = "svc"; - public static final Logger LOGGER = LoggerFactory.getLogger(NAMESPACE); @Override public void onInitializeClient() { - LOGGER.info("Simpler Voice Chat Running"); + System.out.printf("Simpler Voice Chat loading...%n"); + + SSLSocketFactory socketFactory; + try { + socketFactory = SVCClient.createSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + System.out.printf("Failed to create socket factory:%n"); + e.printStackTrace(System.out); + return; + } + + MinecraftClient client = MinecraftClient.getInstance(); + Session session = client.getSession(); + SVCClient voiceChat = new SVCClient( + "localhost", + 6969, + session.getAccessToken(), + session.getUsername(), + session.getUuidOrNull(), + socketFactory + ); + Thread.ofPlatform().start(voiceChat::start); } } diff --git a/client-fabric/src/eu/e99/svc/client/fabric/SVCClient.java b/client-fabric/src/eu/e99/svc/client/fabric/SVCClient.java index 8b1a7fc..c0a4d59 100644 --- a/client-fabric/src/eu/e99/svc/client/fabric/SVCClient.java +++ b/client-fabric/src/eu/e99/svc/client/fabric/SVCClient.java @@ -3,11 +3,9 @@ package eu.e99.svc.client.fabric; import eu.e99.svc.AllTrustManager; import eu.e99.svc.Connection; import eu.e99.svc.SimplerVoiceChat; +import eu.e99.svc.auth.MojangAPI; import eu.e99.svc.io.BinaryMessage; -import eu.e99.svc.packet.AuthRequestPacket; -import eu.e99.svc.packet.AuthResponsePacket; -import eu.e99.svc.packet.AuthSuccessPacket; -import eu.e99.svc.packet.ClientHelloPacket; +import eu.e99.svc.packet.*; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; @@ -18,10 +16,11 @@ import java.net.Socket; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.util.UUID; public class SVCClient { - public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException { + public static SSLSocketFactory createSocketFactory() throws NoSuchAlgorithmException, KeyManagementException { TrustManager[] trustManagers = new TrustManager[]{ new AllTrustManager(), }; @@ -29,37 +28,58 @@ public class SVCClient { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustManagers, new SecureRandom()); - SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - - SVCClient voiceChat = new SVCClient("localhost", 6969, socketFactory); - voiceChat.start(); + return sslContext.getSocketFactory(); } private final String host; private final int port; + private final String accessToken; + private final String username; + private final UUID uuid; private final SSLSocketFactory socketFactory; - public SVCClient(String host, int port, SSLSocketFactory socketFactory) { + public SVCClient(String host, int port, String accessToken, String username, UUID uuid, SSLSocketFactory socketFactory) { this.host = host; this.port = port; + this.accessToken = accessToken; + this.username = username; + this.uuid = uuid; this.socketFactory = socketFactory; } public void start() { // Connect and auth - try (Socket socket = this.socketFactory.createSocket()) { - socket.connect(new InetSocketAddress(this.host, this.port)); - Connection conn = new Connection(socket); + while (true) { + try (Socket socket = this.socketFactory.createSocket()) { + System.out.printf("Connecting to %s.%n", this.host); + socket.connect(new InetSocketAddress(this.host, this.port)); + Connection conn = new Connection(socket); + System.out.printf("Connected."); - this.handleHandshake(conn); - } catch (IOException e) { - System.out.printf("Failed to connect.%n"); - e.printStackTrace(System.out); + boolean ok = this.handleHandshake(conn); + if (!ok) { + System.out.printf("Handshake failed.%n"); + break; + } + + System.out.printf("Successfully authenticated.%n"); + } catch (IOException e) { + System.out.printf("Failed to connect.%n"); + e.printStackTrace(System.out); + } + + System.out.printf("Disconnected. Attempting reconnection in 30 seconds.%n"); + try { + Thread.sleep(30_000); + } catch (InterruptedException e) { + System.out.printf("Failed to wait:%n"); + e.printStackTrace(System.out); + } } } - private void handleHandshake(Connection conn) throws IOException { + private boolean handleHandshake(Connection conn) throws IOException { ClientHelloPacket clientHello = new ClientHelloPacket(); clientHello.version = SimplerVoiceChat.PROTOCOL_VERSION; conn.writePacket(clientHello); @@ -69,18 +89,35 @@ public class SVCClient { switch (packet) { case AuthRequestPacket authRequest -> { - System.out.printf("Joining fake server to authenticate.%n"); + System.out.printf("Joining server to authenticate...%n"); + + boolean ok; + try { + ok = MojangAPI.joinServer(this.accessToken, this.uuid, authRequest.serverId); + } catch (Exception e) { + System.out.printf("Failed to join server:%n"); + e.printStackTrace(System.out); + return false; + } + + if (!ok) { + System.out.printf("Failed to join server.%n"); + return false; + } AuthResponsePacket authResponse = new AuthResponsePacket(); - authResponse.username = "Test"; + authResponse.username = this.username; conn.writePacket(authResponse); } case AuthSuccessPacket authComplete -> { - System.out.printf("Successfully authenticated.%n"); - return; + return true; + } + case DisconnectPacket disconnect -> { + System.out.printf("Disconnected with reason \"%s\".%n", disconnect.reason); + return false; } default -> { - System.out.printf("Got unexpected packet.%n"); + System.out.printf("Got unexpected packet %s.%n", packet.getClass().getName()); } } } diff --git a/common/src/eu/e99/svc/auth/MojangAPI.java b/common/src/eu/e99/svc/auth/MojangAPI.java index 9771b47..446b5ae 100644 --- a/common/src/eu/e99/svc/auth/MojangAPI.java +++ b/common/src/eu/e99/svc/auth/MojangAPI.java @@ -24,7 +24,7 @@ public class MojangAPI { .build(); HttpResponse res = client.send(req, HttpResponse.BodyHandlers.ofString()); - if (res.statusCode() == 204) { + if (res.statusCode() != 200) { return null; } @@ -39,4 +39,29 @@ public class MojangAPI { return new PlayerProfile(name, uuid); } } + + public static boolean joinServer(String accessToken, UUID uuid, String serverId) throws IOException, InterruptedException { + try (HttpClient client = HttpClient.newHttpClient()) { + String loc = "https://sessionserver.mojang.com/session/minecraft/join"; + URI uri = URI.create(loc); + + JsonObject body = new JsonObject(); + body.addProperty("accessToken", accessToken); + body.addProperty("selectedProfile", uuid.toString().replace("-", "")); + body.addProperty("serverId", serverId); + + HttpRequest req = HttpRequest.newBuilder() + .uri(uri) + .POST(HttpRequest.BodyPublishers.ofString(body.toString())) + .build(); + + HttpResponse res = client.send(req, HttpResponse.BodyHandlers.discarding()); + System.out.printf("%d%n", res.statusCode()); + if (res.statusCode() != 204) { + return false; + } + + return true; + } + } } diff --git a/server/src/eu/e99/svc/server/Server.java b/server/src/eu/e99/svc/server/Server.java index 97f047c..7570bf6 100644 --- a/server/src/eu/e99/svc/server/Server.java +++ b/server/src/eu/e99/svc/server/Server.java @@ -7,6 +7,7 @@ import eu.e99.svc.auth.PlayerProfile; import eu.e99.svc.io.BinaryMessage; import eu.e99.svc.packet.*; +import java.io.EOFException; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; @@ -38,7 +39,7 @@ public class Server { this.socket.notify(); } - System.out.printf("Failed to accept client.%n"); + System.out.printf("Failed to handle client.%n"); e.printStackTrace(System.out); } });