mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2025-01-19 00:26:27 +01:00
extension suppoer & abstract Extension class implemented, not tested yet.
This commit is contained in:
parent
2b9c553c9c
commit
fd781afb18
@ -38,8 +38,10 @@ public class Main extends Application {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] args;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
Main.args = args;
|
||||||
launch(args);
|
launch(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
210
src/main/extensions/Extension.java
Normal file
210
src/main/extensions/Extension.java
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package main.extensions;
|
||||||
|
|
||||||
|
import main.protocol.HMessage;
|
||||||
|
import main.protocol.HPacket;
|
||||||
|
import main.protocol.packethandler.PayloadBuffer;
|
||||||
|
import main.ui.extensions.Extensions;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 23/06/18.
|
||||||
|
*/
|
||||||
|
public abstract class Extension {
|
||||||
|
|
||||||
|
public interface MessageListener {
|
||||||
|
void act(HMessage message);
|
||||||
|
}
|
||||||
|
public interface FlagsCheckListener {
|
||||||
|
void act(String[] args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String[] PORT_FLAG = {"--port", "-p"};
|
||||||
|
|
||||||
|
private OutputStream out = null;
|
||||||
|
private Map<Integer, List<MessageListener>> incomingMessageListeners = new HashMap<>();
|
||||||
|
private Map<Integer, List<MessageListener>> outgoingMessageListeners = new HashMap<>();
|
||||||
|
private FlagsCheckListener flagRequestCallback = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Extension(String[] args) {
|
||||||
|
//obtain port
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
|
outerloop:
|
||||||
|
for (int i = 0; i < args.length - 1; i++) {
|
||||||
|
for (String str : PORT_FLAG) {
|
||||||
|
if (args[i].equals(str)) {
|
||||||
|
port = Integer.parseInt(args[i+1]);
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Socket GEarthExtensionServer = new Socket("localhost", port);
|
||||||
|
|
||||||
|
InputStream in = GEarthExtensionServer.getInputStream();
|
||||||
|
out = GEarthExtensionServer.getOutputStream();
|
||||||
|
|
||||||
|
PayloadBuffer buffer = new PayloadBuffer();
|
||||||
|
while (!GEarthExtensionServer.isClosed()) {
|
||||||
|
if (in.available() > 0) {
|
||||||
|
byte[] data = new byte[in.available()];
|
||||||
|
in.read(data);
|
||||||
|
buffer.push(data);
|
||||||
|
|
||||||
|
HPacket[] packets = buffer.receive();
|
||||||
|
for (HPacket packet : packets) {
|
||||||
|
if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.INFOREQUEST) {
|
||||||
|
HPacket response = new HPacket(Extensions.INCOMING_MESSAGES_IDS.EXTENSIONINFO);
|
||||||
|
response.appendString(getTitle())
|
||||||
|
.appendString(getAuthor())
|
||||||
|
.appendString(getVersion())
|
||||||
|
.appendString(getDescription());
|
||||||
|
writeToStream(response.toBytes());
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.CONNECTIONSTART) {
|
||||||
|
onStartConnection();
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.CONNECTIONEND) {
|
||||||
|
onEndConnection();
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.FLAGSCHECK) {
|
||||||
|
// body = an array of G-Earths main flags
|
||||||
|
if (flagRequestCallback != null) {
|
||||||
|
int arraysize = packet.readInteger();
|
||||||
|
String[] gEarthArgs = new String[arraysize];
|
||||||
|
for (int i = 0; i < gEarthArgs.length; i++) {
|
||||||
|
gEarthArgs[i] = packet.readString();
|
||||||
|
}
|
||||||
|
flagRequestCallback.act(gEarthArgs);
|
||||||
|
}
|
||||||
|
flagRequestCallback = null;
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.INIT) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.FREEFLOW) {
|
||||||
|
// nothing to be done yet
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.ONDOUBLECLICK) {
|
||||||
|
onDoubleClick();
|
||||||
|
}
|
||||||
|
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.PACKETINTERCEPT) {
|
||||||
|
HMessage habboMessage = new HMessage(packet.readString());
|
||||||
|
HPacket habboPacket = habboMessage.getPacket();
|
||||||
|
|
||||||
|
Map<Integer, List<MessageListener>> listeners =
|
||||||
|
habboMessage.getDestination() == HMessage.Side.TOCLIENT ?
|
||||||
|
incomingMessageListeners :
|
||||||
|
outgoingMessageListeners;
|
||||||
|
|
||||||
|
if (listeners.containsKey(-1)) { // registered on all packets
|
||||||
|
for (int i = listeners.get(-1).size() - 1; i >= 0; i--) {
|
||||||
|
listeners.get(-1).get(i).act(habboMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (listeners.containsKey(habboPacket.headerId())) {
|
||||||
|
for (int i = listeners.get(habboPacket.headerId()).size() - 1; i >= 0; i--) {
|
||||||
|
listeners.get(habboPacket.headerId()).get(i).act(habboMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HPacket response = new HPacket(Extensions.INCOMING_MESSAGES_IDS.MANIPULATEDPACKET);
|
||||||
|
response.appendString(habboMessage.stringify());
|
||||||
|
|
||||||
|
writeToStream(response.toBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeToStream(byte[] bytes) throws IOException {
|
||||||
|
synchronized (out) {
|
||||||
|
out.write(bytes);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//methods returns if succeed
|
||||||
|
protected boolean sendToClient(HPacket packet) {
|
||||||
|
return send(packet, HMessage.Side.TOCLIENT);
|
||||||
|
}
|
||||||
|
protected boolean sendToServer(HPacket packet) {
|
||||||
|
return send(packet, HMessage.Side.TOSERVER);
|
||||||
|
}
|
||||||
|
private boolean send(HPacket packet, HMessage.Side side) {
|
||||||
|
HPacket packet1 = new HPacket(Extensions.INCOMING_MESSAGES_IDS.SENDMESSAGE);
|
||||||
|
packet1.appendByte(side == HMessage.Side.TOCLIENT ? (byte)0 : (byte)1);
|
||||||
|
packet1.appendInt(packet.getBytesLength());
|
||||||
|
packet1.appendBytes(packet.toBytes());
|
||||||
|
try {
|
||||||
|
writeToStream(packet1.toBytes());
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void intercept(HMessage.Side side, int headerId, MessageListener messageListener) {
|
||||||
|
Map<Integer, List<MessageListener>> listeners =
|
||||||
|
side == HMessage.Side.TOCLIENT ?
|
||||||
|
incomingMessageListeners :
|
||||||
|
outgoingMessageListeners;
|
||||||
|
|
||||||
|
if (!listeners.containsKey(headerId)) {
|
||||||
|
listeners.put(headerId, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
listeners.get(headerId).add(messageListener);
|
||||||
|
}
|
||||||
|
protected void intercept(HMessage.Side side, MessageListener messageListener) {
|
||||||
|
intercept(side, -1, messageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns "false" if another flag requester was busy
|
||||||
|
protected boolean requestFlags(FlagsCheckListener flagRequestCallback) {
|
||||||
|
if (this.flagRequestCallback != null) return false;
|
||||||
|
this.flagRequestCallback = flagRequestCallback;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeToConsole(String s) {
|
||||||
|
HPacket packet = new HPacket(Extensions.INCOMING_MESSAGES_IDS.EXTENSIONCONSOLELOG);
|
||||||
|
packet.appendString(s);
|
||||||
|
try {
|
||||||
|
writeToStream(packet.toBytes());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All methods under here block the stream, use threads if needed.
|
||||||
|
protected abstract void init();
|
||||||
|
protected abstract void onDoubleClick();
|
||||||
|
protected abstract void onStartConnection();
|
||||||
|
protected abstract void onEndConnection();
|
||||||
|
|
||||||
|
protected abstract String getTitle();
|
||||||
|
protected abstract String getDescription();
|
||||||
|
protected abstract String getVersion();
|
||||||
|
protected abstract String getAuthor();
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package main.protocol;
|
package main.protocol;
|
||||||
|
|
||||||
public class HMessage {
|
import main.misc.StringifyAble;
|
||||||
|
|
||||||
|
public class HMessage implements StringifyAble {
|
||||||
|
|
||||||
public enum Side {
|
public enum Side {
|
||||||
TOSERVER,
|
TOSERVER,
|
||||||
@ -13,6 +15,9 @@ public class HMessage {
|
|||||||
|
|
||||||
private boolean isBlocked;
|
private boolean isBlocked;
|
||||||
|
|
||||||
|
public HMessage(String fromString) {
|
||||||
|
constructFromString(fromString);
|
||||||
|
}
|
||||||
|
|
||||||
public HMessage(HPacket packet, Side side, int index) {
|
public HMessage(HPacket packet, Side side, int index) {
|
||||||
this.side = side;
|
this.side = side;
|
||||||
@ -42,4 +47,47 @@ public class HMessage {
|
|||||||
public boolean isCorrupted() {
|
public boolean isCorrupted() {
|
||||||
return hPacket.isCorrupted();
|
return hPacket.isCorrupted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String stringify() {
|
||||||
|
String s = (isBlocked ? "1" : "0") + "\t" + index + "\t" + side.name() + "\t" + hPacket.stringify();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void constructFromString(String str) {
|
||||||
|
String[] parts = str.split("\t");
|
||||||
|
this.isBlocked = parts[0].equals("1");
|
||||||
|
this.index = Integer.parseInt(parts[1]);
|
||||||
|
this.side = parts[2].equals("TOCLIENT") ? Side.TOCLIENT : Side.TOSERVER;
|
||||||
|
HPacket p = new HPacket(new byte[0]);
|
||||||
|
p.constructFromString(parts[3]);
|
||||||
|
this.hPacket = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof HMessage)) return false;
|
||||||
|
|
||||||
|
HMessage message = (HMessage) obj;
|
||||||
|
|
||||||
|
return message.hPacket.equals(hPacket) && (side == message.side) && (index == message.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// HPacket packet3 = new HPacket(81, new byte[]{0,0,0,1,0,0});
|
||||||
|
//
|
||||||
|
// HPacket packet = new HPacket(82, new byte[]{0,0,0,1,0,0});
|
||||||
|
// HMessage message = new HMessage(packet, Side.TOSERVER, 5);
|
||||||
|
//
|
||||||
|
// String stringed = message.stringify();
|
||||||
|
//
|
||||||
|
// HMessage message2 = new HMessage(stringed);
|
||||||
|
// HPacket packet1 = message2.getPacket();
|
||||||
|
//
|
||||||
|
// System.out.println(message.equals(message2));
|
||||||
|
// System.out.println(packet.equals(packet1));
|
||||||
|
// System.out.println(packet.equals(packet3));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package main.protocol;
|
package main.protocol;
|
||||||
|
|
||||||
|
import main.misc.StringifyAble;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -8,7 +10,7 @@ import java.util.Arrays;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class HPacket {
|
public class HPacket implements StringifyAble {
|
||||||
// te komen: toExpressions (+impl. expressies)
|
// te komen: toExpressions (+impl. expressies)
|
||||||
private boolean isEdited = false;
|
private boolean isEdited = false;
|
||||||
private byte[] packetInBytes;
|
private byte[] packetInBytes;
|
||||||
@ -403,7 +405,6 @@ public class HPacket {
|
|||||||
}
|
}
|
||||||
public HPacket replaceAllString(String oldS, String newS) {
|
public HPacket replaceAllString(String oldS, String newS) {
|
||||||
while (replaceFirstString(oldS, newS)) {}
|
while (replaceFirstString(oldS, newS)) {}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,7 +738,7 @@ public class HPacket {
|
|||||||
resultTest[j] = "{b:"+(packetInBytes[j] == 1 ? "true" : "false")+"}";
|
resultTest[j] = "{b:"+(packetInBytes[j] == 1 ? "true" : "false")+"}";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resultTest[j] = "{b:"+packetInBytes[j]+"}";
|
resultTest[j] = "{b:"+((((int)packetInBytes[j])+256)%256)+"}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opeenvolging = 0;
|
opeenvolging = 0;
|
||||||
@ -761,4 +762,23 @@ public class HPacket {
|
|||||||
return expression.toString().replace("{i:0}{b:false}{b:true}", "{s:}{i:1}");
|
return expression.toString().replace("{i:0}{b:false}{b:true}", "{s:}{i:1}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String stringify() {
|
||||||
|
String st = (isEdited ? "1" : "0") + this.toString();
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void constructFromString(String str) {
|
||||||
|
this.isEdited = str.charAt(0) == '1';
|
||||||
|
packetInBytes = fromStringToBytes(str.substring(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (!(object instanceof HPacket)) return false;
|
||||||
|
|
||||||
|
HPacket packet2 = (HPacket) object;
|
||||||
|
return Arrays.equals(packetInBytes, packet2.packetInBytes) && (isEdited == packet2.isEdited);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,13 @@
|
|||||||
package main.ui.extensions;
|
package main.ui.extensions;
|
||||||
|
|
||||||
|
import main.Main;
|
||||||
|
import main.protocol.*;
|
||||||
import main.ui.SubForm;
|
import main.ui.SubForm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 06/04/18.
|
* Created by Jonas on 06/04/18.
|
||||||
*/
|
*/
|
||||||
@ -47,7 +53,7 @@ import main.ui.SubForm;
|
|||||||
* | | | exact implementation is found in the Java abstract Extension class |
|
* | | | exact implementation is found in the Java abstract Extension class |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
* | 3 | PACKET-INTERCEPT* | Includes the whole HMessage as body, needs response with the |
|
* | 3 | PACKET-INTERCEPT* | Includes the whole HMessage as body, needs response with the |
|
||||||
* | | | manipulated HMessage (OUTGOING id: 2) (blank body = no manipulation) |
|
* | | | manipulated HMessage (OUTGOING id: 2) |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
* | 4 | FLAGS-CHECK** | Body: String with G-Earth's boot flags (args from static main method) |
|
* | 4 | FLAGS-CHECK** | Body: String with G-Earth's boot flags (args from static main method) |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
@ -55,6 +61,10 @@ import main.ui.SubForm;
|
|||||||
* | | | you could check this yourself as well (listen to out:4000 packet) |
|
* | | | you could check this yourself as well (listen to out:4000 packet) |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
* | 6 | CONNECTION END | Empty body, just a note that a connection has ended |
|
* | 6 | CONNECTION END | Empty body, just a note that a connection has ended |
|
||||||
|
* -----------------------------------------------------------------------------------------------------
|
||||||
|
* | 7 | INIT | Empty body, a connection with G-Earth has been set up |
|
||||||
|
* -----------------------------------------------------------------------------------------------------
|
||||||
|
* | 99 | FREE FLOW | extension-specific body |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* OUTGOING MESSAGES: (marked with * if that is a response to one of the msgs above)
|
* OUTGOING MESSAGES: (marked with * if that is a response to one of the msgs above)
|
||||||
@ -70,6 +80,8 @@ import main.ui.SubForm;
|
|||||||
* | 4 | SEND-MESSAGE | Body: HMessage object. Sends the HPacket wrapped in the HMessage |
|
* | 4 | SEND-MESSAGE | Body: HMessage object. Sends the HPacket wrapped in the HMessage |
|
||||||
* | | | to the client/server |
|
* | | | to the client/server |
|
||||||
* -----------------------------------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------------------------------
|
||||||
|
* | 99 | FREE FLOW | extension-specific body |
|
||||||
|
* -----------------------------------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* 4. Your extension will only appear in the extension list once the EXTENSION-INFO has been received by G-Earth
|
* 4. Your extension will only appear in the extension list once the EXTENSION-INFO has been received by G-Earth
|
||||||
*
|
*
|
||||||
@ -79,8 +91,157 @@ import main.ui.SubForm;
|
|||||||
|
|
||||||
public class Extensions extends SubForm {
|
public class Extensions extends SubForm {
|
||||||
|
|
||||||
|
public static class OUTGOING_MESSAGES_IDS {
|
||||||
|
public static final int ONDOUBLECLICK = 1;
|
||||||
|
public static final int INFOREQUEST = 2; // backend: implemented
|
||||||
|
public static final int PACKETINTERCEPT = 3; // backend: implemented
|
||||||
|
public static final int FLAGSCHECK = 4; // backend: implemented
|
||||||
|
public static final int CONNECTIONSTART = 5; // backend: implemented
|
||||||
|
public static final int CONNECTIONEND = 6; // backend: implemented
|
||||||
|
public static final int INIT = 7; // backend: implemented
|
||||||
|
public static final int FREEFLOW = 99; // no implementation needed yet
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class INCOMING_MESSAGES_IDS {
|
||||||
|
public static final int EXTENSIONINFO = 1; // backend: implemented
|
||||||
|
public static final int MANIPULATEDPACKET = 2; // backend: implemented
|
||||||
|
public static final int REQUESTFLAGS = 3; // backend: implemented
|
||||||
|
public static final int SENDMESSAGE = 4; // backend: implemented
|
||||||
|
public static final int EXTENSIONCONSOLELOG = 98;
|
||||||
|
public static final int FREEFLOW = 99; // no implementation needed yet
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private List<GEarthExtension> gEarthExtensions = new ArrayList<>();
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onParentSet() {
|
||||||
|
getHConnection().addStateChangeListener((oldState, newState) -> {
|
||||||
|
if (newState == HConnection.State.CONNECTED) {
|
||||||
|
for (GEarthExtension extension : gEarthExtensions) {
|
||||||
|
extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.CONNECTIONSTART));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldState == HConnection.State.CONNECTED) {
|
||||||
|
for (GEarthExtension extension : gEarthExtensions) {
|
||||||
|
extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.CONNECTIONEND));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getHConnection().addTrafficListener(1, message -> {
|
||||||
|
Set<GEarthExtension> collection = new HashSet<>(gEarthExtensions);
|
||||||
|
|
||||||
|
String stringified = message.stringify();
|
||||||
|
HPacket manipulatePacketRequest = new HPacket(OUTGOING_MESSAGES_IDS.PACKETINTERCEPT);
|
||||||
|
manipulatePacketRequest.appendString(stringified);
|
||||||
|
|
||||||
|
boolean[] isblock = new boolean[1];
|
||||||
|
|
||||||
|
for (GEarthExtension extension : gEarthExtensions) {
|
||||||
|
GEarthExtension.ReceiveMessageListener respondCallback = new GEarthExtension.ReceiveMessageListener() {
|
||||||
|
@Override
|
||||||
|
public void act(HPacket packet) {
|
||||||
|
if (packet.headerId() == INCOMING_MESSAGES_IDS.MANIPULATEDPACKET) {
|
||||||
|
String stringifiedresponse = packet.readString();
|
||||||
|
HMessage responseMessage = new HMessage(stringifiedresponse);
|
||||||
|
if (responseMessage.getDestination() == message.getDestination() && responseMessage.getIndex() == message.getIndex()) {
|
||||||
|
if (!message.equals(responseMessage)) {
|
||||||
|
message.constructFromString(stringifiedresponse);
|
||||||
|
if (responseMessage.isBlocked()) {
|
||||||
|
isblock[0] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collection.remove(extension);
|
||||||
|
extension.removeOnReceiveMessageListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
extension.addOnReceiveMessageListener(respondCallback);
|
||||||
|
|
||||||
|
extension.sendMessage(manipulatePacketRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
//block untill all extensions have responded
|
||||||
|
List<GEarthExtension> willdelete = new ArrayList<>();
|
||||||
|
while (!collection.isEmpty()) {
|
||||||
|
for (GEarthExtension extension : collection) {
|
||||||
|
if (!gEarthExtensions.contains(extension)) willdelete.add(extension);
|
||||||
|
}
|
||||||
|
for (int i = willdelete.size() - 1; i >= 0; i--) {
|
||||||
|
collection.remove(willdelete.get(i));
|
||||||
|
willdelete.remove(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isblock[0]) {
|
||||||
|
message.setBlocked(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
GEarthExtensionsRegistrer extensionsRegistrer = null;
|
||||||
|
HashMap<GEarthExtension, GEarthExtension.ReceiveMessageListener> messageListeners = new HashMap<>();
|
||||||
|
try {
|
||||||
|
extensionsRegistrer = new GEarthExtensionsRegistrer(new GEarthExtensionsRegistrer.ExtensionRegisterObserver() {
|
||||||
|
@Override
|
||||||
|
public void onConnect(GEarthExtension extension) {
|
||||||
|
gEarthExtensions.add(extension);
|
||||||
|
GEarthExtension.ReceiveMessageListener receiveMessageListener = message -> {
|
||||||
|
if (message.headerId() == INCOMING_MESSAGES_IDS.REQUESTFLAGS) { // no body
|
||||||
|
HPacket packet = new HPacket(OUTGOING_MESSAGES_IDS.FLAGSCHECK);
|
||||||
|
packet.appendInt(Main.args.length);
|
||||||
|
for (String arg : Main.args) {
|
||||||
|
packet.appendString(arg);
|
||||||
|
}
|
||||||
|
extension.sendMessage(packet);
|
||||||
|
}
|
||||||
|
else if (message.headerId() == INCOMING_MESSAGES_IDS.SENDMESSAGE) {
|
||||||
|
Byte side = message.readByte();
|
||||||
|
int byteLength = message.readInteger();
|
||||||
|
byte[] packetAsByteArray = message.readBytes(byteLength);
|
||||||
|
|
||||||
|
HPacket packet = new HPacket(packetAsByteArray);
|
||||||
|
if (!packet.isCorrupted()) {
|
||||||
|
if (side == 0) { // toclient
|
||||||
|
getHConnection().sendToClientAsync(packet);
|
||||||
|
}
|
||||||
|
else if (side == 1) { // toserver
|
||||||
|
getHConnection().sendToServerAsync(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
messageListeners.put(extension, receiveMessageListener);
|
||||||
|
extension.addOnReceiveMessageListener(receiveMessageListener);
|
||||||
|
|
||||||
|
extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.INIT));
|
||||||
|
if (getHConnection().getState() == HConnection.State.CONNECTED) {
|
||||||
|
extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.CONNECTIONSTART));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnect(GEarthExtension extension) {
|
||||||
|
gEarthExtensions.remove(extension);
|
||||||
|
|
||||||
|
extension.removeOnReceiveMessageListener(messageListeners.get(extension));
|
||||||
|
messageListeners.remove(extension);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.out.println("Extension server registered on port: " + extensionsRegistrer.getPort());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
169
src/main/ui/extensions/GEarthExtension.java
Normal file
169
src/main/ui/extensions/GEarthExtension.java
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package main.ui.extensions;
|
||||||
|
|
||||||
|
import main.protocol.HMessage;
|
||||||
|
import main.protocol.HPacket;
|
||||||
|
import main.protocol.packethandler.PayloadBuffer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public class GEarthExtension {
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private String author;
|
||||||
|
private String version;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Socket connection;
|
||||||
|
|
||||||
|
//calls callback when the extension is creatd
|
||||||
|
static void create(Socket connection, OnCreatedCallback callback, OnDisconnectedCallback onDisconnectedCallback) {
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
connection.getOutputStream().write((new HPacket(Extensions.OUTGOING_MESSAGES_IDS.INFOREQUEST)).toBytes());
|
||||||
|
connection.getOutputStream().flush();
|
||||||
|
|
||||||
|
PayloadBuffer payloadBuffer = new PayloadBuffer();
|
||||||
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
|
||||||
|
outerloop:
|
||||||
|
while (!connection.isClosed()) {
|
||||||
|
if (inputStream.available() > 0) {
|
||||||
|
byte[] incoming = new byte[inputStream.available()];
|
||||||
|
inputStream.read(incoming);
|
||||||
|
payloadBuffer.push(incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
HPacket[] hPackets = payloadBuffer.receive();
|
||||||
|
for (HPacket packet : hPackets) { // it should be only one packet
|
||||||
|
if (packet.headerId() == Extensions.INCOMING_MESSAGES_IDS.EXTENSIONINFO) {
|
||||||
|
|
||||||
|
GEarthExtension gEarthExtension = new GEarthExtension(
|
||||||
|
packet.readString(),
|
||||||
|
packet.readString(),
|
||||||
|
packet.readString(),
|
||||||
|
packet.readString(),
|
||||||
|
connection,
|
||||||
|
onDisconnectedCallback
|
||||||
|
);
|
||||||
|
callback.act(gEarthExtension);
|
||||||
|
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException ignored) {}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private GEarthExtension(String title, String author, String version, String description, Socket connection, OnDisconnectedCallback onDisconnectedCallback) {
|
||||||
|
this.title = title;
|
||||||
|
this.author = author;
|
||||||
|
this.version = version;
|
||||||
|
this.description = description;
|
||||||
|
this.connection = connection;
|
||||||
|
|
||||||
|
GEarthExtension selff = this;
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
PayloadBuffer payloadBuffer = new PayloadBuffer();
|
||||||
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
|
||||||
|
while (!connection.isClosed()) {
|
||||||
|
if (inputStream.available() > 0) {
|
||||||
|
byte[] incoming = new byte[inputStream.available()];
|
||||||
|
inputStream.read(incoming);
|
||||||
|
payloadBuffer.push(incoming);
|
||||||
|
}
|
||||||
|
|
||||||
|
HPacket[] hPackets = payloadBuffer.receive();
|
||||||
|
for (HPacket packet : hPackets) {
|
||||||
|
for (int i = receiveMessageListeners.size() - 1; i >= 0; i--) {
|
||||||
|
receiveMessageListeners.get(i).act(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
onDisconnectedCallback.act(selff);
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Socket getConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public boolean closeConnection() {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendMessage(HPacket message) {
|
||||||
|
try {
|
||||||
|
connection.getOutputStream().write(message.toBytes());
|
||||||
|
connection.getOutputStream().flush();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<ReceiveMessageListener> receiveMessageListeners = new ArrayList<>();
|
||||||
|
public void addOnReceiveMessageListener(ReceiveMessageListener receiveMessageListener) {
|
||||||
|
receiveMessageListeners.add(receiveMessageListener);
|
||||||
|
}
|
||||||
|
public void removeOnReceiveMessageListener(ReceiveMessageListener receiveMessageListener) {
|
||||||
|
receiveMessageListeners.remove(receiveMessageListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ReceiveMessageListener {
|
||||||
|
void act(HPacket message);
|
||||||
|
}
|
||||||
|
public interface OnCreatedCallback {
|
||||||
|
void act(GEarthExtension extension); // returns itself
|
||||||
|
}
|
||||||
|
public interface OnDisconnectedCallback {
|
||||||
|
void act(GEarthExtension extension); // returns itself
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
src/main/ui/extensions/GEarthExtensionsRegistrer.java
Normal file
35
src/main/ui/extensions/GEarthExtensionsRegistrer.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package main.ui.extensions;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public class GEarthExtensionsRegistrer {
|
||||||
|
|
||||||
|
final ServerSocket serverSocket;
|
||||||
|
|
||||||
|
GEarthExtensionsRegistrer(ExtensionRegisterObserver observer) throws IOException {
|
||||||
|
|
||||||
|
serverSocket = new ServerSocket(0);
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
while (!serverSocket.isClosed()) {
|
||||||
|
Socket extensionSocket = serverSocket.accept();
|
||||||
|
GEarthExtension.create(extensionSocket, observer::onConnect, observer::onDisconnect);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {e.printStackTrace();}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return serverSocket.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ExtensionRegisterObserver {
|
||||||
|
void onConnect(GEarthExtension extension);
|
||||||
|
void onDisconnect(GEarthExtension extension);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package main.ui.extensions.extensionfilemanager;
|
||||||
|
|
||||||
|
import main.ui.extensions.extensionfilemanager.extensionfile.ExtensionFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public interface ExtensionFilesManager {
|
||||||
|
|
||||||
|
List<ExtensionFile> getAllExtensions();
|
||||||
|
|
||||||
|
ExtensionFile addExtension(File file); //returns g-earth extension file, returns null if failure
|
||||||
|
|
||||||
|
boolean removeExtension(ExtensionFile file); //returns false if not done
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package main.ui.extensions.extensionfilemanager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public class ExtensionFilesManagerFactory {
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package main.ui.extensions.extensionfilemanager;
|
||||||
|
|
||||||
|
import main.ui.extensions.extensionfilemanager.extensionfile.ExtensionFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public class LinuxExtensionFilesManager implements ExtensionFilesManager {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ExtensionFile> getAllExtensions() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExtensionFile addExtension(File file) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeExtension(ExtensionFile file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package main.ui.extensions.extensionfilemanager.extensionfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Jonas on 21/06/18.
|
||||||
|
*/
|
||||||
|
public class ExtensionFile {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user