mirror of
https://bitbucket.org/projectswg/lightspeed.git
synced 2026-01-16 23:04:40 -05:00
Changed TCP connection server to an HTTP server
This commit is contained in:
@@ -6,5 +6,6 @@
|
||||
<classpathentry kind="lib" path="lib/sqlite-jdbc-3.8.11.2.jar"/>
|
||||
<classpathentry kind="lib" path="lib/fast-json-1.4.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||
<classpathentry kind="lib" path="/home/josh/Downloads/nanohttpd-nanohttpd-project-2.3.1/core/target/nanohttpd-2.3.1.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS servers (
|
||||
id TEXT PRIMARY KEY,
|
||||
directory TEXT,
|
||||
origin TEXT,
|
||||
jvm_arguments TEXT
|
||||
);
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@ public class Lightspeed {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
running.set(false);
|
||||
mainThread.interrupt();
|
||||
try {
|
||||
mainThread.join();
|
||||
} catch (Exception e) {
|
||||
Log.e(e);
|
||||
}
|
||||
}, "lightspeed-shutdown-hook"));
|
||||
runLightspeed(lightspeed, running);
|
||||
LightspeedManager.getDataManager().terminate();
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.control;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
public class Assert {
|
||||
|
||||
private static volatile AssertLevel level = AssertLevel.ASSERT;
|
||||
@@ -40,25 +42,46 @@ public class Assert {
|
||||
}
|
||||
|
||||
public static void notNull(Object o) {
|
||||
notNull(o, "");
|
||||
}
|
||||
|
||||
public static void notNull(Object o, String message) {
|
||||
if (debug() && o == null)
|
||||
handle(new NullPointerException());
|
||||
handle(new NullPointerException(message));
|
||||
}
|
||||
|
||||
public static void isNull(Object o) {
|
||||
isNull(o, "");
|
||||
}
|
||||
|
||||
public static void isNull(Object o, String message) {
|
||||
if (debug() && o != null)
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
public static void test(boolean expr) {
|
||||
test(expr, "");
|
||||
}
|
||||
|
||||
public static void test(boolean expr, String message) {
|
||||
if (debug() && !expr)
|
||||
handle(new AssertionError());
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
public static void fail() {
|
||||
fail("");
|
||||
}
|
||||
|
||||
public static void fail(String message) {
|
||||
if (debug())
|
||||
handle(new AssertionError());
|
||||
handle(new AssertionException(message));
|
||||
}
|
||||
|
||||
private static void handle(RuntimeException e) {
|
||||
AssertLevel level = Assert.level;
|
||||
switch (level) {
|
||||
case WARN:
|
||||
e.printStackTrace();
|
||||
warn(e);
|
||||
break;
|
||||
case ASSERT:
|
||||
throw e;
|
||||
@@ -67,17 +90,22 @@ public class Assert {
|
||||
}
|
||||
}
|
||||
|
||||
private static void handle(Error e) {
|
||||
AssertLevel level = Assert.level;
|
||||
switch (level) {
|
||||
case WARN:
|
||||
e.printStackTrace();
|
||||
break;
|
||||
case ASSERT:
|
||||
throw e;
|
||||
default:
|
||||
break;
|
||||
private static void warn(Exception e) {
|
||||
StackTraceElement [] elements = e.getStackTrace();
|
||||
if (elements.length <= 1)
|
||||
Log.e(e);
|
||||
else
|
||||
Log.e(e);
|
||||
}
|
||||
|
||||
private static class AssertionException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AssertionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum AssertLevel {
|
||||
|
||||
@@ -29,14 +29,12 @@ package com.projectswg.common.control;
|
||||
|
||||
public abstract class Intent {
|
||||
|
||||
private final String type;
|
||||
private boolean broadcasted;
|
||||
private boolean complete;
|
||||
private Intent parallel;
|
||||
private Intent sequential;
|
||||
|
||||
protected Intent(String type) {
|
||||
this.type = type;
|
||||
protected Intent() {
|
||||
this.broadcasted = false;
|
||||
this.complete = false;
|
||||
this.parallel = null;
|
||||
@@ -54,14 +52,6 @@ public abstract class Intent {
|
||||
parallel = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of intent
|
||||
* @return the type of intent
|
||||
*/
|
||||
public synchronized String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the intent has been broadcasted and processed
|
||||
* by the system
|
||||
@@ -130,7 +120,7 @@ public abstract class Intent {
|
||||
|
||||
@Override
|
||||
public synchronized String toString() {
|
||||
return getType();
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
private synchronized void setAsParallel(Intent i) {
|
||||
|
||||
@@ -45,14 +45,14 @@ public class IntentManager {
|
||||
private static final IntentManager INSTANCE = new IntentManager();
|
||||
|
||||
private final Runnable broadcastRunnable;
|
||||
private final Map <String, List<IntentReceiver>> intentRegistrations;
|
||||
private final Map <Class<? extends Intent>, List<IntentReceiver>> intentRegistrations;
|
||||
private final Queue <Intent> intentQueue;
|
||||
private ExecutorService broadcastThreads;
|
||||
private boolean initialized = false;
|
||||
private boolean terminated = false;
|
||||
|
||||
private IntentManager() {
|
||||
intentRegistrations = new HashMap<String, List<IntentReceiver>>();
|
||||
intentRegistrations = new HashMap<>();
|
||||
intentQueue = new IntentQueue<>();
|
||||
initialize();
|
||||
broadcastRunnable = () -> {
|
||||
@@ -67,9 +67,7 @@ public class IntentManager {
|
||||
|
||||
public void initialize() {
|
||||
if (!initialized) {
|
||||
intentRegistrations.clear();
|
||||
intentQueue.clear();
|
||||
final int broadcastThreadCount = 4;
|
||||
final int broadcastThreadCount = Runtime.getRuntime().availableProcessors() * 10;
|
||||
broadcastThreads = Executors.newFixedThreadPool(broadcastThreadCount, ThreadUtilities.newThreadFactory("intent-processor-%d"));
|
||||
initialized = true;
|
||||
terminated = false;
|
||||
@@ -94,14 +92,14 @@ public class IntentManager {
|
||||
catch (RejectedExecutionException e) { } // This error is thrown when the server is being shut down
|
||||
}
|
||||
|
||||
public void registerForIntent(String intentType, IntentReceiver r) {
|
||||
public void registerForIntent(Class<? extends Intent> c, IntentReceiver r) {
|
||||
if (r == null)
|
||||
throw new NullPointerException("Cannot register a null value for an intent");
|
||||
synchronized (intentRegistrations) {
|
||||
List <IntentReceiver> intents = intentRegistrations.get(intentType);
|
||||
List <IntentReceiver> intents = intentRegistrations.get(c);
|
||||
if (intents == null) {
|
||||
intents = new CopyOnWriteArrayList<>();
|
||||
intentRegistrations.put(intentType, intents);
|
||||
intentRegistrations.put(c, intents);
|
||||
}
|
||||
synchronized (intents) {
|
||||
intents.add(r);
|
||||
@@ -109,27 +107,10 @@ public class IntentManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterForIntent(String intentType, IntentReceiver r) {
|
||||
if (r == null)
|
||||
return;
|
||||
synchronized (intentRegistrations) {
|
||||
if (!intentRegistrations.containsKey(intentType))
|
||||
return;
|
||||
List<IntentReceiver> receivers = intentRegistrations.get(intentType);
|
||||
for (IntentReceiver recv : receivers) {
|
||||
if (r == recv || r.equals(recv)) {
|
||||
r = recv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
receivers.remove(r);
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcast(Intent i) {
|
||||
List <IntentReceiver> receivers;
|
||||
synchronized (intentRegistrations) {
|
||||
receivers = intentRegistrations.get(i.getType());
|
||||
receivers = intentRegistrations.get(i.getClass());
|
||||
}
|
||||
if (receivers == null) {
|
||||
i.markAsComplete();
|
||||
@@ -144,9 +125,9 @@ public class IntentManager {
|
||||
private void broadcast(IntentReceiver r, Intent i) {
|
||||
try {
|
||||
r.onIntentReceived(i);
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable t) {
|
||||
Log.e("Fatal Exception while processing intent: " + i);
|
||||
Log.e(e);
|
||||
Log.e(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,17 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.control;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.projectswg.common.data.BackendData;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.DataManager;
|
||||
import com.projectswg.common.info.Log;
|
||||
|
||||
/**
|
||||
* A Service is a class that does a specific job for the application
|
||||
*/
|
||||
public abstract class Service implements IntentReceiver {
|
||||
public abstract class Service {
|
||||
|
||||
private static DataManager dataManager = null;
|
||||
|
||||
@@ -90,27 +91,9 @@ public abstract class Service implements IntentReceiver {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers for the specified intent string
|
||||
* @param type the intent string
|
||||
*/
|
||||
public void registerForIntent(String type) {
|
||||
IntentManager.getInstance().registerForIntent(type, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters for the specified intent string
|
||||
* @param type the intent string
|
||||
*/
|
||||
public void unregisterForIntent(String type) {
|
||||
IntentManager.getInstance().unregisterForIntent(type, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when an intent is received from the system
|
||||
*/
|
||||
public void onIntentReceived(Intent i) {
|
||||
Log.w("Warning: " + getClass().getSimpleName() + " did not override onIntentReceived");
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final <T extends Intent> void registerForIntent(Class<T> c, Consumer<T> consumer) {
|
||||
IntentManager.getInstance().registerForIntent(c, (i) -> consumer.accept((T) i));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,8 +32,6 @@ import com.projectswg.lightspeed.build.ServerBuildData;
|
||||
|
||||
public class LaunchStarshipIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "LaunchStarshipIntent";
|
||||
|
||||
private ServerBuildData build;
|
||||
|
||||
public LaunchStarshipIntent() {
|
||||
@@ -41,7 +39,6 @@ public class LaunchStarshipIntent extends Intent {
|
||||
}
|
||||
|
||||
public LaunchStarshipIntent(ServerBuildData build) {
|
||||
super(TYPE);
|
||||
setBuild(build);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,68 +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.common.intents;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
|
||||
public class OutboundPacketIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "OutboundPacketIntent";
|
||||
|
||||
private InetSocketAddress address;
|
||||
private Packet packet;
|
||||
|
||||
public OutboundPacketIntent() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public OutboundPacketIntent(InetSocketAddress address, Packet packet) {
|
||||
super(TYPE);
|
||||
setAddress(address);
|
||||
setPacket(packet);
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public Packet getPacket() {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void setAddress(InetSocketAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public void setPacket(Packet packet) {
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,8 +32,6 @@ import com.projectswg.lightspeed.server.ServerServerData;
|
||||
|
||||
public class PrepareStarshipIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "PrepareStarshipIntent";
|
||||
|
||||
private ServerServerData server;
|
||||
|
||||
public PrepareStarshipIntent() {
|
||||
@@ -41,7 +39,6 @@ public class PrepareStarshipIntent extends Intent {
|
||||
}
|
||||
|
||||
public PrepareStarshipIntent(ServerServerData server) {
|
||||
super(TYPE);
|
||||
setServer(server);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,42 +27,34 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.intents;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.lightspeed.communication.HttpResponder;
|
||||
|
||||
public class InboundPacketIntent extends Intent {
|
||||
public class RegisterHttpListenerIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "InboundPacketIntent";
|
||||
private PacketType requestType;
|
||||
private HttpResponder predicate;
|
||||
|
||||
private InetSocketAddress address;
|
||||
private Packet packet;
|
||||
|
||||
public InboundPacketIntent() {
|
||||
this(null, null);
|
||||
public RegisterHttpListenerIntent(PacketType requestType, HttpResponder responder) {
|
||||
setRequestType(requestType);
|
||||
setHttpResponder(responder);
|
||||
}
|
||||
|
||||
public InboundPacketIntent(InetSocketAddress address, Packet packet) {
|
||||
super(TYPE);
|
||||
setAddress(address);
|
||||
setPacket(packet);
|
||||
public PacketType getRequestType() {
|
||||
return requestType;
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return address;
|
||||
public HttpResponder getHttpResponder() {
|
||||
return predicate;
|
||||
}
|
||||
|
||||
public Packet getPacket() {
|
||||
return packet;
|
||||
public void setRequestType(PacketType requestType) {
|
||||
this.requestType = requestType;
|
||||
}
|
||||
|
||||
public void setAddress(InetSocketAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public void setPacket(Packet packet) {
|
||||
this.packet = packet;
|
||||
public void setHttpResponder(HttpResponder predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,6 @@
|
||||
package com.projectswg.common.network.packets;
|
||||
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.network.packets.init.*;
|
||||
import com.projectswg.common.network.packets.post.*;
|
||||
import com.projectswg.common.network.packets.request.*;
|
||||
import com.projectswg.common.network.packets.response.*;
|
||||
@@ -73,14 +72,13 @@ public class Packet {
|
||||
|
||||
public static Packet inflate(JSONObject json, PacketType type) {
|
||||
switch (type) {
|
||||
case INIT_PROTOCOL_VERSION: return new InitProtocolVersionPacket(json);
|
||||
case CONNECTED: return new ConnectedPacket(json);
|
||||
case POST_BUILD: return new PostBuildPacket(json);
|
||||
case POST_DEPLOY: return new PostDeployPacket(json);
|
||||
case POST_STOP_BUILD: return new PostStopBuildPacket(json);
|
||||
case POST_STOP_DEPLOY: return new PostStopDeployPacket(json);
|
||||
case POST_CREATE_SERVER: return new PostCreateServerPacket(json);
|
||||
case POST_DELETE_SERVER: return new PostDeleteServerPacket(json);
|
||||
case POST_RESULT: return new PostResult(json);
|
||||
case REQUEST_SERVER_LIST: return new RequestServerListPacket(json);
|
||||
case REQUEST_BUILD_LIST: return new RequestBuildListPacket(json);
|
||||
case REQUEST_DEPLOYMENT_LIST: return new RequestDeploymentListPacket(json);
|
||||
|
||||
@@ -29,10 +29,6 @@ package com.projectswg.common.network.packets;
|
||||
|
||||
public enum PacketType {
|
||||
|
||||
// INIT
|
||||
INIT_PROTOCOL_VERSION,
|
||||
CONNECTED,
|
||||
|
||||
// GET-REQUEST
|
||||
REQUEST_SERVER_LIST,
|
||||
REQUEST_BUILD_LIST,
|
||||
@@ -50,6 +46,7 @@ public enum PacketType {
|
||||
RESPONSE_DEPLOYMENT_DETAILED,
|
||||
|
||||
// POST
|
||||
POST_RESULT,
|
||||
POST_BUILD,
|
||||
POST_DEPLOY,
|
||||
POST_STOP_BUILD,
|
||||
|
||||
@@ -1,56 +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.common.network.packets.init;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
public class InitProtocolVersionPacket extends Packet {
|
||||
|
||||
private static final String VERSION = "version";
|
||||
|
||||
public InitProtocolVersionPacket(JSONObject json) {
|
||||
super(json, PacketType.INIT_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
public InitProtocolVersionPacket(String version) {
|
||||
super(PacketType.INIT_PROTOCOL_VERSION);
|
||||
getJSON().put(VERSION, version);
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return getJSON().getString(VERSION);
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
getJSON().put(VERSION, version);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,11 +37,11 @@ public class PostDeployPacket extends Packet {
|
||||
private static final String SERVER_ID = "server_id";
|
||||
|
||||
public PostDeployPacket(JSONObject json) {
|
||||
super(json, PacketType.POST_DELETE_SERVER);
|
||||
super(json, PacketType.POST_DEPLOY);
|
||||
}
|
||||
|
||||
public PostDeployPacket(String serverId) {
|
||||
super(PacketType.POST_DELETE_SERVER);
|
||||
super(PacketType.POST_DEPLOY);
|
||||
setServerId(serverId);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,21 +25,32 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package com.projectswg.common.network.packets.init;
|
||||
package com.projectswg.common.network.packets.post;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
public class ConnectedPacket extends Packet {
|
||||
public class PostResult extends Packet {
|
||||
|
||||
public ConnectedPacket() {
|
||||
super(PacketType.CONNECTED);
|
||||
private static final String SUCCESS = "success";
|
||||
|
||||
public PostResult(JSONObject json) {
|
||||
super(json, PacketType.POST_RESULT);
|
||||
}
|
||||
|
||||
public ConnectedPacket(JSONObject json) {
|
||||
super(json, PacketType.CONNECTED);
|
||||
public PostResult(boolean success) {
|
||||
super(PacketType.POST_RESULT);
|
||||
setSuccess(success);
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return getJSON().getBoolean(SUCCESS);
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
getJSON().put(SUCCESS, success);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class RequestBuildDetailedPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestBuildDetailedPacket(long buildId) {
|
||||
super(PacketType.REQUEST_BUILD_DETAILED, PacketType.RESPONSE_BUILD_DETAILED);
|
||||
super(PacketType.REQUEST_BUILD_DETAILED);
|
||||
setBuildId(buildId);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class RequestBuildListPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestBuildListPacket(String serverId) {
|
||||
super(PacketType.REQUEST_BUILD_LIST, PacketType.RESPONSE_BUILD_LIST);
|
||||
super(PacketType.REQUEST_BUILD_LIST);
|
||||
setServerId(serverId);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class RequestDeploymentDetailedPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestDeploymentDetailedPacket(long deploymentId) {
|
||||
super(PacketType.REQUEST_DEPLOYMENT_DETAILED, PacketType.RESPONSE_DEPLOYMENT_DETAILED);
|
||||
super(PacketType.REQUEST_DEPLOYMENT_DETAILED);
|
||||
setDeploymentId(deploymentId);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class RequestDeploymentListPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestDeploymentListPacket(String serverId) {
|
||||
super(PacketType.REQUEST_DEPLOYMENT_LIST, PacketType.RESPONSE_DEPLOYMENT_LIST);
|
||||
super(PacketType.REQUEST_DEPLOYMENT_LIST);
|
||||
setServerId(serverId);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,35 +32,14 @@ import me.joshlarson.json.JSONObject;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
public class RequestPacket extends Packet {
|
||||
|
||||
private static final String REQUESTED_TYPE = "request_type";
|
||||
private static final String REQUESTED_ID = "request_id";
|
||||
public abstract class RequestPacket extends Packet {
|
||||
|
||||
public RequestPacket(JSONObject json, PacketType type) {
|
||||
super(json, type);
|
||||
}
|
||||
|
||||
public RequestPacket(PacketType type, PacketType requested) {
|
||||
public RequestPacket(PacketType type) {
|
||||
super(type);
|
||||
setRequestedType(requested);
|
||||
setRequestedId(-1);
|
||||
}
|
||||
|
||||
public PacketType getRequestedPacket() {
|
||||
return PacketType.valueOf(getJSON().getString(REQUESTED_TYPE));
|
||||
}
|
||||
|
||||
public long getRequestId() {
|
||||
return getJSON().getLong(REQUESTED_ID);
|
||||
}
|
||||
|
||||
public void setRequestedType(PacketType type) {
|
||||
getJSON().put(REQUESTED_TYPE, type.name());
|
||||
}
|
||||
|
||||
public void setRequestedId(long requestId) {
|
||||
getJSON().put(REQUESTED_ID, requestId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class RequestServerDetailedPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestServerDetailedPacket(String serverId) {
|
||||
super(PacketType.REQUEST_SERVER_DETAILED, PacketType.RESPONSE_SERVER_DETAILED);
|
||||
super(PacketType.REQUEST_SERVER_DETAILED);
|
||||
setServerId(serverId);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class RequestServerListPacket extends RequestPacket {
|
||||
}
|
||||
|
||||
public RequestServerListPacket() {
|
||||
super(PacketType.REQUEST_SERVER_LIST, PacketType.RESPONSE_SERVER_LIST);
|
||||
super(PacketType.REQUEST_SERVER_LIST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ public class ResponseBuildDetailedPacket extends ResponsePacket {
|
||||
private static final String BUILD_STRING = "build_string";
|
||||
private static final String TEST_STRING = "test_string";
|
||||
private static final String COMPILE_TIME = "compile_time";
|
||||
private static final String OFFLINE = "offline";
|
||||
private static final String BUILD_SUCCESS = "build_success";
|
||||
private static final String TEST_SUCCESS = "test_success";
|
||||
private static final String CANCELLED = "cancelled";
|
||||
@@ -82,10 +81,6 @@ public class ResponseBuildDetailedPacket extends ResponsePacket {
|
||||
return getJSON().getDouble(COMPILE_TIME);
|
||||
}
|
||||
|
||||
public boolean isOffline() {
|
||||
return getJSON().getBoolean(OFFLINE);
|
||||
}
|
||||
|
||||
public boolean isBuildSuccess() {
|
||||
return getJSON().getBoolean(BUILD_SUCCESS);
|
||||
}
|
||||
@@ -112,7 +107,6 @@ public class ResponseBuildDetailedPacket extends ResponsePacket {
|
||||
build.setBuildString(getBuildString());
|
||||
build.setTestString(getTestString());
|
||||
build.setCompileTime(getCompileTime());
|
||||
build.setOffline(isOffline());
|
||||
build.setBuildSuccess(isBuildSuccess());
|
||||
build.setTestSuccess(isTestSuccess());
|
||||
build.setCancelled(isCancelled());
|
||||
@@ -144,10 +138,6 @@ public class ResponseBuildDetailedPacket extends ResponsePacket {
|
||||
getJSON().put(COMPILE_TIME, compileTime);
|
||||
}
|
||||
|
||||
public void setOffline(boolean offline) {
|
||||
getJSON().put(OFFLINE, offline);
|
||||
}
|
||||
|
||||
public void setBuildSuccess(boolean buildSuccess) {
|
||||
getJSON().put(BUILD_SUCCESS, buildSuccess);
|
||||
}
|
||||
@@ -176,7 +166,6 @@ public class ResponseBuildDetailedPacket extends ResponsePacket {
|
||||
setBuildString(buildData.getBuildString());
|
||||
setTestString(buildData.getTestString());
|
||||
setCompileTime(buildData.getCompileTime());
|
||||
setOffline(buildData.isOffline());
|
||||
setBuildSuccess(buildData.isBuildSuccess());
|
||||
setTestSuccess(buildData.isTestSuccess());
|
||||
setCancelled(buildData.isCancelled());
|
||||
|
||||
@@ -32,26 +32,14 @@ import me.joshlarson.json.JSONObject;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
public class ResponsePacket extends Packet {
|
||||
|
||||
private static final String REQUESTED_ID = "request_id";
|
||||
public abstract class ResponsePacket extends Packet {
|
||||
|
||||
public ResponsePacket(JSONObject json, PacketType type) {
|
||||
super(json, type);
|
||||
setRequestedId(json.getLong(REQUESTED_ID));
|
||||
}
|
||||
|
||||
public ResponsePacket(PacketType type) {
|
||||
super(type);
|
||||
setRequestedId(-1);
|
||||
}
|
||||
|
||||
public long getRequestId() {
|
||||
return getJSON().getLong(REQUESTED_ID);
|
||||
}
|
||||
|
||||
public void setRequestedId(long requestId) {
|
||||
getJSON().put(REQUESTED_ID, requestId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,41 +28,51 @@
|
||||
package com.projectswg.lightspeed;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.intents.OutboundPacketIntent;
|
||||
import com.projectswg.common.network.TCPServer;
|
||||
import com.projectswg.common.network.TCPServer.TCPCallback;
|
||||
import com.projectswg.lightspeed.communication.LightspeedSession;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.lightspeed.communication.HttpResponder;
|
||||
|
||||
public class CommunicationService extends Service implements TCPCallback {
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
import fi.iki.elonen.NanoHTTPD.IHTTPSession;
|
||||
import fi.iki.elonen.NanoHTTPD.Response;
|
||||
import fi.iki.elonen.NanoHTTPD.Response.Status;
|
||||
|
||||
public class CommunicationService extends Service {
|
||||
|
||||
private final TCPServer server;
|
||||
private final Map<InetSocketAddress, LightspeedSession> sessions;
|
||||
private final NanoHTTPD httpServer;
|
||||
private final Map<PacketType, HttpResponder> responders;
|
||||
|
||||
public CommunicationService() {
|
||||
server = new TCPServer(getConfig(ConfigFile.LIGHTSPEED).getInt("PORT", 44444), 4096);
|
||||
sessions = new HashMap<>();
|
||||
server.setCallback(this);
|
||||
httpServer = new NanoHTTPD(44444) {
|
||||
public Response serve(IHTTPSession session) {
|
||||
return CommunicationService.this.serve(session);
|
||||
}
|
||||
};
|
||||
responders = new HashMap<>();
|
||||
|
||||
registerForIntent(OutboundPacketIntent.TYPE);
|
||||
registerForIntent(RegisterHttpListenerIntent.class, rhli -> handleRegisterListener(rhli));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
Config config = getConfig(ConfigFile.LIGHTSPEED);
|
||||
try {
|
||||
server.bind();
|
||||
httpServer.start(config.getInt("HTTP-TIMEOUT", 2000));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.a(e);
|
||||
return false;
|
||||
}
|
||||
return super.initialize();
|
||||
@@ -70,75 +80,93 @@ public class CommunicationService extends Service implements TCPCallback {
|
||||
|
||||
@Override
|
||||
public boolean terminate() {
|
||||
server.close();
|
||||
httpServer.stop();
|
||||
return super.terminate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIntentReceived(Intent i) {
|
||||
if (i instanceof OutboundPacketIntent) {
|
||||
LightspeedSession session;
|
||||
synchronized (sessions) {
|
||||
session = sessions.get(((OutboundPacketIntent) i).getAddress());
|
||||
}
|
||||
if (session == null) {
|
||||
Log.e("Unknown session for address: %s", ((OutboundPacketIntent) i).getAddress());
|
||||
return;
|
||||
}
|
||||
session.send(((OutboundPacketIntent) i).getPacket());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIncomingConnection(Socket s) {
|
||||
SocketAddress addr = s.getRemoteSocketAddress();
|
||||
if (addr == null) {
|
||||
Log.e("Unable to accept incoming connection! Address is null.");
|
||||
private Response serve(IHTTPSession session) {
|
||||
try {
|
||||
JSONObject params = getJSONObject(session);
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
switch (session.getMethod()) {
|
||||
case GET:
|
||||
params.put("type", "REQUEST_" + params.getString("type"));
|
||||
return process(params);
|
||||
case POST:
|
||||
params.put("type", "POST_" + params.getString("type"));
|
||||
return process(params);
|
||||
default:
|
||||
return getMethodNotAllowed();
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(e.toString());
|
||||
return getNotFound("Invalid "+session.getMethod()+" Type: " + params.getString("type"));
|
||||
} catch (Exception e) {
|
||||
Log.w(e);
|
||||
return getServerError(e.toString() + "\nRequest:\n" + params);
|
||||
}
|
||||
return;
|
||||
} catch (Throwable t) {
|
||||
Log.w(t);
|
||||
return getServerError(t.toString());
|
||||
}
|
||||
if (!(addr instanceof InetSocketAddress)) {
|
||||
Log.e("Unable to accept incoming connection! Address is not InetSocketAddress.");
|
||||
}
|
||||
|
||||
private Response process(JSONObject params) {
|
||||
PacketType request = PacketType.valueOf(params.getString("type"));
|
||||
HttpResponder responder = responders.get(request);
|
||||
if (responder == null)
|
||||
return getNotFound("No Services Ready to Respond to " + request.name()); // From PacketType.valueOf
|
||||
JSONObject response = responder.request(request, params);
|
||||
if (response == null)
|
||||
return getNotFound("Invalid Request Parameters");
|
||||
return NanoHTTPD.newFixedLengthResponse(Status.OK, NanoHTTPD.MIME_PLAINTEXT, response.toString());
|
||||
}
|
||||
|
||||
private JSONObject getJSONObject(IHTTPSession session) {
|
||||
JSONObject ret = new JSONObject();
|
||||
for (Entry<String, List<String>> param : session.getParameters().entrySet()) {
|
||||
if (param.getValue().isEmpty())
|
||||
continue;
|
||||
String key = new String(param.getKey().getBytes(StandardCharsets.US_ASCII));
|
||||
String val = new String(param.getValue().get(0).getBytes(StandardCharsets.US_ASCII));
|
||||
if (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false")) {
|
||||
ret.put(key, val.equalsIgnoreCase("true"));
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
Log.i("%s connected", addr);
|
||||
synchronized (sessions) {
|
||||
sessions.put((InetSocketAddress) addr, new LightspeedSession(server, (InetSocketAddress) addr));
|
||||
long l = Long.parseLong(val);
|
||||
ret.put(key, l);
|
||||
continue;
|
||||
} catch (NumberFormatException e) { }
|
||||
try {
|
||||
double d = Double.parseDouble(val);
|
||||
ret.put(key, d);
|
||||
continue;
|
||||
} catch (NumberFormatException e) { }
|
||||
ret.put(key, val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionDisconnect(Socket s, SocketAddress addr) {
|
||||
Assert.notNull(addr);
|
||||
Log.i("%s disconnected", addr);
|
||||
synchronized (sessions) {
|
||||
sessions.remove(addr);
|
||||
}
|
||||
private Response getMethodNotAllowed() {
|
||||
return NanoHTTPD.newFixedLengthResponse(Status.METHOD_NOT_ALLOWED, NanoHTTPD.MIME_PLAINTEXT, "Method Not Allowed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIncomingData(Socket s, byte[] data) {
|
||||
SocketAddress addr = s.getRemoteSocketAddress();
|
||||
Assert.notNull(addr);
|
||||
LightspeedSession session;
|
||||
synchronized (sessions) {
|
||||
session = sessions.get(addr);
|
||||
}
|
||||
if (session != null)
|
||||
session.onIncoming(data);
|
||||
private Response getNotFound(String str) {
|
||||
return NanoHTTPD.newFixedLengthResponse(Status.NOT_FOUND, NanoHTTPD.MIME_PLAINTEXT, str);
|
||||
}
|
||||
|
||||
private Response getServerError(String str) {
|
||||
return NanoHTTPD.newFixedLengthResponse(Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, str);
|
||||
}
|
||||
|
||||
private void handleRegisterListener(RegisterHttpListenerIntent rhli) {
|
||||
Log.i("Registering a responder for %s", rhli.getRequestType());
|
||||
Assert.isNull(responders.put(rhli.getRequestType(), rhli.getHttpResponder()), "Cannot register two responders for the same packet type!");
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return server.getPort();
|
||||
return httpServer.getListeningPort();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
package com.projectswg.lightspeed;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@@ -39,19 +38,20 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.info.RelationalDatabase;
|
||||
import com.projectswg.common.info.RelationalServerFactory;
|
||||
import com.projectswg.common.intents.InboundPacketIntent;
|
||||
import com.projectswg.common.intents.LaunchStarshipIntent;
|
||||
import com.projectswg.common.intents.OutboundPacketIntent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.common.network.packets.post.PostDeployPacket;
|
||||
import com.projectswg.common.network.packets.post.PostResult;
|
||||
import com.projectswg.common.network.packets.post.PostStopDeployPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestDeploymentDetailedPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestDeploymentListPacket;
|
||||
@@ -74,8 +74,7 @@ public class DeploymentService extends Service {
|
||||
deployments = new HashMap<>();
|
||||
deploymentHistory = new HashSet<>();
|
||||
|
||||
registerForIntent(LaunchStarshipIntent.TYPE);
|
||||
registerForIntent(InboundPacketIntent.TYPE);
|
||||
registerForIntent(LaunchStarshipIntent.class, lsi -> handleLaunchStarshipIntent(lsi));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,6 +88,10 @@ public class DeploymentService extends Service {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
new RegisterHttpListenerIntent(PacketType.POST_DEPLOY, (type, params) -> processPostDeploy(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.POST_STOP_DEPLOY, (type, params) -> processStopDeployment(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_DEPLOYMENT_LIST, (type, params) -> processDeploymentList(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_DEPLOYMENT_DETAILED, (type, params) -> processDeploymentDetailed(params)).broadcast();
|
||||
return super.initialize();
|
||||
}
|
||||
|
||||
@@ -96,23 +99,20 @@ public class DeploymentService extends Service {
|
||||
public boolean terminate() {
|
||||
synchronized (deployments) {
|
||||
for (ServerDeploymentData deployment : deployments.values()) {
|
||||
if (deployment.getProcess() != null)
|
||||
if (deployment.getProcess() != null) {
|
||||
Log.i("Shutting down child process: %s", deployment.getServer().getName());
|
||||
deployment.getProcess().stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.terminate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIntentReceived(Intent i) {
|
||||
if (i instanceof LaunchStarshipIntent) {
|
||||
ServerBuildData build = ((LaunchStarshipIntent) i).getBuild();
|
||||
Log.i("Deploying %s", build.getServer().getName());
|
||||
ServerDeploymentData deployment = new ServerDeploymentData(deploymentId.incrementAndGet(), build);
|
||||
launch(deployment);
|
||||
} else if (i instanceof InboundPacketIntent) {
|
||||
processInboundPacketIntent(((InboundPacketIntent) i).getAddress(), ((InboundPacketIntent) i).getPacket());
|
||||
}
|
||||
private void handleLaunchStarshipIntent(LaunchStarshipIntent lsi) {
|
||||
ServerBuildData build = lsi.getBuild();
|
||||
Log.i("Deploying %s", build.getServer().getName());
|
||||
ServerDeploymentData deployment = new ServerDeploymentData(deploymentId.incrementAndGet(), build);
|
||||
launch(deployment);
|
||||
}
|
||||
|
||||
private File getJdk() {
|
||||
@@ -130,47 +130,47 @@ public class DeploymentService extends Service {
|
||||
return jdk;
|
||||
}
|
||||
|
||||
private void processInboundPacketIntent(InetSocketAddress address, Packet p) {
|
||||
switch (p.getType()) {
|
||||
case POST_DEPLOY: launchStarship(((PostDeployPacket) p).getServerId()); break;
|
||||
case POST_STOP_DEPLOY: processStopDeployment((PostStopDeployPacket) p); break;
|
||||
case REQUEST_DEPLOYMENT_LIST: processDeploymentList(address, (RequestDeploymentListPacket) p); break;
|
||||
case REQUEST_DEPLOYMENT_DETAILED: processDeploymentDetailed(address, (RequestDeploymentDetailedPacket) p); break;
|
||||
default: break;
|
||||
}
|
||||
private JSONObject processPostDeploy(JSONObject params) {
|
||||
PostDeployPacket deploy = new PostDeployPacket(params);
|
||||
launchStarship(deploy.getServerId());
|
||||
return new PostResult(true).getJSON();
|
||||
}
|
||||
|
||||
private void processDeploymentDetailed(InetSocketAddress address, RequestDeploymentDetailedPacket p) {
|
||||
private JSONObject processStopDeployment(JSONObject params) {
|
||||
PostStopDeployPacket p = new PostStopDeployPacket(params);
|
||||
synchronized (deployments) {
|
||||
ServerDeploymentData d = deployments.get(p.getServerId());
|
||||
if (d != null && d.getProcess() != null) {
|
||||
d.getProcess().stop();
|
||||
return new PostResult(true).getJSON();
|
||||
}
|
||||
}
|
||||
return new PostResult(false).getJSON();
|
||||
}
|
||||
|
||||
private JSONObject processDeploymentDetailed(JSONObject params) {
|
||||
RequestDeploymentDetailedPacket request = new RequestDeploymentDetailedPacket(params);
|
||||
synchronized (deploymentHistory) {
|
||||
for (ServerDeploymentData d : deploymentHistory) {
|
||||
if (d.getId() == p.getDeploymentId()) {
|
||||
new OutboundPacketIntent(address, new ResponseDeploymentDetailedPacket(d.getShared())).broadcast();
|
||||
break;
|
||||
if (d.getId() == request.getDeploymentId()) {
|
||||
return new ResponseDeploymentDetailedPacket(d.getShared()).getJSON();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processDeploymentList(InetSocketAddress address, RequestDeploymentListPacket p) {
|
||||
private JSONObject processDeploymentList(JSONObject params) {
|
||||
RequestDeploymentListPacket request = new RequestDeploymentListPacket(params);
|
||||
List<SharedDeploymentData> deployList = new ArrayList<>();
|
||||
synchronized (deploymentHistory) {
|
||||
for (ServerDeploymentData d : deploymentHistory) {
|
||||
if (d.getServer().getName().equals(p.getServerId())) {
|
||||
if (d.getServer().getName().equals(request.getServerId())) {
|
||||
deployList.add(d.getShared());
|
||||
}
|
||||
}
|
||||
}
|
||||
new OutboundPacketIntent(address, new ResponseDeploymentListPacket(p.getServerId(), deployList)).broadcast();
|
||||
}
|
||||
|
||||
private void processStopDeployment(PostStopDeployPacket p) {
|
||||
synchronized (deployments) {
|
||||
ServerDeploymentData d = deployments.get(p.getServerId());
|
||||
if (d != null) {
|
||||
if (d.getProcess() != null)
|
||||
d.getProcess().stop();
|
||||
}
|
||||
}
|
||||
return new ResponseDeploymentListPacket(request.getServerId(), deployList).getJSON();
|
||||
}
|
||||
|
||||
private void launchStarship(String serverId) {
|
||||
|
||||
@@ -29,7 +29,6 @@ package com.projectswg.lightspeed.build;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.sql.ResultSet;
|
||||
@@ -42,20 +41,21 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.info.Config;
|
||||
import com.projectswg.common.info.ConfigFile;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.info.RelationalDatabase;
|
||||
import com.projectswg.common.info.RelationalServerFactory;
|
||||
import com.projectswg.common.intents.InboundPacketIntent;
|
||||
import com.projectswg.common.intents.LaunchStarshipIntent;
|
||||
import com.projectswg.common.intents.OutboundPacketIntent;
|
||||
import com.projectswg.common.intents.PrepareStarshipIntent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.common.network.packets.post.PostBuildPacket;
|
||||
import com.projectswg.common.network.packets.post.PostResult;
|
||||
import com.projectswg.common.network.packets.post.PostStopBuildPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestBuildDetailedPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestBuildListPacket;
|
||||
@@ -78,8 +78,7 @@ public class BuildService extends Service {
|
||||
inprogress = new HashMap<>();
|
||||
buildHistory = new HashSet<>();
|
||||
|
||||
registerForIntent(PrepareStarshipIntent.TYPE);
|
||||
registerForIntent(InboundPacketIntent.TYPE);
|
||||
registerForIntent(PrepareStarshipIntent.class, psi -> onPrepareStarshipIntent(psi));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,16 +92,13 @@ public class BuildService extends Service {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
new RegisterHttpListenerIntent(PacketType.POST_BUILD, (type, params) -> processBuild(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.POST_STOP_BUILD, (type, params) -> processStopBuild(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_BUILD_LIST, (type, params) -> processBuildList(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_BUILD_DETAILED, (type, params) -> processBuildDetailed(params)).broadcast();
|
||||
return super.initialize();
|
||||
}
|
||||
|
||||
public void onIntentReceived(Intent i) {
|
||||
if (i instanceof PrepareStarshipIntent)
|
||||
onPrepareStarshipIntent((PrepareStarshipIntent) i);
|
||||
else if (i instanceof InboundPacketIntent)
|
||||
onInboundPacketIntent((InboundPacketIntent) i);
|
||||
}
|
||||
|
||||
private File getJdk() {
|
||||
Config config = getConfig(ConfigFile.LIGHTSPEED);
|
||||
String path = config.getString("jdk", System.getProperty("java.home"));
|
||||
@@ -135,53 +131,47 @@ public class BuildService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private void onInboundPacketIntent(InboundPacketIntent ipi) {
|
||||
Packet p = ipi.getPacket();
|
||||
switch (p.getType()) {
|
||||
case POST_BUILD: processBuild((PostBuildPacket) p); break;
|
||||
case POST_STOP_BUILD: processPostStopBuild((PostStopBuildPacket) p); break;
|
||||
case REQUEST_BUILD_LIST: processBuildList(ipi.getAddress(), (RequestBuildListPacket) p); break;
|
||||
case REQUEST_BUILD_DETAILED:processBuildDetailed(ipi.getAddress(), (RequestBuildDetailedPacket) p); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processBuild(PostBuildPacket p) {
|
||||
private JSONObject processBuild(JSONObject params) {
|
||||
PostBuildPacket p = new PostBuildPacket(params);
|
||||
ServerServerData server = getBackendData().getServer(p.getServerId());
|
||||
if (server != null)
|
||||
new PrepareStarshipIntent(server).broadcast();
|
||||
return new PostResult(server != null).getJSON();
|
||||
}
|
||||
|
||||
private void processPostStopBuild(PostStopBuildPacket p) {
|
||||
private JSONObject processStopBuild(JSONObject params) {
|
||||
PostStopBuildPacket p = new PostStopBuildPacket(params);
|
||||
synchronized (inprogress) {
|
||||
ServerBuildData installation = inprogress.get(p.getServerId());
|
||||
if (installation != null)
|
||||
installation.setState(InstallationState.CANCELLED);
|
||||
return new PostResult(installation != null).getJSON();
|
||||
}
|
||||
}
|
||||
|
||||
private void processBuildList(InetSocketAddress address, RequestBuildListPacket p) {
|
||||
private JSONObject processBuildList(JSONObject params) {
|
||||
RequestBuildListPacket p = new RequestBuildListPacket(params);
|
||||
List<SharedBuildData> buildList = new ArrayList<>();
|
||||
synchronized (buildHistory) {
|
||||
List<SharedBuildData> buildList = new ArrayList<>();
|
||||
for (ServerBuildData build : buildHistory) {
|
||||
if (p.getServerId().equals(build.getServer().getName())) {
|
||||
buildList.add(build.getShared());
|
||||
}
|
||||
}
|
||||
new OutboundPacketIntent(address, new ResponseBuildListPacket(p.getServerId(), buildList)).broadcast();
|
||||
}
|
||||
return new ResponseBuildListPacket(p.getServerId(), buildList).getJSON();
|
||||
}
|
||||
|
||||
private void processBuildDetailed(InetSocketAddress address, RequestBuildDetailedPacket p) {
|
||||
private JSONObject processBuildDetailed(JSONObject params) {
|
||||
RequestBuildDetailedPacket p = new RequestBuildDetailedPacket(params);
|
||||
synchronized (buildHistory) {
|
||||
for (ServerBuildData build : buildHistory) {
|
||||
if (p.getBuildId() == build.getId()) {
|
||||
new OutboundPacketIntent(address, new ResponseBuildDetailedPacket(build.getShared())).broadcast();
|
||||
break;
|
||||
return new ResponseBuildDetailedPacket(build.getShared()).getJSON();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onCompleted(String serverId, ServerBuildData build) {
|
||||
|
||||
@@ -27,8 +27,12 @@
|
||||
***********************************************************************************/
|
||||
package com.projectswg.lightspeed.communication;
|
||||
|
||||
public enum LightspeedState {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
public interface HttpResponder {
|
||||
|
||||
JSONObject request(PacketType request, JSONObject params);
|
||||
|
||||
}
|
||||
@@ -1,114 +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.lightspeed.communication;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import com.projectswg.common.control.IntentChain;
|
||||
import com.projectswg.common.intents.InboundPacketIntent;
|
||||
import com.projectswg.common.network.TCPServer;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.init.ConnectedPacket;
|
||||
import com.projectswg.common.network.packets.init.InitProtocolVersionPacket;
|
||||
import com.projectswg.common.network.protocol.Protocol;
|
||||
import com.projectswg.common.network.protocol.ProtocolFactory;
|
||||
|
||||
public class LightspeedSession {
|
||||
|
||||
private final TCPServer server;
|
||||
private final InetSocketAddress address;
|
||||
private final IntentChain incomingChain;
|
||||
private final Object stateMutex;
|
||||
private Protocol protocol;
|
||||
private LightspeedState state;
|
||||
|
||||
public LightspeedSession(TCPServer server, InetSocketAddress address) {
|
||||
this.server = server;
|
||||
this.address = address;
|
||||
this.incomingChain = new IntentChain();
|
||||
this.stateMutex = new Object();
|
||||
this.protocol = ProtocolFactory.createProtocol(null);
|
||||
this.state = LightspeedState.CONNECTING;
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public LightspeedState getState() {
|
||||
synchronized (stateMutex) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
server.disconnect(address);
|
||||
updateState(LightspeedState.DISCONNECTED);
|
||||
}
|
||||
|
||||
public void onIncoming(byte [] data) {
|
||||
protocol.onIncomingData(data);
|
||||
while (protocol.getPacketCount() > 0) {
|
||||
Packet p = protocol.getNextPacket();
|
||||
if (p == null)
|
||||
continue;
|
||||
incomingChain.broadcastAfter(new InboundPacketIntent(address, p));
|
||||
processPacket(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(Packet p) {
|
||||
if (getState() == LightspeedState.CONNECTED)
|
||||
server.send(address, protocol.preparePacket(p));
|
||||
}
|
||||
|
||||
private boolean processPacket(Packet p) {
|
||||
if (p instanceof InitProtocolVersionPacket && getState() == LightspeedState.CONNECTING)
|
||||
return handleProtocolVersion(((InitProtocolVersionPacket) p).getVersion());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleProtocolVersion(String version) {
|
||||
Protocol requestedProtocol = ProtocolFactory.createProtocol(version);
|
||||
if (requestedProtocol == null) {
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
this.protocol = requestedProtocol;
|
||||
updateState(LightspeedState.CONNECTED);
|
||||
send(new ConnectedPacket());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateState(LightspeedState state) {
|
||||
synchronized (stateMutex) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,39 +28,56 @@
|
||||
package com.projectswg.lightspeed.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import me.joshlarson.json.JSONObject;
|
||||
|
||||
import com.projectswg.common.control.Intent;
|
||||
import com.projectswg.common.control.Service;
|
||||
import com.projectswg.common.intents.InboundPacketIntent;
|
||||
import com.projectswg.common.intents.OutboundPacketIntent;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.request.RequestServerListPacket;
|
||||
import com.projectswg.common.intents.RegisterHttpListenerIntent;
|
||||
import com.projectswg.common.network.packets.PacketType;
|
||||
import com.projectswg.common.network.packets.request.RequestServerDetailedPacket;
|
||||
import com.projectswg.common.network.packets.response.ResponseServerDetailedPacket;
|
||||
import com.projectswg.common.network.packets.response.ResponseServerListPacket;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
|
||||
public class ServerService extends Service {
|
||||
|
||||
private final Set<ServerServerData> servers;
|
||||
|
||||
public ServerService() {
|
||||
registerForIntent(InboundPacketIntent.TYPE);
|
||||
this.servers = new HashSet<>();
|
||||
}
|
||||
|
||||
public void onIntentReceived(Intent i) {
|
||||
if (i instanceof InboundPacketIntent)
|
||||
onInboundPacketIntent((InboundPacketIntent) i);
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
servers.addAll(getBackendData().getServerList());
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_SERVER_LIST, (type, params) -> onRequestServerList(params)).broadcast();
|
||||
new RegisterHttpListenerIntent(PacketType.REQUEST_SERVER_DETAILED, (type, params) -> onRequestServerDetailed(params)).broadcast();
|
||||
return super.initialize();
|
||||
}
|
||||
|
||||
private void onInboundPacketIntent(InboundPacketIntent i) {
|
||||
Packet p = i.getPacket();
|
||||
if (p instanceof RequestServerListPacket) {
|
||||
List<ServerServerData> servers = getBackendData().getServerList();
|
||||
List<SharedServerData> serverShared = new ArrayList<>(servers.size());
|
||||
for (ServerServerData server : servers)
|
||||
serverShared.add(server.getShared());
|
||||
ResponseServerListPacket response = new ResponseServerListPacket(serverShared);
|
||||
response.setRequestedId(((RequestServerListPacket) p).getRequestId());
|
||||
new OutboundPacketIntent(i.getAddress(), response).broadcast();
|
||||
private JSONObject onRequestServerList(JSONObject params) {
|
||||
synchronized (servers) {
|
||||
List<SharedServerData> serverList = new ArrayList<>(servers.size());
|
||||
for (ServerServerData server : servers) {
|
||||
serverList.add(server.getShared());
|
||||
}
|
||||
return new ResponseServerListPacket(serverList).getJSON();
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject onRequestServerDetailed(JSONObject params) {
|
||||
synchronized (servers) {
|
||||
RequestServerDetailedPacket request = new RequestServerDetailedPacket(params);
|
||||
for (ServerServerData server : servers) {
|
||||
if (server.getName().equals(request.getServerId())) {
|
||||
return new ResponseServerDetailedPacket(server.getShared()).getJSON();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
package com.projectswg.lightspeed_frontend;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
@@ -41,27 +37,17 @@ import com.projectswg.common.network.packets.request.RequestPacket;
|
||||
import com.projectswg.common.network.packets.request.RequestServerListPacket;
|
||||
import com.projectswg.common.network.packets.response.ResponsePacket;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendLightspeedSession.LightspeedSessionCallback;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
import com.projectswg.lightspeed_frontend.intents.ConnectionStateUpdateIntent;
|
||||
|
||||
public class Frontend {
|
||||
|
||||
private final FrontendCommunication communication;
|
||||
private final SharedData data;
|
||||
private final Map<Long, ResponseCallback> requests;
|
||||
private final AtomicLong requestId;
|
||||
|
||||
public Frontend() {
|
||||
communication = new FrontendCommunication();
|
||||
data = new SharedData();
|
||||
requests = new HashMap<>();
|
||||
requestId = new AtomicLong(0);
|
||||
communication.setCallback(new LightspeedSessionCallback() {
|
||||
public void onConnectionStateChanged(boolean connected) { Frontend.this.onConnectionStateChanged(connected); }
|
||||
public void onIncomingPacket(Packet p) { Frontend.this.processIncoming(p); }
|
||||
});
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@@ -90,12 +76,6 @@ public class Frontend {
|
||||
}
|
||||
|
||||
public void send(RequestPacket p, ResponseCallback callback) {
|
||||
if (callback != null) {
|
||||
p.setRequestedId(requestId.incrementAndGet());
|
||||
synchronized (requests) {
|
||||
requests.put(p.getRequestId(), callback);
|
||||
}
|
||||
}
|
||||
send(p);
|
||||
}
|
||||
|
||||
@@ -124,25 +104,6 @@ public class Frontend {
|
||||
});
|
||||
}
|
||||
|
||||
private void onConnectionStateChanged(boolean connected) {
|
||||
new ConnectionStateUpdateIntent(connected).broadcast();
|
||||
}
|
||||
|
||||
private void processIncoming(Packet p) {
|
||||
Log.i("RX %s", p);
|
||||
if (p instanceof ResponsePacket)
|
||||
processResponse((ResponsePacket) p);
|
||||
}
|
||||
|
||||
private void processResponse(ResponsePacket rp) {
|
||||
ResponseCallback callback;
|
||||
synchronized (requests) {
|
||||
callback = requests.get(rp.getRequestId());
|
||||
}
|
||||
if (callback != null)
|
||||
callback.onResponse(rp);
|
||||
}
|
||||
|
||||
public interface ResponseCallback {
|
||||
void onResponse(ResponsePacket p);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class LightspeedFrontendGUI extends Application {
|
||||
public LightspeedFrontendGUI() {
|
||||
frontend = new Frontend();
|
||||
primaryView = new LightspeedPrimaryView(frontend);
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.TYPE, (i) -> onConnectionUpdate(((ConnectionStateUpdateIntent) i).isConnected()));
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.class, i -> onConnectionUpdate(((ConnectionStateUpdateIntent) i).isConnected()));
|
||||
frontend.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,12 +56,11 @@ import com.projectswg.common.network.packets.response.ResponseDeploymentListPack
|
||||
import com.projectswg.common.network.packets.response.ResponseServerListPacket;
|
||||
import com.projectswg.common.utilities.TimeUtilities;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendLightspeedSession.LightspeedSessionCallback;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
|
||||
import com.projectswg.lightspeed_frontend.data.SharedServerData;
|
||||
|
||||
public class LightspeedFrontendText implements LightspeedSessionCallback {
|
||||
public class LightspeedFrontendText {
|
||||
|
||||
private final FrontendCommunication communication;
|
||||
private final Queue<Packet> inbound;
|
||||
@@ -69,23 +68,9 @@ public class LightspeedFrontendText implements LightspeedSessionCallback {
|
||||
|
||||
public LightspeedFrontendText() {
|
||||
communication = new FrontendCommunication();
|
||||
communication.setCallback(this);
|
||||
inbound = new ArrayDeque<>();
|
||||
running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChanged(boolean connected) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIncomingPacket(Packet p) {
|
||||
synchronized (inbound) {
|
||||
inbound.add(p);
|
||||
inbound.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
running = true;
|
||||
|
||||
@@ -35,21 +35,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import com.projectswg.common.control.Assert;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.utilities.ThreadUtilities;
|
||||
import com.projectswg.lightspeed.communication.LightspeedState;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendLightspeedSession.LightspeedSessionCallback;
|
||||
|
||||
public class FrontendCommunication {
|
||||
|
||||
private final AtomicBoolean running;
|
||||
|
||||
private ExecutorService executor;
|
||||
private FrontendLightspeedSession session;
|
||||
private LightspeedSessionCallback callback;
|
||||
|
||||
public FrontendCommunication() {
|
||||
running = new AtomicBoolean(false);
|
||||
session = null;
|
||||
callback = null;
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
@@ -67,50 +61,24 @@ public class FrontendCommunication {
|
||||
return false;
|
||||
}
|
||||
executor.shutdownNow();
|
||||
if (session != null) {
|
||||
session.disconnect();
|
||||
session = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return session != null && session.getState() == LightspeedState.CONNECTED;
|
||||
}
|
||||
|
||||
public void setCallback(LightspeedSessionCallback callback) {
|
||||
if (session != null)
|
||||
session.setCallback(callback);
|
||||
this.callback = callback;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void connect(InetSocketAddress addr) {
|
||||
if (addr == null)
|
||||
throw new NullPointerException();
|
||||
executor.execute(() -> {
|
||||
Assert.test(callback != null);
|
||||
if (session != null)
|
||||
session.disconnect();
|
||||
session = new FrontendLightspeedSession(addr);
|
||||
session.setCallback(callback);
|
||||
session.connect();
|
||||
});
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
executor.execute(() -> {
|
||||
Assert.test(session != null);
|
||||
if (session != null) {
|
||||
session.disconnect();
|
||||
session = null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void send(Packet p) {
|
||||
Assert.test(session != null);
|
||||
if (session != null)
|
||||
session.send(p);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,153 +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.lightspeed_frontend.communication;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import com.projectswg.common.callback.CallbackManager;
|
||||
import com.projectswg.common.info.Log;
|
||||
import com.projectswg.common.network.TCPSocket;
|
||||
import com.projectswg.common.network.TCPSocket.TCPSocketCallback;
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.common.network.packets.init.ConnectedPacket;
|
||||
import com.projectswg.common.network.packets.init.InitProtocolVersionPacket;
|
||||
import com.projectswg.common.network.protocol.AlphaProtocol;
|
||||
import com.projectswg.common.network.protocol.Protocol;
|
||||
import com.projectswg.common.network.protocol.ProtocolFactory;
|
||||
import com.projectswg.lightspeed.communication.LightspeedState;
|
||||
|
||||
public class FrontendLightspeedSession {
|
||||
|
||||
private final TCPSocket socket;
|
||||
private final InetSocketAddress address;
|
||||
private final CallbackManager<LightspeedSessionCallback> callbackManager;
|
||||
private final Object stateMutex;
|
||||
private LightspeedState state;
|
||||
private Protocol protocol;
|
||||
|
||||
public FrontendLightspeedSession(InetSocketAddress address) {
|
||||
this.socket = new TCPSocket(address, 4096);
|
||||
this.address = address;
|
||||
this.callbackManager = new CallbackManager<FrontendLightspeedSession.LightspeedSessionCallback>("lightspeed-session", 1);
|
||||
this.stateMutex = new Object();
|
||||
this.state = LightspeedState.DISCONNECTED;
|
||||
this.protocol = ProtocolFactory.createProtocol(AlphaProtocol.VERSION);
|
||||
this.socket.setCallback(new TCPSocketCallback() {
|
||||
public void onConnected(TCPSocket socket) { onConnectionChanged(true); }
|
||||
public void onDisconnected(TCPSocket socket) { onConnectionChanged(false); }
|
||||
public void onIncomingData(TCPSocket socket, byte [] data) { onIncoming(data); }
|
||||
});
|
||||
}
|
||||
|
||||
public void setCallback(LightspeedSessionCallback callback) {
|
||||
callbackManager.setCallback(callback);
|
||||
}
|
||||
|
||||
public InetSocketAddress getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public LightspeedState getState() {
|
||||
synchronized (stateMutex) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
Log.i("Connecting...");
|
||||
updateState(LightspeedState.CONNECTING);
|
||||
callbackManager.start();
|
||||
socket.connect();
|
||||
send(new InitProtocolVersionPacket(protocol.getVersion()));
|
||||
synchronized (stateMutex) {
|
||||
while (state == LightspeedState.CONNECTING) {
|
||||
try {
|
||||
stateMutex.wait();
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getState() == LightspeedState.CONNECTED)
|
||||
Log.i("Connected.");
|
||||
else
|
||||
Log.e("Failed to connect.");
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
socket.disconnect();
|
||||
Log.i("Disconnected.");
|
||||
updateState(LightspeedState.DISCONNECTED);
|
||||
callbackManager.stop();
|
||||
}
|
||||
|
||||
public void onIncoming(byte [] data) {
|
||||
protocol.onIncomingData(data);
|
||||
while (protocol.getPacketCount() > 0) {
|
||||
Packet p = protocol.getNextPacket();
|
||||
if (p != null)
|
||||
processPacket(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(Packet p) {
|
||||
if (getState() == LightspeedState.CONNECTED || (p instanceof InitProtocolVersionPacket && getState() == LightspeedState.CONNECTING))
|
||||
socket.send(protocol.preparePacket(p));
|
||||
}
|
||||
|
||||
public interface LightspeedSessionCallback {
|
||||
void onConnectionStateChanged(boolean connected);
|
||||
void onIncomingPacket(Packet p);
|
||||
}
|
||||
|
||||
private void processPacket(Packet p) {
|
||||
if (p instanceof ConnectedPacket) {
|
||||
updateState(LightspeedState.CONNECTED);
|
||||
return;
|
||||
}
|
||||
callbackManager.callOnEach((callback) -> callback.onIncomingPacket(p));
|
||||
}
|
||||
|
||||
private void onConnectionChanged(boolean connected) {
|
||||
if (!connected)
|
||||
disconnect();
|
||||
}
|
||||
|
||||
private void updateState(LightspeedState state) {
|
||||
LightspeedState old;
|
||||
synchronized (stateMutex) {
|
||||
old = this.state;
|
||||
this.state = state;
|
||||
stateMutex.notifyAll();
|
||||
}
|
||||
if (old == LightspeedState.CONNECTED && state == LightspeedState.DISCONNECTED)
|
||||
callbackManager.callOnEach((callback) -> callback.onConnectionStateChanged(false));
|
||||
else if (old == LightspeedState.CONNECTING && state == LightspeedState.CONNECTED)
|
||||
callbackManager.callOnEach((callback) -> callback.onConnectionStateChanged(true));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +41,6 @@ public class SharedBuildData {
|
||||
private String buildString;
|
||||
private String testString;
|
||||
private double compileTime;
|
||||
private boolean offline;
|
||||
private boolean buildSuccess;
|
||||
private boolean testSuccess;
|
||||
private boolean cancelled;
|
||||
@@ -54,7 +53,6 @@ public class SharedBuildData {
|
||||
this.buildString = "";
|
||||
this.testString = "";
|
||||
this.compileTime = 0;
|
||||
this.offline = false;
|
||||
this.buildSuccess = false;
|
||||
this.testSuccess = false;
|
||||
this.cancelled = false;
|
||||
@@ -97,10 +95,6 @@ public class SharedBuildData {
|
||||
return compileTime;
|
||||
}
|
||||
|
||||
public boolean isOffline() {
|
||||
return offline;
|
||||
}
|
||||
|
||||
public boolean isBuildSuccess() {
|
||||
return buildSuccess;
|
||||
}
|
||||
@@ -137,10 +131,6 @@ public class SharedBuildData {
|
||||
this.compileTime = compileTime;
|
||||
}
|
||||
|
||||
public void setOffline(boolean offline) {
|
||||
this.offline = offline;
|
||||
}
|
||||
|
||||
public void setBuildSuccess(boolean buildSuccess) {
|
||||
this.buildSuccess = buildSuccess;
|
||||
}
|
||||
@@ -169,4 +159,8 @@ public class SharedBuildData {
|
||||
return ((SharedBuildData) o).getId() == id;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("SharedBuildData[id=%d, server=%s]", id, getServer().getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class SharedDeploymentData {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("DeploymentInformation[id=%d, server=%s, build=%d, start_time=%d, end_time=%d]", id, getServer().getName(), getBuild().getId(), startTime, endTime);
|
||||
return String.format("SharedDeploymentData[id=%d, build=%d, server=%s, start_time=%d, end_time=%d]", id, getBuild().getId(), getServer().getName(), startTime, endTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -205,4 +205,8 @@ public class SharedServerData {
|
||||
return ((SharedServerData) o).getName().equals(name);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("SharedServerData[name=%s, dir=%s, args=%s]", name, directory, jvmArgs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class LightspeedPrimaryView extends VBox implements Initializable {
|
||||
this.initialized = new AtomicBoolean(false);
|
||||
this.server = null;
|
||||
this.address = null;
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.TYPE, (i) -> update());
|
||||
IntentManager.getInstance().registerForIntent(ConnectionStateUpdateIntent.class, i -> update());
|
||||
FrontendFXMLLoader.load(this, "fxml/PrimaryView.fxml");
|
||||
}
|
||||
|
||||
|
||||
@@ -202,11 +202,7 @@ public class BuildTab extends GridPane implements Initializable {
|
||||
}
|
||||
|
||||
private void setMode() {
|
||||
if (selectedBuildData == null) {
|
||||
modeText.setText("N/A");
|
||||
} else {
|
||||
modeText.setText(selectedBuildData.isOffline() ? "Offline" : "Online");
|
||||
}
|
||||
modeText.setText("N/A");
|
||||
}
|
||||
|
||||
private void setTests() {
|
||||
|
||||
@@ -72,7 +72,7 @@ public class GeneralTab extends GridPane implements Initializable {
|
||||
selectedServerData = null;
|
||||
callback = null;
|
||||
FrontendFXMLLoader.load(this, "fxml/primary_tabs/General.fxml");
|
||||
IntentManager.getInstance().registerForIntent(ServerDataUpdateIntent.TYPE, (i) -> onIntent((ServerDataUpdateIntent) i));
|
||||
IntentManager.getInstance().registerForIntent(ServerDataUpdateIntent.class, i -> onIntent((ServerDataUpdateIntent) i));
|
||||
}
|
||||
|
||||
public void setFrontend(Frontend frontend) {
|
||||
|
||||
@@ -31,8 +31,6 @@ import com.projectswg.common.control.Intent;
|
||||
|
||||
public class BuildDataUpdateIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "BuildDataUpdateIntent";
|
||||
|
||||
private String serverName;
|
||||
private long buildId;
|
||||
private BuildUpdateType updateType;
|
||||
@@ -42,7 +40,6 @@ public class BuildDataUpdateIntent extends Intent {
|
||||
}
|
||||
|
||||
public BuildDataUpdateIntent(String serverName, long buildId, BuildUpdateType type) {
|
||||
super(TYPE);
|
||||
setServerName(serverName);
|
||||
setBuildId(buildId);
|
||||
setUpdateType(type);
|
||||
|
||||
@@ -31,8 +31,6 @@ import com.projectswg.common.control.Intent;
|
||||
|
||||
public class ConnectionStateUpdateIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "ConnectionStateUpdateIntent";
|
||||
|
||||
private boolean connected;
|
||||
|
||||
public ConnectionStateUpdateIntent() {
|
||||
@@ -40,7 +38,6 @@ public class ConnectionStateUpdateIntent extends Intent {
|
||||
}
|
||||
|
||||
public ConnectionStateUpdateIntent(boolean connected) {
|
||||
super(TYPE);
|
||||
setConnected(connected);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ import com.projectswg.common.control.Intent;
|
||||
|
||||
public class DeploymentDataUpdateIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "DeploymentDataUpdateIntent";
|
||||
|
||||
private String serverName;
|
||||
private long buildId;
|
||||
private long deploymentId;
|
||||
@@ -43,7 +41,6 @@ public class DeploymentDataUpdateIntent extends Intent {
|
||||
}
|
||||
|
||||
public DeploymentDataUpdateIntent(String serverName, long buildId, long deploymentId, DeploymentUpdateType type) {
|
||||
super(TYPE);
|
||||
setServerName(serverName);
|
||||
setBuildId(buildId);
|
||||
setDeploymentId(deploymentId);
|
||||
|
||||
@@ -31,8 +31,6 @@ import com.projectswg.common.control.Intent;
|
||||
|
||||
public class ServerDataUpdateIntent extends Intent {
|
||||
|
||||
public static final String TYPE = "ServerDataUpdateIntent";
|
||||
|
||||
private String name;
|
||||
private ServerUpdateType updateType;
|
||||
|
||||
@@ -41,7 +39,6 @@ public class ServerDataUpdateIntent extends Intent {
|
||||
}
|
||||
|
||||
public ServerDataUpdateIntent(String name, ServerUpdateType type) {
|
||||
super(TYPE);
|
||||
setName(name);
|
||||
setUpdateType(type);
|
||||
}
|
||||
|
||||
@@ -31,9 +31,7 @@ import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendLightspeedSession.LightspeedSessionCallback;
|
||||
|
||||
public class LinearTestFrontendCommunication {
|
||||
|
||||
@@ -45,10 +43,6 @@ public class LinearTestFrontendCommunication {
|
||||
public LinearTestFrontendCommunication() {
|
||||
communication = new FrontendCommunication();
|
||||
connected = new AtomicBoolean(false);
|
||||
communication.setCallback(new LightspeedSessionCallback() {
|
||||
public void onIncomingPacket(Packet p) { LinearTestFrontendCommunication.this.onIncomingPacket(p); }
|
||||
public void onConnectionStateChanged(boolean connected) { LinearTestFrontendCommunication.this.onConnectionStateChanged(connected); }
|
||||
});
|
||||
communication.start();
|
||||
}
|
||||
|
||||
@@ -80,12 +74,4 @@ public class LinearTestFrontendCommunication {
|
||||
return connected.get() == state;
|
||||
}
|
||||
|
||||
private void onIncomingPacket(Packet p) {
|
||||
|
||||
}
|
||||
|
||||
private void onConnectionStateChanged(boolean connected) {
|
||||
this.connected.set(connected);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.projectswg.common.network.packets.Packet;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
|
||||
import com.projectswg.lightspeed_frontend.communication.FrontendLightspeedSession.LightspeedSessionCallback;
|
||||
|
||||
public class TestConnect {
|
||||
|
||||
@@ -44,16 +42,6 @@ public class TestConnect {
|
||||
public void testConnect() throws InterruptedException {
|
||||
AtomicBoolean state = new AtomicBoolean(false);
|
||||
FrontendCommunication communication = new FrontendCommunication();
|
||||
communication.setCallback(new LightspeedSessionCallback() {
|
||||
@Override
|
||||
public void onIncomingPacket(Packet p) {
|
||||
|
||||
}
|
||||
@Override
|
||||
public void onConnectionStateChanged(boolean connected) {
|
||||
state.set(connected);
|
||||
}
|
||||
});
|
||||
communication.start();
|
||||
communication.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), 44444));
|
||||
int timeout = 1000;
|
||||
|
||||
Reference in New Issue
Block a user