diff --git a/jus/Client.cpp b/jus/Client.cpp index 89649ea..2972063 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -4,6 +4,7 @@ * @license APACHE v2.0 (see license file) */ +#include #include #include @@ -13,9 +14,6 @@ jus::Client::Client() : propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Client::onPropertyChangeIp), propertyPort(this, "port", 1983, "Port to connect server", &jus::Client::onPropertyChangePort), m_id(0) { - m_interfaceClient.propertyIp.set(*propertyIp); - m_interfaceClient.propertyPort.set(*propertyPort); - m_interfaceClient.propertyServer.set(false); m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::Client::onClientData); } @@ -27,6 +25,25 @@ void jus::Client::onClientData(const std::string& _value) { m_newData.push_back(_value); } +jus::ServiceRemote jus::Client::getService(const std::string& _name) { + return jus::ServiceRemote(this, _name); +} + +void jus::Client::link(const std::string& _serviceName) { + // TODO : Check the number of connection of this service ... + bool ret = call_b("link", _serviceName); + if (ret == false) { + JUS_ERROR("Can not link with the service named: '" << _serviceName << "'"); + } +} + +void jus::Client::unlink(const std::string& _serviceName) { + bool ret = call_b("unlink", _serviceName); + if (ret == false) { + JUS_ERROR("Can not unlink with the service named: '" << _serviceName << "'"); + } +} + std::string jus::Client::asyncRead() { int32_t iii = 5000; while (iii>0) { @@ -48,28 +65,31 @@ std::string jus::Client::asyncRead() { } void jus::Client::onPropertyChangeIp() { - m_interfaceClient.propertyIp.set(*propertyIp); + disconnect(); } void jus::Client::onPropertyChangePort(){ - m_interfaceClient.propertyPort.set(*propertyPort); + disconnect(); } void jus::Client::connect(const std::string& _remoteUserToConnect){ + disconnect(); JUS_DEBUG("connect [START]"); + enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort)); + m_interfaceClient.setInterface(std::move(connection)); m_interfaceClient.connect(); m_interfaceClient.write(std::string("{\"connect-to-user\":\"") + _remoteUserToConnect + "\", \"client-type:\":\"jus-client\"}"); JUS_DEBUG("connect [STOP]"); } -void jus::Client::disconnect(){ +void jus::Client::disconnect() { JUS_DEBUG("disconnect [START]"); m_interfaceClient.disconnect(); JUS_DEBUG("disconnect [STOP]"); } -ejson::Object jus::Client::createBaseCall(const std::string& _service, const std::string& _functionName) { +ejson::Object jus::Client::createBaseCall(const std::string& _functionName, const std::string& _service) { ejson::Object obj; if (_service.size() != 0) { obj.add("service", ejson::String(_service)); diff --git a/jus/Client.h b/jus/Client.h index 1f5157c..9a4831f 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -9,9 +9,11 @@ #include #include #include +#include namespace jus { class Client : public eproperty::Interface { + friend class ServiceRemote; public: eproperty::Value propertyIp; eproperty::Value propertyPort; @@ -25,11 +27,15 @@ namespace jus { virtual ~Client(); void connect(const std::string& _remoteUserToConnect); void disconnect(); + public: + jus::ServiceRemote getService(const std::string& _serviceName); + void link(const std::string& _serviceName); + void unlink(const std::string& _serviceName); private: void onClientData(const std::string& _value); std::string asyncRead(); ejson::Object callJson(const ejson::Object& _obj); - ejson::Object createBaseCall( const std::string& _service, const std::string& _functionName); + ejson::Object createBaseCall(const std::string& _functionName, const std::string& _service=""); void createParam(ejson::Object& _obj) { // Finish recursive parse ... } @@ -125,8 +131,8 @@ namespace jus { } public: template - void call(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + void call(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -134,8 +140,8 @@ namespace jus { } } template - int32_t call_i(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + int32_t call_i(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -153,8 +159,8 @@ namespace jus { return int32_t(val.toNumber().get()); } template - double call_d(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + double call_d(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -172,8 +178,8 @@ namespace jus { return val.toNumber().get(); } template - std::string call_s(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + std::string call_s(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -191,8 +197,8 @@ namespace jus { return val.toString().get(); } template - bool call_b(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + bool call_b(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -210,8 +216,8 @@ namespace jus { return val.toBoolean().get(); } template - std::vector call_vi(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + std::vector call_vi(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -241,8 +247,8 @@ namespace jus { return out; } template - std::vector call_vd(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + std::vector call_vd(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -272,8 +278,8 @@ namespace jus { return out; } template - std::vector call_vs(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + std::vector call_vs(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { @@ -303,8 +309,8 @@ namespace jus { return out; } template - std::vector call_vb(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = createBaseCall(_service, _functionName); + std::vector call_vb(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); createParam(callElem, std::forward<_ARGS>(_args)...); ejson::Object obj = callJson(callElem); if (obj.valueExist("error") == true) { diff --git a/jus/GateWay.cpp b/jus/GateWay.cpp index 09104ae..e1331ba 100644 --- a/jus/GateWay.cpp +++ b/jus/GateWay.cpp @@ -6,8 +6,78 @@ #include #include +#include +namespace jus { + class TcpServerInput { + private: + enet::TcpServer m_interface; + std::thread* m_thread; + bool m_threadRunning; + jus::GateWay* m_gateway; + bool m_service; + public: + TcpServerInput(jus::GateWay* _gateway, bool _service) : + m_thread(nullptr), + m_threadRunning(false), + m_gateway(_gateway), + m_service(_service) { + + } + virtual ~TcpServerInput() {} + void start(const std::string& _host, uint16_t _port) { + m_interface.setHostNane(_host); + m_interface.setPort(_port); + m_interface.link(); + m_threadRunning = true; + m_thread = new std::thread([&](void *){ this->threadCallback();}, nullptr); + if (m_thread == nullptr) { + m_threadRunning = false; + JUS_ERROR("creating callback thread!"); + return; + } + } + void stop() { + if (m_thread != nullptr) { + m_threadRunning = false; + } + m_interface.unlink(); + if (m_thread != nullptr) { + m_thread->join(); + delete m_thread; + m_thread = nullptr; + } + } + void threadCallback() { + // get datas: + while (m_threadRunning == true) { + // READ section data: + enet::Tcp data = std::move(m_interface.waitNext()); + JUS_VERBOSE("New connection"); + if (m_service == true) { + m_gateway->newService(std::move(data)); + } else { + m_gateway->newClient(std::move(data)); + } + } + } + }; +} + +void jus::GateWay::newService(enet::Tcp _connection) { + JUS_WARNING("New TCP connection (service)"); + ememory::SharedPtr tmp = std::make_shared(std::move(_connection), this); + tmp->start(); + m_serviceList.push_back(tmp); +} + +void jus::GateWay::newClient(enet::Tcp _connection) { + JUS_WARNING("New TCP connection (client)"); + ememory::SharedPtr tmp = std::make_shared(std::move(_connection), this); + tmp->start(m_clientUID++); + m_clientList.push_back(tmp); +} jus::GateWay::GateWay() : m_clientUID(1), @@ -17,7 +87,8 @@ jus::GateWay::GateWay() : propertyServiceIp(this, "service-ip", "127.0.0.1", "Ip to listen client", &jus::GateWay::onPropertyChangeServiceIp), propertyServicePort(this, "service-port", 1982, "Port to listen client", &jus::GateWay::onPropertyChangeServicePort), propertyServiceMax(this, "service-max", 80, "Maximum of client at the same time", &jus::GateWay::onPropertyChangeServiceMax) { - + m_interfaceClientServer = std::make_shared(this, false); + m_interfaceServiceServer = std::make_shared(this, true); } jus::GateWay::~GateWay() { @@ -25,12 +96,8 @@ jus::GateWay::~GateWay() { } void jus::GateWay::start() { - m_clientWaiting = std::make_shared(this); - m_clientConnected = m_clientWaiting->signalIsConnected.connect(this, &jus::GateWay::onClientConnect); - m_clientWaiting->start(*propertyClientIp, *propertyClientPort, m_clientUID++); - m_serviceWaiting = std::make_shared(this); - m_serviceConnected = m_serviceWaiting->signalIsConnected.connect(this, &jus::GateWay::onServiceConnect); - m_serviceWaiting->start(*propertyServiceIp, *propertyServicePort); + m_interfaceClientServer->start(*propertyClientIp, *propertyClientPort); + m_interfaceServiceServer->start(*propertyServiceIp, *propertyServicePort); } void jus::GateWay::stop() { @@ -47,11 +114,22 @@ ememory::SharedPtr jus::GateWay::get(const std::string& _se } return it; } - // TODO : Remove this ... - return m_serviceWaiting; return nullptr; } +void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) { + for (auto &it : m_clientList) { + if (it == nullptr) { + continue; + } + if (it->getId() != _userSessionId) { + continue; + } + it->returnMessage(_data); + return; + } +} + void jus::GateWay::onClientConnect(const bool& _value) { JUS_TODO("Client connection: " << _value); } diff --git a/jus/GateWay.h b/jus/GateWay.h index feef56c..6a4994f 100644 --- a/jus/GateWay.h +++ b/jus/GateWay.h @@ -6,8 +6,10 @@ #pragma once #include #include +#include namespace jus { + class TcpServerInput; class GateWay : public eproperty::Interface { private: size_t m_clientUID; @@ -15,10 +17,8 @@ namespace jus { std::vector> m_serviceList; //!< List of all service availlable with their specific connection interface std::vector> m_clientList; //!< List of all Client interface with their own connection //TODO: std::vector m_ServerList; //!< List of all Server connected to this gateway - ememory::SharedPtr m_clientWaiting; - esignal::Connection m_clientConnected; - ememory::SharedPtr m_serviceWaiting; - esignal::Connection m_serviceConnected; + ememory::SharedPtr m_interfaceClientServer; + ememory::SharedPtr m_interfaceServiceServer; public: eproperty::Value propertyClientIp; eproperty::Value propertyClientPort; @@ -32,6 +32,9 @@ namespace jus { void start(); void stop(); ememory::SharedPtr get(const std::string& _serviceName); + void answer(uint64_t _userSessionId, ejson::Object _data); + void newService(enet::Tcp _connection); + void newClient(enet::Tcp _connection); private: void onPropertyChangeClientIp(); void onPropertyChangeClientPort(); diff --git a/jus/GateWayClient.cpp b/jus/GateWayClient.cpp index a07347b..2cfd33b 100644 --- a/jus/GateWayClient.cpp +++ b/jus/GateWayClient.cpp @@ -10,21 +10,19 @@ #include #include -jus::GateWayClient::GateWayClient(jus::GateWay* _gatewayInterface) : +jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface) : m_gatewayInterface(_gatewayInterface), + m_interfaceClient(std::move(_connection)), m_returnValueOk(false) { } jus::GateWayClient::~GateWayClient() { - + JUS_TODO("Call All unlink ..."); } -void jus::GateWayClient::start(const std::string& _ip, uint16_t _port, size_t _uid) { - m_interfaceClient.propertyIp.set(_ip); - m_interfaceClient.propertyPort.set(_port); +void jus::GateWayClient::start(size_t _uid) { m_uid = _uid; - m_interfaceClient.propertyServer.set(true); m_interfaceClient.connect(true); m_interfaceClient.setInterfaceName("cli-" + etk::to_string(m_uid)); m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::GateWayClient::onClientData); @@ -71,6 +69,82 @@ void jus::GateWayClient::onClientData(const std::string& _value) { answer.add("return", listService); } else if (call == "getServiceInformation") { + } else if (call == "link") { + // first param: + std::string serviceName = data["param"].toArray()[0].toString().get(); + // Check if service already link: + auto it = m_listConnectedService.begin(); + while (it != m_listConnectedService.end()) { + if (*it == nullptr) { + ++it; + continue; + } + if ((*it)->getName() != service) { + ++it; + continue; + } + break; + } + if (it == m_listConnectedService.end()) { + // TODO : check if we have authorisation to connect service + ememory::SharedPtr srv = m_gatewayInterface->get(serviceName); + if (srv != nullptr) { + ejson::Object linkService; + linkService.add("user", ejson::String(m_userConnectionName)); + srv->SendData(m_uid, linkService, "new"); + while (m_returnValueOk == false) { + JUS_DEBUG("wait Return Value (LINK)"); + usleep(20000); + } + JUS_DEBUG("new answer: " << m_returnMessage.generate()); + if (m_returnMessage["return"].toString().get() == "OK") { + m_listConnectedService.push_back(srv); + answer.add("return", ejson::Boolean(true)); + } else { + answer.add("return", ejson::Boolean(false)); + } + m_returnValueOk = false; + } else { + answer.add("return", ejson::Boolean(false)); + } + } else { + // TODO : Service already connected; + answer.add("return", ejson::Boolean(false)); + } + } else if (call == "unlink") { + // first param: + std::string serviceName = data["param"].toArray()[0].toString().get(); + // Check if service already link: + auto it = m_listConnectedService.begin(); + while (it != m_listConnectedService.end()) { + if (*it == nullptr) { + ++it; + continue; + } + if ((*it)->getName() != service) { + ++it; + continue; + } + break; + } + if (it == m_listConnectedService.end()) { + // TODO : Service already unlink; + answer.add("return", ejson::Boolean(false)); + } else { + (*it)->SendData(m_uid, ejson::Object(), "delete"); + while (m_returnValueOk == false) { + JUS_DEBUG("wait Return Value (UNLINK)"); + usleep(20000); + } + JUS_DEBUG("new answer: " << m_returnMessage.generate()); + if (m_returnMessage["return"].toString().get() == "OK") { + m_listConnectedService.erase(it); + answer.add("return", ejson::Boolean(true)); + } else { + answer.add("return", ejson::Boolean(false)); + } + m_returnValueOk = false; + } } else { JUS_ERROR("Function does not exist ... '" << call << "'"); answer.add("error", ejson::String("CALL-UNEXISTING")); @@ -95,16 +169,18 @@ void jus::GateWayClient::onClientData(const std::string& _value) { break; } if (it == m_listConnectedService.end()) { - ememory::SharedPtr srv = m_gatewayInterface->get(service); - if (srv != nullptr) { - m_listConnectedService.push_back(srv); - it = m_listConnectedService.end()-1; - } else { - // TODO: Return an error ... - } - } - if (it != m_listConnectedService.end()) { - JUS_CRITICAL("Add in link the name of the user in parameter ..." + // 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")); + std::string valueReturn = answer.generate(); + JUS_DEBUG("answer: " << valueReturn); + m_interfaceClient.write(valueReturn); + } else { + JUS_ERROR("Add in link the name of the user in parameter ..."); + data.remove("service"); (*it)->SendData(m_uid, data); while (m_returnValueOk == false) { JUS_DEBUG("wait Return Value"); diff --git a/jus/GateWayClient.h b/jus/GateWayClient.h index 2393f43..972d79f 100644 --- a/jus/GateWayClient.h +++ b/jus/GateWayClient.h @@ -15,8 +15,8 @@ namespace jus { class GateWayClient { private: jus::GateWay* m_gatewayInterface; - public: jus::TcpString m_interfaceClient; + public: esignal::Signal signalIsConnected; esignal::Connection m_dataCallback; bool m_returnValueOk; @@ -25,12 +25,15 @@ namespace jus { size_t m_uid; std::string m_userConnectionName; public: - GateWayClient(jus::GateWay* _gatewayInterface); + GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface); virtual ~GateWayClient(); - void start(const std::string& _ip, uint16_t _port, size_t _uid); + void start(size_t _uid); void stop(); void onClientData(const std::string& _value); void returnMessage(ejson::Object _data); + size_t getId() const { + return m_uid; + } }; } diff --git a/jus/GateWayService.cpp b/jus/GateWayService.cpp index 94a5f70..6203592 100644 --- a/jus/GateWayService.cpp +++ b/jus/GateWayService.cpp @@ -6,10 +6,12 @@ #include #include +#include #include -jus::GateWayService::GateWayService(jus::GateWay* _gatewayInterface) : - m_gatewayInterface(_gatewayInterface) { +jus::GateWayService::GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface) : + m_gatewayInterface(_gatewayInterface), + m_interfaceClient(std::move(_connection)) { } @@ -17,28 +19,25 @@ jus::GateWayService::~GateWayService() { } -void jus::GateWayService::start(const std::string& _ip, uint16_t _port) { - m_interfaceClient.propertyIp.set(_ip); - m_interfaceClient.propertyPort.set(_port); - m_interfaceClient.propertyServer.set(true); - m_interfaceClient.connect(true); +void jus::GateWayService::start() { + m_interfaceClient.connect(); m_interfaceClient.setInterfaceName("srv-?"); - m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::GateWayService::onClientData); + m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::GateWayService::onServiceData); } void jus::GateWayService::stop() { m_interfaceClient.disconnect(); } -void jus::GateWayService::SendData(size_t _userSessionId, ejson::Object _data) { +void jus::GateWayService::SendData(size_t _userSessionId, ejson::Object _data, const std::string& _action) { _data.add("client-id", ejson::String(etk::to_string(_userSessionId))); - _data.add("action", ejson::String("call")); + _data.add("action", ejson::String(_action)); std::string value = _data.generate(); JUS_DEBUG("Send Service: " << value); m_interfaceClient.write(value); } -void jus::GateWayService::onClientData(const std::string& _value) { +void jus::GateWayService::onServiceData(const std::string& _value) { JUS_DEBUG("On service data: " << _value); ejson::Object data(_value); if (data.valueExist("connect-service") == true) { @@ -54,9 +53,12 @@ void jus::GateWayService::onClientData(const std::string& _value) { return; } if (data.valueExist("client-id") == false) { - JUS_WARNING("Service interface ==> wrong service answer ==> missing 'client-id'"); + JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'"); return; } - JUS_TODO("plop..........."); + uint64_t userSessionId = etk::string_to_uint64_t(data["client-id"].toString().get()); + data.remove("client-id"); + data.remove("action"); + m_gatewayInterface->answer(userSessionId, data); } diff --git a/jus/GateWayService.h b/jus/GateWayService.h index 20feb37..568c5c9 100644 --- a/jus/GateWayService.h +++ b/jus/GateWayService.h @@ -15,19 +15,19 @@ namespace jus { class GateWayService { private: jus::GateWay* m_gatewayInterface; + jus::TcpString m_interfaceClient; std::string m_name; public: - jus::TcpString m_interfaceClient; esignal::Signal signalIsConnected; esignal::Connection m_dataCallback; public: - GateWayService(jus::GateWay* _gatewayInterface); + GateWayService(enet::Tcp _connection, jus::GateWay* _gatewayInterface); virtual ~GateWayService(); - void start(const std::string& _ip, uint16_t _port); + void start(); void stop(); - void onClientData(const std::string& _value); + void onServiceData(const std::string& _value); public: - void SendData(size_t _userSessionId, ejson::Object _data); + void SendData(size_t _userSessionId, ejson::Object _data, const std::string& _action="call"); const std::string& getName() { return m_name; } diff --git a/jus/Service.cpp b/jus/Service.cpp index 8fbe4dd..1a2af6b 100644 --- a/jus/Service.cpp +++ b/jus/Service.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -17,9 +18,6 @@ jus::Service::Service() : propertyIp(this, "ip", "127.0.0.1", "Ip to connect server", &jus::Service::onPropertyChangeIp), propertyPort(this, "port", 1982, "Port to connect server", &jus::Service::onPropertyChangePort), m_id(0) { - m_interfaceClient.propertyIp.set(*propertyIp); - m_interfaceClient.propertyPort.set(*propertyPort); - m_interfaceClient.propertyServer.set(false); m_dataCallback = m_interfaceClient.signalData.connect(this, &jus::Service::onClientData); } @@ -29,21 +27,27 @@ jus::Service::~Service() { void jus::Service::onClientData(const std::string& _value) { ejson::Object request(_value); - JUS_INFO("Request : " << _value); - m_interfaceClient.write("{ \"error\": \"NOT-IMPLEMENTED\"}"); + JUS_INFO("Request: " << _value); + ejson::Object answer = callJson(request); + std::string answerString = answer.generate(); + JUS_INFO("Answer: " << answerString); + m_interfaceClient.write(answerString); } void jus::Service::onPropertyChangeIp() { - m_interfaceClient.propertyIp.set(*propertyIp); + disconnect(); } void jus::Service::onPropertyChangePort(){ - m_interfaceClient.propertyPort.set(*propertyPort); + disconnect(); } void jus::Service::connect(const std::string& _serviceName){ + disconnect(); JUS_DEBUG("connect [START]"); + enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort)); + m_interfaceClient.setInterface(std::move(connection)); m_interfaceClient.connect(); m_interfaceClient.write(std::string("{\"connect-service\":\"") + _serviceName + "\"}"); JUS_DEBUG("connect [STOP]"); @@ -57,44 +61,31 @@ void jus::Service::disconnect(){ ejson::Object jus::Service::callJson(const ejson::Object& _obj) { std::string action = _obj["action"].toString().get(); - #if 0 - if (action == "new") { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); - std::string userName = _obj["user"].toString().get(); - clientConnect(clientId, userName); - ejson::Object tmpp; - tmpp.add("return", ejson::String("OK")); - return tmpp; - } else if (action == "delete") { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); - clientDisconnect(clientId); - ejson::Object tmpp; - tmpp.add("return", ejson::String("OK")); - return tmpp; - } else if ( action == "call" - || action == "") { - uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); - return callJson2(clientId, _obj); - } else { - // TODO : ... - } - #else + if (action == "new") { uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); - std::string call = _obj["call"].toString().get(); - if (call == "link") { - std::string userName = _obj["param"].toArray[0].toString().get(); - clientConnect(clientId, userName); - ejson::Object tmpp; - tmpp.add("return", ejson::String("OK")); - return tmpp; - } else if (call == "unlink") { - clientDisconnect(clientId); - ejson::Object tmpp; - tmpp.add("return", ejson::String("OK")); - return tmpp; - } else { - return callJson2(clientId, _obj); - } - #endif + std::string userName = _obj["user"].toString().get(); + clientConnect(clientId, userName); + ejson::Object tmpp; + tmpp.add("client-id", ejson::String(etk::to_string(clientId))); + tmpp.add("return", ejson::String("OK")); + return tmpp; + } else if (action == "delete") { + uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + clientDisconnect(clientId); + ejson::Object tmpp; + tmpp.add("client-id", ejson::String(etk::to_string(clientId))); + tmpp.add("return", ejson::String("OK")); + return tmpp; + } else if ( action == "call" + || action == "") { + uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); + ejson::Object tmpp = callJson2(clientId, _obj); + tmpp.add("client-id", ejson::String(etk::to_string(clientId))); + return tmpp; + } else { + ejson::Object tmpp; + tmpp.add("error", ejson::String("NOT-IMPLEMENTED-ACTION")); + return tmpp; + } return ejson::Object(); } diff --git a/jus/ServiceRemote.cpp b/jus/ServiceRemote.cpp new file mode 100644 index 0000000..71249d5 --- /dev/null +++ b/jus/ServiceRemote.cpp @@ -0,0 +1,27 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include + +jus::ServiceRemote::ServiceRemote(jus::Client* _clientInterface, const std::string& _name): + m_clientInterface(_clientInterface), + m_name(_name) { + m_clientInterface->link(_name); +} + +jus::ServiceRemote::~ServiceRemote() { + m_clientInterface->unlink(m_name); +} + + +ejson::Object jus::ServiceRemote::createBaseCall(const std::string& _functionName) { + return m_clientInterface->createBaseCall(_functionName, m_name); +} + +ejson::Object jus::ServiceRemote::callJson(const ejson::Object& _obj) { + return m_clientInterface->callJson(_obj); +} diff --git a/jus/ServiceRemote.h b/jus/ServiceRemote.h new file mode 100644 index 0000000..2d74c8c --- /dev/null +++ b/jus/ServiceRemote.h @@ -0,0 +1,331 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2016, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace jus { + class Client; + class ServiceRemote { + private: + jus::Client* m_clientInterface; + std::string m_name; + public: + ServiceRemote(jus::Client* _clientInterface, const std::string& _name); + ~ServiceRemote(); + private: + ejson::Object callJson(const ejson::Object& _obj); + ejson::Object createBaseCall(const std::string& _functionName); + void createParam(ejson::Object& _obj) { + // Finish recursive parse ... + } + template + void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + if (_param == nullptr) { + array.add(ejson::String()); + } else { + array.add(ejson::String(_param)); + } + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::string& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + array.add(ejson::String(_param)); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const bool& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + array.add(ejson::Boolean(_param)); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const int32_t& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + array.add(ejson::Number(_param)); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const double& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + array.add(ejson::Number(_param)); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const float& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + array.add(ejson::Number(_param)); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + ejson::Array array2; + for (auto& it : _param) { + array2.add(ejson::String(it)); + } + array.add(array2); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + ejson::Array array2; + for (const auto& it : _param) { + array2.add(ejson::Boolean(it)); + } + array.add(array2); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + ejson::Array array2; + for (auto& it : _param) { + array2.add(ejson::Number(it)); + } + array.add(array2); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + ejson::Array array2; + for (auto& it : _param) { + array2.add(ejson::Number(it)); + } + array.add(array2); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + template + void createParam(ejson::Object& _obj, const std::vector& _param, _ARGS&&... _args) { + ejson::Array array = _obj["param"].toArray(); + ejson::Array array2; + for (auto& it : _param) { + array2.add(ejson::Number(it)); + } + array.add(array2); + createParam(_obj, std::forward<_ARGS>(_args)...); + } + public: + template + void call(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + } + template + int32_t call_i(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return 0; + } + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); + return 0; + } + return int32_t(val.toNumber().get()); + } + template + double call_d(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return 0.0; + } + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); + return 0.0; + } + return val.toNumber().get(); + } + template + std::string call_s(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return ""; + } + if (val.isString() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'String'"); + return ""; + } + return val.toString().get(); + } + template + bool call_b(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return false; + } + if (val.isBoolean() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); + return false; + } + return val.toBoolean().get(); + } + template + std::vector call_vi(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + if (obj.valueExist("return") == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return std::vector(); + } + std::vector out; + for (auto it : val.toArray()) { + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); + continue; + } + out.push_back(int32_t(val.toNumber().get())); + } + return out; + } + template + std::vector call_vd(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + if (obj.valueExist("return") == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return std::vector(); + } + std::vector out; + for (auto it : val.toArray()) { + if (it.isNumber() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); + continue; + } + out.push_back(it.toNumber().get()); + } + return out; + } + template + std::vector call_vs(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + if (obj.valueExist("return") == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return std::vector(); + } + std::vector out; + for (auto it : val.toArray()) { + if (it.isString() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'String'"); + continue; + } + out.push_back(it.toString().get()); + } + return out; + } + template + std::vector call_vb(const std::string& _functionName, _ARGS&&... _args) { + ejson::Object callElem = createBaseCall(_functionName); + createParam(callElem, std::forward<_ARGS>(_args)...); + ejson::Object obj = callJson(callElem); + if (obj.valueExist("error") == true) { + JUS_WARNING("call error: " << obj["error"]); + } + if (obj.valueExist("return") == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + ejson::Value val = obj["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return std::vector(); + } + std::vector out; + for (auto it : val.toArray()) { + if (it.isBoolean() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Boolean'"); + continue; + } + out.push_back(it.toBoolean().get()); + } + return out; + } + }; +} + diff --git a/jus/TcpString.cpp b/jus/TcpString.cpp index 12ce6bc..fa7ef06 100644 --- a/jus/TcpString.cpp +++ b/jus/TcpString.cpp @@ -8,19 +8,26 @@ #include #include -jus::TcpString::TcpString() : +jus::TcpString::TcpString(enet::Tcp _connection) : + m_connection(std::move(_connection)), m_thread(nullptr), - propertyIp(this, "ip", "127.0.0.1", "ip to open or connect server", &jus::TcpString::onPropertyChangeIp), - propertyPort(this, "port", 1983, "Connection port of the server", &jus::TcpString::onPropertyChangePort), - propertyServer(this, "server", false, "is a server or not", &jus::TcpString::onPropertyChangeServer), signalIsConnected(), signalData() { - m_connection.setHostNane(*propertyIp); - m_connection.setPort(*propertyPort); - m_connection.setServer(*propertyServer); m_threadRunning = false; } +jus::TcpString::TcpString() : + m_connection(), + m_thread(nullptr), + signalIsConnected(), + signalData() { + m_threadRunning = false; +} + +void jus::TcpString::setInterface(enet::Tcp _connection) { + m_connection = std::move(_connection); +} + jus::TcpString::~TcpString() { disconnect(); } @@ -31,13 +38,6 @@ void jus::TcpString::setInterfaceName(const std::string& _name) { void jus::TcpString::threadCallback() { ethread::setName("TcpString-input"); - // Connect ... - if (m_connection.link() == false) { - JUS_ERROR("can not connect to the socket..."); - signalIsConnected.emit(false); - return; - } - signalIsConnected.emit(true); // get datas: while ( m_threadRunning == true && m_connection.getConnectionStatus() == enet::Tcp::status::link) { @@ -48,11 +48,6 @@ void jus::TcpString::threadCallback() { signalData.emit(data); } } - // disconnect ... - if (m_connection.unlink() == false) { - JUS_ERROR("can not disconnect to the socket..."); - } - signalIsConnected.emit(false); JUS_DEBUG("End of thread"); } @@ -135,15 +130,3 @@ std::string jus::TcpString::read() { return out; } -void jus::TcpString::onPropertyChangeIp() { - m_connection.setHostNane(*propertyIp); -} - -void jus::TcpString::onPropertyChangePort() { - m_connection.setPort(*propertyPort); -} - -void jus::TcpString::onPropertyChangeServer() { - m_connection.setServer(*propertyServer); -} - diff --git a/jus/TcpString.h b/jus/TcpString.h index fc80eab..a83b53b 100644 --- a/jus/TcpString.h +++ b/jus/TcpString.h @@ -17,14 +17,13 @@ namespace jus { std::thread* m_thread; bool m_threadRunning; public: - eproperty::Value propertyIp; - eproperty::Value propertyPort; - eproperty::Value propertyServer; esignal::Signal signalIsConnected; esignal::Signal signalData; public: TcpString(); + TcpString(enet::Tcp _connection); virtual ~TcpString(); + void setInterface(enet::Tcp _connection); void connect(bool _async = false); void disconnect(); void setInterfaceName(const std::string& _name); @@ -33,9 +32,6 @@ namespace jus { private: std::string read(); private: - void onPropertyChangeIp(); - void onPropertyChangePort(); - void onPropertyChangeServer(); void threadCallback(); }; } diff --git a/lutin_jus.py b/lutin_jus.py index ed7ceb1..21d5292 100644 --- a/lutin_jus.py +++ b/lutin_jus.py @@ -41,6 +41,7 @@ def create(target, module_name): 'jus/GateWayService.cpp', 'jus/GateWayClient.cpp', 'jus/Service.cpp', + 'jus/ServiceRemote.cpp', 'jus/TcpString.cpp', ]) my_module.add_header_file([ @@ -54,6 +55,7 @@ def create(target, module_name): 'jus/GateWayService.h', 'jus/GateWayClient.h', 'jus/Service.h', + 'jus/ServiceRemote.h', 'jus/TcpString.h', ]) if target.config["compilator"] == "clang": diff --git a/test/client/appl/main.cpp b/test/client/appl/main.cpp index ba47bf1..3800ad2 100644 --- a/test/client/appl/main.cpp +++ b/test/client/appl/main.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -42,23 +43,18 @@ int main(int _argc, const char *_argv[]) { tmp.push_back(22); tmp.push_back(333); tmp.push_back(4444); - int32_t val = client1.call_i("", "getServiceCount", tmp, "coucou", false); + int32_t val = client1.call_i("getServiceCount", tmp, "coucou", false); APPL_INFO("Nb services = " << val); - std::vector val2 = client1.call_vs("", "getServiceList"); + std::vector val2 = client1.call_vs("getServiceList"); APPL_INFO("List services:"); for (auto &it: val2) { APPL_INFO(" - " << it); } - // TODO: add return value - bool valConnect = client1.call_b("serviceTest1", "link"); - APPL_INFO("Link service 'serviceTest1' ret=" << valConnect); + jus::ServiceRemote localService = client1.getService("serviceTest1"); - bool retCall = client1.call_d("serviceTest1", "mul", 13.1, 2.0); + double retCall = localService.call_d("mul", 13.1, 2.0); APPL_INFO("serviceTest1.mul = " << retCall); - valConnect = client1.call_b("serviceTest1", "unlink"); - APPL_INFO("un-Link service 'serviceTest1' ret=" << valConnect); - int32_t iii=0; while (iii < 3) { usleep(500000); diff --git a/test/service1/appl/main.cpp b/test/service1/appl/main.cpp index 39763f0..39dc311 100644 --- a/test/service1/appl/main.cpp +++ b/test/service1/appl/main.cpp @@ -53,8 +53,7 @@ namespace appl { private: ememory::SharedPtr m_user; public: - double mul(double _val1) {//, const double& _val2) { - double _val2 = 1.0f; + double mul(double _val1, double _val2) { return _val1*_val2; } public: