mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-03-09 20:29:17 +07:00
Added MSI (master slave instancer) to create child D2GS processes
Added MSI (master slave instancer) to create child D2GS processes This is intended to act as a temp structure for testing until support for actual servers are added where an API can generate proper instances
This commit is contained in:
parent
115790f51a
commit
9f5d134eee
@ -2,6 +2,7 @@
|
||||
<configuration default="false" name="desktop (networking)" type="CompoundRunConfigurationType" factoryName="Compound Run Configuration">
|
||||
<toRun type="Application" name="BNLS" />
|
||||
<toRun type="Application" name="MCP" />
|
||||
<toRun type="Application" name="MSI" />
|
||||
<toRun type="Application" name="desktop (debug) (854x480)" />
|
||||
<method />
|
||||
</configuration>
|
||||
|
39
core/gen/com/riiablo/net/packet/msi/MSI.java
Normal file
39
core/gen/com/riiablo/net/packet/msi/MSI.java
Normal file
@ -0,0 +1,39 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package com.riiablo.net.packet.msi;
|
||||
|
||||
import java.nio.*;
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
import com.google.flatbuffers.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class MSI extends Table {
|
||||
public static MSI getRootAsMSI(ByteBuffer _bb) { return getRootAsMSI(_bb, new MSI()); }
|
||||
public static MSI getRootAsMSI(ByteBuffer _bb, MSI obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
|
||||
public MSI __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||
|
||||
public byte dataType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; }
|
||||
public Table data(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o) : null; }
|
||||
|
||||
public static int createMSI(FlatBufferBuilder builder,
|
||||
byte data_type,
|
||||
int dataOffset) {
|
||||
builder.startObject(2);
|
||||
MSI.addData(builder, dataOffset);
|
||||
MSI.addDataType(builder, data_type);
|
||||
return MSI.endMSI(builder);
|
||||
}
|
||||
|
||||
public static void startMSI(FlatBufferBuilder builder) { builder.startObject(2); }
|
||||
public static void addDataType(FlatBufferBuilder builder, byte dataType) { builder.addByte(0, dataType, 0); }
|
||||
public static void addData(FlatBufferBuilder builder, int dataOffset) { builder.addOffset(1, dataOffset, 0); }
|
||||
public static int endMSI(FlatBufferBuilder builder) {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
public static void finishMSIBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset); }
|
||||
public static void finishSizePrefixedMSIBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset); }
|
||||
}
|
||||
|
14
core/gen/com/riiablo/net/packet/msi/MSIData.java
Normal file
14
core/gen/com/riiablo/net/packet/msi/MSIData.java
Normal file
@ -0,0 +1,14 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package com.riiablo.net.packet.msi;
|
||||
|
||||
public final class MSIData {
|
||||
private MSIData() { }
|
||||
public static final byte NONE = 0;
|
||||
public static final byte StartInstance = 1;
|
||||
|
||||
public static final String[] names = { "NONE", "StartInstance", };
|
||||
|
||||
public static String name(int e) { return names[e]; }
|
||||
}
|
||||
|
14
core/gen/com/riiablo/net/packet/msi/Result.java
Normal file
14
core/gen/com/riiablo/net/packet/msi/Result.java
Normal file
@ -0,0 +1,14 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package com.riiablo.net.packet.msi;
|
||||
|
||||
public final class Result {
|
||||
private Result() { }
|
||||
public static final byte SUCCESS = 0;
|
||||
public static final byte FAILURE = 1;
|
||||
|
||||
public static final String[] names = { "SUCCESS", "FAILURE", };
|
||||
|
||||
public static String name(int e) { return names[e]; }
|
||||
}
|
||||
|
41
core/gen/com/riiablo/net/packet/msi/StartInstance.java
Normal file
41
core/gen/com/riiablo/net/packet/msi/StartInstance.java
Normal file
@ -0,0 +1,41 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package com.riiablo.net.packet.msi;
|
||||
|
||||
import java.nio.*;
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
import com.google.flatbuffers.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class StartInstance extends Table {
|
||||
public static StartInstance getRootAsStartInstance(ByteBuffer _bb) { return getRootAsStartInstance(_bb, new StartInstance()); }
|
||||
public static StartInstance getRootAsStartInstance(ByteBuffer _bb, StartInstance obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
|
||||
public StartInstance __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||
|
||||
public byte result() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; }
|
||||
public int ip() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
|
||||
public short port() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 0; }
|
||||
|
||||
public static int createStartInstance(FlatBufferBuilder builder,
|
||||
byte result,
|
||||
int ip,
|
||||
short port) {
|
||||
builder.startObject(3);
|
||||
StartInstance.addIp(builder, ip);
|
||||
StartInstance.addPort(builder, port);
|
||||
StartInstance.addResult(builder, result);
|
||||
return StartInstance.endStartInstance(builder);
|
||||
}
|
||||
|
||||
public static void startStartInstance(FlatBufferBuilder builder) { builder.startObject(3); }
|
||||
public static void addResult(FlatBufferBuilder builder, byte result) { builder.addByte(0, result, 0); }
|
||||
public static void addIp(FlatBufferBuilder builder, int ip) { builder.addInt(1, ip, 0); }
|
||||
public static void addPort(FlatBufferBuilder builder, short port) { builder.addShort(2, port, 0); }
|
||||
public static int endStartInstance(FlatBufferBuilder builder) {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.riiablo.net;
|
||||
|
||||
import com.riiablo.net.packet.mcp.CreateGame;
|
||||
import com.riiablo.net.packet.msi.StartInstance;
|
||||
|
||||
public class GameSession {
|
||||
public String name;
|
||||
@ -28,6 +29,12 @@ public class GameSession {
|
||||
desc = builder.desc;
|
||||
}
|
||||
|
||||
public GameSession setConnectInfo(StartInstance info) {
|
||||
ip = info.ip();
|
||||
port = info.port();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
13
core/src/com/riiablo/net/msi/MSI.fbs
Normal file
13
core/src/com/riiablo/net/msi/MSI.fbs
Normal file
@ -0,0 +1,13 @@
|
||||
include "StartInstance.fbs";
|
||||
|
||||
namespace com.riiablo.net.packet.msi;
|
||||
|
||||
union MSIData {
|
||||
StartInstance,
|
||||
}
|
||||
|
||||
table MSI {
|
||||
data:MSIData;
|
||||
}
|
||||
|
||||
root_type MSI;
|
15
core/src/com/riiablo/net/msi/StartInstance.fbs
Normal file
15
core/src/com/riiablo/net/msi/StartInstance.fbs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace com.riiablo.net.packet.msi;
|
||||
|
||||
enum Result : byte {
|
||||
SUCCESS = 0,
|
||||
FAILURE = 1,
|
||||
}
|
||||
|
||||
table StartInstance {
|
||||
// request
|
||||
|
||||
// response
|
||||
result:Result;
|
||||
ip:int32;
|
||||
port:int16;
|
||||
}
|
@ -23,6 +23,7 @@ task dist(type: Jar) {
|
||||
|
||||
manifest {
|
||||
attributes 'Server-Class': project.mainClassName
|
||||
attributes 'Main-Class': project.mainClassName
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,13 @@ import com.riiablo.net.packet.mcp.JoinGame;
|
||||
import com.riiablo.net.packet.mcp.ListGames;
|
||||
import com.riiablo.net.packet.mcp.MCPData;
|
||||
import com.riiablo.net.packet.mcp.Result;
|
||||
import com.riiablo.net.packet.msi.MSI;
|
||||
import com.riiablo.net.packet.msi.MSIData;
|
||||
import com.riiablo.net.packet.msi.StartInstance;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
@ -245,20 +249,38 @@ public class MCP extends ApplicationAdapter {
|
||||
}
|
||||
|
||||
private boolean CreateGame(Socket socket, com.riiablo.net.packet.mcp.MCP packet) throws IOException {
|
||||
CreateGame createGame = (CreateGame) packet.data(new CreateGame());
|
||||
String gameName = createGame.gameName();
|
||||
final CreateGame createGame = (CreateGame) packet.data(new CreateGame());
|
||||
final String gameName = createGame.gameName();
|
||||
Gdx.app.debug(TAG, "Attempting to create " + gameName + " for " + socket.getRemoteAddress());
|
||||
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
final FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
CreateGame.startCreateGame(builder);
|
||||
if (sessions.containsKey(gameName)) {
|
||||
CreateGame.addResult(builder, Result.ALREADY_EXISTS);
|
||||
} else if (sessions.size() >= 4) {
|
||||
CreateGame.addResult(builder, Result.SERVER_DOWN);
|
||||
} else {
|
||||
CreateGame.addResult(builder, Result.SUCCESS);
|
||||
sessions.put(gameName, new GameSession(createGame));
|
||||
Gdx.app.debug(TAG, "Created session " + gameName);
|
||||
final GameSession session = new GameSession(createGame);
|
||||
StartInstance(createGame, new ResponseListener() {
|
||||
@Override
|
||||
public void handleResponse(MSI msi) {
|
||||
StartInstance startInstance = (StartInstance) msi.data(new StartInstance());
|
||||
switch (startInstance.result()) {
|
||||
case Result.SUCCESS:
|
||||
sessions.put(gameName, session.setConnectInfo(startInstance));
|
||||
CreateGame.addResult(builder, Result.SUCCESS);
|
||||
Gdx.app.debug(TAG, "Created session " + gameName);
|
||||
break;
|
||||
default:
|
||||
CreateGame.addResult(builder, Result.SERVER_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable t) {
|
||||
Gdx.app.error(TAG, t.getMessage(), t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int createGameOffset = CreateGame.endCreateGame(builder);
|
||||
@ -304,6 +326,46 @@ public class MCP extends ApplicationAdapter {
|
||||
return false;
|
||||
}
|
||||
|
||||
interface ResponseListener {
|
||||
void handleResponse(MSI msi);
|
||||
void failed(Throwable t);
|
||||
}
|
||||
|
||||
private void StartInstance(CreateGame createGame, ResponseListener listener) {
|
||||
Gdx.app.debug(TAG, "Requesting game instance for " + createGame);
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
StartInstance.startStartInstance(builder);
|
||||
int startInstanceOffset = StartInstance.endStartInstance(builder);
|
||||
int id = MSI.createMSI(builder, MSIData.StartInstance, startInstanceOffset);
|
||||
builder.finish(id);
|
||||
ByteBuffer data = builder.dataBuffer();
|
||||
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = Gdx.net.newClientSocket(Net.Protocol.TCP, "localhost", com.riiablo.server.mcp.MSI.PORT, null);
|
||||
|
||||
OutputStream out = socket.getOutputStream();
|
||||
WritableByteChannel channelOut = Channels.newChannel(out);
|
||||
channelOut.write(data);
|
||||
|
||||
buffer.clear();
|
||||
buffer.mark();
|
||||
InputStream in = socket.getInputStream();
|
||||
ReadableByteChannel channelIn = Channels.newChannel(in);
|
||||
channelIn.read(buffer);
|
||||
buffer.limit(buffer.position());
|
||||
buffer.reset();
|
||||
|
||||
MSI packet = MSI.getRootAsMSI(buffer);
|
||||
Gdx.app.log(TAG, "packet type " + MCPData.name(packet.dataType()));
|
||||
listener.handleResponse(packet);
|
||||
} catch (Throwable t) {
|
||||
listener.failed(t);
|
||||
} finally {
|
||||
if (socket != null) socket.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static String generateClientName() {
|
||||
return String.format("Client-%08X", MathUtils.random(1, Integer.MAX_VALUE - 1));
|
||||
}
|
||||
|
143
server/mcp/src/com/riiablo/server/mcp/MSI.java
Normal file
143
server/mcp/src/com/riiablo/server/mcp/MSI.java
Normal file
@ -0,0 +1,143 @@
|
||||
package com.riiablo.server.mcp;
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
|
||||
import com.badlogic.gdx.Application;
|
||||
import com.badlogic.gdx.ApplicationAdapter;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Net;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
||||
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
||||
import com.badlogic.gdx.net.ServerSocket;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.BufferUtils;
|
||||
import com.riiablo.net.packet.msi.MSIData;
|
||||
import com.riiablo.net.packet.msi.Result;
|
||||
import com.riiablo.net.packet.msi.StartInstance;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class MSI extends ApplicationAdapter {
|
||||
private static final String TAG = "MSI";
|
||||
|
||||
static final int PORT = 6112;
|
||||
|
||||
public static void main(String[] args) {
|
||||
HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
|
||||
new HeadlessApplication(new MSI(), config);
|
||||
}
|
||||
|
||||
ServerSocket server;
|
||||
ByteBuffer buffer;
|
||||
final Array<Process> instances = new Array<>();
|
||||
|
||||
MSI() {}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
Gdx.app.setLogLevel(Application.LOG_DEBUG);
|
||||
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
DateFormat format = DateFormat.getDateTimeInstance();
|
||||
Gdx.app.log(TAG, format.format(calendar.getTime()));
|
||||
|
||||
try {
|
||||
InetAddress address = InetAddress.getLocalHost();
|
||||
Gdx.app.log(TAG, "IP Address: " + address.getHostAddress() + ":" + PORT);
|
||||
Gdx.app.log(TAG, "Host Name: " + address.getHostName());
|
||||
} catch (UnknownHostException e) {
|
||||
Gdx.app.error(TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
Gdx.app.log(TAG, "Starting server...");
|
||||
server = Gdx.net.newServerSocket(Net.Protocol.TCP, PORT, null);
|
||||
buffer = BufferUtils.newByteBuffer(4096);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
Socket socket = null;
|
||||
try {
|
||||
Gdx.app.log(TAG, "waiting...");
|
||||
socket = server.accept(null);
|
||||
Gdx.app.log(TAG, "connection from " + socket.getRemoteAddress());
|
||||
|
||||
buffer.clear();
|
||||
buffer.mark();
|
||||
ReadableByteChannel in = Channels.newChannel(socket.getInputStream());
|
||||
in.read(buffer);
|
||||
buffer.limit(buffer.position());
|
||||
buffer.reset();
|
||||
|
||||
com.riiablo.net.packet.msi.MSI packet = com.riiablo.net.packet.msi.MSI.getRootAsMSI(buffer);
|
||||
Gdx.app.log(TAG, "packet type " + MSIData.name(packet.dataType()));
|
||||
process(socket, packet);
|
||||
} catch (Throwable t) {
|
||||
if (socket != null) socket.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void process(Socket socket, com.riiablo.net.packet.msi.MSI packet) throws IOException {
|
||||
switch (packet.dataType()) {
|
||||
case MSIData.StartInstance:
|
||||
StartInstance(socket, packet);
|
||||
break;
|
||||
default:
|
||||
Gdx.app.error(TAG, "Unknown packet type: " + packet.dataType());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean StartInstance(Socket socket, com.riiablo.net.packet.msi.MSI packet) throws IOException {
|
||||
Gdx.app.debug(TAG, "Starting instance...");
|
||||
|
||||
try {
|
||||
File outFile = new File("D2GS.tmp");
|
||||
ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", "server/d2gs/build/libs/d2gs-1.0.jar");
|
||||
processBuilder.redirectOutput(ProcessBuilder.Redirect.to(outFile));
|
||||
processBuilder.redirectError(ProcessBuilder.Redirect.to(outFile));
|
||||
Process process = processBuilder.start();
|
||||
instances.add(process);
|
||||
} catch (Throwable t) {
|
||||
Gdx.app.error(TAG, t.getMessage(), t);
|
||||
}
|
||||
|
||||
int ip = 2130706433; // 127.0.0.1
|
||||
short port = 6114;
|
||||
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
StartInstance.startStartInstance(builder);
|
||||
StartInstance.addResult(builder, Result.SUCCESS);
|
||||
StartInstance.addIp(builder, ip);
|
||||
StartInstance.addPort(builder, port);
|
||||
int startInstanceOffset = StartInstance.endStartInstance(builder);
|
||||
int id = com.riiablo.net.packet.msi.MSI.createMSI(builder, MSIData.StartInstance, startInstanceOffset);
|
||||
builder.finish(id);
|
||||
|
||||
ByteBuffer data = builder.dataBuffer();
|
||||
OutputStream out = socket.getOutputStream();
|
||||
WritableByteChannel channel = Channels.newChannel(out);
|
||||
channel.write(data);
|
||||
Gdx.app.debug(TAG, "Returning instance at " + InetAddress.getByAddress(ByteBuffer.allocate(4).putInt(ip).array()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Gdx.app.log(TAG, "Shutting down...");
|
||||
server.dispose();
|
||||
for (Process process : instances) {
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user