|
@@ -1,3 +1,4 @@
|
|
|
+#include "../include/global.h"
|
|
|
#include "../include/ioman.h"
|
|
|
|
|
|
#include <boost/asio.hpp>
|
|
@@ -21,12 +22,32 @@ IoMan::IoMan(char *ipcstring) : cmdman(fileman) {
|
|
|
port = 1234;
|
|
|
tcpsock = new tcp::socket(ios);
|
|
|
connected = false;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Json::CharReaderBuilder rbuilder;
|
|
|
+ wbuilder.settings_["indentation"] = "";
|
|
|
+ reader = rbuilder.newCharReader();
|
|
|
+ runnetwork = false;
|
|
|
+ runinput = false;
|
|
|
+ runresponse = false;
|
|
|
+ startlist = false;
|
|
|
}
|
|
|
|
|
|
IoMan::~IoMan() {
|
|
|
+ runnetwork = false;
|
|
|
+ runinput = false;
|
|
|
+ runresponse = false;
|
|
|
+
|
|
|
+ tnetwork.join();
|
|
|
+ tinput.join();
|
|
|
+ tresponse.join();
|
|
|
+
|
|
|
if(connected) {
|
|
|
disconnect();
|
|
|
}
|
|
|
+
|
|
|
delete tcpsock;
|
|
|
}
|
|
|
|
|
@@ -36,11 +57,11 @@ bool IoMan::connect() {
|
|
|
ep = new tcp::endpoint(boost::asio::ip::address::from_string(ipstring), 1234);
|
|
|
|
|
|
|
|
|
- std::cerr << "IoMan::connect() connecting to " << ipstring << std::endl;
|
|
|
+ printDebugMessage("IoMan::connect() connecting to " + ipstring);
|
|
|
tcpsock->connect(*ep, errcode);
|
|
|
if (errcode) {
|
|
|
delete ep;
|
|
|
- printErrorMessage("IoMan::connect() couldnt connect to " + ipstring + "\n" + errcode.message() + "\n");
|
|
|
+ printErrorMessage("IoMan::connect() couldnt connect to " + ipstring + "\n" + errcode.message());
|
|
|
return false;
|
|
|
}
|
|
|
connected = true;
|
|
@@ -50,68 +71,42 @@ bool IoMan::connect() {
|
|
|
|
|
|
|
|
|
void IoMan::disconnect() {
|
|
|
- std::cerr << "IoMan::disconnect()" << std::endl;
|
|
|
+ printDebugMessage("IoMan::disconnect()");
|
|
|
tcpsock->close();
|
|
|
connected = false;
|
|
|
}
|
|
|
|
|
|
-bool IoMan::sendJsonString(std::string msg) {
|
|
|
- std::cerr << "IoMan::sendJsonString() " << msg << std::endl;
|
|
|
- boost::asio::write(*tcpsock, buffer(msg + "\n"), errcode);
|
|
|
- if (errcode) {
|
|
|
- printErrorMessage("IoMan::sendJsonString() couldnt send json data\n" + errcode.message() + "\n");
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-std::string IoMan::receiveJsonString() {
|
|
|
- std::string retstring;
|
|
|
- std::cerr << "IoMan::receiveJsonString()" << std::endl;
|
|
|
-
|
|
|
- boost::asio::read_until(*tcpsock, recvbuf, '\n', errcode);
|
|
|
- if (errcode && errcode != boost::asio::error::eof) {
|
|
|
- printErrorMessage("IoMan::receiveJsonString() couldnt read json data\n" + errcode.message() + "\n");
|
|
|
- }
|
|
|
- retstring = boost::asio::buffer_cast<const char *>(recvbuf.data());
|
|
|
- recvbuf.consume(recvbuf.size());
|
|
|
- std::cerr << "IoMan::receiveJsonString(): returning string \"" << retstring << "\"" << std::endl;
|
|
|
- return retstring;
|
|
|
-}
|
|
|
-
|
|
|
-bool IoMan::parseJson(Json::Value *root, string jsonstring) {
|
|
|
- const char *recvjson;
|
|
|
- std::string jsonerror;
|
|
|
- recvjson = jsonstring.c_str();
|
|
|
- if (!cmdman.reader->parse(recvjson, recvjson + jsonstring.size(), root, &jsonerror)) {
|
|
|
- printErrorMessage("couldnt parse json data: " + jsonerror + "\n");
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
-}
|
|
|
|
|
|
bool IoMan::init() {
|
|
|
CmdMan::CmdRet ret;
|
|
|
string work;
|
|
|
Json::Value root;
|
|
|
|
|
|
+ printDebugMessage("IoMan::Init() begin");
|
|
|
+
|
|
|
if(!connect()) return false;
|
|
|
|
|
|
- ret = cmdman.cmdVersion(protoVersion);
|
|
|
+ printDebugMessage("IoMan::Init() versioncheck");
|
|
|
+
|
|
|
+ localmutex.lock();
|
|
|
+ localinput.push_back("version " + protocolVersion);
|
|
|
+ localmutex.unlock();
|
|
|
|
|
|
- if(!sendJsonString(ret.msg)) return false;
|
|
|
+ printDebugMessage("IoMan::Init() begin");
|
|
|
|
|
|
- work = receiveJsonString();
|
|
|
- if(work.empty()) return false;
|
|
|
+ runnetwork = true;
|
|
|
+ runinput = true;
|
|
|
+ runresponse = true;
|
|
|
|
|
|
- if(!parseJson(&root, work)) return false;
|
|
|
+ tnetwork = std::thread(&IoMan::networkMain, this);
|
|
|
+ tinput = std::thread(&IoMan::inputMain, this);
|
|
|
+ tresponse = std::thread(&IoMan::responseMain, this);
|
|
|
|
|
|
- if(!root["accept"].asBool()) {
|
|
|
- work = "IoMan::init() Version check failed. Server reports ";
|
|
|
- work.append(root["version"].asString());
|
|
|
- work.append(" but client is ");
|
|
|
- work.append(protoVersion);
|
|
|
- printErrorMessage(work);
|
|
|
+ while(versionstatus == off);
|
|
|
+ if(versionstatus == err) {
|
|
|
+ runnetwork = false;
|
|
|
+ runinput = false;
|
|
|
+ runresponse = false;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -119,15 +114,245 @@ bool IoMan::init() {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+void IoMan::networkMain() {
|
|
|
+ vector<Json::Value> toput;
|
|
|
+ const char *recvjson;
|
|
|
+ Json::Value root;
|
|
|
+ unsigned int jsonsize;
|
|
|
+
|
|
|
+ printDebugMessage("IoMan::networkMain() begin");
|
|
|
+ while(runnetwork) {
|
|
|
+
|
|
|
+ read from network until \n
|
|
|
+ try to parse json
|
|
|
+ - output error if not ok
|
|
|
+ store all ok json in local vector
|
|
|
+
|
|
|
+ get networkmutex
|
|
|
+ put all local jsons into network vector
|
|
|
+ release networkmutex
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ boost::asio::read_until(*tcpsock, recvbuf, '\n', errcode);
|
|
|
+ if (errcode && errcode != boost::asio::error::eof) {
|
|
|
+ printErrorMessage("IoMan::networkMain() couldnt read json data\n" + errcode.message());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ recvjson = boost::asio::buffer_cast<const char *>(recvbuf.data());
|
|
|
+ while(strchr(recvjson, '\n')) {
|
|
|
+
|
|
|
+ jsonsize = strchr(recvjson, '\n') - recvjson;
|
|
|
+
|
|
|
+ if (!reader->parse(recvjson, recvjson + jsonsize, &root, &jsonerror)) {
|
|
|
+ printErrorMessage("IoMan::networkMain() couldnt parse json data: " + jsonerror);
|
|
|
+ recvbuf.consume(jsonsize);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ recvbuf.consume(jsonsize);
|
|
|
+
|
|
|
+
|
|
|
+ toput.push_back(root);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ netmutex.lock();
|
|
|
+ netinput.insert(netinput.end(), toput.begin(), toput.end());
|
|
|
+ netmutex.unlock();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void IoMan::inputMain() {
|
|
|
+ vector<string> toprocess;
|
|
|
+ string command;
|
|
|
+ vector<string> args;
|
|
|
+ CmdMan::CmdRet cmdret;
|
|
|
+
|
|
|
+ size_t prev, index, quot;
|
|
|
+
|
|
|
+ printDebugMessage("IoMan::inputMain() begin");
|
|
|
+ while(runinput) {
|
|
|
+
|
|
|
+ get inputmutex
|
|
|
+ read all input vector into local vector
|
|
|
+ release inputmutex
|
|
|
+
|
|
|
+ process inputs
|
|
|
+ send to server if required
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ if(localinput.size()) {
|
|
|
+ localmutex.lock();
|
|
|
+ toprocess = vector<string>(localinput);
|
|
|
+ localinput = vector<string>();
|
|
|
+ localmutex.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+ printDebugMessage(string("have ") + std::to_string(toprocess.size()) + string(" commands"));
|
|
|
+
|
|
|
+
|
|
|
+ for(string cmd : toprocess) {
|
|
|
+ args = vector<string>();
|
|
|
+
|
|
|
+ if((index = cmd.find(" ")) == string::npos) {
|
|
|
+
|
|
|
+ command = cmd;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ command = cmd.substr(0, index);
|
|
|
+ index++;
|
|
|
+ while(true) {
|
|
|
+
|
|
|
+ while(cmd[index] == ' ') {
|
|
|
+ index++;
|
|
|
+
|
|
|
+
|
|
|
+ if(index == cmd.size()) goto end_tokenizing;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd = cmd.substr(index);
|
|
|
+
|
|
|
+ if(cmd[0] == '\"') {
|
|
|
+
|
|
|
+ index = cmd.find("\"");
|
|
|
+ args.push_back(cmd.substr(1, index-1));
|
|
|
+ index++;
|
|
|
+
|
|
|
+
|
|
|
+ tokens.push_back(cmd.substr(0, ++index));
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ if(index == cmd.size()) goto end_tokenizing;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ index = cmd.find(" ");
|
|
|
+ if(index == string::npos) {
|
|
|
+ args.push_back(cmd);
|
|
|
+ goto end_tokenizing;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ args.push_back(cmd.substr(1, index));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ end_tokenizing: ;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmdret = cmdman.execute(command, args);
|
|
|
+
|
|
|
+
|
|
|
+ switch(cmdret.type) {
|
|
|
+ case CmdMan::rettype::send: {
|
|
|
+ printDebugMessage("IoMan::inputMain() sending json \"" + cmdret.msg + "\"");
|
|
|
+ boost::asio::write(*tcpsock, buffer(cmdret.msg + "\n"), errcode);
|
|
|
+ if (errcode) {
|
|
|
+ printErrorMessage("IoMan::inputMain() couldnt send json data\n" + errcode.message() + "\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::notsend: {
|
|
|
+ printNormalMessage(cmdret.msg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::error: {
|
|
|
+ printErrorMessage(cmdret.msg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void IoMan::responseMain() {
|
|
|
+ vector<Json::Value> toprocess;
|
|
|
+ vector<string> toput;
|
|
|
+ CmdMan::CmdRet cmdret;
|
|
|
+
|
|
|
+ printDebugMessage("IoMan::responseMain() begin");
|
|
|
+ while(runresponse) {
|
|
|
+
|
|
|
+ get networkmutex
|
|
|
+ read all network vector into local vector
|
|
|
+ release networkmutex
|
|
|
+
|
|
|
+ process all jsons
|
|
|
+ process putdata
|
|
|
+ process getdata
|
|
|
+ process listdata
|
|
|
+
|
|
|
+ get inputmutex
|
|
|
+ place new commands into input vector
|
|
|
+ release inputmutex
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ if(netinput.size()) {
|
|
|
+ netmutex.lock();
|
|
|
+ toprocess = vector<Json::Value>(netinput);
|
|
|
+ netinput = vector<Json::Value>();
|
|
|
+ netmutex.unlock();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ for(Json::Value root : toprocess) {
|
|
|
+ cmdret = cmdman.handle(root);
|
|
|
+ switch(cmdret.type) {
|
|
|
+ case CmdMan::rettype::startlist: {
|
|
|
+ startlist = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::stoplist: {
|
|
|
+ startlist = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::close: {
|
|
|
+
|
|
|
+ runmain = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::error: {
|
|
|
+ if(versionstatus == off) versionstatus = err;
|
|
|
+ else if(loginstatus == off) loginstatus = err;
|
|
|
+ printErrorMessage(cmdret.msg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::seton: {
|
|
|
+ if(versionstatus == off) versionstatus = on;
|
|
|
+ else loginstatus = on;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::notsend: {
|
|
|
+ printNormalMessage(cmdret.msg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case CmdMan::rettype::send: {
|
|
|
+ toput.push_back(cmdret.msg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ localmutex.lock();
|
|
|
+ localinput.insert(localinput.end(), toput.begin(), toput.end());
|
|
|
+ localmutex.unlock();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void IoMan::run() {
|
|
|
- std::cerr << "IoMan::run() begin" << std::endl;
|
|
|
- bool running = true;
|
|
|
+ printDebugMessage("IoMan::run() begin");
|
|
|
char *line = NULL, *user = NULL, *pass = NULL;
|
|
|
vector<string> tokens;
|
|
|
string work, command;
|
|
|
CmdMan::CmdRet cmdret;
|
|
|
Json::Value root;
|
|
|
|
|
|
+ runmain = true;
|
|
|
+
|
|
|
while(!user) {
|
|
|
user = readline(getUserPrompt().c_str());
|
|
|
printErrorMessage("Using user: " + string(user));
|
|
@@ -137,88 +362,49 @@ void IoMan::run() {
|
|
|
printErrorMessage("Using pass: " + string(pass));
|
|
|
}
|
|
|
|
|
|
- std::cerr << "IoMan::run() begin" << std::endl;
|
|
|
+ printDebugMessage("IoMan::run() login");
|
|
|
|
|
|
-
|
|
|
- cmdret = cmdman.cmdLogin(string(user), string(pass));
|
|
|
+ localmutex.lock();
|
|
|
+ localinput.push_back("login " + string(user) + " " + string(pass));
|
|
|
+ localmutex.unlock();
|
|
|
free(user);
|
|
|
free(pass);
|
|
|
|
|
|
- if(!sendJsonString(cmdret.msg)) return;
|
|
|
+ while(loginstatus == off);
|
|
|
+ if(loginstatus == err) return;
|
|
|
|
|
|
- work = receiveJsonString();
|
|
|
- if(work.empty()) return;
|
|
|
-
|
|
|
- if(!parseJson(&root, work)) return;
|
|
|
- if(!root["accept"].asBool()) {
|
|
|
- work = "IoMan::run() Login refused. ";
|
|
|
- work.append(root["error"].asString());
|
|
|
- printErrorMessage(work);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- while(running) {
|
|
|
+ while(runmain) {
|
|
|
free(line);
|
|
|
|
|
|
line = readline(getCmdPrompt().c_str());
|
|
|
+
|
|
|
+ if(!runmain) break;
|
|
|
|
|
|
-
|
|
|
- if (strlen(line) == 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- boost::algorithm::split(tokens, std::string(line),
|
|
|
- boost::algorithm::is_any_of(" "),
|
|
|
- boost::algorithm::token_compress_on);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (tokens.size() < 1) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- add_history(line);
|
|
|
- command = tokens[0];
|
|
|
- tokens.erase(tokens.begin());
|
|
|
-
|
|
|
- cmdret = cmdman.execute(command, tokens);
|
|
|
- switch(cmdret.type) {
|
|
|
- case CmdMan::rettype::error: {
|
|
|
- printErrorMessage(cmdret.msg);
|
|
|
- break;
|
|
|
- }
|
|
|
- case CmdMan::rettype::text: {
|
|
|
-
|
|
|
- std::cout << cmdret.msg << std::endl;
|
|
|
- break;
|
|
|
- }
|
|
|
- case CmdMan::rettype::json: {
|
|
|
- if(!sendJsonString(cmdret.msg)) continue;
|
|
|
-
|
|
|
- while(1) {
|
|
|
- work = receiveJsonString();
|
|
|
- if(work.empty()) break;
|
|
|
-
|
|
|
- if(!work.size()) break;
|
|
|
-
|
|
|
- if(!parseJson(&root, work)) break;
|
|
|
- else if(!handleJson(root)) {
|
|
|
- running = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(!connected) break;
|
|
|
+
|
|
|
+ if (strlen(line) == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ boost::algorithm::split(tokens, std::string(line),
|
|
|
+ boost::algorithm::is_any_of(" "),
|
|
|
+ boost::algorithm::token_compress_on);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (tokens.size() < 1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ add_history(line);
|
|
|
+
|
|
|
+ localmutex.lock();
|
|
|
+ localinput.push_back(line);
|
|
|
+ localmutex.unlock();
|
|
|
+
|
|
|
+ if(!connected) break;
|
|
|
}
|
|
|
|
|
|
free(line);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|