diff --git a/src/jamidht/server_account_manager.cpp b/src/jamidht/server_account_manager.cpp index f4bb81703977ad8471c866bf577bff55e5587b94..8250a92cba229b6f9b2500419935eff461d3add8 100644 --- a/src/jamidht/server_account_manager.cpp +++ b/src/jamidht/server_account_manager.cpp @@ -22,6 +22,7 @@ #include <opendht/http.h> #include <opendht/log.h> +#include <opendht/thread_pool.h> #include "manager.h" @@ -77,123 +78,132 @@ ServerAccountManager::initAuthentication( } onChange_ = std::move(onChange); - const std::string url = managerHostname_ + PATH_DEVICE; JAMI_WARN("[Auth] authentication with: %s to %s", ctx->credentials->username.c_str(), url.c_str()); auto request = std::make_shared<Request>(*Manager::instance().ioContext(), url, logger_); auto reqid = request->id(); request->set_method(restinio::http_method_post()); request->set_auth(ctx->credentials->username, ctx->credentials->password); - { - std::stringstream ss; - auto csr = ctx->request.get()->toString(); - string_replace(csr, "\n", "\\n"); - string_replace(csr, "\r", "\\r"); - ss << "{\"csr\":\"" << csr << "\", \"deviceName\":\"" << ctx->deviceName << "\"}"; - JAMI_WARN("[Auth] Sending request: %s", csr.c_str()); - request->set_body(ss.str()); - } - setHeaderFields(*request); - request->add_on_state_change_callback([reqid, ctx, onAsync = onAsync_] - (Request::State state, const dht::http::Response& response){ - JAMI_DBG("[Auth] Got request callback with state=%d", (int)state); - if (state != Request::State::DONE) - return; - if (response.status_code == 0) { - ctx->onFailure(AuthError::SERVER_ERROR, "Invalid server provided"); - return; - } else if (response.status_code >= 400 && response.status_code < 500) - ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); - else if (response.status_code < 200 || response.status_code > 299) - ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); - else { - try { - Json::Value json; - std::string err; - Json::CharReaderBuilder rbuilder; - auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); - if (!reader->parse(response.body.data(), response.body.data() + response.body.size(), &json, &err)){ - JAMI_ERR("[Auth] Can't parse server response: %s", err.c_str()); - ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse server response"); + requests_[reqid] = request; + + dht::ThreadPool::computation().run([onAsync = onAsync_, ctx, request, reqid]{ + onAsync([ctx, request, reqid, onAsync](AccountManager& accountManager){ + auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); + { + std::stringstream ss; + auto csr = ctx->request.get()->toString(); + string_replace(csr, "\n", "\\n"); + string_replace(csr, "\r", "\\r"); + ss << "{\"csr\":\"" << csr << "\", \"deviceName\":\"" << ctx->deviceName << "\"}"; + JAMI_WARN("[Auth] Sending request: %s", csr.c_str()); + request->set_body(ss.str()); + } + this_.setHeaderFields(*request); + request->add_on_state_change_callback([reqid, request, ctx, onAsync] + (Request::State state, const dht::http::Response& response){ + JAMI_DBG("[Auth] Got request callback with state=%d", (int)state); + if (state != Request::State::DONE) return; - } - JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); + if (response.status_code == 0) + ctx->onFailure(AuthError::SERVER_ERROR, "Can't connect to server"); + else if (response.status_code >= 400 && response.status_code < 500) + ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); + else if (response.status_code < 200 || response.status_code > 299) + ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); + else { + do { + try { + Json::Value json; + std::string err; + Json::CharReaderBuilder rbuilder; + auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); + if (!reader->parse(response.body.data(), response.body.data() + response.body.size(), &json, &err)){ + JAMI_ERR("[Auth] Can't parse server response: %s", err.c_str()); + ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse server response"); + break; + } + JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); - auto certStr = json["certificateChain"].asString(); - string_replace(certStr, "\\n", "\n"); - string_replace(certStr, "\\r", "\r"); - auto cert = std::make_shared<dht::crypto::Certificate>(certStr); + auto certStr = json["certificateChain"].asString(); + string_replace(certStr, "\\n", "\n"); + string_replace(certStr, "\\r", "\r"); + auto cert = std::make_shared<dht::crypto::Certificate>(certStr); - auto accountCert = cert->issuer; - if (not accountCert) { - JAMI_ERR("[Auth] Can't parse certificate: no issuer"); - ctx->onFailure(AuthError::SERVER_ERROR, "Invalid certificate from server"); - return; - } - auto receipt = json["deviceReceipt"].asString(); - Json::Value receiptJson; - auto receiptReader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); - if (!receiptReader->parse(receipt.data(), receipt.data() + receipt.size(), &receiptJson, &err)){ - JAMI_ERR("[Auth] Can't parse receipt from server: %s", err.c_str()); - ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse receipt from server"); - return; - } - onAsync([reqid, ctx, - json=std::move(json), - receiptJson=std::move(receiptJson), - cert, - accountCert, - receipt=std::move(receipt)] (AccountManager& accountManager) mutable - { - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - auto receiptSignature = base64::decode(json["receiptSignature"].asString()); + auto accountCert = cert->issuer; + if (not accountCert) { + JAMI_ERR("[Auth] Can't parse certificate: no issuer"); + ctx->onFailure(AuthError::SERVER_ERROR, "Invalid certificate from server"); + break; + } + auto receipt = json["deviceReceipt"].asString(); + Json::Value receiptJson; + auto receiptReader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); + if (!receiptReader->parse(receipt.data(), receipt.data() + receipt.size(), &receiptJson, &err)){ + JAMI_ERR("[Auth] Can't parse receipt from server: %s", err.c_str()); + ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse receipt from server"); + break; + } + onAsync([reqid, ctx, + json=std::move(json), + receiptJson=std::move(receiptJson), + cert, + accountCert, + receipt=std::move(receipt)] (AccountManager& accountManager) mutable + { + auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); + auto receiptSignature = base64::decode(json["receiptSignature"].asString()); - auto info = std::make_unique<AccountInfo>(); - info->identity.second = cert; - info->deviceId = cert->getPublicKey().getId().toString(); - info->accountId = accountCert->getId().toString(); - info->contacts = std::make_unique<ContactList>(accountCert, this_.path_, this_.onChange_); - //info->contacts->setContacts(a.contacts); - if (ctx->deviceName.empty()) - ctx->deviceName = info->deviceId.substr(8); - info->contacts->foundAccountDevice(cert, ctx->deviceName, clock::now()); - info->ethAccount = receiptJson["eth"].asString(); - info->announce = parseAnnounce(receiptJson["announce"].asString(), info->accountId, info->deviceId); - if (not info->announce) { - ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse announce from server"); - } - info->username = ctx->credentials->username; + auto info = std::make_unique<AccountInfo>(); + info->identity.second = cert; + info->deviceId = cert->getPublicKey().getId().toString(); + info->accountId = accountCert->getId().toString(); + info->contacts = std::make_unique<ContactList>(accountCert, this_.path_, this_.onChange_); + //info->contacts->setContacts(a.contacts); + if (ctx->deviceName.empty()) + ctx->deviceName = info->deviceId.substr(8); + info->contacts->foundAccountDevice(cert, ctx->deviceName, clock::now()); + info->ethAccount = receiptJson["eth"].asString(); + info->announce = parseAnnounce(receiptJson["announce"].asString(), info->accountId, info->deviceId); + if (not info->announce) { + ctx->onFailure(AuthError::SERVER_ERROR, "Can't parse announce from server"); + } + info->username = ctx->credentials->username; - this_.creds_ = std::move(ctx->credentials); - this_.info_ = std::move(info); - std::map<std::string, std::string> config; - if (json.isMember("nameServer")) { - auto nameServer = json["nameServer"].asString(); - if (!nameServer.empty() && nameServer[0] == '/') - nameServer = this_.managerHostname_ + nameServer; - this_.nameDir_ = NameDirectory::instance(nameServer); - config.emplace(DRing::Account::ConfProperties::RingNS::URI, std::move(nameServer)); - } - if (json.isMember("displayName")) { - config.emplace(DRing::Account::ConfProperties::DISPLAYNAME, json["displayName"].asString()); - } - if (json.isMember("userPhoto")) { - this_.info_->photo = json["userPhoto"].asString(); - } + this_.creds_ = std::move(ctx->credentials); + this_.info_ = std::move(info); + std::map<std::string, std::string> config; + if (json.isMember("nameServer")) { + auto nameServer = json["nameServer"].asString(); + if (!nameServer.empty() && nameServer[0] == '/') + nameServer = this_.managerHostname_ + nameServer; + this_.nameDir_ = NameDirectory::instance(nameServer); + config.emplace(DRing::Account::ConfProperties::RingNS::URI, std::move(nameServer)); + } + if (json.isMember("displayName")) { + config.emplace(DRing::Account::ConfProperties::DISPLAYNAME, json["displayName"].asString()); + } + if (json.isMember("userPhoto")) { + this_.info_->photo = json["userPhoto"].asString(); + } - ctx->onSuccess(*this_.info_, std::move(config), std::move(receipt), std::move(receiptSignature)); - this_.syncDevices(); + ctx->onSuccess(*this_.info_, std::move(config), std::move(receipt), std::move(receiptSignature)); + this_.syncDevices(); + }); + } + catch (const std::exception& e) { + JAMI_ERR("Error when loading account: %s", e.what()); + ctx->onFailure(AuthError::NETWORK, ""); + } + } while (false); + } + onAsync([reqid](AccountManager& accountManager){ + auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); this_.requests_.erase(reqid); }); - } - catch (const std::exception& e) { - JAMI_ERR("Error when loading account: %s", e.what()); - ctx->onFailure(AuthError::NETWORK, ""); - } - } + }); + request->send(); + }); }); - request->send(); - requests_[reqid] = std::move(request); } void