[DEV] binary transmission step 1 ==> OK

This commit is contained in:
Edouard DUPIN 2016-06-14 21:28:54 +02:00
parent bb3858625f
commit 8aa9c0ea0d
20 changed files with 532 additions and 1101 deletions

View File

@ -181,8 +181,7 @@ namespace jus {
answer.add("data", ejson::String(ejson::base64::encode(&m_data.getData()[m_offset], tmpSize))); answer.add("data", ejson::String(ejson::base64::encode(&m_data.getData()[m_offset], tmpSize)));
m_offset += tmpSize; m_offset += tmpSize;
m_size -= tmpSize; m_size -= tmpSize;
JUS_INFO("data: " << answer.generateHumanString()); _interface->writeJson(answer);
_interface->write(answer.generateMachineString());
if (m_size <= 0) { if (m_size <= 0) {
return true; return true;
} }
@ -355,9 +354,11 @@ jus::AbstractFunction::AbstractFunction(const std::string& _name,
m_description(_desc) { m_description(_desc) {
} }
bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejson::Value& _params) {
bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) {
if (createType<bool>() == _type) { if (createType<bool>() == _type) {
return _params.isBoolean(); return _params == "bool";
} }
if ( createType<int64_t>() == _type if ( createType<int64_t>() == _type
|| createType<int32_t>() == _type || createType<int32_t>() == _type
@ -369,10 +370,19 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs
|| createType<uint8_t>() == _type || createType<uint8_t>() == _type
|| createType<float>() == _type || createType<float>() == _type
|| createType<double>() == _type) { || createType<double>() == _type) {
return _params.isNumber(); return _params == "int8"
|| _params == "int16"
|| _params == "int32"
|| _params == "int64"
|| _params == "uint8"
|| _params == "uint16"
|| _params == "uint32"
|| _params == "uint64"
|| _params == "float"
|| _params == "double";
} }
if (createType<std::vector<std::string>>() == _type) { if (createType<std::vector<std::string>>() == _type) {
return _params.isArray(); return _params == "vector:string";
} }
if ( createType<std::vector<bool>>() == _type if ( createType<std::vector<bool>>() == _type
|| createType<std::vector<int64_t>>() == _type || createType<std::vector<int64_t>>() == _type
@ -385,25 +395,30 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs
|| createType<std::vector<uint8_t>>() == _type || createType<std::vector<uint8_t>>() == _type
|| createType<std::vector<float>>() == _type || createType<std::vector<float>>() == _type
|| createType<std::vector<double>>() == _type) { || createType<std::vector<double>>() == _type) {
if (_params.isObject()) { return _params == "vector:int8"
JUS_TODO("Special case of packaging of the data"); || _params == "vector:int16"
return false; || _params == "vector:int32"
} || _params == "vector:int64"
return _params.isArray(); || _params == "vector:uint8"
|| _params == "vector:uint16"
|| _params == "vector:uint32"
|| _params == "vector:uint64"
|| _params == "vector:float"
|| _params == "vector:double"
|| _params == "vector:empty";
} }
if (createType<jus::File>() == _type) { if (createType<jus::File>() == _type) {
/*
if (_params.isObject()) { if (_params.isObject()) {
if (_params.toObject()["type"].toString().get() == "file") { if (_params.toObject()["type"].toString().get() == "file") {
return true; return true;
} }
} }
*/
return false; return false;
} }
if (createType<std::string>() == _type) { if (createType<std::string>() == _type) {
return _params.isString(); return _params == "string";
} }
return false; return false;
} }
bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const std::string& _params) {
return false;
}

View File

@ -4,13 +4,22 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#pragma once #pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h> #include <eproperty/Value.h>
#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> #include <jus/File.h>
#include <jus/Buffer.h>
namespace jus {
class TcpString;
// define basic async call element ...
using ActionAsyncClient = std::function<bool(TcpString* _interface, const uint32_t& _serviceId, uint64_t _transactionId, uint64_t _part)>;
}
namespace jus { namespace jus {
class AbstractFunction { class AbstractFunction {
public: public:
@ -49,19 +58,15 @@ namespace jus {
public: public:
virtual ~AbstractFunction() {}; virtual ~AbstractFunction() {};
public: public:
bool checkCompatibility(const ParamType& _type, const ejson::Value& _params);
bool checkCompatibility(const ParamType& _type, const std::string& _params); bool checkCompatibility(const ParamType& _type, const std::string& _params);
public: public:
std::string getPrototypeFull() const; std::string getPrototypeFull() const;
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 void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, const ejson::Array& _params, void* _class=nullptr) = 0; virtual void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, uint64_t _transactionId, uint64_t _clientId, jus::Buffer& _params, void* _class=nullptr) = 0;
virtual std::string executeString(const std::vector<std::string>& _params, void* _class=nullptr) = 0;
}; };
// define basic async call element ...
using ActionAsyncClient = std::function<bool(TcpString* _interface, const uint32_t& _serviceId, uint64_t _transactionId, uint64_t _part)>;
template<class JUS_TYPE> template<class JUS_TYPE>
JUS_TYPE convertStringTo(const std::string& _value); JUS_TYPE convertStringTo(const std::string& _value);
@ -164,3 +169,5 @@ namespace jus {
} }
#include <jus/TcpString.h>

View File

@ -17,36 +17,35 @@
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>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId, uint64_t _transactionId,
uint64_t _clientId, uint64_t _clientId,
JUS_CLASS_TYPE* _pointer, JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) { jus::Buffer& _obj) {
std::vector<ActionAsyncClient> asyncAction; std::vector<ActionAsyncClient> asyncAction;
#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;
ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...)); JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(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;
ejson::Value ret = convertToJson(asyncAction, -1, (*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...)); JUS_RETURN ret = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else #else
#error Must be implemented ... #error Must be implemented ...
ejson::Value ret = ejson::Null(); JUS_RETURN ret;
return; return;
#endif #endif
if (asyncAction.size() != 0) { if (asyncAction.size() != 0) {
JUS_ERROR("Missing send async messages"); JUS_ERROR("Missing send async messages");
} }
ejson::Object answer; _interfaceClient->addAsync([=](TcpString* _interface) {
answer.add("id", ejson::Number(_transactionId)); _interface->answerValue(_transactionId, ret, _clientId);
answer.add("client-id", ejson::Number(_clientId)); return true;
answer.add("return", ret); });
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
} }
/*
class SendFile { class SendFile {
private: private:
jus::FileServer m_data; jus::FileServer m_data;
@ -112,20 +111,20 @@ namespace jus {
} }
}; };
template <class JUS_CLASS_TYPE, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId, uint64_t _transactionId,
uint64_t _clientId, uint64_t _clientId,
JUS_CLASS_TYPE* _pointer, JUS_CLASS_TYPE* _pointer,
jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) { jus::Buffer& _obj) {
#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;
jus::FileServer tmpElem = (*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...); jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(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;
jus::FileServer tmpElem = (*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...); jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else #else
#error Must be implemented ... #error Must be implemented ...
jus::FileServer tmpElem; jus::FileServer tmpElem;
@ -133,70 +132,31 @@ namespace jus {
#endif #endif
_interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId)); _interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId));
} }
*/
template <class JUS_CLASS_TYPE, class... JUS_TYPES> template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId, uint64_t _transactionId,
uint64_t _clientId, uint64_t _clientId,
JUS_CLASS_TYPE* _pointer, JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...), void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) { jus::Buffer& _obj) {
ejson::Object out;
#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;
(*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...); (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(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;
(*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...); (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else #else
#error Must be implemented ... #error Must be implemented ...
ejson::Value ret = ejson::Null();
return; return;
#endif #endif
ejson::Object answer; _interfaceClient->addAsync([=](TcpString* _interface) {
answer.add("id", ejson::Number(_transactionId)); _interface->answerVoid(_transactionId, _clientId);
answer.add("client-id", ejson::Number(_clientId)); return true;
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>
std::string executeClassCallString(JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const std::vector<std::string>& _params) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
return etk::to_string((*_pointer.*_func)((convertStringTo<JUS_TYPES>(_params[idParam++]))...));
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
return etk::to_string((*_pointer.*_func)(convertStringTo<JUS_TYPES>(_params[idParam--])...));
#else
#error Must be implemented ...
#endif
return "";
}
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) {
ejson::Object out;
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
(*_pointer.*_func)((convertStringTo<JUS_TYPES>(_params[idParam++]))...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
(*_pointer.*_func)(convertStringTo<JUS_TYPES>(_params[idParam--])...);
#else
#error Must be implemented ...
#endif
return "";
} }
template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES> template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES>
@ -236,76 +196,43 @@ namespace jus {
} }
return out; return out;
} }
void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient, void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId, uint64_t _transactionId,
uint64_t _clientId, uint64_t _clientId,
const ejson::Array& _params, jus::Buffer& _obj,
void* _class) override { 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;
} }
// check parameter number // check parameter number
if (_params.size() != sizeof...(JUS_TYPES)) { if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) {
JUS_ERROR("Wrong number of Parameters ..."); JUS_ERROR("Wrong number of Parameters ...");
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-NUMBER"));
std::string help = "request "; std::string help = "request ";
help += etk::to_string(_params.size()); help += etk::to_string(_obj.getNumberParameter());
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();
answer.add("error-help", ejson::String(help)); _interfaceClient->answerError(_transactionId,
JUS_INFO("Answer: " << answer.generateHumanString()); "WRONG-PARAMETER-NUMBER",
_interfaceClient->write(answer.generateMachineString()); help,
_clientId);
return; 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], _obj.getParameterType(iii)) == false) {
ejson::Object answer; _interfaceClient->answerError(_transactionId,
answer.add("id", ejson::Number(_transactionId)); "WRONG-PARAMETER-TYPE",
answer.add("client-id", ejson::Number(_clientId)); std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'",
answer.add("error", ejson::String("WRONG-PARAMETER-TYPE")); _clientId);
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; return;
} }
} }
// execute cmd: // execute cmd:
jus::executeClassCallJson(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _params); jus::executeClassCall(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _obj);
}
std::string executeString(const std::vector<std::string>& _params, void* _class) override {
JUS_CLASS_TYPE* tmpClass = (JUS_CLASS_TYPE*)_class;
std::string out;
// check parameter number
if (_params.size() != sizeof...(JUS_TYPES)) {
JUS_ERROR("Wrong number of Parameters ...");
out += "error:WRONG-PARAMETER-NUMBER;";
out += "error-help:request ";
out += etk::to_string(_params.size());
out += " parameters and need ";
out += etk::to_string(sizeof...(JUS_TYPES));
out += " parameters. prototype function:";
out += getPrototype();
return out;
}
// check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _params[iii]) == false) {
out += "error:WRONG-PARAMETER-TYPE;";
out += "error-help:Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'";
return out;
}
}
// execute cmd:
out = jus::executeClassCallString(tmpClass, m_function, _params);
return out;
} }
}; };

View File

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

View File

@ -60,19 +60,19 @@ void jus::Buffer::internalComposeWith(const uint8_t* _buffer, uint32_t _lenght)
} else { } else {
// TODO : check size ... // TODO : check size ...
} }
JUS_INFO("Get binary messages " << generateHumanString()); JUS_DEBUG("Get binary messages " << generateHumanString());
} }
void jus::Buffer::composeWith(const std::vector<uint8_t>& _buffer) { void jus::Buffer::composeWith(const std::vector<uint8_t>& _buffer) {
internalComposeWith(&_buffer[0], _buffer.size()); internalComposeWith(&_buffer[0], _buffer.size());
} }
void jus::Buffer::composeWith(const std::string& _buffer) { void jus::Buffer::composeWith(const std::string& _buffer) {
internalComposeWith(reinterpret_cast<const uint8_t*>(&_buffer[0]), _buffer.size()); fromJson(ejson::Object(_buffer));
} }
void jus::Buffer::clear() { void jus::Buffer::clear() {
JUS_WARNING("clear buffer"); JUS_VERBOSE("clear buffer");
m_data.clear(); m_data.clear();
m_paramOffset.clear(); m_paramOffset.clear();
m_header.lenght = 0; m_header.lenght = 0;
@ -131,7 +131,7 @@ uint16_t jus::Buffer::getProtocalVersion() const {
} }
void jus::Buffer::setProtocolVersion(uint16_t _value) { void jus::Buffer::setProtocolVersion(uint16_t _value) {
JUS_WARNING("setProtocolVersion :" << _value); JUS_VERBOSE("setProtocolVersion :" << _value);
m_header.versionProtocol = _value; m_header.versionProtocol = _value;
} }
@ -140,7 +140,7 @@ uint32_t jus::Buffer::getTransactionId() const {
} }
void jus::Buffer::setTransactionId(uint32_t _value) { void jus::Buffer::setTransactionId(uint32_t _value) {
JUS_WARNING("setTransactionId :" << _value); JUS_VERBOSE("setTransactionId :" << _value);
m_header.transactionID = _value; m_header.transactionID = _value;
} }
@ -149,7 +149,7 @@ uint32_t jus::Buffer::getClientId() const {
} }
void jus::Buffer::setClientId(uint32_t _value) { void jus::Buffer::setClientId(uint32_t _value) {
JUS_WARNING("setClientId :" << _value); JUS_VERBOSE("setClientId :" << _value);
m_header.clientID = _value; m_header.clientID = _value;
} }
@ -159,7 +159,7 @@ uint16_t jus::Buffer::getPartId() const {
} }
void jus::Buffer::setPartId(uint16_t _value) { void jus::Buffer::setPartId(uint16_t _value) {
JUS_WARNING("setPartId :" << _value); JUS_VERBOSE("setPartId :" << _value);
m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF); m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF);
} }
@ -168,7 +168,7 @@ bool jus::Buffer::getPartFinish() const {
} }
void jus::Buffer::setPartFinish(bool _value) { void jus::Buffer::setPartFinish(bool _value) {
JUS_WARNING("setPartFinish :" << _value); JUS_VERBOSE("setPartFinish :" << _value);
if (_value == true) { if (_value == true) {
m_header.partID = (m_header.partID & 0x7FFF) | 0x8000; m_header.partID = (m_header.partID & 0x7FFF) | 0x8000;
} else { } else {
@ -181,7 +181,7 @@ enum jus::Buffer::typeMessage jus::Buffer::getType() const {
} }
void jus::Buffer::setType(enum typeMessage _value) { void jus::Buffer::setType(enum typeMessage _value) {
JUS_WARNING("setType :" << _value); JUS_VERBOSE("setType :" << _value);
m_header.typeMessage = uint16_t(_value); m_header.typeMessage = uint16_t(_value);
} }
@ -2154,19 +2154,6 @@ std::vector<std::string> jus::Buffer::internalGetParameter<std::vector<std::stri
pointer += out[iii].size() + 1; pointer += out[iii].size() + 1;
JUS_DEBUG(" value: '" << out[iii] << "'"); JUS_DEBUG(" value: '" << out[iii] << "'");
} }
// TODO : ...
JUS_TODO("parse list of string ...");
/*
const uint8_t* tmp = reinterpret_cast<const uint8_t*>(pointer);
int32_t nbElement = dataSize / sizeof(uint8_t);
out.resize(nbElement);
for (size_t iii=0; iii<nbElement; ++iii) {
out[iii] = tmp[iii] == 'T';
}
*/
return out; return out;
} }
JUS_ERROR("Can not get type from '" << type << "'"); JUS_ERROR("Can not get type from '" << type << "'");
@ -2360,11 +2347,6 @@ ejson::Object jus::Buffer::toJson() const {
return out; return out;
} }
// TODO : Add protocl ERROR ...
void jus::Buffer::fromJson(const std::string& _data) {
return fromJson(ejson::Object(_data));
}
void jus::Buffer::fromJson(const ejson::Object& _data) { void jus::Buffer::fromJson(const ejson::Object& _data) {
clear(); clear();
uint32_t valueClientId = 0; uint32_t valueClientId = 0;

View File

@ -192,7 +192,6 @@ namespace jus {
void prepare(); void prepare();
ejson::Object toJson() const; ejson::Object toJson() const;
void fromJson(const ejson::Object& _data); void fromJson(const ejson::Object& _data);
void fromJson(const std::string& _data);
}; };
std::ostream& operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value); std::ostream& operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value);

View File

@ -13,7 +13,6 @@
jus::Client::Client() : jus::Client::Client() :
propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Client::onPropertyChangeIp), propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Client::onPropertyChangeIp),
propertyPort(this, "port", 1983, "Port to connect server", &jus::Client::onPropertyChangePort), propertyPort(this, "port", 1983, "Port to connect server", &jus::Client::onPropertyChangePort),
m_interfaceMode(jus::connectionMode::modeJson),
m_id(1) { m_id(1) {
m_interfaceClient.connect(this, &jus::Client::onClientData); m_interfaceClient.connect(this, &jus::Client::onClientData);
} }
@ -22,7 +21,7 @@ jus::Client::~Client() {
} }
void jus::Client::onClientDataRaw(jus::Buffer& _value) { void jus::Client::onClientData(jus::Buffer& _value) {
JUS_DEBUG("Get answer RAW : "/* << _value*/); JUS_DEBUG("Get answer RAW : "/* << _value*/);
jus::FutureBase future; jus::FutureBase future;
uint64_t tid = _value.getTransactionId(); uint64_t tid = _value.getTransactionId();
@ -85,67 +84,6 @@ void jus::Client::onClientDataRaw(jus::Buffer& _value) {
} }
} }
void jus::Client::onClientData(std::string _value) {
JUS_DEBUG("Get answer : " << _value);
ejson::Object obj(_value);
jus::FutureBase future;
uint64_t tid = obj["id"].toNumber().get();
if (tid == 0) {
if (obj["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &it : m_pendingCall) {
if (it.isValid() == false) {
continue;
}
it.setAnswer(obj);
}
m_pendingCall.clear();
} else {
JUS_ERROR("call with no ID ==> error ...");
}
return;
}
{
std::unique_lock<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;
}
future = *it;
break;
}
}
if (future.isValid() == false) {
JUS_TODO("manage this event better ...");
//m_newData.push_back(std::move(_value));
return;
}
bool ret = future.setAnswer(obj);
if (ret == true) {
std::unique_lock<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;
}
}
}
jus::ServiceRemote jus::Client::getService(const std::string& _name) { jus::ServiceRemote jus::Client::getService(const std::string& _name) {
return jus::ServiceRemote(this, _name); return jus::ServiceRemote(this, _name);
} }
@ -171,29 +109,6 @@ bool jus::Client::unlink(const uint32_t& _serviceId) {
return ret.get(); return ret.get();
} }
std::string jus::Client::asyncRead() {
if (m_interfaceClient.isActive() == false) {
return "";
}
int32_t iii = 5000;
while (iii>0) {
usleep(10000);
if (m_newData.size() != 0) {
break;
}
--iii;
}
if (iii == 0) {
// Time-out ...
return "";
}
std::string out;
out = std::move(m_newData[0]);
m_newData.erase(m_newData.begin());
JUS_DEBUG("get async data: " << out);
return out;
}
void jus::Client::onPropertyChangeIp() { void jus::Client::onPropertyChangeIp() {
disconnect(); disconnect();
} }
@ -214,9 +129,7 @@ bool jus::Client::connect(const std::string& _remoteUserToConnect){
jus::Future<bool> retBin = call("setMode", "BIN").wait(); jus::Future<bool> retBin = call("setMode", "BIN").wait();
if (retBin.get() == true) { if (retBin.get() == true) {
JUS_WARNING(" ==> accepted binary"); JUS_WARNING(" ==> accepted binary");
m_interfaceMode = jus::connectionMode::modeBinary; m_interfaceClient.setMode(jus::connectionMode::modeBinary);
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::Client::onClientDataRaw);
JUS_INFO("Connection jump in BINARY ..."); JUS_INFO("Connection jump in BINARY ...");
} else { } else {
// stay in JSON // stay in JSON
@ -281,8 +194,7 @@ class SendAsyncJson {
obj.add("id", ejson::Number(m_transactionId)); obj.add("id", ejson::Number(m_transactionId));
obj.add("part", ejson::Number(m_partId)); obj.add("part", ejson::Number(m_partId));
obj.add("finish", ejson::Boolean(true)); obj.add("finish", ejson::Boolean(true));
JUS_DEBUG("Send JSON '" << obj.generateHumanString() << "'"); _interface->writeJson(obj);
_interface->write(obj.generateMachineString());
return true; return true;
} }
return false; return false;
@ -309,8 +221,7 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId,
if (_async.size() != 0) { if (_async.size() != 0) {
_obj.add("part", ejson::Number(0)); _obj.add("part", ejson::Number(0));
} }
JUS_DEBUG("Send JSON '" << _obj.generateHumanString() << "'"); m_interfaceClient.writeJson(_obj);
m_interfaceClient.write(_obj.generateMachineString());
if (_async.size() != 0) { if (_async.size() != 0) {
m_interfaceClient.addAsync(SendAsyncJson(_transactionId, _serviceId, _async)); m_interfaceClient.addAsync(SendAsyncJson(_transactionId, _serviceId, _async));

View File

@ -23,10 +23,8 @@ namespace jus {
eproperty::Value<uint16_t> propertyPort; eproperty::Value<uint16_t> propertyPort;
std::mutex m_mutex; std::mutex m_mutex;
std::vector<jus::FutureBase> m_pendingCall; std::vector<jus::FutureBase> m_pendingCall;
protected:
enum jus::connectionMode m_interfaceMode;
public: public:
enum jus::connectionMode getMode() { return m_interfaceMode; } enum jus::connectionMode getMode() { return m_interfaceClient.getMode(); }
private: private:
jus::TcpString m_interfaceClient; jus::TcpString m_interfaceClient;
uint32_t m_id; uint32_t m_id;
@ -46,9 +44,7 @@ namespace jus {
// Connect to ourself: // Connect to ourself:
//client1.authentificate("coucou"); //client1.authentificate("coucou");
private: private:
void onClientData(std::string _value); void onClientData(jus::Buffer& _value);
void onClientDataRaw(jus::Buffer& _value);
std::string asyncRead();
jus::FutureBase callJson(uint64_t _transactionId, jus::FutureBase callJson(uint64_t _transactionId,
ejson::Object _obj, ejson::Object _obj,
const std::vector<ActionAsyncClient>& _async, const std::vector<ActionAsyncClient>& _async,

View File

@ -93,6 +93,7 @@ bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
tmp.fromJson(_returnValue); tmp.fromJson(_returnValue);
return setAnswer(tmp); return setAnswer(tmp);
} }
bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) { bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) {
if (m_data == nullptr) { if (m_data == nullptr) {
JUS_ERROR(" Not a valid future ..."); JUS_ERROR(" Not a valid future ...");
@ -208,51 +209,17 @@ jus::FutureBase& jus::FutureBase::waitUntil(std::chrono::steady_clock::time_poin
} }
jus::FutureCall::FutureCall(uint64_t _clientId, uint64_t _transactionId, const ejson::Object& _callValue) : jus::FutureCall::FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue) :
m_transactionId(_transactionId), m_transactionId(_transactionId),
m_clientId(_clientId), m_clientId(_clientId),
m_isFinished(false) { m_isFinished(false) {
m_data = _callValue; m_data = _callValue;
if (m_data.valueExist("part") == true) { m_isFinished = m_data.getPartFinish();
if (m_data.valueExist("finish") == true) {
if (m_data["finish"].toBoolean().get() == true) {
m_isFinished = true;
}
}
} else {
m_isFinished = true;
}
} }
void jus::FutureCall::appendData(const ejson::Object& _callValue) { void jus::FutureCall::appendData(jus::Buffer& _callValue) {
uint64_t paramID = _callValue["param-id"].toNumber().getU64(); m_dataMultiplePack.push_back(_callValue);
// get the previous element parameters m_isFinished = _callValue.getPartFinish();
ejson::Array params = m_data["param"].toArray();
if (params.exist() == false) {
JUS_ERROR("try to add element on an inexistand parameter ...==> bad case");
m_isFinished = true;
return;
}
// Get the specific parameter
ejson::Object param = params[paramID].toObject();
if (param.exist() == false) {
JUS_ERROR("the parameter is not an object ==> bad case");
m_isFinished = true;
return;
}
// check if section data
if (param.valueExist("data") == false) {
param.add("data", ejson::Array());
}
// add data in the array (only if we have local data ...
if (_callValue.valueExist("data") == true) {
param["data"].toArray().add(_callValue["data"]);
}
if (_callValue.valueExist("finish") == true) {
if (_callValue["finish"].toBoolean().get() == true) {
m_isFinished = true;
}
}
} }
uint64_t jus::FutureCall::getTransactionId() { uint64_t jus::FutureCall::getTransactionId() {
@ -267,7 +234,7 @@ bool jus::FutureCall::isFinished() {
return m_isFinished; return m_isFinished;
} }
ejson::Object jus::FutureCall::getRaw() { jus::Buffer& jus::FutureCall::getRaw() {
return m_data; return m_data;
} }

View File

@ -38,17 +38,18 @@ namespace jus {
uint64_t m_transactionId; uint64_t m_transactionId;
uint64_t m_clientId; uint64_t m_clientId;
bool m_isFinished; bool m_isFinished;
ejson::Object m_data; jus::Buffer m_data;
std::vector<jus::Buffer> m_dataMultiplePack;
std::chrono::steady_clock::time_point m_receiveTime; std::chrono::steady_clock::time_point m_receiveTime;
std::chrono::steady_clock::time_point m_answerTime; std::chrono::steady_clock::time_point m_answerTime;
public: public:
FutureCall(uint64_t _clientId, uint64_t _transactionId, const ejson::Object& _callValue); FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue);
void appendData(const ejson::Object& _callValue); void appendData(jus::Buffer& _callValue);
uint64_t getTransactionId(); uint64_t getTransactionId();
uint64_t getClientId(); uint64_t getClientId();
bool isFinished(); bool isFinished();
std::chrono::nanoseconds getTransmitionTime(); std::chrono::nanoseconds getTransmitionTime();
ejson::Object getRaw(); jus::Buffer& getRaw();
}; };
} }

View File

@ -129,7 +129,7 @@ std::vector<std::string> jus::GateWay::getAllServiceName() {
} }
void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) { void jus::GateWay::answer(uint64_t _userSessionId, jus::Buffer& _data) {
for (auto &it : m_clientList) { for (auto &it : m_clientList) {
if (it == nullptr) { if (it == nullptr) {
continue; continue;

View File

@ -33,7 +33,7 @@ namespace jus {
void stop(); void stop();
ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName); ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName);
std::vector<std::string> getAllServiceName(); std::vector<std::string> getAllServiceName();
void answer(uint64_t _userSessionId, ejson::Object _data); void answer(uint64_t _userSessionId, jus::Buffer& _data);
void newService(enet::Tcp _connection); void newService(enet::Tcp _connection);
void newClient(enet::Tcp _connection); void newClient(enet::Tcp _connection);
void cleanIO(); void cleanIO();

View File

@ -19,7 +19,6 @@ jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayI
m_state(jus::GateWayClient::state::unconnect), m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface), m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)), m_interfaceClient(std::move(_connection)),
m_interfaceMode(jus::connectionMode::modeJson),
m_transactionLocalId(1) { m_transactionLocalId(1) {
JUS_INFO("----------------"); JUS_INFO("----------------");
JUS_INFO("-- NEW Client --"); JUS_INFO("-- NEW Client --");
@ -71,42 +70,13 @@ bool jus::GateWayClient::isAlive() {
} }
void jus::GateWayClient::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) { void jus::GateWayClient::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) {
answerError(_transactionId, protocolError, _errorHelp); m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp);
m_state = jus::GateWayClient::state::disconnect; m_state = jus::GateWayClient::state::disconnect;
m_interfaceClient.disconnect(true); m_interfaceClient.disconnect(true);
} }
/*
void jus::GateWayClient::answerValue(int32_t _transactionId, bool _value) {
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("return", ejson::Boolean(_value));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
}
*/
void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("error", ejson::String(protocolError));
answer.add("id", ejson::Number(_clientTransactionId));
answer.add("error-help", ejson::String(_errorHelp));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.addError(protocolError, _errorHelp);
m_interfaceClient.writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) { void jus::GateWayClient::onClientData(jus::Buffer& _value) {
uint32_t transactionId = _value.getTransactionId(); uint32_t transactionId = _value.getTransactionId();
if (transactionId == 0) { if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id"); JUS_ERROR("Protocol error ==>missing id");
@ -137,20 +107,16 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
std::string mode = _value.getParameter<std::string>(0); std::string mode = _value.getParameter<std::string>(0);
if (mode == "JSON") { if (mode == "JSON") {
JUS_WARNING("[" << m_uid << "] Change mode in: JSON"); JUS_WARNING("[" << m_uid << "] Change mode in: JSON");
answerValue(transactionId, true); m_interfaceClient.answerValue(transactionId, true);
m_interfaceMode = jus::connectionMode::modeJson; m_interfaceClient.setMode(jus::connectionMode::modeJson);
m_interfaceClient.connectCleanRaw();
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
} else if (mode == "BIN") { } else if (mode == "BIN") {
JUS_WARNING("[" << m_uid << "] Change mode in: BINARY"); JUS_WARNING("[" << m_uid << "] Change mode in: BINARY");
answerValue(transactionId, true); m_interfaceClient.answerValue(transactionId, true);
m_interfaceMode = jus::connectionMode::modeBinary; m_interfaceClient.setMode(jus::connectionMode::modeBinary);
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw);
} else if (mode == "XML") { } else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML"); JUS_WARNING("[" << m_uid << "] Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml; //m_interfaceMode = jus::connectionMode::modeXml;
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
} else { } else {
answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]"); answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
} }
@ -168,7 +134,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
jus::Future<bool> futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector<std::string>()); jus::Future<bool> futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector<std::string>());
futLocalService.wait(); // TODO: Set timeout ... futLocalService.wait(); // TODO: Set timeout ...
m_state = jus::GateWayClient::state::userIdentify; m_state = jus::GateWayClient::state::userIdentify;
answerValue(transactionId, true); m_interfaceClient.answerValue(transactionId, true);
} }
} }
return; return;
@ -199,11 +165,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
fut.wait(); // TODO: Set timeout ... fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) { if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ..."); JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1"); answerProtocolError(transactionId, "connection refused 1");
return; return;
} else if (fut.get() == false) { } else if (fut.get() == false) {
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2"); answerProtocolError(transactionId, "connection refused 2");
return; return;
} }
@ -215,11 +181,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
fut.wait(); // TODO: Set timeout ... fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) { if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ..."); JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1"); answerProtocolError(transactionId, "connection refused 1");
return; return;
} else if (fut.get() == false) { } else if (fut.get() == false) {
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2"); answerProtocolError(transactionId, "connection refused 2");
return; return;
} }
@ -235,7 +201,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
futGroup.wait(); // TODO: Set timeout ... futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) { if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ..."); JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "grouping error"); answerProtocolError(transactionId, "grouping error");
return; return;
} }
@ -248,7 +214,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
futServices.wait(); // TODO: Set timeout ... futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) { if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ..."); JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false); m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "service filtering error"); answerProtocolError(transactionId, "service filtering error");
return; return;
} }
@ -258,7 +224,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
JUS_WARNING(" services: " << etk::to_string(m_clientServices)); JUS_WARNING(" services: " << etk::to_string(m_clientServices));
answerValue(transactionId, true); m_interfaceClient.answerValue(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify; m_state = jus::GateWayClient::state::clientIdentify;
return; return;
} }
@ -269,11 +235,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
if (serviceId == 0) { if (serviceId == 0) {
// This is 2 default service for the cient interface that manage the authorisation of view: // This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") { if (callFunction == "getServiceCount") {
answerValue(transactionId, m_clientServices.size()); m_interfaceClient.answerValue(transactionId, m_clientServices.size());
return; return;
} }
if (callFunction == "getServiceList") { if (callFunction == "getServiceList") {
answerValue(transactionId, m_clientServices); m_interfaceClient.answerValue(transactionId, m_clientServices);
//listService.add(ejson::String("ServiceManager/v0.1.0")); //listService.add(ejson::String("ServiceManager/v0.1.0"));
return; return;
} }
@ -296,7 +262,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
if (it == m_listConnectedService.end()) { if (it == m_listConnectedService.end()) {
// check if service is connectable ... // check if service is connectable ...
if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) { if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) {
answerError(transactionId, "UN-AUTHORIZED-SERVICE"); m_interfaceClient.answerError(transactionId, "UN-AUTHORIZED-SERVICE");
return; return;
} }
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName); ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
@ -305,17 +271,17 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
futLink.wait(); // TODO: Set timeout ... futLink.wait(); // TODO: Set timeout ...
if (futLink.hasError() == true) { if (futLink.hasError() == true) {
JUS_ERROR("Get error from the service ... LINK"); JUS_ERROR("Get error from the service ... LINK");
answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return; return;
} }
m_listConnectedService.push_back(srv); m_listConnectedService.push_back(srv);
answerValue(transactionId, m_listConnectedService.size()); m_interfaceClient.answerValue(transactionId, m_listConnectedService.size());
return; return;
} }
answerError(transactionId, "CAN-NOT-CONNECT-SERVICE"); m_interfaceClient.answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
return; return;
} }
answerError(transactionId, "SERVICE-ALREADY-CONNECTED");; m_interfaceClient.answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
return; return;
} }
if (callFunction == "unlink") { if (callFunction == "unlink") {
@ -323,28 +289,28 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
int64_t localServiceID = _value.getParameter<int64_t>(0)-1; int64_t localServiceID = _value.getParameter<int64_t>(0)-1;
// Check if service already link: // Check if service already link:
if (localServiceID >= m_listConnectedService.size()) { if (localServiceID >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE"); m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE");
return; return;
} }
jus::Future<bool> futUnLink = call(m_uid, m_listConnectedService[localServiceID], "_delete"); jus::Future<bool> futUnLink = call(m_uid, m_listConnectedService[localServiceID], "_delete");
futUnLink.wait(); // TODO: Set timeout ... futUnLink.wait(); // TODO: Set timeout ...
if (futUnLink.hasError() == true) { if (futUnLink.hasError() == true) {
JUS_ERROR("Get error from the service ... UNLINK"); JUS_ERROR("Get error from the service ... UNLINK");
answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE"); m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return; return;
} }
m_listConnectedService[localServiceID] = nullptr; m_listConnectedService[localServiceID] = nullptr;
answerValue(transactionId, true); m_interfaceClient.answerValue(transactionId, true);
return; return;
} }
JUS_ERROR("Function does not exist ... '" << callFunction << "'"); JUS_ERROR("Function does not exist ... '" << callFunction << "'");
answerError(transactionId, "CALL-UNEXISTING"); m_interfaceClient.answerError(transactionId, "CALL-UNEXISTING");
return; return;
} }
// decrease service ID ... // decrease service ID ...
serviceId -= 1; serviceId -= 1;
if (serviceId >= m_listConnectedService.size()) { if (serviceId >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE"); m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE");
return; return;
} else { } else {
if (m_listConnectedService[serviceId] == nullptr) { if (m_listConnectedService[serviceId] == nullptr) {
@ -388,8 +354,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << transactionId); JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << transactionId);
JUS_VERBOSE(" msg=" << tmpp.generateMachineString()); JUS_VERBOSE(" msg=" << tmpp.generateMachineString());
tmpp["id"].toNumber().set(uint64_t(transactionId)); tmpp["id"].toNumber().set(uint64_t(transactionId));
JUS_DEBUG("transmit=" << tmpp.generateMachineString()); m_interfaceClient.writeJson(tmpp);
m_interfaceClient.write(tmpp.generateMachineString());
if (tmpp.valueExist("part") == true) { if (tmpp.valueExist("part") == true) {
// multiple send element ... // multiple send element ...
if (tmpp.valueExist("finish") == true) { if (tmpp.valueExist("finish") == true) {
@ -405,341 +370,6 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
} }
} }
void jus::GateWayClient::onClientData(std::string _value) {
JUS_DEBUG("On data: " << _value);
jus::Buffer tmp;
tmp.fromJson(_value);
onClientDataRaw(tmp);
#ifdef SDFGSDFSFDSFSDFSDF
ejson::Object data(_value);
uint64_t transactionId = data["id"].toNumber().getU64();
if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
std::string callFunction = data["call"].toString().get();
switch (m_state) {
case jus::GateWayClient::state::disconnect:
case jus::GateWayClient::state::unconnect:
{
JUS_ERROR("Must never appear");
answerProtocolError(transactionId, "Gateway internal error");
return;
}
case jus::GateWayClient::state::connect:
{
if (m_userConnectionName != "") {
answerProtocolError(transactionId, "Gateway internal error 2");
return;
}
if (callFunction == "setMode") {
std::string mode = data["param"].toArray()[0].toString().get();
if (mode == "JSON") {
JUS_WARNING("[" << m_uid << "] Change mode in: JSON");
answerValue(transactionId, true);
m_interfaceMode = jus::connectionMode::modeJson;
m_interfaceClient.connectCleanRaw();
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
} else if (mode == "BIN") {
JUS_WARNING("[" << m_uid << "] Change mode in: BINARY");
answerValue(transactionId, true);
m_interfaceMode = jus::connectionMode::modeBinary;
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw);
} else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml;
answerValue(transactionId, false);
} else {
answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
}
return;
} else if (callFunction == "connectToUser") {
m_userConnectionName = data["param"].toArray()[0].toString().get();
if (m_userConnectionName == "") {
answerProtocolError(transactionId, "Call connectToUser with no parameter 'user'");
} else {
JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'");
m_userService = m_gatewayInterface->get("system-user");
if (m_userService == nullptr) {
answerProtocolError(transactionId, "Gateway internal error 'No user interface'");
} else {
jus::Future<bool> futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector<std::string>());
futLocalService.wait(); // TODO: Set timeout ...
m_state = jus::GateWayClient::state::userIdentify;
answerValue(transactionId, true);
}
}
return;
}
JUS_WARNING("[" << m_uid << "] Client must send conection to user name ...");
answerProtocolError(transactionId, "Missing call of connectToUser");
return;
}
case jus::GateWayClient::state::userIdentify:
{
m_clientServices.clear();
m_clientgroups.clear();
m_clientName.clear();
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous") {
answerProtocolError(transactionId, "Client must call: identify/auth/anonymous");
return;
}
if (callFunction == "identify") {
std::string clientName = data["param"].toArray()[0].toString().get();
std::string clientTocken = data["param"].toArray()[1].toString().get();
if (m_userService == nullptr) {
answerProtocolError(transactionId, "gateWay internal error 3");
return;
}
jus::Future<bool> fut = call(m_uid2, m_userService, "checkTocken", clientName, clientTocken);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = clientName;
}
if (callFunction == "auth") {
std::string password = data["param"].toArray()[0].toString().get();
jus::Future<bool> fut = call(m_uid2, m_userService, "checkAuth", password);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = m_userConnectionName;
}
if (callFunction == "anonymous") {
m_clientName = "";
}
// --------------------------------
// -- Get groups:
// --------------------------------
jus::Future<std::vector<std::string>> futGroup = call(m_uid2, m_userService, "getGroups", m_clientName);
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
answerProtocolError(transactionId, "grouping error");
return;
}
m_clientgroups = futGroup.get();
// --------------------------------
// -- Get services:
// --------------------------------
std::vector<std::string> currentServices = m_gatewayInterface->getAllServiceName();
jus::Future<std::vector<std::string>> futServices = call(m_uid2, m_userService, "filterServices", m_clientName, currentServices);
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
answerProtocolError(transactionId, "service filtering error");
return;
}
m_clientServices = futServices.get();
JUS_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'");
JUS_WARNING(" groups: " << etk::to_string(m_clientgroups));
JUS_WARNING(" services: " << etk::to_string(m_clientServices));
answerValue(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify;
return;
}
break;
case jus::GateWayClient::state::clientIdentify:
{
ejson::Number numService = data["service"].toNumber();
if ( numService.exist() == false
|| numService.getU64() == 0) {
// This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") {
answerValue(transactionId, m_clientServices.size());
return;
}
if (callFunction == "getServiceList") {
answerValue(transactionId, m_clientServices);
//listService.add(ejson::String("ServiceManager/v0.1.0"));
return;
}
if (callFunction == "link") {
// first param:
std::string serviceName = data["param"].toArray()[0].toString().get();
// Check if service already link:
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == nullptr) {
++it;
continue;
}
if ((*it)->getName() != serviceName) {
++it;
continue;
}
break;
}
if (it == m_listConnectedService.end()) {
// check if service is connectable ...
if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) {
answerError(transactionId, "UN-AUTHORIZED-SERVICE");
return;
}
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
if (srv != nullptr) {
jus::Future<bool> futLink = call(m_uid, srv, "_new", m_userConnectionName, m_clientName, m_clientgroups);
futLink.wait(); // TODO: Set timeout ...
if (futLink.hasError() == true) {
JUS_ERROR("Get error from the service ... LINK");
answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService.push_back(srv);
answerValue(transactionId, m_listConnectedService.size());
return;
}
answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
return;
}
answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
return;
}
if (callFunction == "unlink") {
// first param:
int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1;
// Check if service already link:
if (localServiceID >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE");
return;
}
jus::Future<bool> futUnLink = call(m_uid, m_listConnectedService[localServiceID], "_delete");
futUnLink.wait(); // TODO: Set timeout ...
if (futUnLink.hasError() == true) {
JUS_ERROR("Get error from the service ... UNLINK");
answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService[localServiceID] = nullptr;
answerValue(transactionId, true);
return;
}
JUS_ERROR("Function does not exist ... '" << callFunction << "'");
answerError(transactionId, "CALL-UNEXISTING");
return;
}
uint64_t serviceId = numService.getU64()-1;
if (serviceId >= m_listConnectedService.size()) {
ejson::Object answer;
answer.add("id", data["id"]);
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
} else {
bool finish = false;
if (data.valueExist("finish") == true) {
finish = data["finish"].toBoolean().get();
}
int64_t partTmp = -1;
if (data.valueExist("part") == true) {
uint64_t part = data["part"].toNumber().getU64();
partTmp = part;
if (part != 0) {
// subMessage ... ==> try to forward message:
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &itCall : m_pendingCall) {
JUS_INFO(" compare : " << itCall.first << " =?= " << transactionId);
if (itCall.first == transactionId) {
// Find element ==> transit it ...
if (m_listConnectedService[serviceId] == nullptr) {
// TODO ...
} else {
ejson::Object obj;
obj.add("id", ejson::Number(itCall.second.getTransactionId()));
obj.add("param-id", data["param-id"]);
obj.add("part", ejson::Number(part));
obj.add("data", data["data"]);
if (finish == true) {
obj.add("finish", ejson::Boolean(true));
}
m_listConnectedService[serviceId]->SendData(m_uid, obj);
}
return;
}
}
JUS_ERROR("Can not transfer part of a message ...");
return;
}
}
callActionForward(m_uid,
transactionId,
m_listConnectedService[serviceId],
data["call"].toString().get(),
data["param"].toArray(),
[=](jus::FutureBase _ret) {
ejson::Object tmpp = _ret.getRaw();
JUS_VERBOSE(" ==> transmit : " << tmpp["id"].toNumber().getU64() << " -> " << data["id"].toNumber().getU64());
JUS_VERBOSE(" msg=" << tmpp.generateMachineString());
tmpp["id"].toNumber().set(transactionId);
JUS_DEBUG("transmit=" << tmpp.generateMachineString());
m_interfaceClient.write(tmpp.generateMachineString());
if (tmpp.valueExist("part") == true) {
// multiple send element ...
if (tmpp.valueExist("finish") == true) {
return tmpp["finish"].toBoolean().get();
}
return false;
}
return true;
},
partTmp,
finish);
}
}
}
#endif
}
jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId,
uint64_t _clientTransactionId,
ememory::SharedPtr<jus::GateWayService> _srv,
const std::string& _functionName,
ejson::Array _params,
jus::FutureData::ObserverFinish _callback,
int64_t _part,
bool _finish) {
uint64_t id = getId();
ejson::Object callElem = jus::createCallJson(id, _functionName, _params);
if (_part != -1) {
callElem.add("part", ejson::Number(uint64_t(_part)));
}
if (_finish == true) {
callElem.add("finish", ejson::Boolean(true));
}
jus::FutureBase ret = callJson(_callerId, _srv, _clientTransactionId, id, callElem, _callback);
ret.setSynchronous();
return ret;
}
jus::FutureBase jus::GateWayClient::callBinary(uint64_t _callerId, jus::FutureBase jus::GateWayClient::callBinary(uint64_t _callerId,
ememory::SharedPtr<jus::GateWayService> _srv, ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId, uint64_t _clientTransactionId,
@ -809,10 +439,11 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId,
void jus::GateWayClient::returnMessage(ejson::Object _data) { void jus::GateWayClient::returnMessage(jus::Buffer& _data) {
jus::FutureBase future; jus::FutureBase future;
uint64_t tid = _data["id"].toNumber().get(); uint32_t tid = _data.getTransactionId();
if (tid == 0) { if (tid == 0) {
/* TODO ...
if (_data["error"].toString().get() == "PROTOCOL-ERROR") { if (_data["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ..."); JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
@ -826,6 +457,7 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) {
} else { } else {
JUS_ERROR("call with no ID ==> error ..."); JUS_ERROR("call with no ID ==> error ...");
} }
*/
return; return;
} }
{ {

View File

@ -30,10 +30,10 @@ namespace jus {
private: private:
jus::GateWay* m_gatewayInterface; jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient; jus::TcpString m_interfaceClient;
protected:
enum jus::connectionMode m_interfaceMode;
public: public:
enum jus::connectionMode getMode() { return m_interfaceMode; } enum jus::connectionMode getMode() {
return m_interfaceClient.getMode();
}
public: public:
esignal::Signal<bool> signalIsConnected; esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService; ememory::SharedPtr<jus::GateWayService> m_userService;
@ -49,9 +49,8 @@ namespace jus {
virtual ~GateWayClient(); virtual ~GateWayClient();
void start(uint64_t _uid, uint64_t _uid2); void start(uint64_t _uid, uint64_t _uid2);
void stop(); void stop();
void onClientDataRaw(jus::Buffer& _value); void onClientData(jus::Buffer& _value);
void onClientData(std::string _value); void returnMessage(jus::Buffer& _data);
void returnMessage(ejson::Object _data);
bool checkId(uint64_t _id) const { bool checkId(uint64_t _id) const {
return m_uid == _id return m_uid == _id
|| m_uid2 == _id; || m_uid2 == _id;
@ -63,7 +62,12 @@ namespace jus {
std::mutex m_mutex; std::mutex m_mutex;
std::vector<std::pair<uint64_t, jus::FutureBase>> m_pendingCall; std::vector<std::pair<uint64_t, jus::FutureBase>> m_pendingCall;
int32_t m_transactionLocalId; int32_t m_transactionLocalId;
jus::FutureBase callJson(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, uint64_t _clientTransactionId, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr); jus::FutureBase callJson(uint64_t _callerId,
ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId,
uint64_t _transactionId,
const ejson::Object& _obj,
jus::FutureData::ObserverFinish _callback=nullptr);
jus::FutureBase callBinary(uint64_t _callerId, jus::FutureBase callBinary(uint64_t _callerId,
ememory::SharedPtr<jus::GateWayService> _srv, ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId, uint64_t _clientTransactionId,
@ -101,40 +105,15 @@ namespace jus {
int64_t _part, int64_t _part,
bool _finish); bool _finish);
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
template<class JUS_ARG>
void answerValue(uint64_t _clientTransactionId, JUS_ARG _value) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
std::vector<ActionAsyncClient> asyncAction;
answer.add("return", jus::convertToJson(asyncAction, -1, _value));
if (asyncAction.size() != 0) {
JUS_ERROR("ASYNC datas ... TODO ///");
}
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.addAnswer(_value);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment="");
jus::FutureBase callActionForward(ememory::SharedPtr<jus::GateWayService> _srv, jus::FutureBase callActionForward(ememory::SharedPtr<jus::GateWayService> _srv,
jus::Buffer& _Buffer, jus::Buffer& _Buffer,
jus::FutureData::ObserverFinish _callback); jus::FutureData::ObserverFinish _callback);
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
}; };
} }

View File

@ -9,10 +9,14 @@
#include <jus/GateWay.h> #include <jus/GateWay.h>
#include <ejson/ejson.h> #include <ejson/ejson.h>
// todo : cHANGE THIS ...
static const std::string protocolError = "PROTOCOL-ERROR";
jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) : jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_gatewayInterface(_gatewayInterface), m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)), m_interfaceClient(std::move(_connection)) {
m_interfaceMode(jus::connectionMode::modeJson) {
JUS_INFO("-----------------"); JUS_INFO("-----------------");
JUS_INFO("-- NEW Service --"); JUS_INFO("-- NEW Service --");
JUS_INFO("-----------------"); JUS_INFO("-----------------");
@ -41,61 +45,89 @@ void jus::GateWayService::stop() {
void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) { void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) {
_data.add("client-id", ejson::Number(_userSessionId)); _data.add("client-id", ejson::Number(_userSessionId));
JUS_DEBUG("Send Service: " << _data.generateHumanString()); m_interfaceClient.writeJson(_data);
m_interfaceClient.write(_data.generateMachineString());
} }
void jus::GateWayService::SendData(uint64_t _userSessionId, jus::Buffer& _data) { void jus::GateWayService::SendData(uint64_t _userSessionId, jus::Buffer& _data) {
_data.setClientId(_userSessionId); _data.setClientId(_userSessionId);
_data.prepare(); _data.prepare();
if (m_interfaceMode == jus::connectionMode::modeJson) { if (m_interfaceClient.getMode() == jus::connectionMode::modeJson) {
JUS_ERROR("NOT manage transcriptioon binary to JSON ... ");
ejson::Object obj = _data.toJson(); ejson::Object obj = _data.toJson();
JUS_DEBUG("Send Service: " << obj.generateHumanString()); m_interfaceClient.writeJson(obj);
m_interfaceClient.write(obj.generateMachineString()); } else if (m_interfaceClient.getMode() == jus::connectionMode::modeXml) {
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("NOT manage transcriptioon binary to XML ... "); JUS_ERROR("NOT manage transcriptioon binary to XML ... ");
} else if (m_interfaceMode == jus::connectionMode::modeBinary) { } else if (m_interfaceClient.getMode() == jus::connectionMode::modeBinary) {
m_interfaceClient.writeBinary(_data); m_interfaceClient.writeBinary(_data);
} else { } else {
JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... "); JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... ");
} }
} }
void jus::GateWayService::onServiceData(std::string _value) { void jus::GateWayService::onServiceData(jus::Buffer& _value) {
JUS_DEBUG("On service data: " << _value); //JUS_DEBUG("On service data: " << _value);
ejson::Object data(_value); uint32_t transactionId = _value.getTransactionId();
data.add("from-service", ejson::String(m_name)); //data.add("from-service", ejson::String(m_name));
if (data.valueExist("event") == true) { if (_value.getType() == jus::Buffer::typeMessage::event) {
// No need to have a user ID ... /*
if (data["event"].toString().get() == "IS-ALIVE") { if (data.valueExist("event") == true) {
JUS_VERBOSE("Service Alive ..."); // No need to have a user ID ...
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) { if (data["event"].toString().get() == "IS-ALIVE") {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}"); JUS_VERBOSE("Service Alive ...");
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) {
ejson::Object tmpp;
tmpp.add("event", ejson::String("IS-ALIVE"));
m_interfaceClient.writeJson(tmpp);
}
} else {
JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'");
} }
} else {
JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'");
}
return;
}
if (data.valueExist("connect-service") == true) {
if (m_name != "") {
JUS_WARNING("Service interface ==> try change the servie name after init: '" << data["connect-service"].toString().get());
// TODO : Return something ...
return; return;
} }
m_name = data["connect-service"].toString().get(); */
m_interfaceClient.setInterfaceName("srv-" + m_name);
JUS_WARNING("Service name configured");
// TODO : Return something ...
return; return;
} }
if (data.valueExist("client-id") == false) { if (_value.getType() == jus::Buffer::typeMessage::call) {
std::string callFunction = _value.getCall();
if (callFunction == "setMode") {
std::string mode = _value.getParameter<std::string>(0);
if (mode == "JSON") {
JUS_WARNING("Change mode in: JSON");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeJson);
} else if (mode == "BIN") {
JUS_WARNING("Change mode in: BINARY");
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeBinary);
} else if (mode == "XML") {
JUS_WARNING("Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml;
m_interfaceClient.answerValue(transactionId, false);
} else {
answerProtocolError(transactionId, std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
}
return;
} else if (callFunction == "connect-service") {
if (m_name != "") {
JUS_WARNING("Service interface ==> try change the servie name after init: '" << _value.getParameter<std::string>(0));
m_interfaceClient.answerValue(transactionId, false);
return;
}
m_name = _value.getParameter<std::string>(0);
m_interfaceClient.setInterfaceName("srv-" + m_name);
m_interfaceClient.answerValue(transactionId, false);
return;
}
answerProtocolError(transactionId, "unknow function");
}
if (_value.getClientId() == 0) {
JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'"); JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'");
return; return;
} }
uint64_t userSessionId = data["client-id"].toNumber().getU64(); m_gatewayInterface->answer(_value.getClientId(), _value);
data.remove("client-id");
data.remove("action");
m_gatewayInterface->answer(userSessionId, data);
} }
void jus::GateWayService::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) {
m_interfaceClient.answerError(_transactionId, protocolError, _errorHelp);
m_interfaceClient.disconnect(true);
}

View File

@ -18,7 +18,6 @@ namespace jus {
jus::GateWay* m_gatewayInterface; jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient; jus::TcpString m_interfaceClient;
std::string m_name; std::string m_name;
enum jus::connectionMode m_interfaceMode;
public: public:
esignal::Signal<bool> signalIsConnected; esignal::Signal<bool> signalIsConnected;
public: public:
@ -26,7 +25,7 @@ namespace jus {
virtual ~GateWayService(); virtual ~GateWayService();
void start(); void start();
void stop(); void stop();
void onServiceData(std::string _value); void onServiceData(jus::Buffer& _value);
public: public:
void SendData(uint64_t _userSessionId, ejson::Object _data); void SendData(uint64_t _userSessionId, ejson::Object _data);
void SendData(uint64_t _userSessionId, jus::Buffer& _data); void SendData(uint64_t _userSessionId, jus::Buffer& _data);
@ -34,6 +33,8 @@ namespace jus {
return m_name; return m_name;
} }
bool isAlive(); bool isAlive();
protected:
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
}; };
} }

View File

@ -34,29 +34,27 @@ std::vector<std::string> jus::Service::getExtention() {
} }
void jus::Service::onClientData(std::string _value) { void jus::Service::onClientData(jus::Buffer& _value) {
JUS_INFO("Request: " << _value); uint32_t tmpID = _value.getTransactionId();
ejson::Object request(_value); uint32_t clientId = _value.getClientId();;
uint64_t tmpID = request["id"].toNumber().getU64();
uint64_t clientId = request["client-id"].toNumber().getU64();
auto it = m_callMultiData.begin(); auto it = m_callMultiData.begin();
while (it != m_callMultiData.end()) { while (it != m_callMultiData.end()) {
if ( it->getTransactionId() == tmpID if ( it->getTransactionId() == tmpID
&& it->getClientId() == clientId) { && it->getClientId() == clientId) {
JUS_WARNING("Append data ... " << tmpID); JUS_WARNING("Append data ... " << tmpID);
it->appendData(request); it->appendData(_value);
if (it->isFinished() == true) { if (it->isFinished() == true) {
JUS_WARNING("CALL Function ..."); JUS_WARNING("CALL Function ...");
callJson(tmpID, it->getRaw()); callBinary(tmpID, it->getRaw());
it = m_callMultiData.erase(it); it = m_callMultiData.erase(it);
} }
return; return;
} }
++it; ++it;
} }
jus::FutureCall futCall(clientId, tmpID, request); jus::FutureCall futCall(clientId, tmpID, _value);
if (futCall.isFinished() == true) { if (futCall.isFinished() == true) {
callJson(tmpID, futCall.getRaw()); callBinary(tmpID, futCall.getRaw());
} else { } else {
m_callMultiData.push_back(futCall); m_callMultiData.push_back(futCall);
} }
@ -81,7 +79,13 @@ void jus::Service::connect(const std::string& _serviceName, uint32_t _numberRetr
} }
m_interfaceClient->setInterface(std::move(connection)); m_interfaceClient->setInterface(std::move(connection));
m_interfaceClient->connect(); m_interfaceClient->connect();
m_interfaceClient->write(std::string("{\"connect-service\":\"") + _serviceName + "\"}"); ejson::Object tmpp;
tmpp.add("id", ejson::Number(1));
tmpp.add("call", ejson::String("connect-service"));
ejson::Array params;
params.add(ejson::String(_serviceName));
tmpp.add("param", params);
m_interfaceClient->writeJson(tmpp);
JUS_DEBUG("connect [STOP]"); JUS_DEBUG("connect [STOP]");
} }
@ -97,12 +101,17 @@ bool jus::Service::GateWayAlive() {
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\"}"); /*
ejson::Object tmpp;
tmpp.add("event", ejson::String("IS-ALIVE"));
m_interfaceClient->writeJson(tmpp);
*/
} }
} }
void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj) { void jus::Service::callBinary(uint32_t _transactionId, jus::Buffer& _obj) {
if (_obj.valueExist("event") == true) { if (_obj.getType() == jus::Buffer::typeMessage::event) {
/*
std::string event = _obj["event"].toString().get(); std::string event = _obj["event"].toString().get();
if (event == "IS-ALIVE") { if (event == "IS-ALIVE") {
// Gateway just aswer a keep alive information ... // Gateway just aswer a keep alive information ...
@ -110,44 +119,39 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj)
} else { } else {
JUS_ERROR("Unknow event: '" << event << "'"); JUS_ERROR("Unknow event: '" << event << "'");
} }
*/
JUS_ERROR("Unknow event: '...'");
return; return;
} }
ejson::Object answer; if (_obj.getType() == jus::Buffer::typeMessage::answer) {
uint64_t clientId = _obj["client-id"].toNumber().getU64(); JUS_ERROR("Local Answer: '...'");
if (_obj.valueExist("call") == true) { return;
std::string call = _obj["call"].toString().get(); }
ejson::Array params = _obj["param"].toArray(); //if (_obj.getType() == jus::Buffer::typeMessage::event) {
if (call[0] == '_') { if (m_interfaceClient->getMode() == jus::connectionMode::modeBinary) {
if (call == "_new") {
std::string userName = params[0].toString().get(); } else if (m_interfaceClient->getMode() == jus::connectionMode::modeJson) {
std::string clientName = params[1].toString().get(); uint32_t clientId = _obj.getClientId();
std::vector<std::string> clientGroup = convertJsonTo<std::vector<std::string>>(params[2]); std::string callFunction = _obj.getCall();
if (callFunction[0] == '_') {
if (callFunction == "_new") {
std::string userName = _obj.getParameter<std::string>(0);
std::string clientName = _obj.getParameter<std::string>(1);
std::vector<std::string> clientGroup = _obj.getParameter<std::vector<std::string>>(2);
clientConnect(clientId, userName, clientName, clientGroup); clientConnect(clientId, userName, clientName, clientGroup);
} else if (call == "_delete") { } else if (callFunction == "_delete") {
clientDisconnect(clientId); clientDisconnect(clientId);
} }
// TODO : Do it better ... m_interfaceClient->answerValue(_transactionId, true, clientId);
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(clientId));
answer.add("return", ejson::Boolean(true));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
return; return;
} else if (isFunctionAuthorized(clientId, call) == true) { } else if (isFunctionAuthorized(clientId, callFunction) == true) {
callJson2(_transactionId, clientId, call, params); callBinary2(_transactionId, clientId, callFunction, _obj);
return; return;
} else { } else {
answer.add("id", ejson::Number(_transactionId)); m_interfaceClient->answerError(_transactionId, "NOT-AUTHORIZED-FUNCTION", "", clientId);
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; return;
} }
} else {
JUS_ERROR("Not manage transfer mode ");
} }
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(clientId));
answer.add("error", ejson::String("NOT-IMPLEMENTED-FUNCTION"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
} }

View File

@ -69,8 +69,7 @@ namespace jus {
void connect(const std::string& _serviceName, uint32_t _numberRetry = 1); void connect(const std::string& _serviceName, uint32_t _numberRetry = 1);
void disconnect(); void disconnect();
private: private:
void onClientData(std::string _value); void onClientData(jus::Buffer& _value);
std::string asyncRead();
public: public:
void pingIsAlive(); void pingIsAlive();
bool GateWayAlive(); bool GateWayAlive();
@ -86,8 +85,8 @@ namespace jus {
virtual void clientConnect(uint64_t _clientId, const std::string& _userName, const std::string& _clientName, const std::vector<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(uint64_t _clientId) = 0; virtual void clientDisconnect(uint64_t _clientId) = 0;
// Genenric function call: // Genenric function call:
void callJson(uint64_t _transactionId, const ejson::Object& _obj); void callBinary(uint32_t _transactionId, jus::Buffer& _obj);
virtual void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _obj) = 0; virtual void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _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)
@ -116,6 +115,8 @@ namespace jus {
JUS_INFO("Add function '" << _name << "' in local mode"); JUS_INFO("Add function '" << _name << "' in local mode");
m_listFunction.push_back(tmp); m_listFunction.push_back(tmp);
} }
}; };
template<class JUS_TYPE_SERVICE, class JUS_USER_ACCESS> template<class JUS_TYPE_SERVICE, class JUS_USER_ACCESS>
class ServiceType : public jus::Service { class ServiceType : public jus::Service {
@ -208,15 +209,10 @@ namespace jus {
} }
it->second.first->setGroups(_clientGroups); it->second.first->setGroups(_clientGroups);
} }
void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _params) { void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) {
auto it = m_interface.find(_clientId); auto it = m_interface.find(_clientId);
if (it == m_interface.end()) { if (it == m_interface.end()) {
ejson::Object answer; m_interfaceClient->answerError(_transactionId, "CLIENT-UNKNOW", "", _clientId);
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; return;
} }
for (auto &it2 : m_listFunction) { for (auto &it2 : m_listFunction) {
@ -229,19 +225,19 @@ namespace jus {
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();
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)elem); it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)elem);
return; return;
} }
case jus::AbstractFunction::type::local: { case jus::AbstractFunction::type::local: {
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)((RemoteProcessCall*)this)); it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)((RemoteProcessCall*)this));
return; return;
} }
case jus::AbstractFunction::type::service: { case jus::AbstractFunction::type::service: {
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)this); it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)this);
return; return;
} }
case jus::AbstractFunction::type::global: { case jus::AbstractFunction::type::global: {
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, nullptr); it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, nullptr);
return; return;
} }
case jus::AbstractFunction::type::unknow: case jus::AbstractFunction::type::unknow:
@ -249,14 +245,7 @@ namespace jus {
break; break;
} }
} }
{ m_interfaceClient->answerError(_transactionId, "FUNCTION-UNKNOW", "", _clientId);
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; return;
} }
}; };

View File

@ -12,20 +12,20 @@ jus::TcpString::TcpString(enet::Tcp _connection) :
m_connection(std::move(_connection)), m_connection(std::move(_connection)),
m_thread(nullptr), m_thread(nullptr),
m_observerElement(nullptr), m_observerElement(nullptr),
m_observerRawElement(nullptr),
m_threadAsync(nullptr) { m_threadAsync(nullptr) {
m_threadRunning = false; m_threadRunning = false;
m_threadAsyncRunning = false; m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
} }
jus::TcpString::TcpString() : jus::TcpString::TcpString() :
m_connection(), m_connection(),
m_thread(nullptr), m_thread(nullptr),
m_observerElement(nullptr), m_observerElement(nullptr),
m_observerRawElement(nullptr),
m_threadAsync(nullptr) { m_threadAsync(nullptr) {
m_threadRunning = false; m_threadRunning = false;
m_threadAsyncRunning = false; m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
} }
void jus::TcpString::setInterface(enet::Tcp _connection) { void jus::TcpString::setInterface(enet::Tcp _connection) {
@ -39,38 +39,14 @@ jus::TcpString::~TcpString() {
void jus::TcpString::setInterfaceName(const std::string& _name) { void jus::TcpString::setInterfaceName(const std::string& _name) {
ethread::setName(*m_thread, "Tcp-" + _name); ethread::setName(*m_thread, "Tcp-" + _name);
} }
// TODO : Do it better :
void jus::TcpString::threadCallback() { void jus::TcpString::threadCallback() {
ethread::setName("TcpString-input"); ethread::setName("TcpString-input");
// get datas: // get datas:
while ( m_threadRunning == true while ( m_threadRunning == true
&& m_connection.getConnectionStatus() == enet::Tcp::status::link) { && m_connection.getConnectionStatus() == enet::Tcp::status::link) {
// READ section data: // READ section data:
if (m_observerElement != nullptr) { read();
JUS_PRINT("Call String ...");
std::string data = std::move(read());
JUS_PRINT("Receive data: '" << data << "'");
if (data.size() != 0) {
m_lastReceive = std::chrono::steady_clock::now();
JUS_PRINT(" Call function ... 1");
if (m_observerElement != nullptr) {
m_observerElement(std::move(data));
} else if (m_observerRawElement != nullptr) {
jus::Buffer dataRaw;
dataRaw.composeWith(data);
m_observerRawElement(dataRaw);
} else {
JUS_ERROR("Lose DATA ...");
}
JUS_PRINT(" Call function ... 1 (done)");
}
} else if (m_observerRawElement != nullptr) {
JUS_PRINT("Call Raw ...");
jus::Buffer data = readRaw();
JUS_PRINT(" Call function ... 2");
m_observerRawElement(data);
JUS_PRINT(" Call function ... 2 (done)");
}
} }
m_threadRunning = false; m_threadRunning = false;
JUS_DEBUG("End of thread"); JUS_DEBUG("End of thread");
@ -136,33 +112,30 @@ void jus::TcpString::disconnect(bool _inThreadStop){
JUS_DEBUG("disconnect [STOP]"); JUS_DEBUG("disconnect [STOP]");
} }
int32_t jus::TcpString::write(const std::string& _data) { int32_t jus::TcpString::writeJson(ejson::Object& _data) {
JUS_DEBUG("Send JSON '" << _data.generateHumanString() << "'");
if (m_threadRunning == false) { if (m_threadRunning == false) {
return -2; return -2;
} }
if (_data.size() == 0) {
return 0;
}
uint32_t size = _data.size();
m_lastSend = std::chrono::steady_clock::now(); m_lastSend = std::chrono::steady_clock::now();
m_connection.write(&size, 4); m_connection.write("J", 1);
return m_connection.write(_data.c_str(), _data.size()); std::string tmpData = _data.generateMachineString();
uint32_t dataSize = tmpData.size();
m_connection.write(&dataSize, sizeof(uint32_t));
m_connection.write(&tmpData[0], tmpData.size());
return 1;
} }
int32_t jus::TcpString::writeBinary(jus::Buffer& _data) { int32_t jus::TcpString::writeBinary(jus::Buffer& _data) {
_data.prepare(); _data.prepare();
JUS_DEBUG("Send BINARY '" << _data.generateHumanString() << "'"); JUS_DEBUG("Send BINARY '" << _data.toJson().generateHumanString() << "'");
if (m_threadRunning == false) { if (m_threadRunning == false) {
return -2; return -2;
} }
/* m_lastSend = std::chrono::steady_clock::now();
if (_data.size() == 0) { m_connection.write("B", 1);
return 0;
}
*/
//uint32_t size = _data.size();
const uint8_t* data = nullptr; const uint8_t* data = nullptr;
uint32_t dataSize = 0; uint32_t dataSize = 0;
m_lastSend = std::chrono::steady_clock::now();
data = _data.getHeader(); data = _data.getHeader();
dataSize = _data.getHeaderSize(); dataSize = _data.getHeaderSize();
m_connection.write(data, dataSize); m_connection.write(data, dataSize);
@ -175,84 +148,92 @@ int32_t jus::TcpString::writeBinary(jus::Buffer& _data) {
return 1; return 1;
} }
std::string jus::TcpString::read() { void jus::TcpString::read() {
JUS_VERBOSE("Read [START]"); JUS_VERBOSE("Read [START]");
if (m_threadRunning == false) { if (m_threadRunning == false) {
JUS_DEBUG("Read [END] Disconected"); JUS_DEBUG("Read [END] Disconected");
return ""; return;
} }
// TODO : Do it better with a correct way to check data size ... // TODO : Do it better with a correct way to check data size ...
JUS_VERBOSE("Read [START]"); JUS_VERBOSE("Read [START]");
std::string out; uint8_t type = 0;
uint32_t size = 0; int32_t len = m_connection.read(&type, 1);
int32_t len = m_connection.read(&size, 4); if (len == 0) {
if (len != 4) { JUS_ERROR("Protocol error occured ==> No datas ...");
JUS_ERROR("Protocol error occured ...");
} else { } else {
if (size == -1) { if (type == 'B') { // binary
JUS_WARNING("Remote close connection"); // Binary mode ... start with the lenght of the stream
m_threadRunning = false; JUS_VERBOSE("Read Binary [START]");
//m_connection.unlink(); uint32_t size = 0;
} else { len = m_connection.read(&size, 4);
int64_t offset = 0; if (len != 4) {
out.resize(size); JUS_ERROR("Protocol error occured ...");
while (offset != size) { } else {
len = m_connection.read(&out[offset], size-offset); if (size == -1) {
offset += len; JUS_WARNING("Remote close connection");
if (len == 0) { m_threadRunning = false;
JUS_WARNING("Read No data"); //m_connection.unlink();
//break; } else {
int64_t offset = 0;
m_buffer.resize(size);
while (offset != size) {
len = m_connection.read(&m_buffer[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
}
}
if (m_observerElement != nullptr) {
jus::Buffer dataRaw;
dataRaw.composeWith(m_buffer);
JUS_VERBOSE("Receive Binary :" << dataRaw.toJson().generateHumanString());
m_observerElement(dataRaw);
}
} }
/*
else if (size != offset) {
JUS_ERROR("Protocol error occured .2. ==> concat (offset=" << offset << " size=" << size);
}
*/
} }
JUS_VERBOSE("ReadRaw [STOP]");
} else if ( type == 'X' // XML
|| type == 'J' // JSON
) {
JUS_VERBOSE("Read sized String [START]");
// XML/JSON mode ... start with the lenght of the stream
std::string out;
uint32_t size = 0;
len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
} else {
if (size == -1) {
JUS_WARNING("Remote close connection");
m_threadRunning = false;
//m_connection.unlink();
} else {
int64_t offset = 0;
out.resize(size);
while (offset != size) {
len = m_connection.read(&out[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
}
}
if (m_observerElement != nullptr) {
JUS_VERBOSE("Receive String :" << out);
jus::Buffer dataRaw;
dataRaw.composeWith(out);
m_observerElement(dataRaw);
}
}
}
JUS_VERBOSE("Read sized String [STOP]");
} else if (type == '{') {
// JSON Raw mode ... Finish with a \0
// TODO: m_dataBuffer
} else if (type == '<') {
// XML Raw mode ... Finish with a \0
// TODO : m_dataBuffer
} }
} }
JUS_VERBOSE("Read [STOP]");
return out;
}
jus::Buffer jus::TcpString::readRaw() {
jus::Buffer out;
JUS_VERBOSE("ReadRaw [START]");
if (m_threadRunning == false) {
JUS_DEBUG("Read [END] Disconected");
return out;
}
JUS_VERBOSE("ReadRaw [START]");
uint32_t size = 0;
int32_t len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
} else {
if (size == -1) {
JUS_WARNING("Remote close connection");
m_threadRunning = false;
//m_connection.unlink();
} else {
int64_t offset = 0;
m_buffer.resize(size);
while (offset != size) {
len = m_connection.read(&m_buffer[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
//break;
}
/*
else if (size != offset) {
JUS_ERROR("Protocol error occured .2. ==> concat (offset=" << offset << " size=" << size);
}
*/
}
out.composeWith(m_buffer);
}
}
JUS_VERBOSE("ReadRaw [STOP]");
return out;
} }
void jus::TcpString::threadAsyncCallback() { void jus::TcpString::threadAsyncCallback() {
@ -280,3 +261,51 @@ void jus::TcpString::threadAsyncCallback() {
JUS_DEBUG("End of thread"); JUS_DEBUG("End of thread");
} }
void jus::TcpString::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp, uint32_t _clientId) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("error", ejson::String(_errorValue));
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
answer.add("error-help", ejson::String(_errorHelp));
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addError(_errorValue, _errorHelp);
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void jus::TcpString::answerVoid(uint64_t _clientTransactionId, uint32_t _clientId) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
answer.add("return", ejson::Null());
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addParameter();
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}

View File

@ -10,6 +10,8 @@
#include <enet/Tcp.h> #include <enet/Tcp.h>
#include <thread> #include <thread>
#include <memory> #include <memory>
#include <jus/connectionMode.h>
#include <jus/AbstractFunction.h>
namespace jus { namespace jus {
class TcpString : public eproperty::Interface { class TcpString : public eproperty::Interface {
@ -17,13 +19,22 @@ namespace jus {
enet::Tcp m_connection; enet::Tcp m_connection;
std::thread* m_thread; std::thread* m_thread;
bool m_threadRunning; bool m_threadRunning;
protected:
enum jus::connectionMode m_interfaceMode;
public:
enum jus::connectionMode getMode() {
return m_interfaceMode;
}
void setMode(enum jus::connectionMode _mode) {
m_interfaceMode = _mode;
}
std::vector<uint8_t> m_buffer;
std::vector<uint8_t> m_temporaryBuffer;
std::chrono::steady_clock::time_point m_lastReceive; std::chrono::steady_clock::time_point m_lastReceive;
std::chrono::steady_clock::time_point m_lastSend; std::chrono::steady_clock::time_point m_lastSend;
public: public:
using Observer = std::function<void(std::string)>; //!< Define an Observer: function pointer using Observer = std::function<void(jus::Buffer&)>; //!< Define an Observer: function pointer
using ObserverRaw = std::function<void(jus::Buffer&)>; //!< Define an Observer: function pointer
Observer m_observerElement; Observer m_observerElement;
ObserverRaw m_observerRawElement;
/** /**
* @brief Connect an function member on the signal with the shared_ptr object. * @brief Connect an function member on the signal with the shared_ptr object.
* @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr. * @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr.
@ -31,23 +42,11 @@ namespace jus {
* @param[in] _args Argument optinnal the user want to add. * @param[in] _args Argument optinnal the user want to add.
*/ */
template<class CLASS_TYPE> template<class CLASS_TYPE>
void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(std::string)) { void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) {
m_observerElement = [=](std::string _value){ m_observerElement = [=](jus::Buffer& _value){
(*_class.*_func)(std::move(_value));
};
}
void connectClean() {
m_observerElement = nullptr;
}
template<class CLASS_TYPE>
void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) {
m_observerRawElement = [=](jus::Buffer& _value){
(*_class.*_func)(_value); (*_class.*_func)(_value);
}; };
} }
void connectCleanRaw() {
m_observerRawElement = nullptr;
}
public: public:
TcpString(); TcpString();
TcpString(enet::Tcp _connection); TcpString(enet::Tcp _connection);
@ -57,13 +56,12 @@ namespace jus {
void disconnect(bool _inThreadStop = false); void disconnect(bool _inThreadStop = false);
bool isActive() const; bool isActive() const;
void setInterfaceName(const std::string& _name); void setInterfaceName(const std::string& _name);
int32_t write(const std::string& _data); int32_t writeJson(ejson::Object& _data);
int32_t writeBinary(jus::Buffer& _data); int32_t writeBinary(jus::Buffer& _data);
std::string asyncRead(); std::string asyncRead();
private: private:
std::string read(); void read();
jus::Buffer readRaw(); jus::Buffer readRaw();
std::vector<uint8_t> m_buffer;
private: private:
void threadCallback(); void threadCallback();
public: public:
@ -86,6 +84,39 @@ namespace jus {
std::unique_lock<std::mutex> lock(m_threadAsyncMutex); std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
m_threadAsyncList.push_back(_elem); m_threadAsyncList.push_back(_elem);
} }
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
template<class JUS_ARG>
void answerValue(uint64_t _clientTransactionId, JUS_ARG _value, uint32_t _clientId=0) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
if (_clientId != 0) {
answer.add("client-id", ejson::Number(_clientId));
}
std::vector<jus::ActionAsyncClient> asyncAction;
answer.add("return", jus::convertToJson(asyncAction, -1, _value));
if (asyncAction.size() != 0) {
JUS_ERROR("ASYNC datas ... TODO ///");
}
writeJson(answer);
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.setClientId(_clientId);
answer.addAnswer(_value);
writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void answerVoid(uint64_t _clientTransactionId, uint32_t _clientId=0);
void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment="", uint32_t _clientId=0);
}; };
} }