diff --git a/src/com/projectswg/ClientConnection.java b/src/com/projectswg/ClientConnection.java index 6d54ee3..a9a9637 100644 --- a/src/com/projectswg/ClientConnection.java +++ b/src/com/projectswg/ClientConnection.java @@ -8,6 +8,7 @@ import com.projectswg.ClientReceiver.ClientReceiverCallback; import com.projectswg.ClientReceiver.ConnectionState; import com.projectswg.networking.NetInterceptor; import com.projectswg.networking.Packet; +import com.projectswg.networking.NetInterceptor.InterceptorProperties; import com.projectswg.networking.swg.HeartBeat; public class ClientConnection { @@ -28,11 +29,20 @@ public class ClientConnection { receiver.setClientSender(sender); } + public InterceptorProperties getInterceptorProperties() { + return interceptor.getProperties(); + } + + public boolean restart() { + stop(); + return start(); + } + public boolean start() { if (!sender.start()) return false; receiver.start(); - interceptor.setPort(sender.getZonePort()); + interceptor.getProperties().setPort(sender.getZonePort()); sender.setLoginCallback((packet) -> receiver.onPacket(false, packet)); sender.setZoneCallback((packet) -> receiver.onPacket(true, packet)); receiver.setReceiverCallback(new ClientReceiverCallback() { @@ -48,8 +58,9 @@ public class ClientConnection { return true; } - public void stop() { - pinger.shutdownNow(); + private void stop() { + if (pinger != null) + pinger.shutdownNow(); sender.stop(); receiver.stop(); onDisconnected(); diff --git a/src/com/projectswg/Connections.java b/src/com/projectswg/Connections.java index 3869493..f138142 100644 --- a/src/com/projectswg/Connections.java +++ b/src/com/projectswg/Connections.java @@ -6,6 +6,7 @@ import java.util.concurrent.atomic.AtomicLong; import com.projectswg.ClientConnection.ClientCallback; import com.projectswg.ServerConnection.ConnectionStatus; import com.projectswg.ServerConnection.ServerCallback; +import com.projectswg.networking.NetInterceptor.InterceptorProperties; import com.projectswg.networking.swg.ErrorMessage; public class Connections { @@ -50,7 +51,10 @@ public class Connections { public void terminate() { server.stop(); - client.stop(); + for (int i = 0; i < 3; i++) { + if (client.restart()) + break; + } } public void setCallback(ConnectionCallback callback) { @@ -62,7 +66,6 @@ public class Connections { return; terminate(); server.setRemoteAddress(addr, port); - initialize(); } public InetAddress getRemoteAddress() { @@ -97,6 +100,10 @@ public class Connections { return udpSent.get(); } + public InterceptorProperties getInterceptorProperties() { + return client.getInterceptorProperties(); + } + private void setCallbacks() { client.setCallback(new ClientCallback() { public void onPacket(byte[] data) { onDataSentTcp(data); } @@ -116,7 +123,6 @@ public class Connections { client.send(new ErrorMessage("Connection Update", "\n" + status.name().replace('_', ' '), false)); try { Thread.sleep(50); } catch (InterruptedException e) { } terminate(); - client.start(); } if (callback != null) callback.onServerStatusChanged(oldStatus, status); @@ -132,7 +138,6 @@ public class Connections { terminate(); if (callback != null) callback.onClientDisconnected(); - client.start(); } private void onDataRecvTcp(byte [] data) { diff --git a/src/com/projectswg/Forwarder.java b/src/com/projectswg/Forwarder.java index 79e5754..69b5673 100644 --- a/src/com/projectswg/Forwarder.java +++ b/src/com/projectswg/Forwarder.java @@ -11,6 +11,7 @@ import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; +import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; @@ -30,6 +31,8 @@ public class Forwarder extends Application implements ConnectionCallback { private final ExecutorService executor; private final Connections connections; + private final TextField usernameField; + private final TextField passwordField; private final TextField serverIpField; private final TextField serverPortField; private final Button serverSetButton; @@ -49,6 +52,8 @@ public class Forwarder extends Application implements ConnectionCallback { public Forwarder() { executor = Executors.newSingleThreadExecutor(); connections = new Connections(); + usernameField = new TextField(""); + passwordField = new PasswordField(); serverIpField = new TextField(connections.getRemoteAddress().getHostAddress()); serverPortField = new TextField(Integer.toString(connections.getRemotePort())); serverSetButton = new Button("Set"); @@ -71,6 +76,10 @@ public class Forwarder extends Application implements ConnectionCallback { updateServerButton(); } }; + usernameField.promptTextProperty().setValue("Username"); + passwordField.promptTextProperty().setValue("Password"); + usernameField.textProperty().addListener((event, oldValue, newValue) -> connections.getInterceptorProperties().setUsername(newValue)); + passwordField.textProperty().addListener((event, oldValue, newValue) -> connections.getInterceptorProperties().setPassword(newValue)); serverIpField.setOnKeyPressed(handler); serverPortField.setOnKeyPressed(handler); serverIpField.setOnKeyTyped(handler); @@ -162,7 +171,7 @@ public class Forwarder extends Application implements ConnectionCallback { clientConnectionPort.setText(Integer.toString(connections.getLoginPort())); GridPane root = new GridPane(); setupGridPane(root); - Scene scene = new Scene(root, 400, 140); + Scene scene = new Scene(root, 400, 160); primaryStage.setTitle("Holocore Forwarder"); primaryStage.setScene(scene); primaryStage.setMinWidth(scene.getWidth()); @@ -190,23 +199,25 @@ public class Forwarder extends Application implements ConnectionCallback { addColumnConstraint(root, 100); addColumnConstraint(root, 75); addColumnConstraint(root, 175); - root.add(serverIpField, 0, 0, 2, 1); - root.add(serverPortField, 2, 0, 1, 1); - root.add(serverSetButton, 3, 0, 1, 1); - root.add(new Text("Server Connection:"), 0, 1, 2, 1); - root.add(serverConnectionText, 2, 1, 1, 1); - root.add(serverStatusText, 3, 1, 1, 1); - root.add(new Text("Client Connection:"), 0, 2, 2, 1); - root.add(clientConnectionText, 2, 2, 2, 1); - root.add(clientConnectionPort, 3, 2, 1, 1); - root.add(new Text("Sent"), 1, 3, 1, 1); - root.add(new Text("Recv"), 2, 3, 1, 1); - root.add(new Text("TCP"), 0, 4, 1, 1); - root.add(serverTxText, 1, 4, 1, 1); - root.add(serverRxText, 2, 4, 1, 1); - root.add(new Text("UDP"), 0, 5, 1, 1); - root.add(clientTxText, 1, 5, 1, 1); - root.add(clientRxText, 2, 5, 1, 1); + root.add(usernameField, 0, 0, 2, 1); + root.add(passwordField, 2, 0, 2, 1); + root.add(serverIpField, 0, 1, 2, 1); + root.add(serverPortField, 2, 1, 1, 1); + root.add(serverSetButton, 3, 1, 1, 1); + root.add(new Text("Server Connection:"), 0, 2, 2, 1); + root.add(serverConnectionText, 2, 2, 1, 1); + root.add(serverStatusText, 3, 2, 1, 1); + root.add(new Text("Client Connection:"), 0, 3, 2, 1); + root.add(clientConnectionText, 2, 3, 2, 1); + root.add(clientConnectionPort, 3, 3, 1, 1); + root.add(new Text("Sent"), 1, 4, 1, 1); + root.add(new Text("Recv"), 2, 4, 1, 1); + root.add(new Text("TCP"), 0, 5, 1, 1); + root.add(serverTxText, 1, 5, 1, 1); + root.add(serverRxText, 2, 5, 1, 1); + root.add(new Text("UDP"), 0, 6, 1, 1); + root.add(clientTxText, 1, 6, 1, 1); + root.add(clientRxText, 2, 6, 1, 1); } private void addColumnConstraint(GridPane root, double width) { diff --git a/src/com/projectswg/networking/NetInterceptor.java b/src/com/projectswg/networking/NetInterceptor.java index a96f32c..5a9bb59 100644 --- a/src/com/projectswg/networking/NetInterceptor.java +++ b/src/com/projectswg/networking/NetInterceptor.java @@ -4,22 +4,31 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import com.projectswg.networking.resources.Galaxy; +import com.projectswg.networking.swg.LoginClientId; import com.projectswg.networking.swg.LoginClusterStatus; public class NetInterceptor { - private int port; + private final InterceptorProperties properties; public NetInterceptor() { - + properties = new InterceptorProperties(); } - public void setPort(int port) { - this.port = port; + public InterceptorProperties getProperties() { + return properties; } public byte [] interceptClient(byte [] data) { - return data; + if (data.length < 6) + return data; + ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN); + switch (bb.getInt(2)) { + case 0x41131F96: + return setAutoLogin(bb); + default: + return data; + } } public byte [] interceptServer(byte [] data) { @@ -34,15 +43,63 @@ public class NetInterceptor { } } + private byte [] setAutoLogin(ByteBuffer data) { + LoginClientId id = new LoginClientId(data); + if (!id.getUsername().equals(properties.getUsername()) || !id.getPassword().isEmpty()) { + return data.array(); + } + System.out.println("Set Password: " + properties.getPassword()); + id.setPassword(properties.getPassword()); + return id.encode().array(); + } + private byte [] getServerList(ByteBuffer data) { LoginClusterStatus cluster = new LoginClusterStatus(); cluster.decode(data); for (Galaxy g : cluster.getGalaxies()) { g.setAddress("127.0.0.1"); - g.setZonePort((short) port); - g.setPingPort((short) port); + g.setZonePort((short) properties.getPort()); + g.setPingPort((short) properties.getPort()); } return cluster.encode().array(); } + public static class InterceptorProperties { + + private int port; + private String username; + private String password; + + public InterceptorProperties() { + port = 0; + username = ""; + password = ""; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + } + } diff --git a/src/com/projectswg/networking/swg/LoginClientId.java b/src/com/projectswg/networking/swg/LoginClientId.java new file mode 100644 index 0000000..f1060a1 --- /dev/null +++ b/src/com/projectswg/networking/swg/LoginClientId.java @@ -0,0 +1,81 @@ +/*********************************************************************************** +* Copyright (c) 2015 /// Project SWG /// www.projectswg.com * +* * +* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * +* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * +* Our goal is to create an emulator which will provide a server for players to * +* continue playing a game similar to the one they used to play. We are basing * +* it on the final publish of the game prior to end-game events. * +* * +* This file is part of Holocore. * +* * +* -------------------------------------------------------------------------------- * +* * +* Holocore is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Affero General Public License as * +* published by the Free Software Foundation, either version 3 of the * +* License, or (at your option) any later version. * +* * +* Holocore is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Affero General Public License for more details. * +* * +* You should have received a copy of the GNU Affero General Public License * +* along with Holocore. If not, see . * +* * +***********************************************************************************/ +package com.projectswg.networking.swg; + +import java.nio.ByteBuffer; + +import com.projectswg.networking.SWGPacket; + + +public class LoginClientId extends SWGPacket { + + public static final int CRC = 0x41131F96; + + private String username; + private String password; + private String version; + + public LoginClientId() { + this("", "", ""); + } + + public LoginClientId(ByteBuffer data) { + decode(data); + } + + public LoginClientId(String username, String password, String version) { + this.username = username; + this.password = password; + this.version = version; + } + + public void decode(ByteBuffer data) { + if (!super.decode(data, CRC)) + return; + username = getAscii(data); + password = getAscii(data); + version = getAscii(data); + } + + public ByteBuffer encode() { + int length = 6 + 6 + username.length() + password.length() + version.length(); + ByteBuffer data = ByteBuffer.allocate(length); + addShort(data, 4); + addInt( data, CRC); + addAscii(data, username); + addAscii(data, password); + addAscii(data, version); + return data; + } + + public String getUsername() { return username; } + public void setUsername(String str) { this.username = str; } + public String getPassword() { return password; } + public void setPassword(String str) { this.password = str; } + public String getVersion() { return version; } +}