mirror of
https://bitbucket.org/projectswg/client-holocore.git
synced 2026-01-15 22:04:32 -05:00
Updated client-holocore to use new pswgcommon utilities
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||
|
||||
Binary file not shown.
Submodule PSWGCommon deleted from 753adaca22
25
build.gradle
25
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"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
include ':PSWGCommon'
|
||||
include ':pswgcommon'
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
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 <UDPPacket> 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<UDPPacket>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<ServerConnectionStatus> status;
|
||||
private final UDPServer udpServer;
|
||||
private final BlockingQueue<DatagramPacket> udpInboundQueue;
|
||||
private final BlockingQueue<RawPacket> 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);
|
||||
}
|
||||
Reference in New Issue
Block a user