diff --git a/jus/AbstractFunction.cpp b/jus/AbstractFunction.cpp index 94e3166..9b7ab37 100644 --- a/jus/AbstractFunction.cpp +++ b/jus/AbstractFunction.cpp @@ -152,6 +152,12 @@ namespace jus { } +ejson::Object jus::createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params) { + ejson::Object callElem = createBaseCall(_transactionId, _functionName); + callElem.add("param", _params); + return callElem; +} + ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service) { ejson::Object obj; if (_service.size() != 0) { @@ -207,6 +213,26 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs || createType() == _type) { return _params.isNumber(); } + if (createType>() == _type) { + return _params.isArray(); + } + if ( createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type + || createType>() == _type) { + if (_params.isObject()) { + JUS_TODO("Special case of packaging of the data"); + return false; + } + return _params.isArray(); + } if (createType() == _type) { return _params.isString(); } diff --git a/jus/AbstractFunction.h b/jus/AbstractFunction.h index 03625b6..886b78e 100644 --- a/jus/AbstractFunction.h +++ b/jus/AbstractFunction.h @@ -52,6 +52,30 @@ namespace jus { ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service=""); void createParam(ejson::Object& _obj); + + template + void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::string& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const bool& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const int32_t& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const double& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const float& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); + template void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args) { if (_obj.valueExist("param") == false) { @@ -188,7 +212,7 @@ namespace jus { createParam(callElem, std::forward<_ARGS>(_args)...); return callElem; } - + ejson::Object createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params); } diff --git a/jus/Client.cpp b/jus/Client.cpp index d2f60f1..12794b4 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -22,12 +22,25 @@ jus::Client::~Client() { } void jus::Client::onClientData(std::string _value) { + JUS_DEBUG("Get answer : " << _value); ejson::Object obj(_value); jus::FutureBase future; { uint64_t tid = obj["id"].toNumber().get(); if (tid == 0) { - JUS_ERROR("call with no ID ==> error ..."); + if (obj["error"].toString().get() == "PROTOCOL-ERROR") { + JUS_ERROR("Get a Protocol error ..."); + std::unique_lock lock(m_mutex); + for (auto &it : m_pendingCall) { + if (it.isValid() == false) { + continue; + } + it.setAnswer(obj); + } + m_pendingCall.clear(); + } else { + JUS_ERROR("call with no ID ==> error ..."); + } return; } std::unique_lock lock(m_mutex); @@ -136,15 +149,15 @@ uint64_t jus::Client::getId() { return m_id++; } -jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj) { +jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { JUS_VERBOSE("Send JSON [START] "); if (m_interfaceClient.isActive() == false) { ejson::Object obj; obj.add("error", ejson::String("NOT-CONNECTED")); obj.add("error-help", ejson::String("Client interface not connected (no TCP)")); - return jus::FutureBase(_transactionId, true, obj); + return jus::FutureBase(_transactionId, true, obj, _callback); } - jus::FutureBase tmpFuture(_transactionId); + jus::FutureBase tmpFuture(_transactionId, _callback); { std::unique_lock lock(m_mutex); m_pendingCall.push_back(tmpFuture); diff --git a/jus/Client.h b/jus/Client.h index 480d191..9b530d5 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -43,7 +43,7 @@ namespace jus { private: void onClientData(std::string _value); std::string asyncRead(); - jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); + jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); public: uint64_t getId(); template @@ -52,6 +52,12 @@ namespace jus { ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); return callJson(id, callElem); } + template + jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, _callback); + } private: void onPropertyChangeIp(); void onPropertyChangePort(); diff --git a/jus/FutureBase.cpp b/jus/FutureBase.cpp index 75d85f8..b08ad49 100644 --- a/jus/FutureBase.cpp +++ b/jus/FutureBase.cpp @@ -16,16 +16,24 @@ jus::FutureBase::FutureBase() { m_data = nullptr; } -jus::FutureBase::FutureBase(uint64_t _transactionId) { +jus::FutureBase::FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback) { m_data = std::make_shared(); if (m_data == nullptr) { return; } m_data->m_transactionId = _transactionId; m_data->m_isFinished = false; + m_data->m_callbackFinish = _callback; } -jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData) { +ejson::Object jus::FutureBase::getRaw() { + if (m_data == nullptr) { + return ejson::Object(); + } + return m_data->m_returnData; +} + +jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback) { m_data = std::make_shared(); if (m_data == nullptr) { return; @@ -33,6 +41,11 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob m_data->m_transactionId = _transactionId; m_data->m_isFinished = _isFinished; m_data->m_returnData = _returnData; + m_data->m_callbackFinish = _callback; + if ( m_data->m_isFinished == true + && m_data->m_callbackFinish != nullptr) { + m_data->m_callbackFinish(*this); + } } jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) { @@ -47,6 +60,9 @@ void jus::FutureBase::setAnswer(const ejson::Object& _returnValue) { } m_data->m_returnData = _returnValue; m_data->m_isFinished = true; + if (m_data->m_callbackFinish != nullptr) { + m_data->m_callbackFinish(*this); + } } uint64_t jus::FutureBase::getTransactionId() { diff --git a/jus/FutureBase.h b/jus/FutureBase.h index 66ea4c6..7442076 100644 --- a/jus/FutureBase.h +++ b/jus/FutureBase.h @@ -14,8 +14,8 @@ namespace jus { public: FutureBase(const jus::FutureBase& _base); FutureBase(); - FutureBase(uint64_t _transactionId); - FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData); + FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback=nullptr); + FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback=nullptr); jus::FutureBase operator= (const jus::FutureBase& _base); void setAnswer(const ejson::Object& _returnValue); uint64_t getTransactionId(); @@ -27,6 +27,7 @@ namespace jus { void wait(); bool waitFor(std::chrono::microseconds _delta); bool waitUntil(std::chrono::steady_clock::time_point _endTime); + ejson::Object getRaw(); }; } diff --git a/jus/FutureData.h b/jus/FutureData.h index 8ef6e63..742a7fa 100644 --- a/jus/FutureData.h +++ b/jus/FutureData.h @@ -9,11 +9,15 @@ #include namespace jus { + class FutureBase; class FutureData { + public: + using ObserverFinish = std::function; //!< Define an Observer: function pointer public: uint64_t m_transactionId; bool m_isFinished; ejson::Object m_returnData; + ObserverFinish m_callbackFinish; }; } diff --git a/jus/GateWay.cpp b/jus/GateWay.cpp index 06f94ce..3974ac5 100644 --- a/jus/GateWay.cpp +++ b/jus/GateWay.cpp @@ -117,6 +117,18 @@ ememory::SharedPtr jus::GateWay::get(const std::string& _se return nullptr; } +std::vector jus::GateWay::getAllServiceName() { + std::vector out; + for (auto &it : m_serviceList) { + if (it == nullptr) { + continue; + } + out.push_back(it->getName()); + } + return out; +} + + void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) { for (auto &it : m_clientList) { if (it == nullptr) { diff --git a/jus/GateWay.h b/jus/GateWay.h index ba6f614..94e1fb4 100644 --- a/jus/GateWay.h +++ b/jus/GateWay.h @@ -32,6 +32,7 @@ namespace jus { void start(); void stop(); ememory::SharedPtr get(const std::string& _serviceName); + std::vector getAllServiceName(); void answer(uint64_t _userSessionId, ejson::Object _data); void newService(enet::Tcp _connection); void newClient(enet::Tcp _connection); diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index 4cc18eb..9d18ec4 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -16,7 +16,7 @@ jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayI m_state(jus::GateWayClient::state::unconnect), m_gatewayInterface(_gatewayInterface), m_interfaceClient(std::move(_connection)), - m_transactionLocalId(-1) { + m_transactionLocalId(1) { JUS_INFO("----------------"); JUS_INFO("-- NEW Client --"); JUS_INFO("----------------"); @@ -131,73 +131,89 @@ void jus::GateWayClient::onClientData(std::string _value) { } case jus::GateWayClient::state::userIdentify: { - std::string call = data["call"].toString().get(); - if (call == "identify") { + std::string callFunction = data["call"].toString().get(); + m_clientServices.clear(); + m_clientgroups.clear(); + m_clientName.clear(); + + if ( callFunction != "identify" + && callFunction != "auth" + && callFunction != "anonymous") { + protocolError("Client must call: identify/auth/anonymous"); + return; + } + if (callFunction == "identify") { std::string clientName = data["param"].toArray()[0].toString().get(); std::string clientTocken = data["param"].toArray()[1].toString().get(); - ejson::Object gwCall; - int32_t tmpID = m_transactionLocalId--; - gwCall.add("id", ejson::Number(tmpID)); - gwCall.add("call", ejson::String("checkTocken")); - ejson::Array gwParam; - gwParam.add(ejson::String(clientName)); - gwParam.add(ejson::String(clientTocken)); - gwCall.add("param", gwParam); - { - std::unique_lock lock(m_mutex); - m_actions.push_back(std::make_pair(tmpID, - [=](ejson::Object& _data) { - JUS_ERROR(" ==> Tocken ckeck return ..."); - if (_data["return"].toBoolean().get() == true) { - m_clientName = clientName; - m_clientgroups.clear(); - ejson::Object gwCall; - int32_t tmpID = m_transactionLocalId--; - gwCall.add("id", ejson::Number(tmpID)); - gwCall.add("call", ejson::String("getGroups")); - ejson::Array gwParam; - gwParam.add(ejson::String(clientName)); - gwCall.add("param", gwParam); - { - std::unique_lock lock(m_mutex); - m_actions.push_back(std::make_pair(tmpID, - [=](ejson::Object& _data) { - JUS_ERROR(" ==> group get return ..."); - if (_data["return"].isArray() == false) { - returnBool(transactionId, false); - } else { - m_clientgroups = convertJsonTo>(_data["return"]); - returnBool(transactionId, true); - } - })); - } - if (m_userService != nullptr) { - m_userService->SendData(m_uid2, gwCall); - } else { - protocolError("gateWay internal error 3"); - } - } else { - returnBool(transactionId, false); - } - })); - } - if (m_userService != nullptr) { - m_userService->SendData(m_uid2, gwCall); - } else { + if (m_userService == nullptr) { protocolError("gateWay internal error 3"); + return; } - return; + jus::Future fut = call(m_uid2, m_userService, "checkTocken", clientName, clientTocken); + fut.wait(); // TODO: Set timeout ... + if (fut.hasError() == true) { + JUS_ERROR("Get error from the service ..."); + returnBool(transactionId, false); + protocolError("connection refused 1"); + return; + } else if (fut.get() == false) { + returnBool(transactionId, false); + protocolError("connection refused 2"); + return; + } + m_clientName = clientName; } - if (call == "auth") { + if (callFunction == "auth") { std::string password = data["param"].toArray()[0].toString().get(); - protocolError("Not implemented"); + jus::Future fut = call(m_uid2, m_userService, "auth", password); + fut.wait(); // TODO: Set timeout ... + if (fut.hasError() == true) { + JUS_ERROR("Get error from the service ..."); + returnBool(transactionId, false); + protocolError("connection refused 1"); + return; + } else if (fut.get() == false) { + returnBool(transactionId, false); + protocolError("connection refused 2"); + return; + } + m_clientName = m_userConnectionName; + } + if (callFunction == "anonymous") { + m_clientName = ""; + } + // -------------------------------- + // -- Get groups: + // -------------------------------- + jus::Future> futGroup = call(m_uid2, m_userService, "getGroups", m_clientName); + futGroup.wait(); // TODO: Set timeout ... + if (futGroup.hasError() == true) { + JUS_ERROR("Get error from the service ..."); + returnBool(transactionId, false); + protocolError("grouping error"); return; } - if (call == "anonymous") { - protocolError("Not implemented"); + m_clientgroups = futGroup.get(); + // -------------------------------- + // -- Get services: + // -------------------------------- + std::vector currentServices = m_gatewayInterface->getAllServiceName(); + jus::Future> futServices = call(m_uid2, m_userService, "filterServices", m_clientName, currentServices); + futServices.wait(); // TODO: Set timeout ... + if (futServices.hasError() == true) { + JUS_ERROR("Get error from the service ..."); + returnBool(transactionId, false); + protocolError("service filtering error"); return; } - protocolError("Client must call: identify/auth/anonymous"); + m_clientServices = futServices.get(); + JUS_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'"); + JUS_WARNING(" groups: " << etk::to_string(m_clientgroups)); + JUS_WARNING(" services: " << etk::to_string(m_clientServices)); + + + returnBool(transactionId, true); + m_state = jus::GateWayClient::state::clientIdentify; return; } break; @@ -206,18 +222,18 @@ void jus::GateWayClient::onClientData(std::string _value) { std::string service = data["service"].toString().get(); // Thsi is 2 default service for the cient interface that manage the authorisation of view: if (service == "") { - std::string call = data["call"].toString().get(); + std::string callFunction = data["call"].toString().get(); ejson::Object answer; //answer.add("from-service", ejson::String("")); answer.add("id", data["id"]); - if (call == "getServiceCount") { + if (callFunction == "getServiceCount") { // TODO : Do it better: answer.add("return", ejson::Number(2)); JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); return; } - if (call == "getServiceList") { + if (callFunction == "getServiceList") { ejson::Array listService; listService.add(ejson::String("ServiceManager/v0.1.0")); listService.add(ejson::String("getServiceInformation/v0.1.0")); @@ -226,7 +242,7 @@ void jus::GateWayClient::onClientData(std::string _value) { m_interfaceClient.write(answer.generateMachineString()); return; } - if (call == "link") { + if (callFunction == "link") { // first param: std::string serviceName = data["param"].toArray()[0].toString().get(); // Check if service already link: @@ -265,7 +281,7 @@ void jus::GateWayClient::onClientData(std::string _value) { m_interfaceClient.write(answer.generateMachineString()); return; } - if (call == "unlink") { + if (callFunction == "unlink") { // first param: std::string serviceName = data["param"].toArray()[0].toString().get(); // Check if service already link: @@ -294,7 +310,7 @@ void jus::GateWayClient::onClientData(std::string _value) { m_interfaceClient.write(answer.generateMachineString()); return; } - JUS_ERROR("Function does not exist ... '" << call << "'"); + JUS_ERROR("Function does not exist ... '" << callFunction << "'"); answer.add("error", ejson::String("CALL-UNEXISTING")); JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); @@ -323,8 +339,19 @@ void jus::GateWayClient::onClientData(std::string _value) { m_interfaceClient.write(answer.generateMachineString()); } else { JUS_ERROR("Add in link the name of the user in parameter ..."); - data.remove("service"); - { + //data.remove("service"); + //transactionId + callActionForward(m_uid, + *it, + data["call"].toString().get(), + data["param"].toArray(), + [=](jus::FutureBase _ret) { + ejson::Object tmpp = _ret.getRaw(); + tmpp["id"] = data["id"]; + JUS_DEBUG(" ==> transmit"); + m_interfaceClient.write(tmpp.generateMachineString()); + }); + /* std::unique_lock lock(m_mutex); m_actions.push_back(std::make_pair(transactionId, [=](ejson::Object& _data) { @@ -333,41 +360,82 @@ void jus::GateWayClient::onClientData(std::string _value) { })); } (*it)->SendData(m_uid, data); + */ } } } } -void jus::GateWayClient::returnMessage(ejson::Object _data) { - JUS_DEBUG("answer: " << _data.generateHumanString()); - int32_t id = _data["id"].toNumber().get(); - if (id == 0) { - JUS_ERROR("gateway reject transaction ... ==> No 'id' or 'id' == 0"); - return; +jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCallJson(id, _functionName, _params); + return callJson(_callerId, _srv, id, callElem, _callback); +} + +uint64_t jus::GateWayClient::getId() { + return m_transactionLocalId++; +} + +jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { + JUS_VERBOSE("Send JSON [START] "); + if (_srv == nullptr) { + ejson::Object obj; + obj.add("error", ejson::String("NOT-CONNECTED")); + obj.add("error-help", ejson::String("Client interface not connected (no TCP)")); + return jus::FutureBase(_transactionId, true, obj, _callback); } - jus::GateWayClient::Observer obs; - ejson::Object localData; + jus::FutureBase tmpFuture(_transactionId, _callback); { std::unique_lock lock(m_mutex); - auto it = m_actions.begin(); - while (it != m_actions.end()) { - if (it->first != id) { + m_pendingCall.push_back(tmpFuture); + } + _srv->SendData(_callerId, _obj); + JUS_VERBOSE("Send JSON [STOP]"); + return tmpFuture; +} + + + +void jus::GateWayClient::returnMessage(ejson::Object _data) { + jus::FutureBase future; + { + uint64_t tid = _data["id"].toNumber().get(); + if (tid == 0) { + if (_data["error"].toString().get() == "PROTOCOL-ERROR") { + JUS_ERROR("Get a Protocol error ..."); + std::unique_lock lock(m_mutex); + for (auto &it : m_pendingCall) { + if (it.isValid() == false) { + continue; + } + it.setAnswer(_data); + } + m_pendingCall.clear(); + } else { + JUS_ERROR("call with no ID ==> error ..."); + } + return; + } + std::unique_lock lock(m_mutex); + auto it = m_pendingCall.begin(); + while (it != m_pendingCall.end()) { + if (it->isValid() == false) { + it = m_pendingCall.erase(it); + continue; + } + if (it->getTransactionId() != tid) { ++it; continue; } - obs = (*it).second; - m_actions.erase(it); + future = *it; + it = m_pendingCall.erase(it); break; } - if (obs == nullptr) { - JUS_ERROR("gateway reject transaction ... (not find answer)" << _data.generateHumanString()); - return; - } } - obs(_data); - if (id >= 0) { - m_interfaceClient.write(_data.generateMachineString()); - } else { + if (future.isValid() == false) { JUS_WARNING("Action to do ..."); + return; } -} \ No newline at end of file + future.setAnswer(_data); +} + diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 32ca74a..667fea4 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include @@ -16,7 +18,6 @@ namespace jus { class GateWay; class GateWayClient { private: - using Observer = std::function; enum class state { unconnect, // starting sate connect, // just get a TCP connection @@ -39,9 +40,7 @@ namespace jus { std::string m_userConnectionName; std::string m_clientName; std::vector m_clientgroups; - std::mutex m_mutex; - std::vector> m_actions; - int32_t m_transactionLocalId; + std::vector m_clientServices; public: GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface); virtual ~GateWayClient(); @@ -54,6 +53,28 @@ namespace jus { || m_uid2 == _id; } bool isAlive(); + + + private: + std::mutex m_mutex; + std::vector m_pendingCall; + int32_t m_transactionLocalId; + jus::FutureBase callJson(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); + uint64_t getId(); + public: + template + jus::FutureBase call(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, _ARGS&&... _args) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(_callerId, _srv, id, callElem); + } + template + jus::FutureBase callAction(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(_callerId, _srv, id, callElem, _callback); + } + jus::FutureBase callActionForward(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback); }; } diff --git a/jus/GateWayService.cpp b/jus/GateWayService.cpp index f60167c..4edba76 100644 --- a/jus/GateWayService.cpp +++ b/jus/GateWayService.cpp @@ -38,8 +38,8 @@ void jus::GateWayService::stop() { m_interfaceClient.disconnect(); } -void jus::GateWayService::SendData(int32_t _userSessionId, ejson::Object _data) { - _data.add("client-id", ejson::String(etk::to_string(_userSessionId))); +void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) { + _data.add("client-id", ejson::Number(_userSessionId)); JUS_DEBUG("Send Service: " << _data.generateHumanString()); m_interfaceClient.write(_data.generateMachineString()); } @@ -76,7 +76,7 @@ void jus::GateWayService::onServiceData(std::string _value) { JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'"); return; } - uint64_t userSessionId = etk::string_to_uint64_t(data["client-id"].toString().get()); + uint64_t userSessionId = data["client-id"].toNumber().getU64(); data.remove("client-id"); data.remove("action"); m_gatewayInterface->answer(userSessionId, data); diff --git a/jus/GateWayService.h b/jus/GateWayService.h index f3fa829..ea2afc1 100644 --- a/jus/GateWayService.h +++ b/jus/GateWayService.h @@ -26,7 +26,7 @@ namespace jus { void stop(); void onServiceData(std::string _value); public: - void SendData(int32_t _userSessionId, ejson::Object _data); + void SendData(uint64_t _userSessionId, ejson::Object _data); const std::string& getName() { return m_name; } diff --git a/jus/Service.cpp b/jus/Service.cpp index 435cecb..466c484 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -84,11 +84,11 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) { // Gateway just aswer a keep alive information ... // Nothing to do ... } else if (event == "new") { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + uint64_t clientId = _obj["client-id"].toNumber().getU64(); std::string userName = _obj["user"].toString().get(); clientConnect(clientId, userName); } else if (event == "delete") { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + uint64_t clientId = _obj["client-id"].toNumber().getU64(); clientDisconnect(clientId); } else { JUS_ERROR("Unknow event: '" << event << "'"); @@ -96,9 +96,9 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) { return ejson::Null(); } if (_obj.valueExist("call") == true) { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + uint64_t clientId = _obj["client-id"].toNumber().getU64(); ejson::Object tmpp = callJson2(clientId, _obj); - tmpp.add("client-id", ejson::String(etk::to_string(clientId))); + tmpp.add("client-id", ejson::Number(clientId)); return tmpp; } ejson::Object tmpp; diff --git a/jus/ServiceRemote.cpp b/jus/ServiceRemote.cpp index 671f360..0fde772 100644 --- a/jus/ServiceRemote.cpp +++ b/jus/ServiceRemote.cpp @@ -28,7 +28,7 @@ uint64_t jus::ServiceRemote::getId() { return m_clientInterface->getId(); } -jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj) { - return m_clientInterface->callJson(_transactionId, _obj); +jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { + return m_clientInterface->callJson(_transactionId, _obj, _callback); } diff --git a/jus/ServiceRemote.h b/jus/ServiceRemote.h index a659f26..199c704 100644 --- a/jus/ServiceRemote.h +++ b/jus/ServiceRemote.h @@ -25,7 +25,7 @@ namespace jus { ~ServiceRemote(); bool exist(); private: - jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); + jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); uint64_t getId(); public: template @@ -34,6 +34,12 @@ namespace jus { ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); return callJson(id, callElem); } + template + jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, _callback); + } }; } diff --git a/tools/system-user/appl/main.cpp b/tools/system-user/appl/main.cpp index 51a17f7..2b8aa73 100644 --- a/tools/system-user/appl/main.cpp +++ b/tools/system-user/appl/main.cpp @@ -54,6 +54,9 @@ namespace appl { // No specificity for this client (in case it have no special right) return out; } + if (client["tocken"].toString().get() != "") { + out.push_back("connected"); + } // TODO: check banishing ... ejson::Array groups = client["group"].toArray(); for (auto it : groups) { @@ -81,6 +84,24 @@ namespace appl { } return false; } + bool checkAuth(const std::string& _password) { + std::unique_lock lock(m_mutex); + std::string pass = m_database["password"].toString().get(); + if (pass == "") { + // pb password + return false; + } + if (pass == _password) { + return true; + } + return false; + } + std::vector filterServices(const std::string& _clientName, std::vector _inputList) { + std::unique_lock lock(m_mutex); + std::vector out; + // TODO: ... + return out; + } }; class UserManager { @@ -137,41 +158,29 @@ namespace appl { } return out; } - std::vector getServices(std::string _clientName) { - std::vector out; - if (m_user == nullptr) { - return out; - } - if (_clientName == m_user->getName()) { - out.push_back(SERVICE_NAME); - } - return out; - } bool checkTocken(std::string _clientName, std::string _tocken) { return m_user->checkTocken(_clientName, _tocken); } + bool checkAuth(std::string _password) { + return m_user->checkAuth(_password); + } + std::vector filterServices(std::string _clientName, std::vector _currentList) { + return m_user->filterServices(_clientName, _currentList); + } }; } int main(int _argc, const char *_argv[]) { etk::init(_argc, _argv); - appl::UserManager userMng; - jus::ServiceType serviceInterface(userMng); - serviceInterface.setDescription("user interface management"); - serviceInterface.setVersion("0.1.0"); - serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com"); - serviceInterface.advertise("getGroups", &appl::SystemService::getGroups); - serviceInterface.setLastFuncDesc("Get list of group availlable for a client name"); - serviceInterface.addLastFuncParam("clientName", "Name of the client"); - serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken); - serviceInterface.advertise("getServices", &appl::SystemService::getServices); + std::string ip; + uint16_t port = 0; for (int32_t iii=0; iii<_argc ; ++iii) { std::string data = _argv[iii]; if (etk::start_with(data, "--ip=") == true) { - serviceInterface.propertyIp.set(std::string(&data[5])); + ip = std::string(&data[5]); } else if (etk::start_with(data, "--port=") == true) { - serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7]))); + port = etk::string_to_uint16_t(std::string(&data[7])); } else if ( data == "-h" || data == "--help") { APPL_PRINT(etk::getApplicationName() << " - help : "); @@ -183,7 +192,35 @@ int main(int _argc, const char *_argv[]) { } while (true) { APPL_INFO("==========================================================="); - APPL_INFO("== JUS service: " << SERVICE_NAME << " [START]"); + APPL_INFO("== JUS instanciate service: " << SERVICE_NAME << " [START]"); + APPL_INFO("==========================================================="); + appl::UserManager userMng; + jus::ServiceType serviceInterface(userMng); + if (ip != "") { + serviceInterface.propertyIp.set(ip); + } + if (port != 0) { + serviceInterface.propertyPort.set(port); + } + serviceInterface.setDescription("user interface management"); + serviceInterface.setVersion("0.1.0"); + serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com"); + serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken); + serviceInterface.setLastFuncDesc("Check if a user tocken is correct or not"); + serviceInterface.addLastFuncParam("clientName", "Name of the client"); + serviceInterface.addLastFuncParam("tocken", "String containing the Tocken"); + serviceInterface.advertise("checkAuth", &appl::SystemService::checkAuth); + serviceInterface.setLastFuncDesc("Check the password of the curent user"); + serviceInterface.addLastFuncParam("password", "client/user password"); + serviceInterface.advertise("getGroups", &appl::SystemService::getGroups); + serviceInterface.setLastFuncDesc("Get list of group availlable for a client name"); + serviceInterface.addLastFuncParam("clientName", "Name of the client"); + serviceInterface.advertise("filterServices", &appl::SystemService::filterServices); + serviceInterface.setLastFuncDesc("Filter a list of service with the cuurent profile of the user (restrict area)"); + serviceInterface.addLastFuncParam("clientName", "Name of the client"); + serviceInterface.addLastFuncParam("currentList", "Vector of name of the services"); + APPL_INFO("==========================================================="); + APPL_INFO("== JUS service: " << SERVICE_NAME << " [service instanciate]"); APPL_INFO("==========================================================="); serviceInterface.connect(SERVICE_NAME); if (serviceInterface.GateWayAlive() == false) {