[DEV] try to re-send async datas...

This commit is contained in:
Edouard DUPIN 2016-06-01 20:08:45 +02:00
parent 5334df4513
commit e0861c66ac
19 changed files with 671 additions and 172 deletions

View File

@ -107,6 +107,15 @@ namespace jus {
} }
return out; return out;
} }
template<> ejson::Value convertToJson<jus::FileServer>(const jus::FileServer& _value) {
ejson::Array out;
/*
for (auto &it : _value) {
out.add(ejson::String(it));
}
*/
return out;
}
template<> bool convertStringTo<bool>(const std::string& _value) { template<> bool convertStringTo<bool>(const std::string& _value) {
return etk::string_to_bool(_value); return etk::string_to_bool(_value);
@ -149,6 +158,9 @@ namespace jus {
JUS_TODO("Convert string to vs"); JUS_TODO("Convert string to vs");
return out; return out;
} }
template<> jus::FileServer convertStringTo<jus::FileServer>(const std::string& _value) {
return jus::FileServer();
}
} }

View File

@ -10,6 +10,7 @@
#include <ejson/ejson.h> #include <ejson/ejson.h>
#include <jus/debug.h> #include <jus/debug.h>
#include <jus/ParamType.h> #include <jus/ParamType.h>
#include <jus/File.h>
namespace jus { namespace jus {
class AbstractFunction { class AbstractFunction {
public: public:
@ -55,7 +56,7 @@ namespace jus {
virtual std::string getPrototype() const = 0; virtual std::string getPrototype() const = 0;
virtual std::string getPrototypeReturn() const = 0; virtual std::string getPrototypeReturn() const = 0;
virtual std::vector<std::string> getPrototypeParam() const = 0; virtual std::vector<std::string> getPrototypeParam() const = 0;
virtual ejson::Value executeJson(const ejson::Array& _params, void* _class=nullptr) = 0; virtual void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, const ejson::Array& _params, void* _class=nullptr) = 0;
virtual std::string executeString(const std::vector<std::string>& _params, void* _class=nullptr) = 0; virtual std::string executeString(const std::vector<std::string>& _params, void* _class=nullptr) = 0;
}; };

View File

@ -12,23 +12,63 @@
#include <jus/AbstractFunction.h> #include <jus/AbstractFunction.h>
namespace jus { namespace jus {
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
ejson::Value executeClassCallJson(JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0; int32_t idParam = 0;
return convertToJson((*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...)); ejson::Value ret = convertToJson((*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...));
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
return convertToJson((*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...)); ejson::Value ret = convertToJson((*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...));
#else #else
#error Must be implemented ... #error Must be implemented ...
ejson::Value ret = ejson::Null();
return;
#endif #endif
return ejson::Null(); ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ret);
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
}
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
jus::FileServer tmpElem = (*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
jus::FileServer tmpElem = (*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...);
#else
#error Must be implemented ...
jus::FileServer tmpElem;
return;
#endif
JUS_ERROR("Must be implemented in a worker ...");
} }
template <class JUS_CLASS_TYPE, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class... JUS_TYPES>
ejson::Value executeClassCallJson(JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const ejson::Array& _params) { void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
ejson::Object out; ejson::Object out;
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
@ -40,12 +80,21 @@ namespace jus {
(*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...); (*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...);
#else #else
#error Must be implemented ... #error Must be implemented ...
ejson::Value ret = ejson::Null();
return;
#endif #endif
return ejson::Null(); ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ejson::Null());
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
} }
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector<std::string>& _params) { std::string executeClassCallString(JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const std::vector<std::string>& _params) {
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
@ -60,7 +109,9 @@ namespace jus {
return ""; return "";
} }
template <class JUS_CLASS_TYPE, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class... JUS_TYPES>
std::string executeClassCallString(JUS_CLASS_TYPE* _pointer, void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), const std::vector<std::string>& _params) { std::string executeClassCallString(JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const std::vector<std::string>& _params) {
ejson::Object out; ejson::Object out;
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
@ -113,37 +164,49 @@ namespace jus {
} }
return out; return out;
} }
ejson::Value executeJson(const ejson::Array& _params, void* _class) override { void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
const ejson::Array& _params,
void* _class) override {
JUS_CLASS_TYPE* tmpClass = nullptr; JUS_CLASS_TYPE* tmpClass = nullptr;
if (_class != nullptr) { if (_class != nullptr) {
tmpClass = (JUS_CLASS_TYPE*)_class; tmpClass = (JUS_CLASS_TYPE*)_class;
} }
ejson::Object out;
// check parameter number // check parameter number
if (_params.size() != sizeof...(JUS_TYPES)) { if (_params.size() != sizeof...(JUS_TYPES)) {
JUS_ERROR("Wrong number of Parameters ..."); JUS_ERROR("Wrong number of Parameters ...");
out.add("error", ejson::String("WRONG-PARAMETER-NUMBER")); ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER"));
std::string help = "request "; std::string help = "request ";
help += etk::to_string(_params.size()); help += etk::to_string(_params.size());
help += " parameters and need "; help += " parameters and need ";
help += etk::to_string(sizeof...(JUS_TYPES)); help += etk::to_string(sizeof...(JUS_TYPES));
help += " parameters. prototype function:"; help += " parameters. prototype function:";
help += getPrototype(); help += getPrototype();
out.add("error-help", ejson::String(help)); answer.add("error-help", ejson::String(help));
return out; JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
return;
} }
// check parameter compatibility // check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) { for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _params[iii]) == false) { if (checkCompatibility(m_paramType[iii], _params[iii]) == false) {
out.add("error", ejson::String("WRONG-PARAMETER-TYPE")); ejson::Object answer;
out.add("error-help", ejson::String("Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'")); answer.add("id", ejson::Number(_transactionId));
return out; answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-TYPE"));
answer.add("error-help", ejson::String("Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'"));
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
return;
} }
} }
// execute cmd: // execute cmd:
ejson::Value retVal = jus::executeClassCallJson(tmpClass, m_function, _params); jus::executeClassCallJson(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _params);
out.add("return", retVal);
return out;
} }
std::string executeString(const std::vector<std::string>& _params, void* _class) override { std::string executeString(const std::vector<std::string>& _params, void* _class) override {
JUS_CLASS_TYPE* tmpClass = (JUS_CLASS_TYPE*)_class; JUS_CLASS_TYPE* tmpClass = (JUS_CLASS_TYPE*)_class;

View File

@ -12,23 +12,37 @@
#include <jus/AbstractFunction.h> #include <jus/AbstractFunction.h>
namespace jus { namespace jus {
template <class JUS_RETURN, class... JUS_TYPES> template <class JUS_RETURN, class... JUS_TYPES>
ejson::Value executeCallJson(JUS_RETURN (*_func)(JUS_TYPES...), const ejson::Array& _params) { void executeCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_RETURN (*_func)(JUS_TYPES...),
const ejson::Array& _params) {
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced] // warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0; int32_t idParam = 0;
return convertToJson(_func((convertJsonTo<JUS_TYPES>(_params[idParam++]))...)); ejson::Value ret = convertToJson(_func((convertJsonTo<JUS_TYPES>(_params[idParam++]))...));
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) #elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1; int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
return convertToJson(_func(convertJsonTo<JUS_TYPES>(_params[idParam--])...)); ejson::Value ret = convertToJson(_func(convertJsonTo<JUS_TYPES>(_params[idParam--])...));
#else #else
#error Must be implemented ... #error Must be implemented ...
ejson::Value ret = ejson::Null();
#endif #endif
return ejson::Null(); ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ret);
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
} }
template <class... JUS_TYPES> template <class... JUS_TYPES>
ejson::Value executeCallJson(void (*_func)(JUS_TYPES...), const ejson::Array& _params) { void executeCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
void (*_func)(JUS_TYPES...),
const ejson::Array& _params) {
ejson::Object out; ejson::Object out;
#if defined(__clang__) #if defined(__clang__)
// clang generate a basic warning: // clang generate a basic warning:
@ -41,7 +55,16 @@ namespace jus {
#else #else
#error Must be implemented ... #error Must be implemented ...
#endif #endif
return ejson::Null(); _interfaceClient->addAsync([=](TcpString* _interface) {
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ejson::Null());
JUS_INFO("Answer: " << answer.generateHumanString());
_interface->write(answer.generateMachineString());
return true;
});
}
} }
template <class JUS_RETURN, class... JUS_TYPES> template <class JUS_RETURN, class... JUS_TYPES>
@ -113,33 +136,43 @@ namespace jus {
} }
return out; return out;
} }
ejson::Value executeJson(const ejson::Array& _params, void* _class) override { void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
ejson::Object out; uint64_t _transactionId,
uint64_t _clientId,
const ejson::Array& _params,
void* _class) override {
// check parameter number // check parameter number
if (_params.size() != sizeof...(JUS_TYPES)) { if (_params.size() != sizeof...(JUS_TYPES)) {
JUS_ERROR("Wrong number of Parameters ..."); ejson::Object answer;
out.add("error", ejson::String("WRONG-PARAMETER-NUMBER")); answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER"));
std::string help = "request "; std::string help = "request ";
help += etk::to_string(_params.size()); help += etk::to_string(_params.size());
help += " parameters and need "; help += " parameters and need ";
help += etk::to_string(sizeof...(JUS_TYPES)); help += etk::to_string(sizeof...(JUS_TYPES));
help += " parameters. prototype function:"; help += " parameters. prototype function:";
help += getPrototype(); help += getPrototype();
out.add("error-help", ejson::String(help)); answer.add("error-help", ejson::String(help));
return out; JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
return;
} }
// check parameter compatibility // check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) { for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _params[iii]) == false) { if (checkCompatibility(m_paramType[iii], _params[iii]) == false) {
out.add("error", ejson::String("WRONG-PARAMETER-TYPE")); ejson::Object answer;
out.add("error-help", ejson::String("Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'")); answer.add("id", ejson::Number(_transactionId));
return out; answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-TYPE"));
answer.add("error-help", ejson::String("Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'"));
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
return;
} }
} }
// execute cmd: // execute cmd:
ejson::Value retVal = jus::executeCallJson(m_function, _params); jus::executeCallJson(_interfaceClient, _transactionId, _clientId, m_function, _params);
out.add("return", retVal);
return out;
} }
std::string executeString(const std::vector<std::string>& _params, void* _class) override { std::string executeString(const std::vector<std::string>& _params, void* _class) override {
std::string out; std::string out;

38
jus/File.cpp Normal file
View File

@ -0,0 +1,38 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/File.h>
#include <etk/types.h>
#include <etk/stdTools.h>
jus::File::File() {
}
jus::File::File(const std::string& _filename) {
}
jus::File::File(const std::string& _mineType, std::vector<uint8_t> _data) {
}
jus::FileServer::FileServer() {
}
jus::FileServer::FileServer(const std::string& _filename) {
m_name = _filename;
}
namespace etk {
template<>
std::string to_string<jus::FileServer>(jus::FileServer const& _obj) {
return "";
}
}

33
jus/File.h Normal file
View File

@ -0,0 +1,33 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
namespace jus {
class File {
private:
std::string m_mineType;
std::vector<uint8_t> m_data;
public:
File();
File(const std::string& _filename);
File(const std::string& _mineType, std::vector<uint8_t> _data);
const std::string& getMineType() {
return m_mineType;
}
const std::vector<uint8_t>& getData() {
return m_data;
}
};
class FileServer {
private:
std::string m_name;
public:
FileServer();
FileServer(const std::string& _filename);
};
}

View File

@ -6,6 +6,7 @@
#include <jus/Future.h> #include <jus/Future.h>
#include <jus/debug.h> #include <jus/debug.h>
#include <unistd.h> #include <unistd.h>
#include <jus/File.h>
namespace jus { namespace jus {
template<> template<>
@ -488,6 +489,33 @@ namespace jus {
} }
return out; return out;
} }
template<>
jus::File jus::Future<jus::File>::get() {
jus::File out;
if (m_data == nullptr) {
return out;
}
// TODO :...
/*
ejson::Value val = m_data->m_returnData["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return out;
}
if (val.isArray() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'");
return out;
}
for (auto it : val.toArray()) {
if (it.isBoolean() == false) {
JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Boolean'");
continue;
}
out.push_back(it.toBoolean().get());
}
*/
return out;
}
} }

View File

@ -24,6 +24,7 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFi
m_data->m_sendTime = std::chrono::steady_clock::now(); m_data->m_sendTime = std::chrono::steady_clock::now();
m_data->m_transactionId = _transactionId; m_data->m_transactionId = _transactionId;
m_data->m_isFinished = false; m_data->m_isFinished = false;
m_data->m_isSynchronous = false;
m_data->m_callbackFinish = _callback; m_data->m_callbackFinish = _callback;
} }
@ -42,6 +43,7 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob
m_data->m_sendTime = std::chrono::steady_clock::now(); m_data->m_sendTime = std::chrono::steady_clock::now();
m_data->m_transactionId = _transactionId; m_data->m_transactionId = _transactionId;
m_data->m_isFinished = _isFinished; m_data->m_isFinished = _isFinished;
m_data->m_isSynchronous = false;
m_data->m_returnData = _returnData; m_data->m_returnData = _returnData;
m_data->m_callbackFinish = _callback; m_data->m_callbackFinish = _callback;
if (m_data->m_isFinished == true) { if (m_data->m_isFinished == true) {
@ -67,17 +69,50 @@ jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) {
return *this; return *this;
} }
void jus::FutureBase::setAnswer(const ejson::Object& _returnValue) { bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
if (m_data == nullptr) { if (m_data == nullptr) {
JUS_ERROR(" Not a valid future ..."); JUS_ERROR(" Not a valid future ...");
return; return true;
} }
m_data->m_receiveTime = std::chrono::steady_clock::now(); m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_isSynchronous == true) {
m_data->m_returnData = _returnValue;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
if (_returnValue.valueExist("part") == true) {
uint64_t idPart = _returnValue["part"].toNumber().getU64();
if (idPart == 0) {
m_data->m_returnData = _returnValue;
} else {
m_data->m_returnDataPart.push_back(_returnValue["data"]);
}
if (_returnValue.valueExist("finish") == true) {
if (_returnValue["finish"].toBoolean().get() == true) {
m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
// finish is false ==> normal case ...
}
return false;
}
m_data->m_returnData = _returnValue; m_data->m_returnData = _returnValue;
m_data->m_isFinished = true; m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) { if (m_data->m_callbackFinish != nullptr) {
m_data->m_callbackFinish(*this); return m_data->m_callbackFinish(*this);
} }
return true;
}
void jus::FutureBase::setSynchronous() {
if (m_data == nullptr) {
return;
}
m_data->m_isSynchronous = true;
} }
uint64_t jus::FutureBase::getTransactionId() { uint64_t jus::FutureBase::getTransactionId() {

View File

@ -17,7 +17,8 @@ namespace jus {
FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback=nullptr); FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback=nullptr);
FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback=nullptr); FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback=nullptr);
jus::FutureBase operator= (const jus::FutureBase& _base); jus::FutureBase operator= (const jus::FutureBase& _base);
void setAnswer(const ejson::Object& _returnValue); bool setAnswer(const ejson::Object& _returnValue);
void setSynchronous();
uint64_t getTransactionId(); uint64_t getTransactionId();
bool hasError(); bool hasError();
std::string getErrorType(); std::string getErrorType();

View File

@ -12,11 +12,13 @@ namespace jus {
class FutureBase; class FutureBase;
class FutureData { class FutureData {
public: public:
using ObserverFinish = std::function<void(jus::FutureBase)>; //!< Define an Observer: function pointer using ObserverFinish = std::function<bool(jus::FutureBase)>; //!< Define an Observer: function pointer
public: public:
uint64_t m_transactionId; uint64_t m_transactionId;
bool m_isSynchronous;
bool m_isFinished; bool m_isFinished;
ejson::Object m_returnData; ejson::Object m_returnData;
std::vector<ejson::Value> m_returnDataPart;
ObserverFinish m_callbackFinish; ObserverFinish m_callbackFinish;
std::chrono::steady_clock::time_point m_sendTime; std::chrono::steady_clock::time_point m_sendTime;
std::chrono::steady_clock::time_point m_receiveTime; std::chrono::steady_clock::time_point m_receiveTime;

View File

@ -362,6 +362,14 @@ void jus::GateWayClient::onClientData(std::string _value) {
tmpp["id"].toNumber().set(data["id"].toNumber().getU64()); tmpp["id"].toNumber().set(data["id"].toNumber().getU64());
JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); JUS_VERBOSE(" msg=" << tmpp.generateMachineString());
m_interfaceClient.write(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;
}); });
} }
} }
@ -371,7 +379,9 @@ void jus::GateWayClient::onClientData(std::string _value) {
jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback) { jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId(); uint64_t id = getId();
ejson::Object callElem = jus::createCallJson(id, _functionName, _params); ejson::Object callElem = jus::createCallJson(id, _functionName, _params);
return callJson(_callerId, _srv, id, callElem, _callback); jus::FutureBase ret = callJson(_callerId, _srv, id, callElem, _callback);
ret.setSynchronous();
return ret;
} }
uint64_t jus::GateWayClient::getId() { uint64_t jus::GateWayClient::getId() {
@ -400,7 +410,6 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::Shared
void jus::GateWayClient::returnMessage(ejson::Object _data) { void jus::GateWayClient::returnMessage(ejson::Object _data) {
jus::FutureBase future; jus::FutureBase future;
{
uint64_t tid = _data["id"].toNumber().get(); uint64_t tid = _data["id"].toNumber().get();
if (tid == 0) { if (tid == 0) {
if (_data["error"].toString().get() == "PROTOCOL-ERROR") { if (_data["error"].toString().get() == "PROTOCOL-ERROR") {
@ -418,6 +427,7 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) {
} }
return; return;
} }
{
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_pendingCall.begin(); auto it = m_pendingCall.begin();
while (it != m_pendingCall.end()) { while (it != m_pendingCall.end()) {
@ -429,8 +439,8 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) {
++it; ++it;
continue; continue;
} }
// TODO : Do it better ...
future = *it; future = *it;
it = m_pendingCall.erase(it);
break; break;
} }
} }
@ -438,6 +448,22 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) {
JUS_WARNING("Action to do ..."); JUS_WARNING("Action to do ...");
return; return;
} }
future.setAnswer(_data); bool ret = future.setAnswer(_data);
if (ret == true) {
std::unique_lock<std::mutex> 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;
}
}
} }

View File

@ -6,6 +6,7 @@
#include <jus/ParamType.h> #include <jus/ParamType.h>
#include <jus/debug.h> #include <jus/debug.h>
#include <jus/File.h>
jus::ParamType::ParamType(const char* _name): jus::ParamType::ParamType(const char* _name):
@ -56,3 +57,9 @@ generate_basic_type(std::vector<uint32_t>, "vector:uint32");
generate_basic_type(std::vector<uint16_t>, "vector:uint16"); generate_basic_type(std::vector<uint16_t>, "vector:uint16");
generate_basic_type(std::vector<uint8_t>, "vector:uint8"); generate_basic_type(std::vector<uint8_t>, "vector:uint8");
generate_basic_type(std::vector<std::string>, "vector:string"); generate_basic_type(std::vector<std::string>, "vector:string");
generate_basic_type(jus::File, "file");
generate_basic_type(jus::FileServer, "file");

View File

@ -15,7 +15,8 @@
jus::Service::Service() : jus::Service::Service() :
propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp), propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp),
propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort) { propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort) {
m_interfaceClient.connect(this, &jus::Service::onClientData); m_interfaceClient = std::make_shared<jus::TcpString>();
m_interfaceClient->connect(this, &jus::Service::onClientData);
advertise("getExtention", &jus::Service::getExtention); advertise("getExtention", &jus::Service::getExtention);
setLastFuncDesc("Get List of availlable extention of this service"); setLastFuncDesc("Get List of availlable extention of this service");
@ -35,16 +36,18 @@ std::vector<std::string> jus::Service::getExtention() {
void jus::Service::onClientData(std::string _value) { void jus::Service::onClientData(std::string _value) {
ejson::Object request(_value); ejson::Object request(_value);
ejson::Value tmpID = request["id"]; uint64_t tmpID = request["id"].toNumber().getU64();
request.remove("id"); //request.remove("id");
JUS_INFO("Request: " << _value); JUS_INFO("Request: " << _value);
ejson::Value answer = callJson(request); callJson(tmpID, request);
/*
// check if an answer is needed // check if an answer is needed
if (answer.isNull() == false) { if (answer.isNull() == false) {
answer.toObject().add("id", tmpID); answer.toObject().add("id", tmpID);
JUS_INFO("Answer: " << answer.generateHumanString()); JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient->write(answer.generateMachineString());
} }
*/
} }
void jus::Service::onPropertyChangeIp() { void jus::Service::onPropertyChangeIp() {
@ -64,29 +67,29 @@ void jus::Service::connect(const std::string& _serviceName, uint32_t _numberRetr
JUS_DEBUG("connect [STOP] ==> can not connect"); JUS_DEBUG("connect [STOP] ==> can not connect");
return; return;
} }
m_interfaceClient.setInterface(std::move(connection)); m_interfaceClient->setInterface(std::move(connection));
m_interfaceClient.connect(); m_interfaceClient->connect();
m_interfaceClient.write(std::string("{\"connect-service\":\"") + _serviceName + "\"}"); m_interfaceClient->write(std::string("{\"connect-service\":\"") + _serviceName + "\"}");
JUS_DEBUG("connect [STOP]"); JUS_DEBUG("connect [STOP]");
} }
void jus::Service::disconnect(){ void jus::Service::disconnect(){
JUS_DEBUG("disconnect [START]"); JUS_DEBUG("disconnect [START]");
m_interfaceClient.disconnect(); m_interfaceClient->disconnect();
JUS_DEBUG("disconnect [STOP]"); JUS_DEBUG("disconnect [STOP]");
} }
bool jus::Service::GateWayAlive() { bool jus::Service::GateWayAlive() {
return m_interfaceClient.isActive(); return m_interfaceClient->isActive();
} }
void jus::Service::pingIsAlive() { void jus::Service::pingIsAlive() {
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(30)) { if (std::chrono::steady_clock::now() - m_interfaceClient->getLastTimeSend() >= std::chrono::seconds(30)) {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}"); m_interfaceClient->write("{\"event\":\"IS-ALIVE\"}");
} }
} }
ejson::Value jus::Service::callJson(const ejson::Object& _obj) { void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj) {
if (_obj.valueExist("event") == true) { if (_obj.valueExist("event") == true) {
std::string event = _obj["event"].toString().get(); std::string event = _obj["event"].toString().get();
if (event == "IS-ALIVE") { if (event == "IS-ALIVE") {
@ -104,22 +107,27 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) {
} else { } else {
JUS_ERROR("Unknow event: '" << event << "'"); JUS_ERROR("Unknow event: '" << event << "'");
} }
return ejson::Null(); return;
} }
ejson::Object tmpp; ejson::Object answer;
uint64_t clientId = _obj["client-id"].toNumber().getU64(); uint64_t clientId = _obj["client-id"].toNumber().getU64();
if (_obj.valueExist("call") == true) { if (_obj.valueExist("call") == true) {
std::string call = _obj["call"].toString().get(); std::string call = _obj["call"].toString().get();
if (isFunctionAuthorized(clientId, call) == true) { if (isFunctionAuthorized(clientId, call) == true) {
tmpp = callJson2(clientId, _obj); callJson2(_transactionId, clientId, call, _obj["param"].toArray());
tmpp.add("client-id", ejson::Number(clientId)); return;
return tmpp;
} else { } else {
tmpp.add("error", ejson::String("NOT-AUTHORIZED-FUNCTION")); answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(clientId));
answer.add("error", ejson::String("NOT-AUTHORIZED-FUNCTION"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
return;
} }
} else {
tmpp.add("error", ejson::String("NOT-IMPLEMENTED-FUNCTION"));
} }
tmpp.add("client-id", ejson::Number(clientId)); answer.add("id", ejson::Number(_transactionId));
return tmpp; answer.add("client-id", ejson::Number(clientId));
answer.add("error", ejson::String("NOT-IMPLEMENTED-FUNCTION"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
} }

View File

@ -57,8 +57,8 @@ namespace jus {
public: public:
eproperty::Value<std::string> propertyIp; eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> propertyPort; eproperty::Value<uint16_t> propertyPort;
private: protected:
jus::TcpString m_interfaceClient; ememory::SharedPtr<jus::TcpString> m_interfaceClient;
uint32_t m_id; uint32_t m_id;
std::vector<std::string> m_newData; std::vector<std::string> m_newData;
public: public:
@ -77,15 +77,15 @@ namespace jus {
void onPropertyChangePort(); void onPropertyChangePort();
/** /**
* @brief A extern client connect on specific user * @brief A extern client connect on specific user
* @param[in] _clientSessionID Source session Id on the client * @param[in] _clientId Source session Id on the client
* @param[in] _userName User name of the client to connect * @param[in] _userName User name of the client to connect
* @todo Set a relur like ==> service not availlable / service close / service maintenance / service right reject * @todo Set a relur like ==> service not availlable / service close / service maintenance / service right reject
*/ */
virtual void clientConnect(size_t _clientSessionID, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) = 0; virtual void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) = 0;
virtual void clientDisconnect(size_t _clientSessionID) = 0; virtual void clientDisconnect(uint64_t _clientId) = 0;
// Genenric function call: // Genenric function call:
ejson::Value callJson(const ejson::Object& _obj); void callJson(uint64_t _transactionId, const ejson::Object& _obj);
virtual ejson::Object callJson2(size_t _clientId, const ejson::Object& _obj) = 0; virtual void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _obj) = 0;
std::vector<std::string> getExtention(); std::vector<std::string> getExtention();
public: public:
// Add Local fuction (depend on this class) // Add Local fuction (depend on this class)
@ -154,21 +154,21 @@ namespace jus {
m_getUserInterface(_interface) { m_getUserInterface(_interface) {
} }
bool isFunctionAuthorized(uint64_t _clientSessionID, const std::string& _funcName) { bool isFunctionAuthorized(uint64_t _clientId, const std::string& _funcName) {
auto it = m_interface.find(_clientSessionID); auto it = m_interface.find(_clientId);
if (it == m_interface.end()) { if (it == m_interface.end()) {
return false; return false;
} }
return it->second.first->isFunctionAuthorized(_funcName); return it->second.first->isFunctionAuthorized(_funcName);
} }
void clientConnect(uint64_t _clientSessionID, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) { void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector<std::string>& _groups) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("connect: " << _clientSessionID << " to '" << _userName << "'"); JUS_DEBUG("connect: " << _clientId << " to '" << _userName << "'");
JUS_DEBUG(" client name='" << _clientName << "'"); JUS_DEBUG(" client name='" << _clientName << "'");
JUS_DEBUG(" groups=" << etk::to_string(_groups)); JUS_DEBUG(" groups=" << etk::to_string(_groups));
ememory::SharedPtr<ClientProperty> tmpProperty = std::make_shared<ClientProperty>(_clientName, _groups); ememory::SharedPtr<ClientProperty> tmpProperty = std::make_shared<ClientProperty>(_clientName, _groups);
ememory::SharedPtr<JUS_TYPE_SERVICE> tmpSrv = std::make_shared<JUS_TYPE_SERVICE>(m_getUserInterface.getUser(_userName), tmpProperty); ememory::SharedPtr<JUS_TYPE_SERVICE> tmpSrv = std::make_shared<JUS_TYPE_SERVICE>(m_getUserInterface.getUser(_userName), tmpProperty);
m_interface.insert(std::make_pair(_clientSessionID, std::make_pair(tmpProperty, tmpSrv))); m_interface.insert(std::make_pair(_clientId, std::make_pair(tmpProperty, tmpSrv)));
// enable list of function availlable: // enable list of function availlable:
for (auto &it : m_listFunction) { for (auto &it : m_listFunction) {
if (it == nullptr) { if (it == nullptr) {
@ -177,72 +177,85 @@ namespace jus {
tmpProperty->addAuthorized(it->getName()); tmpProperty->addAuthorized(it->getName());
} }
} }
void clientDisconnect(uint64_t _clientSessionID) { void clientDisconnect(uint64_t _clientId) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("disconnect: " << _clientSessionID); JUS_DEBUG("disconnect: " << _clientId);
auto it = m_interface.find(_clientSessionID); auto it = m_interface.find(_clientId);
if (it == m_interface.end()) { if (it == m_interface.end()) {
JUS_WARNING("disconnect ==> Not find Client ID " << _clientSessionID); JUS_WARNING("disconnect ==> Not find Client ID " << _clientId);
// noting to do ==> user never conected. // noting to do ==> user never conected.
return; return;
} }
m_interface.erase(it); m_interface.erase(it);
} }
void clientSetName(uint64_t _clientSessionID, const std::string& _clientName) { void clientSetName(uint64_t _clientId, const std::string& _clientName) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientSessionID); auto it = m_interface.find(_clientId);
if (it == m_interface.end()) { if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ..."); JUS_ERROR("Change the client property but client was not created ...");
return; return;
} }
it->second.first->setName(_clientName); it->second.first->setName(_clientName);
} }
void clientSetGroup(uint64_t _clientSessionID, const std::vector<std::string>& _clientGroups) { void clientSetGroup(uint64_t _clientId, const std::vector<std::string>& _clientGroups) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientSessionID); auto it = m_interface.find(_clientId);
if (it == m_interface.end()) { if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ..."); JUS_ERROR("Change the client property but client was not created ...");
return; return;
} }
it->second.first->setGroups(_clientGroups); it->second.first->setGroups(_clientGroups);
} }
ejson::Object callJson2(uint64_t _clientSessionID, const ejson::Object& _obj) { void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _params) {
ejson::Object out; auto it = m_interface.find(_clientId);
auto it = m_interface.find(_clientSessionID);
if (it == m_interface.end()) { if (it == m_interface.end()) {
out.add("error", ejson::String("CLIENT-UNKNOW")); ejson::Object answer;
return out; answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("CLIENT-UNKNOW"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
return;
} }
std::string call = _obj["call"].toString().get();
const ejson::Array param = _obj["param"].toArray();
for (auto &it2 : m_listFunction) { for (auto &it2 : m_listFunction) {
if (it2 == nullptr) { if (it2 == nullptr) {
continue; continue;
} }
if (it2->getName() != call) { if (it2->getName() != _call) {
continue; continue;
} }
switch (it2->getType()) { switch (it2->getType()) {
case jus::AbstractFunction::type::object: { case jus::AbstractFunction::type::object: {
JUS_TYPE_SERVICE* elem = it->second.second.get(); JUS_TYPE_SERVICE* elem = it->second.second.get();
return it2->executeJson(param, (void*)elem).toObject(); it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)elem);
return;
} }
case jus::AbstractFunction::type::local: { case jus::AbstractFunction::type::local: {
return it2->executeJson(param, (void*)((RemoteProcessCall*)this)).toObject(); it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)((RemoteProcessCall*)this));
return;
} }
case jus::AbstractFunction::type::service: { case jus::AbstractFunction::type::service: {
return it2->executeJson(param, (void*)this).toObject(); it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)this);
return;
} }
case jus::AbstractFunction::type::global: { case jus::AbstractFunction::type::global: {
return it2->executeJson(param, nullptr).toObject(); it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, nullptr);
return;
} }
case jus::AbstractFunction::type::unknow: case jus::AbstractFunction::type::unknow:
JUS_ERROR("Can not call unknow type ..."); JUS_ERROR("Can not call unknow type ...");
break; break;
} }
} }
out.add("error", ejson::String("FUNCTION-UNKNOW")); {
return out; ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("FUNCTION-UNKNOW"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
}
return;
} }
}; };
} }

View File

@ -11,15 +11,19 @@
jus::TcpString::TcpString(enet::Tcp _connection) : jus::TcpString::TcpString(enet::Tcp _connection) :
m_connection(std::move(_connection)), m_connection(std::move(_connection)),
m_thread(nullptr), m_thread(nullptr),
m_obsercerElement(nullptr) { m_obsercerElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false; m_threadRunning = false;
m_threadAsyncRunning = false;
} }
jus::TcpString::TcpString() : jus::TcpString::TcpString() :
m_connection(), m_connection(),
m_thread(nullptr), m_thread(nullptr),
m_obsercerElement(nullptr) { m_obsercerElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false; m_threadRunning = false;
m_threadAsyncRunning = false;
} }
void jus::TcpString::setInterface(enet::Tcp _connection) { void jus::TcpString::setInterface(enet::Tcp _connection) {
@ -66,6 +70,14 @@ void jus::TcpString::connect(bool _async){
JUS_ERROR("creating callback thread!"); JUS_ERROR("creating callback thread!");
return; return;
} }
m_threadAsyncRunning = true;
m_threadAsync = new std::thread([&](void *){ this->threadAsyncCallback();}, nullptr);
if (m_threadAsync == nullptr) {
m_threadAsyncRunning = false;
JUS_ERROR("creating async sender thread!");
return;
}
while ( _async == false while ( _async == false
&& m_threadRunning == true && m_threadRunning == true
&& m_connection.getConnectionStatus() != enet::Tcp::status::link) { && m_connection.getConnectionStatus() != enet::Tcp::status::link) {
@ -81,9 +93,8 @@ void jus::TcpString::connect(bool _async){
void jus::TcpString::disconnect(bool _inThreadStop){ void jus::TcpString::disconnect(bool _inThreadStop){
JUS_DEBUG("disconnect [START]"); JUS_DEBUG("disconnect [START]");
if (m_thread != nullptr) {
m_threadRunning = false; m_threadRunning = false;
} m_threadAsyncRunning = false;
if (m_connection.getConnectionStatus() == enet::Tcp::status::link) { if (m_connection.getConnectionStatus() == enet::Tcp::status::link) {
uint32_t size = 0xFFFFFFFF; uint32_t size = 0xFFFFFFFF;
m_connection.write(&size, 4); m_connection.write(&size, 4);
@ -91,6 +102,11 @@ void jus::TcpString::disconnect(bool _inThreadStop){
if (m_connection.getConnectionStatus() != enet::Tcp::status::unlink) { if (m_connection.getConnectionStatus() != enet::Tcp::status::unlink) {
m_connection.unlink(); m_connection.unlink();
} }
if (m_threadAsync != nullptr) {
m_threadAsync->join();
delete m_threadAsync;
m_threadAsync = nullptr;
}
if (_inThreadStop == false) { if (_inThreadStop == false) {
if (m_thread != nullptr) { if (m_thread != nullptr) {
m_thread->join(); m_thread->join();
@ -147,3 +163,36 @@ std::string jus::TcpString::read() {
return out; return out;
} }
void jus::TcpString::threadAsyncCallback() {
ethread::setName("Async-sender");
// get datas:
while ( m_threadAsyncRunning == true
&& m_connection.getConnectionStatus() == enet::Tcp::status::link) {
if (m_threadAsyncList.size() == 0) {
usleep(10000);
continue;
}
std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
auto it = m_threadAsyncList.begin();
while (it != m_threadAsyncList.end()) {
bool ret = m_threadAsyncList(this);
if (ret == true) {
// Remove it ...
it = m_threadAsyncList.erase(it);
} else {
++it;
}
}
JUS_VERBOSE("Receive data: '" << data << "'");
if (data.size() != 0) {
m_lastReceive = std::chrono::steady_clock::now();
if (m_obsercerElement != nullptr) {
m_obsercerElement(std::move(data));
}
}
}
m_threadRunning = false;
JUS_DEBUG("End of thread");
}

View File

@ -55,6 +55,19 @@ namespace jus {
const std::chrono::steady_clock::time_point& getLastTimeSend() { const std::chrono::steady_clock::time_point& getLastTimeSend() {
return m_lastSend; return m_lastSend;
} }
private:
using ActionAsync = std::function<bool(TcpString* _interface)>;
std::mutex m_threadAsyncMutex;
std::thread* m_threadAsync;
bool m_threadAsyncRunning;
std::vector<ActionAsync> m_threadAsyncList;
private:
void threadAsyncCallback();
public:
void addAsync(ActionAsync _elem) {
std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
m_threadAsyncList.push_back(_elem);
}
}; };
} }

View File

@ -37,6 +37,7 @@ def create(target, module_name):
'jus/AbstractFunctionTypeClass.cpp', 'jus/AbstractFunctionTypeClass.cpp',
'jus/FutureBase.cpp', 'jus/FutureBase.cpp',
'jus/Future.cpp', 'jus/Future.cpp',
'jus/File.cpp',
'jus/ParamType.cpp', 'jus/ParamType.cpp',
'jus/Client.cpp', 'jus/Client.cpp',
'jus/GateWay.cpp', 'jus/GateWay.cpp',
@ -54,6 +55,7 @@ def create(target, module_name):
'jus/FutureData.h', 'jus/FutureData.h',
'jus/FutureBase.h', 'jus/FutureBase.h',
'jus/Future.h', 'jus/Future.h',
'jus/File.h',
'jus/ParamType.h', 'jus/ParamType.h',
'jus/debug.h', 'jus/debug.h',
'jus/Client.h', 'jus/Client.h',

View File

@ -145,6 +145,10 @@ int main(int _argc, const char *_argv[]) {
jus::Future<uint32_t> retCount = remoteServicePicture.call("getAlbumCount", it).wait(); jus::Future<uint32_t> retCount = remoteServicePicture.call("getAlbumCount", it).wait();
if (retCount.get() != 0) { if (retCount.get() != 0) {
APPL_INFO(" - " << it << " / " << retCount.get() << " images"); APPL_INFO(" - " << it << " / " << retCount.get() << " images");
jus::Future<std::vector<std::string>> retListImage = remoteServicePicture.call("getAlbumListPicture", it).wait();
for (auto &it3 : retListImage.get()) {
APPL_INFO(" - " << it3);
}
} else { } else {
APPL_INFO(" - " << it); APPL_INFO(" - " << it);
} }
@ -153,6 +157,14 @@ int main(int _argc, const char *_argv[]) {
jus::Future<uint32_t> retCount2 = remoteServicePicture.call("getAlbumCount", it2).wait(); jus::Future<uint32_t> retCount2 = remoteServicePicture.call("getAlbumCount", it2).wait();
if (retCount2.get() != 0) { if (retCount2.get() != 0) {
APPL_INFO(" - " << it2 << " / " << retCount2.get() << " images"); APPL_INFO(" - " << it2 << " / " << retCount2.get() << " images");
jus::Future<std::vector<std::string>> retListImage = remoteServicePicture.call("getAlbumListPicture", it2).wait();
for (auto &it3 : retListImage.get()) {
APPL_INFO(" - " << it3);
jus::Future<jus::File> retListImage = remoteServicePicture.call("getAlbumPicture", it3).wait();
jus::File tmpFile = retListImage.get();
APPL_INFO(" mine-type: " << tmpFile.getMineType());
APPL_INFO(" size: " << tmpFile.getData().size());
}
} else { } else {
APPL_INFO(" - " << it2); APPL_INFO(" - " << it2);
} }

View File

@ -6,6 +6,7 @@
#include <appl/debug.h> #include <appl/debug.h>
#include <jus/Service.h> #include <jus/Service.h>
#include <jus/File.h>
#include <etk/etk.h> #include <etk/etk.h>
#include <unistd.h> #include <unistd.h>
#include <mutex> #include <mutex>
@ -19,46 +20,23 @@ namespace appl {
std::mutex m_mutex; std::mutex m_mutex;
std::string m_userName; std::string m_userName;
std::string m_basePath; std::string m_basePath;
ejson::Document m_database;
std::map<uint64_t,std::string> m_listFile;
public: public:
User(const std::string& _userName) : User(const std::string& _userName) :
m_userName(_userName) { m_userName(_userName) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("new USER: " << m_userName); APPL_WARNING("new USER: " << m_userName << " [START]");
m_basePath = std::string("USERDATA:") + m_userName + "/"; m_basePath = std::string("USERDATA:") + m_userName + "/";
APPL_WARNING("new USER: " << m_userName);
bool ret = m_database.load(m_basePath + "database.json");
if (ret == false) {
APPL_WARNING(" ==> LOAD error");
} }
~User() { // Load all files (image and video ...)
std::unique_lock<std::mutex> lock(m_mutex); etk::FSNode node(m_basePath);
APPL_WARNING("delete USER [START]");
APPL_WARNING("delete USER [STOP]");
}
// Return the list of root albums
std::vector<std::string> getAlbums() {
return getSubAlbums("");
}
// Get the list of sub album
std::vector<std::string> getSubAlbums(const std::string& _parrentAlbum) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
etk::FSNode node(m_basePath + _parrentAlbum);
std::vector<etk::FSNode*> tmpList = node.folderGetSubList(false, true, false, false);
for (auto &it : tmpList) {
if (it == nullptr) {
continue;
}
if ( _parrentAlbum.size() == 0
|| _parrentAlbum[_parrentAlbum.size()-1] == '/') {
out.push_back(_parrentAlbum + it->getNameFile());
} else {
out.push_back(_parrentAlbum + "/" + it->getNameFile());
}
}
return out;
}
uint32_t getAlbumCount(const std::string& _album) {
std::unique_lock<std::mutex> lock(m_mutex);
etk::FSNode node(m_basePath + _album);
std::vector<etk::FSNode*> tmpList = node.folderGetSubList(false, false, true, false); std::vector<etk::FSNode*> tmpList = node.folderGetSubList(false, false, true, false);
uint32_t nbElem = 0; APPL_WARNING("Find " << tmpList.size() << " files");
for (auto &it : tmpList) { for (auto &it : tmpList) {
if (it == nullptr) { if (it == nullptr) {
continue; continue;
@ -66,24 +44,163 @@ namespace appl {
if ( etk::end_with(it->getNameFile(), ".svg", false) == true if ( etk::end_with(it->getNameFile(), ".svg", false) == true
|| etk::end_with(it->getNameFile(), ".bmp", false) == true || etk::end_with(it->getNameFile(), ".bmp", false) == true
|| etk::end_with(it->getNameFile(), ".png", false) == true || etk::end_with(it->getNameFile(), ".png", false) == true
|| etk::end_with(it->getNameFile(), ".jpg", false) == true) { || etk::end_with(it->getNameFile(), ".jpg", false) == true
nbElem++; || etk::end_with(it->getNameFile(), ".tga", false) == true
|| etk::end_with(it->getNameFile(), ".mp4", false) == true
|| etk::end_with(it->getNameFile(), ".avi", false) == true
|| etk::end_with(it->getNameFile(), ".mov", false) == true
|| etk::end_with(it->getNameFile(), ".mkv", false) == true) {
// TODO : Do it better (proto ..)
std::string idString = it->getNameFile();
idString.resize(idString.size()-4);
uint64_t id = 0;
std::stringstream ss;
ss << std::hex << idString;
ss >> id;
if (id <= 1024) {
APPL_WARNING(" ==> REJECTED file " << it->getNameFile() << " with ID = " << id);
} else {
m_listFile.insert(std::make_pair(id, it->getNameFile()));
APPL_WARNING(" ==> load file " << it->getNameFile() << " with ID = " << id);
}
} else {
APPL_WARNING(" ==> REJECT file " << it->getNameFile());
} }
} }
return nbElem; APPL_WARNING("new USER: " << m_userName << " [STOP]");
} }
// Return the list of the album files ~User() {
std::vector<std::string> getAlbumListPicture(const std::string& _album, uint32_t _startId, uint32_t _stopId) { std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("delete USER [START]");
APPL_DEBUG("Store User Info:");
bool ret = m_database.storeSafe(m_basePath + "database.json");
if (ret == false) {
APPL_WARNING(" ==> Store error");
}
APPL_WARNING("delete USER [STOP]");
}
// Return the list of root albums
std::vector<std::string> getAlbums() {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out; std::vector<std::string> out;
ejson::Array globalGroups = m_database["group-global"].toArray();
if (globalGroups.exist() == false) {
return out;
}
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return out;
}
for (auto it: globalGroups) {
std::string tmpString = it.toString().get();
if (tmpString == "") {
continue;
}
out.push_back(tmpString);
}
return out;
/*
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return std::vector<std::string>(); return std::vector<std::string>();
} }
/* groups
// Return a File Data (might be a picture .tiff/.png/.jpg) return getSubAlbums("");
jus::File getAlbumPicture(const std::string& _pictureName) { */
std::unique_lock<std::mutex> lock(m_mutex);
return jus::File();
} }
// Get the list of sub album
std::vector<std::string> getSubAlbums(const std::string& _album) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
return out;
}
// find parrentAlbum ==> to get sub group
/*
for (size_t iii=0; iii<groups.size(); ++iii) {
//ejson::Object group = groups[iii].toObject()["sub"];
if (groups.getKey(iii) != _parrentAlbum) {
continue;
}
}
*/
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
return out;
}
ejson::Array groupSubs = group["sub"].toArray();
for (auto it: groupSubs) {
std::string tmpString = it.toString().get();
if (tmpString == "") {
continue;
}
out.push_back(tmpString);
}
// TODO: Check right
return out;
}
uint32_t getAlbumCount(const std::string& _album) {
std::unique_lock<std::mutex> lock(m_mutex);
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
// TODO : Throw an error ...
return 0;
}
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
// TODO : Throw an error ...
return 0;
}
ejson::Array groupSubs = group["files"].toArray();
// TODO: Check right
return groupSubs.size();
/*
for (auto it: groupSubs) {
uint64_t id = it.toNumber().getU64();
if (id == 0) {
continue;
}
out.push_back(id);
}
*/
}
// Return the list of the album files
std::vector<std::string> getAlbumListPicture(const std::string& _album) {//, uint32_t _startId, uint32_t _stopId) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Object groups = m_database["groups"].toObject();
if (groups.exist() == false) {
// TODO : Throw an error ...
return out;
}
ejson::Object group = groups[_album].toObject();
if (group.exist() == false) {
// TODO : Throw an error ...
return out;
}
ejson::Array groupSubs = group["files"].toArray();
for (auto it: groupSubs) {
uint64_t id = it.toNumber().getU64();
/*
auto itImage = m_listFile.find(id);
if (itImage == m_listFile.end()) {
}*/
if (id == 0) {
continue;
}
out.push_back(etk::to_string(id));
}
return out;
}
// Return a File Data (might be a picture .tiff/.png/.jpg)
jus::FileServer getAlbumPicture(const std::string& _pictureName) {
std::unique_lock<std::mutex> lock(m_mutex);
return jus::FileServer();
}
/*
// Return a global UTC time // Return a global UTC time
jus::Time getAlbumPictureTime(const std::string& _pictureName) { jus::Time getAlbumPictureTime(const std::string& _pictureName) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
@ -94,6 +211,11 @@ namespace appl {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
return jus::Geo(); return jus::Geo();
} }
jus::FileId addElement(const jus::File& _file) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
return std::vector<std::string>();
}
*/ */
}; };
@ -148,14 +270,14 @@ namespace appl {
return m_user->getAlbumCount(_album); return m_user->getAlbumCount(_album);
} }
// Return the list of the album files // Return the list of the album files
std::vector<std::string> getAlbumListPicture(std::string _album, uint32_t _startId, uint32_t _stopId) { std::vector<std::string> getAlbumListPicture(std::string _album) {//, uint32_t _startId, uint32_t _stopId) {
return m_user->getAlbumListPicture(_album, _startId, _stopId); return m_user->getAlbumListPicture(_album);//, _startId, _stopId);
} }
/*
// Return a File Data (might be a picture .tiff/.png/.jpg) // Return a File Data (might be a picture .tiff/.png/.jpg)
jus::File getAlbumPicture(std::string _pictureName) { jus::FileServer getAlbumPicture(std::string _pictureName) {
return m_user->getAlbumPicture(_pictureName); return m_user->getAlbumPicture(_pictureName);
} }
/*
// Return a global UTC time // Return a global UTC time
jus::Time getAlbumPictureTime(std::string _pictureName) { jus::Time getAlbumPictureTime(std::string _pictureName) {
return m_user->getAlbumPictureTime(_pictureName); return m_user->getAlbumPictureTime(_pictureName);
@ -209,6 +331,7 @@ int main(int _argc, const char *_argv[]) {
serviceInterface.advertise("getSubAlbums", &appl::PictureService::getSubAlbums); serviceInterface.advertise("getSubAlbums", &appl::PictureService::getSubAlbums);
serviceInterface.advertise("getAlbumCount", &appl::PictureService::getAlbumCount); serviceInterface.advertise("getAlbumCount", &appl::PictureService::getAlbumCount);
serviceInterface.advertise("getAlbumListPicture", &appl::PictureService::getAlbumListPicture); serviceInterface.advertise("getAlbumListPicture", &appl::PictureService::getAlbumListPicture);
serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture);
/* /*
serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture); serviceInterface.advertise("getAlbumPicture", &appl::PictureService::getAlbumPicture);
serviceInterface.advertise("getAlbumPictureTime", &appl::PictureService::getAlbumPictureTime); serviceInterface.advertise("getAlbumPictureTime", &appl::PictureService::getAlbumPictureTime);