Switch SubData Packets from JSON to MessagePack encoding

This is a change to how packets are transferred; the API has not been changed.

While the difference may be unnoticable when using unencrypted packets, because of MessagePack's compact size and better handling of byte values encrypted packets should transfer faster.
This commit is contained in:
ME1312 2018-08-23 22:32:49 -04:00
parent 9f88bb5099
commit 7cd9c9bc4c
No known key found for this signature in database
GPG Key ID: FEFFE2F698E88FA8
67 changed files with 832 additions and 571 deletions

View File

@ -31,6 +31,12 @@
<version>1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.imaginarycode.minecraft</groupId>
<artifactId>RedisBungee</artifactId>

View File

@ -99,15 +99,6 @@ public class YAMLConfig {
return yaml.dump(config.map);
}
/**
* Converts Config Contents to JSON
*
* @return JSON Formatted Config Contents
*/
public String toJSON() {
return get().toJSON();
}
protected static DumperOptions getDumperOptions() {
DumperOptions options = new DumperOptions();
options.setAllowUnicode(true);

View File

@ -2,6 +2,9 @@ package net.ME1312.SubServers.Bungee.Library.Config;
import com.google.gson.Gson;
import net.ME1312.SubServers.Bungee.Library.Util;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
@ -73,6 +76,28 @@ public class YAMLSection {
setAll(map);
}
/**
* Creates a YAML Section from Message Pack Contents
*
* @param msgpack MessagePack Map
*/
public YAMLSection(MapValue msgpack) {
if (Util.isNull(msgpack)) throw new NullPointerException();
this.map = new LinkedHashMap<>();
this.yaml = new Yaml(YAMLConfig.getDumperOptions());
boolean warned = false;
Map<Value, Value> map = msgpack.map();
for (Value key : map.keySet()) {
if (key.isStringValue()) {
set(key.asStringValue().asString(), map.get(key));
} else if (!warned) {
new IllegalStateException("MessagePack contains non-string key(s)").printStackTrace();
warned = true;
}
}
}
protected YAMLSection(Map<String, ?> map, YAMLSection up, String handle, Yaml yaml) {
this.map = new LinkedHashMap<String, Object>();
this.yaml = yaml;
@ -127,8 +152,43 @@ public class YAMLSection {
}
private Object convert(Object value) {
if (value instanceof Value) {
if (((Value) value).isNilValue()) {
value = null;
} else if (((Value) value).isMapValue()) {
value = new YAMLSection(((Value) value).asMapValue());
} else if (((Value) value).isArrayValue()) {
value = ((Value) value).asArrayValue().list();
} else if (((Value) value).isBinaryValue()) {
value = ((Value) value).asBinaryValue().asByteArray();
} else if (((Value) value).isBooleanValue()) {
value = ((Value) value).asBooleanValue().getBoolean();
} else if (((Value) value).isFloatValue()) {
if (((Value) value).asFloatValue().toDouble() == (double)(float) ((Value) value).asFloatValue().toDouble()) {
value = ((Value) value).asFloatValue().toFloat();
} else {
value = ((Value) value).asFloatValue().toDouble();
}
} else if (((Value) value).isIntegerValue()) {
if (((Value) value).asIntegerValue().isInByteRange()) {
value = ((Value) value).asIntegerValue().asByte();
} else if (((Value) value).asIntegerValue().isInShortRange()) {
value = ((Value) value).asIntegerValue().asShort();
} else if (((Value) value).asIntegerValue().isInIntRange()) {
value = ((Value) value).asIntegerValue().asInt();
} else if (((Value) value).asIntegerValue().isInLongRange()) {
value = ((Value) value).asIntegerValue().asLong();
} else {
value = ((Value) value).asIntegerValue().asBigInteger();
}
} else if (((Value) value).isStringValue()) {
value = ((Value) value).asStringValue().asString();
}
}
if (value instanceof Map) {
if (value == null) {
return null;
} else if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key)));
@ -166,18 +226,10 @@ public class YAMLSection {
*/
public void set(String handle, Object value) {
if (Util.isNull(handle)) throw new NullPointerException();
if (value == null) {
remove(handle);
} else if (value instanceof Collection) {
set(handle, (Collection<?>) value);
} else if (value.getClass().isArray()) {
set(handle, (Object[]) value);
} else {
map.put(handle, convert(value));
map.put(handle, convert(value));
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
@ -192,62 +244,6 @@ public class YAMLSection {
if (!contains(handle)) set(handle, value);
}
/**
* Set V[] into this YAML Section
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void set(String handle, V[] array) {
if (Util.isNull(handle, array)) throw new NullPointerException();
List<Object> values = new LinkedList<Object>();
for (V value : array) {
values.add(convert(value));
}
map.put(handle, values);
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
/**
* Set V[] into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void safeSet(String handle, V[] array) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, array);
}
/**
* Set Collection&lt;V&gt; into this YAML Section
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void set(String handle, Collection<V> list) {
if (Util.isNull(handle, list)) throw new NullPointerException();
set(handle, list.toArray());
}
/**
* Set Collection&lt;V&gt; into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void safeSet(String handle, Collection<V> list) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, list);
}
/**
* Set All Objects into this YAML Section
*
@ -1056,4 +1052,47 @@ public class YAMLSection {
public String toJSON() {
return new Gson().toJson(get(), Map.class);
}
private Value msgPack(Object value) {
if (value == null) {
return ValueFactory.newNil();
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Map) {
ValueFactory.MapBuilder map = ValueFactory.newMapBuilder();
for (String key : ((Map<String, ?>) value).keySet()) {
Value v = msgPack(((Map<String, ?>) value).get(key));
if (v != null) map.put(ValueFactory.newString(key), v);
}
return map.build();
} else if (value instanceof Collection) {
LinkedList<Value> values = new LinkedList<Value>();
for (Object object : (Collection<?>) value) {
Value v = msgPack(object);
if (v != null) values.add(v);
}
return ValueFactory.newArray(values);
} else if (value instanceof Boolean) {
return ValueFactory.newBoolean((boolean) value);
} else if (value instanceof Number) {
if (((Number) value).doubleValue() == (double)(int) ((Number) value).doubleValue()) {
return ValueFactory.newInteger(((Number) value).longValue());
} else {
return ValueFactory.newFloat(((Number) value).doubleValue());
}
} else if (value instanceof String) {
return ValueFactory.newString((String) value);
} else {
return null;
}
}
/**
* Convert to a MessagePack Map
*
* @return MessagePack Map
*/
public MapValue msgPack() {
return (MapValue) msgPack(get());
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Bungee.Network;
import net.ME1312.SubServers.Bungee.Library.Config.YAMLSection;
import org.msgpack.value.Value;
/**
* SubData Cipher Layout Class
@ -20,7 +21,7 @@ public interface Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
byte[] encrypt(String key, YAMLSection data) throws Exception;
Value encrypt(String key, YAMLSection data) throws Exception;
/**
* Decrypt Encrypted JSON Data
@ -29,5 +30,5 @@ public interface Cipher {
* @param data Encrypted Data Array
* @return JSON Data
*/
YAMLSection decrypt(String key, byte[] data) throws Exception;
YAMLSection decrypt(String key, Value data) throws Exception;
}

View File

@ -1,10 +1,14 @@
package net.ME1312.SubServers.Bungee.Network;
import com.google.gson.JsonParseException;
import net.ME1312.SubServers.Bungee.Library.Config.YAMLSection;
import net.ME1312.SubServers.Bungee.Library.Exception.IllegalPacketException;
import net.ME1312.SubServers.Bungee.Library.Util;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketAuthorization;
import org.msgpack.core.MessageInsufficientBufferException;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.*;
@ -21,7 +25,7 @@ public class Client {
private Socket socket;
private InetSocketAddress address;
private ClientHandler handler;
private PrintWriter writer;
private MessagePacker out;
private Timer authorized;
private SubDataServer subdata;
boolean closed;
@ -37,7 +41,7 @@ public class Client {
this.subdata = subdata;
closed = false;
socket = client;
writer = new PrintWriter(client.getOutputStream(), true);
out = MessagePack.newDefaultPacker(client.getOutputStream());
address = new InetSocketAddress(client.getInetAddress(), client.getPort());
authorized = new Timer();
authorized.schedule(new TimerTask() {
@ -59,11 +63,11 @@ public class Client {
private void loop() {
new Thread(() -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String input;
while ((input = in.readLine()) != null) {
MessageUnpacker in = MessagePack.newDefaultUnpacker(socket.getInputStream());
Value input;
while ((input = in.unpackValue()) != null) {
try {
YAMLSection data = subdata.getCipher().decrypt(subdata.plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), Base64.getDecoder().decode(input));
YAMLSection data = subdata.getCipher().decrypt(subdata.plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), input);
for (PacketIn packet : SubDataServer.decodePacket(this, data)) {
boolean auth = authorized == null;
if (auth || packet instanceof PacketAuthorization) {
@ -73,18 +77,18 @@ public class Client {
List<Client> clients = new ArrayList<Client>();
clients.addAll(subdata.getClients());
for (Client client : clients) {
client.writer.println(input);
client.out.packValue(input);
}
} else {
Client client = subdata.getClient(data.getString("f"));
if (client != null) {
client.writer.println(input);
client.out.packValue(input);
} else {
throw new IllegalPacketException(getAddress().toString() + ": Unknown Forward Address: " + data.getString("f"));
}
}
} else {
packet.execute(Client.this, (data.contains("c"))?data.getSection("c"):null);
packet.execute(Client.this, (data.contains("c")) ? data.getSection("c") : null);
}
} catch (Throwable e) {
new InvocationTargetException(e, getAddress().toString() + ": Exception while executing PacketIn").printStackTrace();
@ -94,7 +98,7 @@ public class Client {
throw new IllegalPacketException(getAddress().toString() + ": Unauthorized call to packet type: " + data.getSection("h"));
}
}
} catch (JsonParseException | YAMLException e) {
} catch (YAMLException e) { // TODO
new IllegalPacketException(getAddress().toString() + ": Unknown Packet Format: " + input).printStackTrace();
} catch (IllegalPacketException e) {
e.printStackTrace();
@ -108,7 +112,7 @@ public class Client {
e1.printStackTrace();
}
} catch (Exception e) {
if (!(e instanceof SocketException)) e.printStackTrace();
if (!(e instanceof SocketException || e instanceof MessageInsufficientBufferException)) e.printStackTrace();
try {
subdata.removeClient(Client.this);
} catch (IOException e1) {
@ -137,7 +141,8 @@ public class Client {
public void sendPacket(PacketOut packet) {
if (Util.isNull(packet)) throw new NullPointerException();
try {
writer.println(Base64.getEncoder().encodeToString(subdata.getCipher().encrypt(subdata.plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), SubDataServer.encodePacket(this, packet))));
out.packValue(subdata.getCipher().encrypt(subdata.plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), SubDataServer.encodePacket(this, packet)));
out.flush();
} catch (Throwable e) {
e.printStackTrace();
}

View File

@ -2,6 +2,11 @@ package net.ME1312.SubServers.Bungee.Network.Encryption;
import com.google.gson.Gson;
import net.ME1312.SubServers.Bungee.Library.Config.YAMLSection;
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
@ -180,10 +185,15 @@ public final class AES implements net.ME1312.SubServers.Bungee.Network.Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
public byte[] encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(data.toJSON().getBytes(StandardCharsets.UTF_8)), bytes);
return bytes.toByteArray();
public Value encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream unencrypted = new ByteArrayOutputStream();
MessagePacker packer = MessagePack.newDefaultPacker(unencrypted);
packer.packValue(data.msgPack());
packer.close();
ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(unencrypted.toByteArray()), encrypted);
return ValueFactory.newBinary(encrypted.toByteArray());
}
public String getName() {
@ -271,10 +281,10 @@ public final class AES implements net.ME1312.SubServers.Bungee.Network.Cipher {
* @return JSON Data
*/
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
public YAMLSection decrypt(String key, Value data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decrypt(key, new ByteArrayInputStream(data), bytes);
return new YAMLSection(new Gson().fromJson(new String(bytes.toByteArray(), StandardCharsets.UTF_8), Map.class));
decrypt(key, new ByteArrayInputStream(data.asBinaryValue().asByteArray()), bytes);
return new YAMLSection(MessagePack.newDefaultUnpacker(bytes.toByteArray()).unpackValue().asMapValue());
}
/**

View File

@ -49,7 +49,7 @@ public class PacketCommandServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
return data;

View File

@ -44,7 +44,7 @@ public class PacketCreateServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
return data;

View File

@ -52,7 +52,7 @@ public class PacketDownloadGroupInfo implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection groups = new YAMLSection();
for (String group : plugin.api.getGroups().keySet()) {

View File

@ -48,7 +48,7 @@ public class PacketDownloadHostInfo implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection hosts = new YAMLSection();
for (Host host : plugin.api.getHosts().values()) {

View File

@ -40,7 +40,7 @@ public class PacketDownloadLang implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
LinkedHashMap<String, Map<String, String>> full = new LinkedHashMap<>();
for (String channel : plugin.api.getLangChannels())
full.put(channel, plugin.api.getLang(channel));

View File

@ -45,7 +45,7 @@ public class PacketDownloadNetworkList implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
if (id != null) json.set("id", id);
YAMLSection clients = new YAMLSection();
for (Client client : plugin.subdata.getClients()) {
try {

View File

@ -45,7 +45,7 @@ public class PacketDownloadPlayerList implements PacketIn, PacketOut {
@SuppressWarnings("unchecked")
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection players = new YAMLSection();
for (NamedContainer<String, UUID> player : plugin.api.getGlobalPlayers()) {
YAMLSection pinfo = new YAMLSection();

View File

@ -50,7 +50,7 @@ public class PacketDownloadProxyInfo implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection proxies = new YAMLSection();
for (Proxy proxy : plugin.api.getProxies().values()) {

View File

@ -50,7 +50,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection servers = new YAMLSection();
for (Server server : plugin.api.getServers().values()) {

View File

@ -46,7 +46,7 @@ public class PacketEditServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
if (id != null) json.set("id", id);
json.set("r", response);
return json;
}

View File

@ -57,7 +57,7 @@ public class PacketExAddServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
YAMLSection server = new YAMLSection();
server.set("name", name);
server.set("enabled", enabled);

View File

@ -41,7 +41,7 @@ public class PacketExRemoveServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("server", name);
return data;
}

View File

@ -53,7 +53,7 @@ public class PacketListenLog implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection add = new YAMLSection();
add.set("id", id);
if (id != null) add.set("id", id);
LinkedList<String> lines = new LinkedList<String>();
for (SubLogger.LogMessage line : this.lines) lines.add(new SimpleDateFormat("hh:mm:ss").format(line.getDate()) + " [" + line.getLevel().getLocalizedName() + "] " + line.getMessage());
add.set("lines", lines);

View File

@ -64,7 +64,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubAddHostEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player",event.getPlayer().toString());
args.set("host", event.getHost().getName());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
}
@ -74,8 +74,8 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubAddServerEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
args.set("host", ((event.getHost() == null)?null:event.getHost().getName()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
if (event.getHost() != null) args.set("host", event.getHost().getName());
args.set("server", event.getServer().getName());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
}
@ -85,7 +85,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubCreateEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("host", event.getHost().getName());
args.set("name", event.getName());
args.set("template", event.getTemplate().getName());
@ -98,7 +98,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubSendCommandEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("server", event.getServer().getName());
args.set("command", event.getCommand());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
@ -109,7 +109,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubEditServerEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("server", event.getServer().getName());
args.set("edit", event.getEdit().name());
args.set("value", event.getEdit().get().asObject());
@ -122,7 +122,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubStartEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("server", event.getServer().getName());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
}
@ -131,7 +131,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubStopEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("server", event.getServer().getName());
args.set("force", event.isForced());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
@ -149,8 +149,8 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubRemoveServerEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
args.set("host", ((event.getHost() == null)?null:event.getHost().getName()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
if (event.getHost() != null) args.set("host", event.getHost().getName());
args.set("server", event.getServer().getName());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
}
@ -160,7 +160,7 @@ public class PacketOutRunEvent implements Listener, PacketOut {
public void event(SubRemoveHostEvent event) {
if (!event.isCancelled()) {
YAMLSection args = new YAMLSection();
args.set("player", ((event.getPlayer() == null)?null:event.getPlayer().toString()));
if (event.getPlayer() != null) args.set("player", event.getPlayer().toString());
args.set("host", event.getHost().getName());
plugin.subdata.broadcastPacket(new PacketOutRunEvent(event.getClass(), args));
}

View File

@ -49,7 +49,7 @@ public class PacketStartServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
if (id != null) json.set("id", id);
json.set("r", response);
json.set("m", message);
return json;

View File

@ -49,7 +49,7 @@ public class PacketStopServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
if (id != null) json.set("id", id);
json.set("r", response);
json.set("m", message);
return json;

View File

@ -11,6 +11,9 @@ import net.ME1312.SubServers.Bungee.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Network.Encryption.AES;
import net.ME1312.SubServers.Bungee.Network.Packet.*;
import net.ME1312.SubServers.Bungee.SubPlugin;
import org.msgpack.core.MessagePack;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@ -60,13 +63,13 @@ public final class SubDataServer {
return "NONE";
}
@Override
public byte[] encrypt(String key, YAMLSection data) {
return data.toJSON().getBytes(StandardCharsets.UTF_8);
public Value encrypt(String key, YAMLSection data) {
return data.msgPack();
}
@Override
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) {
return new YAMLSection(new Gson().fromJson(new String(data, StandardCharsets.UTF_8), Map.class));
public YAMLSection decrypt(String key, Value data) {
return new YAMLSection(data.asMapValue());
}
};

View File

@ -31,6 +31,12 @@
<version>1.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.puharesource.mc</groupId>
<artifactId>TitleManager</artifactId>

View File

@ -99,15 +99,6 @@ public class YAMLConfig {
return yaml.dump(config.map);
}
/**
* Converts Config Contents to JSON
*
* @return JSON Formatted Config Contents
*/
public String toJSON() {
return get().toJSON();
}
protected static DumperOptions getDumperOptions() {
DumperOptions options = new DumperOptions();
options.setAllowUnicode(true);

View File

@ -1,6 +1,9 @@
package net.ME1312.SubServers.Client.Bukkit.Library.Config;
import net.ME1312.SubServers.Client.Bukkit.Library.Util;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
@ -73,6 +76,28 @@ public class YAMLSection {
setAll(map);
}
/**
* Creates a YAML Section from Message Pack Contents
*
* @param msgpack MessagePack Map
*/
public YAMLSection(MapValue msgpack) {
if (Util.isNull(msgpack)) throw new NullPointerException();
this.map = new LinkedHashMap<>();
this.yaml = new Yaml(YAMLConfig.getDumperOptions());
boolean warned = false;
Map<Value, Value> map = msgpack.map();
for (Value key : map.keySet()) {
if (key.isStringValue()) {
set(key.asStringValue().asString(), map.get(key));
} else if (!warned) {
new IllegalStateException("MessagePack contains non-string key(s)").printStackTrace();
warned = true;
}
}
}
protected YAMLSection(Map<String, ?> map, YAMLSection up, String handle, Yaml yaml) {
this.map = new LinkedHashMap<String, Object>();
this.yaml = yaml;
@ -127,7 +152,45 @@ public class YAMLSection {
}
private Object convert(Object value) {
if (value instanceof Map) {
if (value instanceof Value) {
if (((Value) value).isNilValue()) {
value = null;
} else if (((Value) value).isMapValue()) {
Map<Value, Value> map = ((Value) value).asMapValue().map();
value = new YAMLSection(((Value) value).asMapValue());
} else if (((Value) value).isArrayValue()) {
value = ((Value) value).asArrayValue().list();
} else if (((Value) value).isBinaryValue()) {
value = ((Value) value).asBinaryValue().asByteArray();
} else if (((Value) value).isBooleanValue()) {
value = ((Value) value).asBooleanValue().getBoolean();
} else if (((Value) value).isFloatValue()) {
if (((Value) value).asFloatValue().toDouble() == (double)(float) ((Value) value).asFloatValue().toDouble()) {
value = ((Value) value).asFloatValue().toFloat();
} else {
value = ((Value) value).asFloatValue().toDouble();
}
} else if (((Value) value).isIntegerValue()) {
if (((Value) value).asIntegerValue().isInByteRange()) {
value = ((Value) value).asIntegerValue().asByte();
} else if (((Value) value).asIntegerValue().isInShortRange()) {
value = ((Value) value).asIntegerValue().asShort();
} else if (((Value) value).asIntegerValue().isInIntRange()) {
value = ((Value) value).asIntegerValue().asInt();
} else if (((Value) value).asIntegerValue().isInLongRange()) {
value = ((Value) value).asIntegerValue().asLong();
} else {
value = ((Value) value).asIntegerValue().asBigInteger();
}
} else if (((Value) value).isStringValue()) {
value = ((Value) value).asStringValue().asString();
}
}
if (value == null) {
return null;
} else if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key)));
@ -165,18 +228,10 @@ public class YAMLSection {
*/
public void set(String handle, Object value) {
if (Util.isNull(handle)) throw new NullPointerException();
if (value == null) {
remove(handle);
} else if (value instanceof Collection) {
set(handle, (Collection<?>) value);
} else if (value.getClass().isArray()) {
set(handle, (Object[]) value);
} else {
map.put(handle, convert(value));
map.put(handle, convert(value));
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
@ -191,62 +246,6 @@ public class YAMLSection {
if (!contains(handle)) set(handle, value);
}
/**
* Set V[] into this YAML Section
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void set(String handle, V[] array) {
if (Util.isNull(handle, array)) throw new NullPointerException();
List<Object> values = new LinkedList<Object>();
for (V value : array) {
values.add(convert(value));
}
map.put(handle, values);
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
/**
* Set V[] into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void safeSet(String handle, V[] array) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, array);
}
/**
* Set Collection&lt;V&gt; into this YAML Section
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void set(String handle, Collection<V> list) {
if (Util.isNull(handle, list)) throw new NullPointerException();
set(handle, list.toArray());
}
/**
* Set Collection&lt;V&gt; into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void safeSet(String handle, Collection<V> list) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, list);
}
/**
* Set All Objects into this YAML Section
*
@ -1062,4 +1061,47 @@ public class YAMLSection {
return "{}";
}
}
private Value msgPack(Object value) {
if (value == null) {
return ValueFactory.newNil();
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Map) {
ValueFactory.MapBuilder map = ValueFactory.newMapBuilder();
for (String key : ((Map<String, ?>) value).keySet()) {
Value v = msgPack(((Map<String, ?>) value).get(key));
if (v != null) map.put(ValueFactory.newString(key), v);
}
return map.build();
} else if (value instanceof Collection) {
LinkedList<Value> values = new LinkedList<Value>();
for (Object object : (Collection<?>) value) {
Value v = msgPack(object);
if (v != null) values.add(v);
}
return ValueFactory.newArray(values);
} else if (value instanceof Boolean) {
return ValueFactory.newBoolean((boolean) value);
} else if (value instanceof Number) {
if (((Number) value).doubleValue() == (double)(int) ((Number) value).doubleValue()) {
return ValueFactory.newInteger(((Number) value).longValue());
} else {
return ValueFactory.newFloat(((Number) value).doubleValue());
}
} else if (value instanceof String) {
return ValueFactory.newString((String) value);
} else {
return null;
}
}
/**
* Convert to a MessagePack Map
*
* @return MessagePack Map
*/
public MapValue msgPack() {
return (MapValue) msgPack(get());
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Client.Bukkit.Network;
import net.ME1312.SubServers.Client.Bukkit.Library.Config.YAMLSection;
import org.msgpack.value.Value;
/**
* SubData Cipher Layout Class
@ -20,7 +21,7 @@ public interface Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
byte[] encrypt(String key, YAMLSection data) throws Exception;
Value encrypt(String key, YAMLSection data) throws Exception;
/**
* Decrypt Encrypted JSON Data
@ -29,5 +30,5 @@ public interface Cipher {
* @param data Encrypted Data Array
* @return JSON Data
*/
YAMLSection decrypt(String key, byte[] data) throws Exception;
YAMLSection decrypt(String key, Value data) throws Exception;
}

View File

@ -2,6 +2,10 @@ package net.ME1312.SubServers.Client.Bukkit.Network.Encryption;
import net.ME1312.SubServers.Client.Bukkit.Library.Config.YAMLSection;
import net.ME1312.SubServers.Client.Bukkit.SubAPI;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
@ -180,10 +184,15 @@ public final class AES implements net.ME1312.SubServers.Client.Bukkit.Network.Ci
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
public byte[] encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(data.toJSON().getBytes(StandardCharsets.UTF_8)), bytes);
return bytes.toByteArray();
public Value encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream unencrypted = new ByteArrayOutputStream();
MessagePacker packer = MessagePack.newDefaultPacker(unencrypted);
packer.packValue(data.msgPack());
packer.close();
ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(unencrypted.toByteArray()), encrypted);
return ValueFactory.newBinary(encrypted.toByteArray());
}
public String getName() {
@ -271,10 +280,10 @@ public final class AES implements net.ME1312.SubServers.Client.Bukkit.Network.Ci
* @return JSON Data
*/
@SuppressWarnings("deprecation")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
public YAMLSection decrypt(String key, Value data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decrypt(key, new ByteArrayInputStream(data), bytes);
return new YAMLSection(SubAPI.getInstance().getInternals().parseJSON(new String(bytes.toByteArray(), StandardCharsets.UTF_8)));
decrypt(key, new ByteArrayInputStream(data.asBinaryValue().asByteArray()), bytes);
return new YAMLSection(MessagePack.newDefaultUnpacker(bytes.toByteArray()).unpackValue().asMapValue());
}
/**

View File

@ -41,7 +41,7 @@ public class PacketDownloadGroupInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("group", group);
if (group != null) json.set("group", group);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadHostInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("host", host);
if (host != null) json.set("host", host);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadProxyInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("proxy", proxy);
if (proxy != null) json.set("proxy", proxy);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("server", server);
if (server != null) json.set("server", server);
return json;
}

View File

@ -11,6 +11,11 @@ import net.ME1312.SubServers.Client.Bukkit.Network.Encryption.AES;
import net.ME1312.SubServers.Client.Bukkit.Network.Packet.*;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import org.bukkit.Bukkit;
import org.msgpack.core.MessageInsufficientBufferException;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.*;
@ -29,7 +34,7 @@ public final class SubDataClient {
private static HashMap<String, HashMap<String, List<PacketIn>>> pIn = new HashMap<String, HashMap<String, List<PacketIn>>>();
private static HashMap<String, Cipher> ciphers = new HashMap<String, Cipher>();
private static boolean defaults = false;
private PrintWriter writer;
private MessagePacker out;
private NamedContainer<Boolean, Socket> socket;
private String name;
private Cipher cipher;
@ -51,7 +56,7 @@ public final class SubDataClient {
socket = new NamedContainer<>(false, new Socket(address, port));
this.plugin = plugin;
this.name = name;
this.writer = new PrintWriter(socket.get().getOutputStream(), true);
this.out = MessagePack.newDefaultPacker(socket.get().getOutputStream());
this.queue = new LinkedList<NamedContainer<String, PacketOut>>();
this.cipher = (cipher != null)?cipher:new Cipher() {
@Override
@ -59,13 +64,13 @@ public final class SubDataClient {
return "NONE";
}
@Override
public byte[] encrypt(String key, YAMLSection data) {
return data.toJSON().getBytes(StandardCharsets.UTF_8);
public Value encrypt(String key, YAMLSection data) {
return data.msgPack();
}
@Override
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
return new YAMLSection(plugin.parseJSON(new String(data, StandardCharsets.UTF_8)));
public YAMLSection decrypt(String key, Value data) {
return new YAMLSection(data.asMapValue());
}
};
@ -130,11 +135,11 @@ public final class SubDataClient {
private void loop() {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.get().getInputStream()));
String input;
while ((input = in.readLine()) != null) {
MessageUnpacker in = MessagePack.newDefaultUnpacker(socket.get().getInputStream());
Value input;
while ((input = in.unpackValue()) != null) {
try {
YAMLSection data = cipher.decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), Base64.getDecoder().decode(input));
YAMLSection data = cipher.decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), input);
for (PacketIn packet : decodePacket(data)) {
if (plugin.isEnabled()) Bukkit.getScheduler().runTask(plugin, () -> {
try {
@ -144,16 +149,12 @@ public final class SubDataClient {
}
});
}
} catch (YAMLException e) {
new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace();
} catch (IllegalPacketException e) {
e.printStackTrace();
} catch (Exception e) {
Class<?> gsone = Class.forName(((Util.getDespiteException(() -> Class.forName("com.google.gson.JsonParseException") != null, false)?"":"org.bukkit.craftbukkit.libs.")) + "com.google.gson.JsonParseException");
//Class<?> gsone = com.google.gson.JsonParseException.class;
if (e instanceof YAMLException || gsone.isInstance(e)) {
new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace();
} else {
new InvocationTargetException(e, "Exception while decoding packet").printStackTrace();
}
new InvocationTargetException(e, "Exception while decoding packet").printStackTrace();
}
}
try {
@ -162,7 +163,7 @@ public final class SubDataClient {
e1.printStackTrace();
}
} catch (Exception e) {
if (!(e instanceof SocketException)) e.printStackTrace();
if (!(e instanceof SocketException || e instanceof MessageInsufficientBufferException)) e.printStackTrace();
try {
destroy(plugin.config.get().getSection("Settings").getSection("SubData").getInt("Reconnect", 30));
} catch (IOException e1) {
@ -325,7 +326,8 @@ public final class SubDataClient {
try {
YAMLSection data = encodePacket(packet.get());
if (packet.name() != null) data.set("f", packet.name());
writer.println(Base64.getEncoder().encodeToString(cipher.encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data)));
out.packValue(getCipher().encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data));
out.flush();
} catch (Throwable e) {
e.printStackTrace();
}

View File

@ -23,6 +23,12 @@
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>

View File

@ -99,15 +99,6 @@ public class YAMLConfig {
return yaml.dump(config.map);
}
/**
* Converts Config Contents to JSON
*
* @return JSON Formatted Config Contents
*/
public String toJSON() {
return get().toJSON();
}
protected static DumperOptions getDumperOptions() {
DumperOptions options = new DumperOptions();
options.setAllowUnicode(true);

View File

@ -2,6 +2,9 @@ package net.ME1312.SubServers.Client.Sponge.Library.Config;
import com.google.gson.Gson;
import net.ME1312.SubServers.Client.Sponge.Library.Util;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
@ -73,6 +76,28 @@ public class YAMLSection {
setAll(map);
}
/**
* Creates a YAML Section from Message Pack Contents
*
* @param msgpack MessagePack Map
*/
public YAMLSection(MapValue msgpack) {
if (Util.isNull(msgpack)) throw new NullPointerException();
this.map = new LinkedHashMap<>();
this.yaml = new Yaml(YAMLConfig.getDumperOptions());
boolean warned = false;
Map<Value, Value> map = msgpack.map();
for (Value key : map.keySet()) {
if (key.isStringValue()) {
set(key.asStringValue().asString(), map.get(key));
} else if (!warned) {
new IllegalStateException("MessagePack contains non-string key(s)").printStackTrace();
warned = true;
}
}
}
protected YAMLSection(Map<String, ?> map, YAMLSection up, String handle, Yaml yaml) {
this.map = new LinkedHashMap<String, Object>();
this.yaml = yaml;
@ -127,7 +152,45 @@ public class YAMLSection {
}
private Object convert(Object value) {
if (value instanceof Map) {
if (value instanceof Value) {
if (((Value) value).isNilValue()) {
value = null;
} else if (((Value) value).isMapValue()) {
Map<Value, Value> map = ((Value) value).asMapValue().map();
value = new YAMLSection(((Value) value).asMapValue());
} else if (((Value) value).isArrayValue()) {
value = ((Value) value).asArrayValue().list();
} else if (((Value) value).isBinaryValue()) {
value = ((Value) value).asBinaryValue().asByteArray();
} else if (((Value) value).isBooleanValue()) {
value = ((Value) value).asBooleanValue().getBoolean();
} else if (((Value) value).isFloatValue()) {
if (((Value) value).asFloatValue().toDouble() == (double)(float) ((Value) value).asFloatValue().toDouble()) {
value = ((Value) value).asFloatValue().toFloat();
} else {
value = ((Value) value).asFloatValue().toDouble();
}
} else if (((Value) value).isIntegerValue()) {
if (((Value) value).asIntegerValue().isInByteRange()) {
value = ((Value) value).asIntegerValue().asByte();
} else if (((Value) value).asIntegerValue().isInShortRange()) {
value = ((Value) value).asIntegerValue().asShort();
} else if (((Value) value).asIntegerValue().isInIntRange()) {
value = ((Value) value).asIntegerValue().asInt();
} else if (((Value) value).asIntegerValue().isInLongRange()) {
value = ((Value) value).asIntegerValue().asLong();
} else {
value = ((Value) value).asIntegerValue().asBigInteger();
}
} else if (((Value) value).isStringValue()) {
value = ((Value) value).asStringValue().asString();
}
}
if (value == null) {
return null;
} else if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key)));
@ -165,18 +228,10 @@ public class YAMLSection {
*/
public void set(String handle, Object value) {
if (Util.isNull(handle)) throw new NullPointerException();
if (value == null) {
remove(handle);
} else if (value instanceof Collection) {
set(handle, (Collection<?>) value);
} else if (value.getClass().isArray()) {
set(handle, (Object[]) value);
} else {
map.put(handle, convert(value));
map.put(handle, convert(value));
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
@ -191,62 +246,6 @@ public class YAMLSection {
if (!contains(handle)) set(handle, value);
}
/**
* Set V[] into this YAML Section
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void set(String handle, V[] array) {
if (Util.isNull(handle, array)) throw new NullPointerException();
List<Object> values = new LinkedList<Object>();
for (V value : array) {
values.add(convert(value));
}
map.put(handle, values);
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
/**
* Set V[] into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void safeSet(String handle, V[] array) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, array);
}
/**
* Set Collection&lt;V&gt; into this YAML Section
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void set(String handle, Collection<V> list) {
if (Util.isNull(handle, list)) throw new NullPointerException();
set(handle, list.toArray());
}
/**
* Set Collection&lt;V&gt; into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void safeSet(String handle, Collection<V> list) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, list);
}
/**
* Set All Objects into this YAML Section
*
@ -1055,4 +1054,47 @@ public class YAMLSection {
public String toJSON() {
return new Gson().toJson(get(), Map.class);
}
private Value msgPack(Object value) {
if (value == null) {
return ValueFactory.newNil();
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Map) {
ValueFactory.MapBuilder map = ValueFactory.newMapBuilder();
for (String key : ((Map<String, ?>) value).keySet()) {
Value v = msgPack(((Map<String, ?>) value).get(key));
if (v != null) map.put(ValueFactory.newString(key), v);
}
return map.build();
} else if (value instanceof Collection) {
LinkedList<Value> values = new LinkedList<Value>();
for (Object object : (Collection<?>) value) {
Value v = msgPack(object);
if (v != null) values.add(v);
}
return ValueFactory.newArray(values);
} else if (value instanceof Boolean) {
return ValueFactory.newBoolean((boolean) value);
} else if (value instanceof Number) {
if (((Number) value).doubleValue() == (double)(int) ((Number) value).doubleValue()) {
return ValueFactory.newInteger(((Number) value).longValue());
} else {
return ValueFactory.newFloat(((Number) value).doubleValue());
}
} else if (value instanceof String) {
return ValueFactory.newString((String) value);
} else {
return null;
}
}
/**
* Convert to a MessagePack Map
*
* @return MessagePack Map
*/
public MapValue msgPack() {
return (MapValue) msgPack(get());
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Client.Sponge.Network;
import net.ME1312.SubServers.Client.Sponge.Library.Config.YAMLSection;
import org.msgpack.value.Value;
/**
* SubData Cipher Layout Class
@ -20,7 +21,7 @@ public interface Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
byte[] encrypt(String key, YAMLSection data) throws Exception;
Value encrypt(String key, YAMLSection data) throws Exception;
/**
* Decrypt Encrypted JSON Data
@ -29,5 +30,5 @@ public interface Cipher {
* @param data Encrypted Data Array
* @return JSON Data
*/
YAMLSection decrypt(String key, byte[] data) throws Exception;
YAMLSection decrypt(String key, Value data) throws Exception;
}

View File

@ -2,6 +2,10 @@ package net.ME1312.SubServers.Client.Sponge.Network.Encryption;
import com.google.gson.Gson;
import net.ME1312.SubServers.Client.Sponge.Library.Config.YAMLSection;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
@ -180,10 +184,15 @@ public final class AES implements net.ME1312.SubServers.Client.Sponge.Network.Ci
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
public byte[] encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(data.toJSON().getBytes(StandardCharsets.UTF_8)), bytes);
return bytes.toByteArray();
public Value encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream unencrypted = new ByteArrayOutputStream();
MessagePacker packer = MessagePack.newDefaultPacker(unencrypted);
packer.packValue(data.msgPack());
packer.close();
ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(unencrypted.toByteArray()), encrypted);
return ValueFactory.newBinary(encrypted.toByteArray());
}
public String getName() {
@ -271,10 +280,10 @@ public final class AES implements net.ME1312.SubServers.Client.Sponge.Network.Ci
* @return JSON Data
*/
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
public YAMLSection decrypt(String key, Value data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decrypt(key, new ByteArrayInputStream(data), bytes);
return new YAMLSection(new Gson().fromJson(new String(bytes.toByteArray(), StandardCharsets.UTF_8), Map.class));
decrypt(key, new ByteArrayInputStream(data.asBinaryValue().asByteArray()), bytes);
return new YAMLSection(MessagePack.newDefaultUnpacker(bytes.toByteArray()).unpackValue().asMapValue());
}
/**

View File

@ -41,7 +41,7 @@ public class PacketDownloadGroupInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("group", group);
if (group != null) json.set("group", group);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadHostInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("host", host);
if (host != null) json.set("host", host);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadProxyInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("proxy", proxy);
if (proxy != null) json.set("proxy", proxy);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("server", server);
if (server != null) json.set("server", server);
return json;
}

View File

@ -1,7 +1,5 @@
package net.ME1312.SubServers.Client.Sponge.Network;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import net.ME1312.SubServers.Client.Sponge.Event.SubNetworkConnectEvent;
import net.ME1312.SubServers.Client.Sponge.Event.SubNetworkDisconnectEvent;
import net.ME1312.SubServers.Client.Sponge.Library.Config.YAMLSection;
@ -12,6 +10,11 @@ import net.ME1312.SubServers.Client.Sponge.Library.Version.Version;
import net.ME1312.SubServers.Client.Sponge.Network.Encryption.AES;
import net.ME1312.SubServers.Client.Sponge.Network.Packet.*;
import net.ME1312.SubServers.Client.Sponge.SubPlugin;
import org.msgpack.core.MessageInsufficientBufferException;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.api.Sponge;
@ -22,7 +25,6 @@ import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -35,7 +37,7 @@ public final class SubDataClient {
private static HashMap<String, Cipher> ciphers = new HashMap<String, Cipher>();
private static boolean defaults = false;
protected static Logger log;
private PrintWriter writer;
private MessagePacker out;
private NamedContainer<Boolean, Socket> socket;
private String name;
private Cipher cipher;
@ -57,7 +59,7 @@ public final class SubDataClient {
socket = new NamedContainer<>(false, new Socket(address, port));
this.plugin = plugin;
this.name = name;
this.writer = new PrintWriter(socket.get().getOutputStream(), true);
this.out = MessagePack.newDefaultPacker(socket.get().getOutputStream());
this.queue = new LinkedList<NamedContainer<String, PacketOut>>();
this.cipher = (cipher != null)?cipher:new Cipher() {
@Override
@ -65,13 +67,13 @@ public final class SubDataClient {
return "NONE";
}
@Override
public byte[] encrypt(String key, YAMLSection data) {
return data.toJSON().getBytes(StandardCharsets.UTF_8);
public Value encrypt(String key, YAMLSection data) {
return data.msgPack();
}
@Override
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) {
return new YAMLSection(new Gson().fromJson(new String(data, StandardCharsets.UTF_8), Map.class));
public YAMLSection decrypt(String key, Value data) {
return new YAMLSection(data.asMapValue());
}
};
@ -137,11 +139,11 @@ public final class SubDataClient {
private void loop() {
Sponge.getScheduler().createTaskBuilder().async().execute(() -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.get().getInputStream()));
String input;
while ((input = in.readLine()) != null) {
MessageUnpacker in = MessagePack.newDefaultUnpacker(socket.get().getInputStream());
Value input;
while ((input = in.unpackValue()) != null) {
try {
YAMLSection data = cipher.decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), Base64.getDecoder().decode(input));
YAMLSection data = getCipher().decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), input);
for (PacketIn packet : decodePacket(data)) {
Sponge.getScheduler().createTaskBuilder().execute(() -> {
try {
@ -151,7 +153,7 @@ public final class SubDataClient {
}
}).submit(plugin);
}
} catch (JsonParseException | YAMLException e) {
} catch (YAMLException e) {
new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace();
} catch (IllegalPacketException e) {
e.printStackTrace();
@ -165,7 +167,7 @@ public final class SubDataClient {
e1.printStackTrace();
}
} catch (Exception e) {
if (!(e instanceof SocketException)) e.printStackTrace();
if (!(e instanceof SocketException || e instanceof MessageInsufficientBufferException)) e.printStackTrace();
try {
destroy(plugin.config.get().getSection("Settings").getSection("SubData").getInt("Reconnect", 30));
} catch (IOException e1) {
@ -328,7 +330,8 @@ public final class SubDataClient {
try {
YAMLSection data = encodePacket(packet.get());
if (packet.name() != null) data.set("f", packet.name());
writer.println(Base64.getEncoder().encodeToString(cipher.encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data)));
out.packValue(getCipher().encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data));
out.flush();
} catch (Throwable e) {
e.printStackTrace();
}

View File

@ -29,9 +29,9 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.20</version>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -40,6 +40,12 @@
<version>20180130</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.20</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>

View File

@ -100,15 +100,6 @@ public class YAMLConfig {
return yaml.dump(config.map);
}
/**
* Converts Config Contents to JSON
*
* @return JSON Formatted Config Contents
*/
public JSONObject toJSON() {
return new JSONObject(config.map);
}
protected static DumperOptions getDumperOptions() {
DumperOptions options = new DumperOptions();
options.setAllowUnicode(true);

View File

@ -3,6 +3,9 @@ package net.ME1312.SubServers.Host.Library.Config;
import net.ME1312.SubServers.Host.Library.Util;
import org.json.JSONArray;
import org.json.JSONObject;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
@ -61,16 +64,6 @@ public class YAMLSection {
this.map = (LinkedHashMap<String, Object>) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).loadAs(str, LinkedHashMap.class);
}
/**
* Creates a YAML Section from JSON Contents
*
* @param json JSON
*/
public YAMLSection(JSONObject json) {
if (Util.isNull(json)) throw new NullPointerException();
this.map = (LinkedHashMap<String, Object>) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).loadAs(json.toString(4), LinkedHashMap.class);
}
/**
* Creates a YAML Section from Map Contents
*
@ -84,6 +77,38 @@ public class YAMLSection {
setAll(map);
}
/**
* Creates a YAML Section from Message Pack Contents
*
* @param msgpack MessagePack Map
*/
public YAMLSection(MapValue msgpack) {
if (Util.isNull(msgpack)) throw new NullPointerException();
this.map = new LinkedHashMap<>();
this.yaml = new Yaml(YAMLConfig.getDumperOptions());
boolean warned = false;
Map<Value, Value> map = msgpack.map();
for (Value key : map.keySet()) {
if (key.isStringValue()) {
set(key.asStringValue().asString(), map.get(key));
} else if (!warned) {
new IllegalStateException("MessagePack contains non-string key(s)").printStackTrace();
warned = true;
}
}
}
/**
* Creates a YAML Section from JSON Contents
*
* @param json JSON
*/
public YAMLSection(JSONObject json) {
if (Util.isNull(json)) throw new NullPointerException();
this.map = (LinkedHashMap<String, Object>) (this.yaml = new Yaml(YAMLConfig.getDumperOptions())).loadAs(json.toString(4), LinkedHashMap.class);
}
protected YAMLSection(Map<String, ?> map, YAMLSection up, String handle, Yaml yaml) {
this.map = new LinkedHashMap<String, Object>();
this.yaml = yaml;
@ -138,11 +163,45 @@ public class YAMLSection {
}
private Object convert(Object value) {
if (value instanceof JSONObject) {
value = new YAMLSection((JSONObject) value);
if (value instanceof Value) {
if (((Value) value).isNilValue()) {
value = null;
} else if (((Value) value).isMapValue()) {
Map<Value, Value> map = ((Value) value).asMapValue().map();
value = new YAMLSection(((Value) value).asMapValue());
} else if (((Value) value).isArrayValue()) {
value = ((Value) value).asArrayValue().list();
} else if (((Value) value).isBinaryValue()) {
value = ((Value) value).asBinaryValue().asByteArray();
} else if (((Value) value).isBooleanValue()) {
value = ((Value) value).asBooleanValue().getBoolean();
} else if (((Value) value).isFloatValue()) {
if (((Value) value).asFloatValue().toDouble() == (double)(float) ((Value) value).asFloatValue().toDouble()) {
value = ((Value) value).asFloatValue().toFloat();
} else {
value = ((Value) value).asFloatValue().toDouble();
}
} else if (((Value) value).isIntegerValue()) {
if (((Value) value).asIntegerValue().isInByteRange()) {
value = ((Value) value).asIntegerValue().asByte();
} else if (((Value) value).asIntegerValue().isInShortRange()) {
value = ((Value) value).asIntegerValue().asShort();
} else if (((Value) value).asIntegerValue().isInIntRange()) {
value = ((Value) value).asIntegerValue().asInt();
} else if (((Value) value).asIntegerValue().isInLongRange()) {
value = ((Value) value).asIntegerValue().asLong();
} else {
value = ((Value) value).asIntegerValue().asBigInteger();
}
} else if (((Value) value).isStringValue()) {
value = ((Value) value).asStringValue().asString();
}
}
if (value instanceof Map) {
if (value == null) {
return null;
} else if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key)));
@ -157,10 +216,6 @@ public class YAMLSection {
return ((YAMLSection) value).map;
} else if (value instanceof YAMLValue) {
return ((YAMLValue) value).asObject();
} else if (value instanceof JSONArray) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < ((JSONArray) value).length(); i++) list.add(convert(((JSONArray) value).get(i)));
return list;
} else if (value instanceof Collection) {
List<Object> list = new ArrayList<Object>();
for (Object val : (Collection<Object>) value) list.add(convert(val));
@ -184,18 +239,10 @@ public class YAMLSection {
*/
public void set(String handle, Object value) {
if (Util.isNull(handle)) throw new NullPointerException();
if (value == null) {
remove(handle);
} else if (value instanceof Collection) {
set(handle, (Collection<?>) value);
} else if (value.getClass().isArray()) {
set(handle, (Object[]) value);
} else {
map.put(handle, convert(value));
map.put(handle, convert(value));
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
@ -210,62 +257,6 @@ public class YAMLSection {
if (!contains(handle)) set(handle, value);
}
/**
* Set V[] into this YAML Section
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void set(String handle, V[] array) {
if (Util.isNull(handle, array)) throw new NullPointerException();
List<Object> values = new LinkedList<Object>();
for (V value : array) {
values.add(convert(value));
}
map.put(handle, values);
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
/**
* Set V[] into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void safeSet(String handle, V[] array) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, array);
}
/**
* Set Collection&lt;V&gt; into this YAML Section
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void set(String handle, Collection<V> list) {
if (Util.isNull(handle, list)) throw new NullPointerException();
set(handle, list.toArray());
}
/**
* Set Collection&lt;V&gt; into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void safeSet(String handle, Collection<V> list) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, list);
}
/**
* Set All Objects into this YAML Section
*
@ -1074,4 +1065,47 @@ public class YAMLSection {
public JSONObject toJSON() {
return new JSONObject(map);
}
private Value msgPack(Object value) {
if (value == null) {
return ValueFactory.newNil();
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Map) {
ValueFactory.MapBuilder map = ValueFactory.newMapBuilder();
for (String key : ((Map<String, ?>) value).keySet()) {
Value v = msgPack(((Map<String, ?>) value).get(key));
if (v != null) map.put(ValueFactory.newString(key), v);
}
return map.build();
} else if (value instanceof Collection) {
LinkedList<Value> values = new LinkedList<Value>();
for (Object object : (Collection<?>) value) {
Value v = msgPack(object);
if (v != null) values.add(v);
}
return ValueFactory.newArray(values);
} else if (value instanceof Boolean) {
return ValueFactory.newBoolean((boolean) value);
} else if (value instanceof Number) {
if (((Number) value).doubleValue() == (double)(int) ((Number) value).doubleValue()) {
return ValueFactory.newInteger(((Number) value).longValue());
} else {
return ValueFactory.newFloat(((Number) value).doubleValue());
}
} else if (value instanceof String) {
return ValueFactory.newString((String) value);
} else {
return null;
}
}
/**
* Convert to a MessagePack Map
*
* @return MessagePack Map
*/
public MapValue msgPack() {
return (MapValue) msgPack(get());
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Host.Network;
import net.ME1312.SubServers.Host.Library.Config.YAMLSection;
import org.msgpack.value.Value;
/**
* SubData Cipher Layout Class
@ -20,7 +21,7 @@ public interface Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
byte[] encrypt(String key, YAMLSection data) throws Exception;
Value encrypt(String key, YAMLSection data) throws Exception;
/**
* Decrypt Encrypted JSON Data
@ -29,5 +30,5 @@ public interface Cipher {
* @param data Encrypted Data Array
* @return JSON Data
*/
YAMLSection decrypt(String key, byte[] data) throws Exception;
YAMLSection decrypt(String key, Value data) throws Exception;
}

View File

@ -2,6 +2,10 @@ package net.ME1312.SubServers.Host.Network.Encryption;
import net.ME1312.SubServers.Host.Library.Config.YAMLSection;
import org.json.JSONObject;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
@ -180,10 +184,15 @@ public final class AES implements net.ME1312.SubServers.Host.Network.Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
public byte[] encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(data.toJSON().toString().getBytes(StandardCharsets.UTF_8)), bytes);
return bytes.toByteArray();
public Value encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream unencrypted = new ByteArrayOutputStream();
MessagePacker packer = MessagePack.newDefaultPacker(unencrypted);
packer.packValue(data.msgPack());
packer.close();
ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(unencrypted.toByteArray()), encrypted);
return ValueFactory.newBinary(encrypted.toByteArray());
}
public String getName() {
@ -271,10 +280,10 @@ public final class AES implements net.ME1312.SubServers.Host.Network.Cipher {
* @return JSON Data
*/
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
public YAMLSection decrypt(String key, Value data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decrypt(key, new ByteArrayInputStream(data), bytes);
return new YAMLSection(new JSONObject(new String(bytes.toByteArray(), StandardCharsets.UTF_8)));
decrypt(key, new ByteArrayInputStream(data.asBinaryValue().asByteArray()), bytes);
return new YAMLSection(MessagePack.newDefaultUnpacker(bytes.toByteArray()).unpackValue().asMapValue());
}
/**

View File

@ -41,7 +41,7 @@ public class PacketDownloadGroupInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("group", group);
if (group != null) json.set("group", group);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadHostInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("host", host);
if (host != null) json.set("host", host);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadProxyInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("proxy", proxy);
if (proxy != null) json.set("proxy", proxy);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("server", server);
if (server != null) json.set("server", server);
return json;
}

View File

@ -57,7 +57,7 @@ public class PacketExAddServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
return data;

View File

@ -48,7 +48,7 @@ public class PacketExCreateServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
data.set("c", info);

View File

@ -58,7 +58,7 @@ public class PacketExDeleteServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
return data;

View File

@ -54,7 +54,7 @@ public class PacketExRemoveServer implements PacketIn, PacketOut {
@Override
public YAMLSection generate() {
YAMLSection data = new YAMLSection();
data.set("id", id);
if (id != null) data.set("id", id);
data.set("r", response);
data.set("m", message);
return data;

View File

@ -14,6 +14,11 @@ import net.ME1312.SubServers.Host.SubAPI;
import net.ME1312.SubServers.Host.ExHost;
import org.json.JSONException;
import org.json.JSONObject;
import org.msgpack.core.MessageInsufficientBufferException;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.BufferedReader;
@ -37,7 +42,7 @@ public final class SubDataClient {
private static HashMap<String, Cipher> ciphers = new HashMap<String, Cipher>();
private static boolean defaults = false;
protected static Logger log;
private PrintWriter writer;
private MessagePacker out;
private NamedContainer<Boolean, Socket> socket;
private String name;
private Cipher cipher;
@ -59,7 +64,7 @@ public final class SubDataClient {
socket = new NamedContainer<>(false, new Socket(address, port));
this.host = host;
this.name = name;
this.writer = new PrintWriter(socket.get().getOutputStream(), true);
this.out = MessagePack.newDefaultPacker(socket.get().getOutputStream());
this.queue = new LinkedList<NamedContainer<String, PacketOut>>();
this.cipher = (cipher != null)?cipher:new Cipher() {
@Override
@ -67,12 +72,13 @@ public final class SubDataClient {
return "NONE";
}
@Override
public byte[] encrypt(String key, YAMLSection data) throws Exception {
return data.toJSON().toString().getBytes(StandardCharsets.UTF_8);
public Value encrypt(String key, YAMLSection data) {
return data.msgPack();
}
@Override
public YAMLSection decrypt(String key, byte[] data) throws Exception {
return new YAMLSection(new JSONObject(new String(data, StandardCharsets.UTF_8)));
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, Value data) {
return new YAMLSection(data.asMapValue());
}
};
@ -155,11 +161,11 @@ public final class SubDataClient {
private void loop() {
new Thread(() -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.get().getInputStream()));
String input;
while ((input = in.readLine()) != null) {
MessageUnpacker in = MessagePack.newDefaultUnpacker(socket.get().getInputStream());
Value input;
while ((input = in.unpackValue()) != null) {
try {
YAMLSection data = cipher.decrypt(host.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), Base64.getDecoder().decode(input));
YAMLSection data = cipher.decrypt(host.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), input);
for (PacketIn packet : decodePacket(data)) {
try {
packet.execute((data.contains("c"))?data.getSection("c"):null);
@ -181,7 +187,7 @@ public final class SubDataClient {
log.error.println(e1);
}
} catch (Exception e) {
if (!(e instanceof SocketException)) log.error.println(e);
if (!(e instanceof SocketException || e instanceof MessageInsufficientBufferException)) log.error.println(e);
try {
destroy(host.config.get().getSection("Settings").getSection("SubData").getInt("Reconnect", 30));
} catch (IOException e1) {
@ -344,7 +350,8 @@ public final class SubDataClient {
try {
YAMLSection data = encodePacket(packet.get());
if (packet.name() != null) data.set("f", packet.name());
writer.println(Base64.getEncoder().encodeToString(cipher.encrypt(host.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data)));
out.packValue(getCipher().encrypt(host.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data));
out.flush();
} catch (Throwable e) {
log.error.println(e);
}

View File

@ -31,6 +31,12 @@
<version>1.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>msgpack-core</artifactId>
<version>0.8.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.imaginarycode.minecraft</groupId>
<artifactId>RedisBungee</artifactId>

View File

@ -99,15 +99,6 @@ public class YAMLConfig {
return yaml.dump(config.map);
}
/**
* Converts Config Contents to JSON
*
* @return JSON Formatted Config Contents
*/
public String toJSON() {
return config.toJSON();
}
protected static DumperOptions getDumperOptions() {
DumperOptions options = new DumperOptions();
options.setAllowUnicode(true);

View File

@ -2,6 +2,9 @@ package net.ME1312.SubServers.Sync.Library.Config;
import com.google.gson.Gson;
import net.ME1312.SubServers.Sync.Library.Util;
import org.msgpack.value.MapValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;
@ -73,6 +76,28 @@ public class YAMLSection {
setAll(map);
}
/**
* Creates a YAML Section from Message Pack Contents
*
* @param msgpack MessagePack Map
*/
public YAMLSection(MapValue msgpack) {
if (Util.isNull(msgpack)) throw new NullPointerException();
this.map = new LinkedHashMap<>();
this.yaml = new Yaml(YAMLConfig.getDumperOptions());
boolean warned = false;
Map<Value, Value> map = msgpack.map();
for (Value key : map.keySet()) {
if (key.isStringValue()) {
set(key.asStringValue().asString(), map.get(key));
} else if (!warned) {
new IllegalStateException("MessagePack contains non-string key(s)").printStackTrace();
warned = true;
}
}
}
protected YAMLSection(Map<String, ?> map, YAMLSection up, String handle, Yaml yaml) {
this.map = new LinkedHashMap<String, Object>();
this.yaml = yaml;
@ -127,7 +152,45 @@ public class YAMLSection {
}
private Object convert(Object value) {
if (value instanceof Map) {
if (value instanceof Value) {
if (((Value) value).isNilValue()) {
value = null;
} else if (((Value) value).isMapValue()) {
Map<Value, Value> map = ((Value) value).asMapValue().map();
value = new YAMLSection(((Value) value).asMapValue());
} else if (((Value) value).isArrayValue()) {
value = ((Value) value).asArrayValue().list();
} else if (((Value) value).isBinaryValue()) {
value = ((Value) value).asBinaryValue().asByteArray();
} else if (((Value) value).isBooleanValue()) {
value = ((Value) value).asBooleanValue().getBoolean();
} else if (((Value) value).isFloatValue()) {
if (((Value) value).asFloatValue().toDouble() == (double)(float) ((Value) value).asFloatValue().toDouble()) {
value = ((Value) value).asFloatValue().toFloat();
} else {
value = ((Value) value).asFloatValue().toDouble();
}
} else if (((Value) value).isIntegerValue()) {
if (((Value) value).asIntegerValue().isInByteRange()) {
value = ((Value) value).asIntegerValue().asByte();
} else if (((Value) value).asIntegerValue().isInShortRange()) {
value = ((Value) value).asIntegerValue().asShort();
} else if (((Value) value).asIntegerValue().isInIntRange()) {
value = ((Value) value).asIntegerValue().asInt();
} else if (((Value) value).asIntegerValue().isInLongRange()) {
value = ((Value) value).asIntegerValue().asLong();
} else {
value = ((Value) value).asIntegerValue().asBigInteger();
}
} else if (((Value) value).isStringValue()) {
value = ((Value) value).asStringValue().asString();
}
}
if (value == null) {
return null;
} else if (value instanceof Map) {
List<String> list = new ArrayList<String>();
list.addAll(((Map<String, Object>) value).keySet());
for (String key : list) ((Map<String, Object>) value).put(key, convert(((Map<String, Object>) value).get(key)));
@ -165,18 +228,10 @@ public class YAMLSection {
*/
public void set(String handle, Object value) {
if (Util.isNull(handle)) throw new NullPointerException();
if (value == null) {
remove(handle);
} else if (value instanceof Collection) {
set(handle, (Collection<?>) value);
} else if (value.getClass().isArray()) {
set(handle, (Object[]) value);
} else {
map.put(handle, convert(value));
map.put(handle, convert(value));
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
@ -191,62 +246,6 @@ public class YAMLSection {
if (!contains(handle)) set(handle, value);
}
/**
* Set V[] into this YAML Section
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void set(String handle, V[] array) {
if (Util.isNull(handle, array)) throw new NullPointerException();
List<Object> values = new LinkedList<Object>();
for (V value : array) {
values.add(convert(value));
}
map.put(handle, values);
if (this.handle != null && this.up != null) {
this.up.set(this.handle, this);
}
}
/**
* Set V[] into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param array Value
* @param <V> Array Type
*/
public <V> void safeSet(String handle, V[] array) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, array);
}
/**
* Set Collection&lt;V&gt; into this YAML Section
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void set(String handle, Collection<V> list) {
if (Util.isNull(handle, list)) throw new NullPointerException();
set(handle, list.toArray());
}
/**
* Set Collection&lt;V&gt; into this YAML Section without overwriting existing value
*
* @param handle Handle
* @param list Value
* @param <V> Collection Type
*/
public <V> void safeSet(String handle, Collection<V> list) {
if (Util.isNull(handle)) throw new NullPointerException();
if (!contains(handle)) set(handle, list);
}
/**
* Set All Objects into this YAML Section
*
@ -1055,4 +1054,47 @@ public class YAMLSection {
public String toJSON() {
return new Gson().toJson(get(), Map.class);
}
private Value msgPack(Object value) {
if (value == null) {
return ValueFactory.newNil();
} else if (value instanceof Value) {
return (Value) value;
} else if (value instanceof Map) {
ValueFactory.MapBuilder map = ValueFactory.newMapBuilder();
for (String key : ((Map<String, ?>) value).keySet()) {
Value v = msgPack(((Map<String, ?>) value).get(key));
if (v != null) map.put(ValueFactory.newString(key), v);
}
return map.build();
} else if (value instanceof Collection) {
LinkedList<Value> values = new LinkedList<Value>();
for (Object object : (Collection<?>) value) {
Value v = msgPack(object);
if (v != null) values.add(v);
}
return ValueFactory.newArray(values);
} else if (value instanceof Boolean) {
return ValueFactory.newBoolean((boolean) value);
} else if (value instanceof Number) {
if (((Number) value).doubleValue() == (double)(int) ((Number) value).doubleValue()) {
return ValueFactory.newInteger(((Number) value).longValue());
} else {
return ValueFactory.newFloat(((Number) value).doubleValue());
}
} else if (value instanceof String) {
return ValueFactory.newString((String) value);
} else {
return null;
}
}
/**
* Convert to a MessagePack Map
*
* @return MessagePack Map
*/
public MapValue msgPack() {
return (MapValue) msgPack(get());
}
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Sync.Network;
import net.ME1312.SubServers.Sync.Library.Config.YAMLSection;
import org.msgpack.value.Value;
/**
* SubData Cipher Layout Class
@ -20,7 +21,7 @@ public interface Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
byte[] encrypt(String key, YAMLSection data) throws Exception;
Value encrypt(String key, YAMLSection data) throws Exception;
/**
* Decrypt Encrypted JSON Data
@ -29,5 +30,5 @@ public interface Cipher {
* @param data Encrypted Data Array
* @return JSON Data
*/
YAMLSection decrypt(String key, byte[] data) throws Exception;
YAMLSection decrypt(String key, Value data) throws Exception;
}

View File

@ -2,6 +2,10 @@ package net.ME1312.SubServers.Sync.Network.Encryption;
import com.google.gson.Gson;
import net.ME1312.SubServers.Sync.Library.Config.YAMLSection;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
@ -180,10 +184,15 @@ public final class AES implements net.ME1312.SubServers.Sync.Network.Cipher {
* @param data Data to Encrypt
* @return Encrypted Data Array
*/
public byte[] encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(data.toJSON().getBytes(StandardCharsets.UTF_8)), bytes);
return bytes.toByteArray();
public Value encrypt(String key, YAMLSection data) throws Exception {
ByteArrayOutputStream unencrypted = new ByteArrayOutputStream();
MessagePacker packer = MessagePack.newDefaultPacker(unencrypted);
packer.packValue(data.msgPack());
packer.close();
ByteArrayOutputStream encrypted = new ByteArrayOutputStream();
encrypt(keyLength, key, new ByteArrayInputStream(unencrypted.toByteArray()), encrypted);
return ValueFactory.newBinary(encrypted.toByteArray());
}
public String getName() {
@ -271,10 +280,10 @@ public final class AES implements net.ME1312.SubServers.Sync.Network.Cipher {
* @return JSON Data
*/
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) throws Exception {
public YAMLSection decrypt(String key, Value data) throws Exception {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
decrypt(key, new ByteArrayInputStream(data), bytes);
return new YAMLSection(new Gson().fromJson(new String(bytes.toByteArray(), StandardCharsets.UTF_8), Map.class));
decrypt(key, new ByteArrayInputStream(data.asBinaryValue().asByteArray()), bytes);
return new YAMLSection(MessagePack.newDefaultUnpacker(bytes.toByteArray()).unpackValue().asMapValue());
}
/**

View File

@ -41,7 +41,7 @@ public class PacketDownloadGroupInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("group", group);
if (group != null) json.set("group", group);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadHostInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("host", host);
if (host != null) json.set("host", host);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadProxyInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("proxy", proxy);
if (proxy != null) json.set("proxy", proxy);
return json;
}

View File

@ -41,7 +41,7 @@ public class PacketDownloadServerInfo implements PacketIn, PacketOut {
public YAMLSection generate() {
YAMLSection json = new YAMLSection();
json.set("id", id);
json.set("server", server);
if (server != null) json.set("server", server);
return json;
}

View File

@ -15,6 +15,11 @@ import net.ME1312.SubServers.Sync.Network.Packet.*;
import net.ME1312.SubServers.Sync.SubPlugin;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.conf.Configuration;
import org.msgpack.core.MessageInsufficientBufferException;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;
import org.msgpack.value.Value;
import org.yaml.snakeyaml.error.YAMLException;
import java.io.BufferedReader;
@ -38,7 +43,7 @@ public final class SubDataClient {
private static HashMap<String, HashMap<String, List<PacketIn>>> pIn = new HashMap<String, HashMap<String, List<PacketIn>>>();
private static HashMap<String, Cipher> ciphers = new HashMap<String, Cipher>();
private static boolean defaults = false;
private PrintWriter writer;
private MessagePacker out;
private NamedContainer<Boolean, Socket> socket;
private String name = null;
private Cipher cipher;
@ -59,20 +64,20 @@ public final class SubDataClient {
socket = new NamedContainer<>(false, new Socket(address, port));
this.plugin = plugin;
this.name = name;
this.writer = new PrintWriter(socket.get().getOutputStream(), true);
this.out = MessagePack.newDefaultPacker(socket.get().getOutputStream());
this.cipher = (cipher != null)?cipher:new Cipher() {
@Override
public String getName() {
return "NONE";
}
@Override
public byte[] encrypt(String key, YAMLSection data) {
return data.toJSON().getBytes(StandardCharsets.UTF_8);
public Value encrypt(String key, YAMLSection data) {
return data.msgPack();
}
@Override
@SuppressWarnings("unchecked")
public YAMLSection decrypt(String key, byte[] data) {
return new YAMLSection(new Gson().fromJson(new String(data, StandardCharsets.UTF_8), Map.class));
public YAMLSection decrypt(String key, Value data) {
return new YAMLSection(data.asMapValue());
}
};
this.queue = new LinkedList<NamedContainer<String, PacketOut>>();
@ -166,11 +171,11 @@ public final class SubDataClient {
private void loop() {
new Thread(() -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.get().getInputStream()));
String input;
while ((input = in.readLine()) != null) {
MessageUnpacker in = MessagePack.newDefaultUnpacker(socket.get().getInputStream());
Value input;
while ((input = in.unpackValue()) != null) {
try {
YAMLSection data = cipher.decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), Base64.getDecoder().decode(input));
YAMLSection data = cipher.decrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), input);
for (PacketIn packet : decodePacket(data)) {
try {
packet.execute((data.contains("c")) ? data.getSection("c") : null);
@ -192,7 +197,7 @@ public final class SubDataClient {
e1.printStackTrace();
}
} catch (Exception e) {
if (!(e instanceof SocketException)) e.printStackTrace();
if (!(e instanceof SocketException || e instanceof MessageInsufficientBufferException)) e.printStackTrace();
try {
destroy(plugin.config.get().getSection("Settings").getSection("SubData").getInt("Reconnect", 30));
} catch (IOException e1) {
@ -366,7 +371,8 @@ public final class SubDataClient {
try {
YAMLSection data = encodePacket(packet.get());
if (packet.name() != null) data.set("f", packet.name());
writer.println(Base64.getEncoder().encodeToString(cipher.encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data)));
out.packValue(getCipher().encrypt(plugin.config.get().getSection("Settings").getSection("SubData").getRawString("Password"), data));
out.flush();
} catch (Throwable e) {
e.printStackTrace();
}