[DEV] clean connect interface with the gateway

This commit is contained in:
Edouard DUPIN 2016-05-27 22:21:32 +02:00
parent 3ef98f5693
commit bdf4983fbe
17 changed files with 371 additions and 136 deletions

View File

@ -152,6 +152,12 @@ namespace jus {
} }
ejson::Object jus::createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params) {
ejson::Object callElem = createBaseCall(_transactionId, _functionName);
callElem.add("param", _params);
return callElem;
}
ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service) { ejson::Object jus::createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service) {
ejson::Object obj; ejson::Object obj;
if (_service.size() != 0) { if (_service.size() != 0) {
@ -207,6 +213,26 @@ bool jus::AbstractFunction::checkCompatibility(const ParamType& _type, const ejs
|| createType<double>() == _type) { || createType<double>() == _type) {
return _params.isNumber(); return _params.isNumber();
} }
if (createType<std::vector<std::string>>() == _type) {
return _params.isArray();
}
if ( createType<std::vector<bool>>() == _type
|| createType<std::vector<int64_t>>() == _type
|| createType<std::vector<int32_t>>() == _type
|| createType<std::vector<int16_t>>() == _type
|| createType<std::vector<int8_t>>() == _type
|| createType<std::vector<uint64_t>>() == _type
|| createType<std::vector<uint32_t>>() == _type
|| createType<std::vector<uint16_t>>() == _type
|| createType<std::vector<uint8_t>>() == _type
|| createType<std::vector<float>>() == _type
|| createType<std::vector<double>>() == _type) {
if (_params.isObject()) {
JUS_TODO("Special case of packaging of the data");
return false;
}
return _params.isArray();
}
if (createType<std::string>() == _type) { if (createType<std::string>() == _type) {
return _params.isString(); return _params.isString();
} }

View File

@ -52,6 +52,30 @@ namespace jus {
ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service=""); ejson::Object createBaseCall(uint64_t _transactionId, const std::string& _functionName, const std::string& _service="");
void createParam(ejson::Object& _obj); void createParam(ejson::Object& _obj);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::string& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const bool& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const int32_t& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const double& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const float& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<std::string>& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<bool>& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<int32_t>& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<double>& _param, _ARGS&&... _args);
template<class... _ARGS>
void createParam(ejson::Object& _obj, const std::vector<float>& _param, _ARGS&&... _args);
template<class... _ARGS> template<class... _ARGS>
void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args) { void createParam(ejson::Object& _obj, const char* _param, _ARGS&&... _args) {
if (_obj.valueExist("param") == false) { if (_obj.valueExist("param") == false) {
@ -188,7 +212,7 @@ namespace jus {
createParam(callElem, std::forward<_ARGS>(_args)...); createParam(callElem, std::forward<_ARGS>(_args)...);
return callElem; return callElem;
} }
ejson::Object createCallJson(uint64_t _transactionId, const std::string& _functionName, ejson::Array _params);
} }

View File

@ -22,12 +22,25 @@ jus::Client::~Client() {
} }
void jus::Client::onClientData(std::string _value) { void jus::Client::onClientData(std::string _value) {
JUS_DEBUG("Get answer : " << _value);
ejson::Object obj(_value); ejson::Object obj(_value);
jus::FutureBase future; jus::FutureBase future;
{ {
uint64_t tid = obj["id"].toNumber().get(); uint64_t tid = obj["id"].toNumber().get();
if (tid == 0) { if (tid == 0) {
JUS_ERROR("call with no ID ==> error ..."); if (obj["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &it : m_pendingCall) {
if (it.isValid() == false) {
continue;
}
it.setAnswer(obj);
}
m_pendingCall.clear();
} else {
JUS_ERROR("call with no ID ==> error ...");
}
return; return;
} }
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
@ -136,15 +149,15 @@ uint64_t jus::Client::getId() {
return m_id++; return m_id++;
} }
jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj) { jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) {
JUS_VERBOSE("Send JSON [START] "); JUS_VERBOSE("Send JSON [START] ");
if (m_interfaceClient.isActive() == false) { if (m_interfaceClient.isActive() == false) {
ejson::Object obj; ejson::Object obj;
obj.add("error", ejson::String("NOT-CONNECTED")); obj.add("error", ejson::String("NOT-CONNECTED"));
obj.add("error-help", ejson::String("Client interface not connected (no TCP)")); obj.add("error-help", ejson::String("Client interface not connected (no TCP)"));
return jus::FutureBase(_transactionId, true, obj); return jus::FutureBase(_transactionId, true, obj, _callback);
} }
jus::FutureBase tmpFuture(_transactionId); jus::FutureBase tmpFuture(_transactionId, _callback);
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
m_pendingCall.push_back(tmpFuture); m_pendingCall.push_back(tmpFuture);

View File

@ -43,7 +43,7 @@ namespace jus {
private: private:
void onClientData(std::string _value); void onClientData(std::string _value);
std::string asyncRead(); std::string asyncRead();
jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr);
public: public:
uint64_t getId(); uint64_t getId();
template<class... _ARGS> template<class... _ARGS>
@ -52,6 +52,12 @@ namespace jus {
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem); return callJson(id, callElem);
} }
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, _callback);
}
private: private:
void onPropertyChangeIp(); void onPropertyChangeIp();
void onPropertyChangePort(); void onPropertyChangePort();

View File

@ -16,16 +16,24 @@ jus::FutureBase::FutureBase() {
m_data = nullptr; m_data = nullptr;
} }
jus::FutureBase::FutureBase(uint64_t _transactionId) { jus::FutureBase::FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback) {
m_data = std::make_shared<jus::FutureData>(); m_data = std::make_shared<jus::FutureData>();
if (m_data == nullptr) { if (m_data == nullptr) {
return; return;
} }
m_data->m_transactionId = _transactionId; m_data->m_transactionId = _transactionId;
m_data->m_isFinished = false; m_data->m_isFinished = false;
m_data->m_callbackFinish = _callback;
} }
jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData) { ejson::Object jus::FutureBase::getRaw() {
if (m_data == nullptr) {
return ejson::Object();
}
return m_data->m_returnData;
}
jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback) {
m_data = std::make_shared<jus::FutureData>(); m_data = std::make_shared<jus::FutureData>();
if (m_data == nullptr) { if (m_data == nullptr) {
return; return;
@ -33,6 +41,11 @@ jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Ob
m_data->m_transactionId = _transactionId; m_data->m_transactionId = _transactionId;
m_data->m_isFinished = _isFinished; m_data->m_isFinished = _isFinished;
m_data->m_returnData = _returnData; m_data->m_returnData = _returnData;
m_data->m_callbackFinish = _callback;
if ( m_data->m_isFinished == true
&& m_data->m_callbackFinish != nullptr) {
m_data->m_callbackFinish(*this);
}
} }
jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) { jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) {
@ -47,6 +60,9 @@ void jus::FutureBase::setAnswer(const ejson::Object& _returnValue) {
} }
m_data->m_returnData = _returnValue; m_data->m_returnData = _returnValue;
m_data->m_isFinished = true; m_data->m_isFinished = true;
if (m_data->m_callbackFinish != nullptr) {
m_data->m_callbackFinish(*this);
}
} }
uint64_t jus::FutureBase::getTransactionId() { uint64_t jus::FutureBase::getTransactionId() {

View File

@ -14,8 +14,8 @@ namespace jus {
public: public:
FutureBase(const jus::FutureBase& _base); FutureBase(const jus::FutureBase& _base);
FutureBase(); FutureBase();
FutureBase(uint64_t _transactionId); FutureBase(uint64_t _transactionId, jus::FutureData::ObserverFinish _callback=nullptr);
FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData); FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData, jus::FutureData::ObserverFinish _callback=nullptr);
jus::FutureBase operator= (const jus::FutureBase& _base); jus::FutureBase operator= (const jus::FutureBase& _base);
void setAnswer(const ejson::Object& _returnValue); void setAnswer(const ejson::Object& _returnValue);
uint64_t getTransactionId(); uint64_t getTransactionId();
@ -27,6 +27,7 @@ namespace jus {
void wait(); void wait();
bool waitFor(std::chrono::microseconds _delta); bool waitFor(std::chrono::microseconds _delta);
bool waitUntil(std::chrono::steady_clock::time_point _endTime); bool waitUntil(std::chrono::steady_clock::time_point _endTime);
ejson::Object getRaw();
}; };
} }

View File

@ -9,11 +9,15 @@
#include <ejson/ejson.h> #include <ejson/ejson.h>
namespace jus { namespace jus {
class FutureBase;
class FutureData { class FutureData {
public:
using ObserverFinish = std::function<void(jus::FutureBase)>; //!< Define an Observer: function pointer
public: public:
uint64_t m_transactionId; uint64_t m_transactionId;
bool m_isFinished; bool m_isFinished;
ejson::Object m_returnData; ejson::Object m_returnData;
ObserverFinish m_callbackFinish;
}; };
} }

View File

@ -117,6 +117,18 @@ ememory::SharedPtr<jus::GateWayService> jus::GateWay::get(const std::string& _se
return nullptr; return nullptr;
} }
std::vector<std::string> jus::GateWay::getAllServiceName() {
std::vector<std::string> out;
for (auto &it : m_serviceList) {
if (it == nullptr) {
continue;
}
out.push_back(it->getName());
}
return out;
}
void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) { void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) {
for (auto &it : m_clientList) { for (auto &it : m_clientList) {
if (it == nullptr) { if (it == nullptr) {

View File

@ -32,6 +32,7 @@ namespace jus {
void start(); void start();
void stop(); void stop();
ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName); ememory::SharedPtr<jus::GateWayService> get(const std::string& _serviceName);
std::vector<std::string> getAllServiceName();
void answer(uint64_t _userSessionId, ejson::Object _data); void answer(uint64_t _userSessionId, ejson::Object _data);
void newService(enet::Tcp _connection); void newService(enet::Tcp _connection);
void newClient(enet::Tcp _connection); void newClient(enet::Tcp _connection);

View File

@ -16,7 +16,7 @@ jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayI
m_state(jus::GateWayClient::state::unconnect), m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface), m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)), m_interfaceClient(std::move(_connection)),
m_transactionLocalId(-1) { m_transactionLocalId(1) {
JUS_INFO("----------------"); JUS_INFO("----------------");
JUS_INFO("-- NEW Client --"); JUS_INFO("-- NEW Client --");
JUS_INFO("----------------"); JUS_INFO("----------------");
@ -131,73 +131,89 @@ void jus::GateWayClient::onClientData(std::string _value) {
} }
case jus::GateWayClient::state::userIdentify: case jus::GateWayClient::state::userIdentify:
{ {
std::string call = data["call"].toString().get(); std::string callFunction = data["call"].toString().get();
if (call == "identify") { m_clientServices.clear();
m_clientgroups.clear();
m_clientName.clear();
if ( callFunction != "identify"
&& callFunction != "auth"
&& callFunction != "anonymous") {
protocolError("Client must call: identify/auth/anonymous");
return;
}
if (callFunction == "identify") {
std::string clientName = data["param"].toArray()[0].toString().get(); std::string clientName = data["param"].toArray()[0].toString().get();
std::string clientTocken = data["param"].toArray()[1].toString().get(); std::string clientTocken = data["param"].toArray()[1].toString().get();
ejson::Object gwCall; if (m_userService == nullptr) {
int32_t tmpID = m_transactionLocalId--;
gwCall.add("id", ejson::Number(tmpID));
gwCall.add("call", ejson::String("checkTocken"));
ejson::Array gwParam;
gwParam.add(ejson::String(clientName));
gwParam.add(ejson::String(clientTocken));
gwCall.add("param", gwParam);
{
std::unique_lock<std::mutex> lock(m_mutex);
m_actions.push_back(std::make_pair(tmpID,
[=](ejson::Object& _data) {
JUS_ERROR(" ==> Tocken ckeck return ...");
if (_data["return"].toBoolean().get() == true) {
m_clientName = clientName;
m_clientgroups.clear();
ejson::Object gwCall;
int32_t tmpID = m_transactionLocalId--;
gwCall.add("id", ejson::Number(tmpID));
gwCall.add("call", ejson::String("getGroups"));
ejson::Array gwParam;
gwParam.add(ejson::String(clientName));
gwCall.add("param", gwParam);
{
std::unique_lock<std::mutex> lock(m_mutex);
m_actions.push_back(std::make_pair(tmpID,
[=](ejson::Object& _data) {
JUS_ERROR(" ==> group get return ...");
if (_data["return"].isArray() == false) {
returnBool(transactionId, false);
} else {
m_clientgroups = convertJsonTo<std::vector<std::string>>(_data["return"]);
returnBool(transactionId, true);
}
}));
}
if (m_userService != nullptr) {
m_userService->SendData(m_uid2, gwCall);
} else {
protocolError("gateWay internal error 3");
}
} else {
returnBool(transactionId, false);
}
}));
}
if (m_userService != nullptr) {
m_userService->SendData(m_uid2, gwCall);
} else {
protocolError("gateWay internal error 3"); protocolError("gateWay internal error 3");
return;
} }
return; jus::Future<bool> fut = call(m_uid2, m_userService, "checkTocken", clientName, clientTocken);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("connection refused 1");
return;
} else if (fut.get() == false) {
returnBool(transactionId, false);
protocolError("connection refused 2");
return;
}
m_clientName = clientName;
} }
if (call == "auth") { if (callFunction == "auth") {
std::string password = data["param"].toArray()[0].toString().get(); std::string password = data["param"].toArray()[0].toString().get();
protocolError("Not implemented"); jus::Future<bool> fut = call(m_uid2, m_userService, "auth", password);
fut.wait(); // TODO: Set timeout ...
if (fut.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("connection refused 1");
return;
} else if (fut.get() == false) {
returnBool(transactionId, false);
protocolError("connection refused 2");
return;
}
m_clientName = m_userConnectionName;
}
if (callFunction == "anonymous") {
m_clientName = "";
}
// --------------------------------
// -- Get groups:
// --------------------------------
jus::Future<std::vector<std::string>> futGroup = call(m_uid2, m_userService, "getGroups", m_clientName);
futGroup.wait(); // TODO: Set timeout ...
if (futGroup.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("grouping error");
return; return;
} }
if (call == "anonymous") { m_clientgroups = futGroup.get();
protocolError("Not implemented"); // --------------------------------
// -- Get services:
// --------------------------------
std::vector<std::string> currentServices = m_gatewayInterface->getAllServiceName();
jus::Future<std::vector<std::string>> futServices = call(m_uid2, m_userService, "filterServices", m_clientName, currentServices);
futServices.wait(); // TODO: Set timeout ...
if (futServices.hasError() == true) {
JUS_ERROR("Get error from the service ...");
returnBool(transactionId, false);
protocolError("service filtering error");
return; return;
} }
protocolError("Client must call: identify/auth/anonymous"); m_clientServices = futServices.get();
JUS_WARNING("Connection of: '" << m_clientName << "' to '" << m_userConnectionName << "'");
JUS_WARNING(" groups: " << etk::to_string(m_clientgroups));
JUS_WARNING(" services: " << etk::to_string(m_clientServices));
returnBool(transactionId, true);
m_state = jus::GateWayClient::state::clientIdentify;
return; return;
} }
break; break;
@ -206,18 +222,18 @@ void jus::GateWayClient::onClientData(std::string _value) {
std::string service = data["service"].toString().get(); std::string service = data["service"].toString().get();
// Thsi is 2 default service for the cient interface that manage the authorisation of view: // Thsi is 2 default service for the cient interface that manage the authorisation of view:
if (service == "") { if (service == "") {
std::string call = data["call"].toString().get(); std::string callFunction = data["call"].toString().get();
ejson::Object answer; ejson::Object answer;
//answer.add("from-service", ejson::String("")); //answer.add("from-service", ejson::String(""));
answer.add("id", data["id"]); answer.add("id", data["id"]);
if (call == "getServiceCount") { if (callFunction == "getServiceCount") {
// TODO : Do it better: // TODO : Do it better:
answer.add("return", ejson::Number(2)); answer.add("return", ejson::Number(2));
JUS_DEBUG("answer: " << answer.generateHumanString()); JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (call == "getServiceList") { if (callFunction == "getServiceList") {
ejson::Array listService; ejson::Array listService;
listService.add(ejson::String("ServiceManager/v0.1.0")); listService.add(ejson::String("ServiceManager/v0.1.0"));
listService.add(ejson::String("getServiceInformation/v0.1.0")); listService.add(ejson::String("getServiceInformation/v0.1.0"));
@ -226,7 +242,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (call == "link") { if (callFunction == "link") {
// first param: // first param:
std::string serviceName = data["param"].toArray()[0].toString().get(); std::string serviceName = data["param"].toArray()[0].toString().get();
// Check if service already link: // Check if service already link:
@ -265,7 +281,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
if (call == "unlink") { if (callFunction == "unlink") {
// first param: // first param:
std::string serviceName = data["param"].toArray()[0].toString().get(); std::string serviceName = data["param"].toArray()[0].toString().get();
// Check if service already link: // Check if service already link:
@ -294,7 +310,7 @@ void jus::GateWayClient::onClientData(std::string _value) {
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
return; return;
} }
JUS_ERROR("Function does not exist ... '" << call << "'"); JUS_ERROR("Function does not exist ... '" << callFunction << "'");
answer.add("error", ejson::String("CALL-UNEXISTING")); answer.add("error", ejson::String("CALL-UNEXISTING"));
JUS_DEBUG("answer: " << answer.generateHumanString()); JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
@ -323,8 +339,19 @@ void jus::GateWayClient::onClientData(std::string _value) {
m_interfaceClient.write(answer.generateMachineString()); m_interfaceClient.write(answer.generateMachineString());
} else { } else {
JUS_ERROR("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"); //data.remove("service");
{ //transactionId
callActionForward(m_uid,
*it,
data["call"].toString().get(),
data["param"].toArray(),
[=](jus::FutureBase _ret) {
ejson::Object tmpp = _ret.getRaw();
tmpp["id"] = data["id"];
JUS_DEBUG(" ==> transmit");
m_interfaceClient.write(tmpp.generateMachineString());
});
/*
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
m_actions.push_back(std::make_pair(transactionId, m_actions.push_back(std::make_pair(transactionId,
[=](ejson::Object& _data) { [=](ejson::Object& _data) {
@ -333,41 +360,82 @@ void jus::GateWayClient::onClientData(std::string _value) {
})); }));
} }
(*it)->SendData(m_uid, data); (*it)->SendData(m_uid, data);
*/
} }
} }
} }
} }
void jus::GateWayClient::returnMessage(ejson::Object _data) { jus::FutureBase jus::GateWayClient::callActionForward(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback) {
JUS_DEBUG("answer: " << _data.generateHumanString()); uint64_t id = getId();
int32_t id = _data["id"].toNumber().get(); ejson::Object callElem = jus::createCallJson(id, _functionName, _params);
if (id == 0) { return callJson(_callerId, _srv, id, callElem, _callback);
JUS_ERROR("gateway reject transaction ... ==> No 'id' or 'id' == 0"); }
return;
uint64_t jus::GateWayClient::getId() {
return m_transactionLocalId++;
}
jus::FutureBase jus::GateWayClient::callJson(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) {
JUS_VERBOSE("Send JSON [START] ");
if (_srv == nullptr) {
ejson::Object obj;
obj.add("error", ejson::String("NOT-CONNECTED"));
obj.add("error-help", ejson::String("Client interface not connected (no TCP)"));
return jus::FutureBase(_transactionId, true, obj, _callback);
} }
jus::GateWayClient::Observer obs; jus::FutureBase tmpFuture(_transactionId, _callback);
ejson::Object localData;
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_actions.begin(); m_pendingCall.push_back(tmpFuture);
while (it != m_actions.end()) { }
if (it->first != id) { _srv->SendData(_callerId, _obj);
JUS_VERBOSE("Send JSON [STOP]");
return tmpFuture;
}
void jus::GateWayClient::returnMessage(ejson::Object _data) {
jus::FutureBase future;
{
uint64_t tid = _data["id"].toNumber().get();
if (tid == 0) {
if (_data["error"].toString().get() == "PROTOCOL-ERROR") {
JUS_ERROR("Get a Protocol error ...");
std::unique_lock<std::mutex> lock(m_mutex);
for (auto &it : m_pendingCall) {
if (it.isValid() == false) {
continue;
}
it.setAnswer(_data);
}
m_pendingCall.clear();
} else {
JUS_ERROR("call with no ID ==> error ...");
}
return;
}
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_pendingCall.begin();
while (it != m_pendingCall.end()) {
if (it->isValid() == false) {
it = m_pendingCall.erase(it);
continue;
}
if (it->getTransactionId() != tid) {
++it; ++it;
continue; continue;
} }
obs = (*it).second; future = *it;
m_actions.erase(it); it = m_pendingCall.erase(it);
break; break;
} }
if (obs == nullptr) {
JUS_ERROR("gateway reject transaction ... (not find answer)" << _data.generateHumanString());
return;
}
} }
obs(_data); if (future.isValid() == false) {
if (id >= 0) {
m_interfaceClient.write(_data.generateMachineString());
} else {
JUS_WARNING("Action to do ..."); JUS_WARNING("Action to do ...");
return;
} }
} future.setAnswer(_data);
}

View File

@ -9,6 +9,8 @@
#include <ememory/memory.h> #include <ememory/memory.h>
#include <esignal/Signal.h> #include <esignal/Signal.h>
#include <jus/GateWayService.h> #include <jus/GateWayService.h>
#include <jus/Future.h>
#include <jus/AbstractFunction.h>
@ -16,7 +18,6 @@ namespace jus {
class GateWay; class GateWay;
class GateWayClient { class GateWayClient {
private: private:
using Observer = std::function<void(ejson::Object& _data)>;
enum class state { enum class state {
unconnect, // starting sate unconnect, // starting sate
connect, // just get a TCP connection connect, // just get a TCP connection
@ -39,9 +40,7 @@ namespace jus {
std::string m_userConnectionName; std::string m_userConnectionName;
std::string m_clientName; std::string m_clientName;
std::vector<std::string> m_clientgroups; std::vector<std::string> m_clientgroups;
std::mutex m_mutex; std::vector<std::string> m_clientServices;
std::vector<std::pair<int32_t, Observer>> m_actions;
int32_t m_transactionLocalId;
public: public:
GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface); GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface);
virtual ~GateWayClient(); virtual ~GateWayClient();
@ -54,6 +53,28 @@ namespace jus {
|| m_uid2 == _id; || m_uid2 == _id;
} }
bool isAlive(); bool isAlive();
private:
std::mutex m_mutex;
std::vector<jus::FutureBase> m_pendingCall;
int32_t m_transactionLocalId;
jus::FutureBase callJson(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr);
uint64_t getId();
public:
template<class... _ARGS>
jus::FutureBase call(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, _ARGS&&... _args) {
uint64_t id = getId();
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(_callerId, _srv, id, callElem);
}
template<class... _ARGS>
jus::FutureBase callAction(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(_callerId, _srv, id, callElem, _callback);
}
jus::FutureBase callActionForward(uint64_t _callerId, ememory::SharedPtr<jus::GateWayService> _srv, const std::string& _functionName, ejson::Array _params, jus::FutureData::ObserverFinish _callback);
}; };
} }

View File

@ -38,8 +38,8 @@ void jus::GateWayService::stop() {
m_interfaceClient.disconnect(); m_interfaceClient.disconnect();
} }
void jus::GateWayService::SendData(int32_t _userSessionId, ejson::Object _data) { void jus::GateWayService::SendData(uint64_t _userSessionId, ejson::Object _data) {
_data.add("client-id", ejson::String(etk::to_string(_userSessionId))); _data.add("client-id", ejson::Number(_userSessionId));
JUS_DEBUG("Send Service: " << _data.generateHumanString()); JUS_DEBUG("Send Service: " << _data.generateHumanString());
m_interfaceClient.write(_data.generateMachineString()); m_interfaceClient.write(_data.generateMachineString());
} }
@ -76,7 +76,7 @@ void jus::GateWayService::onServiceData(std::string _value) {
JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'"); JUS_ERROR("Service interface ==> wrong service answer ==> missing 'client-id'");
return; return;
} }
uint64_t userSessionId = etk::string_to_uint64_t(data["client-id"].toString().get()); uint64_t userSessionId = data["client-id"].toNumber().getU64();
data.remove("client-id"); data.remove("client-id");
data.remove("action"); data.remove("action");
m_gatewayInterface->answer(userSessionId, data); m_gatewayInterface->answer(userSessionId, data);

View File

@ -26,7 +26,7 @@ namespace jus {
void stop(); void stop();
void onServiceData(std::string _value); void onServiceData(std::string _value);
public: public:
void SendData(int32_t _userSessionId, ejson::Object _data); void SendData(uint64_t _userSessionId, ejson::Object _data);
const std::string& getName() { const std::string& getName() {
return m_name; return m_name;
} }

View File

@ -84,11 +84,11 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) {
// Gateway just aswer a keep alive information ... // Gateway just aswer a keep alive information ...
// Nothing to do ... // Nothing to do ...
} else if (event == "new") { } else if (event == "new") {
uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); uint64_t clientId = _obj["client-id"].toNumber().getU64();
std::string userName = _obj["user"].toString().get(); std::string userName = _obj["user"].toString().get();
clientConnect(clientId, userName); clientConnect(clientId, userName);
} else if (event == "delete") { } else if (event == "delete") {
uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); uint64_t clientId = _obj["client-id"].toNumber().getU64();
clientDisconnect(clientId); clientDisconnect(clientId);
} else { } else {
JUS_ERROR("Unknow event: '" << event << "'"); JUS_ERROR("Unknow event: '" << event << "'");
@ -96,9 +96,9 @@ ejson::Value jus::Service::callJson(const ejson::Object& _obj) {
return ejson::Null(); return ejson::Null();
} }
if (_obj.valueExist("call") == true) { if (_obj.valueExist("call") == true) {
uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get()); uint64_t clientId = _obj["client-id"].toNumber().getU64();
ejson::Object tmpp = callJson2(clientId, _obj); ejson::Object tmpp = callJson2(clientId, _obj);
tmpp.add("client-id", ejson::String(etk::to_string(clientId))); tmpp.add("client-id", ejson::Number(clientId));
return tmpp; return tmpp;
} }
ejson::Object tmpp; ejson::Object tmpp;

View File

@ -28,7 +28,7 @@ uint64_t jus::ServiceRemote::getId() {
return m_clientInterface->getId(); return m_clientInterface->getId();
} }
jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj) { jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback) {
return m_clientInterface->callJson(_transactionId, _obj); return m_clientInterface->callJson(_transactionId, _obj, _callback);
} }

View File

@ -25,7 +25,7 @@ namespace jus {
~ServiceRemote(); ~ServiceRemote();
bool exist(); bool exist();
private: private:
jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj, jus::FutureData::ObserverFinish _callback=nullptr);
uint64_t getId(); uint64_t getId();
public: public:
template<class... _ARGS> template<class... _ARGS>
@ -34,6 +34,12 @@ namespace jus {
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem); return callJson(id, callElem);
} }
template<class... _ARGS>
jus::FutureBase callAction(const std::string& _functionName, _ARGS&&... _args, jus::FutureData::ObserverFinish _callback) {
uint64_t id = getId();
ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...);
return callJson(id, callElem, _callback);
}
}; };
} }

View File

@ -54,6 +54,9 @@ namespace appl {
// No specificity for this client (in case it have no special right) // No specificity for this client (in case it have no special right)
return out; return out;
} }
if (client["tocken"].toString().get() != "") {
out.push_back("connected");
}
// TODO: check banishing ... // TODO: check banishing ...
ejson::Array groups = client["group"].toArray(); ejson::Array groups = client["group"].toArray();
for (auto it : groups) { for (auto it : groups) {
@ -81,6 +84,24 @@ namespace appl {
} }
return false; return false;
} }
bool checkAuth(const std::string& _password) {
std::unique_lock<std::mutex> lock(m_mutex);
std::string pass = m_database["password"].toString().get();
if (pass == "") {
// pb password
return false;
}
if (pass == _password) {
return true;
}
return false;
}
std::vector<std::string> filterServices(const std::string& _clientName, std::vector<std::string> _inputList) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
// TODO: ...
return out;
}
}; };
class UserManager { class UserManager {
@ -137,41 +158,29 @@ namespace appl {
} }
return out; return out;
} }
std::vector<std::string> getServices(std::string _clientName) {
std::vector<std::string> out;
if (m_user == nullptr) {
return out;
}
if (_clientName == m_user->getName()) {
out.push_back(SERVICE_NAME);
}
return out;
}
bool checkTocken(std::string _clientName, std::string _tocken) { bool checkTocken(std::string _clientName, std::string _tocken) {
return m_user->checkTocken(_clientName, _tocken); return m_user->checkTocken(_clientName, _tocken);
} }
bool checkAuth(std::string _password) {
return m_user->checkAuth(_password);
}
std::vector<std::string> filterServices(std::string _clientName, std::vector<std::string> _currentList) {
return m_user->filterServices(_clientName, _currentList);
}
}; };
} }
int main(int _argc, const char *_argv[]) { int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv); etk::init(_argc, _argv);
appl::UserManager userMng; std::string ip;
jus::ServiceType<appl::SystemService, appl::UserManager> serviceInterface(userMng); uint16_t port = 0;
serviceInterface.setDescription("user interface management");
serviceInterface.setVersion("0.1.0");
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("getGroups", &appl::SystemService::getGroups);
serviceInterface.setLastFuncDesc("Get list of group availlable for a client name");
serviceInterface.addLastFuncParam("clientName", "Name of the client");
serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken);
serviceInterface.advertise("getServices", &appl::SystemService::getServices);
for (int32_t iii=0; iii<_argc ; ++iii) { for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii]; std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) { if (etk::start_with(data, "--ip=") == true) {
serviceInterface.propertyIp.set(std::string(&data[5])); ip = std::string(&data[5]);
} else if (etk::start_with(data, "--port=") == true) { } else if (etk::start_with(data, "--port=") == true) {
serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7]))); port = etk::string_to_uint16_t(std::string(&data[7]));
} else if ( data == "-h" } else if ( data == "-h"
|| data == "--help") { || data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : "); APPL_PRINT(etk::getApplicationName() << " - help : ");
@ -183,7 +192,35 @@ int main(int _argc, const char *_argv[]) {
} }
while (true) { while (true) {
APPL_INFO("==========================================================="); APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [START]"); APPL_INFO("== JUS instanciate service: " << SERVICE_NAME << " [START]");
APPL_INFO("===========================================================");
appl::UserManager userMng;
jus::ServiceType<appl::SystemService, appl::UserManager> serviceInterface(userMng);
if (ip != "") {
serviceInterface.propertyIp.set(ip);
}
if (port != 0) {
serviceInterface.propertyPort.set(port);
}
serviceInterface.setDescription("user interface management");
serviceInterface.setVersion("0.1.0");
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken);
serviceInterface.setLastFuncDesc("Check if a user tocken is correct or not");
serviceInterface.addLastFuncParam("clientName", "Name of the client");
serviceInterface.addLastFuncParam("tocken", "String containing the Tocken");
serviceInterface.advertise("checkAuth", &appl::SystemService::checkAuth);
serviceInterface.setLastFuncDesc("Check the password of the curent user");
serviceInterface.addLastFuncParam("password", "client/user password");
serviceInterface.advertise("getGroups", &appl::SystemService::getGroups);
serviceInterface.setLastFuncDesc("Get list of group availlable for a client name");
serviceInterface.addLastFuncParam("clientName", "Name of the client");
serviceInterface.advertise("filterServices", &appl::SystemService::filterServices);
serviceInterface.setLastFuncDesc("Filter a list of service with the cuurent profile of the user (restrict area)");
serviceInterface.addLastFuncParam("clientName", "Name of the client");
serviceInterface.addLastFuncParam("currentList", "Vector of name of the services");
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [service instanciate]");
APPL_INFO("==========================================================="); APPL_INFO("===========================================================");
serviceInterface.connect(SERVICE_NAME); serviceInterface.connect(SERVICE_NAME);
if (serviceInterface.GateWayAlive() == false) { if (serviceInterface.GateWayAlive() == false) {