|
@@ -0,0 +1,396 @@
|
|
|
+#include "../include/batchioman.h"
|
|
|
+
|
|
|
+#include <iostream>
|
|
|
+#include <vector>
|
|
|
+#include <string>
|
|
|
+
|
|
|
+BatchIoMan::BatchIoMan(char *ipcstring) : IoMan(ipcstring) {};
|
|
|
+
|
|
|
+BatchIoMan::BatchIoMan(char *ipcstring, bool usessl, std::string batchpath) : IoMan(ipcstring, usessl) {
|
|
|
+ batchin.open(batchpath);
|
|
|
+ normalout.open(batchpath + ".out");
|
|
|
+ debugout.open(batchpath + ".debug");
|
|
|
+ errorout.open(batchpath + ".err");
|
|
|
+
|
|
|
+ /* setup json stuff */
|
|
|
+ Json::CharReaderBuilder rbuilder;
|
|
|
+ wbuilder.settings_["indentation"] = "";
|
|
|
+ reader = rbuilder.newCharReader();
|
|
|
+
|
|
|
+ /* initialize print command map */
|
|
|
+ printmap["error"] = &BatchIoMan::printError;
|
|
|
+ printmap["connect"] = &BatchIoMan::printConnect;
|
|
|
+ printmap["help"] = &BatchIoMan::printHelp;
|
|
|
+ printmap["status"] = &BatchIoMan::printStatus;
|
|
|
+ printmap["disconnect"] = &BatchIoMan::printDisconnect;
|
|
|
+ printmap["put"] = &BatchIoMan::printPut;
|
|
|
+ printmap["get"] = &BatchIoMan::printGet;
|
|
|
+ printmap["list"] = &BatchIoMan::printList;
|
|
|
+ printmap["version"] = &BatchIoMan::printVersion;
|
|
|
+ printmap["login"] = &BatchIoMan::printLogin;
|
|
|
+ printmap["signup"] = &BatchIoMan::printSignup;
|
|
|
+ printmap["putdata"] = &BatchIoMan::printPutdata;
|
|
|
+ printmap["getdata"] = &BatchIoMan::printGetdata;
|
|
|
+ printmap["head"] = &BatchIoMan::printHead;
|
|
|
+ printmap["deletefile"] = &BatchIoMan::printDeletefile;
|
|
|
+ printmap["deleteme"] = &BatchIoMan::printDeleteme;
|
|
|
+ printmap["keyfile"] = &BatchIoMan::printKeyfile;
|
|
|
+ printmap["closekey"] = &BatchIoMan::printClosekey;
|
|
|
+
|
|
|
+ getnextline = false;
|
|
|
+}
|
|
|
+
|
|
|
+bool BatchIoMan::init() {
|
|
|
+ if(!batchin.is_open() || !normalout.is_open() || !debugout.is_open() || !errorout.is_open()) return false;
|
|
|
+ return IoMan::init();
|
|
|
+}
|
|
|
+
|
|
|
+BatchIoMan::~BatchIoMan() {
|
|
|
+ batchin.close();
|
|
|
+ normalout.close();
|
|
|
+ debugout.close();
|
|
|
+ errorout.close();
|
|
|
+ delete reader;
|
|
|
+}
|
|
|
+
|
|
|
+void BatchIoMan::printMessage(std::string msg, OutMsgType type) {
|
|
|
+ Json::Value root;
|
|
|
+ msgmutex.lock();
|
|
|
+ switch (type) {
|
|
|
+ case normal: {
|
|
|
+ // this should never happen outside of development
|
|
|
+ if (!reader->parse(msg.c_str(), msg.c_str() + msg.size(), &root, &jsonerror)) {
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + " couldnt parse json data: " + jsonerror, debug);
|
|
|
+ } else {
|
|
|
+ normalout << printJson(root) << std::endl;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case error: {
|
|
|
+ // this should never happen outside of development
|
|
|
+ if (!reader->parse(msg.c_str(), msg.c_str() + msg.size(), &root, &jsonerror)) {
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + " couldnt parse json data: " + jsonerror, debug);
|
|
|
+ } else {
|
|
|
+ errorout << printJson(root) << std::endl;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case debug: {
|
|
|
+ debugout << msg << std::endl;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ msgmutex.unlock();
|
|
|
+}
|
|
|
+
|
|
|
+void BatchIoMan::printWelcomeMessage() {}
|
|
|
+
|
|
|
+std::string BatchIoMan::getCmdPrompt() { return ""; }
|
|
|
+
|
|
|
+/* modified handleInCmdResponse to abort on error */
|
|
|
+void BatchIoMan::handleInCmdResponse(CmdMan::CmdRet cmdret) {
|
|
|
+ // determine wether to send something and do so if required
|
|
|
+ if (cmdret.type & CmdMan::rettype::print) {
|
|
|
+ printMessage(Json::writeString(wbuilder, cmdret.msg), normal);
|
|
|
+ if(!(cmdret.type ^ CmdMan::rettype::print)) {
|
|
|
+ // xor here works because flag is set at this point
|
|
|
+ // if we only printed something get the next line
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::send) {
|
|
|
+ printMessage("IoMan::inputMain() sending json \"" + Json::writeString(wbuilder, cmdret.msg) + "\"", debug);
|
|
|
+ if(usessl) boost::asio::write(*sslsock, boost::asio::buffer(Json::writeString(wbuilder, cmdret.msg) + "\n"), errcode);
|
|
|
+ else boost::asio::write(*tcpsock, boost::asio::buffer(Json::writeString(wbuilder, cmdret.msg) + "\n"), errcode);
|
|
|
+ if (errcode) {
|
|
|
+ printMessage("IoMan::inputMain() couldnt send json data\n" + errcode.message() + "\n", error);
|
|
|
+ mainmutex.lock();
|
|
|
+ runmain = false;
|
|
|
+ mainmutex.unlock();
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::error) {
|
|
|
+ printMessage(Json::writeString(wbuilder, cmdret.msg), error);
|
|
|
+ mainmutex.lock();
|
|
|
+ runmain = false;
|
|
|
+ mainmutex.unlock();
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::close) {
|
|
|
+ /* TODO i dunno */
|
|
|
+ mainmutex.lock();
|
|
|
+ runmain = false;
|
|
|
+ mainmutex.unlock();
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* modified handleOutCmdResponse to fetch next command and abort on error */
|
|
|
+void BatchIoMan::handleOutCmdResponse(CmdMan::CmdRet cmdret, std::vector<std::string> &toput) {
|
|
|
+ if (cmdret.type & CmdMan::rettype::close) {
|
|
|
+ /* TODO i dunno */
|
|
|
+ mainmutex.lock();
|
|
|
+ runmain = false;
|
|
|
+ mainmutex.unlock();
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::error) {
|
|
|
+ initmutex.lock();
|
|
|
+ if (versionstatus == off)
|
|
|
+ versionstatus = err;
|
|
|
+ else if (loginstatus == off)
|
|
|
+ loginstatus = err;
|
|
|
+ initmutex.unlock();
|
|
|
+ initcv.notify_all();
|
|
|
+ printMessage(Json::writeString(wbuilder, cmdret.msg), error);
|
|
|
+ mainmutex.lock();
|
|
|
+ runmain = false;
|
|
|
+ mainmutex.unlock();
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::seton) {
|
|
|
+ initmutex.lock();
|
|
|
+ if (versionstatus == off)
|
|
|
+ versionstatus = on;
|
|
|
+ else
|
|
|
+ loginstatus = on;
|
|
|
+ initmutex.unlock();
|
|
|
+ initcv.notify_all();
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::print) {
|
|
|
+ printMessage(Json::writeString(wbuilder, cmdret.msg), normal);
|
|
|
+ }
|
|
|
+ if (cmdret.type & CmdMan::rettype::send) {
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" send new cmd"), debug);
|
|
|
+ if (cmdret.nextcommand.size()) {
|
|
|
+ toput.push_back(cmdret.nextcommand);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(versionstatus == on && !(cmdret.type & CmdMan::rettype::send)) {
|
|
|
+ // only fetch next line if we did not send a new command on our own
|
|
|
+ // if we managed to get here, get next command from file
|
|
|
+ linemutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get linemutex"), debug);
|
|
|
+ getnextline = true;
|
|
|
+ linemutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release linemutex"), debug);
|
|
|
+ linecv.notify_all();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* main user input loop */
|
|
|
+void BatchIoMan::run() {
|
|
|
+ std::string line;
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + " begin", debug);
|
|
|
+ std::unique_lock<std::mutex> ulock;
|
|
|
+
|
|
|
+ runmain = true;
|
|
|
+
|
|
|
+ mainmutex.lock();
|
|
|
+ while (runmain) {
|
|
|
+ mainmutex.unlock();
|
|
|
+
|
|
|
+ line.erase();
|
|
|
+ ulock = std::unique_lock<std::mutex>(linemutex);
|
|
|
+ while (!getnextline && runmain) {
|
|
|
+ linecv.wait(ulock);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!runmain) break;
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + " fetch next line", debug);
|
|
|
+ while(!line.size()) {
|
|
|
+ // skip empty lines until either eof or non-empty line
|
|
|
+ if(batchin.eof()) {
|
|
|
+ line = "disconnect";
|
|
|
+ }
|
|
|
+ else std::getline(batchin, line);
|
|
|
+ }
|
|
|
+
|
|
|
+ getnextline = false;
|
|
|
+ linemutex.unlock();
|
|
|
+
|
|
|
+ localmutex.lock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"), debug);
|
|
|
+ localinput.push_back(line);
|
|
|
+ localmutex.unlock();
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"), debug);
|
|
|
+ localcv.notify_all();
|
|
|
+
|
|
|
+ if (!connected)
|
|
|
+ break;
|
|
|
+ if (loginstatus == err)
|
|
|
+ break;
|
|
|
+
|
|
|
+ mainmutex.lock();
|
|
|
+ }
|
|
|
+ mainmutex.unlock();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+std::string BatchIoMan::printJson(Json::Value root) {
|
|
|
+ map<string, std::string (BatchIoMan::*)(Json::Value)>::iterator it = printmap.find(root["command"].asString());
|
|
|
+ if (it == printmap.end()) {
|
|
|
+ // this should never happen outside of development
|
|
|
+ printMessage(string(__PRETTY_FUNCTION__) + " unknown command \"" + root["command"].asString() + "\".\nensure code is implemented.", debug);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return (this->*(printmap[root["command"].asString()]))(root);
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printError(Json::Value root) { return std::string("Error: ") + root["error"].asString(); }
|
|
|
+
|
|
|
+std::string BatchIoMan::printConnect(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return std::string("Couldnt connect to ") + root["address"].asString() + ":" + std::to_string(root["port"].asUInt()) + "\n"
|
|
|
+ + "Reason: " + root["error"].asString();
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printHelp(Json::Value root) {
|
|
|
+ std::string ret = std::string("Available commands are: ") + "\n";
|
|
|
+ for (Json::Value i : root["names"])
|
|
|
+ ret += i.asString() + "\n";
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printStatus(Json::Value root) { return std::string("Server reports status: ") + root["response"].asString(); }
|
|
|
+
|
|
|
+std::string BatchIoMan::printDisconnect(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return "Disconnect failed.";
|
|
|
+ } else {
|
|
|
+ return "Disconnect successful.";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printPut(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ if (root.isMember("file")) {
|
|
|
+ return std::string("Upload request for file ") + root["file"].asString() + " failed: " + root["error"].asString();
|
|
|
+ } else {
|
|
|
+ return std::string("Upload request failed: ") + root["error"].asString();
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ return std::string("Begin uploading file ") + root["file"].asString();
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printGet(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ if (root.isMember("file")) {
|
|
|
+ return std::string("Download request for file ") + root["file"].asString() + " failed: " + root["error"].asString();
|
|
|
+ } else {
|
|
|
+ return std::string("Download request failed: ") + root["error"].asString();
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ return std::string("Begin downloading file ") + root["file"].asString();
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printList(Json::Value root) {
|
|
|
+ std::string ret;
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ ret = std::string("Listing files failed: ") + root["error"].asString();
|
|
|
+ } else {
|
|
|
+ ret = std::string("Listing files stored on server: ") + "\n";
|
|
|
+ for (Json::Value i : root["names"])
|
|
|
+ ret += i.asString() + "\n";
|
|
|
+ ret += "End of list.";
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printVersion(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return std::string("Version check failed. Server reports ") + root["serverversion"].asString() + " but client is " + root["clientversion"].asString();
|
|
|
+ } else
|
|
|
+ return "Version check ok.";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printLogin(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return std::string("Login failed: ") + root["error"].asString();
|
|
|
+ } else
|
|
|
+ return "Login ok.";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printSignup(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return std::string("Signup failed: ") + root["error"].asString();
|
|
|
+ } else
|
|
|
+ return "Signup ok. You are now logged in.";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printDeleteme(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool()) {
|
|
|
+ return std::string("User deletion failed: ") + root["error"].asString();
|
|
|
+ } else
|
|
|
+ return "User deletion ok. You are now disconnected from the server.";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printPutdata(Json::Value root) { return ""; }
|
|
|
+
|
|
|
+std::string BatchIoMan::printGetdata(Json::Value root) { return ""; }
|
|
|
+
|
|
|
+std::string BatchIoMan::printListdata(Json::Value root) { return ""; }
|
|
|
+
|
|
|
+std::string BatchIoMan::printHead(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool())
|
|
|
+ return std::string("Request of the first four bytes failed. ") + root["error"].asString();
|
|
|
+ else
|
|
|
+ return std::string("First four bytes of file ") + root["file"].asString() + " are: " + root["data"].asString();
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printDeletefile(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool())
|
|
|
+ return std::string("Deletion of file ") + root["file"].asString() + " failed. " + root["error"].asString();
|
|
|
+ else
|
|
|
+ return std::string("File ") + root["file"].asString() + " deleted succesfully";
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printKeyfile(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool())
|
|
|
+ return std::string("Couldnt select keyfile ") + root["file"].asString() + ": " + root["error"].asString();
|
|
|
+ else
|
|
|
+ return std::string("Using keyfile ") + root["file"].asString();
|
|
|
+}
|
|
|
+
|
|
|
+std::string BatchIoMan::printClosekey(Json::Value root) {
|
|
|
+ if (!root["accept"].asBool())
|
|
|
+ return std::string("Failed to close key: ") + root["error"].asString();
|
|
|
+ else
|
|
|
+ return "Key closed.";
|
|
|
+}
|