From 4983fea72119662e2cd1a2cc5f7556d521be5a6a Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 10 Jun 2016 21:34:21 +0200 Subject: [PATCH] [DEV] start better interface binary --- jus/Buffer.cpp | 319 ++++++++++++++++----- jus/Buffer.h | 49 ++-- jus/BufferConvertBinaryToJson.cpp | 106 +++++++ jus/Client.cpp | 2 - jus/GateWayClient.cpp | 450 ++++++++++++++++++++++++------ jus/GateWayClient.h | 11 +- jus/GateWayService.cpp | 19 +- jus/GateWayService.h | 3 + jus/ParamType.cpp | 6 + jus/ParamType.h | 5 + jus/TcpString.cpp | 12 +- jus/TcpString.h | 10 +- lutin_jus.py | 1 + 13 files changed, 817 insertions(+), 176 deletions(-) create mode 100644 jus/BufferConvertBinaryToJson.cpp diff --git a/jus/Buffer.cpp b/jus/Buffer.cpp index 787edab..23de799 100644 --- a/jus/Buffer.cpp +++ b/jus/Buffer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace etk { template<> std::string to_string(const enum jus::Buffer::typeMessage& _value) { @@ -20,7 +21,7 @@ namespace etk { return "???"; } } -std::ostream& jus::operator <<(std::ostream& _os, const std::vector& _value) { +std::ostream& jus::operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value) { _os << etk::to_string(_value); return _os; } @@ -44,22 +45,32 @@ jus::Buffer::Buffer() { void jus::Buffer::composeWith(const std::vector& _buffer) { clear(); m_header.lenght = _buffer.size(); - memcpy(&m_header + 4, &_buffer[0], sizeof(headerBin)-4); - JUS_INFO("Get binary message : "); - JUS_INFO(" lenght = " << m_header.lenght); - JUS_INFO(" versionProtocol = " << m_header.versionProtocol); - JUS_INFO(" transactionID = " << m_header.transactionID); - JUS_INFO(" clientID = " << m_header.clientID); - JUS_INFO(" partID = " << m_header.partID); - enum jus::Buffer::typeMessage ttype = getTypeType(m_header.typeMessage); - JUS_INFO(" typeMessage = " << ttype); - JUS_TODO(" ..."); + uint32_t offset = 0; + memcpy(reinterpret_cast(&m_header) + sizeof(uint32_t), &_buffer[offset], sizeof(headerBin)-sizeof(uint32_t)); + offset += sizeof(headerBin)-sizeof(uint32_t); + if (m_header.numberOfParameter != 0) { + m_paramOffset.resize(m_header.numberOfParameter); + memcpy(&m_paramOffset[0], &_buffer[offset], m_header.numberOfParameter * sizeof(uint16_t)); + offset += m_header.numberOfParameter * sizeof(uint16_t); + m_data.resize(_buffer.size() - offset); + memcpy(&m_data[0], &_buffer[offset], m_data.size()); + } else { + // TODO : check size ... + } + JUS_INFO("Get binary messages " << generateHumanString()); } void jus::Buffer::clear() { + JUS_WARNING("clear buffer"); m_data.clear(); m_paramOffset.clear(); - m_header.clear(); + m_header.lenght = 0; + m_header.versionProtocol = 1; + m_header.transactionID = 1; + m_header.clientID = 0; + m_header.partID = 0x8000; + m_header.typeMessage = 1; + m_header.numberOfParameter = 1; } std::string jus::Buffer::generateHumanString() { std::string out = "jus::Buffer Lenght=: "; @@ -67,69 +78,166 @@ std::string jus::Buffer::generateHumanString() { out += " v=" + etk::to_string(m_header.versionProtocol); out += " id=" + etk::to_string(m_header.transactionID); out += " cId=" + etk::to_string(m_header.clientID); - out += " pId=" + etk::to_string(m_header.partID); + out += " pId=" + etk::to_string(getPartId()); + out += " finish=" + etk::to_string(getPartFinish()); enum jus::Buffer::typeMessage type = getTypeType(m_header.typeMessage); out += " type=" + etk::to_string(type); + switch (type) { + case jus::Buffer::typeMessage::call: + out += " nbParam=" + etk::to_string(getNumberParameter()); + break; + case jus::Buffer::typeMessage::answer: + if (getNumberParameter() == 1) { + out += " mode=Value"; + } else if (getNumberParameter() == 2) { + out += " mode=Error"; + } else if (getNumberParameter() == 3) { + out += " mode=Value+Error"; + } else { + out += " mode=???"; + } + break; + case jus::Buffer::typeMessage::event: + + break; + } + if (getNumberParameter() != 0) { + out += " paramType("; + for (int32_t iii=0; iii< getNumberParameter(); ++iii) { + if (iii != 0) { + out += ","; + } + out += internalGetParameterType(iii); + } + out += ")"; + } return out; } -uint16_t jus::Buffer::getProtocalVersion() { +uint16_t jus::Buffer::getProtocalVersion() const { return m_header.versionProtocol; } void jus::Buffer::setProtocolVersion(uint16_t _value) { + JUS_WARNING("setProtocolVersion :" << _value); m_header.versionProtocol = _value; } -uint32_t jus::Buffer::getTransactionId() { +uint32_t jus::Buffer::getTransactionId() const { return m_header.transactionID; } void jus::Buffer::setTransactionId(uint32_t _value) { + JUS_WARNING("setTransactionId :" << _value); m_header.transactionID = _value; } -uint32_t jus::Buffer::getClientId() { +uint32_t jus::Buffer::getClientId() const { return m_header.clientID; } void jus::Buffer::setClientId(uint32_t _value) { + JUS_WARNING("setClientId :" << _value); m_header.clientID = _value; } // note limited 15 bits -uint16_t jus::Buffer::getPartId() { +uint16_t jus::Buffer::getPartId() const { return uint16_t(m_header.partID & 0x7FFF); } void jus::Buffer::setPartId(uint16_t _value) { + JUS_WARNING("setPartId :" << _value); m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF); } -bool jus::Buffer::getPartFinish() { - return m_header.versionProtocol<0; +bool jus::Buffer::getPartFinish() const { + return m_header.partID<0; } void jus::Buffer::setPartFinish(bool _value) { + JUS_WARNING("setPartFinish :" << _value); if (_value == true) { - m_header.versionProtocol = (m_header.versionProtocol & 0x7FFF) | 0x8000; + m_header.partID = (m_header.partID & 0x7FFF) | 0x8000; } else { - m_header.versionProtocol = m_header.versionProtocol & 0x7FFF; + m_header.partID = m_header.partID & 0x7FFF; } } -enum jus::Buffer::typeMessage jus::Buffer::getType() { +enum jus::Buffer::typeMessage jus::Buffer::getType() const { return (enum jus::Buffer::typeMessage)m_header.typeMessage; } void jus::Buffer::setType(enum typeMessage _value) { + JUS_WARNING("setType :" << _value); m_header.typeMessage = uint16_t(_value); } -uint16_t jus::Buffer::getNumberParameter() { +uint16_t jus::Buffer::getNumberParameter() const { return m_paramOffset.size()-1; } +std::string jus::Buffer::internalGetParameterType(int32_t _id) const { + std::string out; + if (m_paramOffset.size() <= _id) { + JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); + return out; + } + out = reinterpret_cast(&m_data[m_paramOffset[_id]]); + return out; +} +std::string jus::Buffer::getParameterType(int32_t _id) const { + return internalGetParameterType(_id + 1); +} +const uint8_t* jus::Buffer::internalGetParameterPointer(int32_t _id) const { + const uint8_t* out = nullptr; + if (m_paramOffset.size() <= _id) { + JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); + return out; + } + out = reinterpret_cast(&m_data[m_paramOffset[_id]]); + if (out == nullptr) { + return out; + } + // TODO : unlock if > 1024 + while (*out != 0) { + out++; + } + out++; + return out; +} + +const uint8_t* jus::Buffer::getParameterPointer(int32_t _id) const { + return internalGetParameterPointer(_id + 1); +} + +uint32_t jus::Buffer::internalGetParameterSize(int32_t _id) const { + int32_t out = 0; + if (m_paramOffset.size() <= _id) { + JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); + return out; + } + int32_t startPos = m_paramOffset[_id]; + int32_t endPos = m_data.size(); + if (m_paramOffset.size() > _id+1) { + endPos = m_paramOffset[_id+1]; + } + // First get type: + const char* type = reinterpret_cast(&m_data[startPos]); // Will be stop with \0 ... + // move in the buffer pos + startPos += strlen(type) + 1; + // get real data size + out = endPos - startPos; + if (out < 0) { + JUS_ERROR("Get size < 0 : " << out); + out = 0; + } + return out; +} + +uint32_t jus::Buffer::getParameterSize(int32_t _id) const { + return internalGetParameterSize(_id + 1); +} void jus::Buffer::addParameter() { int32_t currentOffset = m_data.size(); @@ -151,8 +259,9 @@ void jus::Buffer::addParameter(const std::string& _value) { m_data.push_back('n'); m_data.push_back('g'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+_value.size()+1); - memcpy(&m_data[currentOffset], &_value[0], m_data.size()); + memcpy(&m_data[currentOffset], &_value[0], _value.size()); } template<> void jus::Buffer::addParameter(const int8_t& _value) { @@ -187,6 +296,7 @@ void jus::Buffer::addParameter(const int16_t& _value) { m_data.push_back('1'); m_data.push_back('6'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+2); memcpy(&m_data[currentOffset], &_value, 2); } @@ -201,6 +311,7 @@ void jus::Buffer::addParameter(const uint16_t& _value) { m_data.push_back('1'); m_data.push_back('6'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+2); memcpy(&m_data[currentOffset], &_value, 2); } @@ -214,6 +325,7 @@ void jus::Buffer::addParameter(const int32_t& _value) { m_data.push_back('3'); m_data.push_back('2'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+4); memcpy(&m_data[currentOffset], &_value, 4); } @@ -228,6 +340,7 @@ void jus::Buffer::addParameter(const uint32_t& _value) { m_data.push_back('3'); m_data.push_back('2'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+4); memcpy(&m_data[currentOffset], &_value, 4); } @@ -241,6 +354,7 @@ void jus::Buffer::addParameter(const int64_t& _value) { m_data.push_back('3'); m_data.push_back('2'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+8); memcpy(&m_data[currentOffset], &_value, 8); } @@ -255,6 +369,7 @@ void jus::Buffer::addParameter(const uint64_t& _value) { m_data.push_back('6'); m_data.push_back('4'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+8); memcpy(&m_data[currentOffset], &_value, 8); } @@ -268,6 +383,7 @@ void jus::Buffer::addParameter(const float& _value) { m_data.push_back('a'); m_data.push_back('t'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+4); memcpy(&m_data[currentOffset], &_value, 4); } @@ -282,6 +398,7 @@ void jus::Buffer::addParameter(const double& _value) { m_data.push_back('l'); m_data.push_back('e'); m_data.push_back('\0'); + currentOffset = m_data.size(); m_data.resize(m_data.size()+8); memcpy(&m_data[currentOffset], &_value, 8); } @@ -302,7 +419,7 @@ void jus::Buffer::addParameter(const bool& _value) { } template<> -std::string jus::Buffer::internalGetParameter(int32_t _id) { +std::string jus::Buffer::internalGetParameter(int32_t _id) const { std::string out; if (m_paramOffset.size() <= _id) { JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); @@ -314,7 +431,7 @@ std::string jus::Buffer::internalGetParameter(int32_t _id) { endPos = m_paramOffset[_id+1]; } // First get type: - char* type = reinterpret_cast(&m_data[startPos]); // Will be stop with \0 ... + const char* type = reinterpret_cast(&m_data[startPos]); // Will be stop with \0 ... if (strcmp(type, "string") == 0) { // OK // move in the buffer pos @@ -340,52 +457,36 @@ std::string jus::Buffer::internalGetParameter(int32_t _id) { template<> -int8_t jus::Buffer::internalGetParameter(int32_t _id) { - int8_t out; - if (m_paramOffset.size() <= _id) { - JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); - return out; +int8_t jus::Buffer::internalGetParameter(int32_t _id) const { + std::string type = getParameterType(_id); + const uint8_t* pointer = getParameterPointer(_id); + uint32_t dataSize = getParameterSize(_id); + if (createType() != type) { + return 0; } - int32_t startPos = m_paramOffset[_id]; - int32_t endPos = m_data.size(); - if (m_paramOffset.size() > _id+1) { - endPos = m_paramOffset[_id+1]; + const int8_t* pointer2 = reinterpret_cast(pointer); + return *pointer2; +} + +template<> +int32_t jus::Buffer::internalGetParameter(int32_t _id) const { + std::string type = getParameterType(_id); + const uint8_t* pointer = getParameterPointer(_id); + uint32_t dataSize = getParameterSize(_id); + if (createType() != type) { + return 0; } - // First get type: - char* type = reinterpret_cast(&m_data[startPos]); // Will be stop with \0 ... - if (strcmp(type, "int8") == 0) { - // OK - // move in the buffer pos - startPos += strlen(type) + 1; - // get real data size - int32_t dataSize = endPos - startPos; - if (dataSize < 0) { - JUS_ERROR("Get size < 0 : " << dataSize); - } else if (dataSize < 0) { - // nothing to do ... - } else { - if (dataSize != 1) { - JUS_ERROR("Get size > 1 : " << dataSize << " ==> limit 1"); - dataSize = 1; - } - // Allocate data - memcpy(&out, &m_data[startPos], dataSize); - } - } else { - //wrong type ... - JUS_ERROR("Can not convert '" << type << "' into 'string'"); - } - return out; + const int32_t* pointer2 = reinterpret_cast(pointer); + return *pointer2; } void jus::Buffer::addError(const std::string& _value, const std::string& _comment) { - addParameter(); addParameter(_value); addParameter(_comment); } -std::string jus::Buffer::getCall() { +std::string jus::Buffer::getCall() const { std::string out; switch(getType()) { case jus::Buffer::typeMessage::call: @@ -411,4 +512,96 @@ void jus::Buffer::setCall(std::string _value) { m_data.clear(); } addParameter(_value); -} \ No newline at end of file +} + +void jus::Buffer::prepare() { + m_header.numberOfParameter = m_paramOffset.size(); + m_header.lenght = sizeof(headerBin) - sizeof(uint32_t); + m_header.lenght += m_paramOffset.size() * sizeof(uint16_t); // param list + m_header.lenght += m_data.size(); +} + +ejson::Object jus::Buffer::toJson() const { + ejson::Object out; + out.add("id", ejson::Number(getTransactionId())); + out.add("client-id", ejson::Number(getClientId())); + uint16_t partId = getPartId(); + bool partFinish = getPartFinish(); + if ( partId != 0 + || partFinish == false) { + out.add("part", ejson::Number(partId)); + if (partFinish == true) { + out.add("finish", ejson::Boolean(partFinish)); + } + } + if (getType() == jus::Buffer::typeMessage::call) { + out.add("call", ejson::String(getCall())); + ejson::Array listParam; + out.add("param", listParam); + for (int32_t iii=0; iii() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType() == type) { + param = convertBinaryToJson(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + //param = convertBinaryToJson>(dataPointer, dataLenght); + } else if (createType>() == type) { + param = convertBinaryToJson>(dataPointer, dataLenght); + } else { + JUS_ERROR("Unknow param ==> can not convert ..."); + } + listParam.add(param); + } + } else if (getType() == jus::Buffer::typeMessage::answer) { + + } else if (getType() == jus::Buffer::typeMessage::event) { + JUS_ERROR(" NOT managed ..."); + } else { + JUS_ERROR("Unknow TYPE ..."); + } + return out; +} diff --git a/jus/Buffer.h b/jus/Buffer.h index 49f0aa7..f110320 100644 --- a/jus/Buffer.h +++ b/jus/Buffer.h @@ -5,9 +5,11 @@ */ #pragma once #include +#include namespace jus { //U32 message lenght + #pragma pack(push,1) struct headerBin { uint32_t lenght; uint16_t versionProtocol; // protocol Version (might be 1) @@ -15,15 +17,9 @@ namespace jus { uint32_t clientID; // same as sevice ID int16_t partID; // if < 0 the partId ifs the last (start at 0 if multiple or 0x8000 if single message) uint16_t typeMessage; //TypeMessgae (1:call, 2:Answer, 4:event) - void clear() { - lenght = 0; - versionProtocol = 1; - transactionID = 1; - clientID = 0; - partID = 0x8000; - typeMessage = 1; - } + uint16_t numberOfParameter; //TypeMessgae (1:call, 2:Answer, 4:event) }; + #pragma pack(pop) /* // not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0 ====================== @@ -114,29 +110,29 @@ namespace jus { void composeWith(const std::vector& _buffer); std::string generateHumanString(); void clear(); - uint16_t getProtocalVersion(); + uint16_t getProtocalVersion() const; void setProtocolVersion(uint16_t _value); - uint32_t getTransactionId(); + uint32_t getTransactionId() const; void setTransactionId(uint32_t _value); - uint32_t getClientId();// this is the same as serviceId + uint32_t getClientId() const;// this is the same as serviceId void setClientId(uint32_t _value); - uint32_t getServiceId() { + uint32_t getServiceId() const { return getClientId(); } void setServiceId(uint32_t _value) { setClientId(_value); } // note limited 15 bits - uint16_t getPartId(); + uint16_t getPartId() const; void setPartId(uint16_t _value); - bool getPartFinish(); + bool getPartFinish() const; void setPartFinish(bool _value); enum class typeMessage { call = 0x0001, answer = 0x0002, event = 0x0004, }; - enum typeMessage getType(); + enum typeMessage getType() const; void setType(enum typeMessage _value); // =============================================== @@ -144,18 +140,24 @@ namespace jus { // =============================================== private: template - JUS_TYPE_DATA internalGetParameter(int32_t _id); + JUS_TYPE_DATA internalGetParameter(int32_t _id) const; + std::string internalGetParameterType(int32_t _id) const; + const uint8_t* internalGetParameterPointer(int32_t _id) const; + uint32_t internalGetParameterSize(int32_t _id) const; public: - std::string getCall(); + std::string getCall() const; void setCall(std::string _value); - uint16_t getNumberParameter(); + uint16_t getNumberParameter() const; + std::string getParameterType(int32_t _id) const; + const uint8_t* getParameterPointer(int32_t _id) const; + uint32_t getParameterSize(int32_t _id) const; template void addParameter(const JUS_TYPE_DATA& _value); void addParameter(); template - JUS_TYPE_DATA getParameter(int32_t _id) { + JUS_TYPE_DATA getParameter(int32_t _id) const { return internalGetParameter(_id+1); } @@ -169,7 +171,14 @@ namespace jus { addParameter(_value); } void addError(const std::string& _value, const std::string& _comment); + + + void prepare(); + ejson::Object toJson() const; }; - std::ostream& operator <<(std::ostream& _os, const std::vector& _value); + std::ostream& operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value); + + template + ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size); } diff --git a/jus/BufferConvertBinaryToJson.cpp b/jus/BufferConvertBinaryToJson.cpp new file mode 100644 index 0000000..f5daa88 --- /dev/null +++ b/jus/BufferConvertBinaryToJson.cpp @@ -0,0 +1,106 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include +#include +#include + + + + +namespace jus { + // ---------------------------------------------------------------------------------------------------- + + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const bool* value = reinterpret_cast(_data); + return ejson::Boolean(*value); + } + template<> ejson::Value convertBinaryToJson>(const uint8_t* _data, uint32_t _size) { + const bool* value = reinterpret_cast(_data); + ejson::Array out; + for (size_t iii=0; iii<_size; ++iii) { + out.add(ejson::Boolean(value[iii])); + } + return out; + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const float* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const double* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const int64_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const int32_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const int16_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const int8_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const uint64_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const uint32_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const uint16_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + const uint8_t* value = reinterpret_cast(_data); + return ejson::Number(*value); + } + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + std::string val; + val.resize(_size, '\0'); + memcpy(&val[0], _data, _size); + return ejson::String(val); + } + template<> ejson::Value convertBinaryToJson>(const uint8_t* _data, uint32_t _size) { + /* + Little hard ... TODO : ... + const bool* value = reinterpret_cast(_data); + ejson::Array out; + for (size_t iii=0; iii<_size; ++iii) { + out.add(ejson::Boolean(value[iii])); + } + return out; + */ + ejson::Array out; + return out; + } + /* + template<> ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size) { + ejson::Object out; + out.add("type", ejson::String("file")); + out.add("mine-type", ejson::String(_value.getMineType())); + out.add("size", ejson::Number(_value.getData().size())); + if (_value.getData().size() != 0) { + _asyncAction.push_back(SenderJusFile(_value, _paramId)); + } + return out; + } + */ + + // ---------------------------------------------------------------------------------------------------- + +} + + + diff --git a/jus/Client.cpp b/jus/Client.cpp index 624d24d..c8bfcc6 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -279,7 +279,6 @@ class SendAsyncBinary { obj.setTransactionId(m_transactionId); obj.setPartId(m_partId); obj.setPartFinish(true); - JUS_DEBUG("Send BINARY '" << obj.generateHumanString() << "'"); _interface->writeBinary(obj); return true; } @@ -310,7 +309,6 @@ jus::FutureBase jus::Client::callBinary(uint64_t _transactionId, } else { _obj.setPartFinish(true); } - JUS_DEBUG("Send Binary '" << _obj.generateHumanString() << "'"); m_interfaceClient.writeBinary(_obj); if (_async.size() != 0) { diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index e3e6550..c443429 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -98,7 +98,6 @@ void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::s answer.setType(jus::Buffer::typeMessage::answer); answer.setTransactionId(_clientTransactionId); answer.addError(protocolError, _errorHelp); - JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.writeBinary(answer); } else if (m_interfaceMode == jus::connectionMode::modeXml) { JUS_ERROR("TODO ... "); @@ -107,19 +106,19 @@ void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::s } } -void jus::GateWayClient::onClientDataRaw(const jus::Buffer& _value) { - -} - -void jus::GateWayClient::onClientData(std::string _value) { - JUS_DEBUG("On data: " << _value); - ejson::Object data(_value); - uint64_t transactionId = data["id"].toNumber().getU64(); +void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { + uint32_t transactionId = _value.getTransactionId(); if (transactionId == 0) { JUS_ERROR("Protocol error ==>missing id"); answerProtocolError(transactionId, "missing parameter: 'id'"); return; } + if (_value.getType() != jus::Buffer::typeMessage::call) { + JUS_ERROR("Protocol error ==>missing 'call'"); + answerProtocolError(transactionId, "missing parameter: 'call' / wrong type 'call'"); + return; + } + std::string callFunction = _value.getCall(); switch (m_state) { case jus::GateWayClient::state::disconnect: case jus::GateWayClient::state::unconnect: @@ -134,21 +133,20 @@ void jus::GateWayClient::onClientData(std::string _value) { answerProtocolError(transactionId, "Gateway internal error 2"); return; } - std::string call = data["call"].toString().get(); - if (call == "setMode") { - std::string mode = data["param"].toArray()[0].toString().get(); + if (callFunction == "setMode") { + 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); - answerValue(transactionId, true); } 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); - answerValue(transactionId, true); } else if (mode == "XML") { JUS_WARNING("[" << m_uid << "] Change mode in: XML"); //m_interfaceMode = jus::connectionMode::modeXml; @@ -157,26 +155,303 @@ void jus::GateWayClient::onClientData(std::string _value) { answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]"); } return; - } else if (call == "connectToUser") { - m_userConnectionName = data["param"].toArray()[0].toString().get(); + } else if (callFunction == "connectToUser") { + m_userConnectionName = _value.getParameter(0); 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 { - ejson::Object linkService; - linkService.add("call", ejson::String("_new")); - linkService.add("id", ejson::Number(m_transactionLocalId++)); - ejson::Array params; - params.add(ejson::String(m_userConnectionName)); - params.add(ejson::String("**Gateway**")); - params.add(ejson::Array()); - linkService.add("param", params); - m_userService->SendData(m_uid2, linkService); + 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 = _value.getParameter(0); + std::string clientTocken = _value.getParameter(1); + 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 = _value.getParameter(0); + 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: + { + uint32_t serviceId = _value.getServiceId(); + 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()); + 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 = _value.getParameter(0); + // 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: the service we want to unconnect ... + int64_t localServiceID = _value.getParameter(0)-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; + } + // decrease service ID ... + serviceId -= 1; + if (serviceId >= m_listConnectedService.size()) { + answerError(transactionId, "NOT-CONNECTED-SERVICE"); + return; + } else { + if (m_listConnectedService[serviceId] == nullptr) { + // TODO ... + JUS_ERROR("TODO : Manage this case ..."); + return; + } + bool finish = _value.getPartFinish(); + uint16_t partId = _value.getPartId(); + if (partId != 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 ... + _value.setTransactionId(itCall.second.getTransactionId()); + m_listConnectedService[serviceId]->SendData(m_uid, _value); + return; + } + } + JUS_ERROR("Can not transfer part of a message ..."); + return; + } + callActionForward(m_listConnectedService[serviceId], + _value, + [=](jus::FutureBase _ret) { + // TODO : Check if it is a JSON or binary ... + ejson::Object tmpp = _ret.getRaw(); + 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()); + if (tmpp.valueExist("part") == true) { + // multiple send element ... + if (tmpp.valueExist("finish") == true) { + return tmpp["finish"].toBoolean().get(); + } + return false; + } + return true; + }); + } + } + } +} + +void jus::GateWayClient::onClientData(std::string _value) { + JUS_DEBUG("On data: " << _value); + 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); } @@ -189,7 +464,6 @@ void jus::GateWayClient::onClientData(std::string _value) { } case jus::GateWayClient::state::userIdentify: { - std::string callFunction = data["call"].toString().get(); m_clientServices.clear(); m_clientgroups.clear(); m_clientName.clear(); @@ -281,24 +555,13 @@ void jus::GateWayClient::onClientData(std::string _value) { if ( numService.exist() == false || numService.getU64() == 0) { // This is 2 default service for the cient interface that manage the authorisation of view: - std::string callFunction = data["call"].toString().get(); - ejson::Object answer; - answer.add("id", data["id"]); if (callFunction == "getServiceCount") { - answer.add("return", ejson::Number(m_clientServices.size())); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + answerValue(transactionId, m_clientServices.size()); return; } if (callFunction == "getServiceList") { - ejson::Array listService; - for (auto &it : m_clientServices) { - listService.add(ejson::String(it)); - } + answerValue(transactionId, m_clientServices); //listService.add(ejson::String("ServiceManager/v0.1.0")); - answer.add("return", listService); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); return; } if (callFunction == "link") { @@ -320,38 +583,26 @@ void jus::GateWayClient::onClientData(std::string _value) { if (it == m_listConnectedService.end()) { // check if service is connectable ... if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) { - answer.add("error", ejson::String("UN-AUTHORIZED-SERVICE")); - JUS_DEBUG("answer: (NOT authorized service) " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + answerError(transactionId, "UN-AUTHORIZED-SERVICE"); return; } ememory::SharedPtr srv = m_gatewayInterface->get(serviceName); if (srv != nullptr) { - ejson::Object linkService; - linkService.add("call", ejson::String("_new")); - linkService.add("id", ejson::Number(m_transactionLocalId++)); - ejson::Array params; - params.add(ejson::String(m_userConnectionName)); - params.add(ejson::String(m_clientName)); - // TODO ==> remove events ... - std::vector asyncAction; - params.add(convertToJson(asyncAction, 0, m_clientgroups)); - linkService.add("param", params); - if (asyncAction.size() != 0) { - JUS_ERROR("Missing send async messages"); + 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; } - srv->SendData(m_uid, linkService); m_listConnectedService.push_back(srv); - answer.add("return", ejson::Number(m_listConnectedService.size())); - } else { - answer.add("error", ejson::String("CAN-NOT-CONNECT-SERVICE")); + answerValue(transactionId, m_listConnectedService.size()); + return; } - } else { - // TODO : Service already connected; - answer.add("return", ejson::Boolean(false)); + answerError(transactionId, "CAN-NOT-CONNECT-SERVICE"); + return; } - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + answerError(transactionId, "SERVICE-ALREADY-CONNECTED");; return; } if (callFunction == "unlink") { @@ -359,27 +610,22 @@ void jus::GateWayClient::onClientData(std::string _value) { int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1; // Check if service already link: if (localServiceID >= m_listConnectedService.size()) { - answer.add("error", ejson::String("NOT-CONNECTED-SERVICE")); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + 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; } - ejson::Object linkService; - linkService.add("call", ejson::String("_delete")); - linkService.add("id", ejson::Number(m_transactionLocalId++)); - ejson::Array params; - linkService.add("param", params); - m_listConnectedService[localServiceID]->SendData(m_uid, linkService); m_listConnectedService[localServiceID] = nullptr; - answer.add("return", ejson::Boolean(true)); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + answerValue(transactionId, true); return; } JUS_ERROR("Function does not exist ... '" << callFunction << "'"); - answer.add("error", ejson::String("CALL-UNEXISTING")); - JUS_DEBUG("answer: " << answer.generateHumanString()); - m_interfaceClient.write(answer.generateMachineString()); + answerError(transactionId, "CALL-UNEXISTING"); return; } @@ -476,11 +722,53 @@ jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, return ret; } +jus::FutureBase jus::GateWayClient::callBinary(uint64_t _callerId, + ememory::SharedPtr _srv, + uint64_t _clientTransactionId, + uint64_t _transactionId, + jus::Buffer& _obj, + jus::FutureData::ObserverFinish _callback) { + JUS_VERBOSE("Send BINARY [START] "); + if (_srv == nullptr) { + // TODO : Change this ... + jus::Buffer obj; + obj.setTransactionId(_transactionId); + obj.setClientId(_callerId); + obj.setType(jus::Buffer::typeMessage::answer); + obj.addError("NOT-CONNECTED", "Client interface not connected (no TCP)"); + return jus::FutureBase(_transactionId, true, obj, _callback); + } + jus::FutureBase tmpFuture(_transactionId, _callback); + { + std::unique_lock lock(m_mutex); + m_pendingCall.push_back(std::make_pair(_clientTransactionId, tmpFuture)); + } + _srv->SendData(_callerId, _obj); + JUS_VERBOSE("Send BINARY [STOP]"); + return tmpFuture; +} + +jus::FutureBase jus::GateWayClient::callActionForward(ememory::SharedPtr _srv, + jus::Buffer& _Buffer, + jus::FutureData::ObserverFinish _callback) { + uint64_t id = getId(); + uint64_t clientTransactionId = _Buffer.getTransactionId(); + jus::FutureBase ret = callBinary(m_uid, _srv, clientTransactionId, id, _Buffer, _callback); + ret.setSynchronous(); + return ret; +} + + uint64_t jus::GateWayClient::getId() { return m_transactionLocalId++; } -jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::SharedPtr _srv, uint64_t _clientTransactionId, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { +jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, + ememory::SharedPtr _srv, + uint64_t _clientTransactionId, + uint64_t _transactionId, + const ejson::Object& _obj, + jus::FutureData::ObserverFinish _callback) { JUS_VERBOSE("Send JSON [START] "); if (_srv == nullptr) { ejson::Object obj; @@ -500,6 +788,8 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::Shared + + void jus::GateWayClient::returnMessage(ejson::Object _data) { jus::FutureBase future; uint64_t tid = _data["id"].toNumber().get(); diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 3e839ab..1905a4e 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -49,7 +49,7 @@ namespace jus { virtual ~GateWayClient(); void start(uint64_t _uid, uint64_t _uid2); void stop(); - void onClientDataRaw(const jus::Buffer& _value); + void onClientDataRaw(jus::Buffer& _value); void onClientData(std::string _value); void returnMessage(ejson::Object _data); bool checkId(uint64_t _id) const { @@ -64,6 +64,12 @@ namespace jus { 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 callBinary(uint64_t _callerId, + ememory::SharedPtr _srv, + uint64_t _clientTransactionId, + uint64_t _transactionId, + jus::Buffer& _obj, + jus::FutureData::ObserverFinish _callback=nullptr); uint64_t getId(); public: template @@ -125,6 +131,9 @@ namespace jus { 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); }; } diff --git a/jus/GateWayService.cpp b/jus/GateWayService.cpp index 4edba76..a33735c 100644 --- a/jus/GateWayService.cpp +++ b/jus/GateWayService.cpp @@ -11,7 +11,8 @@ jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) : m_gatewayInterface(_gatewayInterface), - m_interfaceClient(std::move(_connection)) { + m_interfaceClient(std::move(_connection)), + m_interfaceMode(jus::connectionMode::modeJson) { JUS_INFO("-----------------"); JUS_INFO("-- NEW Service --"); JUS_INFO("-----------------"); @@ -43,6 +44,22 @@ void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) JUS_DEBUG("Send Service: " << _data.generateHumanString()); m_interfaceClient.write(_data.generateMachineString()); } +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 ... "); + ejson::Object obj = _data.toJson(); + JUS_DEBUG("Send Service: " << obj.generateHumanString()); + m_interfaceClient.write(obj.generateMachineString()); + } else if (m_interfaceMode == jus::connectionMode::modeXml) { + JUS_ERROR("NOT manage transcriptioon binary to XML ... "); + } else if (m_interfaceMode == 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); diff --git a/jus/GateWayService.h b/jus/GateWayService.h index ea2afc1..38af4f7 100644 --- a/jus/GateWayService.h +++ b/jus/GateWayService.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace jus { class GateWay; @@ -17,6 +18,7 @@ namespace jus { jus::GateWay* m_gatewayInterface; jus::TcpString m_interfaceClient; std::string m_name; + enum jus::connectionMode m_interfaceMode; public: esignal::Signal signalIsConnected; public: @@ -27,6 +29,7 @@ namespace jus { void onServiceData(std::string _value); public: void SendData(uint64_t _userSessionId, ejson::Object _data); + void SendData(uint64_t _userSessionId, jus::Buffer& _data); const std::string& getName() { return m_name; } diff --git a/jus/ParamType.cpp b/jus/ParamType.cpp index f93e5af..fa300f2 100644 --- a/jus/ParamType.cpp +++ b/jus/ParamType.cpp @@ -22,6 +22,12 @@ bool jus::ParamType::operator == (const ParamType& _obj) const { return m_typeName == _obj.m_typeName; } +bool jus::ParamType::operator == (const std::string& _value) const { + return _value == m_typeName; +} +bool jus::ParamType::operator != (const std::string& _value) const { + return _value != m_typeName; +} #define generate_basic_type(_type, _name) \ namespace jus { \ diff --git a/jus/ParamType.h b/jus/ParamType.h index f88b626..e59208f 100644 --- a/jus/ParamType.h +++ b/jus/ParamType.h @@ -4,6 +4,9 @@ * @license APACHE v2.0 (see license file) */ #pragma once + +#include + namespace jus { class ParamType { protected: @@ -12,6 +15,8 @@ namespace jus { ParamType(const char* _name = ""); const char* getName() const; bool operator == (const ParamType& _obj) const; + bool operator == (const std::string& _value) const; + bool operator != (const std::string& _value) const; }; diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index 9b84af8..7a267c7 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -55,7 +55,7 @@ void jus::TcpString::threadCallback() { } } else if (m_observerRawElement != nullptr) { jus::Buffer data = std::move(readRaw()); - m_observerRawElement(std::move(data)); + m_observerRawElement(data); } } m_threadRunning = false; @@ -134,7 +134,9 @@ int32_t jus::TcpString::write(const std::string& _data) { m_connection.write(&size, 4); return m_connection.write(_data.c_str(), _data.size()); } -int32_t jus::TcpString::writeBinary(const jus::Buffer& _data) { +int32_t jus::TcpString::writeBinary(jus::Buffer& _data) { + _data.prepare(); + JUS_DEBUG("Send BINARY '" << _data.generateHumanString() << "'"); if (m_threadRunning == false) { return -2; } @@ -144,9 +146,11 @@ int32_t jus::TcpString::writeBinary(const jus::Buffer& _data) { } */ //uint32_t size = _data.size(); + const uint8_t* data = nullptr; + uint32_t dataSize = 0; m_lastSend = std::chrono::steady_clock::now(); - const uint8_t* data = _data.getHeader(); - uint32_t dataSize = _data.getHeaderSize(); + data = _data.getHeader(); + dataSize = _data.getHeaderSize(); m_connection.write(data, dataSize); data = _data.getParam(); dataSize = _data.getParamSize(); diff --git a/jus/TcpString.h b/jus/TcpString.h index cab4967..46c3652 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -21,7 +21,7 @@ namespace jus { 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 ObserverRaw = std::function; //!< Define an Observer: function pointer Observer m_observerElement; ObserverRaw m_observerRawElement; /** @@ -40,9 +40,9 @@ namespace jus { m_observerElement = nullptr; } template - void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(const jus::Buffer&)) { - m_observerRawElement = [=](const jus::Buffer& _value){ - (*_class.*_func)(std::move(_value)); + void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) { + m_observerRawElement = [=](jus::Buffer& _value){ + (*_class.*_func)(_value); }; } void connectCleanRaw() { @@ -58,7 +58,7 @@ namespace jus { bool isActive() const; void setInterfaceName(const std::string& _name); int32_t write(const std::string& _data); - int32_t writeBinary(const jus::Buffer& _data); + int32_t writeBinary(jus::Buffer& _data); std::string asyncRead(); private: std::string read(); diff --git a/lutin_jus.py b/lutin_jus.py index b7e6cd4..bf73333 100644 --- a/lutin_jus.py +++ b/lutin_jus.py @@ -39,6 +39,7 @@ def create(target, module_name): 'jus/Future.cpp', 'jus/File.cpp', 'jus/Buffer.cpp', + 'jus/BufferConvertBinaryToJson.cpp', 'jus/ParamType.cpp', 'jus/Client.cpp', 'jus/GateWay.cpp',