Initial TACNET Config syncing is now working

This commit is contained in:
2020-09-09 14:20:15 -05:00
parent 5c5b26229c
commit bbf7a5b57a
5 changed files with 322 additions and 51 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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!");