[DEV] continue better interfacing

This commit is contained in:
Edouard DUPIN 2016-05-23 21:18:37 +02:00
parent 2e49776f86
commit 50544c3704
16 changed files with 682 additions and 169 deletions

View File

@ -4,6 +4,7 @@
* @license APACHE v2.0 (see license file)
*/
#include <enet/TcpClient.h>
#include <jus/Client.h>
#include <jus/debug.h>
@ -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,16 +65,19 @@ 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]");
@ -69,7 +89,7 @@ void jus::Client::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));

View File

@ -9,9 +9,11 @@
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/debug.h>
#include <jus/ServiceRemote.h>
namespace jus {
class Client : public eproperty::Interface {
friend class ServiceRemote;
public:
eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> 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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
std::vector<int32_t> call_vi(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_service, _functionName);
std::vector<int32_t> 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<class... _ARGS>
std::vector<double> call_vd(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_service, _functionName);
std::vector<double> 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<class... _ARGS>
std::vector<std::string> call_vs(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_service, _functionName);
std::vector<std::string> 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<class... _ARGS>
std::vector<bool> call_vb(const std::string& _service, const std::string& _functionName, _ARGS&&... _args) {
ejson::Object callElem = createBaseCall(_service, _functionName);
std::vector<bool> 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) {

View File

@ -6,8 +6,78 @@
#include <jus/GateWay.h>
#include <jus/debug.h>
#include <enet/TcpServer.h>
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<jus::GateWayService> tmp = std::make_shared<jus::GateWayService>(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<jus::GateWayClient> tmp = std::make_shared<jus::GateWayClient>(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<jus::TcpServerInput>(this, false);
m_interfaceServiceServer = std::make_shared<jus::TcpServerInput>(this, true);
}
jus::GateWay::~GateWay() {
@ -25,12 +96,8 @@ jus::GateWay::~GateWay() {
}
void jus::GateWay::start() {
m_clientWaiting = std::make_shared<jus::GateWayClient>(this);
m_clientConnected = m_clientWaiting->signalIsConnected.connect(this, &jus::GateWay::onClientConnect);
m_clientWaiting->start(*propertyClientIp, *propertyClientPort, m_clientUID++);
m_serviceWaiting = std::make_shared<jus::GateWayService>(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::GateWayService> 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);
}

View File

@ -6,8 +6,10 @@
#pragma once
#include <jus/GateWayService.h>
#include <jus/GateWayClient.h>
#include <ejson/ejson.h>
namespace jus {
class TcpServerInput;
class GateWay : public eproperty::Interface {
private:
size_t m_clientUID;
@ -15,10 +17,8 @@ namespace jus {
std::vector<ememory::SharedPtr<jus::GateWayService>> m_serviceList; //!< List of all service availlable with their specific connection interface
std::vector<ememory::SharedPtr<jus::GateWayClient>> m_clientList; //!< List of all Client interface with their own connection
//TODO: std::vector<jus::GateWayServer> m_ServerList; //!< List of all Server connected to this gateway
ememory::SharedPtr<jus::GateWayClient> m_clientWaiting;
esignal::Connection m_clientConnected;
ememory::SharedPtr<jus::GateWayService> m_serviceWaiting;
esignal::Connection m_serviceConnected;
ememory::SharedPtr<jus::TcpServerInput> m_interfaceClientServer;
ememory::SharedPtr<jus::TcpServerInput> m_interfaceServiceServer;
public:
eproperty::Value<std::string> propertyClientIp;
eproperty::Value<uint16_t> propertyClientPort;
@ -32,6 +32,9 @@ namespace jus {
void start();
void stop();
ememory::SharedPtr<jus::GateWayService> 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();

View File

@ -10,21 +10,19 @@
#include <jus/GateWay.h>
#include <unistd.h>
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<jus::GateWayService> 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<jus::GateWayService> srv = m_gatewayInterface->get(service);
if (srv != nullptr) {
m_listConnectedService.push_back(srv);
it = m_listConnectedService.end()-1;
// 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 {
// TODO: Return an error ...
}
}
if (it != m_listConnectedService.end()) {
JUS_CRITICAL("Add in link the name of the user in parameter ..."
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");

View File

@ -15,8 +15,8 @@ namespace jus {
class GateWayClient {
private:
jus::GateWay* m_gatewayInterface;
public:
jus::TcpString m_interfaceClient;
public:
esignal::Signal<bool> 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;
}
};
}

View File

@ -6,10 +6,12 @@
#include <jus/debug.h>
#include <jus/GateWayService.h>
#include <jus/GateWay.h>
#include <ejson/ejson.h>
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);
}

View File

@ -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<bool> 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;
}

View File

@ -7,6 +7,7 @@
#include <jus/Service.h>
#include <jus/debug.h>
#include <etk/stdTools.h>
#include <enet/TcpClient.h>
#include <ejson/ejson.h>
#include <unistd.h>
@ -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);
}
@ -30,20 +28,26 @@ 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\"}");
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("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());
return callJson2(clientId, _obj);
} else {
// TODO : ...
}
#else
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"));
ejson::Object tmpp = callJson2(clientId, _obj);
tmpp.add("client-id", ejson::String(etk::to_string(clientId)));
return tmpp;
} else {
return callJson2(clientId, _obj);
ejson::Object tmpp;
tmpp.add("error", ejson::String("NOT-IMPLEMENTED-ACTION"));
return tmpp;
}
#endif
return ejson::Object();
}

27
jus/ServiceRemote.cpp Normal file
View File

@ -0,0 +1,27 @@
/** @file
* @author Edouard DUPIN
* @copyright 2016, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <jus/ServiceRemote.h>
#include <jus/Client.h>
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);
}

331
jus/ServiceRemote.h Normal file
View File

@ -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 <jus/TcpString.h>
#include <eproperty/Value.h>
#include <ejson/ejson.h>
#include <jus/debug.h>
#include <jus/ServiceRemote.h>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<std::string>& _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<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<bool>& _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<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<int32_t>& _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<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<double>& _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<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<float>& _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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
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<class... _ARGS>
std::vector<int32_t> 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<int32_t>();
}
ejson::Value val = obj["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return std::vector<int32_t>();
}
if (val.isArray() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'");
return std::vector<int32_t>();
}
std::vector<int32_t> 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<class... _ARGS>
std::vector<double> 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<double>();
}
ejson::Value val = obj["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return std::vector<double>();
}
if (val.isArray() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'");
return std::vector<double>();
}
std::vector<double> 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<class... _ARGS>
std::vector<std::string> 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<std::string>();
}
ejson::Value val = obj["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return std::vector<std::string>();
}
if (val.isArray() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'");
return std::vector<std::string>();
}
std::vector<std::string> 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<class... _ARGS>
std::vector<bool> 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<bool>();
}
ejson::Value val = obj["return"];
if (val.exist() == false) {
JUS_WARNING("No Return value ...");
return std::vector<bool>();
}
if (val.isArray() == false) {
JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'");
return std::vector<bool>();
}
std::vector<bool> 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;
}
};
}

View File

@ -8,19 +8,26 @@
#include <ethread/tools.h>
#include <unistd.h>
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);
}

View File

@ -17,14 +17,13 @@ namespace jus {
std::thread* m_thread;
bool m_threadRunning;
public:
eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> propertyPort;
eproperty::Value<bool> propertyServer;
esignal::Signal<bool> signalIsConnected;
esignal::Signal<std::string> 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();
};
}

View File

@ -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":

View File

@ -6,6 +6,7 @@
#include <appl/debug.h>
#include <jus/Client.h>
#include <jus/ServiceRemote.h>
#include <etk/etk.h>
#include <unistd.h>
@ -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<std::string> val2 = client1.call_vs("", "getServiceList");
std::vector<std::string> 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);

View File

@ -53,8 +53,7 @@ namespace appl {
private:
ememory::SharedPtr<appl::User> m_user;
public:
double mul(double _val1) {//, const double& _val2) {
double _val2 = 1.0f;
double mul(double _val1, double _val2) {
return _val1*_val2;
}
public: