mirror of
https://github.com/TimeCrafters/TimeCraftersConfigurationTool.git
synced 2025-12-15 05:02:33 +00:00
Initial TACNET Config syncing is now working
This commit is contained in:
@@ -11,7 +11,9 @@ import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.R;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Action;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Configuration;
|
||||
@@ -32,6 +34,7 @@ import org.timecrafters.TimeCraftersConfigurationTool.serializers.SettingsDeseri
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.serializers.SettingsSerializer;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.serializers.VariableDeserializer;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.serializers.VariableSerializer;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.tacnet.PacketHandler;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.tacnet.Server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -135,6 +138,14 @@ public class Backend {
|
||||
configChanged = true;
|
||||
|
||||
saveConfig();
|
||||
|
||||
/* Automatically upload whole config to server
|
||||
* TODO: Implement a more atomic remote config updating
|
||||
* */
|
||||
if (config != null && tacnet.isConnected()) {
|
||||
String json = gsonForConfig().toJson(config);
|
||||
tacnet.puts(PacketHandler.packetUploadConfig(config.getName(), json).toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasConfigChanged() { return configChanged; }
|
||||
@@ -158,6 +169,34 @@ public class Backend {
|
||||
}
|
||||
}
|
||||
|
||||
public Config loadConfigWithoutMutatingBackend(String name) {
|
||||
if (name.equals("")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String path = configPath(name);
|
||||
File file = new File(path);
|
||||
|
||||
if (file.exists() && file.isFile()) {
|
||||
Config config = gsonForConfig().fromJson(readFromFile(path), Config.class);
|
||||
config.setName(name);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isConfigValid(String json) {
|
||||
try {
|
||||
gsonForConfig().fromJson(json, Config.class);
|
||||
|
||||
return true;
|
||||
} catch (JsonSyntaxException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean saveConfig() {
|
||||
if (config == null) { return false; }
|
||||
|
||||
@@ -193,19 +232,6 @@ public class Backend {
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
public void uploadConfig() {
|
||||
if (config != null && tacnet.isConnected()) {
|
||||
String json = "";
|
||||
// tacnet.puts(PacketHandler.packetUploadConfig(json));
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadConfig() {
|
||||
if (config != null && tacnet.isConnected()) {
|
||||
// tacnet.puts(PacketHandler.packetDownloadConfig());
|
||||
}
|
||||
}
|
||||
|
||||
public void writeNewConfig(String name) {
|
||||
String path = configPath(name);
|
||||
File file = new File(path);
|
||||
|
||||
@@ -11,6 +11,16 @@ public class Group {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public static boolean nameIsUnique(ArrayList<Group> groups, String name) {
|
||||
for (Group group: groups) {
|
||||
if (group.name.equals(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ArrayList<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import java.util.Arrays;
|
||||
|
||||
public class Packet {
|
||||
final static public String PROTOCOL_VERSION = "1";
|
||||
final static public String PROTOCOL_HEADER_SEPERATOR = "|";
|
||||
final static public String PROTOCOL_SEPERATOR = "|";
|
||||
final static public String PROTOCOL_HEARTBEAT = "heartbeat";
|
||||
private static final String TAG = "TACNET|Packet";
|
||||
|
||||
@@ -21,9 +21,10 @@ public class Packet {
|
||||
DOWNLOAD_CONFIG(10),
|
||||
UPLOAD_CONFIG(11),
|
||||
LIST_CONFIGS(12),
|
||||
ADD_CONFIG(13),
|
||||
UPDATE_CONFIG(14),
|
||||
DELETE_CONFIG(15),
|
||||
SELECT_CONFIG(13),
|
||||
ADD_CONFIG(14),
|
||||
UPDATE_CONFIG(15),
|
||||
DELETE_CONFIG(16),
|
||||
|
||||
ADD_GROUP(20),
|
||||
UPDATE_GROUP(21),
|
||||
@@ -70,7 +71,7 @@ public class Packet {
|
||||
String[] slice = message.split("\\|", 4);
|
||||
|
||||
if (slice.length < 4) {
|
||||
Log.i(TAG, "Failed to split packet along first 4 " + PROTOCOL_HEADER_SEPERATOR + ". Raw return: " + Arrays.toString(slice));
|
||||
Log.i(TAG, "Failed to split packet along first 4 " + PROTOCOL_SEPERATOR + ". Raw return: " + Arrays.toString(slice));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ public class Packet {
|
||||
return true;
|
||||
}
|
||||
|
||||
String[] parts = rawMessage.split(PROTOCOL_HEADER_SEPERATOR);
|
||||
String[] parts = rawMessage.split(PROTOCOL_SEPERATOR);
|
||||
|
||||
return parts[0].equals(PROTOCOL_VERSION) &&
|
||||
isPacketTypeValid( Integer.parseInt(parts[1]));
|
||||
@@ -121,11 +122,11 @@ public class Packet {
|
||||
public String encodeHeader() {
|
||||
String string = "";
|
||||
string += PROTOCOL_VERSION;
|
||||
string += PROTOCOL_HEADER_SEPERATOR;
|
||||
string += PROTOCOL_SEPERATOR;
|
||||
string += packetType.getId();
|
||||
string += PROTOCOL_HEADER_SEPERATOR;
|
||||
string += PROTOCOL_SEPERATOR;
|
||||
string += contentLength;
|
||||
string += PROTOCOL_HEADER_SEPERATOR;
|
||||
string += PROTOCOL_SEPERATOR;
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,13 @@ package org.timecrafters.TimeCraftersConfigurationTool.tacnet;
|
||||
import android.util.Log;
|
||||
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.Config;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.TAC;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Action;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.config.Group;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PacketHandler {
|
||||
@@ -45,8 +48,8 @@ public class PacketHandler {
|
||||
}
|
||||
|
||||
case ERROR: {
|
||||
// handleHeartBeat(packet);
|
||||
// return;
|
||||
handleError(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
case DOWNLOAD_CONFIG: {
|
||||
@@ -59,13 +62,32 @@ public class PacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
case LIST_CONFIGS: {
|
||||
handleListConfigs(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
case ADD_CONFIG: {
|
||||
handleAddConfig(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
case UPDATE_CONFIG: {
|
||||
handleUpdateConfig(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
case DELETE_CONFIG: {
|
||||
handleDeleteConfig(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
// case CHANGE_ACTION: {
|
||||
// handleChangeAction(packet);
|
||||
// return;
|
||||
// }
|
||||
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,20 +96,21 @@ public class PacketHandler {
|
||||
private void handleHandShake(Packet packet) {}
|
||||
// NO-OP
|
||||
private void handleHeartBeat(Packet packet) {}
|
||||
// NO-OP
|
||||
private void handleError(Packet packet) {}
|
||||
|
||||
private void handleUploadConfig(Packet packet) {
|
||||
String[] split = packet.getContent().split("\\" + Packet.PROTOCOL_HEADER_SEPERATOR, 2);
|
||||
String[] split = packet.getContent().split("\\" + Packet.PROTOCOL_SEPERATOR, 2);
|
||||
final String configName = split[0];
|
||||
final String json = split[1];
|
||||
if (configName.length() == 0 && false) { //!Backend.instance().configIsValid(json)) {
|
||||
return;
|
||||
}
|
||||
if (configName.length() == 0) {
|
||||
|
||||
if (configName.length() == 0 && !Backend.instance().isConfigValid(json)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String path = TAC.CONFIGS_PATH + File.separator + configName + ".json";
|
||||
|
||||
Log.i(TAG, "Got valid json: " + packet.getContent());
|
||||
Log.i(TAG, "Got valid json: " + json);
|
||||
|
||||
Backend.instance().writeToFile(path, json);
|
||||
}
|
||||
@@ -101,27 +124,152 @@ public class PacketHandler {
|
||||
final String path = TAC.CONFIGS_PATH + File.separator + configName + ".json";
|
||||
|
||||
String content = Backend.instance().readFromFile(path);
|
||||
Packet.create(Packet.PacketType.UPLOAD_CONFIG, content);
|
||||
} else { // Errored
|
||||
final String content = "ERROR";
|
||||
Packet.create(Packet.PacketType.ERROR, content);
|
||||
pkt = packetUploadConfig(configName, content);
|
||||
} else { // Error
|
||||
pkt = packetError("Remote config not found", "The requested config " + configName + " does not exist over here.");
|
||||
}
|
||||
|
||||
if (hostIsAConnection) {
|
||||
Backend.instance().tacnet().puts(packet.toString());
|
||||
Backend.instance().tacnet().puts(pkt.toString());
|
||||
} else {
|
||||
Backend.instance().getServer().getActiveClient().puts(packet.toString());
|
||||
Backend.instance().getServer().getActiveClient().puts(pkt.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChangeAction(Packet packet) {
|
||||
// TODO: Handle renaming, deleting, and adding.
|
||||
// TODO: reply with config_name,456|other_config,10 (config name,revision)
|
||||
private void handleListConfigs(Packet packet) {
|
||||
if (hostIsAConnection) {
|
||||
final String[] remoteConfigs = packet.getContent().split("\\" + Packet.PROTOCOL_SEPERATOR);
|
||||
ArrayList<String> diff = Backend.instance().configsList();
|
||||
|
||||
for (String part : remoteConfigs) {
|
||||
final String[] configInfo = part.split(",", 2);
|
||||
final String name = configInfo[0];
|
||||
final int revision = Integer.parseInt(configInfo[1]);
|
||||
|
||||
diff.remove(name);
|
||||
|
||||
File file = new File(Backend.instance().configPath(name));
|
||||
|
||||
if (file.exists()) {
|
||||
final Config config = Backend.instance().loadConfigWithoutMutatingBackend(name);
|
||||
|
||||
if (config.getConfiguration().revision < revision) {
|
||||
Log.i(TAG, "handleListConfigs: requesting config: " + name + " since local " + config.getName() + " is @ " + config.getConfiguration().revision);
|
||||
Backend.instance().tacnet().puts(PacketHandler.packetDownloadConfig(name).toString());
|
||||
} else if (config.getConfiguration().revision > revision) {
|
||||
Log.i(TAG, "handleListConfigs: sending config: " + name + " since local " + config.getName() + " is @ " + config.getConfiguration().revision);
|
||||
Backend.instance().tacnet().puts(PacketHandler.packetUploadConfig(name, Backend.instance().gsonForConfig().toJson(config)).toString());
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "handleListConfigs: requesting config: " + name + " since there is no local file with that name");
|
||||
|
||||
Backend.instance().tacnet().puts( PacketHandler.packetDownloadConfig(name).toString() );
|
||||
}
|
||||
}
|
||||
|
||||
for (String name : diff) {
|
||||
final Config config = Backend.instance().loadConfigWithoutMutatingBackend(name);
|
||||
|
||||
Backend.instance().tacnet().puts(PacketHandler.packetUploadConfig(name, Backend.instance().gsonForConfig().toJson(config)).toString());
|
||||
}
|
||||
|
||||
} else {
|
||||
Backend.instance().getServer().getActiveClient().puts(PacketHandler.packetListConfigs().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChangeVariable(Packet packet) {
|
||||
// TODO: Handle renaming, deleting, and adding.
|
||||
private void handleSelectConfig(Packet packet) {
|
||||
final String configName = packet.getContent();
|
||||
|
||||
Backend.instance().getSettings().config = configName;
|
||||
Backend.instance().saveSettings();
|
||||
Backend.instance().loadConfig(configName);
|
||||
}
|
||||
|
||||
private void handleAddConfig(Packet packet) {
|
||||
final String configName = packet.getContent();
|
||||
|
||||
if (Backend.instance().configsList().contains(configName)) {
|
||||
if (!hostIsAConnection) {
|
||||
Backend.instance().getServer().getActiveClient().puts(
|
||||
packetError("Config already exists!", "A config with the name " +
|
||||
configName + " already exists here.").toString()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Backend.instance().writeNewConfig(configName);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUpdateConfig(Packet packet) {
|
||||
final String[] split = packet.getContent().split("\\" + Packet.PROTOCOL_SEPERATOR, 2);
|
||||
final String oldConfigName = split[0];
|
||||
final String newConfigName = split[1];
|
||||
|
||||
if (Backend.instance().configsList().contains(newConfigName)) {
|
||||
if (!hostIsAConnection) {
|
||||
Backend.instance().getServer().getActiveClient().puts(
|
||||
packetError("Config already exists!", "A config with the name " +
|
||||
newConfigName + " already exists here.").toString()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Backend.instance().moveConfig(oldConfigName, newConfigName);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeleteConfig(Packet packet) {
|
||||
final String configName = packet.getContent();
|
||||
|
||||
Backend.instance().deleteConfig(configName);
|
||||
}
|
||||
|
||||
private void handleAddGroup(Packet packet) {
|
||||
final String[] split = packet.getContent().split("\\" + Packet.PROTOCOL_SEPERATOR, 2);
|
||||
final String configName = packet.getContent();
|
||||
final String groupName = packet.getContent();
|
||||
|
||||
if (Backend.instance().getConfig().getName().equals(configName)) {
|
||||
if (Group.nameIsUnique(Backend.instance().getConfig().getGroups(), groupName)) {
|
||||
Group group = new Group(groupName, new ArrayList<Action>());
|
||||
Backend.instance().getConfig().getGroups().add(group);
|
||||
} else {
|
||||
Backend.instance().getServer().getActiveClient().puts(
|
||||
packetError("Group name collision", "A group with the name " + groupName + " already exists").toString()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
Backend.instance().getServer().getActiveClient().puts(
|
||||
packetError("Active config mismatch", "Active config is not " + configName).toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUpdateGroup(Packet packet) {}
|
||||
|
||||
private void handleDeleteGroup(Packet packet) {}
|
||||
|
||||
private void handleAddAction(Packet packet) {}
|
||||
|
||||
private void handleChangeAction(Packet packet) {
|
||||
// TODO: Handle renaming action and updating comment.
|
||||
}
|
||||
|
||||
private void handleDeleteAction(Packet packet) {}
|
||||
|
||||
private void handleAddVariable(Packet packet) {}
|
||||
|
||||
private void handleUpdateVariable(Packet packet) {}
|
||||
|
||||
private void handleChangeVariable(Packet packet) {}
|
||||
|
||||
private void handleDeleteVariable(Packet packet) {}
|
||||
|
||||
/**************************************
|
||||
PACKET HELPER FUNCTIONS
|
||||
**************************************/
|
||||
|
||||
static public Packet packetHandShake(String clientUUID) {
|
||||
return Packet.create(Packet.PacketType.HANDSHAKE, clientUUID);
|
||||
}
|
||||
@@ -130,9 +278,98 @@ public class PacketHandler {
|
||||
return Packet.create(Packet.PacketType.HEARTBEAT, Packet.PROTOCOL_HEARTBEAT);
|
||||
}
|
||||
|
||||
// static public Packet packetDumpConfig(String string) {
|
||||
// string = string.replace("\n", " ");
|
||||
//
|
||||
// return Packet.create(Packet.PacketType.DUMP_CONFIG, string);
|
||||
// }
|
||||
static private Packet packetError(String errorTitle, String errorMessage) {
|
||||
return Packet.create(Packet.PacketType.ERROR, errorTitle + Packet.PROTOCOL_SEPERATOR + errorMessage);
|
||||
}
|
||||
|
||||
static public Packet packetUploadConfig(String configName, String json) {
|
||||
return Packet.create(Packet.PacketType.UPLOAD_CONFIG, configName + Packet.PROTOCOL_SEPERATOR + json);
|
||||
}
|
||||
|
||||
static public Packet packetDownloadConfig(String configName) {
|
||||
return Packet.create(Packet.PacketType.DOWNLOAD_CONFIG, configName);
|
||||
}
|
||||
|
||||
static public Packet packetListConfigs() {
|
||||
String configsList = "";
|
||||
final ArrayList<String> configs = Backend.instance().configsList();
|
||||
|
||||
int i = 0;
|
||||
for (final String configName : configs) {
|
||||
final String path = Backend.instance().configPath(configName);
|
||||
Config config = Backend.instance().gsonForConfig().fromJson(Backend.instance().readFromFile(path), Config.class);
|
||||
|
||||
configsList += configName + "," + config.getConfiguration().revision;
|
||||
|
||||
if (i != configs.size() - 1) {
|
||||
configsList += Packet.PROTOCOL_SEPERATOR;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return Packet.create(Packet.PacketType.LIST_CONFIGS, configsList);
|
||||
}
|
||||
|
||||
static public Packet packetSelectConfig(String configName) {
|
||||
return Packet.create(Packet.PacketType.SELECT_CONFIG, configName);
|
||||
}
|
||||
|
||||
static public Packet packetAddConfig(String configName) {
|
||||
return Packet.create(Packet.PacketType.ADD_CONFIG, configName);
|
||||
}
|
||||
|
||||
static public Packet packetUpdateConfig(String oldConfigName, String newConfigName) {
|
||||
return Packet.create(Packet.PacketType.UPDATE_CONFIG, oldConfigName + Packet.PROTOCOL_SEPERATOR + newConfigName);
|
||||
}
|
||||
|
||||
static public Packet packetDeleteConfig(String configName) {
|
||||
return Packet.create(Packet.PacketType.DELETE_CONFIG, configName);
|
||||
}
|
||||
|
||||
static public Packet packetAddGroup(String configName, String groupName) {
|
||||
return Packet.create(Packet.PacketType.ADD_GROUP, configName + Packet.PROTOCOL_SEPERATOR + groupName);
|
||||
}
|
||||
|
||||
static public Packet packetUpdateGroup(String configName, String oldGroupName, String newGroupName) {
|
||||
return Packet.create(Packet.PacketType.UPDATE_GROUP, configName + Packet.PROTOCOL_SEPERATOR +
|
||||
oldGroupName + Packet.PROTOCOL_SEPERATOR + newGroupName);
|
||||
}
|
||||
|
||||
static public Packet packetDeleteGroup(String configName, String groupName) {
|
||||
return Packet.create(Packet.PacketType.DELETE_GROUP, configName + Packet.PROTOCOL_SEPERATOR + groupName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
static public Packet packetAddAction(String configName, String groupName, String actionName) {
|
||||
return Packet.create(Packet.PacketType.ADD_ACTION, configName + Packet.PROTOCOL_SEPERATOR + groupName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
static public Packet packetUpdateAction(String configName, String oldGroupName, String newGroupName) {
|
||||
return Packet.create(Packet.PacketType.UPDATE_ACTION, configName + Packet.PROTOCOL_SEPERATOR +
|
||||
oldGroupName + Packet.PROTOCOL_SEPERATOR + newGroupName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
static public Packet packetDeleteAction(String configName, String groupName) {
|
||||
return Packet.create(Packet.PacketType.DELETE_ACTION, configName + Packet.PROTOCOL_SEPERATOR + groupName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
static public Packet packetAddVariable(String configName, String groupName) {
|
||||
return Packet.create(Packet.PacketType.ADD_VARIABLE, configName + Packet.PROTOCOL_SEPERATOR + groupName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
static public Packet packetUpdateVariable(String configName, String oldGroupName, String newGroupName) {
|
||||
return Packet.create(Packet.PacketType.UPDATE_VARIABLE, configName + Packet.PROTOCOL_SEPERATOR +
|
||||
oldGroupName + Packet.PROTOCOL_SEPERATOR + newGroupName);
|
||||
}
|
||||
|
||||
static public Packet packetDeleteVariable(String configName, String groupName, String actionName, String variableName) {
|
||||
return Packet.create(Packet.PacketType.DELETE_VARIABLE, configName + Packet.PROTOCOL_SEPERATOR + groupName +
|
||||
Packet.PROTOCOL_SEPERATOR + actionName +
|
||||
Packet.PROTOCOL_SEPERATOR + variableName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +78,10 @@ public class Server {
|
||||
client.close("Too many clients!");
|
||||
|
||||
} else {
|
||||
// Writer.writeJSON(Writer.getBackupConfigFilePath(), AppSync.getDataStructs());
|
||||
|
||||
this.activeClient = client;
|
||||
// AppSync.getMainActivity().clientConnected();
|
||||
|
||||
activeClient.puts(PacketHandler.packetHandShake( activeClient.uuid() ).toString());
|
||||
// activeClient.puts(PacketHandler.packetDumpConfig( Reader.rawConfigFile() ).toString());
|
||||
activeClient.puts(PacketHandler.packetListConfigs().toString());
|
||||
|
||||
Log.i(TAG, "Client connected!");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user