123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- #include "../include/global.h"
- #include "../include/ioman.h"
- #include <boost/asio.hpp>
- #include <iostream>
- #include <boost/algorithm/string.hpp>
- #include <string>
- #include <vector>
- #include <readline/history.h>
- #include <readline/readline.h>
- using std::string;
- using std::vector;
- using boost::asio::ip::tcp;
- using boost::asio::buffer;
- IoMan::IoMan(char *ipcstring) : cmdman(fileman) {
- ipstring = std::string(ipcstring);
- port = 1234;
- tcpsock = new tcp::socket(ios);
- connected = false;
-
- /* to be put elsewhere */
- /* setup json stuff */
- Json::CharReaderBuilder rbuilder;
- wbuilder.settings_["indentation"] = "";
- reader = rbuilder.newCharReader();
- runnetwork = false;
- runinput = false;
- runresponse = false;
- startlist = false;
- versionstatus = off;
- loginstatus = off;
- }
- IoMan::~IoMan() {
- runnetwork = false;
- runinput = false;
- runresponse = false;
-
- tnetwork.join();
- tinput.join();
- tresponse.join();
-
- if(connected) {
- disconnect();
- }
-
- delete tcpsock;
- delete reader;
- }
- void IoMan::printNormalMessage(string nouse) {
- }
- void IoMan::printErrorMessage(string nouse) {
- }
- void IoMan::printDebugMessage(string nouse) {
- }
- bool IoMan::connect() {
- tcp::endpoint *ep;
- ep = new tcp::endpoint(boost::asio::ip::address::from_string(ipstring), 1234);
- // establish connection
- printDebugMessage("IoMan::connect() connecting to " + ipstring);
- tcpsock->connect(*ep, errcode);
- if (errcode) {
- delete ep;
- printErrorMessage("IoMan::connect() couldnt connect to " + ipstring + "\n" + errcode.message());
- return false;
- }
- connected = true;
- delete ep;
- return true;
- }
- void IoMan::disconnect() {
- printDebugMessage("IoMan::disconnect()");
- tcpsock->close();
- connected = false;
- }
- bool IoMan::init() {
- CmdMan::CmdRet ret;
- string work;
- Json::Value root;
-
- printDebugMessage("IoMan::Init() begin");
-
- if(!connect()) return false;
-
- printDebugMessage("IoMan::Init() versioncheck");
-
- localmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"));
- localinput.push_back("version " + protocolVersion);
- localmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"));
-
- printDebugMessage("IoMan::Init() begin");
-
- runnetwork = true;
- runinput = true;
- runresponse = true;
-
- tnetwork = std::thread(&IoMan::networkMain, this);
- tinput = std::thread(&IoMan::inputMain, this);
- tresponse = std::thread(&IoMan::responseMain, this);
-
- while(versionstatus == off);
- if(versionstatus == err) {
- runnetwork = false;
- runinput = false;
- runresponse = false;
- return false;
- }
-
- printWelcomeMessage();
- return true;
- }
- void IoMan::networkMain() {
- vector<Json::Value> toput;
- char *recvjson;
- Json::Value root;
- unsigned int jsonsize, readsize;
-
- printDebugMessage("IoMan::networkMain() begin");
- while(runnetwork) {
- std::this_thread::yield();
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- /*
- 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
- */
-
- // read from network
- readsize = boost::asio::read_until(*tcpsock, recvbuf, '\n', errcode);
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" asio::read() ok"));
- if (errcode && errcode != boost::asio::error::eof) {
- printErrorMessage("IoMan::networkMain() couldnt read json data\n" + errcode.message());
- continue;
- }
-
- recvjson = (char *)(boost::asio::buffer_cast<const char *>(recvbuf.data()));
- while(strchr(recvjson, '\n')) {
- // parse
- jsonsize = strchr(recvjson, '\n') - recvjson + 1;
-
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" found jsondata ") + string(recvjson));
-
- if (!reader->parse(recvjson, recvjson + jsonsize, &root, &jsonerror)) {
- printErrorMessage("IoMan::networkMain() couldnt parse json data: " + jsonerror);
- recvbuf.consume(jsonsize);
- continue;
- }
- recvbuf.consume(jsonsize);
- readsize -= jsonsize;
-
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" remaining recvbuf ") + string(boost::asio::buffer_cast<const char *>(recvbuf.data())));
-
- for(int i = 0; i < jsonsize; i++) recvjson++;
- // store locally
- toput.push_back(root);
- }
-
- if(toput.size()){
- // put into global vector
- netmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get netmutex"));
- netinput.insert(netinput.end(), toput.begin(), toput.end());
- netmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release netmutex"));
- }
-
- // clean up local stuff
- toput = vector<Json::Value>();
- recvbuf.consume(readsize);
- }
- }
- 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) {
- std::this_thread::yield();
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- /*
- get inputmutex
- read all input vector into local vector
- release inputmutex
-
- process inputs
- send to server if required
- */
-
- // read into local vector
- if(localinput.size()) {
- localmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" has localmutex"));
- toprocess = vector<string>(localinput);
- localinput = vector<string>();
- localmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"));
- }
-
- // printDebugMessage(string("have ") + std::to_string(toprocess.size()) + string(" commands"));
-
- // process
- for(string cmd : toprocess) {
- args = vector<string>();
-
- if((index = cmd.find(" ")) == string::npos) {
- // only command no args
- command = cmd;
- }
- else {
- command = cmd.substr(0, index);
- //~ index++;
- while(true) {
- // find first char thats not a space
- while(cmd[index] == ' ') {
- index++;
-
- // bounds check
- if(index == cmd.size()) goto end_tokenizing;
- }
-
- cmd = cmd.substr(index);
-
- if(cmd[0] == '\"') {
- // quoted string
- index = cmd.find("\"");
- args.push_back(cmd.substr(1, index-1));
- index++;
-
- /*
- tokens.push_back(cmd.substr(0, ++index));
- */
-
- // char after closing quote should be space while within bounds
- if(index == cmd.size()) goto end_tokenizing;
- }
- else {
- // non-quoted string
- index = cmd.find(" ");
- if(index == string::npos) { // no spaces, last arg
- args.push_back(cmd);
- goto end_tokenizing;
- }
- else {
- args.push_back(cmd.substr(0, index));
- }
- }
- }
- end_tokenizing: ;
- }
-
- cmdret = cmdman.execute(command, args);
-
- // determine wether to send something and do so if required
- 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;
- }
- }
- }
-
- // clean up local stuff
- toprocess = vector<string>();
- }
- }
- void IoMan::responseMain() {
- vector<Json::Value> toprocess;
- vector<string> toput;
- CmdMan::CmdRet cmdret;
-
- printDebugMessage("IoMan::responseMain() begin");
- while(runresponse) {
- std::this_thread::yield();
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- /*
- 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
- */
-
- // read into local vector
- if(netinput.size()) {
- netmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get netmutex"));
- toprocess = vector<Json::Value>(netinput);
- netinput = vector<Json::Value>();
- netmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release netmutex"));
- }
-
- // process jsons
- 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: {
- /* TODO i dunno */
- 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;
- }
- }
- }
-
- if(toput.size()) {
- // put new commands into global vector
- localmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"));
- localinput.insert(localinput.end(), toput.begin(), toput.end());
- localmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"));
- }
-
- // clean up local stuff
- toprocess = vector<Json::Value>();
- toput = vector<string>();
- }
- }
- void IoMan::run() {
- 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));
- }
- while(!pass) {
- pass = readline(getPassPrompt().c_str());
- printErrorMessage("Using pass: " + string(pass));
- }
-
- printDebugMessage("IoMan::run() login");
-
- localmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"));
- localinput.push_back("login " + string(user) + " " + string(pass));
- localmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"));
- free(user);
- free(pass);
-
- while(loginstatus == off);
- if(loginstatus == err) return;
-
- while(runmain) {
- free(line);
-
- line = readline(getCmdPrompt().c_str());
-
- if(!runmain) break;
- // if no input, do not add to history, and go to reading next line
- if (strlen(line) == 0) {
- continue;
- }
- // split input line into tokens
- boost::algorithm::split(tokens, std::string(line),
- boost::algorithm::is_any_of(" "),
- boost::algorithm::token_compress_on);
- // if input contains only spaces, do not add to history, and go to reading
- // next line
- if (tokens.size() < 1) {
- continue;
- }
- // add the line to history
- add_history(line);
-
- localmutex.lock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" get localmutex"));
- localinput.push_back(line);
- localmutex.unlock();
- printDebugMessage(string(__PRETTY_FUNCTION__) + string(" release localmutex"));
-
- if(!connected) break;
- }
-
- free(line);
- }
|