diff --git a/jus/AbstractFunction.cpp b/jus/AbstractFunction.cpp new file mode 100644 index 0000000..6df9c7e --- /dev/null +++ b/jus/AbstractFunction.cpp @@ -0,0 +1,145 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include + +template<> bool convertJsonTo(const ejson::Value& _value) { + return _value.toBoolean().get(); +} +template<> float convertJsonTo(const ejson::Value& _value) { + return _value.toNumber().get(); +} +template<> double convertJsonTo(const ejson::Value& _value) { + return _value.toNumber().get(); +} +template<> int64_t convertJsonTo(const ejson::Value& _value) { + return int64_t(_value.toNumber().get()); +} +template<> int32_t convertJsonTo(const ejson::Value& _value) { + //_value.display(); + return int32_t(_value.toNumber().get()); +} +template<> int16_t convertJsonTo(const ejson::Value& _value) { + return int16_t(_value.toNumber().get()); +} +template<> int8_t convertJsonTo(const ejson::Value& _value) { + return int8_t(_value.toNumber().get()); +} +template<> uint64_t convertJsonTo(const ejson::Value& _value) { + return uint64_t(_value.toNumber().get()); +} +template<> uint32_t convertJsonTo(const ejson::Value& _value) { + return uint32_t(_value.toNumber().get()); +} +template<> uint16_t convertJsonTo(const ejson::Value& _value) { + return uint16_t(_value.toNumber().get()); +} +template<> uint8_t convertJsonTo(const ejson::Value& _value) { + return uint8_t(_value.toNumber().get()); +} +template<> std::string convertJsonTo(const ejson::Value& _value) { + //_value.display(); + return _value.toString().get(); +} + +template<> ejson::Value convertToJson(const bool& _value) { + return ejson::Boolean(_value); +} +template<> ejson::Value convertToJson(const float& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const double& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const int64_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const int32_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const int16_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const int8_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const uint64_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const uint32_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const uint16_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const uint8_t& _value) { + return ejson::Number(_value); +} +template<> ejson::Value convertToJson(const std::string& _value) { + return ejson::String(_value); +} + +template<> bool convertStringTo(const std::string& _value) { + return etk::string_to_bool(_value); +} +template<> float convertStringTo(const std::string& _value) { + return etk::string_to_float(_value); +} +template<> double convertStringTo(const std::string& _value) { + return etk::string_to_double(_value); +} +template<> int64_t convertStringTo(const std::string& _value) { + return etk::string_to_int64_t(_value); +} +template<> int32_t convertStringTo(const std::string& _value) { + return etk::string_to_int32_t(_value); +} +template<> int16_t convertStringTo(const std::string& _value) { + return etk::string_to_int16_t(_value); +} +template<> int8_t convertStringTo(const std::string& _value) { + return etk::string_to_int8_t(_value); +} +template<> uint64_t convertStringTo(const std::string& _value) { + return etk::string_to_uint64_t(_value); +} +template<> uint32_t convertStringTo(const std::string& _value) { + return etk::string_to_uint32_t(_value); +} +template<> uint16_t convertStringTo(const std::string& _value) { + return etk::string_to_uint16_t(_value); +} +template<> uint8_t convertStringTo(const std::string& _value) { + return etk::string_to_uint8_t(_value); +} +template<> std::string convertStringTo(const std::string& _value) { + return _value; +} + +bool AbstractFunction::checkCompatibility(const ParamType& _type, const ejson::Value& _params) { + if (createType() == _type) { + return _params.isBoolean(); + } + if ( createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type + || createType() == _type) { + return _params.isNumber(); + } + if (createType() == _type) { + return _params.isString(); + } + return false; +} +bool AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) { + return false; +} diff --git a/jus/AbstractFunction.h b/jus/AbstractFunction.h new file mode 100644 index 0000000..c40723d --- /dev/null +++ b/jus/AbstractFunction.h @@ -0,0 +1,56 @@ +/** @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 + +class AbstractFunction { + protected: + const std::string m_name; + public: + const std::string& getName() const { + return m_name; + } + protected: + const std::string m_description; + public: + const std::string& getDescription() const { + return m_description; + } + protected: + AbstractFunction(const std::string& _name, + const std::string& _desc): + m_name(_name), + m_description(_desc) { + + } + public: + virtual ~AbstractFunction() {}; + bool checkCompatibility(const ParamType& _type, const ejson::Value& _params); + bool checkCompatibility(const ParamType& _type, const std::string& _params); + public: + virtual std::string getPrototype() 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; +}; + +template +JUS_TYPE convertStringTo(const std::string& _value); + +template +JUS_TYPE convertJsonTo(const ejson::Value& _value); + +template +ejson::Value convertToJson(const JUS_TYPE& _value); +/* +template +class TypeList; +*/ + diff --git a/jus/AbstractFunctionTypeClass.cpp b/jus/AbstractFunctionTypeClass.cpp new file mode 100644 index 0000000..e69de29 diff --git a/jus/AbstractFunctionTypeClass.h b/jus/AbstractFunctionTypeClass.h new file mode 100644 index 0000000..0c7850f --- /dev/null +++ b/jus/AbstractFunctionTypeClass.h @@ -0,0 +1,175 @@ +/** @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 + +template +ejson::Value executeClassCallJson(JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + return convertToJson((*_pointer.*_func)((convertJsonTo(_params[idParam++]))...)); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + return convertToJson((*_pointer.*_func)(convertJsonTo(_params[idParam--])...)); + #else + #error Must be implemented ... + #endif + return ejson::Null(); +} + +template +ejson::Value executeClassCallJson(JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { + ejson::Object out; + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + (*_pointer.*_func)(convertJsonTo(_params[idParam--])...); + #else + #error Must be implemented ... + #endif + return ejson::Null(); +} + +template +std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector& _params) { + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + return etk::to_string((*_pointer.*_func)((convertStringTo(_params[idParam++]))...)); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + return etk::to_string((*_pointer.*_func)(convertStringTo(_params[idParam--])...)); + #else + #error Must be implemented ... + #endif + return ""; +} +template +std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector& _params) { + ejson::Object out; + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + (*_pointer.*_func)((convertStringTo(_params[idParam++]))...); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + (*_pointer.*_func)(convertStringTo(_params[idParam--])...); + #else + #error Must be implemented ... + #endif + return ""; +} + +template +class AbstractFunctionTypeClass: public AbstractFunction { + protected: + static const ParamType m_returnType; + static const ParamType m_paramType[sizeof...(JUS_TYPES)]; + public: + using functionType = JUS_RETURN (JUS_CLASS_TYPE::*)(JUS_TYPES...); + functionType m_function; + AbstractFunctionTypeClass(const std::string& _name, const std::string& _desc, functionType _fptr): + AbstractFunction(_name, _desc), + m_function(_fptr) { + } + std::string getPrototype() const override { + std::string ret; + ret += m_returnType.getName(); + ret += " "; + ret += m_name; + ret += "("; + for (size_t iii=0; iii& _params, void* _class) override { + JUS_CLASS_TYPE* tmpClass = (JUS_CLASS_TYPE*)_class; + std::string out; + // check parameter number + if (_params.size() != sizeof...(JUS_TYPES)) { + JUS_ERROR("Wrong number of Parameters ..."); + out += "error:WRONG-PARAMETER-NUMBER;"; + out += "error-help:request "; + out += etk::to_string(_params.size()); + out += " parameters and need "; + out += etk::to_string(sizeof...(JUS_TYPES)); + out += " parameters. prototype function:"; + out += getPrototype(); + return out; + } + // check parameter compatibility + for (size_t iii=0; iii +const ParamType AbstractFunctionTypeClass::m_returnType = createType(); + +template +const ParamType AbstractFunctionTypeClass::m_paramType[sizeof...(JUS_TYPES)] = {createType()...}; + + +template +AbstractFunction* createAbstractFunctionClass(const std::string& _name, const std::string& _desc, JUS_RETURN (JUS_CLASS_TYPE::*_fffp)(JUS_TYPES...)) { + return new AbstractFunctionTypeClass(_name, _desc, _fffp); +} + diff --git a/jus/AbstractFunctionTypeDirect.cpp b/jus/AbstractFunctionTypeDirect.cpp new file mode 100644 index 0000000..e69de29 diff --git a/jus/AbstractFunctionTypeDirect.h b/jus/AbstractFunctionTypeDirect.h new file mode 100644 index 0000000..fc18f82 --- /dev/null +++ b/jus/AbstractFunctionTypeDirect.h @@ -0,0 +1,173 @@ +/** @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 + +template +ejson::Value executeCallJson(JUS_RETURN (*_func)(JUS_TYPES...), const ejson::Array& _params) { + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + return convertToJson(_func((convertJsonTo(_params[idParam++]))...)); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + return convertToJson(_func(convertJsonTo(_params[idParam--])...)); + #else + #error Must be implemented ... + #endif + return ejson::Null(); +} + +template +ejson::Value executeCallJson(void (*_func)(JUS_TYPES...), const ejson::Array& _params) { + ejson::Object out; + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + _func((convertJsonTo(_params[idParam++]))...); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + _func(convertJsonTo(_params[idParam--])...); + #else + #error Must be implemented ... + #endif + return ejson::Null(); +} + +template +std::string executeCallString(JUS_RETURN (*_func)(JUS_TYPES...), const std::vector& _params) { + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + return etk::to_string(_func((convertStringTo(_params[idParam++]))...)); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + return etk::to_string(_func(convertStringTo(_params[idParam--])...)); + #else + #error Must be implemented ... + #endif + return ""; +} +template +std::string executeCallString(void (*_func)(JUS_TYPES...), const std::vector& _params) { + ejson::Object out; + #if defined(__clang__) + // clang generate a basic warning: + // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] + int32_t idParam = 0; + _func((convertStringTo(_params[idParam++]))...); + #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) + int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; + _func(convertStringTo(_params[idParam--])...); + #else + #error Must be implemented ... + #endif + return ""; +} + +template +class AbstractFunctionTypeDirect: public AbstractFunction { + protected: + static const ParamType m_returnType; + static const ParamType m_paramType[sizeof...(JUS_TYPES)]; + public: + using functionType = JUS_RETURN (*)(JUS_TYPES...); + functionType m_function; + AbstractFunctionTypeDirect(const std::string& _name, const std::string& _desc, functionType _fptr): + AbstractFunction(_name, _desc), + m_function(_fptr) { + } + std::string getPrototype() const override { + std::string ret; + ret += m_returnType.getName(); + ret += " "; + ret += m_name; + ret += "("; + for (size_t iii=0; iii& _params, void* _class) override { + std::string out; + // check parameter number + if (_params.size() != sizeof...(JUS_TYPES)) { + JUS_ERROR("Wrong number of Parameters ..."); + out += "error:WRONG-PARAMETER-NUMBER;"; + out += "error-help:request "; + out += etk::to_string(_params.size()); + out += " parameters and need "; + out += etk::to_string(sizeof...(JUS_TYPES)); + out += " parameters. prototype function:"; + out += getPrototype(); + return out; + } + // check parameter compatibility + for (size_t iii=0; iii +const ParamType AbstractFunctionTypeDirect::m_returnType = createType(); + +template +const ParamType AbstractFunctionTypeDirect::m_paramType[sizeof...(JUS_TYPES)] = {createType()...}; + + +template +AbstractFunction* createAbstractFunctionDirect(const std::string& _name, const std::string& _desc, JUS_RETURN (*_fffp)(JUS_TYPES...)) { + return new AbstractFunctionTypeDirect(_name, _desc, _fffp); +} + diff --git a/jus/Client.cpp b/jus/Client.cpp index d59cdad..5c2ff7a 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -68,10 +68,13 @@ void jus::Client::disconnect(){ JUS_DEBUG("disconnect [STOP]"); } -ejson::Object jus::Client::createBaseCall(const std::string& _functionName) { +ejson::Object jus::Client::createBaseCall(const std::string& _service, const std::string& _functionName) { ejson::Object obj; + if (_service.size() != 0) { + obj.add("service", ejson::String(_service)); + } obj.add("call", ejson::String(_functionName)); - obj.add("transaction-id", ejson::Number(m_id++)); + obj.add("id", ejson::Number(m_id++)); obj.add("param", ejson::Array()); return obj; } diff --git a/jus/Client.h b/jus/Client.h index 733add6..5b46989 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -29,7 +29,7 @@ namespace jus { void onClientData(const std::string& _value); std::string asyncRead(); ejson::Object callJson(const ejson::Object& _obj); - ejson::Object createBaseCall(const std::string& _functionName); + ejson::Object createBaseCall( const std::string& _service, const std::string& _functionName); void createParam(ejson::Object& _obj) { // Finish recursive parse ... } @@ -125,8 +125,8 @@ namespace jus { } public: template - void call(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + void call(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -134,8 +134,8 @@ namespace jus { } } template - int32_t call_i(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + int32_t call_i(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -153,8 +153,8 @@ namespace jus { return int32_t(val.toNumber().get()); } template - double call_d(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + double call_d(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -172,8 +172,8 @@ namespace jus { return val.toNumber().get(); } template - std::string call_s(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + std::string call_s(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -191,8 +191,8 @@ namespace jus { return val.toString().get(); } template - bool call_b(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + bool call_b(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -210,8 +210,8 @@ namespace jus { return val.toBoolean().get(); } template - std::vector call_vi(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + std::vector call_vi(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -241,8 +241,8 @@ namespace jus { return out; } template - std::vector call_vd(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + std::vector call_vd(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -272,8 +272,8 @@ namespace jus { return out; } template - std::vector call_vs(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + std::vector call_vs(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -303,8 +303,8 @@ namespace jus { return out; } template - std::vector call_vb(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_functionName); + std::vector call_vb(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_service, _functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { diff --git a/jus/GateWay.cpp b/jus/GateWay.cpp index 738a17b..09104ae 100644 --- a/jus/GateWay.cpp +++ b/jus/GateWay.cpp @@ -10,6 +10,7 @@ jus::GateWay::GateWay() : + m_clientUID(1), propertyClientIp(this, "client-ip", "127.0.0.1", "Ip to listen client", &jus::GateWay::onPropertyChangeClientIp), propertyClientPort(this, "client-port", 1983, "Port to listen client", &jus::GateWay::onPropertyChangeClientPort), propertyClientMax(this, "client-max", 80, "Maximum of client at the same time", &jus::GateWay::onPropertyChangeClientMax), @@ -24,17 +25,39 @@ jus::GateWay::~GateWay() { } void jus::GateWay::start() { - m_clientWaiting = std::make_shared(); + m_clientWaiting = std::make_shared(this); m_clientConnected = m_clientWaiting->signalIsConnected.connect(this, &jus::GateWay::onClientConnect); - m_clientWaiting->start(*propertyClientIp, *propertyClientPort); + m_clientWaiting->start(*propertyClientIp, *propertyClientPort, m_clientUID++); + m_serviceWaiting = std::make_shared(this); + m_serviceConnected = m_serviceWaiting->signalIsConnected.connect(this, &jus::GateWay::onServiceConnect); + m_serviceWaiting->start(*propertyServiceIp, *propertyServicePort); } void jus::GateWay::stop() { } +ememory::SharedPtr jus::GateWay::get(const std::string& _serviceName) { + for (auto &it : m_serviceList) { + if (it == nullptr) { + continue; + } + if (it->getName() != _serviceName) { + continue; + } + return it; + } + // TODO : Remove this ... + return m_serviceWaiting; + return nullptr; +} + void jus::GateWay::onClientConnect(const bool& _value) { - JUS_TODO("lklklk: " << _value); + JUS_TODO("Client connection: " << _value); +} + +void jus::GateWay::onServiceConnect(const bool& _value) { + JUS_TODO("Service connection: " << _value); } void jus::GateWay::onPropertyChangeClientIp() { diff --git a/jus/GateWay.h b/jus/GateWay.h index 5bd7140..feef56c 100644 --- a/jus/GateWay.h +++ b/jus/GateWay.h @@ -9,12 +9,16 @@ namespace jus { class GateWay : public eproperty::Interface { + private: + size_t m_clientUID; private: std::vector> m_serviceList; //!< List of all service availlable with their specific connection interface std::vector> m_clientList; //!< List of all Client interface with their own connection //TODO: std::vector m_ServerList; //!< List of all Server connected to this gateway ememory::SharedPtr m_clientWaiting; esignal::Connection m_clientConnected; + ememory::SharedPtr m_serviceWaiting; + esignal::Connection m_serviceConnected; public: eproperty::Value propertyClientIp; eproperty::Value propertyClientPort; @@ -27,6 +31,7 @@ namespace jus { virtual ~GateWay(); void start(); void stop(); + ememory::SharedPtr get(const std::string& _serviceName); private: void onPropertyChangeClientIp(); void onPropertyChangeClientPort(); @@ -35,6 +40,7 @@ namespace jus { void onPropertyChangeServicePort(); void onPropertyChangeServiceMax(); void onClientConnect(const bool& _value); + void onServiceConnect(const bool& _value); }; } diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index eae385b..53eae6f 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -7,8 +7,12 @@ #include #include #include +#include +#include -jus::GateWayClient::GateWayClient() { +jus::GateWayClient::GateWayClient(jus::GateWay* _gatewayInterface) : + m_gatewayInterface(_gatewayInterface), + m_returnValueOk(false) { } @@ -16,11 +20,13 @@ jus::GateWayClient::~GateWayClient() { } -void jus::GateWayClient::start(const std::string& _ip, uint16_t _port) { +void jus::GateWayClient::start(const std::string& _ip, uint16_t _port, size_t _uid) { m_interfaceClient.propertyIp.set(_ip); m_interfaceClient.propertyPort.set(_port); + m_uid = _uid; m_interfaceClient.propertyServer.set(true); - m_interfaceClient.connect(); + m_interfaceClient.connect(true); + m_interfaceClient.setInterfaceName("cli-" + etk::to_string(m_uid)); m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::GateWayClient::onClientData); } @@ -42,7 +48,7 @@ void jus::GateWayClient::onClientData(const std::string& _value) { std::string call = data["call"].toString().get(); ejson::Object answer; answer.add("from-service", ejson::String("ServiceManager")); - answer.add("transaction-id", data["transaction-id"]); + answer.add("id", data["id"]); if (call == "getServiceCount") { // TODO : Do it better: answer.add("return", ejson::Number(2)); @@ -53,6 +59,21 @@ void jus::GateWayClient::onClientData(const std::string& _value) { answer.add("return", listService); } else if (call == "getServiceInformation") { + } else if (call == "link") { + // first param : + std::string serviceName = data["param"].toArray()[0].toString().get(); + // TODO : check if already connected ... + //m_listConnectedService + // TODO : check if we have authorisation to connect service + ememory::SharedPtr srv = m_gatewayInterface->get(serviceName); + if (srv != nullptr) { + m_listConnectedService.push_back(srv); + answer.add("return", ejson::Boolean(true)); + } else { + answer.add("return", ejson::Boolean(false)); + } + } else if (call == "unlink") { + answer.add("return", ejson::Boolean(false)); } else { JUS_ERROR("Function does not exist ... '" << call << "'"); answer.add("error", ejson::String("CALL-UNEXISTING")); @@ -64,7 +85,28 @@ void jus::GateWayClient::onClientData(const std::string& _value) { std::string call = data["call"].toString().get(); } else { - JUS_TODO("mmmmmmmmmmm: " << _value); + for (auto &it : m_listConnectedService) { + if (it == nullptr) { + continue; + } + if (it->getName() != service) { + continue; + } + it->SendData(m_uid, data); + while (m_returnValueOk == false) { + JUS_DEBUG("wait Return Value"); + usleep(20000); + } + std::string valueReturn = m_returnMessage.generate(); + JUS_DEBUG("answer: " << valueReturn); + m_interfaceClient.write(valueReturn); + m_returnValueOk = false; + break; + } } } +void jus::GateWayClient::returnMessage(ejson::Object _data) { + m_returnMessage = _data; + m_returnValueOk = true; +} \ No newline at end of file diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 101dc3b..7b69fd9 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -8,19 +8,28 @@ #include #include #include +#include namespace jus { + class GateWay; class GateWayClient { + private: + jus::GateWay* m_gatewayInterface; public: jus::TcpString m_interfaceClient; esignal::Signal signalIsConnected; esignal::Connection m_dataCallback; + bool m_returnValueOk; + ejson::Object m_returnMessage; + std::vector> m_listConnectedService; + size_t m_uid; public: - GateWayClient(); + GateWayClient(jus::GateWay* _gatewayInterface); virtual ~GateWayClient(); - void start(const std::string& _ip, uint16_t _port); + void start(const std::string& _ip, uint16_t _port, size_t _uid); void stop(); void onClientData(const std::string& _value); + void returnMessage(ejson::Object _data); }; } diff --git a/jus/GateWayService.cpp b/jus/GateWayService.cpp index e69de29..e516508 100644 --- a/jus/GateWayService.cpp +++ b/jus/GateWayService.cpp @@ -0,0 +1,60 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#include + +jus::GateWayService::GateWayService(jus::GateWay* _gatewayInterface) : + m_gatewayInterface(_gatewayInterface) { + +} + +jus::GateWayService::~GateWayService() { + +} + +void jus::GateWayService::start(const std::string& _ip, uint16_t _port) { + m_interfaceClient.propertyIp.set(_ip); + m_interfaceClient.propertyPort.set(_port); + m_interfaceClient.propertyServer.set(true); + m_interfaceClient.connect(true); + m_interfaceClient.setInterfaceName("srv-?"); + m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::GateWayService::onClientData); +} + +void jus::GateWayService::stop() { + m_interfaceClient.disconnect(); +} + +void jus::GateWayService::SendData(size_t _userSessionId, ejson::Object _data) { + _data.add("client-id", ejson::String(etk::to_string(_userSessionId))); + _data.add("action", ejson::String("call")); + std::string value = _data.generate(); + JUS_DEBUG("Send Service: " << value); + m_interfaceClient.write(value); +} + +void jus::GateWayService::onClientData(const std::string& _value) { + JUS_DEBUG("On service data: " << _value); + ejson::Object data(_value); + if (data.valueExist("connect-service") == true) { + if (m_name != "") { + JUS_WARNING("Service interface ==> try change the servie name after init: '" << data["connect-service"].toString().get()); + return; + } + m_name = data["connect-service"].toString().get(); + m_interfaceClient.setInterfaceName("srv-" + m_name); + JUS_WARNING("Service name configured"); + return; + } + if (data.valueExist("client-id") == false) { + JUS_WARNING("Service interface ==> wrong service answer ==> missing 'client-id'"); + return; + } + JUS_TODO("plop..........."); +} + diff --git a/jus/GateWayService.h b/jus/GateWayService.h index 62c0569..20feb37 100644 --- a/jus/GateWayService.h +++ b/jus/GateWayService.h @@ -7,15 +7,30 @@ #include #include +#include +#include namespace jus { + class GateWay; class GateWayService { - public: - ememory::SharedPtr m_interfaceService; + private: + jus::GateWay* m_gatewayInterface; std::string m_name; public: - GateWayService(const ememory::SharedPtr& _interface); + jus::TcpString m_interfaceClient; + esignal::Signal signalIsConnected; + esignal::Connection m_dataCallback; + public: + GateWayService(jus::GateWay* _gatewayInterface); virtual ~GateWayService(); + void start(const std::string& _ip, uint16_t _port); + void stop(); + void onClientData(const std::string& _value); + public: + void SendData(size_t _userSessionId, ejson::Object _data); + const std::string& getName() { + return m_name; + } }; } diff --git a/jus/ParamType.cpp b/jus/ParamType.cpp new file mode 100644 index 0000000..eda8e9d --- /dev/null +++ b/jus/ParamType.cpp @@ -0,0 +1,28 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include + +#define generate_basic_type(_type, _name) \ +template<> ParamType createType<_type>() {\ + return ParamType(_name); \ +} + +generate_basic_type(void, "void"); +generate_basic_type(bool, "bool"); +generate_basic_type(float, "float"); +generate_basic_type(double, "double"); +generate_basic_type(int64_t, "int64"); +generate_basic_type(int32_t, "int32"); +generate_basic_type(int16_t, "int16"); +generate_basic_type(int8_t, "int8"); +generate_basic_type(uint64_t, "uint64"); +generate_basic_type(uint32_t, "uint32"); +generate_basic_type(uint16_t, "uint16"); +generate_basic_type(uint8_t, "uint8"); +generate_basic_type(std::string, "string"); + diff --git a/jus/ParamType.h b/jus/ParamType.h new file mode 100644 index 0000000..0bf1f30 --- /dev/null +++ b/jus/ParamType.h @@ -0,0 +1,28 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +class ParamType { + protected: + const char* m_typeName; + public: + ParamType(const char* _name = ""): + m_typeName(_name) { + + } + const char* getName() const { + return m_typeName; + } + bool operator == (const ParamType& _obj) const { + return m_typeName == _obj.m_typeName; + } +}; + + +template +ParamType createType(); + + diff --git a/jus/Service.cpp b/jus/Service.cpp index 3ca4623..e6dd03c 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -6,166 +6,16 @@ #include #include +#include +#include #include -generate_basic_type(void, "void"); -generate_basic_type(bool, "bool"); -generate_basic_type(float, "float"); -generate_basic_type(double, "double"); -generate_basic_type(int64_t, "int64"); -generate_basic_type(int32_t, "int32"); -generate_basic_type(int16_t, "int16"); -generate_basic_type(int8_t, "int8"); -generate_basic_type(uint64_t, "uint64"); -generate_basic_type(uint32_t, "uint32"); -generate_basic_type(uint16_t, "uint16"); -generate_basic_type(uint8_t, "uint8"); -generate_basic_type(std::string, "string"); - -template<> bool convertJsonTo(const ejson::Value& _value) { - return _value.toBoolean().get(); -} -template<> float convertJsonTo(const ejson::Value& _value) { - return _value.toNumber().get(); -} -template<> double convertJsonTo(const ejson::Value& _value) { - return _value.toNumber().get(); -} -template<> int64_t convertJsonTo(const ejson::Value& _value) { - return int64_t(_value.toNumber().get()); -} -template<> int32_t convertJsonTo(const ejson::Value& _value) { - //_value.display(); - return int32_t(_value.toNumber().get()); -} -template<> int16_t convertJsonTo(const ejson::Value& _value) { - return int16_t(_value.toNumber().get()); -} -template<> int8_t convertJsonTo(const ejson::Value& _value) { - return int8_t(_value.toNumber().get()); -} -template<> uint64_t convertJsonTo(const ejson::Value& _value) { - return uint64_t(_value.toNumber().get()); -} -template<> uint32_t convertJsonTo(const ejson::Value& _value) { - return uint32_t(_value.toNumber().get()); -} -template<> uint16_t convertJsonTo(const ejson::Value& _value) { - return uint16_t(_value.toNumber().get()); -} -template<> uint8_t convertJsonTo(const ejson::Value& _value) { - return uint8_t(_value.toNumber().get()); -} -template<> std::string convertJsonTo(const ejson::Value& _value) { - //_value.display(); - return _value.toString().get(); -} - -template<> ejson::Value convertToJson(const bool& _value) { - return ejson::Boolean(_value); -} -template<> ejson::Value convertToJson(const float& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const double& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const int64_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const int32_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const int16_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const int8_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const uint64_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const uint32_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const uint16_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const uint8_t& _value) { - return ejson::Number(_value); -} -template<> ejson::Value convertToJson(const std::string& _value) { - return ejson::String(_value); -} - -template<> bool convertStringTo(const std::string& _value) { - return etk::string_to_bool(_value); -} -template<> float convertStringTo(const std::string& _value) { - return etk::string_to_float(_value); -} -template<> double convertStringTo(const std::string& _value) { - return etk::string_to_double(_value); -} -template<> int64_t convertStringTo(const std::string& _value) { - return etk::string_to_int64_t(_value); -} -template<> int32_t convertStringTo(const std::string& _value) { - return etk::string_to_int32_t(_value); -} -template<> int16_t convertStringTo(const std::string& _value) { - return etk::string_to_int16_t(_value); -} -template<> int8_t convertStringTo(const std::string& _value) { - return etk::string_to_int8_t(_value); -} -template<> uint64_t convertStringTo(const std::string& _value) { - return etk::string_to_uint64_t(_value); -} -template<> uint32_t convertStringTo(const std::string& _value) { - return etk::string_to_uint32_t(_value); -} -template<> uint16_t convertStringTo(const std::string& _value) { - return etk::string_to_uint16_t(_value); -} -template<> uint8_t convertStringTo(const std::string& _value) { - return etk::string_to_uint8_t(_value); -} -template<> std::string convertStringTo(const std::string& _value) { - return _value; -} - -bool CmdBase::checkCompatibility(const ParamType& _type, const ejson::Value& _params) { - if (createType() == _type) { - return _params.isBoolean(); - } - if ( createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type - || createType() == _type) { - return _params.isNumber(); - } - if (createType() == _type) { - return _params.isString(); - } - return false; -} -bool CmdBase::checkCompatibility(const ParamType& _type, const std::string& _params) { - return false; -} - jus::Service::Service() : propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp), - propertyPort(this, "port", 1984, "Port to connect server", &jus::Service::onPropertyChangePort), + propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort), m_id(0) { m_interfaceClient.propertyIp.set(*propertyIp); m_interfaceClient.propertyPort.set(*propertyPort); @@ -192,9 +42,10 @@ void jus::Service::onPropertyChangePort(){ } -void jus::Service::connect(){ +void jus::Service::connect(const std::string& _serviceName){ JUS_DEBUG("connect [START]"); m_interfaceClient.connect(); + m_interfaceClient.write(std::string("{\"connect-service\":\"") + _serviceName + "\"}"); JUS_DEBUG("connect [STOP]"); } @@ -205,13 +56,26 @@ void jus::Service::disconnect(){ } ejson::Object jus::Service::callJson(const ejson::Object& _obj) { - /* - JUS_VERBOSE("Call JSON [START] "); - std::string tmpVal = _obj.generate(); - JUS_DEBUG("Call JSON '" << tmpVal << "'"); - m_interfaceClient.write(_obj.generate()); - std::string ret = asyncRead(); - JUS_VERBOSE("Call JSON [STOP]"); - */ + std::string action = _obj["action"].toString().get(); + if (action == "new") { + uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + std::string userName = _obj["user"].toString().get(); + clientConnect(clientId, userName); + ejson::Object tmpp; + tmpp.add("return", ejson::String("OK")); + return tmpp; + } else if (action == "delete") { + uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + clientDisconnect(clientId); + ejson::Object tmpp; + tmpp.add("return", ejson::String("OK")); + return tmpp; + } else if ( action == "call" + || action == "") { + uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + return callJson2(clientId, _obj); + } else { + // TODO : ... + } return ejson::Object(); } diff --git a/jus/Service.h b/jus/Service.h index c7b97a9..dc2e998 100644 --- a/jus/Service.h +++ b/jus/Service.h @@ -8,240 +8,10 @@ #include #include #include +#include +#include #include -class ParamType { - protected: - const char* m_typeName; - public: - ParamType(const char* _name = ""): - m_typeName(_name) { - - } - const char* getName() const { - return m_typeName; - } - bool operator == (const ParamType& _obj) const { - return m_typeName == _obj.m_typeName; - } -}; - -template -ParamType createType(); - -#define generate_basic_type(_type, _name) \ -template<> ParamType createType<_type>() {\ - return ParamType(_name); \ -} - -class CmdBase { - protected: - const std::string m_name; - public: - const std::string& getName() const { - return m_name; - } - protected: - const std::string m_description; - public: - const std::string& getDescription() const { - return m_description; - } - protected: - CmdBase(const std::string& _name, - const std::string& _desc): - m_name(_name), - m_description(_desc) { - - } - public: - virtual ~CmdBase() {}; - bool checkCompatibility(const ParamType& _type, const ejson::Value& _params); - bool checkCompatibility(const ParamType& _type, const std::string& _params); - public: - virtual std::string getPrototype() const = 0; - virtual ejson::Value executeJson(const ejson::Array& _params) = 0; - virtual std::string executeString(const std::vector& _params) = 0; -}; - -template -JUS_TYPE convertStringTo(const std::string& _value); - -template -JUS_TYPE convertJsonTo(const ejson::Value& _value); - -template -ejson::Value convertToJson(const JUS_TYPE& _value); - -template -class TypeList; - -template -ejson::Value executeCallJson(JUS_RETURN (*_func)(JUS_TYPES...), const ejson::Array& _params) { - #if defined(__clang__) - // clang generate a basic warning: - // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] - int32_t idParam = 0; - return convertToJson(_func((convertJsonTo(_params[idParam++]))...)); - #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) - int32_t idParam = m_paramCount-1; - return convertToJson(_func(convertJsonTo(_params[idParam--])...)); - #else - #error Must be implemented ... - #endif - return ejson::Null(); -} - -template -ejson::Value executeCallJson(void (*_func)(JUS_TYPES...), const ejson::Array& _params) { - ejson::Object out; - #if defined(__clang__) - // clang generate a basic warning: - // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] - int32_t idParam = 0; - _func((convertJsonTo(_params[idParam++]))...); - #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) - int32_t idParam = m_paramCount-1; - _func(convertJsonTo(_params[idParam--])...); - #else - #error Must be implemented ... - #endif - return ejson::Null(); -} - -template -std::string executeCallString(JUS_RETURN (*_func)(JUS_TYPES...), const std::vector& _params) { - #if defined(__clang__) - // clang generate a basic warning: - // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] - int32_t idParam = 0; - return etk::to_string(_func((convertStringTo(_params[idParam++]))...)); - #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) - int32_t idParam = m_paramCount-1; - return etk::to_string(_func(convertStringTo(_params[idParam--])...)); - #else - #error Must be implemented ... - #endif - return ""; -} -template -std::string executeCallString(void (*_func)(JUS_TYPES...), const std::vector& _params) { - ejson::Object out; - #if defined(__clang__) - // clang generate a basic warning: - // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] - int32_t idParam = 0; - _func((convertStringTo(_params[idParam++]))...); - #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) - int32_t idParam = m_paramCount-1; - _func(convertStringTo(_params[idParam--])...); - #else - #error Must be implemented ... - #endif - return ""; -} - -template -class TypeList: public CmdBase { - protected: - static const ParamType m_returnType; - static const ParamType m_paramType[sizeof...(JUS_TYPES)]; - static const int32_t m_paramCount; - public: - using functionType = JUS_RETURN (*)(JUS_TYPES...); - functionType m_function; - TypeList(const std::string& _name, const std::string& _desc, functionType _fptr): - CmdBase(_name, _desc), - m_function(_fptr) { - } - std::string getPrototype() const override { - std::string ret; - ret += m_returnType.getName(); - ret += " "; - ret += m_name; - ret += "("; - for (size_t iii=0; iii& _params) override { - std::string out; - // check parameter number - if (_params.size() != m_paramCount) { - JUS_ERROR("Wrong number of Parameters ..."); - out += "error:WRONG-PARAMETER-NUMBER;"; - out += "error-help:request "; - out += etk::to_string(_params.size()); - out += " parameters and need "; - out += etk::to_string(m_paramCount); - out += " parameters. prototype function:"; - out += getPrototype(); - return out; - } - // check parameter compatibility - for (size_t iii=0; iii -const ParamType TypeList::m_returnType = createType(); - -template -const ParamType TypeList::m_paramType[sizeof...(JUS_TYPES)] = {createType()...}; - -template -const int32_t TypeList::m_paramCount = sizeof...(JUS_TYPES); - - -template -CmdBase* createCmd(const std::string& _name, const std::string& _desc, JUS_RETURN (*_fffp)(JUS_TYPES...)) { - return new TypeList(_name, _desc, _fffp); -} - - - static double mulllll(double _val1) { double _val2 = 2.0f; JUS_ERROR("Call with parameter : " << _val1); @@ -278,7 +48,8 @@ namespace jus { virtual ~Service(); // Genenric function call: ejson::Object callJson(const ejson::Object& _obj); - void connect(); + virtual ejson::Object callJson2(size_t _clientId, const ejson::Object& _obj) = 0; + void connect(const std::string& _serviceName); void disconnect(); private: void onClientData(const std::string& _value); @@ -286,47 +57,14 @@ namespace jus { private: void onPropertyChangeIp(); void onPropertyChangePort(); - protected: - - void createSignatureInternal(std::vector& _signature) { - // Finish recursive parse ... - } - template - void createSignatureInternal(std::vector& _signature, const std::string& _param, _ARGS&&... _args) { - _signature.push_back("string"); - createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); - } - template - void createSignatureInternal(std::vector& _signature, const bool& _param, _ARGS&&... _args) { - _signature.push_back("bool"); - createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); - } - template - void createSignatureInternal(std::vector& _signature, const double& _param, _ARGS&&... _args) { - _signature.push_back("double"); - createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); - } - template - void createSignatureInternal(std::vector& _signature, const int32_t& _param, _ARGS&&... _args) { - _signature.push_back("int32"); - createSignatureInternal(_signature, std::forward<_ARGS>(_args)...); - } - template - std::vector createSignature(_ARGS&&... _args) { - std::vector signature; - createSignatureInternal(signature, std::forward<_ARGS>(_args)...); - return signature; - } - + public: template void advertise(const std::string& _name, - JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(const JUS_FUNC_ARGS_TYPE&... _args), + JUS_RETURN_VALUE (*_func)(JUS_FUNC_ARGS_TYPE... _args), const std::string& _desc) { - - //CmdBase* tmp = createCmd(_name, &mulllll); - CmdBase* tmp = createCmd(_name, "desc", &mulllll); + //AbstractFunction* tmp = createAbstractFunctionDirect(_name, &mulllll); + AbstractFunction* tmp = createAbstractFunctionDirect(_name, "desc", &mulllll); JUS_ERROR("Signature : " << tmp->getPrototype()); { ejson::Array param; @@ -337,7 +75,7 @@ namespace jus { } - tmp = createCmd(_name, "desc", &mulllll2); + tmp = createAbstractFunctionDirect(_name, "desc", &mulllll2); JUS_ERROR("Signature2 : " << tmp->getPrototype()); { ejson::Array param; @@ -347,20 +85,80 @@ namespace jus { JUS_ERROR(" return: "); out.display(); } - tmp = createCmd(_name, "desc", &mulllll3); + tmp = createAbstractFunctionDirect(_name, "desc", &mulllll3); JUS_ERROR("Signature3 : " << tmp->getPrototype()); JUS_ERROR(" return: " << tmp->executeString(etk::split("3.5 false", ' '))); - tmp = createCmd(_name, "desc", &mulllll4); + tmp = createAbstractFunctionDirect(_name, "desc", &mulllll4); JUS_ERROR("Signature4 : " << tmp->getPrototype()); - /* - std::vector plop = createSignature(_args): - JUS_ERROR("signature:"); - for (auto& it : plop) { - JUS_ERROR(" - " << it); + } + /** + * @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; + }; + 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 m_interface; + std::vector m_listFunction; + public: + template + void advertise(const std::string& _name, + JUS_RETURN_VALUE (JUS_CLASS_TYPE::*_func)(JUS_FUNC_ARGS_TYPE... _args), + const std::string& _desc) { + // TODO: check if fucntion does not exist ... + AbstractFunction* tmp = createAbstractFunctionClass(_name, _desc, _func); + m_listFunction.push_back(tmp); + } + ServiceType(JUS_USER_ACCESS& _interface): + m_getUserInterface(_interface) { + + } + void clientConnect(size_t _clientSessionID, const std::string& _userName) { + // TODO : Set a mutex ... + m_interface.insert(std::make_pair(_clientSessionID, new JUS_TYPE_SERVICE(m_getUserInterface.getUser(_userName)))); + } + void clientDisconnect(size_t _clientSessionID) { + auto it = m_interface.find(_clientSessionID); + if (it != m_interface.end()) { + // noting to do ==> user never conected. + return; } - */ + // TODO : Set a mutex ... + m_interface.erase(it); + } + ejson::Object callJson2(size_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; + return it2->executeJson(param, (void*)elem).toObject(); + } + out.add("error", ejson::String("FUNCTION-UNKNOW")); + return out; } }; } + diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index c4e2959..12ce6bc 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -25,6 +25,10 @@ jus::TcpString::~TcpString() { disconnect(); } +void jus::TcpString::setInterfaceName(const std::string& _name) { + ethread::setName(*m_thread, "Tcp-" + _name); +} + void jus::TcpString::threadCallback() { ethread::setName("TcpString-input"); // Connect ... @@ -52,7 +56,7 @@ void jus::TcpString::threadCallback() { JUS_DEBUG("End of thread"); } -void jus::TcpString::connect(){ +void jus::TcpString::connect(bool _async){ JUS_DEBUG("connect [START]"); m_threadRunning = true; m_thread = new std::thread([&](void *){ this->threadCallback();}, nullptr); @@ -61,12 +65,17 @@ void jus::TcpString::connect(){ JUS_ERROR("creating callback thread!"); return; } - while ( m_threadRunning == true + while ( _async == false + && m_threadRunning == true && m_connection.getConnectionStatus() != enet::Tcp::status::link) { usleep(50000); } //ethread::setPriority(*m_receiveThread, -6); - JUS_DEBUG("connect [STOP]"); + if (_async == true) { + JUS_DEBUG("connect [STOP] async mode"); + } else { + JUS_DEBUG("connect [STOP]"); + } } void jus::TcpString::disconnect(){ diff --git a/jus/TcpString.h b/jus/TcpString.h index 6b8329d..fc80eab 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -25,8 +25,9 @@ namespace jus { public: TcpString(); virtual ~TcpString(); - void connect(); + void connect(bool _async = false); void disconnect(); + void setInterfaceName(const std::string& _name); int32_t write(const std::string& _data); std::string asyncRead(); private: diff --git a/lutin_jus.py b/lutin_jus.py index 66ed00b..ed7ceb1 100644 --- a/lutin_jus.py +++ b/lutin_jus.py @@ -32,6 +32,10 @@ def create(target, module_name): ]) my_module.add_path(tools.get_current_path(__file__)) my_module.add_src_file([ + 'jus/AbstractFunction.cpp', + 'jus/AbstractFunctionTypeDirect.cpp', + 'jus/AbstractFunctionTypeClass.cpp', + 'jus/ParamType.cpp', 'jus/Client.cpp', 'jus/GateWay.cpp', 'jus/GateWayService.cpp', @@ -40,6 +44,10 @@ def create(target, module_name): 'jus/TcpString.cpp', ]) my_module.add_header_file([ + 'jus/AbstractFunction.h', + 'jus/AbstractFunctionTypeDirect.h', + 'jus/AbstractFunctionTypeClass.h', + 'jus/ParamType.h', 'jus/debug.h', 'jus/Client.h', 'jus/GateWay.h', diff --git a/test/client/appl/main.cpp b/test/client/appl/main.cpp index 24e4de6..35193e1 100644 --- a/test/client/appl/main.cpp +++ b/test/client/appl/main.cpp @@ -42,13 +42,22 @@ int main(int _argc, const char *_argv[]) { tmp.push_back(22); tmp.push_back(333); tmp.push_back(4444); - int32_t val = client1.call_i("getServiceCount", tmp, "soucou", false); + int32_t val = client1.call_i("", "getServiceCount", tmp, "coucou", false); APPL_INFO("Nb services = " << val); - std::vector val2 = client1.call_vs("getServiceList"); + std::vector val2 = client1.call_vs("", "getServiceList"); APPL_INFO("List services:"); for (auto &it: val2) { APPL_INFO(" - " << it); } + // TODO: add return value + bool valConnect = client1.call_b("", "link", "serviceTest1"); + APPL_INFO("Link service 'serviceTest1' ret=" << valConnect); + + bool retCall = client1.call_d("serviceTest1", "mul", 13.1, 2.0); + APPL_INFO("serviceTest1.mul = " << retCall); + + valConnect = client1.call_b("", "unlink", "serviceTest1"); + APPL_INFO("un-Link service 'serviceTest1' ret=" << valConnect); int32_t iii=0; while (iii < 3) { diff --git a/test/service1/appl/main.cpp b/test/service1/appl/main.cpp index 63638d3..a943bcb 100644 --- a/test/service1/appl/main.cpp +++ b/test/service1/appl/main.cpp @@ -11,15 +11,49 @@ #include namespace appl { - class Service1 : public jus::Service { + class User { + public: + User() { + APPL_WARNING("new USER"); + } + ~User() { + APPL_WARNING("delete USER"); + } + + }; + + class UserManager { private: - double mul(const double& _val1) {//, const double& _val2) { + std::map> m_listLoaded; + public: + UserManager() { + + } + ememory::SharedPtr getUser(const std::string& _userName) { + // TODO : Lock ... + 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); + m_listLoaded.insert(std::make_pair(_userName, tmp)); + return tmp; + } + }; + class Calculator { + private: + ememory::SharedPtr m_user; + public: + double mul(double _val1) {//, const double& _val2) { double _val2 = 1.0f; return _val1*_val2; } public: - Service1() { - advertise("mul", &appl::Service1::mul, "simple multiplication to test double IO"); + Calculator(ememory::SharedPtr _user) : + m_user(_user) { + //advertise("mul", &appl::Service1::mul, "simple multiplication to test double IO"); } }; } @@ -27,13 +61,15 @@ namespace appl { int main(int _argc, const char *_argv[]) { etk::init(_argc, _argv); - appl::Service1 service1; + appl::UserManager userMng; + jus::ServiceType serviceInterface(userMng); + serviceInterface.advertise("mul", &appl::Calculator::mul, "simple multiplication to test double IO"); for (int32_t iii=0; iii<_argc ; ++iii) { std::string data = _argv[iii]; if (etk::start_with(data, "--ip=") == true) { - service1.propertyIp.set(std::string(&data[5])); + serviceInterface.propertyIp.set(std::string(&data[5])); } else if (etk::start_with(data, "--port=") == true) { - service1.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7]))); + serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7]))); } else if ( data == "-h" || data == "--help") { APPL_PRINT(etk::getApplicationName() << " - help : "); @@ -46,16 +82,14 @@ int main(int _argc, const char *_argv[]) { APPL_INFO("=================================="); APPL_INFO("== JUS test service1 start =="); APPL_INFO("=================================="); - /* - service1.connect(); + serviceInterface.connect("serviceTest1"); int32_t iii=0; while (true) { usleep(500000); - APPL_INFO("Appl in waiting ... " << iii << "/inf"); + APPL_INFO("service in waiting ... " << iii << "/inf"); iii++; } - service1.disconnect(); - */ + serviceInterface.disconnect(); APPL_INFO("=================================="); APPL_INFO("== JUS test service1 stop =="); APPL_INFO("==================================");