[DEV] start test binary comminicaution

This commit is contained in:
Edouard DUPIN 2016-06-09 22:32:24 +02:00
parent 0d73df3593
commit 3a141c64b2
15 changed files with 399 additions and 70 deletions

View File

@ -261,10 +261,10 @@ ejson::Object jus::createCallJson(uint64_t _transactionId, const std::string& _f
return callElem;
}
ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service) {
ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId) {
ejson::Object obj;
if (_service.size() != 0) {
obj.add("service", ejson::String(_service));
if (_serviceId != 0) {
obj.add("service", ejson::Number(_serviceId));
}
obj.add("call", ejson::String(_functionName));
obj.add("id", ejson::Number(_transactionId));

View File

@ -77,7 +77,7 @@ namespace jus {
// ============================================================
// == JSON
// ============================================================
ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service="");
ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const uint32_t& _serviceId=0);
void createParam(std::vector<ActionAsyncClient>& _asyncAction,
int32_t _paramId,
@ -113,8 +113,8 @@ namespace jus {
return callElem;
}
template<class... _ARGS>
ejson::Object createCallService(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const std::string& _serviceName, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_transactionId, _functionName, _serviceName);
ejson::Object createCallService(std::vector<ActionAsyncClient>& _asyncAction, uint64_t _transactionId, const uint32_t& _serviceId, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_transactionId, _functionName, _serviceId);
createParam(_asyncAction, 0, callElem, std::forward<_ARGS>(_args)...);
return callElem;
}

View File

@ -7,17 +7,70 @@
#include <jus/Buffer.h>
#include <jus/debug.h>
namespace etk {
template<> std::string to_string<enum jus::Buffer::typeMessage>(const enum jus::Buffer::typeMessage& _value) {
switch (_value) {
case jus::Buffer::typeMessage::call:
return "call";
case jus::Buffer::typeMessage::answer:
return "answer";
case jus::Buffer::typeMessage::event:
return "event";
}
return "???";
}
}
std::ostream& jus::operator <<(std::ostream& _os, const std::vector<enum jus::Buffer::typeMessage>& _value) {
_os << etk::to_string(_value);
return _os;
}
static enum jus::Buffer::typeMessage getTypeType(uint16_t _value) {
switch (_value) {
case 1:
return jus::Buffer::typeMessage::call;
case 2:
return jus::Buffer::typeMessage::answer;
case 4:
return jus::Buffer::typeMessage::event;
}
return jus::Buffer::typeMessage::call;
}
jus::Buffer::Buffer() {
clear();
}
void jus::Buffer::composeWith(const std::vector<uint8_t>& _buffer) {
clear();
m_header.lenght = _buffer.size();
memcpy(&m_header + 4, &_buffer[0], sizeof(headerBin)-4);
JUS_INFO("Get binary message : ");
JUS_INFO(" lenght = " << m_header.lenght);
JUS_INFO(" versionProtocol = " << m_header.versionProtocol);
JUS_INFO(" transactionID = " << m_header.transactionID);
JUS_INFO(" clientID = " << m_header.clientID);
JUS_INFO(" partID = " << m_header.partID);
enum jus::Buffer::typeMessage ttype = getTypeType(m_header.typeMessage);
JUS_INFO(" typeMessage = " << ttype);
JUS_TODO(" ...");
}
void jus::Buffer::clear() {
m_data.clear();
m_paramOffset.clear();
m_header.clear();
}
std::string jus::Buffer::generateHumanString() {
return "jus::Buffer ...";
std::string out = "jus::Buffer Lenght=: ";
out += etk::to_string(m_header.lenght);
out += " v=" + etk::to_string(m_header.versionProtocol);
out += " id=" + etk::to_string(m_header.transactionID);
out += " cId=" + etk::to_string(m_header.clientID);
out += " pId=" + etk::to_string(m_header.partID);
enum jus::Buffer::typeMessage type = getTypeType(m_header.typeMessage);
out += " type=" + etk::to_string(type);
return out;
}
uint16_t jus::Buffer::getProtocalVersion() {
@ -78,6 +131,15 @@ uint16_t jus::Buffer::getNumberParameter() {
}
void jus::Buffer::addParameter() {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('v');
m_data.push_back('o');
m_data.push_back('i');
m_data.push_back('d');
m_data.push_back('\0');
}
template<>
void jus::Buffer::addParameter<std::string>(const std::string& _value) {
int32_t currentOffset = m_data.size();
@ -223,6 +285,21 @@ void jus::Buffer::addParameter<double>(const double& _value) {
m_data.resize(m_data.size()+8);
memcpy(&m_data[currentOffset], &_value, 8);
}
template<>
void jus::Buffer::addParameter<bool>(const bool& _value) {
int32_t currentOffset = m_data.size();
m_paramOffset.push_back(currentOffset);
m_data.push_back('b');
m_data.push_back('o');
m_data.push_back('o');
m_data.push_back('l');
m_data.push_back('\0');
if (_value == true) {
m_data.push_back('T');
} else {
m_data.push_back('F');
}
}
template<>
std::string jus::Buffer::internalGetParameter<std::string>(int32_t _id) {
@ -302,7 +379,11 @@ int8_t jus::Buffer::internalGetParameter<int8_t>(int32_t _id) {
}
void jus::Buffer::addError(const std::string& _value, const std::string& _comment) {
addParameter();
addParameter(_value);
addParameter(_comment);
}
std::string jus::Buffer::getCall() {
std::string out;

View File

@ -29,6 +29,7 @@ namespace jus {
======================
== call
======================
U16 param count
U16[param count] parameters offset (first offset is the "callName" and limit size of the number of parameter
CALL Name (funtion name)
[param 1]
@ -38,8 +39,11 @@ namespace jus {
======================
== Answer
======================
U16 ErrorOffset
[return value 1]
U16 param count = 3
U16[param count]
[param 1] (return value)
[param 2] (error value)
[param 3] (error help)
[error] (constituated with 2 strings (error type and comment)
======================
== event
@ -86,8 +90,28 @@ namespace jus {
headerBin m_header;
std::vector<uint16_t> m_paramOffset;
std::vector<uint8_t> m_data;
public:
const uint8_t* getHeader() const {
return reinterpret_cast<const uint8_t*>(&m_header);
}
uint32_t getHeaderSize() const {
return sizeof(headerBin);
}
const uint8_t* getParam() const {
return reinterpret_cast<const uint8_t*>(&m_paramOffset[0]);
}
uint32_t getParamSize() const {
return m_paramOffset.size() * 2;
}
const uint8_t* getData() const {
return &m_data[0];
}
uint32_t getDataSize() const {
return m_data.size();
}
public:
Buffer();
void composeWith(const std::vector<uint8_t>& _buffer);
std::string generateHumanString();
void clear();
uint16_t getProtocalVersion();
@ -114,6 +138,7 @@ namespace jus {
};
enum typeMessage getType();
void setType(enum typeMessage _value);
// ===============================================
// == Section call
// ===============================================
@ -127,6 +152,7 @@ namespace jus {
template<class JUS_TYPE_DATA>
void addParameter(const JUS_TYPE_DATA& _value);
void addParameter();
template<class JUS_TYPE_DATA>
JUS_TYPE_DATA getParameter(int32_t _id) {
@ -139,7 +165,11 @@ namespace jus {
// ===============================================
public:
template<class JUS_TYPE_DATA>
void addAnswer(const JUS_TYPE_DATA& _value);
void addAnswer(const JUS_TYPE_DATA& _value) {
addParameter(_value);
}
void addError(const std::string& _value, const std::string& _comment);
};
std::ostream& operator <<(std::ostream& _os, const std::vector<enum jus::Buffer::typeMessage>& _value);
}

View File

@ -146,6 +146,15 @@ bool jus::Client::connect(const std::string& _remoteUserToConnect){
enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort));
m_interfaceClient.setInterface(std::move(connection));
m_interfaceClient.connect();
// Force mode binary:
jus::Future<bool> retBin = call("setMode", "BIN").wait();
if (retBin.get() == true) {
m_interfaceMode = jus::connectionMode::modeBinary;
JUS_INFO("Connection jump in BINARY ...");
} else {
// stay in JSON
}
jus::Future<bool> ret = call("connectToUser", _remoteUserToConnect, "jus-client");
ret.wait();
if (ret.hasError() == true) {

View File

@ -25,6 +25,7 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFi
m_data->m_transactionId = _transactionId;
m_data->m_isFinished = false;
m_data->m_isSynchronous = false;
m_data->m_mode = false;
m_data->m_callbackFinish = _callback;
}
@ -44,6 +45,7 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob
m_data->m_transactionId = _transactionId;
m_data->m_isFinished = _isFinished;
m_data->m_isSynchronous = false;
m_data->m_mode = false;
m_data->m_returnData = _returnData;
m_data->m_callbackFinish = _callback;
if (m_data->m_isFinished == true) {
@ -54,6 +56,25 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob
}
}
jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, jus::Buffer _returnData, jus::FutureData::ObserverFinish _callback) {
m_data = std::make_shared<jus::FutureData>();
if (m_data == nullptr) {
return;
}
m_data->m_sendTime = std::chrono::steady_clock::now();
m_data->m_transactionId = _transactionId;
m_data->m_isFinished = _isFinished;
m_data->m_isSynchronous = false;
m_data->m_mode = true;
m_data->m_returnDataBinary = _returnData;
m_data->m_callbackFinish = _callback;
if (m_data->m_isFinished == true) {
m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_callbackFinish != nullptr) {
m_data->m_callbackFinish(*this);
}
}
}
std::chrono::nanoseconds jus::FutureBase::getTransmitionTime() {
if (m_data == nullptr) {
return std::chrono::nanoseconds(0);
@ -74,6 +95,7 @@ bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
JUS_ERROR(" Not a valid future ...");
return true;
}
m_data->m_mode = false;
m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_isSynchronous == true) {
m_data->m_returnData = _returnValue;
@ -108,6 +130,48 @@ bool jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
}
return true;
}
bool jus::FutureBase::setAnswer(const jus::Buffer& _returnValue) {
if (m_data == nullptr) {
JUS_ERROR(" Not a valid future ...");
return true;
}
m_data->m_mode = true;
m_data->m_receiveTime = std::chrono::steady_clock::now();
if (m_data->m_isSynchronous == true) {
m_data->m_returnDataBinary = _returnValue;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
/* TODO : ...
if (_returnValue.valueExist("part") == true) {
uint64_t idPart = _returnValue["part"].toNumber().getU64();
if (idPart == 0) {
m_data->m_returnData = _returnValue;
} else {
m_data->m_returnDataPart.push_back(_returnValue["data"]);
}
if (_returnValue.valueExist("finish") == true) {
if (_returnValue["finish"].toBoolean().get() == true) {
m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
return true;
}
// finish is false ==> normal case ...
}
return false;
}
m_data->m_returnData = _returnValue;
m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
return m_data->m_callbackFinish(*this);
}
*/
return true;
}
void jus::FutureBase::setSynchronous() {
if (m_data == nullptr) {
return;

View File

@ -19,6 +19,7 @@ namespace jus {
uint64_t m_transactionId;
bool m_isSynchronous;
bool m_isFinished;
bool m_mode;
ejson::Object m_returnData;
jus::Buffer m_returnDataBinary;
std::vector<ejson::Value> m_returnDataPart;

View File

@ -12,10 +12,14 @@
#include <jus/AbstractFunction.h>
static const std::string protocolError = "PROTOCOL-ERROR";
jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)),
m_interfaceMode(jus::connectionMode::modeJson),
m_transactionLocalId(1) {
JUS_INFO("----------------");
JUS_INFO("-- NEW Client --");
@ -45,12 +49,16 @@ void jus::GateWayClient::stop() {
continue;
}
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
linkService.add("call", ejson::String("_delete"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
linkService.add("param", ejson::Array());
it->SendData(m_uid, linkService);
}
if (m_userService != nullptr) {
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
linkService.add("call", ejson::String("_delete"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
linkService.add("param", ejson::Array());
m_userService->SendData(m_uid2, linkService);
m_userService = nullptr;
}
@ -62,23 +70,42 @@ bool jus::GateWayClient::isAlive() {
return m_interfaceClient.isActive();
}
void jus::GateWayClient::protocolError(const std::string& _errorHelp) {
ejson::Object answer;
answer.add("error", ejson::String("PROTOCOL-ERROR"));
answer.add("error-help", ejson::String(_errorHelp));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
void jus::GateWayClient::answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp) {
answerError(_transactionId, protocolError, _errorHelp);
m_state = jus::GateWayClient::state::disconnect;
m_interfaceClient.disconnect(true);
}
void jus::GateWayClient::returnBool(int32_t _transactionId, bool _value) {
/*
void jus::GateWayClient::answerValue(int32_t _transactionId, bool _value) {
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("return", ejson::Boolean(_value));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
}
*/
void jus::GateWayClient::answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorHelp) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("error", ejson::String(protocolError));
answer.add("id", ejson::Number(_clientTransactionId));
answer.add("error-help", ejson::String(_errorHelp));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.addError(protocolError, _errorHelp);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void jus::GateWayClient::onClientDataRaw(const jus::Buffer& _value) {
@ -90,7 +117,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
uint64_t transactionId = data["id"].toNumber().getU64();
if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id");
protocolError("missing parameter: 'id'");
answerProtocolError(transactionId, "missing parameter: 'id'");
return;
}
switch (m_state) {
@ -98,13 +125,13 @@ void jus::GateWayClient::onClientData(std::string _value) {
case jus::GateWayClient::state::unconnect:
{
JUS_ERROR("Must never appear");
protocolError("Gateway internal error");
answerProtocolError(transactionId, "Gateway internal error");
return;
}
case jus::GateWayClient::state::connect:
{
if (m_userConnectionName != "") {
protocolError("Gateway internal error 2");
answerProtocolError(transactionId, "Gateway internal error 2");
return;
}
std::string call = data["call"].toString().get();
@ -112,46 +139,52 @@ 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");
m_interfaceMode = jus::connectionMode::modeJson;
m_interfaceClient.connectCleanRaw();
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
returnBool(transactionId, true);
answerValue(transactionId, true);
} else if (mode == "BIN") {
JUS_WARNING("[" << m_uid << "] Change mode in: BINARY");
m_interfaceMode = jus::connectionMode::modeBinary;
m_interfaceClient.connectClean();
m_interfaceClient.connectRaw(this, &jus::GateWayClient::onClientDataRaw);
returnBool(transactionId, true);
answerValue(transactionId, true);
} else if (mode == "XML") {
JUS_WARNING("[" << m_uid << "] Change mode in: XML");
returnBool(transactionId, false);
//m_interfaceMode = jus::connectionMode::modeXml;
answerValue(transactionId, false);
} else {
protocolError(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;
} else if (call == "connectToUser") {
m_userConnectionName = data["param"].toArray()[0].toString().get();
if (m_userConnectionName == "") {
protocolError("Call connectToUser with no parameter 'user'");
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) {
protocolError("Gateway internal error 'No user interface'");
answerProtocolError(transactionId, "Gateway internal error 'No user interface'");
} else {
ejson::Object linkService;
linkService.add("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
linkService.add("client", ejson::String("**Gateway**"));
linkService.add("groups", ejson::Array());
linkService.add("call", ejson::String("_new"));
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;
returnBool(transactionId, true);
answerValue(transactionId, true);
}
}
return;
}
JUS_WARNING("[" << m_uid << "] Client must send conection to user name ...");
protocolError("Missing call of connectToUser");
answerProtocolError(transactionId, "Missing call of connectToUser");
return;
}
case jus::GateWayClient::state::userIdentify:
@ -164,26 +197,26 @@ void jus::GateWayClient::onClientData(std::string _value) {
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous") {
protocolError("Client must call: identify/auth/anonymous");
answerProtocolError(transactionId, "Client must call: identify/auth/anonymous");
return;
}
if (callFunction == "identify") {
std::string clientName = data["param"].toArray()[0].toString().get();
std::string clientTocken = data["param"].toArray()[1].toString().get();
if (m_userService == nullptr) {
protocolError("gateWay internal error 3");
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 ...");
returnBool(transactionId, false);
protocolError("connection refused 1");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
returnBool(transactionId, false);
protocolError("connection refused 2");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = clientName;
@ -194,12 +227,12 @@ void jus::GateWayClient::onClientData(std::string _value) {
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("connection refused 1");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 1");
return;
} else if (fut.get() == false) {
returnBool(transactionId, false);
protocolError("connection refused 2");
answerValue(transactionId, false);
answerProtocolError(transactionId, "connection refused 2");
return;
}
m_clientName = m_userConnectionName;
@ -214,8 +247,8 @@ void jus::GateWayClient::onClientData(std::string _value) {
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("grouping error");
answerValue(transactionId, false);
answerProtocolError(transactionId, "grouping error");
return;
}
m_clientgroups = futGroup.get();
@ -227,8 +260,8 @@ void jus::GateWayClient::onClientData(std::string _value) {
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("service filtering error");
answerValue(transactionId, false);
answerProtocolError(transactionId, "service filtering error");
return;
}
m_clientServices = futServices.get();
@ -237,7 +270,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
JUS_WARNING(" services: " << etk::to_string(m_clientServices));
returnBool(transactionId, true);
answerValue(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify;
return;
}
@ -250,7 +283,6 @@ void jus::GateWayClient::onClientData(std::string _value) {
// 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("from-service", ejson::String(""));
answer.add("id", data["id"]);
if (callFunction == "getServiceCount") {
answer.add("return", ejson::Number(m_clientServices.size()));
@ -296,18 +328,21 @@ void jus::GateWayClient::onClientData(std::string _value) {
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
if (srv != nullptr) {
ejson::Object linkService;
linkService.add("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
linkService.add("client", ejson::String(m_clientName));
linkService.add("call", ejson::String("_new"));
linkService.add("id", ejson::Number(m_transactionLocalId++));
ejson::Array params;
params.add(ejson::String(m_userConnectionName));
params.add(ejson::String(m_clientName));
// TODO ==> remove events ...
std::vector<ActionAsyncClient> asyncAction;
linkService.add("groups", convertToJson(asyncAction, 0, m_clientgroups));
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);
answer.add("return", ejson::Number(m_listConnectedService.size()-1));
answer.add("return", ejson::Number(m_listConnectedService.size()));
} else {
answer.add("error", ejson::String("CAN-NOT-CONNECT-SERVICE"));
}
@ -321,7 +356,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
}
if (callFunction == "unlink") {
// first param:
int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64();
int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64()-1;
// Check if service already link:
if (localServiceID >= m_listConnectedService.size()) {
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE"));
@ -330,8 +365,10 @@ void jus::GateWayClient::onClientData(std::string _value) {
return;
}
ejson::Object linkService;
// TODO : Change event in call ...
linkService.add("event", ejson::String("delete")); // TODO : **************************************************
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;
answer.add("return", ejson::Boolean(true));
@ -346,8 +383,10 @@ void jus::GateWayClient::onClientData(std::string _value) {
return;
}
uint64_t serviceId = numService.getU64();
uint64_t serviceId = numService.getU64()-1;
if (serviceId >= m_listConnectedService.size()) {
ejson::Object answer;
answer.add("id", data["id"]);
answer.add("error", ejson::String("NOT-CONNECTED-SERVICE"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());

View File

@ -11,6 +11,7 @@
#include <jus/GateWayService.h>
#include <jus/Future.h>
#include <jus/AbstractFunction.h>
#include <jus/connectionMode.h>
@ -29,8 +30,10 @@ namespace jus {
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
void protocolError(const std::string& _errorHelp);
void returnBool(int32_t _transactionId, bool _value);
protected:
enum jus::connectionMode m_interfaceMode;
public:
enum jus::connectionMode getMode() { return m_interfaceMode; }
public:
esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService;
@ -91,6 +94,38 @@ namespace jus {
jus::FutureData::ObserverFinish _callback,
int64_t _part,
bool _finish);
void answerProtocolError(uint32_t _transactionId, const std::string& _errorHelp);
template<class JUS_ARG>
void answerValue(uint64_t _clientTransactionId, JUS_ARG _value) {
if (m_interfaceMode == jus::connectionMode::modeJson) {
ejson::Object answer;
answer.add("id", ejson::Number(_clientTransactionId));
std::vector<ActionAsyncClient> asyncAction;
answer.add("return", jus::convertToJson(asyncAction, -1, _value));
if (asyncAction.size() != 0) {
JUS_ERROR("ASYNC datas ... TODO ///");
}
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else if (m_interfaceMode == jus::connectionMode::modeBinary) {
jus::Buffer answer;
answer.setType(jus::Buffer::typeMessage::answer);
answer.setTransactionId(_clientTransactionId);
answer.addAnswer(_value);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.writeBinary(answer);
} else if (m_interfaceMode == jus::connectionMode::modeXml) {
JUS_ERROR("TODO ... ");
} else {
JUS_ERROR("wrong type of communication");
}
}
void answerError(uint64_t _clientTransactionId, const std::string& _errorValue, const std::string& _errorComment="");
};
}

View File

@ -116,7 +116,7 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj)
uint64_t clientId = _obj["client-id"].toNumber().getU64();
if (_obj.valueExist("call") == true) {
std::string call = _obj["call"].toString().get();
ejson::Array params = _obj["param"].toArray()
ejson::Array params = _obj["param"].toArray();
if (call[0] == '_') {
if (call == "_new") {
std::string userName = params[0].toString().get();
@ -126,6 +126,13 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj)
} else if (call == "_delete") {
clientDisconnect(clientId);
}
// TODO : Do it better ...
answer.add("id", ejson::Number(_transactionId));
answer.add("client-id", ejson::Number(clientId));
answer.add("return", ejson::Boolean(true));
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient->write(answer.generateMachineString());
return;
} else if (isFunctionAuthorized(clientId, call) == true) {
callJson2(_transactionId, clientId, call, params);
return;

View File

@ -48,7 +48,7 @@ jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId,
}
jus::FutureBase jus::ServiceRemote::callBinary(uint64_t _transactionId,
const jus::Buffer& _obj,
jus::Buffer& _obj,
const std::vector<ActionAsyncClient>& _async,
jus::FutureData::ObserverFinish _callback) {
return m_clientInterface->callBinary(_transactionId, _obj, _async, _callback, m_serviceId);

View File

@ -28,7 +28,7 @@ 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);
jus::FutureBase callBinary(uint64_t _transactionId, jus::Buffer& _obj, const std::vector<ActionAsyncClient>& _async, jus::FutureData::ObserverFinish _callback=nullptr);
uint64_t getId();
enum jus::connectionMode getMode();
public:

View File

@ -55,9 +55,7 @@ void jus::TcpString::threadCallback() {
}
} else if (m_observerRawElement != nullptr) {
jus::Buffer data = std::move(readRaw());
if (data.size() != 0) {
m_observerRawElement(std::move(data));
}
m_observerRawElement(std::move(data));
}
}
m_threadRunning = false;
@ -136,6 +134,28 @@ int32_t jus::TcpString::write(const std::string& _data) {
m_connection.write(&size, 4);
return m_connection.write(_data.c_str(), _data.size());
}
int32_t jus::TcpString::writeBinary(const jus::Buffer& _data) {
if (m_threadRunning == false) {
return -2;
}
/*
if (_data.size() == 0) {
return 0;
}
*/
//uint32_t size = _data.size();
m_lastSend = std::chrono::steady_clock::now();
const uint8_t* data = _data.getHeader();
uint32_t dataSize = _data.getHeaderSize();
m_connection.write(data, dataSize);
data = _data.getParam();
dataSize = _data.getParamSize();
m_connection.write(data, dataSize);
data = _data.getData();
dataSize = _data.getDataSize();
m_connection.write(data, dataSize);
return 1;
}
std::string jus::TcpString::read() {
JUS_VERBOSE("Read [START]");
@ -177,6 +197,45 @@ std::string jus::TcpString::read() {
return out;
}
jus::Buffer jus::TcpString::readRaw() {
jus::Buffer out;
JUS_VERBOSE("ReadRaw [START]");
if (m_threadRunning == false) {
JUS_DEBUG("Read [END] Disconected");
return out;
}
JUS_VERBOSE("ReadRaw [START]");
uint32_t size = 0;
int32_t len = m_connection.read(&size, 4);
if (len != 4) {
JUS_ERROR("Protocol error occured ...");
} else {
if (size == -1) {
JUS_WARNING("Remote close connection");
m_threadRunning = false;
//m_connection.unlink();
} else {
int64_t offset = 0;
m_buffer.resize(size);
while (offset != size) {
len = m_connection.read(&m_buffer[offset], size-offset);
offset += len;
if (len == 0) {
JUS_WARNING("Read No data");
//break;
}
/*
else if (size != offset) {
JUS_ERROR("Protocol error occured .2. ==> concat (offset=" << offset << " size=" << size);
}
*/
}
out.composeWith(m_buffer);
}
}
JUS_VERBOSE("ReadRaw [STOP]");
return out;
}
void jus::TcpString::threadAsyncCallback() {
ethread::setName("Async-sender");

View File

@ -62,6 +62,8 @@ namespace jus {
std::string asyncRead();
private:
std::string read();
jus::Buffer readRaw();
std::vector<uint8_t> m_buffer;
private:
void threadCallback();
public:

View File

@ -86,7 +86,7 @@ int main(int _argc, const char *_argv[]) {
APPL_INFO("serviceTest1.mul = " << retCall);
}
*/
if (false) {
if (true) {
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service system-user");
APPL_INFO(" ----------------------------------");
@ -182,6 +182,7 @@ int main(int _argc, const char *_argv[]) {
}
}
*/
#if 0
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
jus::File tmp("./photo_2016_33913.bmp");//"image/jpg", {0,5,2,6,7,5,8,4,5,2,1,5,65,5,2,6,85,4,6,6,54,65,88,64,14,6,4,64,51,3,16,4});
int32_t size = tmp.getData().size();
@ -190,6 +191,7 @@ int main(int _argc, const char *_argv[]) {
APPL_WARNING(" IO*=" << int64_t((stop-start).count()/1000)/1000.0 << " ms");
double megaParSec = double(size)/(double((stop-start).count())/1000000000.0);
APPL_WARNING(" speed=" << int64_t(megaParSec/1024.0)/1024.0 << " Mo/s");
#endif
}
int32_t iii=0;
while (iii < 3) {