diff --git a/jus/AbstractFunction.cpp b/jus/AbstractFunction.cpp index 9b7ab37..573fe2a 100644 --- a/jus/AbstractFunction.cpp +++ b/jus/AbstractFunction.cpp @@ -171,6 +171,14 @@ void jus::createParam(ejson::Object& _obj) { // Finish recursive parse ... } +enum jus::AbstractFunction::type jus::AbstractFunction::getType() const { + return m_type; +} + +void jus::AbstractFunction::setType(enum jus::AbstractFunction::type _type) { + m_type = _type; +} + const std::string& jus::AbstractFunction::getName() const { return m_name; } @@ -191,8 +199,33 @@ void jus::AbstractFunction::addParam(const std::string& _name, const std::string m_paramsDescription.push_back(std::make_pair(_name, _desc)); } +void jus::AbstractFunction::setReturn(const std::string& _desc) { + m_returnDescription = _desc; +} + +std::string jus::AbstractFunction::getPrototypeFull() const { + std::string out = getPrototypeReturn(); + out += " "; + out += m_name; + out += "("; + std::vector tmp = getPrototypeParam(); + for (size_t iii=0; iii namespace jus { class AbstractFunction { + public: + enum class type { + unknow, + global, + local, + service, + object, + }; + protected: + enum type m_type; + public: + enum type getType() const; + void setType(enum type _type); protected: std::string m_name; public: @@ -26,6 +39,10 @@ namespace jus { public: void setParam(int32_t _idParam, const std::string& _name, const std::string& _desc); void addParam(const std::string& _name, const std::string& _desc); + protected: + std::string m_returnDescription; + public: + void setReturn(const std::string& _desc); protected: AbstractFunction(const std::string& _name, const std::string& _desc=""); public: @@ -34,7 +51,10 @@ namespace jus { bool checkCompatibility(const ParamType& _type, const ejson::Value& _params); bool checkCompatibility(const ParamType& _type, const std::string& _params); public: + std::string getPrototypeFull() const; virtual std::string getPrototype() const = 0; + virtual std::string getPrototypeReturn() const = 0; + virtual std::vector getPrototypeParam() const = 0; virtual ejson::Value executeJson(const ejson::Array& _params, void* _class=nullptr) = 0; virtual std::string executeString(const std::vector& _params, void* _class=nullptr) = 0; }; diff --git a/jus/AbstractFunctionTypeClass.h b/jus/AbstractFunctionTypeClass.h index 4f58b77..dde876e 100644 --- a/jus/AbstractFunctionTypeClass.h +++ b/jus/AbstractFunctionTypeClass.h @@ -103,8 +103,21 @@ namespace jus { ret += ");"; return ret; } + std::string getPrototypeReturn() const override { + return m_returnType.getName(); + } + std::vector getPrototypeParam() const override { + std::vector out; + for (size_t iii=0; iii getPrototypeParam() const override { + std::vector out; + for (size_t iii=0; iiim_sendTime = std::chrono::steady_clock::now(); m_data->m_transactionId = _transactionId; m_data->m_isFinished = false; m_data->m_callbackFinish = _callback; @@ -38,16 +39,29 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob if (m_data == nullptr) { return; } + m_data->m_sendTime = std::chrono::steady_clock::now(); 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); + if (m_data->m_isFinished == true) { + m_data->m_receiveTime = std::chrono::steady_clock::now(); + if (m_data->m_callbackFinish != nullptr) { + m_data->m_callbackFinish(*this); + } } } +std::chrono::nanoseconds jus::FutureBase::getTransmitionTime() { + if (m_data == nullptr) { + return std::chrono::nanoseconds(0); + } + if (m_data->m_isFinished == false) { + return std::chrono::nanoseconds(0); + } + return m_data->m_receiveTime - m_data->m_sendTime; +} + jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) { m_data = _base.m_data; return *this; @@ -58,6 +72,7 @@ void jus::FutureBase::setAnswer(const ejson::Object& _returnValue) { JUS_ERROR(" Not a valid future ..."); return; } + m_data->m_receiveTime = std::chrono::steady_clock::now(); m_data->m_returnData = _returnValue; m_data->m_isFinished = true; if (m_data->m_callbackFinish != nullptr) { diff --git a/jus/FutureBase.h b/jus/FutureBase.h index 7d47c3c..70aeba2 100644 --- a/jus/FutureBase.h +++ b/jus/FutureBase.h @@ -28,6 +28,7 @@ namespace jus { FutureBase& waitFor(std::chrono::microseconds _delta = std::chrono::seconds(30)); FutureBase& waitUntil(std::chrono::steady_clock::time_point _endTime); ejson::Object getRaw(); + std::chrono::nanoseconds getTransmitionTime(); }; } diff --git a/jus/FutureData.h b/jus/FutureData.h index 742a7fa..d6aba8a 100644 --- a/jus/FutureData.h +++ b/jus/FutureData.h @@ -18,6 +18,8 @@ namespace jus { bool m_isFinished; ejson::Object m_returnData; ObserverFinish m_callbackFinish; + std::chrono::steady_clock::time_point m_sendTime; + std::chrono::steady_clock::time_point m_receiveTime; }; } diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index fe2beef..53f5501 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -351,21 +351,18 @@ void jus::GateWayClient::onClientData(std::string _value) { JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); } else { - JUS_ERROR("Add in link the name of the user in parameter ..."); - //data.remove("service"); - //transactionId callActionForward(m_uid, - *it, - data["call"].toString().get(), - data["param"].toArray(), - [=](jus::FutureBase _ret) { - ejson::Object tmpp = _ret.getRaw(); - JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << data["id"].toNumber().getU64()); - JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); - tmpp["id"].toNumber().set(data["id"].toNumber().getU64()); - JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); - m_interfaceClient.write(tmpp.generateMachineString()); - }); + *it, + data["call"].toString().get(), + data["param"].toArray(), + [=](jus::FutureBase _ret) { + ejson::Object tmpp = _ret.getRaw(); + JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << data["id"].toNumber().getU64()); + JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); + tmpp["id"].toNumber().set(data["id"].toNumber().getU64()); + JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); + m_interfaceClient.write(tmpp.generateMachineString()); + }); } } } diff --git a/jus/RemoteProcessCall.cpp b/jus/RemoteProcessCall.cpp index 1cd9450..79505fd 100644 --- a/jus/RemoteProcessCall.cpp +++ b/jus/RemoteProcessCall.cpp @@ -5,15 +5,50 @@ */ #include - -std::vector m_listFunction; +jus::RemoteProcessCall::RemoteProcessCall() : + m_type("UNKNOW"){ + advertise("getDescription", &jus::RemoteProcessCall::getDescription); + setLastFuncDesc("Get description"); + addLastFuncReturn("String version of the service number separate with dot with -dev at the end if developpement version, and '-number' or integration version uipdate : 1.5.2 or 1.8-dev 1.5.2-55"); + + advertise("getVersion", &jus::RemoteProcessCall::getVersion); + setLastFuncDesc("Get version"); + addLastFuncReturn("String version of the service number separate with dot with -dev at the end if developpement version, and '-number' or integration version uipdate : 1.5.2 or 1.8-dev 1.5.2-55"); + + advertise("getType", &jus::RemoteProcessCall::getType); + setLastFuncDesc("Get type"); + addLastFuncReturn("String of generic type of the service base on TYPE-ENTERPRISE.ENTERPRISE-NAME.SERVICE-TYPE/VERSION_PROTOCOL"); + + advertise("getAuthors", &jus::RemoteProcessCall::getAuthors2); + setLastFuncDesc("Get List of developper/maintainer"); + addLastFuncReturn("list of personnes: 'NAME surname '"); + + advertise("getFunctions", &jus::RemoteProcessCall::getFunctions); + setLastFuncDesc("Get List of function availlable (filter with right)"); + addLastFuncReturn("list of function name"); + + advertise("getFunctionSignature", &jus::RemoteProcessCall::getFunctionSignature); + addLastFuncParam("func", "function name"); + setLastFuncDesc("Get List type of return and after the parameters"); + addLastFuncReturn("list of element type"); + + advertise("getFunctionPrototype", &jus::RemoteProcessCall::getFunctionPrototype); + addLastFuncParam("func", "function name"); + setLastFuncDesc("Get List type of return and after the parameters"); + addLastFuncReturn("list of element type"); + + advertise("getFunctionDescription", &jus::RemoteProcessCall::getFunctionDescription); + addLastFuncParam("func", "function name"); + setLastFuncDesc("get function description"); + addLastFuncReturn("generic string"); +} void jus::RemoteProcessCall::setDescription(const std::string& _desc) { m_description = _desc; } -const std::string& jus::RemoteProcessCall::getDescription() const { +std::string jus::RemoteProcessCall::getDescription() { return m_description; } @@ -21,7 +56,7 @@ void jus::RemoteProcessCall::setVersion(const std::string& _desc) { m_version = _desc; } -const std::string& jus::RemoteProcessCall::getVersion() const { +std::string jus::RemoteProcessCall::getVersion() { return m_version; } @@ -33,6 +68,14 @@ const std::vector>& jus::RemoteProcessCall::g return m_authors; } +std::vector jus::RemoteProcessCall::getAuthors2() { + std::vector out; + for (auto &it : m_authors) { + out.push_back(it.first + "<" + it.second + ">"); + } + return out; +} + void jus::RemoteProcessCall::setLastFuncDesc(const std::string& _desc) { if (m_listFunction.size() == 0) { JUS_ERROR("Can not set description to a function with no function advertise before ..."); @@ -84,3 +127,116 @@ void jus::RemoteProcessCall::setFuncParam(const std::string& _funcName, int32_t } JUS_ERROR("function '" << _funcName << "' des not exist"); } + +void jus::RemoteProcessCall::addLastFuncReturn(const std::string& _desc) { + if (m_listFunction.size() == 0) { + JUS_ERROR("Can not set return to a function with no function advertise before ..."); + return; + } + if (m_listFunction[m_listFunction.size()-1] == nullptr) { + JUS_ERROR("Last element is nullptr ... ==> what are you doing??"); + return; + } + m_listFunction[m_listFunction.size()-1]->setReturn(_desc); +} + +void jus::RemoteProcessCall::setFuncReturn(const std::string& _funcName, const std::string& _desc) { + for (auto &it : m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() != _funcName) { + continue; + } + it->setReturn(_desc); + return; + } + JUS_ERROR("function '" << _funcName << "' des not exist"); +} + + +std::string jus::RemoteProcessCall::getType() { + return m_type; +} +void jus::RemoteProcessCall::setType(const std::string& _type, uint16_t _version) { + m_type = _type + "/" + etk::to_string(_version); +} + + +std::vector jus::RemoteProcessCall::getFunctions() { + std::vector out; + for (auto &it: m_listFunction) { + if (it == nullptr) { + continue; + } + /* + if (isFunctionAuthorized(it->getName()) == false) { + continue; + } + */ + out.push_back(it->getName()); + } + return out; +} + +std::vector jus::RemoteProcessCall::getFunctionSignature(std::string _funcName) { + /* + if (isFunctionAuthorized(_funcName) == false) { + return std::vector(); + } + */ + for (auto &it: m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() != _funcName) { + continue; + } + std::vector out; + out = it->getPrototypeParam(); + out.insert(out.begin(), it->getPrototypeReturn()); + return out; + } + return std::vector(); +} + +std::string jus::RemoteProcessCall::getFunctionPrototype(std::string _funcName) { + /* + if (isFunctionAuthorized(_funcName) == false) { + return ""; + } + */ + for (auto &it: m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() != _funcName) { + continue; + } + return it->getPrototypeFull(); + } + return ""; +} + +std::string jus::RemoteProcessCall::getFunctionDescription(std::string _funcName) { + /* + if (isFunctionAuthorized(_funcName) == false) { + return std::string("UNKNOW Function: ") + _funcName; + } + */ + for (auto &it: m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() != _funcName) { + continue; + } + return it->getDescription(); + } + return ""; + +} + +bool jus::RemoteProcessCall::isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName) { + return true; +} diff --git a/jus/RemoteProcessCall.h b/jus/RemoteProcessCall.h index 79c783a..6b23962 100644 --- a/jus/RemoteProcessCall.h +++ b/jus/RemoteProcessCall.h @@ -14,29 +14,47 @@ namespace jus { class RemoteProcessCall { + public: + RemoteProcessCall(); protected: std::vector m_listFunction; protected: std::string m_description; public: void setDescription(const std::string& _desc); - const std::string& getDescription() const; + std::string getDescription(); protected: std::string m_version; public: void setVersion(const std::string& _desc); - const std::string& getVersion() const; + std::string getVersion(); protected: std::vector> m_authors; public: void addAuthor(const std::string& _name, const std::string& _email); const std::vector>& getAuthors() const; + std::vector getAuthors2(); + protected: + std::string m_type; + public: + std::string getType(); + void setType(const std::string& _type, uint16_t _version); + public: + std::vector getFunctions(); + std::vector getFunctionSignature(std::string _funcName); + std::string getFunctionPrototype(std::string _funcName); + std::string getFunctionDescription(std::string _funcName); public: void setLastFuncDesc(const std::string& _desc); void setFuncDesc(const std::string& _funcName, const std::string& _desc); void addLastFuncParam(const std::string& _name, const std::string& _desc); void setFuncParam(const std::string& _funcName, int32_t _idParam, const std::string& _name, const std::string& _desc); + void addLastFuncReturn(const std::string& _desc); + void setFuncReturn(const std::string& _funcName, const std::string& _desc); + protected: + virtual bool isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName); public: + // Add global fuction (no link with this class) template void advertise(const std::string& _name, @@ -52,6 +70,38 @@ namespace jus { } } AbstractFunction* tmp = createAbstractFunctionDirect(_name, _desc, _func); + if (tmp == nullptr) { + JUS_ERROR("can not create abstract function ... '" << _name << "'"); + return; + } + tmp->setType(jus::AbstractFunction::type::global); + JUS_INFO("Add function '" << _name << "' in global mode"); + m_listFunction.push_back(tmp); + } + // Add Local fuction (depend on this class) + template + void advertise(std::string _name, + JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args), + const std::string& _desc = "") { + _name = "sys." + _name; + for (auto &it : m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() == _name) { + JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'"); + return; + } + } + AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func); + if (tmp == nullptr) { + JUS_ERROR("can not create abstract function ... '" << _name << "'"); + return; + } + tmp->setType(jus::AbstractFunction::type::local); + JUS_INFO("Add function '" << _name << "' in local mode"); m_listFunction.push_back(tmp); } }; diff --git a/jus/Service.cpp b/jus/Service.cpp index b7a0abc..cde150d 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -12,18 +12,27 @@ #include - - jus::Service::Service() : propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp), propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort) { m_interfaceClient.connect(this, &jus::Service::onClientData); + + advertise("getExtention", &jus::Service::getExtention); + setLastFuncDesc("Get List of availlable extention of this service"); + addLastFuncReturn("A list of extention register in the service"); + } jus::Service::~Service() { } + +std::vector jus::Service::getExtention() { + return std::vector(); +} + + void jus::Service::onClientData(std::string _value) { ejson::Object request(_value); ejson::Value tmpID = request["id"]; @@ -98,17 +107,19 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) { return ejson::Null(); } ejson::Object tmpp; + uint64_t clientId = _obj["client-id"].toNumber().getU64(); if (_obj.valueExist("call") == true) { - uint64_t clientId = _obj["client-id"].toNumber().getU64(); std::string call = _obj["call"].toString().get(); - if (etk::start_with(call, "srv.") == true) { - tmpp.add("error", ejson::String("NOT-IMPLEMENTED-ACTION **")); - } else { + if (isFunctionAuthorized(clientId, call) == true) { tmpp = callJson2(clientId, _obj); + tmpp.add("client-id", ejson::Number(clientId)); + return tmpp; + } else { + tmpp.add("error", ejson::String("NOT-AUTHORIZED-FUNCTION")); } - tmpp.add("client-id", ejson::Number(clientId)); - return tmpp; + } else { + tmpp.add("error", ejson::String("NOT-IMPLEMENTED-FUNCTION")); } - tmpp.add("error", ejson::String("NOT-IMPLEMENTED-ACTION")); + tmpp.add("client-id", ejson::Number(clientId)); return tmpp; } diff --git a/jus/Service.h b/jus/Service.h index 498f546..2066e14 100644 --- a/jus/Service.h +++ b/jus/Service.h @@ -39,6 +39,15 @@ namespace jus { const std::vector& getGroups() { return m_groups; } + private: + std::vector m_listAthorizedFunction; + public: + void addAuthorized(const std::string& _funcName) { + m_listAthorizedFunction.push_back(_funcName); + } + bool isFunctionAuthorized(const std::string& _funcName) { + return std::find(m_listAthorizedFunction.begin(), m_listAthorizedFunction.end(), _funcName) != m_listAthorizedFunction.end(); + } }; } namespace jus { @@ -77,21 +86,16 @@ namespace jus { // Genenric function call: ejson::Value callJson(const ejson::Object& _obj); virtual ejson::Object callJson2(size_t _clientId, const ejson::Object& _obj) = 0; - }; - template - class ServiceType : public jus::Service { - private: - JUS_USER_ACCESS& m_getUserInterface; - // no need of shared_ptr or unique_ptr (if service die all is lost and is client die, the gateway notify us...) - std::map, ememory::SharedPtr>> m_interface; - + std::vector getExtention(); public: + // Add Local fuction (depend on this class) template - void advertise(const std::string& _name, + void advertise(std::string _name, JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args), const std::string& _desc = "") { + _name = "srv." + _name; for (auto &it : m_listFunction) { if (it == nullptr) { continue; @@ -102,12 +106,61 @@ namespace jus { } } AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func); + if (tmp == nullptr) { + JUS_ERROR("can not create abstract function ... '" << _name << "'"); + return; + } + tmp->setType(jus::AbstractFunction::type::service); + JUS_INFO("Add function '" << _name << "' in local mode"); + m_listFunction.push_back(tmp); + } + }; + template + class ServiceType : public jus::Service { + private: + JUS_USER_ACCESS& m_getUserInterface; + // no need of shared_ptr or unique_ptr (if service die all is lost and is client die, the gateway notify us...) + std::map, ememory::SharedPtr>> m_interface; + public: + template + void advertise(const std::string& _name, + JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args), + const std::string& _desc = "") { + if (etk::start_with(_name, "srv.") == true) { + JUS_ERROR("Advertise function start with 'srv.' is not permited ==> only allow for internal service: '" << _name << "'"); + return; + } + for (auto &it : m_listFunction) { + if (it == nullptr) { + continue; + } + if (it->getName() == _name) { + JUS_ERROR("Advertise function already bind .. ==> can not be done...: '" << _name << "'"); + return; + } + } + AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func); + if (tmp == nullptr) { + JUS_ERROR("can not create abstract function ... '" << _name << "'"); + return; + } + tmp->setType(jus::AbstractFunction::type::object); + JUS_INFO("Add function '" << _name << "' in object mode"); m_listFunction.push_back(tmp); } ServiceType(JUS_USER_ACCESS& _interface): m_getUserInterface(_interface) { } + bool isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName) { + auto it = m_interface.find(_clientSessionID); + if (it == m_interface.end()) { + return false; + } + return it->second.first->isFunctionAuthorized(_funcName); + } void clientConnect(uint64_t _clientSessionID, const std::string& _userName, const std::string& _clientName, const std::vector& _groups) { std::unique_lock lock(m_mutex); JUS_DEBUG("connect: " << _clientSessionID << " to '" << _userName << "'"); @@ -116,6 +169,13 @@ namespace jus { ememory::SharedPtr tmpProperty = std::make_shared(_clientName, _groups); ememory::SharedPtr tmpSrv = std::make_shared(m_getUserInterface.getUser(_userName), tmpProperty); m_interface.insert(std::make_pair(_clientSessionID, std::make_pair(tmpProperty, tmpSrv))); + // enable list of function availlable: + for (auto &it : m_listFunction) { + if (it == nullptr) { + continue; + } + tmpProperty->addAuthorized(it->getName()); + } } void clientDisconnect(uint64_t _clientSessionID) { std::unique_lock lock(m_mutex); @@ -162,8 +222,24 @@ namespace jus { if (it2->getName() != call) { continue; } - JUS_TYPE_SERVICE* elem = it->second.second.get(); - return it2->executeJson(param, (void*)elem).toObject(); + switch (it2->getType()) { + case jus::AbstractFunction::type::object: { + JUS_TYPE_SERVICE* elem = it->second.second.get(); + return it2->executeJson(param, (void*)elem).toObject(); + } + case jus::AbstractFunction::type::local: { + return it2->executeJson(param, (void*)((RemoteProcessCall*)this)).toObject(); + } + case jus::AbstractFunction::type::service: { + return it2->executeJson(param, (void*)this).toObject(); + } + case jus::AbstractFunction::type::global: { + return it2->executeJson(param, nullptr).toObject(); + } + case jus::AbstractFunction::type::unknow: + JUS_ERROR("Can not call unknow type ..."); + break; + } } out.add("error", ejson::String("FUNCTION-UNKNOW")); return out; diff --git a/lutinParseSubFolders.txt b/lutinParseSubFolders.txt index bf3047a..cc4eea8 100644 --- a/lutinParseSubFolders.txt +++ b/lutinParseSubFolders.txt @@ -1,4 +1,5 @@ -tools/system-gateway tools/system-user +tools/system-gateway +tools/picture test/client test/service1 \ No newline at end of file diff --git a/test/client/appl/main.cpp b/test/client/appl/main.cpp index 4b36197..f2057b3 100644 --- a/test/client/appl/main.cpp +++ b/test/client/appl/main.cpp @@ -93,25 +93,71 @@ int main(int _argc, const char *_argv[]) { jus::Future> retCall = remoteServiceUser.call("getGroups", "clientTest1#atria-soft.com"); retCall.wait(); APPL_INFO("system-user.getGroups() = " << retCall.get()); - jus::Future retVersion = remoteServiceUser.call("srv.getVersion"); - jus::Future retType = remoteServiceUser.call("srv.getType"); + jus::Future retDesc = remoteServiceUser.call("sys.getDescription"); + jus::Future retVersion = remoteServiceUser.call("sys.getVersion"); + jus::Future retType = remoteServiceUser.call("sys.getType"); jus::Future> retExtention = remoteServiceUser.call("srv.getExtention"); - jus::Future> retMaintainer = remoteServiceUser.call("srv.getMaintainer"); - jus::Future> retFuctions = remoteServiceUser.call("srv.getFunctions"); - jus::Future> retFunctionSignature = remoteServiceUser.call("srv.getFunctionSignature", "filterServices"); - jus::Future retFunctionPrototype = remoteServiceUser.call("srv.getFunctionPrototype", "filterServices"); - jus::Future retFunctionHelp = remoteServiceUser.call("srv.getFunctionHelp", "filterServices"); + jus::Future> retMaintainer = remoteServiceUser.call("sys.getAuthors"); + retDesc.wait(); retVersion.wait(); retType.wait(); retExtention.wait(); retMaintainer.wait(); - retFuctions.wait(); - retFunctionSignature.wait(); - retFunctionPrototype.wait(); - retFunctionHelp.wait(); - - APPL_INFO("system-user.getClientGroups() = " << retCall.get()); - + APPL_INFO("Service: system-user"); + APPL_INFO(" version : " << retVersion.get()); + APPL_INFO(" type : " << retType.get()); + APPL_INFO(" Extention : " << retExtention.get().size()); + for (auto &it : retExtention.get()) { + APPL_INFO(" - " << it); + } + APPL_INFO(" maintainer: " << retMaintainer.get().size()); + for (auto &it : retMaintainer.get()) { + APPL_INFO(" - " << it); + } + APPL_INFO(" description:"); + APPL_INFO(" " << retDesc.get()); + APPL_INFO(" Function List:"); + jus::Future> retFuctions = remoteServiceUser.call("sys.getFunctions").wait(); + for (auto it : retFuctions.get()) { + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); + jus::Future retFunctionPrototype = remoteServiceUser.call("sys.getFunctionPrototype", it); + jus::Future retFunctionHelp = remoteServiceUser.call("sys.getFunctionDescription", it); + retFunctionPrototype.wait(); + retFunctionHelp.wait(); + std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now(); + APPL_INFO(" - " << retFunctionPrototype.get()); + APPL_INFO(" " << retFunctionHelp.get()); + APPL_INFO(" IO1=" << int64_t(retFunctionPrototype.getTransmitionTime().count()/1000)/1000.0 << " ms"); + APPL_INFO(" IO2=" << int64_t(retFunctionHelp.getTransmitionTime().count()/1000)/1000.0 << " ms"); + APPL_INFO(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms"); + } + } + + APPL_INFO(" ----------------------------------"); + APPL_INFO(" -- Get service picture"); + APPL_INFO(" ----------------------------------"); + + jus::ServiceRemote remoteServicePicture = client1.getService("picture"); + if (remoteServicePicture.exist() == true) { + jus::Future> retCall = remoteServicePicture.call("getAlbums").wait(); + APPL_INFO(" album list: "); + for (auto &it : retCall.get()) { + jus::Future retCount = remoteServicePicture.call("getAlbumCount", it).wait(); + if (retCount.get() != 0) { + APPL_INFO(" - " << it << " / " << retCount.get() << " images"); + } else { + APPL_INFO(" - " << it); + } + jus::Future> retCall2 = remoteServicePicture.call("getSubAlbums", it).wait(); + for (auto &it2 : retCall2.get()) { + jus::Future retCount2 = remoteServicePicture.call("getAlbumCount", it2).wait(); + if (retCount2.get() != 0) { + APPL_INFO(" - " << it2 << " / " << retCount2.get() << " images"); + } else { + APPL_INFO(" - " << it2); + } + } + } } int32_t iii=0; while (iii < 3) { diff --git a/tools/picture/appl/debug.cpp b/tools/picture/appl/debug.cpp new file mode 100644 index 0000000..862cc27 --- /dev/null +++ b/tools/picture/appl/debug.cpp @@ -0,0 +1,12 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include + +int32_t appl::getLogId() { + static int32_t g_val = elog::registerInstance("jus-picture"); + return g_val; +} diff --git a/tools/picture/appl/debug.h b/tools/picture/appl/debug.h new file mode 100644 index 0000000..d422118 --- /dev/null +++ b/tools/picture/appl/debug.h @@ -0,0 +1,40 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include + +namespace appl { + int32_t getLogId(); +}; + +#define APPL_BASE(info,data) ELOG_BASE(appl::getLogId(),info,data) + +#define APPL_PRINT(data) APPL_BASE(-1, data) +#define APPL_CRITICAL(data) APPL_BASE(1, data) +#define APPL_ERROR(data) APPL_BASE(2, data) +#define APPL_WARNING(data) APPL_BASE(3, data) +#ifdef DEBUG + #define APPL_INFO(data) APPL_BASE(4, data) + #define APPL_DEBUG(data) APPL_BASE(5, data) + #define APPL_VERBOSE(data) APPL_BASE(6, data) + #define APPL_TODO(data) APPL_BASE(4, "TODO : " << data) +#else + #define APPL_INFO(data) do { } while(false) + #define APPL_DEBUG(data) do { } while(false) + #define APPL_VERBOSE(data) do { } while(false) + #define APPL_TODO(data) do { } while(false) +#endif + +#define APPL_ASSERT(cond,data) \ + do { \ + if (!(cond)) { \ + APPL_CRITICAL(data); \ + assert(!#cond); \ + } \ + } while (0) + + diff --git a/tools/picture/appl/main.cpp b/tools/picture/appl/main.cpp new file mode 100644 index 0000000..bc78a46 --- /dev/null +++ b/tools/picture/appl/main.cpp @@ -0,0 +1,242 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +namespace appl { + class User { + private: + std::mutex m_mutex; + std::string m_userName; + std::string m_basePath; + public: + User(const std::string& _userName) : + m_userName(_userName) { + std::unique_lock lock(m_mutex); + APPL_WARNING("new USER: " << m_userName); + m_basePath = std::string("USERDATA:") + m_userName + "/"; + } + ~User() { + std::unique_lock lock(m_mutex); + APPL_WARNING("delete USER [START]"); + APPL_WARNING("delete USER [STOP]"); + } + // Return the list of root albums + std::vector getAlbums() { + return getSubAlbums(""); + } + // Get the list of sub album + std::vector getSubAlbums(const std::string& _parrentAlbum) { + std::unique_lock lock(m_mutex); + std::vector out; + etk::FSNode node(m_basePath + _parrentAlbum); + std::vector tmpList = node.folderGetSubList(false, true, false, false); + for (auto &it : tmpList) { + if (it == nullptr) { + continue; + } + if ( _parrentAlbum.size() == 0 + || _parrentAlbum[_parrentAlbum.size()-1] == '/') { + out.push_back(_parrentAlbum + it->getNameFile()); + } else { + out.push_back(_parrentAlbum + "/" + it->getNameFile()); + } + } + return out; + } + uint32_t getAlbumCount(const std::string& _album) { + std::unique_lock lock(m_mutex); + etk::FSNode node(m_basePath + _album); + std::vector tmpList = node.folderGetSubList(false, false, true, false); + uint32_t nbElem = 0; + for (auto &it : tmpList) { + if (it == nullptr) { + continue; + } + if ( etk::end_with(it->getNameFile(), ".svg", false) == true + || etk::end_with(it->getNameFile(), ".bmp", false) == true + || etk::end_with(it->getNameFile(), ".png", false) == true + || etk::end_with(it->getNameFile(), ".jpg", false) == true) { + nbElem++; + } + } + return nbElem; + } + // Return the list of the album files + std::vector getAlbumListPicture(const std::string& _album, uint32_t _startId, uint32_t _stopId) { + std::unique_lock lock(m_mutex); + std::vector out; + return std::vector(); + } + /* + // Return a File Data (might be a picture .tiff/.png/.jpg) + jus::File getAlbumPicture(const std::string& _pictureName) { + std::unique_lock lock(m_mutex); + return jus::File(); + } + // Return a global UTC time + jus::Time getAlbumPictureTime(const std::string& _pictureName) { + std::unique_lock lock(m_mutex); + return jus::Time(); + } + // Return a Geolocalization information (latitude, longitude) + jus::Geo getAlbumPictureGeoLocalization(const std::string& _pictureName) { + std::unique_lock lock(m_mutex); + return jus::Geo(); + } + */ + }; + + class UserManager { + private: + std::mutex m_mutex; + std::map> m_listLoaded; + public: + UserManager() { + + } + ememory::SharedPtr getUser(const std::string& _userName) { + std::unique_lock lock(m_mutex); + auto it = m_listLoaded.find(_userName); + if (it != m_listLoaded.end()) { + // User already loaded: + return it->second; + } + // load New User: + ememory::SharedPtr tmp(new appl::User(_userName)); + m_listLoaded.insert(std::make_pair(_userName, tmp)); + return tmp; + } + }; + class PictureService { + private: + ememory::SharedPtr m_user; + private: + ememory::SharedPtr m_client; + public: + PictureService() { + APPL_WARNING("New PictureService ..."); + } + PictureService(ememory::SharedPtr _user, ememory::SharedPtr _client) : + m_user(_user), + m_client(_client) { + APPL_WARNING("New PictureService ... for user: "); + } + ~PictureService() { + APPL_WARNING("delete PictureService ..."); + } + public: + + std::vector getAlbums() { + return m_user->getAlbums(); + } + // Get the list of sub album + std::vector getSubAlbums(std::string _parrentAlbum) { + return m_user->getSubAlbums(_parrentAlbum); + } + uint32_t getAlbumCount(std::string _album) { + return m_user->getAlbumCount(_album); + } + // Return the list of the album files + std::vector getAlbumListPicture(std::string _album, uint32_t _startId, uint32_t _stopId) { + return m_user->getAlbumListPicture(_album, _startId, _stopId); + } + /* + // Return a File Data (might be a picture .tiff/.png/.jpg) + jus::File getAlbumPicture(std::string _pictureName) { + return m_user->getAlbumPicture(_pictureName); + } + // Return a global UTC time + jus::Time getAlbumPictureTime(std::string _pictureName) { + return m_user->getAlbumPictureTime(_pictureName); + } + // Return a Geolocalization information (latitude, longitude) + jus::Geo getAlbumPictureGeoLocalization(std::string _pictureName) { + return m_user->getAlbumPictureGeoLocalization(_pictureName); + } + */ + }; +} + + +int main(int _argc, const char *_argv[]) { + etk::init(_argc, _argv); + 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) { + ip = std::string(&data[5]); + } else if (etk::start_with(data, "--port=") == true) { + port = etk::string_to_uint16_t(std::string(&data[7])); + } else if ( data == "-h" + || data == "--help") { + APPL_PRINT(etk::getApplicationName() << " - help : "); + APPL_PRINT(" " << _argv[0] << " [options]"); + APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)"); + APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)"); + return -1; + } + } + while (true) { + APPL_INFO("==========================================================="); + 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("Picture Private Interface"); + serviceInterface.setVersion("0.1.0"); + serviceInterface.setType("PICTURE", 1); + serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com"); + + serviceInterface.advertise("getAlbums", &appl::PictureService::getAlbums); + serviceInterface.advertise("getSubAlbums", &appl::PictureService::getSubAlbums); + serviceInterface.advertise("getAlbumCount", &appl::PictureService::getAlbumCount); + serviceInterface.advertise("getAlbumListPicture", &appl::PictureService::getAlbumListPicture); + /* + serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture); + serviceInterface.advertise("getAlbumPictureTime", &appl::PictureService::getAlbumPictureTime); + serviceInterface.advertise("getAlbumPictureGeoLocalization", &appl::PictureService::getAlbumPictureGeoLocalization); + */ + APPL_INFO("==========================================================="); + APPL_INFO("== JUS service: " << SERVICE_NAME << " [service instanciate]"); + APPL_INFO("==========================================================="); + serviceInterface.connect(SERVICE_NAME); + if (serviceInterface.GateWayAlive() == false) { + APPL_INFO("==========================================================="); + APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] Can not connect to the GateWay"); + APPL_INFO("==========================================================="); + APPL_INFO("wait 5 second ..."); + usleep(5000000); + continue; + } + int32_t iii=0; + while (serviceInterface.GateWayAlive() == true) { + usleep(1000000); + serviceInterface.pingIsAlive(); + APPL_INFO("service in waiting ... " << iii << "/inf"); + iii++; + } + serviceInterface.disconnect(); + APPL_INFO("==========================================================="); + APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] GateWay Stop"); + APPL_INFO("==========================================================="); + } + return 0; +} diff --git a/tools/picture/lutin_jus-picture.py b/tools/picture/lutin_jus-picture.py new file mode 100644 index 0000000..2e7d985 --- /dev/null +++ b/tools/picture/lutin_jus-picture.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +import lutin.module as module +import lutin.tools as tools + + +def get_type(): + return "BINARY" + +def get_sub_type(): + return "TOOLS" + +def get_desc(): + return "JUS picture service" + +def get_licence(): + return "APACHE-2" + +def get_compagny_type(): + return "com" + +def get_compagny_name(): + return "atria-soft" + +def get_maintainer(): + return ["Mr DUPIN Edouard "] + +def create(target, module_name): + my_module = module.Module(__file__, module_name, get_type()) + my_module.add_export_path(tools.get_current_path(__file__)) + my_module.add_module_depend(['jus']) + my_module.add_src_file([ + 'appl/debug.cpp', + 'appl/main.cpp' + ]) + my_module.add_export_flag('c++', "-DSERVICE_NAME=\"\\\"" + module_name[4:] + "\\\"\"") + return my_module + + + diff --git a/tools/system-user/appl/main.cpp b/tools/system-user/appl/main.cpp index a69b9e3..865dea4 100644 --- a/tools/system-user/appl/main.cpp +++ b/tools/system-user/appl/main.cpp @@ -208,6 +208,7 @@ int main(int _argc, const char *_argv[]) { } serviceInterface.setDescription("user interface management"); serviceInterface.setVersion("0.1.0"); + serviceInterface.setType("USER", 1); 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");