From 8aa9c0ea0da7e2b2c5c40e833de417bf7cba9586 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 14 Jun 2016 21:28:54 +0200 Subject: [PATCH] [DEV] binary transmission step 1 ==> OK --- jus/AbstractFunction.cpp | 45 ++-- jus/AbstractFunction.h | 21 +- jus/AbstractFunctionTypeClass.h | 177 ++++--------- jus/AbstractFunctionTypeDirect.h | 147 +++-------- jus/Buffer.cpp | 36 +-- jus/Buffer.h | 1 - jus/Client.cpp | 97 +------ jus/Client.h | 8 +- jus/FutureBase.cpp | 47 +--- jus/FutureBase.h | 9 +- jus/GateWay.cpp | 2 +- jus/GateWay.h | 2 +- jus/GateWayClient.cpp | 432 +++---------------------------- jus/GateWayClient.h | 53 ++-- jus/GateWayService.cpp | 108 +++++--- jus/GateWayService.h | 5 +- jus/Service.cpp | 88 ++++--- jus/Service.h | 35 +-- jus/TcpString.cpp | 249 ++++++++++-------- jus/TcpString.h | 71 +++-- 20 files changed, 532 insertions(+), 1101 deletions(-) diff --git a/jus/AbstractFunction.cpp b/jus/AbstractFunction.cpp index 79d66f1..331b7e3 100644 --- a/jus/AbstractFunction.cpp +++ b/jus/AbstractFunction.cpp @@ -181,8 +181,7 @@ namespace jus { answer.add("data", ejson::String(ejson::base64::encode(&m_data.getData()[m_offset], tmpSize))); m_offset += tmpSize; m_size -= tmpSize; - JUS_INFO("data: " << answer.generateHumanString()); - _interface->write(answer.generateMachineString()); + _interface->writeJson(answer); if (m_size <= 0) { return true; } @@ -355,9 +354,11 @@ jus::AbstractFunction::AbstractFunction(const std::string& _name, m_description(_desc) { } -bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejson::Value& _params) { + + +bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) { if (createType() == _type) { - return _params.isBoolean(); + return _params == "bool"; } if ( createType() == _type || createType() == _type @@ -369,10 +370,19 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs || createType() == _type || createType() == _type || createType() == _type) { - return _params.isNumber(); + return _params == "int8" + || _params == "int16" + || _params == "int32" + || _params == "int64" + || _params == "uint8" + || _params == "uint16" + || _params == "uint32" + || _params == "uint64" + || _params == "float" + || _params == "double"; } if (createType>() == _type) { - return _params.isArray(); + return _params == "vector:string"; } if ( createType>() == _type || createType>() == _type @@ -385,25 +395,30 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs || createType>() == _type || createType>() == _type || createType>() == _type) { - if (_params.isObject()) { - JUS_TODO("Special case of packaging of the data"); - return false; - } - return _params.isArray(); + return _params == "vector:int8" + || _params == "vector:int16" + || _params == "vector:int32" + || _params == "vector:int64" + || _params == "vector:uint8" + || _params == "vector:uint16" + || _params == "vector:uint32" + || _params == "vector:uint64" + || _params == "vector:float" + || _params == "vector:double" + || _params == "vector:empty"; } if (createType() == _type) { + /* if (_params.isObject()) { if (_params.toObject()["type"].toString().get() == "file") { return true; } } + */ return false; } if (createType() == _type) { - return _params.isString(); + return _params == "string"; } return false; } -bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) { - return false; -} diff --git a/jus/AbstractFunction.h b/jus/AbstractFunction.h index 611a7bf..73e4b8a 100644 --- a/jus/AbstractFunction.h +++ b/jus/AbstractFunction.h @@ -4,13 +4,22 @@ * @license APACHE v2.0 (see license file) */ #pragma once - -#include #include #include #include #include #include +#include + +namespace jus { + class TcpString; + // define basic async call element ... + using ActionAsyncClient = std::function; +} + + + + namespace jus { class AbstractFunction { public: @@ -49,19 +58,15 @@ namespace jus { public: virtual ~AbstractFunction() {}; public: - 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 void executeJson(const ememory::SharedPtr& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, const ejson::Array& _params, void* _class=nullptr) = 0; - virtual std::string executeString(const std::vector& _params, void* _class=nullptr) = 0; + virtual void execute(const ememory::SharedPtr& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, jus::Buffer& _params, void* _class=nullptr) = 0; }; - // define basic async call element ... - using ActionAsyncClient = std::function; template JUS_TYPE convertStringTo(const std::string& _value); @@ -164,3 +169,5 @@ namespace jus { } +#include + diff --git a/jus/AbstractFunctionTypeClass.h b/jus/AbstractFunctionTypeClass.h index d8f8171..dac2b8c 100644 --- a/jus/AbstractFunctionTypeClass.h +++ b/jus/AbstractFunctionTypeClass.h @@ -17,36 +17,35 @@ namespace jus { template - void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - JUS_CLASS_TYPE* _pointer, - JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), - const ejson::Array& _params) { + void executeClassCall(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + JUS_CLASS_TYPE* _pointer, + JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), + jus::Buffer& _obj) { std::vector asyncAction; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; - ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...)); + JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter(idParam++)...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)(convertJsonTo(_params[idParam--])...)); + JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter(idParam--)...); #else #error Must be implemented ... - ejson::Value ret = ejson::Null(); + JUS_RETURN ret; return; #endif if (asyncAction.size() != 0) { JUS_ERROR("Missing send async messages"); } - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("return", ret); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interfaceClient->write(answer.generateMachineString()); + _interfaceClient->addAsync([=](TcpString* _interface) { + _interface->answerValue(_transactionId, ret, _clientId); + return true; + }); } + /* class SendFile { private: jus::FileServer m_data; @@ -112,20 +111,20 @@ namespace jus { } }; template - void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - JUS_CLASS_TYPE* _pointer, - jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), - const ejson::Array& _params) { + void executeClassCall(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + JUS_CLASS_TYPE* _pointer, + jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), + jus::Buffer& _obj) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; - jus::FileServer tmpElem = (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...); + jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter(idParam++)...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - jus::FileServer tmpElem = (*_pointer.*_func)(convertJsonTo(_params[idParam--])...); + jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter(idParam--)...); #else #error Must be implemented ... jus::FileServer tmpElem; @@ -133,70 +132,31 @@ namespace jus { #endif _interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId)); } + */ template - void executeClassCallJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - JUS_CLASS_TYPE* _pointer, - void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), - const ejson::Array& _params) { - ejson::Object out; + void executeClassCall(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + JUS_CLASS_TYPE* _pointer, + void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), + jus::Buffer& _obj) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; - (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...); + (*_pointer.*_func)(_obj.getParameter(idParam++)...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - (*_pointer.*_func)(convertJsonTo(_params[idParam--])...); + (*_pointer.*_func)(_obj.getParameter(idParam--)...); #else #error Must be implemented ... - ejson::Value ret = ejson::Null(); return; #endif - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("return", ejson::Null()); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interfaceClient->write(answer.generateMachineString()); - } - - 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 ""; + _interfaceClient->addAsync([=](TcpString* _interface) { + _interface->answerVoid(_transactionId, _clientId); + return true; + }); } template @@ -236,76 +196,43 @@ namespace jus { } return out; } - void executeJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - const ejson::Array& _params, - void* _class) override { + void execute(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + jus::Buffer& _obj, + void* _class) override { JUS_CLASS_TYPE* tmpClass = nullptr; if (_class != nullptr) { tmpClass = (JUS_CLASS_TYPE*)_class; } // check parameter number - if (_params.size() != sizeof...(JUS_TYPES)) { + if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) { JUS_ERROR("Wrong number of Parameters ..."); - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER")); std::string help = "request "; - help += etk::to_string(_params.size()); + help += etk::to_string(_obj.getNumberParameter()); help += " parameters and need "; help += etk::to_string(sizeof...(JUS_TYPES)); help += " parameters. prototype function:"; help += getPrototype(); - answer.add("error-help", ejson::String(help)); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interfaceClient->write(answer.generateMachineString()); + _interfaceClient->answerError(_transactionId, + "WRONG-PARAMETER-NUMBER", + help, + _clientId); return; } // check parameter compatibility for (size_t iii=0; iiiwrite(answer.generateMachineString()); + if (checkCompatibility(m_paramType[iii], _obj.getParameterType(iii)) == false) { + _interfaceClient->answerError(_transactionId, + "WRONG-PARAMETER-TYPE", + std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'", + _clientId); return; } } // execute cmd: - jus::executeClassCallJson(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _params); - } - std::string executeString(const std::vector& _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 namespace jus { template - void executeCallJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - JUS_RETURN (*_func)(JUS_TYPES...), - const ejson::Array& _params) { + void executeCall(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + JUS_RETURN (*_func)(JUS_TYPES...), + jus::Buffer& _obj) { #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; - ejson::Value ret = jus::convertToJson(_func((jus::convertJsonTo(_params[idParam++]))...)); + JUS_RETURN ret = jus::convertToJson(_func(_obj.getParameter(idParam++)...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - ejson::Value ret = jus::convertToJson(_func(jus::convertJsonTo(_params[idParam--])...)); + JUS_RETURN ret = jus::convertToJson(_func(_obj.getParameter(idParam--)...)); #else #error Must be implemented ... - ejson::Value ret = ejson::Null(); + JUS_RETURN ret = ejson::Null(); #endif - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("return", ret); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interfaceClient->write(answer.generateMachineString()); + _interfaceClient->addAsync([=](TcpString* _interface) { + _interface->answerValue(_transactionId, ret, _clientId); + return true; + }); } template - void executeCallJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - void (*_func)(JUS_TYPES...), - const ejson::Array& _params) { + void executeCall(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + void (*_func)(JUS_TYPES...), + jus::Buffer& _obj) { ejson::Object out; #if defined(__clang__) // clang generate a basic warning: // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] int32_t idParam = 0; - _func((jus::convertJsonTo(_params[idParam++]))...); + _func(_obj.getParameter(idParam++)...); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - _func(jus::convertJsonTo(_params[idParam--])...); + _func(_obj.getParameter(idParam--)...); #else #error Must be implemented ... #endif _interfaceClient->addAsync([=](TcpString* _interface) { - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("return", ejson::Null()); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interface->write(answer.generateMachineString()); - return true; + _interface->answerVoid(_transactionId, _clientId); + return true; }); } - 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((jus::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(jus::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((jus::convertStringTo(_params[idParam++]))...); - #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) - int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - _func(jus::convertStringTo(_params[idParam--])...); - #else - #error Must be implemented ... - #endif - return ""; - } - template class AbstractFunctionTypeDirect: public jus::AbstractFunction { protected: @@ -135,69 +96,37 @@ namespace jus { } return out; } - void executeJson(const ememory::SharedPtr& _interfaceClient, - uint64_t _transactionId, - uint64_t _clientId, - const ejson::Array& _params, - void* _class) override { + void execute(const ememory::SharedPtr& _interfaceClient, + uint64_t _transactionId, + uint64_t _clientId, + jus::Buffer& _obj, + void* _class) override { // check parameter number - if (_params.size() != sizeof...(JUS_TYPES)) { - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER")); + if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) { std::string help = "request "; - help += etk::to_string(_params.size()); + help += etk::to_string(_obj.getNumberParameter()); help += " parameters and need "; help += etk::to_string(sizeof...(JUS_TYPES)); help += " parameters. prototype function:"; help += getPrototype(); - answer.add("error-help", ejson::String(help)); - JUS_INFO("Answer: " << answer.generateHumanString()); - _interfaceClient->write(answer.generateMachineString()); + _interfaceClient->answerError(_transactionId, + "WRONG-PARAMETER-NUMBER", + help, + _clientId); return; } // check parameter compatibility for (size_t iii=0; iiiwrite(answer.generateMachineString()); + if (checkCompatibility(m_paramType[iii], _obj.getParameterType(iii)) == false) { + _interfaceClient->answerError(_transactionId, + "WRONG-PARAMETER-TYPE", + std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'", + _clientId); return; } } // execute cmd: - jus::executeCallJson(_interfaceClient, _transactionId, _clientId, m_function, _params); - } - std::string executeString(const std::vector& _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& _buffer) { internalComposeWith(&_buffer[0], _buffer.size()); } void jus::Buffer::composeWith(const std::string& _buffer) { - internalComposeWith(reinterpret_cast(&_buffer[0]), _buffer.size()); + fromJson(ejson::Object(_buffer)); } void jus::Buffer::clear() { - JUS_WARNING("clear buffer"); + JUS_VERBOSE("clear buffer"); m_data.clear(); m_paramOffset.clear(); m_header.lenght = 0; @@ -131,7 +131,7 @@ uint16_t jus::Buffer::getProtocalVersion() const { } void jus::Buffer::setProtocolVersion(uint16_t _value) { - JUS_WARNING("setProtocolVersion :" << _value); + JUS_VERBOSE("setProtocolVersion :" << _value); m_header.versionProtocol = _value; } @@ -140,7 +140,7 @@ uint32_t jus::Buffer::getTransactionId() const { } void jus::Buffer::setTransactionId(uint32_t _value) { - JUS_WARNING("setTransactionId :" << _value); + JUS_VERBOSE("setTransactionId :" << _value); m_header.transactionID = _value; } @@ -149,7 +149,7 @@ uint32_t jus::Buffer::getClientId() const { } void jus::Buffer::setClientId(uint32_t _value) { - JUS_WARNING("setClientId :" << _value); + JUS_VERBOSE("setClientId :" << _value); m_header.clientID = _value; } @@ -159,7 +159,7 @@ uint16_t jus::Buffer::getPartId() const { } void jus::Buffer::setPartId(uint16_t _value) { - JUS_WARNING("setPartId :" << _value); + JUS_VERBOSE("setPartId :" << _value); m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF); } @@ -168,7 +168,7 @@ bool jus::Buffer::getPartFinish() const { } void jus::Buffer::setPartFinish(bool _value) { - JUS_WARNING("setPartFinish :" << _value); + JUS_VERBOSE("setPartFinish :" << _value); if (_value == true) { m_header.partID = (m_header.partID & 0x7FFF) | 0x8000; } else { @@ -181,7 +181,7 @@ enum jus::Buffer::typeMessage jus::Buffer::getType() const { } void jus::Buffer::setType(enum typeMessage _value) { - JUS_WARNING("setType :" << _value); + JUS_VERBOSE("setType :" << _value); m_header.typeMessage = uint16_t(_value); } @@ -2154,19 +2154,6 @@ std::vector jus::Buffer::internalGetParameter(pointer); - int32_t nbElement = dataSize / sizeof(uint8_t); - out.resize(nbElement); - for (size_t iii=0; iii lock(m_mutex); - for (auto &it : m_pendingCall) { - if (it.isValid() == false) { - continue; - } - it.setAnswer(obj); - } - m_pendingCall.clear(); - } else { - JUS_ERROR("call with no ID ==> error ..."); - } - return; - } - { - std::unique_lock lock(m_mutex); - auto it = m_pendingCall.begin(); - while (it != m_pendingCall.end()) { - if (it->isValid() == false) { - it = m_pendingCall.erase(it); - continue; - } - if (it->getTransactionId() != tid) { - ++it; - continue; - } - future = *it; - break; - } - } - if (future.isValid() == false) { - JUS_TODO("manage this event better ..."); - //m_newData.push_back(std::move(_value)); - return; - } - bool ret = future.setAnswer(obj); - if (ret == true) { - std::unique_lock lock(m_mutex); - auto it = m_pendingCall.begin(); - while (it != m_pendingCall.end()) { - if (it->isValid() == false) { - it = m_pendingCall.erase(it); - continue; - } - if (it->getTransactionId() != tid) { - ++it; - continue; - } - it = m_pendingCall.erase(it); - break; - } - } -} - jus::ServiceRemote jus::Client::getService(const std::string& _name) { return jus::ServiceRemote(this, _name); } @@ -171,29 +109,6 @@ bool jus::Client::unlink(const uint32_t& _serviceId) { return ret.get(); } -std::string jus::Client::asyncRead() { - if (m_interfaceClient.isActive() == false) { - return ""; - } - int32_t iii = 5000; - while (iii>0) { - usleep(10000); - if (m_newData.size() != 0) { - break; - } - --iii; - } - if (iii == 0) { - // Time-out ... - return ""; - } - std::string out; - out = std::move(m_newData[0]); - m_newData.erase(m_newData.begin()); - JUS_DEBUG("get async data: " << out); - return out; -} - void jus::Client::onPropertyChangeIp() { disconnect(); } @@ -214,9 +129,7 @@ bool jus::Client::connect(const std::string& _remoteUserToConnect){ jus::Future retBin = call("setMode", "BIN").wait(); if (retBin.get() == true) { JUS_WARNING(" ==> accepted binary"); - m_interfaceMode = jus::connectionMode::modeBinary; - m_interfaceClient.connectClean(); - m_interfaceClient.connectRaw(this, &jus::Client::onClientDataRaw); + m_interfaceClient.setMode(jus::connectionMode::modeBinary); JUS_INFO("Connection jump in BINARY ..."); } else { // stay in JSON @@ -281,8 +194,7 @@ class SendAsyncJson { obj.add("id", ejson::Number(m_transactionId)); obj.add("part", ejson::Number(m_partId)); obj.add("finish", ejson::Boolean(true)); - JUS_DEBUG("Send JSON '" << obj.generateHumanString() << "'"); - _interface->write(obj.generateMachineString()); + _interface->writeJson(obj); return true; } return false; @@ -309,8 +221,7 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId, if (_async.size() != 0) { _obj.add("part", ejson::Number(0)); } - JUS_DEBUG("Send JSON '" << _obj.generateHumanString() << "'"); - m_interfaceClient.write(_obj.generateMachineString()); + m_interfaceClient.writeJson(_obj); if (_async.size() != 0) { m_interfaceClient.addAsync(SendAsyncJson(_transactionId, _serviceId, _async)); diff --git a/jus/Client.h b/jus/Client.h index 70cda8a..ee26f84 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -23,10 +23,8 @@ namespace jus { eproperty::Value propertyPort; std::mutex m_mutex; std::vector m_pendingCall; - protected: - enum jus::connectionMode m_interfaceMode; public: - enum jus::connectionMode getMode() { return m_interfaceMode; } + enum jus::connectionMode getMode() { return m_interfaceClient.getMode(); } private: jus::TcpString m_interfaceClient; uint32_t m_id; @@ -46,9 +44,7 @@ namespace jus { // Connect to ourself: //client1.authentificate("coucou"); private: - void onClientData(std::string _value); - void onClientDataRaw(jus::Buffer& _value); - std::string asyncRead(); + void onClientData(jus::Buffer& _value); jus::FutureBase callJson(uint64_t _transactionId, ejson::Object _obj, const std::vector& _async, diff --git a/jus/FutureBase.cpp b/jus/FutureBase.cpp index 4a2bbb5..cd02450 100644 --- a/jus/FutureBase.cpp +++ b/jus/FutureBase.cpp @@ -93,6 +93,7 @@ bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) { tmp.fromJson(_returnValue); return setAnswer(tmp); } + bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) { if (m_data == nullptr) { JUS_ERROR(" Not a valid future ..."); @@ -208,51 +209,17 @@ jus::FutureBase& jus::FutureBase::waitUntil(std::chrono::steady_clock::time_poin } -jus::FutureCall::FutureCall(uint64_t _clientId, uint64_t _transactionId, const ejson::Object& _callValue) : +jus::FutureCall::FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue) : m_transactionId(_transactionId), m_clientId(_clientId), m_isFinished(false) { m_data = _callValue; - if (m_data.valueExist("part") == true) { - if (m_data.valueExist("finish") == true) { - if (m_data["finish"].toBoolean().get() == true) { - m_isFinished = true; - } - } - } else { - m_isFinished = true; - } + m_isFinished = m_data.getPartFinish(); } -void jus::FutureCall::appendData(const ejson::Object& _callValue) { - uint64_t paramID = _callValue["param-id"].toNumber().getU64(); - // get the previous element parameters - ejson::Array params = m_data["param"].toArray(); - if (params.exist() == false) { - JUS_ERROR("try to add element on an inexistand parameter ...==> bad case"); - m_isFinished = true; - return; - } - // Get the specific parameter - ejson::Object param = params[paramID].toObject(); - if (param.exist() == false) { - JUS_ERROR("the parameter is not an object ==> bad case"); - m_isFinished = true; - return; - } - // check if section data - if (param.valueExist("data") == false) { - param.add("data", ejson::Array()); - } - // add data in the array (only if we have local data ... - if (_callValue.valueExist("data") == true) { - param["data"].toArray().add(_callValue["data"]); - } - if (_callValue.valueExist("finish") == true) { - if (_callValue["finish"].toBoolean().get() == true) { - m_isFinished = true; - } - } +void jus::FutureCall::appendData(jus::Buffer& _callValue) { + m_dataMultiplePack.push_back(_callValue); + m_isFinished = _callValue.getPartFinish(); } uint64_t jus::FutureCall::getTransactionId() { @@ -267,7 +234,7 @@ bool jus::FutureCall::isFinished() { return m_isFinished; } -ejson::Object jus::FutureCall::getRaw() { +jus::Buffer& jus::FutureCall::getRaw() { return m_data; } diff --git a/jus/FutureBase.h b/jus/FutureBase.h index e7cfe8d..dfede44 100644 --- a/jus/FutureBase.h +++ b/jus/FutureBase.h @@ -38,17 +38,18 @@ namespace jus { uint64_t m_transactionId; uint64_t m_clientId; bool m_isFinished; - ejson::Object m_data; + jus::Buffer m_data; + std::vector m_dataMultiplePack; std::chrono::steady_clock::time_point m_receiveTime; std::chrono::steady_clock::time_point m_answerTime; public: - FutureCall(uint64_t _clientId, uint64_t _transactionId, const ejson::Object& _callValue); - void appendData(const ejson::Object& _callValue); + FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue); + void appendData(jus::Buffer& _callValue); uint64_t getTransactionId(); uint64_t getClientId(); bool isFinished(); std::chrono::nanoseconds getTransmitionTime(); - ejson::Object getRaw(); + jus::Buffer& getRaw(); }; } diff --git a/jus/GateWay.cpp b/jus/GateWay.cpp index 3974ac5..e520443 100644 --- a/jus/GateWay.cpp +++ b/jus/GateWay.cpp @@ -129,7 +129,7 @@ std::vector jus::GateWay::getAllServiceName() { } -void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) { +void jus::GateWay::answer(uint64_t _userSessionId, jus::Buffer& _data) { for (auto &it : m_clientList) { if (it == nullptr) { continue; diff --git a/jus/GateWay.h b/jus/GateWay.h index 94e1fb4..b4c3089 100644 --- a/jus/GateWay.h +++ b/jus/GateWay.h @@ -33,7 +33,7 @@ namespace jus { void stop(); ememory::SharedPtr get(const std::string& _serviceName); std::vector getAllServiceName(); - void answer(uint64_t _userSessionId, ejson::Object _data); + void answer(uint64_t _userSessionId, jus::Buffer& _data); void newService(enet::Tcp _connection); void newClient(enet::Tcp _connection); void cleanIO(); diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index 8960a83..f1a09de 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -19,7 +19,6 @@ jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayI m_state(jus::GateWayClient::state::unconnect), m_gatewayInterface(_gatewayInterface), m_interfaceClient(std::move(_connection)), - m_interfaceMode(jus::connectionMode::modeJson), m_transactionLocalId(1) { JUS_INFO("----------------"); JUS_INFO("-- NEW Client --"); @@ -71,42 +70,13 @@ bool jus::GateWayClient::isAlive() { } void jus::GateWayClient::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) { - answerError(_transactionId, protocolError, _errorHelp); + m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp); m_state = jus::GateWayClient::state::disconnect; m_interfaceClient.disconnect(true); } -/* -void jus::GateWayClient::answerValue(int32_t _transactionId, bool _value) { - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("return", ejson::Boolean(_value)); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); -} -*/ -void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp) { - if (m_interfaceMode == jus::connectionMode::modeJson) { - ejson::Object answer; - answer.add("error", ejson::String(protocolError)); - answer.add("id", ejson::Number(_clientTransactionId)); - answer.add("error-help", ejson::String(_errorHelp)); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); - } else if (m_interfaceMode == jus::connectionMode::modeBinary) { - jus::Buffer answer; - answer.setType(jus::Buffer::typeMessage::answer); - answer.setTransactionId(_clientTransactionId); - answer.addError(protocolError, _errorHelp); - m_interfaceClient.writeBinary(answer); - } else if (m_interfaceMode == jus::connectionMode::modeXml) { - JUS_ERROR("TODO ... "); - } else { - JUS_ERROR("wrong type of communication"); - } -} -void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { +void jus::GateWayClient::onClientData(jus::Buffer& _value) { uint32_t transactionId = _value.getTransactionId(); if (transactionId == 0) { JUS_ERROR("Protocol error ==>missing id"); @@ -137,20 +107,16 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { std::string mode = _value.getParameter(0); if (mode == "JSON") { JUS_WARNING("[" << m_uid << "] Change mode in: JSON"); - answerValue(transactionId, true); - m_interfaceMode = jus::connectionMode::modeJson; - m_interfaceClient.connectCleanRaw(); - m_interfaceClient.connect(this, &jus::GateWayClient::onClientData); + m_interfaceClient.answerValue(transactionId, true); + m_interfaceClient.setMode(jus::connectionMode::modeJson); } else if (mode == "BIN") { JUS_WARNING("[" << m_uid << "] Change mode in: BINARY"); - answerValue(transactionId, true); - m_interfaceMode = jus::connectionMode::modeBinary; - m_interfaceClient.connectClean(); - m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw); + m_interfaceClient.answerValue(transactionId, true); + m_interfaceClient.setMode(jus::connectionMode::modeBinary); } else if (mode == "XML") { JUS_WARNING("[" << m_uid << "] Change mode in: XML"); //m_interfaceMode = jus::connectionMode::modeXml; - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); } else { answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]"); } @@ -168,7 +134,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { jus::Future futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector()); futLocalService.wait(); // TODO: Set timeout ... m_state = jus::GateWayClient::state::userIdentify; - answerValue(transactionId, true); + m_interfaceClient.answerValue(transactionId, true); } } return; @@ -199,11 +165,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { fut.wait(); // TODO: Set timeout ... if (fut.hasError() == true) { JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "connection refused 1"); return; } else if (fut.get() == false) { - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "connection refused 2"); return; } @@ -215,11 +181,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { fut.wait(); // TODO: Set timeout ... if (fut.hasError() == true) { JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "connection refused 1"); return; } else if (fut.get() == false) { - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "connection refused 2"); return; } @@ -235,7 +201,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { futGroup.wait(); // TODO: Set timeout ... if (futGroup.hasError() == true) { JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "grouping error"); return; } @@ -248,7 +214,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { futServices.wait(); // TODO: Set timeout ... if (futServices.hasError() == true) { JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); + m_interfaceClient.answerValue(transactionId, false); answerProtocolError(transactionId, "service filtering error"); return; } @@ -258,7 +224,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { JUS_WARNING(" services: " << etk::to_string(m_clientServices)); - answerValue(transactionId, true); + m_interfaceClient.answerValue(transactionId, true); m_state = jus::GateWayClient::state::clientIdentify; return; } @@ -269,11 +235,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { if (serviceId == 0) { // This is 2 default service for the cient interface that manage the authorisation of view: if (callFunction == "getServiceCount") { - answerValue(transactionId, m_clientServices.size()); + m_interfaceClient.answerValue(transactionId, m_clientServices.size()); return; } if (callFunction == "getServiceList") { - answerValue(transactionId, m_clientServices); + m_interfaceClient.answerValue(transactionId, m_clientServices); //listService.add(ejson::String("ServiceManager/v0.1.0")); return; } @@ -296,7 +262,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { if (it == m_listConnectedService.end()) { // check if service is connectable ... if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) { - answerError(transactionId, "UN-AUTHORIZED-SERVICE"); + m_interfaceClient.answerError(transactionId, "UN-AUTHORIZED-SERVICE"); return; } ememory::SharedPtr srv = m_gatewayInterface->get(serviceName); @@ -305,17 +271,17 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { futLink.wait(); // TODO: Set timeout ... if (futLink.hasError() == true) { JUS_ERROR("Get error from the service ... LINK"); - answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); + m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); return; } m_listConnectedService.push_back(srv); - answerValue(transactionId, m_listConnectedService.size()); + m_interfaceClient.answerValue(transactionId, m_listConnectedService.size()); return; } - answerError(transactionId, "CAN-NOT-CONNECT-SERVICE"); + m_interfaceClient.answerError(transactionId, "CAN-NOT-CONNECT-SERVICE"); return; } - answerError(transactionId, "SERVICE-ALREADY-CONNECTED");; + m_interfaceClient.answerError(transactionId, "SERVICE-ALREADY-CONNECTED");; return; } if (callFunction == "unlink") { @@ -323,28 +289,28 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { int64_t localServiceID = _value.getParameter(0)-1; // Check if service already link: if (localServiceID >= m_listConnectedService.size()) { - answerError(transactionId, "NOT-CONNECTED-SERVICE"); + m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE"); return; } jus::Future futUnLink = call(m_uid, m_listConnectedService[localServiceID], "_delete"); futUnLink.wait(); // TODO: Set timeout ... if (futUnLink.hasError() == true) { JUS_ERROR("Get error from the service ... UNLINK"); - answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); + m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); return; } m_listConnectedService[localServiceID] = nullptr; - answerValue(transactionId, true); + m_interfaceClient.answerValue(transactionId, true); return; } JUS_ERROR("Function does not exist ... '" << callFunction << "'"); - answerError(transactionId, "CALL-UNEXISTING"); + m_interfaceClient.answerError(transactionId, "CALL-UNEXISTING"); return; } // decrease service ID ... serviceId -= 1; if (serviceId >= m_listConnectedService.size()) { - answerError(transactionId, "NOT-CONNECTED-SERVICE"); + m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE"); return; } else { if (m_listConnectedService[serviceId] == nullptr) { @@ -388,8 +354,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << transactionId); JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); tmpp["id"].toNumber().set(uint64_t(transactionId)); - JUS_DEBUG("transmit=" << tmpp.generateMachineString()); - m_interfaceClient.write(tmpp.generateMachineString()); + m_interfaceClient.writeJson(tmpp); if (tmpp.valueExist("part") == true) { // multiple send element ... if (tmpp.valueExist("finish") == true) { @@ -405,341 +370,6 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { } } -void jus::GateWayClient::onClientData(std::string _value) { - JUS_DEBUG("On data: " << _value); - jus::Buffer tmp; - tmp.fromJson(_value); - onClientDataRaw(tmp); - - #ifdef SDFGSDFSFDSFSDFSDF - ejson::Object data(_value); - uint64_t transactionId = data["id"].toNumber().getU64(); - if (transactionId == 0) { - JUS_ERROR("Protocol error ==>missing id"); - answerProtocolError(transactionId, "missing parameter: 'id'"); - return; - } - std::string callFunction = data["call"].toString().get(); - switch (m_state) { - case jus::GateWayClient::state::disconnect: - case jus::GateWayClient::state::unconnect: - { - JUS_ERROR("Must never appear"); - answerProtocolError(transactionId, "Gateway internal error"); - return; - } - case jus::GateWayClient::state::connect: - { - if (m_userConnectionName != "") { - answerProtocolError(transactionId, "Gateway internal error 2"); - return; - } - if (callFunction == "setMode") { - std::string mode = data["param"].toArray()[0].toString().get(); - if (mode == "JSON") { - JUS_WARNING("[" << m_uid << "] Change mode in: JSON"); - answerValue(transactionId, true); - m_interfaceMode = jus::connectionMode::modeJson; - m_interfaceClient.connectCleanRaw(); - m_interfaceClient.connect(this, &jus::GateWayClient::onClientData); - } else if (mode == "BIN") { - JUS_WARNING("[" << m_uid << "] Change mode in: BINARY"); - answerValue(transactionId, true); - m_interfaceMode = jus::connectionMode::modeBinary; - m_interfaceClient.connectClean(); - m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw); - } else if (mode == "XML") { - JUS_WARNING("[" << m_uid << "] Change mode in: XML"); - //m_interfaceMode = jus::connectionMode::modeXml; - answerValue(transactionId, false); - } else { - answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]"); - } - return; - } else if (callFunction == "connectToUser") { - m_userConnectionName = data["param"].toArray()[0].toString().get(); - if (m_userConnectionName == "") { - answerProtocolError(transactionId, "Call connectToUser with no parameter 'user'"); - } else { - JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'"); - - m_userService = m_gatewayInterface->get("system-user"); - if (m_userService == nullptr) { - answerProtocolError(transactionId, "Gateway internal error 'No user interface'"); - } else { - jus::Future futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector()); - futLocalService.wait(); // TODO: Set timeout ... - m_state = jus::GateWayClient::state::userIdentify; - answerValue(transactionId, true); - } - } - return; - } - JUS_WARNING("[" << m_uid << "] Client must send conection to user name ..."); - answerProtocolError(transactionId, "Missing call of connectToUser"); - return; - } - case jus::GateWayClient::state::userIdentify: - { - m_clientServices.clear(); - m_clientgroups.clear(); - m_clientName.clear(); - - if ( callFunction != "identify" - && callFunction != "auth" - && callFunction != "anonymous") { - answerProtocolError(transactionId, "Client must call: identify/auth/anonymous"); - return; - } - if (callFunction == "identify") { - std::string clientName = data["param"].toArray()[0].toString().get(); - std::string clientTocken = data["param"].toArray()[1].toString().get(); - if (m_userService == nullptr) { - answerProtocolError(transactionId, "gateWay internal error 3"); - return; - } - jus::Future fut = call(m_uid2, m_userService, "checkTocken", clientName, clientTocken); - fut.wait(); // TODO: Set timeout ... - if (fut.hasError() == true) { - JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); - answerProtocolError(transactionId, "connection refused 1"); - return; - } else if (fut.get() == false) { - answerValue(transactionId, false); - answerProtocolError(transactionId, "connection refused 2"); - return; - } - m_clientName = clientName; - } - if (callFunction == "auth") { - std::string password = data["param"].toArray()[0].toString().get(); - jus::Future fut = call(m_uid2, m_userService, "checkAuth", password); - fut.wait(); // TODO: Set timeout ... - if (fut.hasError() == true) { - JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); - answerProtocolError(transactionId, "connection refused 1"); - return; - } else if (fut.get() == false) { - answerValue(transactionId, false); - answerProtocolError(transactionId, "connection refused 2"); - return; - } - m_clientName = m_userConnectionName; - } - if (callFunction == "anonymous") { - m_clientName = ""; - } - // -------------------------------- - // -- Get groups: - // -------------------------------- - jus::Future> futGroup = call(m_uid2, m_userService, "getGroups", m_clientName); - futGroup.wait(); // TODO: Set timeout ... - if (futGroup.hasError() == true) { - JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); - answerProtocolError(transactionId, "grouping error"); - return; - } - m_clientgroups = futGroup.get(); - // -------------------------------- - // -- Get services: - // -------------------------------- - std::vector currentServices = m_gatewayInterface->getAllServiceName(); - jus::Future> futServices = call(m_uid2, m_userService, "filterServices", m_clientName, currentServices); - futServices.wait(); // TODO: Set timeout ... - if (futServices.hasError() == true) { - JUS_ERROR("Get error from the service ..."); - answerValue(transactionId, false); - answerProtocolError(transactionId, "service filtering error"); - return; - } - m_clientServices = futServices.get(); - JUS_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'"); - JUS_WARNING(" groups: " << etk::to_string(m_clientgroups)); - JUS_WARNING(" services: " << etk::to_string(m_clientServices)); - - - answerValue(transactionId, true); - m_state = jus::GateWayClient::state::clientIdentify; - return; - } - break; - case jus::GateWayClient::state::clientIdentify: - { - ejson::Number numService = data["service"].toNumber(); - if ( numService.exist() == false - || numService.getU64() == 0) { - // This is 2 default service for the cient interface that manage the authorisation of view: - if (callFunction == "getServiceCount") { - answerValue(transactionId, m_clientServices.size()); - return; - } - if (callFunction == "getServiceList") { - answerValue(transactionId, m_clientServices); - //listService.add(ejson::String("ServiceManager/v0.1.0")); - return; - } - if (callFunction == "link") { - // first param: - std::string serviceName = data["param"].toArray()[0].toString().get(); - // Check if service already link: - auto it = m_listConnectedService.begin(); - while (it != m_listConnectedService.end()) { - if (*it == nullptr) { - ++it; - continue; - } - if ((*it)->getName() != serviceName) { - ++it; - continue; - } - break; - } - if (it == m_listConnectedService.end()) { - // check if service is connectable ... - if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) { - answerError(transactionId, "UN-AUTHORIZED-SERVICE"); - return; - } - ememory::SharedPtr srv = m_gatewayInterface->get(serviceName); - if (srv != nullptr) { - jus::Future futLink = call(m_uid, srv, "_new", m_userConnectionName, m_clientName, m_clientgroups); - futLink.wait(); // TODO: Set timeout ... - if (futLink.hasError() == true) { - JUS_ERROR("Get error from the service ... LINK"); - answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); - return; - } - m_listConnectedService.push_back(srv); - answerValue(transactionId, m_listConnectedService.size()); - return; - } - answerError(transactionId, "CAN-NOT-CONNECT-SERVICE"); - return; - } - answerError(transactionId, "SERVICE-ALREADY-CONNECTED");; - return; - } - if (callFunction == "unlink") { - // first param: - int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1; - // Check if service already link: - if (localServiceID >= m_listConnectedService.size()) { - answerError(transactionId, "NOT-CONNECTED-SERVICE"); - return; - } - jus::Future futUnLink = call(m_uid, m_listConnectedService[localServiceID], "_delete"); - futUnLink.wait(); // TODO: Set timeout ... - if (futUnLink.hasError() == true) { - JUS_ERROR("Get error from the service ... UNLINK"); - answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); - return; - } - m_listConnectedService[localServiceID] = nullptr; - answerValue(transactionId, true); - return; - } - JUS_ERROR("Function does not exist ... '" << callFunction << "'"); - answerError(transactionId, "CALL-UNEXISTING"); - return; - } - - uint64_t serviceId = numService.getU64()-1; - if (serviceId >= m_listConnectedService.size()) { - ejson::Object answer; - answer.add("id", data["id"]); - answer.add("error", ejson::String("NOT-CONNECTED-SERVICE")); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); - return; - } else { - bool finish = false; - if (data.valueExist("finish") == true) { - finish = data["finish"].toBoolean().get(); - } - int64_t partTmp = -1; - if (data.valueExist("part") == true) { - uint64_t part = data["part"].toNumber().getU64(); - partTmp = part; - if (part != 0) { - // subMessage ... ==> try to forward message: - std::unique_lock lock(m_mutex); - for (auto &itCall : m_pendingCall) { - JUS_INFO(" compare : " << itCall.first << " =?= " << transactionId); - if (itCall.first == transactionId) { - // Find element ==> transit it ... - if (m_listConnectedService[serviceId] == nullptr) { - // TODO ... - } else { - ejson::Object obj; - obj.add("id", ejson::Number(itCall.second.getTransactionId())); - obj.add("param-id", data["param-id"]); - obj.add("part", ejson::Number(part)); - obj.add("data", data["data"]); - if (finish == true) { - obj.add("finish", ejson::Boolean(true)); - } - m_listConnectedService[serviceId]->SendData(m_uid, obj); - } - return; - } - } - JUS_ERROR("Can not transfer part of a message ..."); - return; - } - } - callActionForward(m_uid, - transactionId, - m_listConnectedService[serviceId], - 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(transactionId); - JUS_DEBUG("transmit=" << tmpp.generateMachineString()); - m_interfaceClient.write(tmpp.generateMachineString()); - if (tmpp.valueExist("part") == true) { - // multiple send element ... - if (tmpp.valueExist("finish") == true) { - return tmpp["finish"].toBoolean().get(); - } - return false; - } - return true; - }, - partTmp, - finish); - } - } - } - #endif -} - -jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, - uint64_t _clientTransactionId, - ememory::SharedPtr _srv, - const std::string& _functionName, - ejson::Array _params, - jus::FutureData::ObserverFinish _callback, - int64_t _part, - bool _finish) { - uint64_t id = getId(); - ejson::Object callElem = jus::createCallJson(id, _functionName, _params); - if (_part != -1) { - callElem.add("part", ejson::Number(uint64_t(_part))); - } - if (_finish == true) { - callElem.add("finish", ejson::Boolean(true)); - } - jus::FutureBase ret = callJson(_callerId, _srv, _clientTransactionId, id, callElem, _callback); - ret.setSynchronous(); - return ret; -} - jus::FutureBase jus::GateWayClient::callBinary(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _clientTransactionId, @@ -809,10 +439,11 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, -void jus::GateWayClient::returnMessage(ejson::Object _data) { +void jus::GateWayClient::returnMessage(jus::Buffer& _data) { jus::FutureBase future; - uint64_t tid = _data["id"].toNumber().get(); + uint32_t tid = _data.getTransactionId(); if (tid == 0) { + /* TODO ... if (_data["error"].toString().get() == "PROTOCOL-ERROR") { JUS_ERROR("Get a Protocol error ..."); std::unique_lock lock(m_mutex); @@ -826,6 +457,7 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) { } else { JUS_ERROR("call with no ID ==> error ..."); } + */ return; } { diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 1905a4e..f850230 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -30,10 +30,10 @@ namespace jus { private: jus::GateWay* m_gatewayInterface; jus::TcpString m_interfaceClient; - protected: - enum jus::connectionMode m_interfaceMode; public: - enum jus::connectionMode getMode() { return m_interfaceMode; } + enum jus::connectionMode getMode() { + return m_interfaceClient.getMode(); + } public: esignal::Signal signalIsConnected; ememory::SharedPtr m_userService; @@ -49,9 +49,8 @@ namespace jus { virtual ~GateWayClient(); void start(uint64_t _uid, uint64_t _uid2); void stop(); - void onClientDataRaw(jus::Buffer& _value); - void onClientData(std::string _value); - void returnMessage(ejson::Object _data); + void onClientData(jus::Buffer& _value); + void returnMessage(jus::Buffer& _data); bool checkId(uint64_t _id) const { return m_uid == _id || m_uid2 == _id; @@ -63,7 +62,12 @@ namespace jus { std::mutex m_mutex; std::vector> m_pendingCall; int32_t m_transactionLocalId; - jus::FutureBase callJson(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _clientTransactionId, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); + jus::FutureBase callJson(uint64_t _callerId, + ememory::SharedPtr _srv, + uint64_t _clientTransactionId, + uint64_t _transactionId, + const ejson::Object& _obj, + jus::FutureData::ObserverFinish _callback=nullptr); jus::FutureBase callBinary(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _clientTransactionId, @@ -101,40 +105,15 @@ namespace jus { int64_t _part, bool _finish); - void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp); - - template - void answerValue(uint64_t _clientTransactionId, JUS_ARG _value) { - if (m_interfaceMode == jus::connectionMode::modeJson) { - ejson::Object answer; - answer.add("id", ejson::Number(_clientTransactionId)); - std::vector asyncAction; - answer.add("return", jus::convertToJson(asyncAction, -1, _value)); - if (asyncAction.size() != 0) { - JUS_ERROR("ASYNC datas ... TODO ///"); - } - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); - } else if (m_interfaceMode == jus::connectionMode::modeBinary) { - jus::Buffer answer; - answer.setType(jus::Buffer::typeMessage::answer); - answer.setTransactionId(_clientTransactionId); - answer.addAnswer(_value); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.writeBinary(answer); - } else if (m_interfaceMode == jus::connectionMode::modeXml) { - JUS_ERROR("TODO ... "); - } else { - JUS_ERROR("wrong type of communication"); - } - } - - void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment=""); - jus::FutureBase callActionForward(ememory::SharedPtr _srv, jus::Buffer& _Buffer, jus::FutureData::ObserverFinish _callback); + + + void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp); + + }; } diff --git a/jus/GateWayService.cpp b/jus/GateWayService.cpp index a33735c..0ad56c1 100644 --- a/jus/GateWayService.cpp +++ b/jus/GateWayService.cpp @@ -9,10 +9,14 @@ #include #include +// todo : cHANGE THIS ... +static const std::string protocolError = "PROTOCOL-ERROR"; + + + jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) : m_gatewayInterface(_gatewayInterface), - m_interfaceClient(std::move(_connection)), - m_interfaceMode(jus::connectionMode::modeJson) { + m_interfaceClient(std::move(_connection)) { JUS_INFO("-----------------"); JUS_INFO("-- NEW Service --"); JUS_INFO("-----------------"); @@ -41,61 +45,89 @@ void jus::GateWayService::stop() { void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) { _data.add("client-id", ejson::Number(_userSessionId)); - JUS_DEBUG("Send Service: " << _data.generateHumanString()); - m_interfaceClient.write(_data.generateMachineString()); + m_interfaceClient.writeJson(_data); } + void jus::GateWayService::SendData(uint64_t _userSessionId, jus::Buffer& _data) { _data.setClientId(_userSessionId); _data.prepare(); - if (m_interfaceMode == jus::connectionMode::modeJson) { - JUS_ERROR("NOT manage transcriptioon binary to JSON ... "); + if (m_interfaceClient.getMode() == jus::connectionMode::modeJson) { ejson::Object obj = _data.toJson(); - JUS_DEBUG("Send Service: " << obj.generateHumanString()); - m_interfaceClient.write(obj.generateMachineString()); - } else if (m_interfaceMode == jus::connectionMode::modeXml) { + m_interfaceClient.writeJson(obj); + } else if (m_interfaceClient.getMode() == jus::connectionMode::modeXml) { JUS_ERROR("NOT manage transcriptioon binary to XML ... "); - } else if (m_interfaceMode == jus::connectionMode::modeBinary) { + } else if (m_interfaceClient.getMode() == jus::connectionMode::modeBinary) { m_interfaceClient.writeBinary(_data); } else { JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... "); } } -void jus::GateWayService::onServiceData(std::string _value) { - JUS_DEBUG("On service data: " << _value); - ejson::Object data(_value); - data.add("from-service", ejson::String(m_name)); - if (data.valueExist("event") == true) { - // No need to have a user ID ... - if (data["event"].toString().get() == "IS-ALIVE") { - JUS_VERBOSE("Service Alive ..."); - if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) { - m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}"); +void jus::GateWayService::onServiceData(jus::Buffer& _value) { + //JUS_DEBUG("On service data: " << _value); + uint32_t transactionId = _value.getTransactionId(); + //data.add("from-service", ejson::String(m_name)); + if (_value.getType() == jus::Buffer::typeMessage::event) { + /* + if (data.valueExist("event") == true) { + // No need to have a user ID ... + if (data["event"].toString().get() == "IS-ALIVE") { + JUS_VERBOSE("Service Alive ..."); + if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) { + ejson::Object tmpp; + tmpp.add("event", ejson::String("IS-ALIVE")); + m_interfaceClient.writeJson(tmpp); + } + } else { + JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'"); } - } else { - JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'"); - } - return; - } - 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()); - // TODO : Return something ... return; } - m_name = data["connect-service"].toString().get(); - m_interfaceClient.setInterfaceName("srv-" + m_name); - JUS_WARNING("Service name configured"); - // TODO : Return something ... + */ return; } - if (data.valueExist("client-id") == false) { + if (_value.getType() == jus::Buffer::typeMessage::call) { + std::string callFunction = _value.getCall(); + if (callFunction == "setMode") { + std::string mode = _value.getParameter(0); + if (mode == "JSON") { + JUS_WARNING("Change mode in: JSON"); + m_interfaceClient.answerValue(transactionId, true); + m_interfaceClient.setMode(jus::connectionMode::modeJson); + } else if (mode == "BIN") { + JUS_WARNING("Change mode in: BINARY"); + m_interfaceClient.answerValue(transactionId, true); + m_interfaceClient.setMode(jus::connectionMode::modeBinary); + } else if (mode == "XML") { + JUS_WARNING("Change mode in: XML"); + //m_interfaceMode = jus::connectionMode::modeXml; + m_interfaceClient.answerValue(transactionId, false); + } else { + answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]"); + } + return; + } else if (callFunction == "connect-service") { + if (m_name != "") { + JUS_WARNING("Service interface ==> try change the servie name after init: '" << _value.getParameter(0)); + m_interfaceClient.answerValue(transactionId, false); + return; + } + m_name = _value.getParameter(0); + m_interfaceClient.setInterfaceName("srv-" + m_name); + m_interfaceClient.answerValue(transactionId, false); + return; + } + answerProtocolError(transactionId, "unknow function"); + } + if (_value.getClientId() == 0) { JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'"); return; } - uint64_t userSessionId = data["client-id"].toNumber().getU64(); - data.remove("client-id"); - data.remove("action"); - m_gatewayInterface->answer(userSessionId, data); + m_gatewayInterface->answer(_value.getClientId(), _value); } + +void jus::GateWayService::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) { + m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp); + m_interfaceClient.disconnect(true); +} \ No newline at end of file diff --git a/jus/GateWayService.h b/jus/GateWayService.h index 38af4f7..7da488a 100644 --- a/jus/GateWayService.h +++ b/jus/GateWayService.h @@ -18,7 +18,6 @@ namespace jus { jus::GateWay* m_gatewayInterface; jus::TcpString m_interfaceClient; std::string m_name; - enum jus::connectionMode m_interfaceMode; public: esignal::Signal signalIsConnected; public: @@ -26,7 +25,7 @@ namespace jus { virtual ~GateWayService(); void start(); void stop(); - void onServiceData(std::string _value); + void onServiceData(jus::Buffer& _value); public: void SendData(uint64_t _userSessionId, ejson::Object _data); void SendData(uint64_t _userSessionId, jus::Buffer& _data); @@ -34,6 +33,8 @@ namespace jus { return m_name; } bool isAlive(); + protected: + void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp); }; } diff --git a/jus/Service.cpp b/jus/Service.cpp index 63d35ea..1047dd3 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -34,29 +34,27 @@ std::vector jus::Service::getExtention() { } -void jus::Service::onClientData(std::string _value) { - JUS_INFO("Request: " << _value); - ejson::Object request(_value); - uint64_t tmpID = request["id"].toNumber().getU64(); - uint64_t clientId = request["client-id"].toNumber().getU64(); +void jus::Service::onClientData(jus::Buffer& _value) { + uint32_t tmpID = _value.getTransactionId(); + uint32_t clientId = _value.getClientId();; auto it = m_callMultiData.begin(); while (it != m_callMultiData.end()) { if ( it->getTransactionId() == tmpID && it->getClientId() == clientId) { JUS_WARNING("Append data ... " << tmpID); - it->appendData(request); + it->appendData(_value); if (it->isFinished() == true) { JUS_WARNING("CALL Function ..."); - callJson(tmpID, it->getRaw()); + callBinary(tmpID, it->getRaw()); it = m_callMultiData.erase(it); } return; } ++it; } - jus::FutureCall futCall(clientId, tmpID, request); + jus::FutureCall futCall(clientId, tmpID, _value); if (futCall.isFinished() == true) { - callJson(tmpID, futCall.getRaw()); + callBinary(tmpID, futCall.getRaw()); } else { m_callMultiData.push_back(futCall); } @@ -81,7 +79,13 @@ void jus::Service::connect(const std::string& _serviceName, uint32_t _numberRetr } m_interfaceClient->setInterface(std::move(connection)); m_interfaceClient->connect(); - m_interfaceClient->write(std::string("{\"connect-service\":\"") + _serviceName + "\"}"); + ejson::Object tmpp; + tmpp.add("id", ejson::Number(1)); + tmpp.add("call", ejson::String("connect-service")); + ejson::Array params; + params.add(ejson::String(_serviceName)); + tmpp.add("param", params); + m_interfaceClient->writeJson(tmpp); JUS_DEBUG("connect [STOP]"); } @@ -97,12 +101,17 @@ bool jus::Service::GateWayAlive() { void jus::Service::pingIsAlive() { if (std::chrono::steady_clock::now() - m_interfaceClient->getLastTimeSend() >= std::chrono::seconds(30)) { - m_interfaceClient->write("{\"event\":\"IS-ALIVE\"}"); + /* + ejson::Object tmpp; + tmpp.add("event", ejson::String("IS-ALIVE")); + m_interfaceClient->writeJson(tmpp); + */ } } -void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj) { - if (_obj.valueExist("event") == true) { +void jus::Service::callBinary(uint32_t _transactionId, jus::Buffer& _obj) { + if (_obj.getType() == jus::Buffer::typeMessage::event) { + /* std::string event = _obj["event"].toString().get(); if (event == "IS-ALIVE") { // Gateway just aswer a keep alive information ... @@ -110,44 +119,39 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj) } else { JUS_ERROR("Unknow event: '" << event << "'"); } + */ + JUS_ERROR("Unknow event: '...'"); return; } - ejson::Object answer; - uint64_t clientId = _obj["client-id"].toNumber().getU64(); - if (_obj.valueExist("call") == true) { - std::string call = _obj["call"].toString().get(); - ejson::Array params = _obj["param"].toArray(); - if (call[0] == '_') { - if (call == "_new") { - std::string userName = params[0].toString().get(); - std::string clientName = params[1].toString().get(); - std::vector clientGroup = convertJsonTo>(params[2]); + if (_obj.getType() == jus::Buffer::typeMessage::answer) { + JUS_ERROR("Local Answer: '...'"); + return; + } + //if (_obj.getType() == jus::Buffer::typeMessage::event) { + if (m_interfaceClient->getMode() == jus::connectionMode::modeBinary) { + + } else if (m_interfaceClient->getMode() == jus::connectionMode::modeJson) { + uint32_t clientId = _obj.getClientId(); + std::string callFunction = _obj.getCall(); + if (callFunction[0] == '_') { + if (callFunction == "_new") { + std::string userName = _obj.getParameter(0); + std::string clientName = _obj.getParameter(1); + std::vector clientGroup = _obj.getParameter>(2); clientConnect(clientId, userName, clientName, clientGroup); - } else if (call == "_delete") { + } else if (callFunction == "_delete") { clientDisconnect(clientId); } - // TODO : Do it better ... - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(clientId)); - answer.add("return", ejson::Boolean(true)); - JUS_INFO("Answer: " << answer.generateHumanString()); - m_interfaceClient->write(answer.generateMachineString()); + m_interfaceClient->answerValue(_transactionId, true, clientId); return; - } else if (isFunctionAuthorized(clientId, call) == true) { - callJson2(_transactionId, clientId, call, params); + } else if (isFunctionAuthorized(clientId, callFunction) == true) { + callBinary2(_transactionId, clientId, callFunction, _obj); return; } else { - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(clientId)); - answer.add("error", ejson::String("NOT-AUTHORIZED-FUNCTION")); - JUS_INFO("Answer: " << answer.generateHumanString()); - m_interfaceClient->write(answer.generateMachineString()); + m_interfaceClient->answerError(_transactionId, "NOT-AUTHORIZED-FUNCTION", "", clientId); return; } + } else { + JUS_ERROR("Not manage transfer mode "); } - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(clientId)); - answer.add("error", ejson::String("NOT-IMPLEMENTED-FUNCTION")); - JUS_INFO("Answer: " << answer.generateHumanString()); - m_interfaceClient->write(answer.generateMachineString()); } diff --git a/jus/Service.h b/jus/Service.h index 0e92049..89836d8 100644 --- a/jus/Service.h +++ b/jus/Service.h @@ -69,8 +69,7 @@ namespace jus { void connect(const std::string& _serviceName, uint32_t _numberRetry = 1); void disconnect(); private: - void onClientData(std::string _value); - std::string asyncRead(); + void onClientData(jus::Buffer& _value); public: void pingIsAlive(); bool GateWayAlive(); @@ -86,8 +85,8 @@ namespace jus { virtual void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector& _groups) = 0; virtual void clientDisconnect(uint64_t _clientId) = 0; // Genenric function call: - void callJson(uint64_t _transactionId, const ejson::Object& _obj); - virtual void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _obj) = 0; + void callBinary(uint32_t _transactionId, jus::Buffer& _obj); + virtual void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) = 0; std::vector getExtention(); public: // Add Local fuction (depend on this class) @@ -116,6 +115,8 @@ namespace jus { JUS_INFO("Add function '" << _name << "' in local mode"); m_listFunction.push_back(tmp); } + + }; template class ServiceType : public jus::Service { @@ -208,15 +209,10 @@ namespace jus { } it->second.first->setGroups(_clientGroups); } - void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _params) { + void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) { auto it = m_interface.find(_clientId); if (it == m_interface.end()) { - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("error", ejson::String("CLIENT-UNKNOW")); - JUS_INFO("Answer: " << answer.generateHumanString()); - m_interfaceClient->write(answer.generateMachineString()); + m_interfaceClient->answerError(_transactionId, "CLIENT-UNKNOW", "", _clientId); return; } for (auto &it2 : m_listFunction) { @@ -229,19 +225,19 @@ namespace jus { switch (it2->getType()) { case jus::AbstractFunction::type::object: { JUS_TYPE_SERVICE* elem = it->second.second.get(); - it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)elem); + it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)elem); return; } case jus::AbstractFunction::type::local: { - it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)((RemoteProcessCall*)this)); + it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)((RemoteProcessCall*)this)); return; } case jus::AbstractFunction::type::service: { - it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)this); + it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)this); return; } case jus::AbstractFunction::type::global: { - it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, nullptr); + it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, nullptr); return; } case jus::AbstractFunction::type::unknow: @@ -249,14 +245,7 @@ namespace jus { break; } } - { - ejson::Object answer; - answer.add("id", ejson::Number(_transactionId)); - answer.add("client-id", ejson::Number(_clientId)); - answer.add("error", ejson::String("FUNCTION-UNKNOW")); - JUS_INFO("Answer: " << answer.generateHumanString()); - m_interfaceClient->write(answer.generateMachineString()); - } + m_interfaceClient->answerError(_transactionId, "FUNCTION-UNKNOW", "", _clientId); return; } }; diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index 79ca191..68dd07a 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -12,20 +12,20 @@ jus::TcpString::TcpString(enet::Tcp _connection) : m_connection(std::move(_connection)), m_thread(nullptr), m_observerElement(nullptr), - m_observerRawElement(nullptr), m_threadAsync(nullptr) { m_threadRunning = false; m_threadAsyncRunning = false; + m_interfaceMode = jus::connectionMode::modeJson; } jus::TcpString::TcpString() : m_connection(), m_thread(nullptr), m_observerElement(nullptr), - m_observerRawElement(nullptr), m_threadAsync(nullptr) { m_threadRunning = false; m_threadAsyncRunning = false; + m_interfaceMode = jus::connectionMode::modeJson; } void jus::TcpString::setInterface(enet::Tcp _connection) { @@ -39,38 +39,14 @@ jus::TcpString::~TcpString() { void jus::TcpString::setInterfaceName(const std::string& _name) { ethread::setName(*m_thread, "Tcp-" + _name); } -// TODO : Do it better : + void jus::TcpString::threadCallback() { ethread::setName("TcpString-input"); // get datas: while ( m_threadRunning == true && m_connection.getConnectionStatus() == enet::Tcp::status::link) { // READ section data: - if (m_observerElement != nullptr) { - JUS_PRINT("Call String ..."); - std::string data = std::move(read()); - JUS_PRINT("Receive data: '" << data << "'"); - if (data.size() != 0) { - m_lastReceive = std::chrono::steady_clock::now(); - JUS_PRINT(" Call function ... 1"); - if (m_observerElement != nullptr) { - m_observerElement(std::move(data)); - } else if (m_observerRawElement != nullptr) { - jus::Buffer dataRaw; - dataRaw.composeWith(data); - m_observerRawElement(dataRaw); - } else { - JUS_ERROR("Lose DATA ..."); - } - JUS_PRINT(" Call function ... 1 (done)"); - } - } else if (m_observerRawElement != nullptr) { - JUS_PRINT("Call Raw ..."); - jus::Buffer data = readRaw(); - JUS_PRINT(" Call function ... 2"); - m_observerRawElement(data); - JUS_PRINT(" Call function ... 2 (done)"); - } + read(); } m_threadRunning = false; JUS_DEBUG("End of thread"); @@ -136,33 +112,30 @@ void jus::TcpString::disconnect(bool _inThreadStop){ JUS_DEBUG("disconnect [STOP]"); } -int32_t jus::TcpString::write(const std::string& _data) { +int32_t jus::TcpString::writeJson(ejson::Object& _data) { + JUS_DEBUG("Send JSON '" << _data.generateHumanString() << "'"); if (m_threadRunning == false) { return -2; } - if (_data.size() == 0) { - return 0; - } - uint32_t size = _data.size(); m_lastSend = std::chrono::steady_clock::now(); - m_connection.write(&size, 4); - return m_connection.write(_data.c_str(), _data.size()); + m_connection.write("J", 1); + std::string tmpData = _data.generateMachineString(); + uint32_t dataSize = tmpData.size(); + m_connection.write(&dataSize, sizeof(uint32_t)); + m_connection.write(&tmpData[0], tmpData.size()); + return 1; } + int32_t jus::TcpString::writeBinary(jus::Buffer& _data) { _data.prepare(); - JUS_DEBUG("Send BINARY '" << _data.generateHumanString() << "'"); + JUS_DEBUG("Send BINARY '" << _data.toJson().generateHumanString() << "'"); if (m_threadRunning == false) { return -2; } - /* - if (_data.size() == 0) { - return 0; - } - */ - //uint32_t size = _data.size(); + m_lastSend = std::chrono::steady_clock::now(); + m_connection.write("B", 1); const uint8_t* data = nullptr; uint32_t dataSize = 0; - m_lastSend = std::chrono::steady_clock::now(); data = _data.getHeader(); dataSize = _data.getHeaderSize(); m_connection.write(data, dataSize); @@ -175,84 +148,92 @@ int32_t jus::TcpString::writeBinary(jus::Buffer& _data) { return 1; } -std::string jus::TcpString::read() { +void jus::TcpString::read() { JUS_VERBOSE("Read [START]"); if (m_threadRunning == false) { JUS_DEBUG("Read [END] Disconected"); - return ""; + return; } // TODO : Do it better with a correct way to check data size ... JUS_VERBOSE("Read [START]"); - std::string out; - uint32_t size = 0; - int32_t len = m_connection.read(&size, 4); - if (len != 4) { - JUS_ERROR("Protocol error occured ..."); + uint8_t type = 0; + int32_t len = m_connection.read(&type, 1); + if (len == 0) { + JUS_ERROR("Protocol error occured ==> No datas ..."); } else { - if (size == -1) { - JUS_WARNING("Remote close connection"); - m_threadRunning = false; - //m_connection.unlink(); - } else { - int64_t offset = 0; - out.resize(size); - while (offset != size) { - len = m_connection.read(&out[offset], size-offset); - offset += len; - if (len == 0) { - JUS_WARNING("Read No data"); - //break; + if (type == 'B') { // binary + // Binary mode ... start with the lenght of the stream + JUS_VERBOSE("Read Binary [START]"); + uint32_t size = 0; + len = m_connection.read(&size, 4); + if (len != 4) { + JUS_ERROR("Protocol error occured ..."); + } else { + if (size == -1) { + JUS_WARNING("Remote close connection"); + m_threadRunning = false; + //m_connection.unlink(); + } else { + int64_t offset = 0; + m_buffer.resize(size); + while (offset != size) { + len = m_connection.read(&m_buffer[offset], size-offset); + offset += len; + if (len == 0) { + JUS_WARNING("Read No data"); + } + } + if (m_observerElement != nullptr) { + jus::Buffer dataRaw; + dataRaw.composeWith(m_buffer); + JUS_VERBOSE("Receive Binary :" << dataRaw.toJson().generateHumanString()); + m_observerElement(dataRaw); + } } - /* - else if (size != offset) { - JUS_ERROR("Protocol error occured .2. ==> concat (offset=" << offset << " size=" << size); - } - */ } + JUS_VERBOSE("ReadRaw [STOP]"); + } else if ( type == 'X' // XML + || type == 'J' // JSON + ) { + JUS_VERBOSE("Read sized String [START]"); + // XML/JSON mode ... start with the lenght of the stream + std::string out; + uint32_t size = 0; + len = m_connection.read(&size, 4); + if (len != 4) { + JUS_ERROR("Protocol error occured ..."); + } else { + if (size == -1) { + JUS_WARNING("Remote close connection"); + m_threadRunning = false; + //m_connection.unlink(); + } else { + int64_t offset = 0; + out.resize(size); + while (offset != size) { + len = m_connection.read(&out[offset], size-offset); + offset += len; + if (len == 0) { + JUS_WARNING("Read No data"); + } + } + if (m_observerElement != nullptr) { + JUS_VERBOSE("Receive String :" << out); + jus::Buffer dataRaw; + dataRaw.composeWith(out); + m_observerElement(dataRaw); + } + } + } + JUS_VERBOSE("Read sized String [STOP]"); + } else if (type == '{') { + // JSON Raw mode ... Finish with a \0 + // TODO: m_dataBuffer + } else if (type == '<') { + // XML Raw mode ... Finish with a \0 + // TODO : m_dataBuffer } } - JUS_VERBOSE("Read [STOP]"); - return out; -} - -jus::Buffer jus::TcpString::readRaw() { - jus::Buffer out; - JUS_VERBOSE("ReadRaw [START]"); - if (m_threadRunning == false) { - JUS_DEBUG("Read [END] Disconected"); - return out; - } - JUS_VERBOSE("ReadRaw [START]"); - uint32_t size = 0; - int32_t len = m_connection.read(&size, 4); - if (len != 4) { - JUS_ERROR("Protocol error occured ..."); - } else { - if (size == -1) { - JUS_WARNING("Remote close connection"); - m_threadRunning = false; - //m_connection.unlink(); - } else { - int64_t offset = 0; - m_buffer.resize(size); - while (offset != size) { - len = m_connection.read(&m_buffer[offset], size-offset); - offset += len; - if (len == 0) { - JUS_WARNING("Read No data"); - //break; - } - /* - else if (size != offset) { - JUS_ERROR("Protocol error occured .2. ==> concat (offset=" << offset << " size=" << size); - } - */ - } - out.composeWith(m_buffer); - } - } - JUS_VERBOSE("ReadRaw [STOP]"); - return out; } void jus::TcpString::threadAsyncCallback() { @@ -280,3 +261,51 @@ void jus::TcpString::threadAsyncCallback() { JUS_DEBUG("End of thread"); } + +void jus::TcpString::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp, uint32_t _clientId) { + if (m_interfaceMode == jus::connectionMode::modeJson) { + ejson::Object answer; + answer.add("error", ejson::String(_errorValue)); + answer.add("id", ejson::Number(_clientTransactionId)); + if (_clientId != 0) { + answer.add("client-id", ejson::Number(_clientId)); + } + answer.add("error-help", ejson::String(_errorHelp)); + writeJson(answer); + } else if (m_interfaceMode == jus::connectionMode::modeBinary) { + jus::Buffer answer; + answer.setType(jus::Buffer::typeMessage::answer); + answer.setTransactionId(_clientTransactionId); + answer.setClientId(_clientId); + answer.addError(_errorValue, _errorHelp); + writeBinary(answer); + } else if (m_interfaceMode == jus::connectionMode::modeXml) { + JUS_ERROR("TODO ... "); + } else { + JUS_ERROR("wrong type of communication"); + } +} + + +void jus::TcpString::answerVoid(uint64_t _clientTransactionId, uint32_t _clientId) { + if (m_interfaceMode == jus::connectionMode::modeJson) { + ejson::Object answer; + answer.add("id", ejson::Number(_clientTransactionId)); + if (_clientId != 0) { + answer.add("client-id", ejson::Number(_clientId)); + } + answer.add("return", ejson::Null()); + writeJson(answer); + } else if (m_interfaceMode == jus::connectionMode::modeBinary) { + jus::Buffer answer; + answer.setType(jus::Buffer::typeMessage::answer); + answer.setTransactionId(_clientTransactionId); + answer.setClientId(_clientId); + answer.addParameter(); + writeBinary(answer); + } else if (m_interfaceMode == jus::connectionMode::modeXml) { + JUS_ERROR("TODO ... "); + } else { + JUS_ERROR("wrong type of communication"); + } +} \ No newline at end of file diff --git a/jus/TcpString.h b/jus/TcpString.h index 46c3652..2e4228c 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace jus { class TcpString : public eproperty::Interface { @@ -17,13 +19,22 @@ namespace jus { enet::Tcp m_connection; std::thread* m_thread; bool m_threadRunning; + protected: + enum jus::connectionMode m_interfaceMode; + public: + enum jus::connectionMode getMode() { + return m_interfaceMode; + } + void setMode(enum jus::connectionMode _mode) { + m_interfaceMode = _mode; + } + std::vector m_buffer; + std::vector m_temporaryBuffer; std::chrono::steady_clock::time_point m_lastReceive; std::chrono::steady_clock::time_point m_lastSend; public: - using Observer = std::function; //!< Define an Observer: function pointer - using ObserverRaw = std::function; //!< Define an Observer: function pointer + using Observer = std::function; //!< Define an Observer: function pointer Observer m_observerElement; - ObserverRaw m_observerRawElement; /** * @brief Connect an function member on the signal with the shared_ptr object. * @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr. @@ -31,23 +42,11 @@ namespace jus { * @param[in] _args Argument optinnal the user want to add. */ template - void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(std::string)) { - m_observerElement = [=](std::string _value){ - (*_class.*_func)(std::move(_value)); - }; - } - void connectClean() { - m_observerElement = nullptr; - } - template - void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) { - m_observerRawElement = [=](jus::Buffer& _value){ + void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) { + m_observerElement = [=](jus::Buffer& _value){ (*_class.*_func)(_value); }; } - void connectCleanRaw() { - m_observerRawElement = nullptr; - } public: TcpString(); TcpString(enet::Tcp _connection); @@ -57,13 +56,12 @@ namespace jus { void disconnect(bool _inThreadStop = false); bool isActive() const; void setInterfaceName(const std::string& _name); - int32_t write(const std::string& _data); + int32_t writeJson(ejson::Object& _data); int32_t writeBinary(jus::Buffer& _data); std::string asyncRead(); private: - std::string read(); + void read(); jus::Buffer readRaw(); - std::vector m_buffer; private: void threadCallback(); public: @@ -86,6 +84,39 @@ namespace jus { std::unique_lock lock(m_threadAsyncMutex); m_threadAsyncList.push_back(_elem); } + + + + void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp); + template + void answerValue(uint64_t _clientTransactionId, JUS_ARG _value, uint32_t _clientId=0) { + if (m_interfaceMode == jus::connectionMode::modeJson) { + ejson::Object answer; + answer.add("id", ejson::Number(_clientTransactionId)); + if (_clientId != 0) { + answer.add("client-id", ejson::Number(_clientId)); + } + std::vector asyncAction; + answer.add("return", jus::convertToJson(asyncAction, -1, _value)); + if (asyncAction.size() != 0) { + JUS_ERROR("ASYNC datas ... TODO ///"); + } + writeJson(answer); + } else if (m_interfaceMode == jus::connectionMode::modeBinary) { + jus::Buffer answer; + answer.setType(jus::Buffer::typeMessage::answer); + answer.setTransactionId(_clientTransactionId); + answer.setClientId(_clientId); + answer.addAnswer(_value); + writeBinary(answer); + } else if (m_interfaceMode == jus::connectionMode::modeXml) { + JUS_ERROR("TODO ... "); + } else { + JUS_ERROR("wrong type of communication"); + } + } + void answerVoid(uint64_t _clientTransactionId, uint32_t _clientId=0); + void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment="", uint32_t _clientId=0); }; }