Standardized naming and updated to Java 11

This commit is contained in:
Josh Larson
2018-12-25 10:57:00 -06:00
parent 668025fac8
commit b104f07fd7
15 changed files with 245 additions and 131 deletions

View File

@@ -1,9 +1,10 @@
plugins {
id 'java'
id "org.javamodularity.moduleplugin"
}
sourceCompatibility = 9
targetCompatibility = 9
sourceCompatibility = 11
targetCompatibility = 11
repositories {
jcenter()

View File

@@ -139,10 +139,12 @@ public class Forwarder {
public static class ForwarderData {
private InetSocketAddress address = null;
private boolean verifyServer = true;
private String username = null;
private String password = null;
private int loginPort = 0;
private int zonePort = 0;
private int pingPort = 0;
private int outboundTunerMaxSend = 100;
private int outboundTunerInterval = 20;
@@ -152,6 +154,10 @@ public class Forwarder {
return address;
}
public boolean isVerifyServer() {
return verifyServer;
}
public String getUsername() {
return username;
}
@@ -168,6 +174,10 @@ public class Forwarder {
return zonePort;
}
public int getPingPort() {
return pingPort;
}
public int getOutboundTunerMaxSend() {
return outboundTunerMaxSend;
}
@@ -180,6 +190,10 @@ public class Forwarder {
this.address = address;
}
public void setVerifyServer(boolean verifyServer) {
this.verifyServer = verifyServer;
}
public void setUsername(String username) {
this.username = username;
}
@@ -196,6 +210,10 @@ public class Forwarder {
this.zonePort = zonePort;
}
public void setPingPort(int pingPort) {
this.pingPort = pingPort;
}
public void setOutboundTunerMaxSend(int outboundTunerMaxSend) {
this.outboundTunerMaxSend = outboundTunerMaxSend;
}

View File

@@ -0,0 +1,17 @@
package com.projectswg.forwarder.intents.client;
import me.joshlarson.jlcommon.control.Intent;
public class SendPongIntent extends Intent {
private final byte [] data;
public SendPongIntent(byte [] data) {
this.data = data;
}
public byte [] getData() {
return data;
}
}

View File

@@ -2,5 +2,6 @@ package com.projectswg.forwarder.resources.networking;
public enum ClientServer {
LOGIN,
ZONE
ZONE,
PING
}

View File

@@ -58,7 +58,7 @@ public class NetInterceptor {
for (Galaxy g : cluster.getGalaxies()) {
g.setAddress("127.0.0.1");
g.setZonePort(this.data.getZonePort());
g.setPingPort(this.data.getZonePort());
g.setPingPort(this.data.getPingPort());
}
return cluster.encode().array();
}

View File

@@ -7,16 +7,17 @@ import com.projectswg.forwarder.resources.networking.packets.Fragmented;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class Packager {
private final AtomicInteger size;
private final List<byte[]> dataChannel;
private final Queue<byte[]> outboundRaw;
private final BlockingQueue<byte[]> outboundRaw;
private final ConnectionStream<SequencedOutbound> outboundPackaged;
public Packager(Queue<byte[]> outboundRaw, ConnectionStream<SequencedOutbound> outboundPackaged, ProtocolStack stack) {
public Packager(BlockingQueue<byte[]> outboundRaw, ConnectionStream<SequencedOutbound> outboundPackaged, ProtocolStack stack) {
this.size = new AtomicInteger(8);
this.dataChannel = new ArrayList<>();
this.outboundRaw = outboundRaw;
@@ -27,16 +28,17 @@ public class Packager {
byte [] packet;
int packetSize;
while (!outboundRaw.isEmpty() && outboundPackaged.size() < maxPackaged) {
while (outboundPackaged.size() < maxPackaged) {
packet = outboundRaw.poll();
if (packet == null)
break;
packetSize = getPacketLength(packet);
if (size.get() + packetSize >= 496) // overflowed previous packet
if (size.get() + packetSize >= 16384) // max data channel size
sendDataChannel();
if (packetSize < 496) {
if (packetSize < 16384) { // if overflowed, must go into fragmented
addToDataChannel(packet, packetSize);
} else {
sendFragmented(packet);

View File

@@ -9,6 +9,9 @@ import org.jetbrains.annotations.NotNull;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.BiConsumer;
public class ProtocolStack {
@@ -17,7 +20,7 @@ public class ProtocolStack {
private final InetSocketAddress source;
private final BiConsumer<InetSocketAddress, byte[]> sender;
private final ClientServer server;
private final Queue<byte []> outboundRaw;
private final BlockingQueue<byte []> outboundRaw;
private final ConnectionStream<SequencedPacket> inbound;
private final ConnectionStream<SequencedOutbound> outbound;
private final Packager packager;
@@ -30,7 +33,7 @@ public class ProtocolStack {
this.source = source;
this.sender = sender;
this.server = server;
this.outboundRaw = new LinkedList<>();
this.outboundRaw = new LinkedBlockingQueue<>();
this.inbound = new ConnectionStream<>();
this.outbound = new ConnectionStream<>();
this.packager = new Packager(outboundRaw, outbound, this);
@@ -94,7 +97,11 @@ public class ProtocolStack {
}
public void addOutbound(@NotNull byte [] data) {
outboundRaw.offer(data);
try {
outboundRaw.put(data);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public short getFirstUnacknowledgedOutbound() {
@@ -108,11 +115,11 @@ public class ProtocolStack {
outbound.removeOrdered(sequence);
}
public void fillOutboundPackagedBuffer(int maxPackaged) {
public synchronized void fillOutboundPackagedBuffer(int maxPackaged) {
packager.handle(maxPackaged);
}
public int fillOutboundBuffer(SequencedOutbound [] buffer) {
public synchronized int fillOutboundBuffer(SequencedOutbound [] buffer) {
return outbound.fillBuffer(buffer);
}
@@ -126,31 +133,30 @@ public class ProtocolStack {
private final PriorityQueue<T> sequenced;
private final PriorityQueue<T> queued;
private short sequence;
private long sequence;
public ConnectionStream() {
this.sequenced = new PriorityQueue<>();
this.queued = new PriorityQueue<>();
this.sequence = 0;
}
public short getSequence() {
return sequence;
return (short) sequence;
}
public synchronized SequencedStatus addUnordered(@NotNull T packet) {
if (SequencedPacket.compare(sequence, packet.getSequence()) > 0) {
if (SequencedPacket.compare(getSequence(), packet.getSequence()) > 0) {
T peek = peek();
return peek != null && peek.getSequence() == sequence ? SequencedStatus.READY : SequencedStatus.STALE;
return peek != null && peek.getSequence() == getSequence() ? SequencedStatus.READY : SequencedStatus.STALE;
}
if (packet.getSequence() == sequence) {
if (packet.getSequence() == getSequence()) {
sequenced.add(packet);
sequence++;
// Add queued OOO packets
T queue;
while ((queue = queued.peek()) != null && queue.getSequence() == sequence) {
while ((queue = queued.peek()) != null && queue.getSequence() == getSequence()) {
sequenced.add(queued.poll());
sequence++;
}
@@ -164,7 +170,7 @@ public class ProtocolStack {
}
public synchronized void addOrdered(@NotNull T packet) {
packet.setSequence(sequence);
packet.setSequence(getSequence());
addUnordered(packet);
}

View File

@@ -66,6 +66,11 @@ public class DataChannel extends Packet implements SequencedPacket {
content.addAll(Arrays.asList(packets));
}
public DataChannel(byte [] packet) {
this();
content.add(packet);
}
@Override
public void decode(ByteBuffer data) {
super.decode(data);
@@ -103,29 +108,18 @@ public class DataChannel extends Packet implements SequencedPacket {
@Override
public ByteBuffer encode() {
NetBuffer data;
if (content.size() == 1) {
byte[] pData = content.get(0);
data = NetBuffer.allocate(4 + pData.length);
data.addNetShort(channel.getOpcode());
data.addNetShort(sequence);
data.addRawArray(pData);
} else if (content.size() > 1) {
data = NetBuffer.allocate(getLength());
data.addNetShort(channel.getOpcode());
data.addNetShort(sequence);
data.addNetShort(0x19);
for (byte[] pData : content) {
if (pData.length >= 0xFF) {
data.addByte(0xFF);
data.addNetShort(pData.length);
} else {
data.addByte(pData.length);
}
data.addRawArray(pData);
NetBuffer data = NetBuffer.allocate(getLength());
data.addNetShort(channel.getOpcode());
data.addNetShort(sequence);
data.addNetShort(0x19);
for (byte[] pData : content) {
if (pData.length >= 0xFF) {
data.addByte(0xFF);
data.addNetShort(pData.length);
} else {
data.addByte(pData.length);
}
} else {
data = NetBuffer.allocate(0);
data.addRawArray(pData);
}
return data.getBuffer();
}
@@ -139,16 +133,12 @@ public class DataChannel extends Packet implements SequencedPacket {
}
public int getLength() {
if (content.size() == 1) {
return 4 + content.get(0).length;
} else {
int length = 6;
for (byte[] packet : content) {
int addLength = packet.length;
length += 1 + addLength + ((addLength >= 0xFF) ? 2 : 0);
}
return length;
int length = 6;
for (byte[] packet : content) {
int addLength = packet.length;
length += 1 + addLength + ((addLength >= 0xFF) ? 2 : 0);
}
return length;
}
@Override

View File

@@ -106,11 +106,11 @@ public class Fragmented extends Packet implements SequencedPacket {
public static byte [][] split(byte [] data) {
int offset = 0;
int packetCount = (int) Math.ceil((data.length+4)/489.0);
int packetCount = (int) Math.ceil((data.length+4)/16377.0); // 489
byte [][] packets = new byte[packetCount][];
for (int i = 0; i < packetCount; i++) {
int header = (i == 0) ? 4 : 0;
ByteBuffer segment = ByteBuffer.allocate(Math.min(data.length-offset-header, 489)).order(ByteOrder.BIG_ENDIAN);
ByteBuffer segment = ByteBuffer.allocate(Math.min(data.length-offset-header, 16377)).order(ByteOrder.BIG_ENDIAN);
if (i == 0)
segment.putInt(data.length);
int segmentLength = segment.remaining();

View File

@@ -1,5 +1,7 @@
package com.projectswg.forwarder.resources.networking.packets;
import com.projectswg.common.utilities.ByteUtilities;
import java.nio.ByteBuffer;
public class PingPacket extends Packet {
@@ -24,4 +26,9 @@ public class PingPacket extends Packet {
return payload;
}
@Override
public String toString() {
return "PingPacket[payload=" + ByteUtilities.getHexString(payload) + "]";
}
}

View File

@@ -3,14 +3,15 @@ package com.projectswg.forwarder.resources.recording;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.TreeMap;
public class PacketRecorder implements AutoCloseable, Closeable {
private static final byte VERSION = 2;
private static final byte VERSION = 3;
private final DataOutputStream dataOut;
@@ -26,7 +27,7 @@ public class PacketRecorder implements AutoCloseable, Closeable {
public void record(boolean server, byte [] data) {
synchronized (dataOut) {
try {
dataOut.writeByte(server?1:0);
dataOut.writeBoolean(server);
dataOut.writeLong(System.currentTimeMillis());
dataOut.writeShort(data.length);
dataOut.write(data);
@@ -47,15 +48,14 @@ public class PacketRecorder implements AutoCloseable, Closeable {
private void writeSystemHeader() {
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
TimeZone tz = TimeZone.getDefault();
Map<String, String> systemStrings = new TreeMap<>();
systemStrings.put("os.arch", os.getArch());
systemStrings.put("os.details", os.getName()+":"+os.getVersion());
systemStrings.put("os.processor_count", Integer.toString(os.getAvailableProcessors()));
systemStrings.put("java.version", System.getProperty("java.version"));
systemStrings.put("java.vendor", System.getProperty("java.vendor"));
systemStrings.put("time.time_zone", tz.getID()+":"+tz.getDisplayName());
systemStrings.put("time.current_time", Long.toString(System.currentTimeMillis()));
systemStrings.put("time.time_zone", ZoneId.systemDefault().getId());
systemStrings.put("time.current_time", Instant.now().toString());
try {
dataOut.writeByte(systemStrings.size()); // Count of strings
for (Entry<String, String> e : systemStrings.entrySet())

View File

@@ -3,7 +3,6 @@ package com.projectswg.forwarder.services.client;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.common.network.packets.swg.zone.HeartBeat;
import com.projectswg.forwarder.Forwarder.ForwarderData;
import com.projectswg.forwarder.intents.client.*;
import com.projectswg.forwarder.intents.control.StartForwarderIntent;
import com.projectswg.forwarder.resources.networking.ClientServer;
@@ -12,9 +11,9 @@ import com.projectswg.forwarder.resources.networking.data.SequencedOutbound;
import com.projectswg.forwarder.resources.networking.packets.Acknowledge;
import com.projectswg.forwarder.resources.networking.packets.OutOfOrder;
import com.projectswg.forwarder.resources.networking.packets.Packet;
import me.joshlarson.jlcommon.concurrency.BasicScheduledThread;
import me.joshlarson.jlcommon.concurrency.BasicThread;
import me.joshlarson.jlcommon.concurrency.Delay;
import me.joshlarson.jlcommon.concurrency.SmartLock;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.IntentMultiplexer;
import me.joshlarson.jlcommon.control.IntentMultiplexer.Multiplexer;
@@ -25,34 +24,34 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class ClientOutboundDataService extends Service {
private final SequencedOutbound [] outboundBuffer;
private final IntentMultiplexer multiplexer;
private final Set<ProtocolStack> activeStacks;
private final BasicThread sendThread;
private final SmartLock signaller;
private ForwarderData data;
private final BasicScheduledThread heartbeatThread;
public ClientOutboundDataService() {
this.outboundBuffer = new SequencedOutbound[4096];
this.multiplexer = new IntentMultiplexer(this, ProtocolStack.class, Packet.class);
this.activeStacks = ConcurrentHashMap.newKeySet();
this.sendThread = new BasicThread("outbound-sender", this::persistentSend);
this.signaller = new SmartLock();
this.data = null;
this.heartbeatThread = new BasicScheduledThread("heartbeat", this::heartbeat);
}
@Override
public boolean terminate() {
sendThread.stop(true);
return sendThread.awaitTermination(1000);
if (sendThread.isExecuting())
sendThread.stop(true);
if (heartbeatThread.isRunning())
heartbeatThread.stop();
return sendThread.awaitTermination(1000) && heartbeatThread.awaitTermination(1000);
}
@IntentHandler
private void handleStartForwarderIntent(StartForwarderIntent sfi) {
data = sfi.getData();
}
@IntentHandler
@@ -65,6 +64,7 @@ public class ClientOutboundDataService extends Service {
if (sendThread.isExecuting())
return;
sendThread.start();
heartbeatThread.startWithFixedRate(0, 500);
}
@IntentHandler
@@ -72,7 +72,9 @@ public class ClientOutboundDataService extends Service {
if (!sendThread.isExecuting())
return;
sendThread.stop(true);
heartbeatThread.stop();
sendThread.awaitTermination(1000);
heartbeatThread.awaitTermination(1000);
}
@IntentHandler
@@ -110,8 +112,7 @@ public class ClientOutboundDataService extends Service {
HeartBeat heartbeat = new HeartBeat();
heartbeat.decode(NetBuffer.wrap(dpoi.getData()));
if (heartbeat.getPayload().length > 0) {
for (ProtocolStack stack : activeStacks)
stack.sendPing(heartbeat.getPayload());
new SendPongIntent(heartbeat.getPayload()).broadcast(getIntentManager());
return;
}
break;
@@ -121,14 +122,14 @@ public class ClientOutboundDataService extends Service {
final ClientServer finalFilterServer = filterServer;
ProtocolStack stack = activeStacks.stream().filter(s -> s.getServer() == finalFilterServer).findFirst().orElse(null);
if (stack == null) {
Log.d("Data/Oubound Sending %s [len=%d] to %s", type, dpoi.getData().length, activeStacks);
for (ProtocolStack active : activeStacks)
Log.d("Data/Outbound Sending %s [len=%d] to %s", type, dpoi.getData().length, activeStacks);
for (ProtocolStack active : activeStacks) {
active.addOutbound(dpoi.getData());
}
} else {
Log.d("Data/Outbound Sending %s [len=%d] to %s", type, dpoi.getData().length, stack);
stack.addOutbound(dpoi.getData());
}
signaller.signal();
}
@Multiplexer
@@ -143,47 +144,41 @@ public class ClientOutboundDataService extends Service {
}
private void persistentSend() {
int maxSend = data.getOutboundTunerMaxSend();
if (maxSend <= 0)
maxSend = 400;
int interval = data.getOutboundTunerInterval();
if (interval <= 0)
interval = 1000;
int bucket = 0;
int [] sendCounts = new int[interval / 20];
SequencedOutbound [] buffer = new SequencedOutbound[maxSend];
Log.d("Data/Outbound Starting Persistent Send");
int iteration = 0;
while (!Delay.isInterrupted()) {
sendCounts[bucket] = 0;
int previousInterval = 0;
for (int count : sendCounts)
previousInterval += count;
if (previousInterval < maxSend) {
for (ProtocolStack stack : activeStacks) {
stack.fillOutboundPackagedBuffer(maxSend);
int count = stack.fillOutboundBuffer(buffer);
for (int i = 0; i < count && Delay.sleepMicro(50); i++) {
stack.send(buffer[i].getData());
}
if (count > 0)
Log.t("Data/Outbound Sent %d Start: %d", count, buffer[0].getSequence());
sendCounts[bucket] += count;
}
try {
signaller.await(20, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
break;
}
} else {
Delay.sleepMilli(20);
}
bucket = (bucket + 1) % sendCounts.length;
flushPackaged(iteration % 20 == 0);
iteration++;
Delay.sleepMilli(50);
}
Log.d("Data/Outbound Stopping Persistent Send");
}
private void heartbeat() {
for (ProtocolStack stack : activeStacks) {
stack.send(new HeartBeat().encode().array());
}
}
private void flushPackaged(boolean overrideSent) {
for (ProtocolStack stack : activeStacks) {
stack.fillOutboundPackagedBuffer(outboundBuffer.length);
int count = stack.fillOutboundBuffer(outboundBuffer);
int sent = 0;
for (int i = 0; i < count; i++) {
SequencedOutbound out = outboundBuffer[i];
if (overrideSent || !out.isSent()) {
stack.send(out.getData());
out.setSent(true);
sent++;
}
}
if (sent > 0)
Log.t("Data/Outbound Sent %d - %d [%d]", outboundBuffer[0].getSequence(), outboundBuffer[count-1].getSequence(), count);
else if (count > 0)
Log.t("Data/Outbound Waiting to send %d - %d [count=%d]", outboundBuffer[0].getSequence(), outboundBuffer[count-1].getSequence(), count);
}
}
}

View File

@@ -19,6 +19,7 @@ import me.joshlarson.jlcommon.network.UDPServer;
import me.joshlarson.jlcommon.utilities.ByteUtilities;
import java.net.*;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.Map;
@@ -31,24 +32,34 @@ public class ClientServerService extends Service {
private final Map<ClientServer, ProtocolStack> stacks;
private final AtomicBoolean serverConnection;
private final AtomicReference<SessionRequest> cachedSessionRequest;
private final AtomicReference<InetSocketAddress> lastPing;
private ForwarderData data;
private UDPServer loginServer;
private UDPServer zoneServer;
private UDPServer pingServer;
public ClientServerService() {
this.intentChain = new IntentChain();
this.stacks = new EnumMap<>(ClientServer.class);
this.serverConnection = new AtomicBoolean(false);
this.cachedSessionRequest = new AtomicReference<>(null);
this.lastPing = new AtomicReference<>(null);
this.data = null;
this.loginServer = null;
this.zoneServer = null;
this.pingServer = null;
}
@Override
public boolean isOperational() {
return data == null || (loginServer != null && zoneServer != null && loginServer.isRunning() && zoneServer.isRunning());
if (data == null)
return true;
if (loginServer == null || !loginServer.isRunning())
return false;
if (zoneServer == null || !zoneServer.isRunning())
return false;
return pingServer != null && pingServer.isRunning();
}
@Override
@@ -66,24 +77,32 @@ public class ClientServerService extends Service {
loginServer = new UDPServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), data.getLoginPort()), 496, this::onLoginPacket);
Log.t("Initializing zone udp server...");
zoneServer = new UDPServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), data.getZonePort()), 496, this::onZonePacket);
Log.t("Initializing ping udp server...");
pingServer = new UDPServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), data.getPingPort()), 496, this::onPingPacket);
Log.t("Binding to login server...");
loginServer.bind(this::customizeUdpServer);
Log.t("Binding to zone server...");
zoneServer.bind(this::customizeUdpServer);
Log.t("Binding to ping server...");
pingServer.bind(this::customizeUdpServer);
data.setLoginPort(loginServer.getPort());
data.setZonePort(zoneServer.getPort());
data.setPingPort(pingServer.getPort());
Log.i("Initialized login (%d) and zone servers (%d)", loginServer.getPort(), zoneServer.getPort());
Log.i("Initialized login (%d), zone (%d), and ping (%d) servers", loginServer.getPort(), zoneServer.getPort(), pingServer.getPort());
} catch (SocketException e) {
Log.a(e);
if (loginServer != null)
loginServer.close();
if (zoneServer != null)
zoneServer.close();
if (pingServer != null)
pingServer.close();
loginServer = null;
zoneServer = null;
pingServer = null;
}
data = sfi.getData();
}
@@ -96,9 +115,13 @@ public class ClientServerService extends Service {
Log.t("Closing the zone udp server...");
if (zoneServer != null)
zoneServer.close();
Log.t("Closing the ping udp server...");
if (pingServer != null)
pingServer.close();
loginServer = null;
zoneServer = null;
Log.i("Closed the login and zone udp servers");
pingServer = null;
Log.i("Closed the login, zone, and ping udp servers");
}
@IntentHandler
@@ -116,6 +139,14 @@ public class ClientServerService extends Service {
serverConnection.set(false);
closeConnection(ClientServer.LOGIN);
closeConnection(ClientServer.ZONE);
closeConnection(ClientServer.PING);
}
@IntentHandler
private void handleSendPongIntent(SendPongIntent spi) {
InetSocketAddress lastPing = this.lastPing.get();
if (lastPing != null)
send(lastPing, ClientServer.PING, spi.getData());
}
private void customizeUdpServer(DatagramSocket socket) {
@@ -138,6 +169,18 @@ public class ClientServerService extends Service {
process((InetSocketAddress) packet.getSocketAddress(), ClientServer.ZONE, packet.getData());
}
private void onPingPacket(DatagramPacket packet) {
InetSocketAddress source = (InetSocketAddress) packet.getSocketAddress();
lastPing.set(source);
ProtocolStack stack = stacks.get(ClientServer.ZONE);
PingPacket pingPacket = new PingPacket(packet.getData());
pingPacket.setAddress(source.getAddress());
pingPacket.setPort(source.getPort());
if (stack != null)
intentChain.broadcastAfter(getIntentManager(), new SonyPacketInboundIntent(stack, pingPacket));
}
private void send(InetSocketAddress addr, ClientServer server, byte [] data) {
switch (server) {
case LOGIN:
@@ -146,13 +189,22 @@ public class ClientServerService extends Service {
case ZONE:
zoneServer.send(addr, data);
break;
case PING:
pingServer.send(addr, data);
break;
}
}
private void process(InetSocketAddress source, ClientServer server, byte [] data) {
Packet parsed = parse(data);
if (parsed == null)
Packet parsed;
try {
parsed = (server == ClientServer.PING) ? new PingPacket(data) : parse(data);
if (parsed == null)
return;
} catch (BufferUnderflowException e) {
Log.w("Failed to parse packet: %s", ByteUtilities.getHexString(data));
return;
}
parsed.setAddress(source.getAddress());
parsed.setPort(source.getPort());
if (parsed instanceof MultiPacket) {
@@ -175,11 +227,14 @@ public class ClientServerService extends Service {
}
private ProtocolStack process(InetSocketAddress source, ClientServer server, Packet parsed) {
Log.t("Process [%b] %s", serverConnection.get(), parsed);
if (!serverConnection.get()) {
if (parsed instanceof SessionRequest) {
cachedSessionRequest.set((SessionRequest) parsed);
intentChain.broadcastAfter(getIntentManager(), new RequestServerConnectionIntent());
}
for (ClientServer serverType : ClientServer.values())
closeConnection(serverType);
return null;
}
if (parsed instanceof SessionRequest)
@@ -275,8 +330,6 @@ public class ClientServerService extends Service {
case 0x17:
case 0x18: return new Acknowledge(data);
default:
if (rawData.length == 4)
return new PingPacket(rawData);
if (rawData.length >= 6)
return new RawSWGPacket(rawData);
Log.w("Unknown SOE packet: %d %s", opcode, ByteUtilities.getHexString(data.array()));

View File

@@ -1,7 +1,7 @@
package com.projectswg.forwarder.services.server;
import com.projectswg.connection.HolocoreSocket;
import com.projectswg.connection.RawPacket;
import com.projectswg.holocore.client.HolocoreSocket;
import com.projectswg.holocore.client.RawPacket;
import com.projectswg.forwarder.Forwarder.ForwarderData;
import com.projectswg.forwarder.intents.client.ClientDisconnectedIntent;
import com.projectswg.forwarder.intents.client.DataPacketInboundIntent;
@@ -55,9 +55,12 @@ public class ServerConnectionService extends Service {
@IntentHandler
private void handleRequestServerConnectionIntent(RequestServerConnectionIntent rsci) {
if (thread.isExecuting())
stopRunningLoop();
thread.start();
HolocoreSocket holocore = this.holocore;
if (holocore != null)
return; // It's trying to connect - give it a little more time
if (stopRunningLoop())
thread.start();
}
@IntentHandler
@@ -73,12 +76,15 @@ public class ServerConnectionService extends Service {
}
private boolean stopRunningLoop() {
if (!thread.isExecuting())
return true;
thread.stop(true);
return thread.awaitTermination(1000);
}
private void primaryConnectionLoop() {
try (HolocoreSocket holocore = new HolocoreSocket(data.getAddress().getAddress(), data.getAddress().getPort())) {
boolean didConnect = false;
try (HolocoreSocket holocore = new HolocoreSocket(data.getAddress().getAddress(), data.getAddress().getPort(), data.isVerifyServer())) {
this.holocore = holocore;
Log.t("Attempting to connect to server at %s", holocore.getRemoteAddress());
if (!holocore.connect(CONNECT_TIMEOUT)) {
@@ -87,11 +93,15 @@ public class ServerConnectionService extends Service {
}
Log.i("Successfully connected to server at %s", holocore.getRemoteAddress());
didConnect = true;
intentChain.broadcastAfter(getIntentManager(), new ServerConnectedIntent());
while (holocore.isConnected()) {
RawPacket inbound = holocore.receive();
if (inbound == null) {
Log.w("Server closed connection!");
if (holocore.isConnected())
Log.w("Server connection interrupted");
else
Log.w("Server closed connection!");
return;
}
intentChain.broadcastAfter(getIntentManager(), new DataPacketOutboundIntent(interceptor.interceptServer(inbound.getData())));
@@ -101,7 +111,8 @@ public class ServerConnectionService extends Service {
Log.w(t);
} finally {
Log.i("Disconnected from server.");
intentChain.broadcastAfter(getIntentManager(), new ServerDisconnectedIntent());
if (didConnect)
intentChain.broadcastAfter(getIntentManager(), new ServerDisconnectedIntent());
this.holocore = null;
}
}

View File

@@ -0,0 +1,13 @@
module com.projectswg.forwarder {
requires com.projectswg.common;
requires com.projectswg.holocore.client;
requires org.jetbrains.annotations;
requires java.management;
exports com.projectswg.forwarder;
opens com.projectswg.forwarder.services.client to me.joshlarson.jlcommon;
opens com.projectswg.forwarder.services.crash to me.joshlarson.jlcommon;
opens com.projectswg.forwarder.services.server to me.joshlarson.jlcommon;
}