diff --git a/.gitmodules b/.gitmodules index ee4cb66..856c61c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "pswgcommon"] path = pswgcommon url = git@bitbucket.org:projectswg/pswgcommon.git -[submodule "PSWGCommon"] - path = PSWGCommon - url = git@bitbucket.org:projectswg/pswgcommon.git diff --git a/ClientHolocore.jar b/ClientHolocore.jar deleted file mode 100644 index 2304986..0000000 Binary files a/ClientHolocore.jar and /dev/null differ diff --git a/PSWGCommon b/PSWGCommon deleted file mode 160000 index 753adac..0000000 --- a/PSWGCommon +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 753adaca225ec1db30c8b72e35bbe216d8def52e diff --git a/build.gradle b/build.gradle index de248dd..b1550e2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,28 +1,19 @@ plugins { id 'java' - id 'idea' } sourceCompatibility = 1.8 targetCompatibility = 1.8 -sourceSets { - main { - java { - srcDir 'src' - } - } -} - -jar { - from sourceSets.main.allSource - archiveName = "PSWGCommon.jar" -} - -task wrapper(type: Wrapper) { - gradleVersion = "4.4" +repositories { + jcenter() } dependencies { - compile project(':PSWGCommon') + compile project(':pswgcommon') + testCompile 'junit:junit:4.12' +} + +task wrapper(type: Wrapper) { + gradleVersion = "4.7" } diff --git a/settings.gradle b/settings.gradle index 40825e9..2e860fa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':PSWGCommon' +include ':pswgcommon' diff --git a/src/com/projectswg/connection/UDPServer.java b/src/com/projectswg/connection/UDPServer.java deleted file mode 100644 index 2ec06d9..0000000 --- a/src/com/projectswg/connection/UDPServer.java +++ /dev/null @@ -1,277 +0,0 @@ -/*********************************************************************************** -* 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.connection; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Queue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * This class represents a UDP server that listens for packets and - * will call the callback when it receives one - */ -class UDPServer { - - private Object waitingForPacket = new Object(); - - private final DatagramSocket socket; - private final UDPUpdater updater; - private final Queue inbound; - private final int packetSize; - private UDPCallback callback; - private int port; - - public UDPServer(int port) throws SocketException { - this(port, 1024); - } - - public UDPServer(int port, int packetSize) throws SocketException { - this(null, port, packetSize); - } - - public UDPServer(InetAddress bindAddr, int port, int packetSize) throws SocketException { - this.callback = null; - this.packetSize = packetSize; - inbound = new LinkedBlockingQueue(); - if (port > 0) { - if (bindAddr == null) - socket = new DatagramSocket(port); - else - socket = new DatagramSocket(port, bindAddr); - } else - socket = new DatagramSocket(); - this.port = socket.getLocalPort(); - updater = new UDPUpdater(); - updater.start(); - } - - public void close() { - if (updater != null) - updater.stop(); - if (socket != null) - socket.close(); - } - - public UDPPacket receive() { - return inbound.poll(); - } - - public int packetCount() { - return inbound.size(); - } - - public int getPort() { - return port; - } - - public boolean isRunning() { - return updater != null && updater.isRunning(); - } - - public void waitForPacket() { - synchronized (waitingForPacket) { - try { - while (inbound.isEmpty()) { - waitingForPacket.wait(); - } - } catch (InterruptedException e) { - - } - } - } - - public boolean waitForPacket(long timeout) { - long start = System.nanoTime(); - synchronized (waitingForPacket) { - try { - while (inbound.isEmpty()) { - long waitTime = (long) (timeout - (System.nanoTime() - start)/1E6 + 0.5); - if (waitTime <= 0) - return false; - waitingForPacket.wait(waitTime); - } - return true; - } catch (InterruptedException e) { - - } - } - return false; - } - - public boolean send(int port, InetAddress addr, byte [] data) { - try { - socket.send(new DatagramPacket(data, data.length, addr, port)); - return true; - } catch (IOException e) { - String msg = e.getMessage(); - if (msg != null && msg.startsWith("Socket") && msg.endsWith("closed")) - return false; - else - e.printStackTrace(); - return false; - } - } - - public boolean send(int port, String addr, byte [] data) { - try { - return send(port, InetAddress.getByName(addr), data); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return false; - } - - public boolean send(InetSocketAddress addr, byte [] data) { - return send(addr.getPort(), addr.getAddress(), data); - } - - public void setCallback(UDPCallback callback) { - this.callback = callback; - } - - public void removeCallback() { - callback = null; - } - - public interface UDPCallback { - public void onReceivedPacket(UDPPacket packet); - } - - public static class UDPPacket { - private final byte [] data; - private final InetAddress addr; - private final int port; - - public UDPPacket(InetAddress addr, int port, byte [] data) { - this.data = data; - this.addr = addr; - this.port = port; - } - - public InetAddress getAddress() { - return addr; - } - - public int getPort() { - return port; - } - - public byte [] getData() { - return data; - } - - public int getLength() { - return data.length; - } - } - - private class UDPUpdater implements Runnable { - - private final Thread thread; - private final byte [] dataBuffer; - private boolean running; - - public UDPUpdater() { - thread = new Thread(this); - thread.setName("UDPServer Port#" + port); - dataBuffer = new byte[packetSize]; - } - - public boolean isRunning() { - return running; - } - - public void start() { - running = true; - thread.start(); - } - - public void stop() { - running = false; - thread.interrupt(); - } - - public void run() { - try { - while (running) { - loop(); - } - } catch (Exception e) { - e.printStackTrace(); - } - running = false; - } - - private void loop() { - DatagramPacket packet = receivePacket(); - if (packet.getLength() <= 0) - return; - UDPPacket udpPacket = generatePacket(packet); - if (callback != null) - callback.onReceivedPacket(udpPacket); - else - inbound.add(udpPacket); - notifyPacketReceived(); - } - - private void notifyPacketReceived() { - synchronized (waitingForPacket) { - waitingForPacket.notifyAll(); - } - } - - private DatagramPacket receivePacket() { - DatagramPacket packet = new DatagramPacket(dataBuffer, dataBuffer.length); - try { - socket.receive(packet); - } catch (IOException e) { - if (e.getMessage() != null && (e.getMessage().contains("socket closed") || e.getMessage().contains("Socket closed"))) - running = false; - else - e.printStackTrace(); - packet.setLength(0); - } - return packet; - } - - private UDPPacket generatePacket(DatagramPacket packet) { - byte [] data = new byte[packet.getLength()]; - System.arraycopy(packet.getData(), 0, data, 0, packet.getLength()); - UDPPacket udpPacket = new UDPPacket(packet.getAddress(), packet.getPort(), data); - return udpPacket; - } - - } - -} diff --git a/src/com/projectswg/connection/HolocoreProtocol.java b/src/main/java/com/projectswg/connection/HolocoreProtocol.java similarity index 100% rename from src/com/projectswg/connection/HolocoreProtocol.java rename to src/main/java/com/projectswg/connection/HolocoreProtocol.java diff --git a/src/com/projectswg/connection/HolocoreSocket.java b/src/main/java/com/projectswg/connection/HolocoreSocket.java similarity index 78% rename from src/com/projectswg/connection/HolocoreSocket.java rename to src/main/java/com/projectswg/connection/HolocoreSocket.java index 4733704..8d556b8 100644 --- a/src/com/projectswg/connection/HolocoreSocket.java +++ b/src/main/java/com/projectswg/connection/HolocoreSocket.java @@ -1,29 +1,24 @@ package com.projectswg.connection; -import com.projectswg.common.debug.Log; import com.projectswg.common.network.NetBuffer; -import com.projectswg.common.network.TCPSocket; -import com.projectswg.common.network.TCPSocket.TCPSocketCallback; import com.projectswg.common.network.packets.swg.holo.HoloConnectionStarted; import com.projectswg.common.network.packets.swg.holo.HoloConnectionStopped; import com.projectswg.common.network.packets.swg.holo.HoloSetProtocolVersion; -import com.projectswg.connection.UDPServer.UDPPacket; import com.projectswg.connection.packets.RawPacket; +import me.joshlarson.jlcommon.log.Log; +import me.joshlarson.jlcommon.network.TCPSocket; +import me.joshlarson.jlcommon.network.TCPSocket.TCPSocketCallback; +import me.joshlarson.jlcommon.network.UDPServer; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; +import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.util.Locale; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; public class HolocoreSocket { @@ -33,6 +28,7 @@ public class HolocoreSocket { private final SWGProtocol swgProtocol; private final AtomicReference status; private final UDPServer udpServer; + private final BlockingQueue udpInboundQueue; private final BlockingQueue inboundQueue; private TCPSocket socket; @@ -42,9 +38,10 @@ public class HolocoreSocket { public HolocoreSocket(InetAddress addr, int port) { this.swgProtocol = new SWGProtocol(); this.status = new AtomicReference<>(ServerConnectionStatus.DISCONNECTED); + this.udpInboundQueue = new LinkedBlockingQueue<>(); + this.inboundQueue = new LinkedBlockingQueue<>(); this.udpServer = createUDPServer(); this.socket = null; - this.inboundQueue = new LinkedBlockingQueue<>(); this.callback = null; this.address = new InetSocketAddress(addr, port); } @@ -129,13 +126,17 @@ public class HolocoreSocket { */ public String getServerStatus(long timeout) { udpServer.send(address, new byte[]{1}); - udpServer.waitForPacket(timeout); - UDPPacket packet = udpServer.receive(); - if (packet == null) - return "OFFLINE"; - NetBuffer data = NetBuffer.wrap(packet.getData()); - data.getByte(); - return data.getAscii(); + try { + DatagramPacket packet = udpInboundQueue.poll(timeout, TimeUnit.MILLISECONDS); + if (packet == null) + return "OFFLINE"; + NetBuffer data = NetBuffer.wrap(packet.getData()); + data.getByte(); + return data.getAscii(); + } catch (InterruptedException e) { + Log.w("Interrupted while waiting for server status response"); + return "UNKNOWN"; + } } /** @@ -150,28 +151,6 @@ public class HolocoreSocket { return finishConnection(socket, timeout); } - /** - * Attempts to connect to the remote server securely. This call is a blocking function that will not - * return until it has either successfully connected or has failed. It starts by initializing a - * TCP connection, then initializes the Holocore connection, then returns. - * @param timeout the timeout for the connect call - * @param keystoreFile the keystore file - * @param password the password for the keystore - * @return TRUE if successful and connected, FALSE on error - * @throws KeyStoreException if KeyManagerFactory.init or TrustManagerFactory.init fails - * @throws NoSuchAlgorithmException if the algorithm for the keystore or key manager could not be found - * @throws CertificateException if any of the certificates in the keystore could not be loaded - * @throws FileNotFoundException if the keystore file does not exist - * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given, or if the given password was incorrect. If the error is due to a wrong password, the cause of the IOException should be an UnrecoverableKeyException - * @throws KeyManagementException if SSLContext.init fails - * @throws UnrecoverableKeyException if the key cannot be recovered (e.g. the given password is wrong). - */ - public boolean connectSecure(int timeout, File keystoreFile, char [] password) throws KeyManagementException, UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException { - TCPSocket socket = new TCPSocket(address, BUFFER_SIZE); -// socket.setupEncryption(keystoreFile, password); - return finishConnection(socket, timeout); - } - private boolean finishConnection(TCPSocket socket, int timeout) { updateStatus(ServerConnectionStatus.CONNECTING, ServerConnectionChangedReason.NONE); try { @@ -233,7 +212,7 @@ public class HolocoreSocket { public boolean send(byte [] raw) { TCPSocket socket = this.socket; if (socket != null) - return socket.send(swgProtocol.assemble(raw)); + return socket.send(swgProtocol.assemble(raw).getBuffer()); return false; } @@ -320,9 +299,11 @@ public class HolocoreSocket { void onConnectionStatusChanged(ServerConnectionStatus oldStatus, ServerConnectionStatus newStatus, ServerConnectionChangedReason reason); } - private static UDPServer createUDPServer() { + private UDPServer createUDPServer() { try { - return new UDPServer(0); + UDPServer server = new UDPServer(new InetSocketAddress(0), 1500, udpInboundQueue::offer); + server.bind(); + return server; } catch (SocketException e) { Log.e(e); } diff --git a/src/com/projectswg/connection/SWGProtocol.java b/src/main/java/com/projectswg/connection/SWGProtocol.java similarity index 100% rename from src/com/projectswg/connection/SWGProtocol.java rename to src/main/java/com/projectswg/connection/SWGProtocol.java diff --git a/src/com/projectswg/connection/ServerConnectionChangedReason.java b/src/main/java/com/projectswg/connection/ServerConnectionChangedReason.java similarity index 100% rename from src/com/projectswg/connection/ServerConnectionChangedReason.java rename to src/main/java/com/projectswg/connection/ServerConnectionChangedReason.java diff --git a/src/com/projectswg/connection/ServerConnectionStatus.java b/src/main/java/com/projectswg/connection/ServerConnectionStatus.java similarity index 100% rename from src/com/projectswg/connection/ServerConnectionStatus.java rename to src/main/java/com/projectswg/connection/ServerConnectionStatus.java diff --git a/src/com/projectswg/connection/packets/RawPacket.java b/src/main/java/com/projectswg/connection/packets/RawPacket.java similarity index 100% rename from src/com/projectswg/connection/packets/RawPacket.java rename to src/main/java/com/projectswg/connection/packets/RawPacket.java