[DEV] start better interface binary

This commit is contained in:
Edouard DUPIN 2016-06-10 21:34:21 +02:00
parent 3a141c64b2
commit 4983fea721
13 changed files with 817 additions and 176 deletions

View File

@ -6,6 +6,7 @@
#include <etk/types.h> #include <etk/types.h>
#include <jus/Buffer.h> #include <jus/Buffer.h>
#include <jus/debug.h> #include <jus/debug.h>
#include <jus/ParamType.h>
namespace etk { namespace etk {
template<> std::string to_string<enum jus::Buffer::typeMessage>(const enum jus::Buffer::typeMessage& _value) { template<> std::string to_string<enum jus::Buffer::typeMessage>(const enum jus::Buffer::typeMessage& _value) {
@ -20,7 +21,7 @@ namespace etk {
return "???"; return "???";
} }
} }
std::ostream& jus::operator <<(std::ostream& _os, const std::vector<enum jus::Buffer::typeMessage>& _value) { std::ostream& jus::operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value) {
_os << etk::to_string(_value); _os << etk::to_string(_value);
return _os; return _os;
} }
@ -44,22 +45,32 @@ jus::Buffer::Buffer() {
void jus::Buffer::composeWith(const std::vector<uint8_t>& _buffer) { void jus::Buffer::composeWith(const std::vector<uint8_t>& _buffer) {
clear(); clear();
m_header.lenght = _buffer.size(); m_header.lenght = _buffer.size();
memcpy(&m_header + 4, &_buffer[0], sizeof(headerBin)-4); uint32_t offset = 0;
JUS_INFO("Get binary message : "); memcpy(reinterpret_cast<char*>(&m_header) + sizeof(uint32_t), &_buffer[offset], sizeof(headerBin)-sizeof(uint32_t));
JUS_INFO(" lenght = " << m_header.lenght); offset += sizeof(headerBin)-sizeof(uint32_t);
JUS_INFO(" versionProtocol = " << m_header.versionProtocol); if (m_header.numberOfParameter != 0) {
JUS_INFO(" transactionID = " << m_header.transactionID); m_paramOffset.resize(m_header.numberOfParameter);
JUS_INFO(" clientID = " << m_header.clientID); memcpy(&m_paramOffset[0], &_buffer[offset], m_header.numberOfParameter * sizeof(uint16_t));
JUS_INFO(" partID = " << m_header.partID); offset += m_header.numberOfParameter * sizeof(uint16_t);
enum jus::Buffer::typeMessage ttype = getTypeType(m_header.typeMessage); m_data.resize(_buffer.size() - offset);
JUS_INFO(" typeMessage = " << ttype); memcpy(&m_data[0], &_buffer[offset], m_data.size());
JUS_TODO(" ..."); } else {
// TODO : check size ...
}
JUS_INFO("Get binary messages " << generateHumanString());
} }
void jus::Buffer::clear() { void jus::Buffer::clear() {
JUS_WARNING("clear buffer");
m_data.clear(); m_data.clear();
m_paramOffset.clear(); m_paramOffset.clear();
m_header.clear(); m_header.lenght = 0;
m_header.versionProtocol = 1;
m_header.transactionID = 1;
m_header.clientID = 0;
m_header.partID = 0x8000;
m_header.typeMessage = 1;
m_header.numberOfParameter = 1;
} }
std::string jus::Buffer::generateHumanString() { std::string jus::Buffer::generateHumanString() {
std::string out = "jus::Buffer Lenght=: "; std::string out = "jus::Buffer Lenght=: ";
@ -67,69 +78,166 @@ std::string jus::Buffer::generateHumanString() {
out += " v=" + etk::to_string(m_header.versionProtocol); out += " v=" + etk::to_string(m_header.versionProtocol);
out += " id=" + etk::to_string(m_header.transactionID); out += " id=" + etk::to_string(m_header.transactionID);
out += " cId=" + etk::to_string(m_header.clientID); out += " cId=" + etk::to_string(m_header.clientID);
out += " pId=" + etk::to_string(m_header.partID); out += " pId=" + etk::to_string(getPartId());
out += " finish=" + etk::to_string(getPartFinish());
enum jus::Buffer::typeMessage type = getTypeType(m_header.typeMessage); enum jus::Buffer::typeMessage type = getTypeType(m_header.typeMessage);
out += " type=" + etk::to_string(type); out += " type=" + etk::to_string(type);
switch (type) {
case jus::Buffer::typeMessage::call:
out += " nbParam=" + etk::to_string(getNumberParameter());
break;
case jus::Buffer::typeMessage::answer:
if (getNumberParameter() == 1) {
out += " mode=Value";
} else if (getNumberParameter() == 2) {
out += " mode=Error";
} else if (getNumberParameter() == 3) {
out += " mode=Value+Error";
} else {
out += " mode=???";
}
break;
case jus::Buffer::typeMessage::event:
break;
}
if (getNumberParameter() != 0) {
out += " paramType(";
for (int32_t iii=0; iii< getNumberParameter(); ++iii) {
if (iii != 0) {
out += ",";
}
out += internalGetParameterType(iii);
}
out += ")";
}
return out; return out;
} }
uint16_t jus::Buffer::getProtocalVersion() { uint16_t jus::Buffer::getProtocalVersion() const {
return m_header.versionProtocol; return m_header.versionProtocol;
} }
void jus::Buffer::setProtocolVersion(uint16_t _value) { void jus::Buffer::setProtocolVersion(uint16_t _value) {
JUS_WARNING("setProtocolVersion :" << _value);
m_header.versionProtocol = _value; m_header.versionProtocol = _value;
} }
uint32_t jus::Buffer::getTransactionId() { uint32_t jus::Buffer::getTransactionId() const {
return m_header.transactionID; return m_header.transactionID;
} }
void jus::Buffer::setTransactionId(uint32_t _value) { void jus::Buffer::setTransactionId(uint32_t _value) {
JUS_WARNING("setTransactionId :" << _value);
m_header.transactionID = _value; m_header.transactionID = _value;
} }
uint32_t jus::Buffer::getClientId() { uint32_t jus::Buffer::getClientId() const {
return m_header.clientID; return m_header.clientID;
} }
void jus::Buffer::setClientId(uint32_t _value) { void jus::Buffer::setClientId(uint32_t _value) {
JUS_WARNING("setClientId :" << _value);
m_header.clientID = _value; m_header.clientID = _value;
} }
// note limited 15 bits // note limited 15 bits
uint16_t jus::Buffer::getPartId() { uint16_t jus::Buffer::getPartId() const {
return uint16_t(m_header.partID & 0x7FFF); return uint16_t(m_header.partID & 0x7FFF);
} }
void jus::Buffer::setPartId(uint16_t _value) { void jus::Buffer::setPartId(uint16_t _value) {
JUS_WARNING("setPartId :" << _value);
m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF); m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF);
} }
bool jus::Buffer::getPartFinish() { bool jus::Buffer::getPartFinish() const {
return m_header.versionProtocol<0; return m_header.partID<0;
} }
void jus::Buffer::setPartFinish(bool _value) { void jus::Buffer::setPartFinish(bool _value) {
JUS_WARNING("setPartFinish :" << _value);
if (_value == true) { if (_value == true) {
m_header.versionProtocol = (m_header.versionProtocol & 0x7FFF) | 0x8000; m_header.partID = (m_header.partID & 0x7FFF) | 0x8000;
} else { } else {
m_header.versionProtocol = m_header.versionProtocol & 0x7FFF; m_header.partID = m_header.partID & 0x7FFF;
} }
} }
enum jus::Buffer::typeMessage jus::Buffer::getType() { enum jus::Buffer::typeMessage jus::Buffer::getType() const {
return (enum jus::Buffer::typeMessage)m_header.typeMessage; return (enum jus::Buffer::typeMessage)m_header.typeMessage;
} }
void jus::Buffer::setType(enum typeMessage _value) { void jus::Buffer::setType(enum typeMessage _value) {
JUS_WARNING("setType :" << _value);
m_header.typeMessage = uint16_t(_value); m_header.typeMessage = uint16_t(_value);
} }
uint16_t jus::Buffer::getNumberParameter() { uint16_t jus::Buffer::getNumberParameter() const {
return m_paramOffset.size()-1; return m_paramOffset.size()-1;
} }
std::string jus::Buffer::internalGetParameterType(int32_t _id) const {
std::string out;
if (m_paramOffset.size() <= _id) {
JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size());
return out;
}
out = reinterpret_cast<const char*>(&m_data[m_paramOffset[_id]]);
return out;
}
std::string jus::Buffer::getParameterType(int32_t _id) const {
return internalGetParameterType(_id + 1);
}
const uint8_t* jus::Buffer::internalGetParameterPointer(int32_t _id) const {
const uint8_t* out = nullptr;
if (m_paramOffset.size() <= _id) {
JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size());
return out;
}
out = reinterpret_cast<const uint8_t*>(&m_data[m_paramOffset[_id]]);
if (out == nullptr) {
return out;
}
// TODO : unlock if > 1024
while (*out != 0) {
out++;
}
out++;
return out;
}
const uint8_t* jus::Buffer::getParameterPointer(int32_t _id) const {
return internalGetParameterPointer(_id + 1);
}
uint32_t jus::Buffer::internalGetParameterSize(int32_t _id) const {
int32_t out = 0;
if (m_paramOffset.size() <= _id) {
JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size());
return out;
}
int32_t startPos = m_paramOffset[_id];
int32_t endPos = m_data.size();
if (m_paramOffset.size() > _id+1) {
endPos = m_paramOffset[_id+1];
}
// First get type:
const char* type = reinterpret_cast<const char*>(&m_data[startPos]); // Will be stop with \0 ...
// move in the buffer pos
startPos += strlen(type) + 1;
// get real data size
out = endPos - startPos;
if (out < 0) {
JUS_ERROR("Get size < 0 : " << out);
out = 0;
}
return out;
}
uint32_t jus::Buffer::getParameterSize(int32_t _id) const {
return internalGetParameterSize(_id + 1);
}
void jus::Buffer::addParameter() { void jus::Buffer::addParameter() {
int32_t currentOffset = m_data.size(); int32_t currentOffset = m_data.size();
@ -151,8 +259,9 @@ void jus::Buffer::addParameter<std::string>(const std::string& _value) {
m_data.push_back('n'); m_data.push_back('n');
m_data.push_back('g'); m_data.push_back('g');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+_value.size()+1); m_data.resize(m_data.size()+_value.size()+1);
memcpy(&m_data[currentOffset], &_value[0], m_data.size()); memcpy(&m_data[currentOffset], &_value[0], _value.size());
} }
template<> template<>
void jus::Buffer::addParameter<int8_t>(const int8_t& _value) { void jus::Buffer::addParameter<int8_t>(const int8_t& _value) {
@ -187,6 +296,7 @@ void jus::Buffer::addParameter<int16_t>(const int16_t& _value) {
m_data.push_back('1'); m_data.push_back('1');
m_data.push_back('6'); m_data.push_back('6');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+2); m_data.resize(m_data.size()+2);
memcpy(&m_data[currentOffset], &_value, 2); memcpy(&m_data[currentOffset], &_value, 2);
} }
@ -201,6 +311,7 @@ void jus::Buffer::addParameter<uint16_t>(const uint16_t& _value) {
m_data.push_back('1'); m_data.push_back('1');
m_data.push_back('6'); m_data.push_back('6');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+2); m_data.resize(m_data.size()+2);
memcpy(&m_data[currentOffset], &_value, 2); memcpy(&m_data[currentOffset], &_value, 2);
} }
@ -214,6 +325,7 @@ void jus::Buffer::addParameter<int32_t>(const int32_t& _value) {
m_data.push_back('3'); m_data.push_back('3');
m_data.push_back('2'); m_data.push_back('2');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+4); m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4); memcpy(&m_data[currentOffset], &_value, 4);
} }
@ -228,6 +340,7 @@ void jus::Buffer::addParameter<uint32_t>(const uint32_t& _value) {
m_data.push_back('3'); m_data.push_back('3');
m_data.push_back('2'); m_data.push_back('2');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+4); m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4); memcpy(&m_data[currentOffset], &_value, 4);
} }
@ -241,6 +354,7 @@ void jus::Buffer::addParameter<int64_t>(const int64_t& _value) {
m_data.push_back('3'); m_data.push_back('3');
m_data.push_back('2'); m_data.push_back('2');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+8); m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8); memcpy(&m_data[currentOffset], &_value, 8);
} }
@ -255,6 +369,7 @@ void jus::Buffer::addParameter<uint64_t>(const uint64_t& _value) {
m_data.push_back('6'); m_data.push_back('6');
m_data.push_back('4'); m_data.push_back('4');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+8); m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8); memcpy(&m_data[currentOffset], &_value, 8);
} }
@ -268,6 +383,7 @@ void jus::Buffer::addParameter<float>(const float& _value) {
m_data.push_back('a'); m_data.push_back('a');
m_data.push_back('t'); m_data.push_back('t');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+4); m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4); memcpy(&m_data[currentOffset], &_value, 4);
} }
@ -282,6 +398,7 @@ void jus::Buffer::addParameter<double>(const double& _value) {
m_data.push_back('l'); m_data.push_back('l');
m_data.push_back('e'); m_data.push_back('e');
m_data.push_back('\0'); m_data.push_back('\0');
currentOffset = m_data.size();
m_data.resize(m_data.size()+8); m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8); memcpy(&m_data[currentOffset], &_value, 8);
} }
@ -302,7 +419,7 @@ void jus::Buffer::addParameter<bool>(const bool& _value) {
} }
template<> template<>
std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) { std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) const {
std::string out; std::string out;
if (m_paramOffset.size() <= _id) { if (m_paramOffset.size() <= _id) {
JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size());
@ -314,7 +431,7 @@ std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) {
endPos = m_paramOffset[_id+1]; endPos = m_paramOffset[_id+1];
} }
// First get type: // First get type:
char* type = reinterpret_cast<char*>(&m_data[startPos]); // Will be stop with \0 ... const char* type = reinterpret_cast<const char*>(&m_data[startPos]); // Will be stop with \0 ...
if (strcmp(type, "string") == 0) { if (strcmp(type, "string") == 0) {
// OK // OK
// move in the buffer pos // move in the buffer pos
@ -340,52 +457,36 @@ std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) {
template<> template<>
int8_t jus::Buffer::internalGetParameter<int8_t>(int32_t _id) { int8_t jus::Buffer::internalGetParameter<int8_t>(int32_t _id) const {
int8_t out; std::string type = getParameterType(_id);
if (m_paramOffset.size() <= _id) { const uint8_t* pointer = getParameterPointer(_id);
JUS_ERROR("out of range Id for parameter ... " << _id << " have " << m_paramOffset.size()); uint32_t dataSize = getParameterSize(_id);
return out; if (createType<int8_t>() != type) {
return 0;
} }
int32_t startPos = m_paramOffset[_id]; const int8_t* pointer2 = reinterpret_cast<const int8_t*>(pointer);
int32_t endPos = m_data.size(); return *pointer2;
if (m_paramOffset.size() > _id+1) { }
endPos = m_paramOffset[_id+1];
template<>
int32_t jus::Buffer::internalGetParameter<int32_t>(int32_t _id) const {
std::string type = getParameterType(_id);
const uint8_t* pointer = getParameterPointer(_id);
uint32_t dataSize = getParameterSize(_id);
if (createType<int32_t>() != type) {
return 0;
} }
// First get type: const int32_t* pointer2 = reinterpret_cast<const int32_t*>(pointer);
char* type = reinterpret_cast<char*>(&m_data[startPos]); // Will be stop with \0 ... return *pointer2;
if (strcmp(type, "int8") == 0) {
// OK
// move in the buffer pos
startPos += strlen(type) + 1;
// get real data size
int32_t dataSize = endPos - startPos;
if (dataSize < 0) {
JUS_ERROR("Get size < 0 : " << dataSize);
} else if (dataSize < 0) {
// nothing to do ...
} else {
if (dataSize != 1) {
JUS_ERROR("Get size > 1 : " << dataSize << " ==> limit 1");
dataSize = 1;
}
// Allocate data
memcpy(&out, &m_data[startPos], dataSize);
}
} else {
//wrong type ...
JUS_ERROR("Can not convert '" << type << "' into 'string'");
}
return out;
} }
void jus::Buffer::addError(const std::string& _value, const std::string& _comment) { void jus::Buffer::addError(const std::string& _value, const std::string& _comment) {
addParameter();
addParameter(_value); addParameter(_value);
addParameter(_comment); addParameter(_comment);
} }
std::string jus::Buffer::getCall() { std::string jus::Buffer::getCall() const {
std::string out; std::string out;
switch(getType()) { switch(getType()) {
case jus::Buffer::typeMessage::call: case jus::Buffer::typeMessage::call:
@ -412,3 +513,95 @@ void jus::Buffer::setCall(std::string _value) {
} }
addParameter(_value); addParameter(_value);
} }
void jus::Buffer::prepare() {
m_header.numberOfParameter = m_paramOffset.size();
m_header.lenght = sizeof(headerBin) - sizeof(uint32_t);
m_header.lenght += m_paramOffset.size() * sizeof(uint16_t); // param list
m_header.lenght += m_data.size();
}
ejson::Object jus::Buffer::toJson() const {
ejson::Object out;
out.add("id", ejson::Number(getTransactionId()));
out.add("client-id", ejson::Number(getClientId()));
uint16_t partId = getPartId();
bool partFinish = getPartFinish();
if ( partId != 0
|| partFinish == false) {
out.add("part", ejson::Number(partId));
if (partFinish == true) {
out.add("finish", ejson::Boolean(partFinish));
}
}
if (getType() == jus::Buffer::typeMessage::call) {
out.add("call", ejson::String(getCall()));
ejson::Array listParam;
out.add("param", listParam);
for (int32_t iii=0; iii<getNumberParameter(); ++iii) {
std::string type = getParameterType(iii);
const uint8_t* dataPointer = getParameterPointer(iii);
uint32_t dataLenght = getParameterSize(iii);
ejson::Value param;
if (createType<bool>() == type) {
param = convertBinaryToJson<bool>(dataPointer, dataLenght);
} else if (createType<int8_t>() == type) {
param = convertBinaryToJson<int8_t>(dataPointer, dataLenght);
} else if (createType<int16_t>() == type) {
param = convertBinaryToJson<int16_t>(dataPointer, dataLenght);
} else if (createType<int32_t>() == type) {
param = convertBinaryToJson<int32_t>(dataPointer, dataLenght);
} else if (createType<int64_t>() == type) {
param = convertBinaryToJson<int64_t>(dataPointer, dataLenght);
} else if (createType<uint8_t>() == type) {
param = convertBinaryToJson<uint8_t>(dataPointer, dataLenght);
} else if (createType<uint16_t>() == type) {
param = convertBinaryToJson<uint16_t>(dataPointer, dataLenght);
} else if (createType<uint32_t>() == type) {
param = convertBinaryToJson<uint32_t>(dataPointer, dataLenght);
} else if (createType<uint64_t>() == type) {
param = convertBinaryToJson<uint64_t>(dataPointer, dataLenght);
} else if (createType<float>() == type) {
param = convertBinaryToJson<float>(dataPointer, dataLenght);
} else if (createType<double>() == type) {
param = convertBinaryToJson<double>(dataPointer, dataLenght);
} else if (createType<std::string>() == type) {
param = convertBinaryToJson<std::string>(dataPointer, dataLenght);
} else if (createType<std::vector<bool>>() == type) {
//param = convertBinaryToJson<std::vector<bool>>(dataPointer, dataLenght);
} else if (createType<std::vector<int8_t>>() == type) {
//param = convertBinaryToJson<std::vector<int8_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<int16_t>>() == type) {
//param = convertBinaryToJson<std::vector<int16_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<int32_t>>() == type) {
//param = convertBinaryToJson<std::vector<int32_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<int64_t>>() == type) {
//param = convertBinaryToJson<std::vector<int64_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<uint8_t>>() == type) {
//param = convertBinaryToJson<std::vector<uint8_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<uint16_t>>() == type) {
//param = convertBinaryToJson<std::vector<uint16_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<uint32_t>>() == type) {
//param = convertBinaryToJson<std::vector<uint32_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<uint64_t>>() == type) {
//param = convertBinaryToJson<std::vector<uint64_t>>(dataPointer, dataLenght);
} else if (createType<std::vector<float>>() == type) {
//param = convertBinaryToJson<std::vector<float>>(dataPointer, dataLenght);
} else if (createType<std::vector<double>>() == type) {
//param = convertBinaryToJson<std::vector<double>>(dataPointer, dataLenght);
} else if (createType<std::vector<std::string>>() == type) {
param = convertBinaryToJson<std::vector<std::string>>(dataPointer, dataLenght);
} else {
JUS_ERROR("Unknow param ==> can not convert ...");
}
listParam.add(param);
}
} else if (getType() == jus::Buffer::typeMessage::answer) {
} else if (getType() == jus::Buffer::typeMessage::event) {
JUS_ERROR(" NOT managed ...");
} else {
JUS_ERROR("Unknow TYPE ...");
}
return out;
}

View File

@ -5,9 +5,11 @@
*/ */
#pragma once #pragma once
#include <etk/types.h> #include <etk/types.h>
#include <ejson/ejson.h>
namespace jus { namespace jus {
//U32 message lenght //U32 message lenght
#pragma pack(push,1)
struct headerBin { struct headerBin {
uint32_t lenght; uint32_t lenght;
uint16_t versionProtocol; // protocol Version (might be 1) uint16_t versionProtocol; // protocol Version (might be 1)
@ -15,15 +17,9 @@ namespace jus {
uint32_t clientID; // same as sevice ID uint32_t clientID; // same as sevice ID
int16_t partID; // if < 0 the partId ifs the last (start at 0 if multiple or 0x8000 if single message) int16_t partID; // if < 0 the partId ifs the last (start at 0 if multiple or 0x8000 if single message)
uint16_t typeMessage; //TypeMessgae (1:call, 2:Answer, 4:event) uint16_t typeMessage; //TypeMessgae (1:call, 2:Answer, 4:event)
void clear() { uint16_t numberOfParameter; //TypeMessgae (1:call, 2:Answer, 4:event)
lenght = 0;
versionProtocol = 1;
transactionID = 1;
clientID = 0;
partID = 0x8000;
typeMessage = 1;
}
}; };
#pragma pack(pop)
/* /*
// not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0 // not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0
====================== ======================
@ -114,29 +110,29 @@ namespace jus {
void composeWith(const std::vector<uint8_t>& _buffer); void composeWith(const std::vector<uint8_t>& _buffer);
std::string generateHumanString(); std::string generateHumanString();
void clear(); void clear();
uint16_t getProtocalVersion(); uint16_t getProtocalVersion() const;
void setProtocolVersion(uint16_t _value); void setProtocolVersion(uint16_t _value);
uint32_t getTransactionId(); uint32_t getTransactionId() const;
void setTransactionId(uint32_t _value); void setTransactionId(uint32_t _value);
uint32_t getClientId();// this is the same as serviceId uint32_t getClientId() const;// this is the same as serviceId
void setClientId(uint32_t _value); void setClientId(uint32_t _value);
uint32_t getServiceId() { uint32_t getServiceId() const {
return getClientId(); return getClientId();
} }
void setServiceId(uint32_t _value) { void setServiceId(uint32_t _value) {
setClientId(_value); setClientId(_value);
} }
// note limited 15 bits // note limited 15 bits
uint16_t getPartId(); uint16_t getPartId() const;
void setPartId(uint16_t _value); void setPartId(uint16_t _value);
bool getPartFinish(); bool getPartFinish() const;
void setPartFinish(bool _value); void setPartFinish(bool _value);
enum class typeMessage { enum class typeMessage {
call = 0x0001, call = 0x0001,
answer = 0x0002, answer = 0x0002,
event = 0x0004, event = 0x0004,
}; };
enum typeMessage getType(); enum typeMessage getType() const;
void setType(enum typeMessage _value); void setType(enum typeMessage _value);
// =============================================== // ===============================================
@ -144,18 +140,24 @@ namespace jus {
// =============================================== // ===============================================
private: private:
template<class JUS_TYPE_DATA> template<class JUS_TYPE_DATA>
JUS_TYPE_DATA internalGetParameter(int32_t _id); JUS_TYPE_DATA internalGetParameter(int32_t _id) const;
std::string internalGetParameterType(int32_t _id) const;
const uint8_t* internalGetParameterPointer(int32_t _id) const;
uint32_t internalGetParameterSize(int32_t _id) const;
public: public:
std::string getCall(); std::string getCall() const;
void setCall(std::string _value); void setCall(std::string _value);
uint16_t getNumberParameter(); uint16_t getNumberParameter() const;
std::string getParameterType(int32_t _id) const;
const uint8_t* getParameterPointer(int32_t _id) const;
uint32_t getParameterSize(int32_t _id) const;
template<class JUS_TYPE_DATA> template<class JUS_TYPE_DATA>
void addParameter(const JUS_TYPE_DATA& _value); void addParameter(const JUS_TYPE_DATA& _value);
void addParameter(); void addParameter();
template<class JUS_TYPE_DATA> template<class JUS_TYPE_DATA>
JUS_TYPE_DATA getParameter(int32_t _id) { JUS_TYPE_DATA getParameter(int32_t _id) const {
return internalGetParameter<JUS_TYPE_DATA>(_id+1); return internalGetParameter<JUS_TYPE_DATA>(_id+1);
} }
@ -169,7 +171,14 @@ namespace jus {
addParameter(_value); addParameter(_value);
} }
void addError(const std::string& _value, const std::string& _comment); void addError(const std::string& _value, const std::string& _comment);
void prepare();
ejson::Object toJson() const;
}; };
std::ostream& operator <<(std::ostream& _os, const std::vector<enum jus::Buffer::typeMessage>& _value); std::ostream& operator <<(std::ostream& _os, enum jus::Buffer::typeMessage _value);
template<class JUS_TYPE>
ejson::Value convertBinaryToJson(const uint8_t* _data, uint32_t _size);
} }

View File

@ -0,0 +1,106 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#include <jus/Buffer.h>
#include <jus/debug.h>
#include <jus/ParamType.h>
namespace jus {
// ----------------------------------------------------------------------------------------------------
template<> ejson::Value convertBinaryToJson<bool>(const uint8_t* _data, uint32_t _size) {
const bool* value = reinterpret_cast<const bool*>(_data);
return ejson::Boolean(*value);
}
template<> ejson::Value convertBinaryToJson<std::vector<bool>>(const uint8_t* _data, uint32_t _size) {
const bool* value = reinterpret_cast<const bool*>(_data);
ejson::Array out;
for (size_t iii=0; iii<_size; ++iii) {
out.add(ejson::Boolean(value[iii]));
}
return out;
}
template<> ejson::Value convertBinaryToJson<float>(const uint8_t* _data, uint32_t _size) {
const float* value = reinterpret_cast<const float*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<double>(const uint8_t* _data, uint32_t _size) {
const double* value = reinterpret_cast<const double*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<int64_t>(const uint8_t* _data, uint32_t _size) {
const int64_t* value = reinterpret_cast<const int64_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<int32_t>(const uint8_t* _data, uint32_t _size) {
const int32_t* value = reinterpret_cast<const int32_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<int16_t>(const uint8_t* _data, uint32_t _size) {
const int16_t* value = reinterpret_cast<const int16_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<int8_t>(const uint8_t* _data, uint32_t _size) {
const int8_t* value = reinterpret_cast<const int8_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<uint64_t>(const uint8_t* _data, uint32_t _size) {
const uint64_t* value = reinterpret_cast<const uint64_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<uint32_t>(const uint8_t* _data, uint32_t _size) {
const uint32_t* value = reinterpret_cast<const uint32_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<uint16_t>(const uint8_t* _data, uint32_t _size) {
const uint16_t* value = reinterpret_cast<const uint16_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<uint8_t>(const uint8_t* _data, uint32_t _size) {
const uint8_t* value = reinterpret_cast<const uint8_t*>(_data);
return ejson::Number(*value);
}
template<> ejson::Value convertBinaryToJson<std::string>(const uint8_t* _data, uint32_t _size) {
std::string val;
val.resize(_size, '\0');
memcpy(&val[0], _data, _size);
return ejson::String(val);
}
template<> ejson::Value convertBinaryToJson<std::vector<std::string>>(const uint8_t* _data, uint32_t _size) {
/*
Little hard ... TODO : ...
const bool* value = reinterpret_cast<const bool*>(_data);
ejson::Array out;
for (size_t iii=0; iii<_size; ++iii) {
out.add(ejson::Boolean(value[iii]));
}
return out;
*/
ejson::Array out;
return out;
}
/*
template<> ejson::Value convertBinaryToJson<jus::File>(const uint8_t* _data, uint32_t _size) {
ejson::Object out;
out.add("type", ejson::String("file"));
out.add("mine-type", ejson::String(_value.getMineType()));
out.add("size", ejson::Number(_value.getData().size()));
if (_value.getData().size() != 0) {
_asyncAction.push_back(SenderJusFile(_value, _paramId));
}
return out;
}
*/
// ----------------------------------------------------------------------------------------------------
}

View File

@ -279,7 +279,6 @@ class SendAsyncBinary {
obj.setTransactionId(m_transactionId); obj.setTransactionId(m_transactionId);
obj.setPartId(m_partId); obj.setPartId(m_partId);
obj.setPartFinish(true); obj.setPartFinish(true);
JUS_DEBUG("Send BINARY '" << obj.generateHumanString() << "'");
_interface->writeBinary(obj); _interface->writeBinary(obj);
return true; return true;
} }
@ -310,7 +309,6 @@ jus::FutureBase jus::Client::callBinary(uint64_t _transactionId,
} else { } else {
_obj.setPartFinish(true); _obj.setPartFinish(true);
} }
JUS_DEBUG("Send Binary '" << _obj.generateHumanString() << "'");
m_interfaceClient.writeBinary(_obj); m_interfaceClient.writeBinary(_obj);
if (_async.size() != 0) { if (_async.size() != 0) {

View File

@ -98,7 +98,6 @@ void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::s
answer.setType(jus::Buffer::typeMessage::answer); answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId); answer.setTransactionId(_clientTransactionId);
answer.addError(protocolError, _errorHelp); answer.addError(protocolError, _errorHelp);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.writeBinary(answer); m_interfaceClient.writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) { } else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... "); JUS_ERROR("TODO ... ");
@ -107,19 +106,19 @@ void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::s
} }
} }
void jus::GateWayClient::onClientDataRaw(const jus::Buffer& _value) { void jus::GateWayClient::onClientDataRaw(jus::Buffer& _value) {
uint32_t transactionId = _value.getTransactionId();
}
void jus::GateWayClient::onClientData(std::string _value) {
JUS_DEBUG("On data: " << _value);
ejson::Object data(_value);
uint64_t transactionId = data["id"].toNumber().getU64();
if (transactionId == 0) { if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id"); JUS_ERROR("Protocol error ==>missing id");
answerProtocolError(transactionId, "missing parameter: 'id'"); answerProtocolError(transactionId, "missing parameter: 'id'");
return; return;
} }
if (_value.getType() != jus::Buffer::typeMessage::call) {
JUS_ERROR("Protocol error ==>missing 'call'");
answerProtocolError(transactionId, "missing parameter: 'call' / wrong type 'call'");
return;
}
std::string callFunction = _value.getCall();
switch (m_state) { switch (m_state) {
case jus::GateWayClient::state::disconnect: case jus::GateWayClient::state::disconnect:
case jus::GateWayClient::state::unconnect: case jus::GateWayClient::state::unconnect:
@ -134,21 +133,20 @@ void jus::GateWayClient::onClientData(std::string _value) {
answerProtocolError(transactionId, "Gateway internal error 2"); answerProtocolError(transactionId, "Gateway internal error 2");
return; return;
} }
std::string call = data["call"].toString().get(); if (callFunction == "setMode") {
if (call == "setMode") { std::string mode = _value.getParameter<std::string>(0);
std::string mode = data["param"].toArray()[0].toString().get();
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_interfaceMode = jus::connectionMode::modeJson; m_interfaceMode = jus::connectionMode::modeJson;
m_interfaceClient.connectCleanRaw(); m_interfaceClient.connectCleanRaw();
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData); m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
answerValue(transactionId, true);
} 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_interfaceMode = jus::connectionMode::modeBinary; m_interfaceMode = jus::connectionMode::modeBinary;
m_interfaceClient.connectClean(); m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw); m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw);
answerValue(transactionId, true);
} 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;
@ -157,26 +155,18 @@ void jus::GateWayClient::onClientData(std::string _value) {
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]");
} }
return; return;
} else if (call == "connectToUser") { } else if (callFunction == "connectToUser") {
m_userConnectionName = data["param"].toArray()[0].toString().get(); m_userConnectionName = _value.getParameter<std::string>(0);
if (m_userConnectionName == "") { if (m_userConnectionName == "") {
answerProtocolError(transactionId, "Call connectToUser with no parameter 'user'"); answerProtocolError(transactionId, "Call connectToUser with no parameter 'user'");
} else { } else {
JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'"); JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'");
m_userService = m_gatewayInterface->get("system-user"); m_userService = m_gatewayInterface->get("system-user");
if (m_userService == nullptr) { if (m_userService == nullptr) {
answerProtocolError(transactionId, "Gateway internal error 'No user interface'"); answerProtocolError(transactionId, "Gateway internal error 'No user interface'");
} else { } else {
ejson::Object linkService; jus::Future<bool> futLocalService = call(m_uid2, m_userService, "_new", m_userConnectionName, "**Gateway**", std::vector<std::string>());
linkService.add("call", ejson::String("_new")); futLocalService.wait(); // TODO: Set timeout ...
linkService.add("id", ejson::Number(m_transactionLocalId++));
ejson::Array params;
params.add(ejson::String(m_userConnectionName));
params.add(ejson::String("**Gateway**"));
params.add(ejson::Array());
linkService.add("param", params);
m_userService->SendData(m_uid2, linkService);
m_state = jus::GateWayClient::state::userIdentify; m_state = jus::GateWayClient::state::userIdentify;
answerValue(transactionId, true); answerValue(transactionId, true);
} }
@ -189,7 +179,291 @@ void jus::GateWayClient::onClientData(std::string _value) {
} }
case jus::GateWayClient::state::userIdentify: 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 = _value.getParameter<std::string>(0);
std::string clientTocken = _value.getParameter<std::string>(1);
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 = _value.getParameter<std::string>(0);
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:
{
uint32_t serviceId = _value.getServiceId();
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());
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 = _value.getParameter<std::string>(0);
// 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: the service we want to unconnect ...
int64_t localServiceID = _value.getParameter<int64_t>(0)-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;
}
// decrease service ID ...
serviceId -= 1;
if (serviceId >= m_listConnectedService.size()) {
answerError(transactionId, "NOT-CONNECTED-SERVICE");
return;
} else {
if (m_listConnectedService[serviceId] == nullptr) {
// TODO ...
JUS_ERROR("TODO : Manage this case ...");
return;
}
bool finish = _value.getPartFinish();
uint16_t partId = _value.getPartId();
if (partId != 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 ...
_value.setTransactionId(itCall.second.getTransactionId());
m_listConnectedService[serviceId]->SendData(m_uid, _value);
return;
}
}
JUS_ERROR("Can not transfer part of a message ...");
return;
}
callActionForward(m_listConnectedService[serviceId],
_value,
[=](jus::FutureBase _ret) {
// TODO : Check if it is a JSON or binary ...
ejson::Object tmpp = _ret.getRaw();
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());
if (tmpp.valueExist("part") == true) {
// multiple send element ...
if (tmpp.valueExist("finish") == true) {
return tmpp["finish"].toBoolean().get();
}
return false;
}
return true;
});
}
}
}
}
void jus::GateWayClient::onClientData(std::string _value) {
JUS_DEBUG("On data: " << _value);
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(); 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_clientServices.clear();
m_clientgroups.clear(); m_clientgroups.clear();
m_clientName.clear(); m_clientName.clear();
@ -281,24 +555,13 @@ void jus::GateWayClient::onClientData(std::string _value) {
if ( numService.exist() == false if ( numService.exist() == false
|| numService.getU64() == 0) { || numService.getU64() == 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:
std::string callFunction = data["call"].toString().get();
ejson::Object answer;
answer.add("id", data["id"]);
if (callFunction == "getServiceCount") { if (callFunction == "getServiceCount") {
answer.add("return", ejson::Number(m_clientServices.size())); answerValue(transactionId, m_clientServices.size());
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (callFunction == "getServiceList") { if (callFunction == "getServiceList") {
ejson::Array listService; answerValue(transactionId, m_clientServices);
for (auto &it : m_clientServices) {
listService.add(ejson::String(it));
}
//listService.add(ejson::String("ServiceManager/v0.1.0")); //listService.add(ejson::String("ServiceManager/v0.1.0"));
answer.add("return", listService);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (callFunction == "link") { if (callFunction == "link") {
@ -320,38 +583,26 @@ void jus::GateWayClient::onClientData(std::string _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()) {
answer.add("error", ejson::String("UN-AUTHORIZED-SERVICE")); answerError(transactionId, "UN-AUTHORIZED-SERVICE");
JUS_DEBUG("answer: (NOT authorized service) " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName); ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
if (srv != nullptr) { if (srv != nullptr) {
ejson::Object linkService; jus::Future<bool> futLink = call(m_uid, srv, "_new", m_userConnectionName, m_clientName, m_clientgroups);
linkService.add("call", ejson::String("_new")); futLink.wait(); // TODO: Set timeout ...
linkService.add("id", ejson::Number(m_transactionLocalId++)); if (futLink.hasError() == true) {
ejson::Array params; JUS_ERROR("Get error from the service ... LINK");
params.add(ejson::String(m_userConnectionName)); answerError(transactionId, "ERROR-CREATE-SERVICE-INSTANCE");
params.add(ejson::String(m_clientName)); return;
// TODO ==> remove events ...
std::vector<ActionAsyncClient> asyncAction;
params.add(convertToJson(asyncAction, 0, m_clientgroups));
linkService.add("param", params);
if (asyncAction.size() != 0) {
JUS_ERROR("Missing send async messages");
} }
srv->SendData(m_uid, linkService);
m_listConnectedService.push_back(srv); m_listConnectedService.push_back(srv);
answer.add("return", ejson::Number(m_listConnectedService.size())); answerValue(transactionId, m_listConnectedService.size());
} else { return;
answer.add("error", ejson::String("CAN-NOT-CONNECT-SERVICE"));
} }
} else { answerError(transactionId, "CAN-NOT-CONNECT-SERVICE");
// TODO : Service already connected; return;
answer.add("return", ejson::Boolean(false));
} }
JUS_DEBUG("answer: " << answer.generateHumanString()); answerError(transactionId, "SERVICE-ALREADY-CONNECTED");;
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (callFunction == "unlink") { if (callFunction == "unlink") {
@ -359,27 +610,22 @@ void jus::GateWayClient::onClientData(std::string _value) {
int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1; int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1;
// Check if service already link: // Check if service already link:
if (localServiceID >= m_listConnectedService.size()) { if (localServiceID >= m_listConnectedService.size()) {
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE")); answerError(transactionId, "NOT-CONNECTED-SERVICE");
JUS_DEBUG("answer: " << answer.generateHumanString()); return;
m_interfaceClient.write(answer.generateMachineString()); }
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; return;
} }
ejson::Object linkService;
linkService.add("call", ejson::String("_delete"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
ejson::Array params;
linkService.add("param", params);
m_listConnectedService[localServiceID]->SendData(m_uid, linkService);
m_listConnectedService[localServiceID] = nullptr; m_listConnectedService[localServiceID] = nullptr;
answer.add("return", ejson::Boolean(true)); answerValue(transactionId, true);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
JUS_ERROR("Function does not exist ... '" << callFunction << "'"); JUS_ERROR("Function does not exist ... '" << callFunction << "'");
answer.add("error", ejson::String("CALL-UNEXISTING")); answerError(transactionId, "CALL-UNEXISTING");
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
@ -476,11 +722,53 @@ jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId,
return ret; return ret;
} }
jus::FutureBase jus::GateWayClient::callBinary(uint64_t _callerId,
ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId,
uint64_t _transactionId,
jus::Buffer& _obj,
jus::FutureData::ObserverFinish _callback) {
JUS_VERBOSE("Send BINARY [START] ");
if (_srv == nullptr) {
// TODO : Change this ...
jus::Buffer obj;
obj.setTransactionId(_transactionId);
obj.setClientId(_callerId);
obj.setType(jus::Buffer::typeMessage::answer);
obj.addError("NOT-CONNECTED", "Client interface not connected (no TCP)");
return jus::FutureBase(_transactionId, true, obj, _callback);
}
jus::FutureBase tmpFuture(_transactionId, _callback);
{
std::unique_lock<std::mutex> lock(m_mutex);
m_pendingCall.push_back(std::make_pair(_clientTransactionId, tmpFuture));
}
_srv->SendData(_callerId, _obj);
JUS_VERBOSE("Send BINARY [STOP]");
return tmpFuture;
}
jus::FutureBase jus::GateWayClient::callActionForward(ememory::SharedPtr<jus::GateWayService> _srv,
jus::Buffer& _Buffer,
jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
uint64_t clientTransactionId = _Buffer.getTransactionId();
jus::FutureBase ret = callBinary(m_uid, _srv, clientTransactionId, id, _Buffer, _callback);
ret.setSynchronous();
return ret;
}
uint64_t jus::GateWayClient::getId() { uint64_t jus::GateWayClient::getId() {
return m_transactionLocalId++; return m_transactionLocalId++;
} }
jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, uint64_t _clientTransactionId, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) { jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId,
ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId,
uint64_t _transactionId,
const ejson::Object& _obj,
jus::FutureData::ObserverFinish _callback) {
JUS_VERBOSE("Send JSON [START] "); JUS_VERBOSE("Send JSON [START] ");
if (_srv == nullptr) { if (_srv == nullptr) {
ejson::Object obj; ejson::Object obj;
@ -500,6 +788,8 @@ jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::Shared
void jus::GateWayClient::returnMessage(ejson::Object _data) { void jus::GateWayClient::returnMessage(ejson::Object _data) {
jus::FutureBase future; jus::FutureBase future;
uint64_t tid = _data["id"].toNumber().get(); uint64_t tid = _data["id"].toNumber().get();

View File

@ -49,7 +49,7 @@ 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(const jus::Buffer& _value); void onClientDataRaw(jus::Buffer& _value);
void onClientData(std::string _value); void onClientData(std::string _value);
void returnMessage(ejson::Object _data); void returnMessage(ejson::Object _data);
bool checkId(uint64_t _id) const { bool checkId(uint64_t _id) const {
@ -64,6 +64,12 @@ namespace jus {
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,
ememory::SharedPtr<jus::GateWayService> _srv,
uint64_t _clientTransactionId,
uint64_t _transactionId,
jus::Buffer& _obj,
jus::FutureData::ObserverFinish _callback=nullptr);
uint64_t getId(); uint64_t getId();
public: public:
template<class... _ARGS> template<class... _ARGS>
@ -125,6 +131,9 @@ namespace jus {
void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment=""); 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);
}; };
} }

View File

@ -11,7 +11,8 @@
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("-----------------");
@ -43,6 +44,22 @@ void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data)
JUS_DEBUG("Send Service: " << _data.generateHumanString()); JUS_DEBUG("Send Service: " << _data.generateHumanString());
m_interfaceClient.write(_data.generateMachineString()); m_interfaceClient.write(_data.generateMachineString());
} }
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 ... ");
ejson::Object obj = _data.toJson();
JUS_DEBUG("Send Service: " << obj.generateHumanString());
m_interfaceClient.write(obj.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("NOT manage transcriptioon binary to XML ... ");
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
m_interfaceClient.writeBinary(_data);
} else {
JUS_ERROR("NOT manage transcriptioon binary to ??? mode ... ");
}
}
void jus::GateWayService::onServiceData(std::string _value) { void jus::GateWayService::onServiceData(std::string _value) {
JUS_DEBUG("On service data: " << _value); JUS_DEBUG("On service data: " << _value);

View File

@ -9,6 +9,7 @@
#include <ememory/memory.h> #include <ememory/memory.h>
#include <esignal/Signal.h> #include <esignal/Signal.h>
#include <ejson/ejson.h> #include <ejson/ejson.h>
#include <jus/connectionMode.h>
namespace jus { namespace jus {
class GateWay; class GateWay;
@ -17,6 +18,7 @@ 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:
@ -27,6 +29,7 @@ namespace jus {
void onServiceData(std::string _value); void onServiceData(std::string _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);
const std::string& getName() { const std::string& getName() {
return m_name; return m_name;
} }

View File

@ -22,6 +22,12 @@ bool jus::ParamType::operator == (const ParamType& _obj) const {
return m_typeName == _obj.m_typeName; return m_typeName == _obj.m_typeName;
} }
bool jus::ParamType::operator == (const std::string& _value) const {
return _value == m_typeName;
}
bool jus::ParamType::operator != (const std::string& _value) const {
return _value != m_typeName;
}
#define generate_basic_type(_type, _name) \ #define generate_basic_type(_type, _name) \
namespace jus { \ namespace jus { \

View File

@ -4,6 +4,9 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#pragma once #pragma once
#include <string>
namespace jus { namespace jus {
class ParamType { class ParamType {
protected: protected:
@ -12,6 +15,8 @@ namespace jus {
ParamType(const char* _name = ""); ParamType(const char* _name = "");
const char* getName() const; const char* getName() const;
bool operator == (const ParamType& _obj) const; bool operator == (const ParamType& _obj) const;
bool operator == (const std::string& _value) const;
bool operator != (const std::string& _value) const;
}; };

View File

@ -55,7 +55,7 @@ void jus::TcpString::threadCallback() {
} }
} else if (m_observerRawElement != nullptr) { } else if (m_observerRawElement != nullptr) {
jus::Buffer data = std::move(readRaw()); jus::Buffer data = std::move(readRaw());
m_observerRawElement(std::move(data)); m_observerRawElement(data);
} }
} }
m_threadRunning = false; m_threadRunning = false;
@ -134,7 +134,9 @@ int32_t jus::TcpString::write(const std::string& _data) {
m_connection.write(&size, 4); m_connection.write(&size, 4);
return m_connection.write(_data.c_str(), _data.size()); return m_connection.write(_data.c_str(), _data.size());
} }
int32_t jus::TcpString::writeBinary(const jus::Buffer& _data) { int32_t jus::TcpString::writeBinary(jus::Buffer& _data) {
_data.prepare();
JUS_DEBUG("Send BINARY '" << _data.generateHumanString() << "'");
if (m_threadRunning == false) { if (m_threadRunning == false) {
return -2; return -2;
} }
@ -144,9 +146,11 @@ int32_t jus::TcpString::writeBinary(const jus::Buffer& _data) {
} }
*/ */
//uint32_t size = _data.size(); //uint32_t size = _data.size();
const uint8_t* data = nullptr;
uint32_t dataSize = 0;
m_lastSend = std::chrono::steady_clock::now(); m_lastSend = std::chrono::steady_clock::now();
const uint8_t* data = _data.getHeader(); data = _data.getHeader();
uint32_t dataSize = _data.getHeaderSize(); dataSize = _data.getHeaderSize();
m_connection.write(data, dataSize); m_connection.write(data, dataSize);
data = _data.getParam(); data = _data.getParam();
dataSize = _data.getParamSize(); dataSize = _data.getParamSize();

View File

@ -21,7 +21,7 @@ namespace jus {
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(std::string)>; //!< Define an Observer: function pointer
using ObserverRaw = std::function<void(const 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; ObserverRaw m_observerRawElement;
/** /**
@ -40,9 +40,9 @@ namespace jus {
m_observerElement = nullptr; m_observerElement = nullptr;
} }
template<class CLASS_TYPE> template<class CLASS_TYPE>
void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(const jus::Buffer&)) { void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(jus::Buffer&)) {
m_observerRawElement = [=](const jus::Buffer& _value){ m_observerRawElement = [=](jus::Buffer& _value){
(*_class.*_func)(std::move(_value)); (*_class.*_func)(_value);
}; };
} }
void connectCleanRaw() { void connectCleanRaw() {
@ -58,7 +58,7 @@ namespace jus {
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 write(const std::string& _data);
int32_t writeBinary(const jus::Buffer& _data); int32_t writeBinary(jus::Buffer& _data);
std::string asyncRead(); std::string asyncRead();
private: private:
std::string read(); std::string read();

View File

@ -39,6 +39,7 @@ def create(target, module_name):
'jus/Future.cpp', 'jus/Future.cpp',
'jus/File.cpp', 'jus/File.cpp',
'jus/Buffer.cpp', 'jus/Buffer.cpp',
'jus/BufferConvertBinaryToJson.cpp',
'jus/ParamType.cpp', 'jus/ParamType.cpp',
'jus/Client.cpp', 'jus/Client.cpp',
'jus/GateWay.cpp', 'jus/GateWay.cpp',