[DEV] continue work on binary transfer

This commit is contained in:
Edouard DUPIN 2016-06-08 21:40:42 +02:00
parent ce5dc052f6
commit 0d73df3593
15 changed files with 630 additions and 53 deletions

View File

@ -163,10 +163,10 @@ namespace jus {
~SenderJusFile() {
}
bool operator() (TcpString* _interface, const std::string& _service, uint64_t _transactionId, uint64_t _part) {
bool operator() (TcpString* _interface, const uint32_t& _serviceId, uint64_t _transactionId, uint64_t _part) {
ejson::Object answer;
if (_service != "") {
answer.add("service", ejson::String(_service));
if (_serviceId != 0) {
answer.add("service", ejson::Number(_serviceId));
}
answer.add("id", ejson::Number(_transactionId));
answer.add("part", ejson::Number(_part));
@ -251,6 +251,9 @@ namespace jus {
}
}
// ============================================================
// == JSON
// ============================================================
ejson::Object jus::createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params) {
ejson::Object callElem = createBaseCall(_transactionId, _functionName);
@ -271,6 +274,28 @@ void jus::createParam(std::vector<ActionAsyncClient>& _asyncAction, int32_t _par
// Finish recursive parse ...
}
// ============================================================
// == Binary
// ============================================================
jus::Buffer jus::createBinaryCall(uint64_t _transactionId, const std::string& _functionName, const jus::Buffer& _params) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName);
//callElem.add("param", _params);
return callElem;
}
jus::Buffer jus::createBinaryBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId) {
jus::Buffer obj;
obj.setServiceId(_serviceId);
obj.setCall(_functionName);
obj.setTransactionId(_transactionId);
return obj;
}
void jus::createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction, int32_t _paramId, jus::Buffer& _obj) {
// Finish recursive parse ...
}
enum jus::AbstractFunction::type jus::AbstractFunction::getType() const {
return m_type;
}

View File

@ -61,7 +61,7 @@ namespace jus {
};
// define basic async call element ...
using ActionAsyncClient = std::function<bool(TcpString* _interface, const std::string& _service, uint64_t _transactionId, uint64_t _part)>;
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);
@ -74,6 +74,9 @@ namespace jus {
//ejson::Value convertToJson(std::vector<ActionAsyncClient>& _asyncAction, int32_t _paramId, const char* _value);
// ============================================================
// == JSON
// ============================================================
ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service="");
void createParam(std::vector<ActionAsyncClient>& _asyncAction,
@ -103,8 +106,6 @@ namespace jus {
_ARGS&&... _args) {
createParam(_asyncAction, _paramId, _obj, std::string(_param), std::forward<_ARGS>(_args)...);
}
template<class... _ARGS>
ejson::Object createCall(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_transactionId, _functionName);
@ -119,5 +120,47 @@ namespace jus {
}
ejson::Object createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params);
// ============================================================
// == Binary
// ============================================================
jus::Buffer createBinaryBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId=0);
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj);
template<class JUS_TYPE, class... _ARGS>
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj,
const JUS_TYPE& _param,
_ARGS&&... _args) {
_obj.addParameter<JUS_TYPE>(/*_asyncAction, _paramId,*/ _param);
_paramId++;
createBinaryParam(_asyncAction, _paramId, _obj, std::forward<_ARGS>(_args)...);
}
// convert const char in std::string ...
template<class... _ARGS>
void createBinaryParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
jus::Buffer& _obj,
const char* _param,
_ARGS&&... _args) {
createBinaryParam(_asyncAction, _paramId, _obj, std::string(_param), std::forward<_ARGS>(_args)...);
}
template<class... _ARGS>
jus::Buffer createBinaryCall(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const std::string& _functionName, _ARGS&&... _args) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName);
createBinaryParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...);
return callElem;
}
template<class... _ARGS>
jus::Buffer createBinaryCallService(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const uint32_t& _serviceName, const std::string& _functionName, _ARGS&&... _args) {
jus::Buffer callElem = createBinaryBaseCall(_transactionId, _functionName, _serviceName);
createBinaryParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...);
return callElem;
}
jus::Buffer createBinaryCall(uint64_t _transactionId, const std::string& _functionName, const jus::Buffer& _params);
}

View File

@ -0,0 +1,333 @@
/** @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>
jus::Buffer::Buffer() {
clear();
}
void jus::Buffer::clear() {
m_data.clear();
m_paramOffset.clear();
m_header.clear();
}
std::string jus::Buffer::generateHumanString() {
return "jus::Buffer ...";
}
uint16_t jus::Buffer::getProtocalVersion() {
return m_header.versionProtocol;
}
void jus::Buffer::setProtocolVersion(uint16_t _value) {
m_header.versionProtocol = _value;
}
uint32_t jus::Buffer::getTransactionId() {
return m_header.transactionID;
}
void jus::Buffer::setTransactionId(uint32_t _value) {
m_header.transactionID = _value;
}
uint32_t jus::Buffer::getClientId() {
return m_header.clientID;
}
void jus::Buffer::setClientId(uint32_t _value) {
m_header.clientID = _value;
}
// note limited 15 bits
uint16_t jus::Buffer::getPartId() {
return uint16_t(m_header.partID & 0x7FFF);
}
void jus::Buffer::setPartId(uint16_t _value) {
m_header.partID = (m_header.partID&0x8000) | (_value & 0x7FFF);
}
bool jus::Buffer::getPartFinish() {
return m_header.versionProtocol<0;
}
void jus::Buffer::setPartFinish(bool _value) {
if (_value == true) {
m_header.versionProtocol = (m_header.versionProtocol & 0x7FFF) | 0x8000;
} else {
m_header.versionProtocol = m_header.versionProtocol & 0x7FFF;
}
}
enum jus::Buffer::typeMessage jus::Buffer::getType() {
return (enum jus::Buffer::typeMessage)m_header.typeMessage;
}
void jus::Buffer::setType(enum typeMessage _value) {
m_header.typeMessage = uint16_t(_value);
}
uint16_t jus::Buffer::getNumberParameter() {
return m_paramOffset.size()-1;
}
template<>
void jus::Buffer::addParameter<std::string>(const std::string& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('s');
m_data.push_back('t');
m_data.push_back('r');
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('g');
m_data.push_back('\0');
m_data.resize(m_data.size()+_value.size()+1);
memcpy(&m_data[currentOffset], &_value[0], m_data.size());
}
template<>
void jus::Buffer::addParameter<int8_t>(const int8_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('8');
m_data.push_back('\0');
m_data.push_back(uint8_t(_value));
}
template<>
void jus::Buffer::addParameter<uint8_t>(const uint8_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('u');
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('8');
m_data.push_back('\0');
m_data.push_back(_value);
}
template<>
void jus::Buffer::addParameter<int16_t>(const int16_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('1');
m_data.push_back('6');
m_data.push_back('\0');
m_data.resize(m_data.size()+2);
memcpy(&m_data[currentOffset], &_value, 2);
}
template<>
void jus::Buffer::addParameter<uint16_t>(const uint16_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('u');
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('1');
m_data.push_back('6');
m_data.push_back('\0');
m_data.resize(m_data.size()+2);
memcpy(&m_data[currentOffset], &_value, 2);
}
template<>
void jus::Buffer::addParameter<int32_t>(const int32_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('3');
m_data.push_back('2');
m_data.push_back('\0');
m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4);
}
template<>
void jus::Buffer::addParameter<uint32_t>(const uint32_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('u');
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('3');
m_data.push_back('2');
m_data.push_back('\0');
m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4);
}
template<>
void jus::Buffer::addParameter<int64_t>(const int64_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('3');
m_data.push_back('2');
m_data.push_back('\0');
m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8);
}
template<>
void jus::Buffer::addParameter<uint64_t>(const uint64_t& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('u');
m_data.push_back('i');
m_data.push_back('n');
m_data.push_back('t');
m_data.push_back('6');
m_data.push_back('4');
m_data.push_back('\0');
m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8);
}
template<>
void jus::Buffer::addParameter<float>(const float& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('f');
m_data.push_back('l');
m_data.push_back('o');
m_data.push_back('a');
m_data.push_back('t');
m_data.push_back('\0');
m_data.resize(m_data.size()+4);
memcpy(&m_data[currentOffset], &_value, 4);
}
template<>
void jus::Buffer::addParameter<double>(const double& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('d');
m_data.push_back('o');
m_data.push_back('u');
m_data.push_back('b');
m_data.push_back('l');
m_data.push_back('e');
m_data.push_back('\0');
m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8);
}
template<>
std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) {
std::string out;
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:
char* type = reinterpret_cast<char*>(&m_data[startPos]); // Will be stop with \0 ...
if (strcmp(type, "string") == 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 {
// Allocate data
out.resize(dataSize, ' ');
memcpy(&out[0], &m_data[startPos], dataSize);
}
} else {
//wrong type ...
JUS_ERROR("Can not convert '" << type << "' into 'string'");
}
return out;
}
template<>
int8_t jus::Buffer::internalGetParameter<int8_t>(int32_t _id) {
int8_t out;
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:
char* type = reinterpret_cast<char*>(&m_data[startPos]); // Will be stop with \0 ...
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;
}
std::string jus::Buffer::getCall() {
std::string out;
switch(getType()) {
case jus::Buffer::typeMessage::call:
return internalGetParameter<std::string>(0);
break;
case jus::Buffer::typeMessage::answer:
JUS_WARNING("get 'call' with an input type: 'answer'");
break;
case jus::Buffer::typeMessage::event:
JUS_WARNING("get 'call' with an input type: 'event'");
break;
default:
JUS_ERROR("unknow type: " << uint16_t(getType()));
break;
}
return "";
}
void jus::Buffer::setCall(std::string _value) {
if (m_paramOffset.size() != 0) {
JUS_ERROR("Clear Buffer of parameter ==> set the call type in first ...");
m_paramOffset.clear();
m_data.clear();
}
addParameter(_value);
}

View File

@ -7,14 +7,24 @@
#include <etk/types.h>
namespace jus {
//U32 message lenght
struct headerBin {
uint32_t lenght;
uint16_t versionProtocol; // protocol Version (might be 1)
uint32_t transactionID;
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)
uint16_t typeMessage; //TypeMessgae (1:call, 2:Answer, 4:event)
void clear() {
lenght = 0;
versionProtocol = 1;
transactionID = 1;
clientID = 0;
partID = 0x8000;
typeMessage = 1;
}
};
/*
U32 message lenght
U16 protocol Version (might be 1)
U32 transactionID;
U32 clientID; ==> sevice ID
U1 finish part
U15 partID;
U16 TypeMessgae (1:call, 2:Answer, 4:event)
// not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0
======================
== call
@ -73,10 +83,13 @@ namespace jus {
*/
class Buffer {
private:
headerBin m_header;
std::vector<uint16_t> m_paramOffset;
std::vector<uint8_t> m_data;
public:
Buffer();
clear();
std::string generateHumanString();
void clear();
uint16_t getProtocalVersion();
void setProtocolVersion(uint16_t _value);
uint32_t getTransactionId();
@ -98,12 +111,15 @@ namespace jus {
call = 0x0001,
answer = 0x0002,
event = 0x0004,
}
};
enum typeMessage getType();
void setType(enum typeMessage _value);
// ===============================================
// == Section call
// ===============================================
private:
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA internalGetParameter(int32_t _id);
public:
std::string getCall();
void setCall(std::string _value);
@ -112,6 +128,12 @@ namespace jus {
template<class JUS_TYPE_DATA>
void addParameter(const JUS_TYPE_DATA& _value);
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA getParameter(int32_t _id) {
return internalGetParameter<JUS_TYPE_DATA>(_id+1);
}
// ===============================================
// == Section Answer
// ===============================================

View File

@ -13,6 +13,7 @@
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);
}
@ -86,9 +87,9 @@ jus::ServiceRemote jus::Client::getService(const std::string& _name) {
return jus::ServiceRemote(this, _name);
}
bool jus::Client::link(const std::string& _serviceName) {
int32_t jus::Client::link(const std::string& _serviceName) {
// TODO : Check the number of connection of this service ...
jus::Future<bool> ret = call("link", _serviceName);
jus::Future<int32_t> ret = call("link", _serviceName);
ret.wait();
if (ret.hasError() == true) {
JUS_WARNING("Can not link with the service named: '" << _serviceName << "' ==> link error");
@ -97,11 +98,11 @@ bool jus::Client::link(const std::string& _serviceName) {
return ret.get();
}
bool jus::Client::unlink(const std::string& _serviceName) {
jus::Future<bool> ret = call("unlink", _serviceName);
bool jus::Client::unlink(const uint32_t& _serviceId) {
jus::Future<bool> ret = call("unlink", _serviceId);
ret.wait();
if (ret.hasError() == true) {
JUS_WARNING("Can not unlink with the service named: '" << _serviceName << "' ==> link error");
JUS_WARNING("Can not unlink with the service id: '" << _serviceId << "' ==> link error");
return false;
}
return ret.get();
@ -164,24 +165,24 @@ uint64_t jus::Client::getId() {
return m_id++;
}
class SendAsync {
class SendAsyncJson {
private:
std::vector<jus::ActionAsyncClient> m_async;
uint64_t m_transactionId;
std::string m_service;
uint32_t m_serviceId;
uint32_t m_partId;
public:
SendAsync(uint64_t _transactionId, const std::string& _service, const std::vector<jus::ActionAsyncClient>& _async) :
SendAsyncJson(uint64_t _transactionId, const uint32_t& _serviceId, const std::vector<jus::ActionAsyncClient>& _async) :
m_async(_async),
m_transactionId(_transactionId),
m_service(_service),
m_serviceId(_serviceId),
m_partId(1) {
}
bool operator() (jus::TcpString* _interface){
auto it = m_async.begin();
while (it != m_async.end()) {
bool ret = (*it)(_interface, m_service, m_transactionId, m_partId);
bool ret = (*it)(_interface, m_serviceId, m_transactionId, m_partId);
if (ret == true) {
// Remove it ...
it = m_async.erase(it);
@ -192,8 +193,8 @@ class SendAsync {
}
if (m_async.size() == 0) {
ejson::Object obj;
if (m_service != "") {
obj.add("service", ejson::String(m_service));
if (m_serviceId != 0) {
obj.add("service", ejson::Number(m_serviceId));
}
obj.add("id", ejson::Number(m_transactionId));
obj.add("part", ejson::Number(m_partId));
@ -210,7 +211,7 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId,
ejson::Object _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback,
const std::string& _service) {
const uint32_t& _serviceId) {
JUS_VERBOSE("Send JSON [START] ");
if (m_interfaceClient.isActive() == false) {
ejson::Object obj;
@ -230,9 +231,82 @@ jus::FutureBase jus::Client::callJson(uint64_t _transactionId,
m_interfaceClient.write(_obj.generateMachineString());
if (_async.size() != 0) {
m_interfaceClient.addAsync(SendAsync(_transactionId, _service, _async));
m_interfaceClient.addAsync(SendAsyncJson(_transactionId, _serviceId, _async));
}
JUS_VERBOSE("Send JSON [STOP]");
return tmpFuture;
}
class SendAsyncBinary {
private:
std::vector<jus::ActionAsyncClient> m_async;
uint64_t m_transactionId;
uint32_t m_serviceId;
uint32_t m_partId;
public:
SendAsyncBinary(uint64_t _transactionId, const uint32_t& _serviceId, const std::vector<jus::ActionAsyncClient>& _async) :
m_async(_async),
m_transactionId(_transactionId),
m_serviceId(_serviceId),
m_partId(1) {
}
bool operator() (jus::TcpString* _interface){
auto it = m_async.begin();
while (it != m_async.end()) {
bool ret = (*it)(_interface, m_serviceId, m_transactionId, m_partId);
if (ret == true) {
// Remove it ...
it = m_async.erase(it);
} else {
++it;
}
m_partId++;
}
if (m_async.size() == 0) {
jus::Buffer obj;
obj.setServiceId(m_serviceId);
obj.setTransactionId(m_transactionId);
obj.setPartId(m_partId);
obj.setPartFinish(true);
JUS_DEBUG("Send BINARY '" << obj.generateHumanString() << "'");
_interface->writeBinary(obj);
return true;
}
return false;
}
};
jus::FutureBase jus::Client::callBinary(uint64_t _transactionId,
jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback,
const uint32_t& _serviceId) {
JUS_VERBOSE("Send Binary [START] ");
if (m_interfaceClient.isActive() == false) {
jus::Buffer obj;
JUS_TODO("SEt error answer ...");
//obj.add("error", ejson::String("NOT-CONNECTED"));
//obj.add("error-help", ejson::String("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(tmpFuture);
}
if (_async.size() != 0) {
_obj.setPartFinish(false);
} else {
_obj.setPartFinish(true);
}
JUS_DEBUG("Send Binary '" << _obj.generateHumanString() << "'");
m_interfaceClient.writeBinary(_obj);
if (_async.size() != 0) {
m_interfaceClient.addAsync(SendAsyncBinary(_transactionId, _serviceId, _async));
}
JUS_VERBOSE("Send Binary [STOP]");
return tmpFuture;
}

View File

@ -13,6 +13,7 @@
#include <chrono>
#include <unistd.h>
#include <jus/Future.h>
#include <jus/connectionMode.h>
namespace jus {
class Client : public eproperty::Interface {
@ -22,6 +23,10 @@ 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; }
private:
jus::TcpString m_interfaceClient;
uint32_t m_id;
@ -33,8 +38,8 @@ namespace jus {
void disconnect();
public:
jus::ServiceRemote getService(const std::string& _serviceName);
bool link(const std::string& _serviceName);
bool unlink(const std::string& _serviceName);
int32_t link(const std::string& _serviceName);
bool unlink(const uint32_t& _serviceId);
// Connect that is not us
//bool identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
@ -47,22 +52,37 @@ namespace jus {
ejson::Object _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback=nullptr,
const std::string& _service="");
const uint32_t& _service=0);
jus::FutureBase callBinary(uint64_t _transactionId,
jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback=nullptr,
const uint32_t& _service=0);
public:
uint64_t getId();
template<class... _ARGS>
jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) {
uint64_t id = getId();
std::vector<ActionAsyncClient> asyncAction;
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction);
if (getMode() == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction);
} else {
jus::Buffer callElem = jus::createBinaryCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncAction);
}
}
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
std::vector<ActionAsyncClient> asyncAction;
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction, _callback);
if (getMode() == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncAction, _callback);
} else {
jus::Buffer callElem = jus::createBinaryCall(asyncAction, id, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncAction, _callback);
}
}
private:
void onPropertyChangeIp();

View File

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

View File

@ -7,6 +7,8 @@
#include <etk/types.h>
#include <ejson/ejson.h>
#include <jus/Buffer.h>
namespace jus {
class FutureBase;
@ -18,6 +20,7 @@ namespace jus {
bool m_isSynchronous;
bool m_isFinished;
ejson::Object m_returnData;
jus::Buffer m_returnDataBinary;
std::vector<ejson::Value> m_returnDataPart;
ObserverFinish m_callbackFinish;
std::chrono::steady_clock::time_point m_sendTime;

View File

@ -80,7 +80,7 @@ void jus::GateWayClient::returnBool(int32_t _transactionId, bool _value) {
m_interfaceClient.write(answer.generateMachineString());
}
void jus::GateWayClient::onClientDataRaw(jus::Buffer _value) {
void jus::GateWayClient::onClientDataRaw(const jus::Buffer& _value) {
}
@ -112,19 +112,19 @@ void jus::GateWayClient::onClientData(std::string _value) {
std::string mode = data["param"].toArray()[0].toString().get();
if (mode == "JSON") {
JUS_WARNING("[" << m_uid << "] Change mode in: JSON");
connectCleanRaw();
m_interfaceClient.connectCleanRaw();
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
returnBool(transactionId, true);
} else if (mode == "BIN") {
JUS_WARNING("[" << m_uid << "] Change mode in: BINARY");
connectClean();
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw);
returnBool(transactionId, true);
} else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML");
returnBool(transactionId, false);
} else {
protocolError("Call setMode with unknow argument : '" << mode << "' supported [JSON/XML/BIN]");
protocolError(std::string("Call setMode with unknow argument : '") /*+ etk::to_string(int32_t(mode))*/ + "' supported [JSON/XML/BIN]");
}
return;
} else if (call == "connectToUser") {
@ -323,7 +323,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
// first param:
int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64();
// Check if service already link:
if (localServiceID >= m_listConnectedService.end()) {
if (localServiceID >= m_listConnectedService.size()) {
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
@ -331,8 +331,8 @@ void jus::GateWayClient::onClientData(std::string _value) {
}
ejson::Object linkService;
// TODO : Change event in call ...
linkService.add("event", ejson::String("delete"));
(*it)->SendData(m_uid, linkService);
linkService.add("event", ejson::String("delete")); // TODO : **************************************************
m_listConnectedService[localServiceID]->SendData(m_uid, linkService);
m_listConnectedService[localServiceID] = nullptr;
answer.add("return", ejson::Boolean(true));
JUS_DEBUG("answer: " << answer.generateHumanString());
@ -347,7 +347,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
}
uint64_t serviceId = numService.getU64();
if (serviceId >= m_listConnectedService.end()) {
if (serviceId >= m_listConnectedService.size()) {
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());

View File

@ -46,6 +46,7 @@ namespace jus {
virtual ~GateWayClient();
void start(uint64_t _uid, uint64_t _uid2);
void stop();
void onClientDataRaw(const jus::Buffer& _value);
void onClientData(std::string _value);
void returnMessage(ejson::Object _data);
bool checkId(uint64_t _id) const {

View File

@ -9,13 +9,21 @@
jus::ServiceRemote::ServiceRemote(jus::Client* _clientInterface, const std::string& _name):
m_clientInterface(_clientInterface),
m_name(_name) {
m_isLinked = m_clientInterface->link(_name);
m_name(_name),
m_serviceId(0) {
int32_t val = m_clientInterface->link(_name);
if (val >= 0) {
m_isLinked = true;
m_serviceId = val;
} else {
m_isLinked = false;
m_serviceId = 0;
}
}
jus::ServiceRemote::~ServiceRemote() {
if (m_isLinked == true) {
m_clientInterface->unlink(m_name);
m_clientInterface->unlink(m_serviceId);
m_isLinked = false;
}
}
@ -28,10 +36,22 @@ uint64_t jus::ServiceRemote::getId() {
return m_clientInterface->getId();
}
enum jus::connectionMode jus::ServiceRemote::getMode() {
return m_clientInterface->getMode();
}
jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId,
const ejson::Object& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback) {
return m_clientInterface->callJson(_transactionId, _obj, _async, _callback, m_name);
return m_clientInterface->callJson(_transactionId, _obj, _async, _callback, m_serviceId);
}
jus::FutureBase jus::ServiceRemote::callBinary(uint64_t _transactionId,
const jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback) {
return m_clientInterface->callBinary(_transactionId, _obj, _async, _callback, m_serviceId);
}

View File

@ -12,6 +12,7 @@
#include <jus/AbstractFunction.h>
#include <jus/ServiceRemote.h>
#include <jus/Future.h>
#include <jus/connectionMode.h>
namespace jus {
class Client;
@ -19,6 +20,7 @@ namespace jus {
private:
jus::Client* m_clientInterface;
std::string m_name;
uint32_t m_serviceId;
bool m_isLinked;
public:
ServiceRemote(jus::Client* _clientInterface, const std::string& _name);
@ -26,21 +28,33 @@ namespace jus {
bool exist();
private:
jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, const std::vector<ActionAsyncClient>& _async, jus::FutureData::ObserverFinish _callback=nullptr);
jus::FutureBase callBinary(uint64_t _transactionId, const jus::Buffer& _obj, const std::vector<ActionAsyncClient>& _async, jus::FutureData::ObserverFinish _callback=nullptr);
uint64_t getId();
enum jus::connectionMode getMode();
public:
template<class... _ARGS>
jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) {
uint64_t id = getId();
std::vector<ActionAsyncClient> asyncActionToDo;
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_name, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo);
if (getMode() == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo);
} else {
jus::Buffer callElem = jus::createBinaryCallService(asyncActionToDo, id, m_serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncActionToDo);
}
}
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
std::vector<ActionAsyncClient> asyncActionToDo;
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_name, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo, _callback);
if (getMode() == jus::connectionMode::modeJson) {
ejson::Object callElem = jus::createCallService(asyncActionToDo, id, m_serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, asyncActionToDo, _callback);
} else {
jus::Buffer callElem = jus::createBinaryCallService(asyncActionToDo, id, m_serviceId, _functionName, std::forward<_ARGS>(_args)...);
return callBinary(id, callElem, asyncActionToDo, _callback);
}
}
};
}

View File

@ -6,6 +6,7 @@
#pragma once
#include <eproperty/Value.h>
#include <esignal/Signal.h>
#include <jus/Buffer.h>
#include <enet/Tcp.h>
#include <thread>
#include <memory>
@ -44,7 +45,7 @@ namespace jus {
(*_class.*_func)(std::move(_value));
};
}
void connectRawClean() {
void connectCleanRaw() {
m_observerRawElement = nullptr;
}
public:
@ -57,6 +58,7 @@ namespace jus {
bool isActive() const;
void setInterfaceName(const std::string& _name);
int32_t write(const std::string& _data);
int32_t writeBinary(const jus::Buffer& _data);
std::string asyncRead();
private:
std::string read();

15
jus/connectionMode.h Normal file
View File

@ -0,0 +1,15 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
namespace jus {
enum class connectionMode {
modeJson,
modeXml,
modeBinary,
};
}

View File

@ -38,6 +38,7 @@ def create(target, module_name):
'jus/FutureBase.cpp',
'jus/Future.cpp',
'jus/File.cpp',
'jus/Buffer.cpp',
'jus/ParamType.cpp',
'jus/Client.cpp',
'jus/GateWay.cpp',
@ -57,6 +58,8 @@ def create(target, module_name):
'jus/FutureBase.h',
'jus/Future.h',
'jus/File.h',
'jus/Buffer.h',
'jus/connectionMode.h',
'jus/ParamType.h',
'jus/debug.h',
'jus/Client.h',