diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index eb076086f..b69fa2943 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -150,24 +150,29 @@ void RsControlModule::run() } // skip account selection if autologin is available - if(initResult != RS_INIT_HAVE_ACCOUNT) - setRunState(WAITING_ACCOUNT_SELECT); + bool wait_for_account_select = (initResult != RS_INIT_HAVE_ACCOUNT); // wait for login request bool auto_login = false; - bool wait_for_account_select = (initResult != RS_INIT_HAVE_ACCOUNT); + + if(wait_for_account_select) + setRunState(WAITING_ACCOUNT_SELECT); + while(wait_for_account_select && !processShouldExit()) { - usleep(5*1000); + usleep(500*1000); RsStackMutex stack(mDataMtx); // ********** LOCKED ********** - wait_for_account_select = mLoadPeerId.isNull(); + + if(!mLoadPeerId.isNull()) + wait_for_account_select = wait_for_account_select && !RsAccounts::SelectAccount(mLoadPeerId); + auto_login = mAutoLoginNextTime; - if(!wait_for_account_select) - { - wait_for_account_select = !RsAccounts::SelectAccount(mLoadPeerId); - if(wait_for_account_select) - setRunState(WAITING_ACCOUNT_SELECT); - } + + //if(!wait_for_account_select) + //{ + // if(wait_for_account_select) + // setRunState(WAITING_ACCOUNT_SELECT); + //} } if(processShouldExit()) diff --git a/libresapi/src/api/RsControlModule.h b/libresapi/src/api/RsControlModule.h index 38d564d9a..e81bb66f1 100644 --- a/libresapi/src/api/RsControlModule.h +++ b/libresapi/src/api/RsControlModule.h @@ -23,6 +23,8 @@ class ApiServer; class RsControlModule: public ResourceRouter, NotifyClient, private RsSingleJobThread { public: + enum RunState { WAITING_INIT, FATAL_ERROR, WAITING_ACCOUNT_SELECT, WAITING_STARTUP, RUNNING_OK, RUNNING_OK_NO_FULL_CONTROL}; + // ApiServer will be called once RS is started, to load additional api modules // full_control: set to true if this module should handle rsinit and login // set to false if rsinit is handled by the Qt gui @@ -32,6 +34,9 @@ public: // returns true if the process should terminate bool processShouldExit(); + // returns the current state of the software booting process + RunState runState() const { return mRunState ; } + // from NotifyClient virtual bool askForPassword(const std::string &title, const std::string& key_details, bool prev_is_bad , std::string& password,bool& canceled) override; virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason = "") override; @@ -42,7 +47,6 @@ protected: virtual void run(); private: - enum RunState { WAITING_INIT, FATAL_ERROR, WAITING_ACCOUNT_SELECT, WAITING_STARTUP, RUNNING_OK, RUNNING_OK_NO_FULL_CONTROL}; void handleRunState(Request& req, Response& resp); void handleIdentities(Request& req, Response& resp); void handleLocations(Request& req, Response& resp); diff --git a/retroshare-nogui/src/TerminalApiClient.cpp b/retroshare-nogui/src/TerminalApiClient.cpp index 7a7762b07..a52d51567 100644 --- a/retroshare-nogui/src/TerminalApiClient.cpp +++ b/retroshare-nogui/src/TerminalApiClient.cpp @@ -87,10 +87,8 @@ private: namespace resource_api { -TerminalApiClient::TerminalApiClient(ApiServer *api): - mApiServer(api) +TerminalApiClient::TerminalApiClient(ApiServer *api): mApiServer(api) { - start("resapi terminal"); } TerminalApiClient::~TerminalApiClient() @@ -98,13 +96,6 @@ TerminalApiClient::~TerminalApiClient() fullstop(); } -struct AccountInfo -{ - std::string name ; - std::string location ; - RsPeerId ssl_id ; -}; - void TerminalApiClient::data_tick() { // values in milliseconds @@ -228,44 +219,7 @@ void TerminalApiClient::data_tick() if(!ask_for_password && edge && runstate == "waiting_account_select") { - JsonStream reqs; - JsonStream resps; - Request req(reqs); - std::stringstream ss; - Response resp(resps, ss); - - req.mPath.push("locations"); - req.mPath.push("control"); - reqs.switchToDeserialisation(); - - ApiServer::RequestId id = mApiServer->handleRequest(req, resp); - waitForResponse(id); - - resps.switchToDeserialisation(); - if(!resps.hasMore()) - std::cout << "Error: No Accounts. Use the Qt-GUI or the webinterface to create an account." << std::endl; - int i = 0; - accounts.clear(); - while(resps.hasMore()) - { - std::string id; - std::string name; - std::string location; - - resps.getStreamToMember() - << makeKeyValueReference("id", id) - << makeKeyValueReference("name", name) - << makeKeyValueReference("location", location); - - AccountInfo info ; - info.location = location ; - info.name = name ; - info.ssl_id = RsPeerId(id) ; - - accounts.push_back(info); - i++; - } - + readAvailableAccounts(accounts) ; account_number_size = (int)ceil(log(accounts.size())/log(10.0f)) ; for(uint32_t i=0;ihandleRequest(req, resp); - waitForResponse(id); + sendSelectedAccount(acc_ssl_id) ; inbuf.clear(); } @@ -330,33 +272,107 @@ void TerminalApiClient::data_tick() } if(ask_for_password && enter_was_pressed && !inbuf.empty()) - { - std::cout << "TerminalApiClient: got a password" << std::endl; - JsonStream reqs; - JsonStream resps; - Request req(reqs); - std::stringstream ss; - Response resp(resps, ss); + { + std::cout << "TerminalApiClient: got a password" << std::endl; - req.mPath.push("password"); - req.mPath.push("control"); - reqs << makeKeyValueReference("password", inbuf); - reqs.switchToDeserialisation(); + // Send passwd to api server + sendPassword(inbuf) ; - ApiServer::RequestId id = mApiServer->handleRequest(req, resp); - waitForResponse(id); - - inbuf.clear(); + // clears buffer + inbuf.clear(); } } } -void TerminalApiClient::waitForResponse(ApiServer::RequestId id) +void TerminalApiClient::waitForResponse(ApiServer::RequestId id) const { while(!mApiServer->isRequestDone(id)) usleep(20*1000); } +void TerminalApiClient::sendPassword(const std::string& passwd) const +{ + JsonStream reqs; + JsonStream resps; + Request req(reqs); + std::stringstream ss; + Response resp(resps, ss); + + req.mPath.push("password"); + req.mPath.push("control"); + + std::string pass(passwd) ; + + reqs << makeKeyValueReference("password", pass); + reqs.switchToDeserialisation(); + + ApiServer::RequestId id = mApiServer->handleRequest(req, resp); + waitForResponse(id); +} + +void TerminalApiClient::sendSelectedAccount(const std::string& ssl_id) const +{ + JsonStream reqs; + JsonStream resps; + Request req(reqs); + std::stringstream ss; + Response resp(resps, ss); + + std::string acc_ssl_id(ssl_id) ; + req.mPath.push("login"); + req.mPath.push("control"); + reqs << makeKeyValueReference("id", acc_ssl_id); + reqs.switchToDeserialisation(); + + ApiServer::RequestId id = mApiServer->handleRequest(req, resp); + waitForResponse(id); +} + +void TerminalApiClient::readAvailableAccounts(std::vector& accounts) const +{ + JsonStream reqs; + JsonStream resps; + Request req(reqs); + std::stringstream ss; + Response resp(resps, ss); + + req.mPath.push("locations"); + req.mPath.push("control"); + reqs.switchToDeserialisation(); + + ApiServer::RequestId id = mApiServer->handleRequest(req, resp); + waitForResponse(id); + + resps.switchToDeserialisation(); + + if(!resps.hasMore()) + std::cout << "Error: No Accounts. Use the Qt-GUI or the webinterface to create an account." << std::endl; + + int i = 0; + accounts.clear(); + + while(resps.hasMore()) + { + std::string id; + std::string name; + std::string location; + + resps.getStreamToMember() + << makeKeyValueReference("id", id) + << makeKeyValueReference("name", name) + << makeKeyValueReference("location", location); + + AccountInfo info ; + info.location = location ; + info.name = name ; + info.ssl_id = RsPeerId(id) ; + + accounts.push_back(info); + i++; + } +} + + bool TerminalApiClient::isTokenValid(StateToken runstate_state_token) { JsonStream reqs; diff --git a/retroshare-nogui/src/TerminalApiClient.h b/retroshare-nogui/src/TerminalApiClient.h index bb5265c9d..4f72afb12 100644 --- a/retroshare-nogui/src/TerminalApiClient.h +++ b/retroshare-nogui/src/TerminalApiClient.h @@ -8,7 +8,7 @@ namespace resource_api { // - account selection // - login // - shutdown -class TerminalApiClient: private RsTickingThread{ +class TerminalApiClient: public RsTickingThread{ public: // zero setup: create an instance of this class and destroy it when not needed anymore // no need to call start or stop or something @@ -19,9 +19,24 @@ protected: // from RsThread virtual void data_tick(); /* called once the thread is started. Should be overloaded by subclasses. */ private: - void waitForResponse(ApiServer::RequestId id); + struct AccountInfo + { + std::string name ; + std::string location ; + RsPeerId ssl_id ; + }; + + + void waitForResponse(ApiServer::RequestId id) const; bool isTokenValid(StateToken st); ApiServer* mApiServer; + + // Methods to talk to the ApiServer + + void sendPassword(const std::string& passwd) const; + void sendSelectedAccount(const std::string& ssl_id) const; + void readAvailableAccounts(std::vector& accounts) const; + void getRunningState() const ; }; } // namespace resource_api diff --git a/retroshare-nogui/src/retroshare.cc b/retroshare-nogui/src/retroshare.cc index 011e03873..2e0b5d443 100644 --- a/retroshare-nogui/src/retroshare.cc +++ b/retroshare-nogui/src/retroshare.cc @@ -100,9 +100,25 @@ int main(int argc, char **argv) } resource_api::TerminalApiClient tac(&api); + tac.start(); + while(ctrl_mod.processShouldExit() == false) { - usleep(20*1000); + usleep(200*1000); + + if(!tac.isRunning()) + { + if(!RsInit::isLocationRunning()) + { + std::cerr << "Terminal API client stopped but location not set ! Relaunching." ; + tac.start(); + } + else if(RsInit::isLocationRunning()) + { + std::cerr << "Terminal API client running but location already set ! Stopping it." ; + tac.shutdown(); + } + } } if(httpd)