From a0b67147c1f71bd4ebda85abc36891acb8e393e6 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 7 Jun 2016 22:09:17 +0200 Subject: [PATCH] [DEV] add base of buffer (not work ...) --- jus/Buffer.cpp | 0 jus/Buffer.h | 32 +++++++++++++ jus/GateWayClient.cpp | 105 ++++++++++++++++++++---------------------- jus/Service.cpp | 23 ++++----- jus/TcpString.cpp | 23 +++++---- jus/TcpString.h | 18 +++++++- 6 files changed, 126 insertions(+), 75 deletions(-) create mode 100644 jus/Buffer.cpp create mode 100644 jus/Buffer.h diff --git a/jus/Buffer.cpp b/jus/Buffer.cpp new file mode 100644 index 0000000..e69de29 diff --git a/jus/Buffer.h b/jus/Buffer.h new file mode 100644 index 0000000..5411cf8 --- /dev/null +++ b/jus/Buffer.h @@ -0,0 +1,32 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once +#include + +namespace jus { + /* + U32 message lenght + U16 protocol Version (might be 1) + U32 transactionID; + U32 clientID; ==> sevice ID + U1 finish part + U15 partID; + // not needed ==> can be deduced with parameter number ... U16 Offset String call Name (start of the buffer) end with \0 + U8 param count + U16[param count] parameters offset + ... DATAS ... + */ + class Buffer { + private: + std::vector m_data; + uint64_t m_transactionId; + uint64_t m_clientId; // clientId/service + uint32_t m_partId; + bool m_partFinish; + uint32_t m_parameterCount; + + public: + Buffer(); \ No newline at end of file diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index 16b3c15..4215354 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -80,6 +80,10 @@ void jus::GateWayClient::returnBool(int32_t _transactionId, bool _value) { m_interfaceClient.write(answer.generateMachineString()); } +void jus::GateWayClient::onClientDataRaw(jus::Buffer _value) { + +} + void jus::GateWayClient::onClientData(std::string _value) { JUS_DEBUG("On data: " << _value); ejson::Object data(_value); @@ -104,7 +108,26 @@ void jus::GateWayClient::onClientData(std::string _value) { return; } std::string call = data["call"].toString().get(); - if (call == "connectToUser") { + if (call == "setMode") { + std::string mode = data["param"].toArray()[0].toString().get(); + if (mode == "JSON") { + JUS_WARNING("[" << m_uid << "] Change mode in: JSON"); + 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.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]"); + } + return; + } else if (call == "connectToUser") { m_userConnectionName = data["param"].toArray()[0].toString().get(); if (m_userConnectionName == "") { protocolError("Call connectToUser with no parameter 'user'"); @@ -221,8 +244,10 @@ void jus::GateWayClient::onClientData(std::string _value) { break; case jus::GateWayClient::state::clientIdentify: { - // This is 2 default service for the cient interface that manage the authorisation of view: - if (data.valueExist("service") == false) { + ejson::Number numService = data["service"].toNumber(); + if ( numService.exist() == false + || numService.getU64() == 0) { + // This is 2 default service for the cient interface that manage the authorisation of view: std::string callFunction = data["call"].toString().get(); ejson::Object answer; //answer.add("from-service", ejson::String("")); @@ -263,7 +288,7 @@ void jus::GateWayClient::onClientData(std::string _value) { if (it == m_listConnectedService.end()) { // check if service is connectable ... if (std::find(m_clientServices.begin(), m_clientServices.end(), serviceName) == m_clientServices.end()) { - answer.add("return", ejson::Boolean(false)); + answer.add("error", ejson::String("UN-AUTHORIZED-SERVICE")); JUS_DEBUG("answer: (NOT authorized service) " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); return; @@ -282,9 +307,9 @@ void jus::GateWayClient::onClientData(std::string _value) { } srv->SendData(m_uid, linkService); m_listConnectedService.push_back(srv); - answer.add("return", ejson::Boolean(true)); + answer.add("return", ejson::Number(m_listConnectedService.size()-1)); } else { - answer.add("return", ejson::Boolean(false)); + answer.add("error", ejson::String("CAN-NOT-CONNECT-SERVICE")); } } else { // TODO : Service already connected; @@ -296,29 +321,20 @@ void jus::GateWayClient::onClientData(std::string _value) { } if (callFunction == "unlink") { // first param: - std::string serviceName = data["param"].toArray()[0].toString().get(); + int64_t localServiceID = data["param"].toArray()[0].toNumber().getI64(); // 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()) { - answer.add("return", ejson::Boolean(false)); - } else { - ejson::Object linkService; - linkService.add("event", ejson::String("delete")); - (*it)->SendData(m_uid, linkService); - m_listConnectedService.erase(it); - answer.add("return", ejson::Boolean(true)); + if (localServiceID >= m_listConnectedService.end()) { + answer.add("error", ejson::String("NOT-CONNECTED-SERVICE")); + JUS_DEBUG("answer: " << answer.generateHumanString()); + m_interfaceClient.write(answer.generateMachineString()); + return; } + ejson::Object linkService; + // TODO : Change event in call ... + linkService.add("event", ejson::String("delete")); + (*it)->SendData(m_uid, linkService); + m_listConnectedService[localServiceID] = nullptr; + answer.add("return", ejson::Boolean(true)); JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); return; @@ -329,32 +345,13 @@ void jus::GateWayClient::onClientData(std::string _value) { m_interfaceClient.write(answer.generateMachineString()); return; } - std::string service = data["service"].toString().get(); - if (service == "") { - protocolError("call with \"service\"=\"\" ==> not permited"); - return; - } - auto it = m_listConnectedService.begin(); - while (it != m_listConnectedService.end()) { - if (*it == nullptr) { - ++it; - continue; - } - if ((*it)->getName() != service) { - ++it; - continue; - } - break; - } - if (it == m_listConnectedService.end()) { - // TODO : Generate an ERROR... - ejson::Object answer; - answer.add("from-service", ejson::String("ServiceManager")); - answer.add("id", data["id"]); - JUS_ERROR("Service not linked ... " << service); - answer.add("error", ejson::String("SERVICE-NOT-LINK")); + + uint64_t serviceId = numService.getU64(); + if (serviceId >= m_listConnectedService.end()) { + answer.add("error", ejson::String("NOT-CONNECTED-SERVICE")); JUS_DEBUG("answer: " << answer.generateHumanString()); m_interfaceClient.write(answer.generateMachineString()); + return; } else { bool finish = false; if (data.valueExist("finish") == true) { @@ -371,7 +368,7 @@ void jus::GateWayClient::onClientData(std::string _value) { JUS_INFO(" compare : " << itCall.first << " =?= " << transactionId); if (itCall.first == transactionId) { // Find element ==> transit it ... - if (*it == nullptr) { + if (m_listConnectedService[serviceId] == nullptr) { // TODO ... } else { ejson::Object obj; @@ -382,7 +379,7 @@ void jus::GateWayClient::onClientData(std::string _value) { if (finish == true) { obj.add("finish", ejson::Boolean(true)); } - (*it)->SendData(m_uid, obj); + m_listConnectedService[serviceId]->SendData(m_uid, obj); } return; } @@ -393,7 +390,7 @@ void jus::GateWayClient::onClientData(std::string _value) { } callActionForward(m_uid, transactionId, - *it, + m_listConnectedService[serviceId], data["call"].toString().get(), data["param"].toArray(), [=](jus::FutureBase _ret) { diff --git a/jus/Service.cpp b/jus/Service.cpp index 26efd78..1527556 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -107,15 +107,6 @@ void jus::Service::callJson(uint64_t _transactionId, const ejson::Object& _obj) if (event == "IS-ALIVE") { // Gateway just aswer a keep alive information ... // Nothing to do ... - } else if (event == "new") { - uint64_t clientId = _obj["client-id"].toNumber().getU64(); - std::string userName = _obj["user"].toString().get(); - std::string clientName = _obj["client"].toString().get(); - std::vector clientGroup = convertJsonTo>(_obj["groups"]); - clientConnect(clientId, userName, clientName, clientGroup); - } else if (event == "delete") { - uint64_t clientId = _obj["client-id"].toNumber().getU64(); - clientDisconnect(clientId); } else { JUS_ERROR("Unknow event: '" << event << "'"); } @@ -125,8 +116,18 @@ 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(); - if (isFunctionAuthorized(clientId, call) == true) { - callJson2(_transactionId, clientId, call, _obj["param"].toArray()); + ejson::Array params = _obj["param"].toArray() + if (call[0] == '_') { + if (call == "_new") { + std::string userName = params[0].toString().get(); + std::string clientName = params[1].toString().get(); + std::vector clientGroup = convertJsonTo>(params[2]); + clientConnect(clientId, userName, clientName, clientGroup); + } else if (call == "_delete") { + clientDisconnect(clientId); + } + } else if (isFunctionAuthorized(clientId, call) == true) { + callJson2(_transactionId, clientId, call, params); return; } else { answer.add("id", ejson::Number(_transactionId)); diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index aea40a8..995fab5 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -11,7 +11,8 @@ jus::TcpString::TcpString(enet::Tcp _connection) : m_connection(std::move(_connection)), m_thread(nullptr), - m_obsercerElement(nullptr), + m_observerElement(nullptr), + m_observerRawElement(nullptr), m_threadAsync(nullptr) { m_threadRunning = false; m_threadAsyncRunning = false; @@ -20,7 +21,8 @@ jus::TcpString::TcpString(enet::Tcp _connection) : jus::TcpString::TcpString() : m_connection(), m_thread(nullptr), - m_obsercerElement(nullptr), + m_observerElement(nullptr), + m_observerRawElement(nullptr), m_threadAsync(nullptr) { m_threadRunning = false; m_threadAsyncRunning = false; @@ -44,12 +46,17 @@ void jus::TcpString::threadCallback() { while ( m_threadRunning == true && m_connection.getConnectionStatus() == enet::Tcp::status::link) { // READ section data: - std::string data = std::move(read()); - JUS_VERBOSE("Receive data: '" << data << "'"); - if (data.size() != 0) { - m_lastReceive = std::chrono::steady_clock::now(); - if (m_obsercerElement != nullptr) { - m_obsercerElement(std::move(data)); + if (m_observerElement != nullptr) { + std::string data = std::move(read()); + JUS_VERBOSE("Receive data: '" << data << "'"); + if (data.size() != 0) { + m_lastReceive = std::chrono::steady_clock::now(); + m_observerElement(std::move(data)); + } + } else if (m_observerRawElement != nullptr) { + jus::Buffer data = std::move(readRaw()); + if (data.size() != 0) { + m_observerRawElement(std::move(data)); } } } diff --git a/jus/TcpString.h b/jus/TcpString.h index 3f733c8..9c54845 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -20,7 +20,9 @@ namespace jus { std::chrono::steady_clock::time_point m_lastSend; public: using Observer = std::function; //!< Define an Observer: function pointer - Observer m_obsercerElement; + using ObserverRaw = std::function; //!< Define an Observer: function pointer + Observer m_observerElement; + ObserverRaw m_observerRawElement; /** * @brief Connect an function member on the signal with the shared_ptr object. * @param[in] _class shared_ptr Object on whe we need to call ==> the object is get in keeped in weak_ptr. @@ -29,10 +31,22 @@ namespace jus { */ template void connect(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(std::string)) { - m_obsercerElement = [=](std::string _value){ + m_observerElement = [=](std::string _value){ (*_class.*_func)(std::move(_value)); }; } + void connectClean() { + m_observerElement = nullptr; + } + template + void connectRaw(CLASS_TYPE* _class, void (CLASS_TYPE::*_func)(const jus::Buffer&)) { + m_observerRawElement = [=](const jus::Buffer& _value){ + (*_class.*_func)(std::move(_value)); + }; + } + void connectRawClean() { + m_observerRawElement = nullptr; + } public: TcpString(); TcpString(enet::Tcp _connection);