/** @file * @author Edouard DUPIN * @copyright 2016, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #pragma once #include #include #include #include #include #include #include namespace jus { class ClientProperty { public: ClientProperty() {} private: std::string m_name; public: void setName(const std::string& _name) { m_name = _name; } const std::string& getName() { return m_name; } private: std::vector m_groups; public: void setGroups(std::vector _groups) { m_groups = _groups; } const std::vector& getGroups() { return m_groups; } }; } namespace jus { class Service : public eproperty::Interface, public jus::RemoteProcessCall { protected: std::mutex m_mutex; public: eproperty::Value propertyIp; eproperty::Value propertyPort; private: jus::TcpString m_interfaceClient; uint32_t m_id; std::vector m_newData; public: Service(); virtual ~Service(); void connect(const std::string& _serviceName, uint32_t _numberRetry = 1); void disconnect(); private: void onClientData(std::string _value); std::string asyncRead(); public: void pingIsAlive(); bool GateWayAlive(); private: void onPropertyChangeIp(); void onPropertyChangePort(); /** * @brief A extern client connect on specific user * @param[in] _clientSessionID Source session Id on the client * @param[in] _userName User name of the client to connect * @todo Set a relur like ==> service not availlable / service close / service maintenance / service right reject */ virtual void clientConnect(size_t _clientSessionID, const std::string& _userName) = 0; virtual void clientDisconnect(size_t _clientSessionID) = 0; // 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; public: template void advertise(const std::string& _name, JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args), const std::string& _desc = "") { 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); m_listFunction.push_back(tmp); } ServiceType(JUS_USER_ACCESS& _interface): m_getUserInterface(_interface) { } void clientConnect(uint64_t _clientSessionID, const std::string& _userName) { std::unique_lock lock(m_mutex); JUS_DEBUG("connect : " << _clientSessionID << " to '" << _userName << "'"); ememory::SharedPtr tmpProperty = std::make_shared(); ememory::SharedPtr tmpSrv = std::make_shared(m_getUserInterface.getUser(_userName), tmpProperty); m_interface.insert(std::make_pair(_clientSessionID, std::make_pair(tmpProperty, tmpSrv))); } void clientDisconnect(uint64_t _clientSessionID) { std::unique_lock lock(m_mutex); JUS_DEBUG("disconnect: " << _clientSessionID); auto it = m_interface.find(_clientSessionID); if (it == m_interface.end()) { JUS_WARNING("disconnect ==> Not find Client ID " << _clientSessionID); // noting to do ==> user never conected. return; } m_interface.erase(it); } void clientSetName(uint64_t _clientSessionID, const std::string& _clientName) { std::unique_lock lock(m_mutex); auto it = m_interface.find(_clientSessionID); if (it == m_interface.end()) { JUS_ERROR("Change the client property but client was not created ..."); return; } it->second.first->setName(_clientName); } void clientSetGroup(uint64_t _clientSessionID, const std::vector& _clientGroups) { std::unique_lock lock(m_mutex); auto it = m_interface.find(_clientSessionID); if (it == m_interface.end()) { JUS_ERROR("Change the client property but client was not created ..."); return; } it->second.first->setGroups(_clientGroups); } ejson::Object callJson2(uint64_t _clientSessionID, const ejson::Object& _obj) { ejson::Object out; auto it = m_interface.find(_clientSessionID); if (it == m_interface.end()) { out.add("error", ejson::String("CLIENT-UNKNOW")); return out; } std::string call = _obj["call"].toString().get(); const ejson::Array param = _obj["param"].toArray(); for (auto &it2 : m_listFunction) { if (it2 == nullptr) { continue; } if (it2->getName() != call) { continue; } JUS_TYPE_SERVICE* elem = it->second.second.get(); return it2->executeJson(param, (void*)elem).toObject(); } out.add("error", ejson::String("FUNCTION-UNKNOW")); return out; } }; }