diff --git a/jus/Buffer.cpp b/jus/Buffer.cpp index 23de799..b4dc224 100644 --- a/jus/Buffer.cpp +++ b/jus/Buffer.cpp @@ -42,9 +42,9 @@ jus::Buffer::Buffer() { clear(); } -void jus::Buffer::composeWith(const std::vector& _buffer) { +void jus::Buffer::internalComposeWith(const uint8_t* _buffer, uint32_t _lenght) { clear(); - m_header.lenght = _buffer.size(); + m_header.lenght = _lenght; 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); @@ -52,7 +52,7 @@ void jus::Buffer::composeWith(const std::vector& _buffer) { 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); + m_data.resize(_lenght - offset); memcpy(&m_data[0], &_buffer[offset], m_data.size()); } else { // TODO : check size ... @@ -60,6 +60,14 @@ void jus::Buffer::composeWith(const std::vector& _buffer) { JUS_INFO("Get binary messages " << generateHumanString()); } +void jus::Buffer::composeWith(const std::vector& _buffer) { + internalComposeWith(&_buffer[0], _buffer.size()); +} +void jus::Buffer::composeWith(const std::string& _buffer) { + internalComposeWith(reinterpret_cast(&_buffer[0]), _buffer.size()); +} + + void jus::Buffer::clear() { JUS_WARNING("clear buffer"); m_data.clear(); @@ -85,13 +93,14 @@ std::string jus::Buffer::generateHumanString() { switch (type) { case jus::Buffer::typeMessage::call: out += " nbParam=" + etk::to_string(getNumberParameter()); + out += " call='" + getCall() + "'"; break; case jus::Buffer::typeMessage::answer: - if (getNumberParameter() == 1) { + if (m_paramOffset.size() == 1) { out += " mode=Value"; - } else if (getNumberParameter() == 2) { + } else if (m_paramOffset.size() == 2) { out += " mode=Error"; - } else if (getNumberParameter() == 3) { + } else if (m_paramOffset.size() == 3) { out += " mode=Value+Error"; } else { out += " mode=???"; @@ -228,6 +237,7 @@ uint32_t jus::Buffer::internalGetParameterSize(int32_t _id) const { startPos += strlen(type) + 1; // get real data size out = endPos - startPos; + out --; if (out < 0) { JUS_ERROR("Get size < 0 : " << out); out = 0; @@ -264,6 +274,41 @@ void jus::Buffer::addParameter(const std::string& _value) { memcpy(&m_data[currentOffset], &_value[0], _value.size()); } template<> +void jus::Buffer::addParameter>(const std::vector& _value) { + int32_t currentOffset = m_data.size(); + m_paramOffset.push_back(currentOffset); + m_data.push_back('v'); + m_data.push_back('e'); + m_data.push_back('c'); + m_data.push_back('t'); + m_data.push_back('o'); + m_data.push_back('r'); + m_data.push_back(':'); + m_data.push_back('s'); + m_data.push_back('t'); + m_data.push_back('r'); + m_data.push_back('i'); + m_data.push_back('n'); + m_data.push_back('g'); + m_data.push_back('\0'); + // count all datas: + uint32_t size = 0; + for (auto &it : _value) { + size+=it.size()+1; + } + uint16_t nb = _value.size(); + currentOffset = m_data.size(); + m_data.resize(m_data.size()+size+2); + memcpy(&m_data[currentOffset], &nb, sizeof(uint16_t)); + currentOffset += sizeof(uint16_t); + for (auto &it : _value) { + memcpy(&m_data[currentOffset], &it[0], it.size()); + currentOffset += it.size(); + m_data[currentOffset] = '\0'; + currentOffset++; + } +} +template<> void jus::Buffer::addParameter(const int8_t& _value) { int32_t currentOffset = m_data.size(); m_paramOffset.push_back(currentOffset); @@ -418,49 +463,39 @@ void jus::Buffer::addParameter(const bool& _value) { } } + +template<> +bool jus::Buffer::internalGetParameter(int32_t _id) const { + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); + if (createType() != type) { + return 0; + } + const char* pointer2 = reinterpret_cast(pointer); + if (*pointer2 == 'T') { + return true; + } + return false; +} + template<> 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()); - 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 ... - if (strcmp(type, "string") == 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 { - // Allocate data - out.resize(dataSize, ' '); - memcpy(&out[0], &m_data[startPos], dataSize); - } - } else { - //wrong type ... - JUS_ERROR("Can not convert '" << type << "' into 'string'"); - } - + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); + out.resize(dataSize, 0); + memcpy(&out[0], pointer, out.size()); return out; } template<> 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); + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); if (createType() != type) { return 0; } @@ -468,11 +503,23 @@ int8_t jus::Buffer::internalGetParameter(int32_t _id) const { return *pointer2; } +template<> +int16_t jus::Buffer::internalGetParameter(int32_t _id) const { + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); + if (createType() != type) { + return 0; + } + const int16_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); + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); if (createType() != type) { return 0; } @@ -480,6 +527,18 @@ int32_t jus::Buffer::internalGetParameter(int32_t _id) const { return *pointer2; } +template<> +int64_t jus::Buffer::internalGetParameter(int32_t _id) const { + std::string type = internalGetParameterType(_id); + const uint8_t* pointer = internalGetParameterPointer(_id); + uint32_t dataSize = internalGetParameterSize(_id); + if (createType() != type) { + return 0; + } + const int64_t* pointer2 = reinterpret_cast(pointer); + return *pointer2; +} + void jus::Buffer::addError(const std::string& _value, const std::string& _comment) { addParameter(_value); diff --git a/jus/Buffer.h b/jus/Buffer.h index f110320..b21a84b 100644 --- a/jus/Buffer.h +++ b/jus/Buffer.h @@ -105,9 +105,12 @@ namespace jus { uint32_t getDataSize() const { return m_data.size(); } + private: + void internalComposeWith(const uint8_t* _buffer, uint32_t _lenght); public: Buffer(); void composeWith(const std::vector& _buffer); + void composeWith(const std::string& _buffer); std::string generateHumanString(); void clear(); uint16_t getProtocalVersion() const; @@ -170,6 +173,11 @@ namespace jus { void addAnswer(const JUS_TYPE_DATA& _value) { addParameter(_value); } + // TODO : Do it better check error ... ==> can be good ... + template + JUS_TYPE_DATA getAnswer() const { + return internalGetParameter(0); + } void addError(const std::string& _value, const std::string& _comment); diff --git a/jus/Client.cpp b/jus/Client.cpp index c8bfcc6..a22b5c4 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -22,6 +22,69 @@ jus::Client::~Client() { } +void jus::Client::onClientDataRaw(jus::Buffer& _value) { + JUS_DEBUG("Get answer RAW : "/* << _value*/); + jus::FutureBase future; + uint64_t tid = _value.getTransactionId(); + if (tid == 0) { + JUS_ERROR("Get a Protocol error ... No ID ..."); + /* + if (obj["error"].toString().get() == "PROTOCOL-ERROR") { + JUS_ERROR("Get a Protocol error ..."); + std::unique_lock 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(_value); + 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; + } + } +} + void jus::Client::onClientData(std::string _value) { JUS_DEBUG("Get answer : " << _value); ejson::Object obj(_value); @@ -147,20 +210,30 @@ bool jus::Client::connect(const std::string& _remoteUserToConnect){ m_interfaceClient.setInterface(std::move(connection)); m_interfaceClient.connect(); // Force mode binary: + JUS_WARNING("Request change in mode Binary"); 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); JUS_INFO("Connection jump in BINARY ..."); } else { // stay in JSON } - jus::Future ret = call("connectToUser", _remoteUserToConnect, "jus-client"); + JUS_WARNING("Request connect user " << _remoteUserToConnect); + jus::Future ret = call("connectToUser", _remoteUserToConnect, "jus-client"); ret.wait(); if (ret.hasError() == true) { JUS_WARNING("Can not connect to user named: '" << _remoteUserToConnect << "' ==> return error"); return false; } + if (ret.get() == true) { + JUS_WARNING(" ==> accepted connection"); + } else { + JUS_WARNING(" ==> Refuse connection"); + } return ret.get(); } @@ -316,4 +389,8 @@ jus::FutureBase jus::Client::callBinary(uint64_t _transactionId, } JUS_VERBOSE("Send Binary [STOP]"); return tmpFuture; -} \ No newline at end of file +} + + + + diff --git a/jus/Client.h b/jus/Client.h index 623b845..70cda8a 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -47,6 +47,7 @@ namespace jus { //client1.authentificate("coucou"); private: void onClientData(std::string _value); + void onClientDataRaw(jus::Buffer& _value); std::string asyncRead(); jus::FutureBase callJson(uint64_t _transactionId, ejson::Object _obj, diff --git a/jus/Future.cpp b/jus/Future.cpp index 8078714..c786104 100644 --- a/jus/Future.cpp +++ b/jus/Future.cpp @@ -15,32 +15,42 @@ namespace jus { if (m_data == nullptr) { return false; } - ejson::Value val = m_data->m_returnData["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return false; + // JSON mode + if (m_data->m_mode == false) { + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return false; + } + if (val.isBoolean() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); + return false; + } + return val.toBoolean().get(); } - if (val.isBoolean() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); - return false; - } - return val.toBoolean().get(); + // binary mode: + return m_data->m_returnDataBinary.getAnswer(); } template<> int64_t jus::Future::get() { if (m_data == nullptr) { return 0; } - ejson::Value val = m_data->m_returnData["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return 0; + // JSON mode + if (m_data->m_mode == false) { + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return 0; + } + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); + return 0; + } + return int64_t(val.toNumber().get()); } - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); - return 0; - } - return int64_t(val.toNumber().get()); + // binary mode: + return m_data->m_returnDataBinary.getAnswer(); } template<> int32_t jus::Future::get() { diff --git a/jus/FutureBase.cpp b/jus/FutureBase.cpp index 70f47fd..bf2f82c 100644 --- a/jus/FutureBase.cpp +++ b/jus/FutureBase.cpp @@ -163,13 +163,12 @@ bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) { // finish is false ==> normal case ... } return false; - } - m_data->m_returnData = _returnValue; + }*/ + m_data->m_returnDataBinary = _returnValue; m_data->m_isFinished = true; if (m_data->m_callbackFinish != nullptr) { return m_data->m_callbackFinish(*this); } - */ return true; } void jus::FutureBase::setSynchronous() { diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index 7a267c7..79ca191 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -39,7 +39,7 @@ 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: @@ -47,15 +47,29 @@ void jus::TcpString::threadCallback() { && 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_VERBOSE("Receive data: '" << data << "'"); + JUS_PRINT("Receive data: '" << data << "'"); if (data.size() != 0) { m_lastReceive = std::chrono::steady_clock::now(); - m_observerElement(std::move(data)); + 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::Buffer data = std::move(readRaw()); + JUS_PRINT("Call Raw ..."); + jus::Buffer data = readRaw(); + JUS_PRINT(" Call function ... 2"); m_observerRawElement(data); + JUS_PRINT(" Call function ... 2 (done)"); } } m_threadRunning = false; diff --git a/jus/debug.h b/jus/debug.h index fa8ca1a..8d33302 100644 --- a/jus/debug.h +++ b/jus/debug.h @@ -13,6 +13,7 @@ namespace jus { #define JUS_BASE(info,data) ELOG_BASE(jus::getLogId(),info,data) +#define JUS_PRINT(data) JUS_BASE(-1, data) #define JUS_CRITICAL(data) JUS_BASE(1, data) #define JUS_ERROR(data) JUS_BASE(2, data) #define JUS_WARNING(data) JUS_BASE(3, data)