From 6d985f7d2f278ca753ad4f914a7e25fc428a40c7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 3 Jun 2016 23:45:01 +0200 Subject: [PATCH] [DEV] start to send data to the server --- database.json_picture | 29 +++++ jus/AbstractFunction.cpp | 105 ++++++++++++++---- jus/AbstractFunction.h | 185 +++++--------------------------- jus/AbstractFunctionTypeClass.h | 8 +- jus/Client.cpp | 55 +++++++++- jus/Client.h | 16 ++- jus/File.cpp | 12 ++- jus/File.h | 1 + jus/FutureBase.cpp | 7 +- jus/GateWayClient.cpp | 86 ++++++++++++--- jus/GateWayClient.h | 29 +++-- jus/Service.cpp | 2 + jus/ServiceRemote.cpp | 7 +- jus/ServiceRemote.h | 12 ++- jus/TcpString.h | 2 +- test/client/appl/main.cpp | 99 ++++++++--------- tools/picture/appl/main.cpp | 3 +- 17 files changed, 392 insertions(+), 266 deletions(-) create mode 100644 database.json_picture diff --git a/database.json_picture b/database.json_picture new file mode 100644 index 0000000..3eb92e9 --- /dev/null +++ b/database.json_picture @@ -0,0 +1,29 @@ +{ + "default-view": { }, + "right-group": [ "public" ], + "right-user": [ ], + "group-global": [ "photo", "drawing" ], + "groups": { + "photo": { + "right-herited": false, + "right-group": [ "famille" ], + "right-user": [ "camille#atria-soft.com" ], + "sub": [ "2015", "2016" ], + "files": [ 22641, 34695 ] + }, + "drawing": { + "right-herited": true, + "files": [ 33913, 262464 ] + }, + "2015": { + "right-herited": true, + "sub": [ ], + "files": [ 33913 ] + }, + "2016": { + "right-herited": true, + "sub": [ ], + "files": [ 33913, 262464 ] + } + } +} diff --git a/jus/AbstractFunction.cpp b/jus/AbstractFunction.cpp index 420016a..9b87842 100644 --- a/jus/AbstractFunction.cpp +++ b/jus/AbstractFunction.cpp @@ -5,6 +5,8 @@ */ #include #include +#include +#include namespace jus { template<> bool convertJsonTo(const ejson::Value& _value) { return _value.toBoolean().get(); @@ -62,61 +64,78 @@ namespace jus { out.setMineType(obj["mine-type"].toString().get()); out.preSetDataSize(obj["size"].toNumber().getU64()); //out.add("type", ejson::String("file")); - // TODO : Add extended datas ... + + uint64_t offset = 0; + for (auto it : obj["data"].toArray()) { + ejson::String valData = it.toString(); + if (valData.get().size() != 0) { + std::vector tmpData = ejson::base64::decode(valData.get()); + out.setData(offset, tmpData); + offset += tmpData.size(); + } + } return out; } - template<> ejson::Value convertToJson(const bool& _value) { + // ---------------------------------------------------------------------------------------------------- + + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const bool& _value) { return ejson::Boolean(_value); } - template<> ejson::Value convertToJson>(const std::vector& _value) { + template<> ejson::Value convertToJson>(std::vector& _asyncAction, int32_t _paramId, const std::vector& _value) { ejson::Array out; for (const auto &it : _value) { out.add(ejson::Boolean(it)); } return out; } - template<> ejson::Value convertToJson(const float& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const float& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const double& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const double& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const int64_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const int64_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const int32_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const int32_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const int16_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const int16_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const int8_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const int8_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const uint64_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const uint64_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const uint32_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const uint32_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const uint16_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const uint16_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const uint8_t& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const uint8_t& _value) { return ejson::Number(_value); } - template<> ejson::Value convertToJson(const std::string& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const std::string& _value) { return ejson::String(_value); } - template<> ejson::Value convertToJson>(const std::vector& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, char* const & _value) { + if (_value == nullptr) { + return ejson::String(); + } + return ejson::String(_value); + } + template<> ejson::Value convertToJson>(std::vector& _asyncAction, int32_t _paramId, const std::vector& _value) { ejson::Array out; for (auto &it : _value) { out.add(ejson::String(it)); } return out; } - template<> ejson::Value convertToJson(const jus::FileServer& _value) { + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const jus::FileServer& _value) { ejson::Array out; /* for (auto &it : _value) { @@ -125,15 +144,63 @@ namespace jus { */ return out; } - template<> ejson::Value convertToJson(const jus::File& _value) { + + class SenderJusFile { + private: + jus::File m_data; + uint64_t m_size; + uint64_t m_offset; + int32_t m_paramID; + public: + SenderJusFile(jus::File _data, int32_t _paramID) : + m_data(_data), + m_size(m_data.getData().size()), + m_offset(0), + m_paramID(_paramID) { + + } + ~SenderJusFile() { + + } + bool operator() (TcpString* _interface, const std::string& _service, uint64_t _transactionId, uint64_t _part) { + ejson::Object answer; + if (_service != "") { + answer.add("service", ejson::String(_service)); + } + answer.add("id", ejson::Number(_transactionId)); + answer.add("part", ejson::Number(_part)); + if (m_paramID >= 0) { + answer.add("param-id", ejson::Number(m_paramID)); + } + int32_t tmpSize = 1023; + if (m_size < 1023) { + tmpSize = m_size; + } + uint8_t tmpData[1023]; + 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()); + if (m_size <= 0) { + return true; + } + return false; + } + }; + template<> ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const jus::File& _value) { 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())); - // TODO : Add extended datas ... + if (_value.getData().size() != 0) { + _asyncAction.push_back(SenderJusFile(_value, _paramId)); + } return out; } + // ---------------------------------------------------------------------------------------------------- + template<> bool convertStringTo(const std::string& _value) { return etk::string_to_bool(_value); } @@ -199,7 +266,7 @@ ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _f obj.add("id", ejson::Number(_transactionId)); return obj; } -void jus::createParam(ejson::Object& _obj) { +void jus::createParam(std::vector& _asyncAction, int32_t _paramId, ejson::Object& _obj) { // Finish recursive parse ... } diff --git a/jus/AbstractFunction.h b/jus/AbstractFunction.h index f0b2f0f..df592e2 100644 --- a/jus/AbstractFunction.h +++ b/jus/AbstractFunction.h @@ -60,6 +60,9 @@ namespace jus { virtual std::string executeString(const std::vector& _params, void* _class=nullptr) = 0; }; + // define basic async call element ... + using ActionAsyncClient = std::function; + template JUS_TYPE convertStringTo(const std::string& _value); @@ -67,181 +70,51 @@ namespace jus { JUS_TYPE convertJsonTo(const ejson::Value& _value); template - ejson::Value convertToJson(const JUS_TYPE& _value); + ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const JUS_TYPE& _value); + //ejson::Value convertToJson(std::vector& _asyncAction, int32_t _paramId, const char* _value); ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service=""); - void createParam(ejson::Object& _obj); + void createParam(std::vector& _asyncAction, + int32_t _paramId, + ejson::Object& _obj); - template - void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::string& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const bool& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const int32_t& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const double& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const float& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args); - template - void createParam(ejson::Object& _obj, const jus::File& _param, _ARGS&&... _args); - - template - void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args) { + template + void createParam(std::vector& _asyncAction, + int32_t _paramId, + ejson::Object& _obj, + const JUS_TYPE& _param, + _ARGS&&... _args) { if (_obj.valueExist("param") == false) { _obj.add("param", ejson::Array()); } ejson::Array array = _obj["param"].toArray(); - if (_param == nullptr) { - array.add(ejson::String()); - } else { - array.add(ejson::String(_param)); - } - createParam(_obj, std::forward<_ARGS>(_args)...); + array.add(convertToJson(_asyncAction, _paramId, _param)); + _paramId++; + createParam(_asyncAction, _paramId, _obj, std::forward<_ARGS>(_args)...); } + // convert const char in std::string ... template - void createParam(ejson::Object& _obj, const std::string& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(ejson::String(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const bool& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(ejson::Boolean(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const int32_t& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(ejson::Number(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const double& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(ejson::Number(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const float& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(ejson::Number(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - ejson::Array array2; - for (auto& it : _param) { - array2.add(ejson::String(it)); - } - array.add(array2); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - ejson::Array array2; - for (const auto& it : _param) { - array2.add(ejson::Boolean(it)); - } - array.add(array2); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - ejson::Array array2; - for (auto& it : _param) { - array2.add(ejson::Number(it)); - } - array.add(array2); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - ejson::Array array2; - for (auto& it : _param) { - array2.add(ejson::Number(it)); - } - array.add(array2); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - ejson::Array array2; - for (auto& it : _param) { - array2.add(ejson::Number(it)); - } - array.add(array2); - createParam(_obj, std::forward<_ARGS>(_args)...); - } - template - void createParam(ejson::Object& _obj, const jus::File& _param, _ARGS&&... _args) { - if (_obj.valueExist("param") == false) { - _obj.add("param", ejson::Array()); - } - ejson::Array array = _obj["param"].toArray(); - array.add(convertToJson(_param)); - createParam(_obj, std::forward<_ARGS>(_args)...); + void createParam(std::vector& _asyncAction, + int32_t _paramId, + ejson::Object& _obj, + const char* _param, + _ARGS&&... _args) { + createParam(_asyncAction, _paramId, _obj, std::string(_param), std::forward<_ARGS>(_args)...); } + template - ejson::Object createCall(uint64_t _transactionId, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object createCall(std::vector& _asyncAction, uint64_t _transactionId, const std::string& _functionName, _ARGS&&... _args) { ejson::Object callElem = createBaseCall(_transactionId, _functionName); - createParam(callElem, std::forward<_ARGS>(_args)...); + createParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...); return callElem; } template - ejson::Object createCallService(uint64_t _transactionId, const std::string& _serviceName, const std::string& _functionName, _ARGS&&... _args) { + ejson::Object createCallService(std::vector& _asyncAction, uint64_t _transactionId, const std::string& _serviceName, const std::string& _functionName, _ARGS&&... _args) { ejson::Object callElem = createBaseCall(_transactionId, _functionName, _serviceName); - createParam(callElem, std::forward<_ARGS>(_args)...); + createParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...); return callElem; } ejson::Object createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params); diff --git a/jus/AbstractFunctionTypeClass.h b/jus/AbstractFunctionTypeClass.h index e7e61b7..d8f8171 100644 --- a/jus/AbstractFunctionTypeClass.h +++ b/jus/AbstractFunctionTypeClass.h @@ -23,19 +23,23 @@ namespace jus { JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { + 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((*_pointer.*_func)((convertJsonTo(_params[idParam++]))...)); + ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)((convertJsonTo(_params[idParam++]))...)); #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; - ejson::Value ret = convertToJson((*_pointer.*_func)(convertJsonTo(_params[idParam--])...)); + ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)(convertJsonTo(_params[idParam--])...)); #else #error Must be implemented ... ejson::Value ret = ejson::Null(); 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)); diff --git a/jus/Client.cpp b/jus/Client.cpp index f44d4d4..1131bf1 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -164,7 +164,53 @@ uint64_t jus::Client::getId() { return m_id++; } -jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { +class SendAsync { + private: + std::vector m_async; + uint64_t m_transactionId; + std::string m_service; + uint32_t m_partId; + public: + SendAsync(uint64_t _transactionId, const std::string& _service, const std::vector& _async) : + m_async(_async), + m_transactionId(_transactionId), + m_service(_service), + m_partId(1) { + + } + bool operator() (jus::TcpString* _interface){ + auto it = m_async.begin(); + while (it != m_async.end()) { + bool ret = (*it)(_interface, m_service, m_transactionId, m_partId); + if (ret == true) { + // Remove it ... + it = m_async.erase(it); + } else { + ++it; + } + m_partId++; + } + if (m_async.size() == 0) { + ejson::Object obj; + if (m_service != "") { + obj.add("service", ejson::String(m_service)); + } + 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()); + return true; + } + return false; + } +}; + +jus::FutureBase jus::Client::callJson(uint64_t _transactionId, + ejson::Object _obj, + const std::vector& _async, + jus::FutureData::ObserverFinish _callback, + const std::string& _service) { JUS_VERBOSE("Send JSON [START] "); if (m_interfaceClient.isActive() == false) { ejson::Object obj; @@ -177,8 +223,15 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Obje std::unique_lock lock(m_mutex); m_pendingCall.push_back(tmpFuture); } + if (_async.size() != 0) { + _obj.add("part", ejson::Number(0)); + } JUS_DEBUG("Send JSON '" << _obj.generateHumanString() << "'"); m_interfaceClient.write(_obj.generateMachineString()); + + if (_async.size() != 0) { + m_interfaceClient.addAsync(SendAsync(_transactionId, _service, _async)); + } JUS_VERBOSE("Send JSON [STOP]"); return tmpFuture; } diff --git a/jus/Client.h b/jus/Client.h index 9b530d5..49b2119 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -43,20 +43,26 @@ namespace jus { private: void onClientData(std::string _value); std::string asyncRead(); - jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); + jus::FutureBase callJson(uint64_t _transactionId, + ejson::Object _obj, + const std::vector& _async, + jus::FutureData::ObserverFinish _callback=nullptr, + const std::string& _service=""); public: uint64_t getId(); template jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) { uint64_t id = getId(); - ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); - return callJson(id, callElem); + std::vector asyncAction; + ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, asyncAction); } template jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { uint64_t id = getId(); - ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); - return callJson(id, callElem, _callback); + std::vector asyncAction; + ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, asyncAction, _callback); } private: void onPropertyChangeIp(); diff --git a/jus/File.cpp b/jus/File.cpp index 39acfb5..9f494c4 100644 --- a/jus/File.cpp +++ b/jus/File.cpp @@ -4,8 +4,11 @@ * @license APACHE v2.0 (see license file) */ #include +#include #include #include +#include +#include @@ -14,7 +17,14 @@ jus::File::File() { } jus::File::File(const std::string& _filename) { - + m_data = etk::FSNodeReadAllDataType(_filename); + std::string extention = std::string(_filename.begin()+_filename.size() -3, _filename.end()); + JUS_WARNING("send file: '" << _filename << "' with extention: '" << extention << "'"); + m_mineType = jus::getMineType(extention); +} + +void jus::File::storeIn(const std::string& _filename) const { + etk::FSNodeWriteAllDataType(_filename, m_data); } jus::File::File(const std::string& _mineType, std::vector _data): diff --git a/jus/File.h b/jus/File.h index e14c996..a7fdff5 100644 --- a/jus/File.h +++ b/jus/File.h @@ -15,6 +15,7 @@ namespace jus { File(); File(const std::string& _filename); File(const std::string& _mineType, std::vector _data); + void storeIn(const std::string& _filename) const; const std::string& getMineType() const { return m_mineType; } diff --git a/jus/FutureBase.cpp b/jus/FutureBase.cpp index f42037f..1cf4dcd 100644 --- a/jus/FutureBase.cpp +++ b/jus/FutureBase.cpp @@ -219,9 +219,10 @@ void jus::FutureCall::appendData(const ejson::Object& _callValue) { if (param.valueExist("data") == false) { param.add("data", ejson::Array()); } - // add data in the array - param["data"].toArray().add(_callValue["data"]); - + // 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; diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index 2c6e9ec..16b3c15 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -83,7 +83,7 @@ void jus::GateWayClient::returnBool(int32_t _transactionId, bool _value) { void jus::GateWayClient::onClientData(std::string _value) { JUS_DEBUG("On data: " << _value); ejson::Object data(_value); - int32_t transactionId = data["id"].toNumber().get(); + uint64_t transactionId = data["id"].toNumber().getU64(); if (transactionId == 0) { JUS_ERROR("Protocol error ==>missing id"); protocolError("missing parameter: 'id'"); @@ -274,7 +274,12 @@ void jus::GateWayClient::onClientData(std::string _value) { linkService.add("event", ejson::String("new")); linkService.add("user", ejson::String(m_userConnectionName)); linkService.add("client", ejson::String(m_clientName)); - linkService.add("groups", convertToJson(m_clientgroups)); + // TODO ==> remove events ... + std::vector asyncAction; + linkService.add("groups", convertToJson(asyncAction, 0, m_clientgroups)); + if (asyncAction.size() != 0) { + JUS_ERROR("Missing send async messages"); + } srv->SendData(m_uid, linkService); m_listConnectedService.push_back(srv); answer.add("return", ejson::Boolean(true)); @@ -351,7 +356,43 @@ void jus::GateWayClient::onClientData(std::string _value) { JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); } 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 (*it == 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)); + } + (*it)->SendData(m_uid, obj); + } + return; + } + } + JUS_ERROR("Can not transfer part of a message ..."); + return; + } + } callActionForward(m_uid, + transactionId, *it, data["call"].toString().get(), data["param"].toArray(), @@ -359,7 +400,7 @@ void jus::GateWayClient::onClientData(std::string _value) { 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(data["id"].toNumber().getU64()); + tmpp["id"].toNumber().set(transactionId); JUS_DEBUG("transmit=" << tmpp.generateMachineString()); m_interfaceClient.write(tmpp.generateMachineString()); if (tmpp.valueExist("part") == true) { @@ -370,16 +411,31 @@ void jus::GateWayClient::onClientData(std::string _value) { return false; } return true; - }); + }, + partTmp, + finish); } } } } -jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback) { +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); - jus::FutureBase ret = callJson(_callerId, _srv, id, callElem, _callback); + 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; } @@ -388,7 +444,7 @@ uint64_t jus::GateWayClient::getId() { return m_transactionLocalId++; } -jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::SharedPtr _srv, 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; @@ -399,7 +455,7 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::Shared jus::FutureBase tmpFuture(_transactionId, _callback); { std::unique_lock lock(m_mutex); - m_pendingCall.push_back(tmpFuture); + m_pendingCall.push_back(std::make_pair(_clientTransactionId, tmpFuture)); } _srv->SendData(_callerId, _obj); JUS_VERBOSE("Send JSON [STOP]"); @@ -416,10 +472,10 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) { JUS_ERROR("Get a Protocol error ..."); std::unique_lock lock(m_mutex); for (auto &it : m_pendingCall) { - if (it.isValid() == false) { + if (it.second.isValid() == false) { continue; } - it.setAnswer(_data); + it.second.setAnswer(_data); } m_pendingCall.clear(); } else { @@ -431,16 +487,16 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) { std::unique_lock lock(m_mutex); auto it = m_pendingCall.begin(); while (it != m_pendingCall.end()) { - if (it->isValid() == false) { + if (it->second.isValid() == false) { it = m_pendingCall.erase(it); continue; } - if (it->getTransactionId() != tid) { + if (it->second.getTransactionId() != tid) { ++it; continue; } // TODO : Do it better ... - future = *it; + future = it->second; break; } } @@ -453,11 +509,11 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) { std::unique_lock lock(m_mutex); auto it = m_pendingCall.begin(); while (it != m_pendingCall.end()) { - if (it->isValid() == false) { + if (it->second.isValid() == false) { it = m_pendingCall.erase(it); continue; } - if (it->getTransactionId() != tid) { + if (it->second.getTransactionId() != tid) { ++it; continue; } diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 667fea4..88609df 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -57,24 +57,39 @@ namespace jus { private: std::mutex m_mutex; - std::vector m_pendingCall; + std::vector> m_pendingCall; int32_t m_transactionLocalId; - jus::FutureBase callJson(uint64_t _callerId, ememory::SharedPtr _srv, 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); uint64_t getId(); public: template jus::FutureBase call(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, _ARGS&&... _args) { uint64_t id = getId(); - ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); - return callJson(_callerId, _srv, id, callElem); + std::vector asyncAction; + ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...); + if (asyncAction.size() != 0) { + JUS_ERROR("Missing send async messages"); + } + return callJson(_callerId, _srv, 0, id, callElem); } template jus::FutureBase callAction(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { uint64_t id = getId(); - ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); - return callJson(_callerId, _srv, id, callElem, _callback); + std::vector asyncAction; + ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...); + if (asyncAction.size() != 0) { + JUS_ERROR("Missing send async messages"); + } + return callJson(_callerId, _srv, 0, id, callElem, _callback); } - jus::FutureBase callActionForward(uint64_t _callerId, ememory::SharedPtr _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback); + jus::FutureBase 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); }; } diff --git a/jus/Service.cpp b/jus/Service.cpp index 0cf29a4..26efd78 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -43,8 +43,10 @@ void jus::Service::onClientData(std::string _value) { while (it != m_callMultiData.end()) { if ( it->getTransactionId() == tmpID && it->getClientId() == clientId) { + JUS_WARNING("Append data ... " << tmpID); it->appendData(request); if (it->isFinished() == true) { + JUS_WARNING("CALL Function ..."); callJson(tmpID, it->getRaw()); it = m_callMultiData.erase(it); } diff --git a/jus/ServiceRemote.cpp b/jus/ServiceRemote.cpp index 0fde772..c19a36c 100644 --- a/jus/ServiceRemote.cpp +++ b/jus/ServiceRemote.cpp @@ -28,7 +28,10 @@ uint64_t jus::ServiceRemote::getId() { return m_clientInterface->getId(); } -jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { - return m_clientInterface->callJson(_transactionId, _obj, _callback); +jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, + const ejson::Object& _obj, + const std::vector& _async, + jus::FutureData::ObserverFinish _callback) { + return m_clientInterface->callJson(_transactionId, _obj, _async, _callback, m_name); } diff --git a/jus/ServiceRemote.h b/jus/ServiceRemote.h index 6807f59..c6f77ee 100644 --- a/jus/ServiceRemote.h +++ b/jus/ServiceRemote.h @@ -25,20 +25,22 @@ namespace jus { ~ServiceRemote(); bool exist(); private: - jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); + jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, const std::vector& _async, jus::FutureData::ObserverFinish _callback=nullptr); uint64_t getId(); public: template jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) { uint64_t id = getId(); - ejson::Object callElem = jus::createCallService(id, m_name, _functionName, std::forward<_ARGS>(_args)...); - return callJson(id, callElem); + std::vector asyncActionToDo; + ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_name, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, asyncActionToDo); } template jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) { uint64_t id = getId(); - ejson::Object callElem = jus::createCallService(id, m_name, _functionName, std::forward<_ARGS>(_args)...); - return callJson(id, callElem, _callback); + std::vector asyncActionToDo; + ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_name, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem, asyncActionToDo, _callback); } }; } diff --git a/jus/TcpString.h b/jus/TcpString.h index 6a6d94b..3f733c8 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -56,7 +56,7 @@ namespace jus { return m_lastSend; } private: - using ActionAsync = std::function; + using ActionAsync = std::function; std::mutex m_threadAsyncMutex; std::thread* m_threadAsync; bool m_threadAsyncRunning; diff --git a/test/client/appl/main.cpp b/test/client/appl/main.cpp index f787bff..e65aca8 100644 --- a/test/client/appl/main.cpp +++ b/test/client/appl/main.cpp @@ -86,61 +86,63 @@ int main(int _argc, const char *_argv[]) { APPL_INFO("serviceTest1.mul = " << retCall); } */ - APPL_INFO(" ----------------------------------"); - APPL_INFO(" -- Get service system-user"); - APPL_INFO(" ----------------------------------"); - - jus::ServiceRemote remoteServiceUser = client1.getService("system-user"); - if (remoteServiceUser.exist() == true) { - jus::Future> retCall = remoteServiceUser.call("getGroups", "clientTest1#atria-soft.com"); - retCall.wait(); - APPL_INFO("system-user.getGroups() = " << retCall.get()); - jus::Future retDesc = remoteServiceUser.call("sys.getDescription"); - jus::Future retVersion = remoteServiceUser.call("sys.getVersion"); - jus::Future retType = remoteServiceUser.call("sys.getType"); - jus::Future> retExtention = remoteServiceUser.call("srv.getExtention"); - jus::Future> retMaintainer = remoteServiceUser.call("sys.getAuthors"); - retDesc.wait(); - retVersion.wait(); - retType.wait(); - retExtention.wait(); - retMaintainer.wait(); - APPL_INFO("Service: system-user"); - APPL_INFO(" version : " << retVersion.get()); - APPL_INFO(" type : " << retType.get()); - APPL_INFO(" Extention : " << retExtention.get().size()); - for (auto &it : retExtention.get()) { - APPL_INFO(" - " << it); - } - APPL_INFO(" maintainer: " << retMaintainer.get().size()); - for (auto &it : retMaintainer.get()) { - APPL_INFO(" - " << it); - } - APPL_INFO(" description:"); - APPL_INFO(" " << retDesc.get()); - APPL_INFO(" Function List:"); - jus::Future> retFuctions = remoteServiceUser.call("sys.getFunctions").wait(); - for (auto it : retFuctions.get()) { - std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); - jus::Future retFunctionPrototype = remoteServiceUser.call("sys.getFunctionPrototype", it); - jus::Future retFunctionHelp = remoteServiceUser.call("sys.getFunctionDescription", it); - retFunctionPrototype.wait(); - retFunctionHelp.wait(); - std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now(); - APPL_INFO(" - " << retFunctionPrototype.get()); - APPL_INFO(" " << retFunctionHelp.get()); - APPL_INFO(" IO1=" << int64_t(retFunctionPrototype.getTransmitionTime().count()/1000)/1000.0 << " ms"); - APPL_INFO(" IO2=" << int64_t(retFunctionHelp.getTransmitionTime().count()/1000)/1000.0 << " ms"); - APPL_INFO(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms"); + if (false) { + APPL_INFO(" ----------------------------------"); + APPL_INFO(" -- Get service system-user"); + APPL_INFO(" ----------------------------------"); + + jus::ServiceRemote remoteServiceUser = client1.getService("system-user"); + if (remoteServiceUser.exist() == true) { + jus::Future> retCall = remoteServiceUser.call("getGroups", "clientTest1#atria-soft.com"); + retCall.wait(); + APPL_INFO("system-user.getGroups() = " << retCall.get()); + jus::Future retDesc = remoteServiceUser.call("sys.getDescription"); + jus::Future retVersion = remoteServiceUser.call("sys.getVersion"); + jus::Future retType = remoteServiceUser.call("sys.getType"); + jus::Future> retExtention = remoteServiceUser.call("srv.getExtention"); + jus::Future> retMaintainer = remoteServiceUser.call("sys.getAuthors"); + retDesc.wait(); + retVersion.wait(); + retType.wait(); + retExtention.wait(); + retMaintainer.wait(); + APPL_INFO("Service: system-user"); + APPL_INFO(" version : " << retVersion.get()); + APPL_INFO(" type : " << retType.get()); + APPL_INFO(" Extention : " << retExtention.get().size()); + for (auto &it : retExtention.get()) { + APPL_INFO(" - " << it); + } + APPL_INFO(" maintainer: " << retMaintainer.get().size()); + for (auto &it : retMaintainer.get()) { + APPL_INFO(" - " << it); + } + APPL_INFO(" description:"); + APPL_INFO(" " << retDesc.get()); + APPL_INFO(" Function List:"); + jus::Future> retFuctions = remoteServiceUser.call("sys.getFunctions").wait(); + for (auto it : retFuctions.get()) { + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); + jus::Future retFunctionPrototype = remoteServiceUser.call("sys.getFunctionPrototype", it); + jus::Future retFunctionHelp = remoteServiceUser.call("sys.getFunctionDescription", it); + retFunctionPrototype.wait(); + retFunctionHelp.wait(); + std::chrono::steady_clock::time_point stop = std::chrono::steady_clock::now(); + APPL_INFO(" - " << retFunctionPrototype.get()); + APPL_INFO(" " << retFunctionHelp.get()); + APPL_INFO(" IO1=" << int64_t(retFunctionPrototype.getTransmitionTime().count()/1000)/1000.0 << " ms"); + APPL_INFO(" IO2=" << int64_t(retFunctionHelp.getTransmitionTime().count()/1000)/1000.0 << " ms"); + APPL_INFO(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms"); + } } } - APPL_INFO(" ----------------------------------"); APPL_INFO(" -- Get service picture"); APPL_INFO(" ----------------------------------"); jus::ServiceRemote remoteServicePicture = client1.getService("picture"); if (remoteServicePicture.exist() == true) { + /* jus::Future> retCall = remoteServicePicture.call("getAlbums").wait(); APPL_INFO(" album list: "); for (auto &it : retCall.get()) { @@ -179,7 +181,8 @@ int main(int _argc, const char *_argv[]) { } } } - jus::File tmp("image/jpg", {0,5,2,6,7,5,8,4,5,2,1,5,65,5,2,6,85,4,6,6,54,65,88,64,14,6,4,64,51,3,16,4}); + */ + jus::File tmp("./photo_2016_33913.bmp");//"image/jpg", {0,5,2,6,7,5,8,4,5,2,1,5,65,5,2,6,85,4,6,6,54,65,88,64,14,6,4,64,51,3,16,4}); jus::FutureBase retSendImage = remoteServicePicture.call("addFile", tmp).wait(); } diff --git a/tools/picture/appl/main.cpp b/tools/picture/appl/main.cpp index f5e3c80..bd31fca 100644 --- a/tools/picture/appl/main.cpp +++ b/tools/picture/appl/main.cpp @@ -235,7 +235,8 @@ namespace appl { } } */ - APPL_ERROR(" ==> Receive FILE " << _dataFile.getMineType()); + APPL_ERROR(" ==> Receive FILE " << _dataFile.getMineType() << " size=" << _dataFile.getData().size()); + _dataFile.storeIn("plopppp.bmp"); return "54654654654654";//jus::FileServer(); } /*