123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- #include "../include/batchioman.h"
- #include <iostream>
- #include <string>
- #include <vector>
- BatchIoMan::BatchIoMan(bool usessl, bool beverbose, std::string batchpath) : IoMan(usessl) {
- /* 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 = true;
- verbose = beverbose;
- filepath = batchpath;
- }
- bool BatchIoMan::init() {
- batchin.open(filepath);
- normalout.open(filepath + ".out");
- if (verbose)
- debugout.open(filepath + ".debug");
- errorout.open(filepath + ".err");
- if (!batchin.is_open() || !normalout.is_open() || (verbose && !debugout.is_open()) || !errorout.is_open())
- return false;
- return IoMan::init();
- }
- BatchIoMan::~BatchIoMan() {
- batchin.close();
- normalout.close();
- if (verbose)
- 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: {
- if (verbose)
- 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();
- }
- if (cmdret.type & CmdMan::rettype::connect) {
- ipstring = cmdret.msg["address"].asString();
- port = cmdret.msg["port"].asUInt();
- if (connect()) {
- runnetwork = true;
- tnetwork = std::thread(&BatchIoMan::networkMain, this);
- // put new commands into global vector
- localmutex.lock();
- printMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"), debug);
- localinput.push_back("version");
- cmdman.stateSetConnectionOk();
- localmutex.unlock();
- printMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"), debug);
- localcv.notify_all();
- }
- }
- if (cmdret.type & CmdMan::rettype::exit) {
- 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.nextcommand.size()) {
- localmutex.lock();
- printMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"), debug);
- localinput.push_back(cmdret.nextcommand);
- localmutex.unlock();
- printMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"), debug);
- localcv.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) {
- // connection closed, stop network thread and shutdown any operations remaining
- networkmutex.lock();
- runnetwork = false;
- networkmutex.unlock();
- disconnect();
- tnetwork.join();
- if (cmdret.nextcommand.size()) {
- toput.push_back(cmdret.nextcommand);
- }
- }
- 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();
- return;
- }
- 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 (!(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 = "exit";
- } 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();
- 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.";
- }
|