[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)));
m_offset += tmpSize;
m_size -= tmpSize;
JUS_INFO("data: " << answer.generateHumanString());
_interface->write(answer.generateMachineString());
_interface->writeJson(answer);
if (m_size <= 0) {
return true;
}
@ -355,9 +354,11 @@ jus::AbstractFunction::AbstractFunction(const std::string& _name,
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) {
return _params.isBoolean();
return _params == "bool";
}
if ( createType<int64_t>() == _type
|| createType<int32_t>() == _type
@ -369,10 +370,19 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs
|| createType<uint8_t>() == _type
|| createType<float>() == _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) {
return _params.isArray();
return _params == "vector:string";
}
if ( createType<std::vector<bool>>() == _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<float>>() == _type
|| createType<std::vector<double>>() == _type) {
if (_params.isObject()) {
JUS_TODO("Special case of packaging of the data");
return false;
}
return _params.isArray();
return _params == "vector:int8"
|| _params == "vector:int16"
|| _params == "vector:int32"
|| _params == "vector:int64"
|| _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 (_params.isObject()) {
if (_params.toObject()["type"].toString().get() == "file") {
return true;
}
}
*/
return false;
}
if (createType<std::string>() == _type) {
return _params.isString();
return _params == "string";
}
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)
*/
#pragma once
#include <jus/TcpString.h>
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/debug.h>
#include <jus/ParamType.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 {
class AbstractFunction {
public:
@ -49,19 +58,15 @@ namespace jus {
public:
virtual ~AbstractFunction() {};
public:
bool checkCompatibility(const ParamType& _type, const ejson::Value& _params);
bool checkCompatibility(const ParamType& _type, const std::string& _params);
public:
std::string getPrototypeFull() const;
virtual std::string getPrototype() const = 0;
virtual std::string getPrototypeReturn() 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 std::string executeString(const std::vector<std::string>& _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;
};
// 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>
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 {
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
JUS_RETURN (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
std::vector<ActionAsyncClient> asyncAction;
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
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)
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
#error Must be implemented ...
ejson::Value ret = ejson::Null();
JUS_RETURN ret;
return;
#endif
if (asyncAction.size() != 0) {
JUS_ERROR("Missing send async messages");
}
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ret);
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerValue(_transactionId, ret, _clientId);
return true;
});
}
/*
class SendFile {
private:
jus::FileServer m_data;
@ -112,20 +111,20 @@ namespace jus {
}
};
template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
jus::FileServer (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
int32_t idParam = 0;
jus::FileServer tmpElem = (*_pointer.*_func)((convertJsonTo<JUS_TYPES>(_params[idParam++]))...);
jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam++)...);
#elif defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
jus::FileServer tmpElem = (*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...);
jus::FileServer tmpElem = (*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
jus::FileServer tmpElem;
@ -133,70 +132,31 @@ namespace jus {
#endif
_interfaceClient->addAsync(SendFile(tmpElem, _transactionId, _clientId));
}
*/
template <class JUS_CLASS_TYPE, class... JUS_TYPES>
void executeClassCallJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
const ejson::Array& _params) {
ejson::Object out;
void executeClassCall(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
JUS_CLASS_TYPE* _pointer,
void (JUS_CLASS_TYPE::*_func)(JUS_TYPES...),
jus::Buffer& _obj) {
#if defined(__clang__)
// clang generate a basic warning:
// warning: multiple unsequenced modifications to 'idParam' [-Wunsequenced]
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)
int32_t idParam = int32_t(sizeof...(JUS_TYPES))-1;
(*_pointer.*_func)(convertJsonTo<JUS_TYPES>(_params[idParam--])...);
(*_pointer.*_func)(_obj.getParameter<JUS_TYPES>(idParam--)...);
#else
#error Must be implemented ...
ejson::Value ret = ejson::Null();
return;
#endif
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("return", ejson::Null());
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
}
template <class JUS_CLASS_TYPE, class JUS_RETURN, class... JUS_TYPES>
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 "";
_interfaceClient->addAsync([=](TcpString* _interface) {
_interface->answerVoid(_transactionId, _clientId);
return true;
});
}
template <class JUS_RETURN, class JUS_CLASS_TYPE, class... JUS_TYPES>
@ -236,76 +196,43 @@ namespace jus {
}
return out;
}
void executeJson(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
const ejson::Array& _params,
void* _class) override {
void execute(const ememory::SharedPtr<jus::TcpString>& _interfaceClient,
uint64_t _transactionId,
uint64_t _clientId,
jus::Buffer& _obj,
void* _class) override {
JUS_CLASS_TYPE* tmpClass = nullptr;
if (_class != nullptr) {
tmpClass = (JUS_CLASS_TYPE*)_class;
}
// check parameter number
if (_params.size() != sizeof...(JUS_TYPES)) {
if (_obj.getNumberParameter() != sizeof...(JUS_TYPES)) {
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 ";
help += etk::to_string(_params.size());
help += etk::to_string(_obj.getNumberParameter());
help += " parameters and need ";
help += etk::to_string(sizeof...(JUS_TYPES));
help += " parameters. prototype function:";
help += getPrototype();
answer.add("error-help", ejson::String(help));
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-NUMBER",
help,
_clientId);
return;
}
// check parameter compatibility
for (size_t iii=0; iii<sizeof...(JUS_TYPES); ++iii) {
if (checkCompatibility(m_paramType[iii], _params[iii]) == false) {
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(_clientId));
answer.add("error", ejson::String("WRONG-PARAMETER-TYPE"));
answer.add("error-help", ejson::String("Parameter id " + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'"));
JUS_INFO("Answer: " << answer.generateHumanString());
_interfaceClient->write(answer.generateMachineString());
if (checkCompatibility(m_paramType[iii], _obj.getParameterType(iii)) == false) {
_interfaceClient->answerError(_transactionId,
"WRONG-PARAMETER-TYPE",
std::string("Parameter id ") + etk::to_string(iii) + " not compatible with type: '" + m_paramType[iii].getName() + "'",
_clientId);
return;
}
}
// execute cmd:
jus::executeClassCallJson(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _params);
}
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;
jus::executeClassCall(_interfaceClient, _transactionId, _clientId, tmpClass, m_function, _obj);
}
};

View File

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

View File

@ -60,19 +60,19 @@ void jus::Buffer::internalComposeWith(const uint8_t* _buffer, uint32_t _lenght)
} else {
// 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) {
internalComposeWith(&_buffer[0], _buffer.size());
}
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() {
JUS_WARNING("clear buffer");
JUS_VERBOSE("clear buffer");
m_data.clear();
m_paramOffset.clear();
m_header.lenght = 0;
@ -131,7 +131,7 @@ uint16_t jus::Buffer::getProtocalVersion() const {
}
void jus::Buffer::setProtocolVersion(uint16_t _value) {
JUS_WARNING("setProtocolVersion :" << _value);
JUS_VERBOSE("setProtocolVersion :" << _value);
m_header.versionProtocol = _value;
}
@ -140,7 +140,7 @@ uint32_t jus::Buffer::getTransactionId() const {
}
void jus::Buffer::setTransactionId(uint32_t _value) {
JUS_WARNING("setTransactionId :" << _value);
JUS_VERBOSE("setTransactionId :" << _value);
m_header.transactionID = _value;
}
@ -149,7 +149,7 @@ uint32_t jus::Buffer::getClientId() const {
}
void jus::Buffer::setClientId(uint32_t _value) {
JUS_WARNING("setClientId :" << _value);
JUS_VERBOSE("setClientId :" << _value);
m_header.clientID = _value;
}
@ -159,7 +159,7 @@ uint16_t jus::Buffer::getPartId() const {
}
void jus::Buffer::setPartId(uint16_t _value) {
JUS_WARNING("setPartId :" << _value);
JUS_VERBOSE("setPartId :" << _value);
m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF);
}
@ -168,7 +168,7 @@ bool jus::Buffer::getPartFinish() const {
}
void jus::Buffer::setPartFinish(bool _value) {
JUS_WARNING("setPartFinish :" << _value);
JUS_VERBOSE("setPartFinish :" << _value);
if (_value == true) {
m_header.partID = (m_header.partID & 0x7FFF) | 0x8000;
} else {
@ -181,7 +181,7 @@ enum jus::Buffer::typeMessage jus::Buffer::getType() const {
}
void jus::Buffer::setType(enum typeMessage _value) {
JUS_WARNING("setType :" << _value);
JUS_VERBOSE("setType :" << _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;
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;
}
JUS_ERROR("Can not get type from '" << type << "'");
@ -2360,11 +2347,6 @@ ejson::Object jus::Buffer::toJson() const {
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) {
clear();
uint32_t valueClientId = 0;

View File

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

View File

@ -13,7 +13,6 @@
jus::Client::Client() :
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),
m_interfaceMode(jus::connectionMode::modeJson),
m_id(1) {
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::FutureBase future;
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) {
return jus::ServiceRemote(this, _name);
}
@ -171,29 +109,6 @@ bool jus::Client::unlink(const uint32_t& _serviceId) {
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() {
disconnect();
}
@ -214,9 +129,7 @@ bool jus::Client::connect(const std::string& _remoteUserToConnect){
jus::Future<bool> retBin = call("setMode", "BIN").wait();
if (retBin.get() == true) {
JUS_WARNING(" ==> accepted binary");
m_interfaceMode = jus::connectionMode::modeBinary;
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::Client::onClientDataRaw);
m_interfaceClient.setMode(jus::connectionMode::modeBinary);
JUS_INFO("Connection jump in BINARY ...");
} else {
// stay in JSON
@ -281,8 +194,7 @@ class SendAsyncJson {
obj.add("id", ejson::Number(m_transactionId));
obj.add("part", ejson::Number(m_partId));
obj.add("finish", ejson::Boolean(true));
JUS_DEBUG("Send JSON '" << obj.generateHumanString() << "'");
_interface->write(obj.generateMachineString());
_interface->writeJson(obj);
return true;
}
return false;
@ -309,8 +221,7 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId,
if (_async.size() != 0) {
_obj.add("part", ejson::Number(0));
}
JUS_DEBUG("Send JSON '" << _obj.generateHumanString() << "'");
m_interfaceClient.write(_obj.generateMachineString());
m_interfaceClient.writeJson(_obj);
if (_async.size() != 0) {
m_interfaceClient.addAsync(SendAsyncJson(_transactionId, _serviceId, _async));

View File

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

View File

@ -93,6 +93,7 @@ bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
tmp.fromJson(_returnValue);
return setAnswer(tmp);
}
bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) {
if (m_data == nullptr) {
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_clientId(_clientId),
m_isFinished(false) {
m_data = _callValue;
if (m_data.valueExist("part") == true) {
if (m_data.valueExist("finish") == true) {
if (m_data["finish"].toBoolean().get() == true) {
m_isFinished = true;
}
}
} else {
m_isFinished = true;
}
m_isFinished = m_data.getPartFinish();
}
void jus::FutureCall::appendData(const ejson::Object& _callValue) {
uint64_t paramID = _callValue["param-id"].toNumber().getU64();
// get the previous element parameters
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;
}
}
void jus::FutureCall::appendData(jus::Buffer& _callValue) {
m_dataMultiplePack.push_back(_callValue);
m_isFinished = _callValue.getPartFinish();
}
uint64_t jus::FutureCall::getTransactionId() {
@ -267,7 +234,7 @@ bool jus::FutureCall::isFinished() {
return m_isFinished;
}
ejson::Object jus::FutureCall::getRaw() {
jus::Buffer& jus::FutureCall::getRaw() {
return m_data;
}

View File

@ -38,17 +38,18 @@ namespace jus {
uint64_t m_transactionId;
uint64_t m_clientId;
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_answerTime;
public:
FutureCall(uint64_t _clientId, uint64_t _transactionId, const ejson::Object& _callValue);
void appendData(const ejson::Object& _callValue);
FutureCall(uint64_t _clientId, uint64_t _transactionId, jus::Buffer& _callValue);
void appendData(jus::Buffer& _callValue);
uint64_t getTransactionId();
uint64_t getClientId();
bool isFinished();
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) {
if (it == nullptr) {
continue;

View File

@ -33,7 +33,7 @@ namespace jus {
void stop();
ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName);
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 newClient(enet::Tcp _connection);
void cleanIO();

View File

@ -19,7 +19,6 @@ jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayI
m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)),
m_interfaceMode(jus::connectionMode::modeJson),
m_transactionLocalId(1) {
JUS_INFO("----------------");
JUS_INFO("-- NEW Client --");
@ -71,42 +70,13 @@ bool jus::GateWayClient::isAlive() {
}
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_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();
if (transactionId == 0) {
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);
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);
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeJson);
} 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);
m_interfaceClient.answerValue(transactionId, true);
m_interfaceClient.setMode(jus::connectionMode::modeBinary);
} else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML");
//m_interfaceMode = jus::connectionMode::modeXml;
answerValue(transactionId, false);
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]");
}
@ -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>());
futLocalService.wait(); // TODO: Set timeout ...
m_state = jus::GateWayClient::state::userIdentify;
answerValue(transactionId, true);
m_interfaceClient.answerValue(transactionId, true);
}
}
return;
@ -199,11 +165,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
@ -215,11 +181,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
@ -235,7 +201,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "grouping error");
return;
}
@ -248,7 +214,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ...");
answerValue(transactionId, false);
m_interfaceClient.answerValue(transactionId, false);
answerProtocolError(transactionId, "service filtering error");
return;
}
@ -258,7 +224,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
JUS_WARNING(" services: " << etk::to_string(m_clientServices));
answerValue(transactionId, true);
m_interfaceClient.answerValue(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify;
return;
}
@ -269,11 +235,11 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
if (serviceId == 0) {
// This is 2 default service for the cient interface that manage the authorisation of view:
if (callFunction == "getServiceCount") {
answerValue(transactionId, m_clientServices.size());
m_interfaceClient.answerValue(transactionId, m_clientServices.size());
return;
}
if (callFunction == "getServiceList") {
answerValue(transactionId, m_clientServices);
m_interfaceClient.answerValue(transactionId, m_clientServices);
//listService.add(ejson::String("ServiceManager/v0.1.0"));
return;
}
@ -296,7 +262,7 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
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");
m_interfaceClient.answerError(transactionId, "UN-AUTHORIZED-SERVICE");
return;
}
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 ...
if (futLink.hasError() == true) {
JUS_ERROR("Get error from the service ... LINK");
answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService.push_back(srv);
answerValue(transactionId, m_listConnectedService.size());
m_interfaceClient.answerValue(transactionId, m_listConnectedService.size());
return;
}
answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
m_interfaceClient.answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
return;
}
answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
m_interfaceClient.answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
return;
}
if (callFunction == "unlink") {
@ -323,28 +289,28 @@ void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
int64_t localServiceID = _value.getParameter<int64_t>(0)-1;
// Check if service already link:
if (localServiceID >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE");
m_interfaceClient.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");
m_interfaceClient.answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
return;
}
m_listConnectedService[localServiceID] = nullptr;
answerValue(transactionId, true);
m_interfaceClient.answerValue(transactionId, true);
return;
}
JUS_ERROR("Function does not exist ... '" << callFunction << "'");
answerError(transactionId, "CALL-UNEXISTING");
m_interfaceClient.answerError(transactionId, "CALL-UNEXISTING");
return;
}
// decrease service ID ...
serviceId -= 1;
if (serviceId >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE");
m_interfaceClient.answerError(transactionId, "NOT-CONNECTED-SERVICE");
return;
} else {
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(" msg=" << tmpp.generateMachineString());
tmpp["id"].toNumber().set(uint64_t(transactionId));
JUS_DEBUG("transmit=" << tmpp.generateMachineString());
m_interfaceClient.write(tmpp.generateMachineString());
m_interfaceClient.writeJson(tmpp);
if (tmpp.valueExist("part") == true) {
// multiple send element ...
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,
ememory::SharedPtr<jus::GateWayService> _srv,
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;
uint64_t tid = _data["id"].toNumber().get();
uint32_t tid = _data.getTransactionId();
if (tid == 0) {
/* TODO ...
if (_data["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex);
@ -826,6 +457,7 @@ void jus::GateWayClient::returnMessage(ejson::Object _data) {
} else {
JUS_ERROR("call with no ID ==> error ...");
}
*/
return;
}
{

View File

@ -30,10 +30,10 @@ namespace jus {
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
protected:
enum jus::connectionMode m_interfaceMode;
public:
enum jus::connectionMode getMode() { return m_interfaceMode; }
enum jus::connectionMode getMode() {
return m_interfaceClient.getMode();
}
public:
esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService;
@ -49,9 +49,8 @@ namespace jus {
virtual ~GateWayClient();
void start(uint64_t _uid, uint64_t _uid2);
void stop();
void onClientDataRaw(jus::Buffer& _value);
void onClientData(std::string _value);
void returnMessage(ejson::Object _data);
void onClientData(jus::Buffer& _value);
void returnMessage(jus::Buffer& _data);
bool checkId(uint64_t _id) const {
return m_uid == _id
|| m_uid2 == _id;
@ -63,7 +62,12 @@ namespace jus {
std::mutex m_mutex;
std::vector<std::pair<uint64_t, jus::FutureBase>> m_pendingCall;
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,
ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId,
@ -101,40 +105,15 @@ namespace jus {
int64_t _part,
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::Buffer& _Buffer,
jus::FutureData::ObserverFinish _callback);
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
};
}

View File

@ -9,10 +9,14 @@
#include <jus/GateWay.h>
#include <ejson/ejson.h>
// todo : cHANGE THIS ...
static const std::string protocolError = "PROTOCOL-ERROR";
jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)),
m_interfaceMode(jus::connectionMode::modeJson) {
m_interfaceClient(std::move(_connection)) {
JUS_INFO("-----------------");
JUS_INFO("-- NEW Service --");
JUS_INFO("-----------------");
@ -41,61 +45,89 @@ void jus::GateWayService::stop() {
void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) {
_data.add("client-id", ejson::Number(_userSessionId));
JUS_DEBUG("Send Service: " << _data.generateHumanString());
m_interfaceClient.write(_data.generateMachineString());
m_interfaceClient.writeJson(_data);
}
void jus::GateWayService::SendData(uint64_t _userSessionId, jus::Buffer& _data) {
_data.setClientId(_userSessionId);
_data.prepare();
if (m_interfaceMode == jus::connectionMode::modeJson) {
JUS_ERROR("NOT manage transcriptioon binary to JSON ... ");
if (m_interfaceClient.getMode() == jus::connectionMode::modeJson) {
ejson::Object obj = _data.toJson();
JUS_DEBUG("Send Service: " << obj.generateHumanString());
m_interfaceClient.write(obj.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
m_interfaceClient.writeJson(obj);
} else if (m_interfaceClient.getMode() == jus::connectionMode::modeXml) {
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);
} else {
JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... ");
}
}
void jus::GateWayService::onServiceData(std::string _value) {
JUS_DEBUG("On service data: " << _value);
ejson::Object data(_value);
data.add("from-service", ejson::String(m_name));
if (data.valueExist("event") == true) {
// No need to have a user ID ...
if (data["event"].toString().get() == "IS-ALIVE") {
JUS_VERBOSE("Service Alive ...");
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}");
void jus::GateWayService::onServiceData(jus::Buffer& _value) {
//JUS_DEBUG("On service data: " << _value);
uint32_t transactionId = _value.getTransactionId();
//data.add("from-service", ejson::String(m_name));
if (_value.getType() == jus::Buffer::typeMessage::event) {
/*
if (data.valueExist("event") == true) {
// No need to have a user ID ...
if (data["event"].toString().get() == "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;
}
m_name = data["connect-service"].toString().get();
m_interfaceClient.setInterfaceName("srv-" + m_name);
JUS_WARNING("Service name configured");
// TODO : Return something ...
*/
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'");
return;
}
uint64_t userSessionId = data["client-id"].toNumber().getU64();
data.remove("client-id");
data.remove("action");
m_gatewayInterface->answer(userSessionId, data);
m_gatewayInterface->answer(_value.getClientId(), _value);
}
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::TcpString m_interfaceClient;
std::string m_name;
enum jus::connectionMode m_interfaceMode;
public:
esignal::Signal<bool> signalIsConnected;
public:
@ -26,7 +25,7 @@ namespace jus {
virtual ~GateWayService();
void start();
void stop();
void onServiceData(std::string _value);
void onServiceData(jus::Buffer& _value);
public:
void SendData(uint64_t _userSessionId, ejson::Object _data);
void SendData(uint64_t _userSessionId, jus::Buffer& _data);
@ -34,6 +33,8 @@ namespace jus {
return m_name;
}
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) {
JUS_INFO("Request: " << _value);
ejson::Object request(_value);
uint64_t tmpID = request["id"].toNumber().getU64();
uint64_t clientId = request["client-id"].toNumber().getU64();
void jus::Service::onClientData(jus::Buffer& _value) {
uint32_t tmpID = _value.getTransactionId();
uint32_t clientId = _value.getClientId();;
auto it = m_callMultiData.begin();
while (it != m_callMultiData.end()) {
if ( it->getTransactionId() == tmpID
&& it->getClientId() == clientId) {
JUS_WARNING("Append data ... " << tmpID);
it->appendData(request);
it->appendData(_value);
if (it->isFinished() == true) {
JUS_WARNING("CALL Function ...");
callJson(tmpID, it->getRaw());
callBinary(tmpID, it->getRaw());
it = m_callMultiData.erase(it);
}
return;
}
++it;
}
jus::FutureCall futCall(clientId, tmpID, request);
jus::FutureCall futCall(clientId, tmpID, _value);
if (futCall.isFinished() == true) {
callJson(tmpID, futCall.getRaw());
callBinary(tmpID, futCall.getRaw());
} else {
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->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]");
}
@ -97,12 +101,17 @@ bool jus::Service::GateWayAlive() {
void jus::Service::pingIsAlive() {
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) {
if (_obj.valueExist("event") == true) {
void jus::Service::callBinary(uint32_t _transactionId, jus::Buffer& _obj) {
if (_obj.getType() == jus::Buffer::typeMessage::event) {
/*
std::string event = _obj["event"].toString().get();
if (event == "IS-ALIVE") {
// Gateway just aswer a keep alive information ...
@ -110,44 +119,39 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj)
} else {
JUS_ERROR("Unknow event: '" << event << "'");
}
*/
JUS_ERROR("Unknow event: '...'");
return;
}
ejson::Object answer;
uint64_t clientId = _obj["client-id"].toNumber().getU64();
if (_obj.valueExist("call") == true) {
std::string call = _obj["call"].toString().get();
ejson::Array params = _obj["param"].toArray();
if (call[0] == '_') {
if (call == "_new") {
std::string userName = params[0].toString().get();
std::string clientName = params[1].toString().get();
std::vector<std::string> clientGroup = convertJsonTo<std::vector<std::string>>(params[2]);
if (_obj.getType() == jus::Buffer::typeMessage::answer) {
JUS_ERROR("Local Answer: '...'");
return;
}
//if (_obj.getType() == jus::Buffer::typeMessage::event) {
if (m_interfaceClient->getMode() == jus::connectionMode::modeBinary) {
} else if (m_interfaceClient->getMode() == jus::connectionMode::modeJson) {
uint32_t clientId = _obj.getClientId();
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);
} else if (call == "_delete") {
} else if (callFunction == "_delete") {
clientDisconnect(clientId);
}
// TODO : Do it better ...
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());
m_interfaceClient->answerValue(_transactionId, true, clientId);
return;
} else if (isFunctionAuthorized(clientId, call) == true) {
callJson2(_transactionId, clientId, call, params);
} else if (isFunctionAuthorized(clientId, callFunction) == true) {
callBinary2(_transactionId, clientId, callFunction, _obj);
return;
} else {
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(clientId));
answer.add("error", ejson::String("NOT-AUTHORIZED-FUNCTION"));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
m_interfaceClient->answerError(_transactionId, "NOT-AUTHORIZED-FUNCTION", "", clientId);
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 disconnect();
private:
void onClientData(std::string _value);
std::string asyncRead();
void onClientData(jus::Buffer& _value);
public:
void pingIsAlive();
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 clientDisconnect(uint64_t _clientId) = 0;
// Genenric function call:
void callJson(uint64_t _transactionId, const ejson::Object& _obj);
virtual void callJson2(uint64_t _transactionId, uint64_t _clientId, const std::string& _call, const ejson::Array& _obj) = 0;
void callBinary(uint32_t _transactionId, jus::Buffer& _obj);
virtual void callBinary2(uint32_t _transactionId, uint64_t _clientId, const std::string& _call, jus::Buffer& _obj) = 0;
std::vector<std::string> getExtention();
public:
// Add Local fuction (depend on this class)
@ -116,6 +115,8 @@ namespace jus {
JUS_INFO("Add function '" << _name << "' in local mode");
m_listFunction.push_back(tmp);
}
};
template<class JUS_TYPE_SERVICE, class JUS_USER_ACCESS>
class ServiceType : public jus::Service {
@ -208,15 +209,10 @@ namespace jus {
}
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);
if (it == m_interface.end()) {
ejson::Object answer;
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());
m_interfaceClient->answerError(_transactionId, "CLIENT-UNKNOW", "", _clientId);
return;
}
for (auto &it2 : m_listFunction) {
@ -229,19 +225,19 @@ namespace jus {
switch (it2->getType()) {
case jus::AbstractFunction::type::object: {
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;
}
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;
}
case jus::AbstractFunction::type::service: {
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, (void*)this);
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, (void*)this);
return;
}
case jus::AbstractFunction::type::global: {
it2->executeJson(m_interfaceClient, _transactionId, _clientId, _params, nullptr);
it2->execute(m_interfaceClient, _transactionId, _clientId, _obj, nullptr);
return;
}
case jus::AbstractFunction::type::unknow:
@ -249,14 +245,7 @@ namespace jus {
break;
}
}
{
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());
}
m_interfaceClient->answerError(_transactionId, "FUNCTION-UNKNOW", "", _clientId);
return;
}
};

View File

@ -12,20 +12,20 @@ jus::TcpString::TcpString(enet::Tcp _connection) :
m_connection(std::move(_connection)),
m_thread(nullptr),
m_observerElement(nullptr),
m_observerRawElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false;
m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
}
jus::TcpString::TcpString() :
m_connection(),
m_thread(nullptr),
m_observerElement(nullptr),
m_observerRawElement(nullptr),
m_threadAsync(nullptr) {
m_threadRunning = false;
m_threadAsyncRunning = false;
m_interfaceMode = jus::connectionMode::modeJson;
}
void jus::TcpString::setInterface(enet::Tcp _connection) {
@ -39,38 +39,14 @@ jus::TcpString::~TcpString() {
void jus::TcpString::setInterfaceName(const std::string& _name) {
ethread::setName(*m_thread, "Tcp-" + _name);
}
// TODO : Do it better :
void jus::TcpString::threadCallback() {
ethread::setName("TcpString-input");
// get datas:
while ( m_threadRunning == true
&& m_connection.getConnectionStatus() == enet::Tcp::status::link) {
// READ section data:
if (m_observerElement != nullptr) {
JUS_PRINT("Call String ...");
std::string data = std::move(read());
JUS_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)");
}
read();
}
m_threadRunning = false;
JUS_DEBUG("End of thread");
@ -136,33 +112,30 @@ void jus::TcpString::disconnect(bool _inThreadStop){
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) {
return -2;
}
if (_data.size() == 0) {
return 0;
}
uint32_t size = _data.size();
m_lastSend = std::chrono::steady_clock::now();
m_connection.write(&size, 4);
return m_connection.write(_data.c_str(), _data.size());
m_connection.write("J", 1);
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) {
_data.prepare();
JUS_DEBUG("Send BINARY '" << _data.generateHumanString() << "'");
JUS_DEBUG("Send BINARY '" << _data.toJson().generateHumanString() << "'");
if (m_threadRunning == false) {
return -2;
}
/*
if (_data.size() == 0) {
return 0;
}
*/
//uint32_t size = _data.size();
m_lastSend = std::chrono::steady_clock::now();
m_connection.write("B", 1);
const uint8_t* data = nullptr;
uint32_t dataSize = 0;
m_lastSend = std::chrono::steady_clock::now();
data = _data.getHeader();
dataSize = _data.getHeaderSize();
m_connection.write(data, dataSize);
@ -175,84 +148,92 @@ int32_t jus::TcpString::writeBinary(jus::Buffer& _data) {
return 1;
}
std::string jus::TcpString::read() {
void jus::TcpString::read() {
JUS_VERBOSE("Read [START]");
if (m_threadRunning == false) {
JUS_DEBUG("Read [END] Disconected");
return "";
return;
}
// TODO : Do it better with a correct way to check data size ...
JUS_VERBOSE("Read [START]");
std::string out;
uint32_t size = 0;
int32_t len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
uint8_t type = 0;
int32_t len = m_connection.read(&type, 1);
if (len == 0) {
JUS_ERROR("Protocol error occured ==> No datas ...");
} 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");
//break;
if (type == 'B') { // binary
// Binary mode ... start with the lenght of the stream
JUS_VERBOSE("Read Binary [START]");
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;
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() {
@ -280,3 +261,51 @@ void jus::TcpString::threadAsyncCallback() {
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 <thread>
#include <memory>
#include <jus/connectionMode.h>
#include <jus/AbstractFunction.h>
namespace jus {
class TcpString : public eproperty::Interface {
@ -17,13 +19,22 @@ namespace jus {
enet::Tcp m_connection;
std::thread* m_thread;
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_lastSend;
public:
using Observer = std::function<void(std::string)>; //!< Define an Observer: function pointer
using ObserverRaw = std::function<void(jus::Buffer&)>; //!< Define an Observer: function pointer
using Observer = std::function<void(jus::Buffer&)>; //!< Define an Observer: function pointer
Observer m_observerElement;
ObserverRaw m_observerRawElement;
/**
* @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.
@ -31,23 +42,11 @@ namespace jus {
* @param[in] _args Argument optinnal the user want to add.
*/
template<class CLASS_TYPE>
void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(std::string)) {
m_observerElement = [=](std::string _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){
void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) {
m_observerElement = [=](jus::Buffer& _value){
(*_class.*_func)(_value);
};
}
void connectCleanRaw() {
m_observerRawElement = nullptr;
}
public:
TcpString();
TcpString(enet::Tcp _connection);
@ -57,13 +56,12 @@ namespace jus {
void disconnect(bool _inThreadStop = false);
bool isActive() const;
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);
std::string asyncRead();
private:
std::string read();
void read();
jus::Buffer readRaw();
std::vector<uint8_t> m_buffer;
private:
void threadCallback();
public:
@ -86,6 +84,39 @@ namespace jus {
std::unique_lock<std::mutex> lock(m_threadAsyncMutex);
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);
};
}