[DEV] better interfacing

This commit is contained in:
Edouard DUPIN 2016-05-25 21:25:33 +02:00
parent 1891295eff
commit 5028352541
23 changed files with 566 additions and 241 deletions

View File

@ -9,6 +9,13 @@ namespace jus {
template<> bool convertJsonTo<bool>(const ejson::Value& _value) {
return _value.toBoolean().get();
}
template<> std::vector<bool> convertJsonTo<std::vector<bool>>(const ejson::Value& _value) {
std::vector<bool> out;
for (const auto it : _value.toArray()) {
out.push_back(convertJsonTo<bool>(it));
}
return out;
}
template<> float convertJsonTo<float>(const ejson::Value& _value) {
return _value.toNumber().get();
}
@ -19,7 +26,6 @@ namespace jus {
return int64_t(_value.toNumber().get());
}
template<> int32_t convertJsonTo<int32_t>(const ejson::Value& _value) {
//_value.display();
return int32_t(_value.toNumber().get());
}
template<> int16_t convertJsonTo<int16_t>(const ejson::Value& _value) {
@ -41,13 +47,26 @@ namespace jus {
return uint8_t(_value.toNumber().get());
}
template<> std::string convertJsonTo<std::string>(const ejson::Value& _value) {
//_value.display();
return _value.toString().get();
}
template<> std::vector<std::string> convertJsonTo<std::vector<std::string>>(const ejson::Value& _value) {
std::vector<std::string> out;
for (const auto it : _value.toArray()) {
out.push_back(convertJsonTo<std::string>(it));
}
return out;
}
template<> ejson::Value convertToJson<bool>(const bool& _value) {
return ejson::Boolean(_value);
}
template<> ejson::Value convertToJson<std::vector<bool>>(const std::vector<bool>& _value) {
ejson::Array out;
for (const auto &it : _value) {
out.add(ejson::Boolean(it));
}
return out;
}
template<> ejson::Value convertToJson<float>(const float& _value) {
return ejson::Number(_value);
}
@ -81,6 +100,13 @@ namespace jus {
template<> ejson::Value convertToJson<std::string>(const std::string& _value) {
return ejson::String(_value);
}
template<> ejson::Value convertToJson<std::vector<std::string>>(const std::vector<std::string>& _value) {
ejson::Array out;
for (auto &it : _value) {
out.add(ejson::String(it));
}
return out;
}
template<> bool convertStringTo<bool>(const std::string& _value) {
return etk::string_to_bool(_value);
@ -118,6 +144,12 @@ namespace jus {
template<> std::string convertStringTo<std::string>(const std::string& _value) {
return _value;
}
template<> std::vector<std::string> convertStringTo<std::vector<std::string>>(const std::string& _value) {
std::vector<std::string> out;
JUS_TODO("Convert string to vs");
return out;
}
}
const std::string& jus::AbstractFunction::getName() const {

View File

@ -13,7 +13,7 @@
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_id(1) {
m_interfaceClient.connect(this, &jus::Client::onClientData);
}
@ -29,12 +29,13 @@ jus::ServiceRemote jus::Client::getService(const std::string& _name) {
return jus::ServiceRemote(this, _name);
}
void jus::Client::link(const std::string& _serviceName) {
bool 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 << "'");
}
return ret;
}
void jus::Client::unlink(const std::string& _serviceName) {

View File

@ -28,8 +28,13 @@ namespace jus {
void disconnect();
public:
jus::ServiceRemote getService(const std::string& _serviceName);
void link(const std::string& _serviceName);
bool link(const std::string& _serviceName);
void unlink(const std::string& _serviceName);
// Connect that is not us
//bool identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
// Connect to ourself:
//client1.authentificate("coucou");
private:
void onClientData(std::string _value);
std::string asyncRead();

View File

@ -122,7 +122,7 @@ void jus::GateWay::answer(uint64_t _userSessionId, ejson::Object _data) {
if (it == nullptr) {
continue;
}
if (it->getId() != _userSessionId) {
if (it->getId() != std::abs(_userSessionId)) {
continue;
}
it->returnMessage(_data);

View File

@ -12,7 +12,8 @@
jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)) {
m_interfaceClient(std::move(_connection)),
m_transactionLocalId(-1) {
JUS_INFO("----------------");
JUS_INFO("-- NEW Client --");
JUS_INFO("----------------");
@ -38,7 +39,15 @@ void jus::GateWayClient::stop() {
if (it == nullptr) {
continue;
}
it->SendData(m_uid, ejson::Object(), "delete");
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
it->SendData(m_uid, linkService);
}
if (m_userService != nullptr) {
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
m_userService->SendData(-m_uid, linkService);
m_userService = nullptr;
}
m_listConnectedService.clear();
m_interfaceClient.disconnect();
@ -51,10 +60,18 @@ bool jus::GateWayClient::isAlive() {
void jus::GateWayClient::onClientData(std::string _value) {
JUS_DEBUG("On data: " << _value);
ejson::Object data(_value);
int32_t transactionId = data["id"].toNumber().get();
if (m_userConnectionName == "") {
if (data.valueExist("connect-to-user") == true) {
m_userConnectionName = data["connect-to-user"].toString().get();
JUS_WARNING("[" << m_uid << "] Set client connect to user : '" << m_userConnectionName << "'");
m_userService = m_gatewayInterface->get("system-user");
ejson::Object linkService;
linkService.add("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
m_userService->SendData(-m_uid, linkService);
// TODO : Return something ...
return;
}
@ -62,30 +79,74 @@ void jus::GateWayClient::onClientData(std::string _value) {
// TODO : Return something ...
return;
}
if (data.valueExist("service") == false) {
// add default service
data.add("service", ejson::String("ServiceManager"));
JUS_WARNING("missing service name ==> set it by default at ServiceManager");
}
std::string service = data["service"].toString().get();
// Thsi is 2 default service for the cient interface that manage the authorisation of view:
if (service == "ServiceManager") {
if (service == "") {
std::string call = data["call"].toString().get();
ejson::Object answer;
answer.add("from-service", ejson::String("ServiceManager"));
//answer.add("from-service", ejson::String(""));
answer.add("id", data["id"]);
if (call == "getServiceCount") {
// TODO : Do it better:
answer.add("return", ejson::Number(2));
} else if (call == "getServiceList") {
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
}
if (call == "getServiceList") {
ejson::Array listService;
listService.add(ejson::String("ServiceManager/v0.1.0"));
listService.add(ejson::String("getServiceInformation/v0.1.0"));
answer.add("return", listService);
} else if (call == "getServiceInformation") {
} else if (call == "link") {
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
}
if (call == "identify") {
// Identify Client has an extern user ...
std::string clientName = data["param"].toArray()[0].toString().get();
std::string clientTocken = data["param"].toArray()[1].toString().get();
ejson::Object gwCall;
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) {
ejson::Object tmpAnswer;
tmpAnswer.add("id", ejson::Number(transactionId));
JUS_ERROR(" ==> Tocken ckeck return ...");
if (_data["return"].toBoolean().get() == true) {
m_clientName = clientName;
m_clientgroups.clear();
// TODO : Update all service name and group ...
tmpAnswer.add("return", ejson::Boolean(true));
} else {
tmpAnswer.add("return", ejson::Boolean(false));
}
JUS_DEBUG("answer: " << tmpAnswer.generateHumanString());
m_interfaceClient.write(tmpAnswer.generateMachineString());
}));
}
if (m_userService != nullptr) {
m_userService->SendData(-m_uid, gwCall);
} else {
// TODO ...
}
return;
}
if (call == "authentify") {
// Identify Client has an local user ... (connection to is the same ...)
std::string password = data["param"].toArray()[0].toString().get();
// TODO: ...
return;
}
if (call == "link") {
// first param:
std::string serviceName = data["param"].toArray()[0].toString().get();
// Check if service already link:
@ -106,8 +167,9 @@ void jus::GateWayClient::onClientData(std::string _value) {
ememory::SharedPtr<jus::GateWayService> srv = m_gatewayInterface->get(serviceName);
if (srv != nullptr) {
ejson::Object linkService;
linkService.add("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
srv->SendData(m_uid, linkService, "new");
srv->SendData(m_uid, linkService);
m_listConnectedService.push_back(srv);
answer.add("return", ejson::Boolean(true));
} else {
@ -117,7 +179,11 @@ void jus::GateWayClient::onClientData(std::string _value) {
// TODO : Service already connected;
answer.add("return", ejson::Boolean(false));
}
} else if (call == "unlink") {
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
}
if (call == "unlink") {
// first param:
std::string serviceName = data["param"].toArray()[0].toString().get();
// Check if service already link:
@ -136,50 +202,88 @@ void jus::GateWayClient::onClientData(std::string _value) {
if (it == m_listConnectedService.end()) {
answer.add("return", ejson::Boolean(false));
} else {
(*it)->SendData(m_uid, ejson::Object(), "delete");
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
(*it)->SendData(m_uid, linkService);
m_listConnectedService.erase(it);
answer.add("return", ejson::Boolean(true));
}
} else {
JUS_ERROR("Function does not exist ... '" << call << "'");
answer.add("error", ejson::String("CALL-UNEXISTING"));
}
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else if (service == "Authentification") {
std::string call = data["call"].toString().get();
} else {
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == nullptr) {
++it;
continue;
}
if ((*it)->getName() != service) {
++it;
continue;
}
break;
}
if (it == m_listConnectedService.end()) {
// TODO : Generate an ERROR...
ejson::Object answer;
answer.add("from-service", ejson::String("ServiceManager"));
answer.add("id", data["id"]);
JUS_ERROR("Service not linked ... " << service);
answer.add("error", ejson::String("SERVICE-NOT-LINK"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else {
JUS_ERROR("Add in link the name of the user in parameter ...");
data.remove("service");
(*it)->SendData(m_uid, data);
return;
}
JUS_ERROR("Function does not exist ... '" << call << "'");
answer.add("error", ejson::String("CALL-UNEXISTING"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
}
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == nullptr) {
++it;
continue;
}
if ((*it)->getName() != service) {
++it;
continue;
}
break;
}
if (it == m_listConnectedService.end()) {
// TODO : Generate an ERROR...
ejson::Object answer;
answer.add("from-service", ejson::String("ServiceManager"));
answer.add("id", data["id"]);
JUS_ERROR("Service not linked ... " << service);
answer.add("error", ejson::String("SERVICE-NOT-LINK"));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
} else {
JUS_ERROR("Add in link the name of the user in parameter ...");
data.remove("service");
{
std::unique_lock<std::mutex> lock(m_mutex);
m_actions.push_back(std::make_pair(transactionId,
[=](ejson::Object& _data) {
JUS_DEBUG(" ==> transmit");
m_interfaceClient.write(_data.generateMachineString());
}));
}
(*it)->SendData(m_uid, data);
}
}
void jus::GateWayClient::returnMessage(ejson::Object _data) {
JUS_DEBUG("answer: " << _data.generateHumanString());
m_interfaceClient.write(_data.generateMachineString());
int32_t id = _data["id"].toNumber().get();
if (id == 0) {
JUS_ERROR("gateway reject transaction ... ==> No 'id' or 'id' == 0");
return;
}
jus::GateWayClient::Observer obs;
ejson::Object localData;
{
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_actions.begin();
while (it != m_actions.end()) {
if (it->first != id) {
++it;
continue;
}
obs = (*it).second;
m_actions.erase(it);
break;
}
if (obs == nullptr) {
JUS_ERROR("gateway reject transaction ... (not find answer)" << _data.generateHumanString());
return;
}
}
obs(_data);
if (id >= 0) {
m_interfaceClient.write(_data.generateMachineString());
} else {
JUS_WARNING("Action to do ...");
}
}

View File

@ -10,17 +10,26 @@
#include <esignal/Signal.h>
#include <jus/GateWayService.h>
namespace jus {
class GateWay;
class GateWayClient {
using Observer = std::function<void(ejson::Object& _data)>;
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
public:
esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService;
std::vector<ememory::SharedPtr<jus::GateWayService>> m_listConnectedService;
size_t m_uid;
std::string m_userConnectionName;
std::string m_clientName;
std::vector<std::string> m_clientgroups;
std::mutex m_mutex;
std::vector<std::pair<int32_t, Observer>> m_actions;
int32_t m_transactionLocalId;
public:
GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface);
virtual ~GateWayClient();

View File

@ -38,9 +38,8 @@ void jus::GateWayService::stop() {
m_interfaceClient.disconnect();
}
void jus::GateWayService::SendData(size_t _userSessionId, ejson::Object _data, const std::string& _action) {
void jus::GateWayService::SendData(int32_t _userSessionId, ejson::Object _data) {
_data.add("client-id", ejson::String(etk::to_string(_userSessionId)));
_data.add("action", ejson::String(_action));
JUS_DEBUG("Send Service: " << _data.generateHumanString());
m_interfaceClient.write(_data.generateMachineString());
}
@ -48,9 +47,14 @@ void jus::GateWayService::SendData(size_t _userSessionId, ejson::Object _data, c
void jus::GateWayService::onServiceData(std::string _value) {
JUS_DEBUG("On service data: " << _value);
ejson::Object data(_value);
data.add("from-service", ejson::String(m_name));
if (data.valueExist("event") == true) {
// No need to have a user ID ...
if (data["event"].toString().get() == "IS-ALIVE") {
JUS_INFO("Service Alive ...");
JUS_VERBOSE("Service Alive ...");
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(20)) {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}");
}
} else {
JUS_INFO("Unknow service event: '" << data["event"].toString().get() << "'");
}

View File

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

View File

@ -43,3 +43,16 @@ generate_basic_type(uint16_t, "uint16");
generate_basic_type(uint8_t, "uint8");
generate_basic_type(std::string, "string");
generate_basic_type(std::vector<bool>, "vector:bool");
generate_basic_type(std::vector<float>, "vector:float");
generate_basic_type(std::vector<double>, "vector:double");
generate_basic_type(std::vector<int64_t>, "vector:int64");
generate_basic_type(std::vector<int32_t>, "vector:int32");
generate_basic_type(std::vector<int16_t>, "vector:int16");
generate_basic_type(std::vector<int8_t>, "vector:int8");
generate_basic_type(std::vector<uint64_t>, "vector:uint64");
generate_basic_type(std::vector<uint32_t>, "vector:uint32");
generate_basic_type(std::vector<uint16_t>, "vector:uint16");
generate_basic_type(std::vector<uint8_t>, "vector:uint8");
generate_basic_type(std::vector<std::string>, "vector:string");

View File

@ -26,10 +26,13 @@ jus::Service::~Service() {
void jus::Service::onClientData(std::string _value) {
ejson::Object request(_value);
ejson::Value tmpID = request["id"];
request.remove("id");
JUS_INFO("Request: " << _value);
ejson::Value answer = callJson(request);
// check if an answer is needed
if (answer.isNull() == false) {
answer.toObject().add("id", tmpID);
JUS_INFO("Answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
}
@ -44,10 +47,14 @@ void jus::Service::onPropertyChangePort(){
}
void jus::Service::connect(const std::string& _serviceName){
void jus::Service::connect(const std::string& _serviceName, uint32_t _numberRetry){
disconnect();
JUS_DEBUG("connect [START]");
enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort));
enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort, _numberRetry));
if (connection.getConnectionStatus() != enet::Tcp::status::link) {
JUS_DEBUG("connect [STOP] ==> can not connect");
return;
}
m_interfaceClient.setInterface(std::move(connection));
m_interfaceClient.connect();
m_interfaceClient.write(std::string("{\"connect-service\":\"") + _serviceName + "\"}");
@ -60,39 +67,36 @@ void jus::Service::disconnect(){
JUS_DEBUG("disconnect [STOP]");
}
bool jus::Service::GateWayAlive() {
return m_interfaceClient.isActive();
}
void jus::Service::pingIsAlive() {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}");
if (std::chrono::steady_clock::now() - m_interfaceClient.getLastTimeSend() >= std::chrono::seconds(30)) {
m_interfaceClient.write("{\"event\":\"IS-ALIVE\"}");
}
}
ejson::Value jus::Service::callJson(const ejson::Object& _obj) {
std::string action = _obj["action"].toString().get();
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
*/
if (_obj.valueExist("event") == true) {
std::string event = _obj["event"].toString().get();
if (event == "IS-ALIVE") {
// Gateway just aswer a keep alive information ...
// Nothing to do ...
} else if (event == "new") {
int64_t clientId = etk::string_to_int64_t(_obj["client-id"].toString().get());
std::string userName = _obj["user"].toString().get();
clientConnect(clientId, userName);
} else if (event == "delete") {
int64_t clientId = etk::string_to_int64_t(_obj["client-id"].toString().get());
clientDisconnect(clientId);
} else {
JUS_ERROR("Unknow event: '" << event << "'");
}
return ejson::Null();
}
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;
*/
return ejson::Null();
}
if ( action == "call"
|| action == "") {
uint64_t clientId = etk::string_to_uint64_t(_obj["client-id"].toString().get());
if (_obj.valueExist("call") == true) {
int64_t clientId = etk::string_to_int64_t(_obj["client-id"].toString().get());
ejson::Object tmpp = callJson2(clientId, _obj);
tmpp.add("client-id", ejson::String(etk::to_string(clientId)));
return tmpp;

View File

@ -13,8 +13,34 @@
#include <jus/debug.h>
#include <jus/RemoteProcessCall.h>
namespace jus {
class ClientProperty {
public:
ClientProperty() {}
private:
std::string m_name;
public:
void setName(const std::string& _name) {
m_name = _name;
}
const std::string& getName() {
return m_name;
}
private:
std::vector<std::string> m_groups;
public:
void setGroups(std::vector<std::string> _groups) {
m_groups = _groups;
}
const std::vector<std::string>& getGroups() {
return m_groups;
}
};
}
namespace jus {
class Service : public eproperty::Interface, public jus::RemoteProcessCall {
protected:
std::mutex m_mutex;
public:
eproperty::Value<std::string> propertyIp;
eproperty::Value<uint16_t> propertyPort;
@ -25,13 +51,14 @@ namespace jus {
public:
Service();
virtual ~Service();
void connect(const std::string& _serviceName);
void connect(const std::string& _serviceName, uint32_t _numberRetry = 1);
void disconnect();
private:
void onClientData(std::string _value);
std::string asyncRead();
public:
void pingIsAlive();
bool GateWayAlive();
private:
void onPropertyChangeIp();
void onPropertyChangePort();
@ -52,7 +79,7 @@ namespace jus {
private:
JUS_USER_ACCESS& m_getUserInterface;
// no need of shared_ptr or unique_ptr (if service die all is lost and is client die, the gateway notify us...)
std::map<size_t, JUS_TYPE_SERVICE*> m_interface;
std::map<int64_t, std::pair<ememory::SharedPtr<ClientProperty>, ememory::SharedPtr<JUS_TYPE_SERVICE>>> m_interface;
public:
template<class JUS_RETURN_VALUE,
@ -78,18 +105,41 @@ namespace jus {
}
void clientConnect(size_t _clientSessionID, const std::string& _userName) {
// TODO : Set a mutex ...
m_interface.insert(std::make_pair(_clientSessionID, new JUS_TYPE_SERVICE(m_getUserInterface.getUser(_userName))));
std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("connect : " << _clientSessionID << " to '" << _userName << "'");
ememory::SharedPtr<ClientProperty> tmpProperty = std::make_shared<ClientProperty>();
ememory::SharedPtr<JUS_TYPE_SERVICE> tmpSrv = std::make_shared<JUS_TYPE_SERVICE>(m_getUserInterface.getUser(_userName), tmpProperty);
m_interface.insert(std::make_pair(_clientSessionID, std::make_pair(tmpProperty, tmpSrv)));
}
void clientDisconnect(size_t _clientSessionID) {
std::unique_lock<std::mutex> lock(m_mutex);
JUS_DEBUG("disconnect: " << _clientSessionID);
auto it = m_interface.find(_clientSessionID);
if (it != m_interface.end()) {
if (it == m_interface.end()) {
JUS_WARNING("disconnect ==> Not find Client ID " << _clientSessionID);
// noting to do ==> user never conected.
return;
}
// TODO : Set a mutex ...
m_interface.erase(it);
}
void clientSetName(size_t _clientSessionID, const std::string& _clientName) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientSessionID);
if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ...");
return;
}
it->second.first->setName(_clientName);
}
void clientSetGroup(size_t _clientSessionID, const std::vector<std::string>& _clientGroups) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_interface.find(_clientSessionID);
if (it == m_interface.end()) {
JUS_ERROR("Change the client property but client was not created ...");
return;
}
it->second.first->setGroups(_clientGroups);
}
ejson::Object callJson2(size_t _clientSessionID, const ejson::Object& _obj) {
ejson::Object out;
auto it = m_interface.find(_clientSessionID);
@ -106,7 +156,7 @@ namespace jus {
if (it2->getName() != call) {
continue;
}
JUS_TYPE_SERVICE* elem = it->second;
JUS_TYPE_SERVICE* elem = it->second.second.get();
return it2->executeJson(param, (void*)elem).toObject();
}
out.add("error", ejson::String("FUNCTION-UNKNOW"));

View File

@ -10,13 +10,19 @@
jus::ServiceRemote::ServiceRemote(jus::Client* _clientInterface, const std::string& _name):
m_clientInterface(_clientInterface),
m_name(_name) {
m_clientInterface->link(_name);
m_isLinked = m_clientInterface->link(_name);
}
jus::ServiceRemote::~ServiceRemote() {
m_clientInterface->unlink(m_name);
if (m_isLinked == true) {
m_clientInterface->unlink(m_name);
m_isLinked = false;
}
}
bool jus::ServiceRemote::exist() {
return m_isLinked;
}
ejson::Object jus::ServiceRemote::createBaseCall(const std::string& _functionName) {
return m_clientInterface->createBaseCall(_functionName, m_name);

View File

@ -17,9 +17,11 @@ namespace jus {
private:
jus::Client* m_clientInterface;
std::string m_name;
bool m_isLinked;
public:
ServiceRemote(jus::Client* _clientInterface, const std::string& _name);
~ServiceRemote();
bool exist();
private:
ejson::Object callJson(const ejson::Object& _obj);
ejson::Object createBaseCall(const std::string& _functionName);

View File

@ -43,6 +43,7 @@ void jus::TcpString::threadCallback() {
std::string data = std::move(read());
JUS_VERBOSE("Receive data: '" << data << "'");
if (data.size() != 0) {
m_lastReceive = std::chrono::steady_clock::now();
if (m_obsercerElement != nullptr) {
m_obsercerElement(std::move(data));
}
@ -106,6 +107,7 @@ int32_t jus::TcpString::write(const std::string& _data) {
return 0;
}
uint32_t size = _data.size();
m_lastSend = std::chrono::steady_clock::now();
m_connection.write(&size, 4);
return m_connection.write(_data.c_str(), _data.size());
}

View File

@ -16,6 +16,8 @@ namespace jus {
enet::Tcp m_connection;
std::thread* m_thread;
bool m_threadRunning;
std::chrono::steady_clock::time_point m_lastReceive;
std::chrono::steady_clock::time_point m_lastSend;
public:
using Observer = std::function<void(std::string)>; //!< Define an Observer: function pointer
Observer m_obsercerElement;
@ -46,6 +48,13 @@ namespace jus {
std::string read();
private:
void threadCallback();
public:
const std::chrono::steady_clock::time_point& getLastTimeReceive() {
return m_lastReceive;
}
const std::chrono::steady_clock::time_point& getLastTimeSend() {
return m_lastSend;
}
};
}

View File

@ -1,4 +1,4 @@
tools/system-gateway
tools/system-service
tools/system-user
test/client
test/service1

View File

@ -33,11 +33,17 @@ int main(int _argc, const char *_argv[]) {
APPL_INFO("==================================");
APPL_INFO("== JUS test client start ==");
APPL_INFO("==================================");
client1.connect("userName");
client1.connect("test1#atria-soft.com");
// Connect that is not us
//client1.identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
bool retIdentify = client1.call_b("identify", "clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968");
// Connect to ourself:
//client1.authentificate("coucou");
//bool retAuthentify = client1.call_b("authentify", "coucou");
APPL_INFO(" ----------------------------------");
APPL_INFO(" -- Get service count --");
APPL_INFO(" ----------------------------------");
/*
std::vector<double> tmp;
tmp.push_back(1);
tmp.push_back(22);
@ -51,10 +57,17 @@ int main(int _argc, const char *_argv[]) {
APPL_INFO(" - " << it);
}
jus::ServiceRemote localService = client1.getService("serviceTest1");
if (localService.exist() == true) {
double retCall = localService.call_d("mul", 13.1, 2.0);
APPL_INFO("serviceTest1.mul = " << retCall);
}
*/
double retCall = localService.call_d("mul", 13.1, 2.0);
APPL_INFO("serviceTest1.mul = " << retCall);
jus::ServiceRemote remoteServiceUser = client1.getService("system-user");
if (remoteServiceUser.exist() == true) {
std::vector<std::string> retCall = remoteServiceUser.call_vs("getClientGroups");
APPL_INFO("system-user.getClientGroups() = " << retCall);
}
int32_t iii=0;
while (iii < 3) {
usleep(500000);

View File

@ -0,0 +1,8 @@
{
"password":"coucou",
"client":{
"clientTest1#atria-soft.com":{
"tocken":"QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"
}
}
}

View File

@ -1,137 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.h>
#include <jus/Service.h>
#include <etk/etk.h>
#include <unistd.h>
#include <etk/stdTools.h>
namespace appl {
class User {
public:
User() {
APPL_WARNING("new USER");
}
~User() {
APPL_WARNING("delete USER");
}
};
class UserManager {
private:
std::map<std::string, ememory::SharedPtr<appl::User>> m_listLoaded;
public:
UserManager() {
}
ememory::SharedPtr<appl::User> getUser(const std::string& _userName) {
// TODO : Lock ...
auto it = m_listLoaded.find(_userName);
if (it != m_listLoaded.end()) {
// User already loaded:
return it->second;
}
// load New User:
ememory::SharedPtr<appl::User> tmp(new appl::User);
m_listLoaded.insert(std::make_pair(_userName, tmp));
return tmp;
}
};
class ClientProperty {
public:
ClientProperty() {}
private:
std::string m_name;
public:
void setName(const std::string& _name) {
m_name = _name
}
const std::string& getName() {
return m_name;
}
private:
std::vector<std::string> m_groups;
public:
void setGroups(std::vector<std::string> _groups) {
m_groups = _groups
}
const std::vector<std::string>& getGroups() {
return m_groups;
}
}
class SystemService {
private:
public:
SystemService() {
APPL_WARNING("New SystemService ...");
}
~SystemService() {
APPL_WARNING("delete SystemService ...");
}
private:
ememory::SharedPtr<appl::User> m_user;
public:
int32_t getServiceCount() {
return 0;
}
std::vector<std::string> getServiceList() {
return std::vector<std::string>();
}
public:
SystemService(ememory::SharedPtr<appl::User> _user) :
m_user(_user) {
}
};
}
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
appl::UserManager userMng;
jus::ServiceType<appl::SystemService, appl::UserManager> serviceInterface(userMng);
serviceInterface.setDescription("SystemService interface");
serviceInterface.setVersion("0.1.1");
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("mul", &appl::SystemService::mul);
serviceInterface.setLastFuncDesc("simple multiplication to test double IO");
serviceInterface.addLastFuncParam("val1", "First Parameter To multiply");
serviceInterface.addLastFuncParam("val2", "Second Parameter To multiply");
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
serviceInterface.propertyIp.set(std::string(&data[5]));
} else if (etk::start_with(data, "--port=") == true) {
serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7])));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
return -1;
}
}
APPL_INFO("==================================");
APPL_INFO("== JUS test service1 start ==");
APPL_INFO("==================================");
serviceInterface.connect("serviceTest1");
int32_t iii=0;
while (true) {
usleep(1000000);
serviceInterface.pingIsAlive();
APPL_INFO("service in waiting ... " << iii << "/inf");
iii++;
}
serviceInterface.disconnect();
APPL_INFO("==================================");
APPL_INFO("== JUS test service1 stop ==");
APPL_INFO("==================================");
return 0;
}

View File

@ -0,0 +1,199 @@
/** @file
* @author Edouard DUPIN
* @copyright 2014, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.h>
#include <jus/Service.h>
#include <etk/etk.h>
#include <unistd.h>
#include <mutex>
#include <ejson/ejson.h>
#include <etk/stdTools.h>
namespace appl {
class User {
private:
std::mutex m_mutex;
std::string m_userName;
ejson::Document m_database;
public:
User(const std::string& _userName) :
m_userName(_userName) {
std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("new USER: " << m_userName);
bool ret = m_database.load(std::string("USERDATA:") + m_userName + ".json");
if (ret == false) {
APPL_WARNING(" ==> LOAD error");
}
}
~User() {
std::unique_lock<std::mutex> lock(m_mutex);
APPL_WARNING("delete USER [START]");
APPL_DEBUG("Store User Info:");
bool ret = m_database.storeSafe(std::string("USERDATA:") + m_userName + ".json");
if (ret == false) {
APPL_WARNING(" ==> Store error");
}
APPL_WARNING("delete USER [STOP]");
}
std::vector<std::string> getGroups(const std::string& _clientName) {
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<std::string> out;
ejson::Object clients = m_database["client"].toObject();
if (clients.exist() == false) {
// Section never created
return out;
}
ejson::Object client = clients[_clientName].toObject();
if (clients.exist() == false) {
// No specificity for this client (in case it have no special right)
return out;
}
// TODO: check banishing ...
ejson::Array groups = client["group"].toArray();
for (auto it : groups) {
out.push_back(it.toString().get());
}
return out;
}
bool checkTocken(const std::string& _clientName, const std::string& _tocken) {
std::unique_lock<std::mutex> lock(m_mutex);
ejson::Object clients = m_database["client"].toObject();
if (clients.exist() == false) {
// Section never created
return false;
}
ejson::Object client = clients[_clientName].toObject();
if (clients.exist() == false) {
// No specificity for this client (in case it have no special right)
return false;
}
// TODO: check banishing ...
// TODO: Do it better ...
std::string registerTocken = client["tocken"].toString().get();
if (registerTocken == _tocken) {
return true;
}
return false;
}
};
class UserManager {
private:
std::mutex m_mutex;
std::map<std::string, ememory::SharedPtr<appl::User>> m_listLoaded;
public:
UserManager() {
}
ememory::SharedPtr<appl::User> getUser(const std::string& _userName) {
std::unique_lock<std::mutex> lock(m_mutex);
auto it = m_listLoaded.find(_userName);
if (it != m_listLoaded.end()) {
// User already loaded:
return it->second;
}
// load New User:
ememory::SharedPtr<appl::User> tmp(new appl::User(_userName));
m_listLoaded.insert(std::make_pair(_userName, tmp));
return tmp;
}
};
class SystemService {
private:
ememory::SharedPtr<appl::User> m_user;
private:
ememory::SharedPtr<jus::ClientProperty> m_client;
public:
SystemService() {
APPL_WARNING("New SystemService ...");
}
SystemService(ememory::SharedPtr<appl::User> _user, ememory::SharedPtr<jus::ClientProperty> _client) :
m_user(_user),
m_client(_client) {
APPL_WARNING("New SystemService ... for user: ");
}
~SystemService() {
APPL_WARNING("delete SystemService ...");
}
public:
std::vector<std::string> getClientGroups() {
std::vector<std::string> out;
if (m_client == nullptr) {
return out;
}
// TODO: check if basished ...
if (m_client->getName() != "") {
out = m_user->getGroups(m_client->getName());
}
// TODO: Check default visibility ... (if user want to have default visibility at Noone ==> then public must be removed...
if (true) {
out.push_back("public");
}
return out;
}
std::vector<std::string> getClientServices() {
return std::vector<std::string>();
}
bool checkTocken(std::string _clientName, std::string _tocken) {
return m_user->checkTocken(_clientName, _tocken);
}
};
}
int main(int _argc, const char *_argv[]) {
etk::init(_argc, _argv);
appl::UserManager userMng;
jus::ServiceType<appl::SystemService, appl::UserManager> serviceInterface(userMng);
serviceInterface.setDescription("user interface management");
serviceInterface.setVersion("0.1.0");
serviceInterface.addAuthor("Heero Yui", "yui.heero@gmail.com");
serviceInterface.advertise("getClientGroups", &appl::SystemService::getClientGroups);
serviceInterface.setLastFuncDesc("Get list of group availlable for a client name");
serviceInterface.addLastFuncParam("clientName", "Name of the client");
serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken);
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data, "--ip=") == true) {
serviceInterface.propertyIp.set(std::string(&data[5]));
} else if (etk::start_with(data, "--port=") == true) {
serviceInterface.propertyPort.set(etk::string_to_uint16_t(std::string(&data[7])));
} else if ( data == "-h"
|| data == "--help") {
APPL_PRINT(etk::getApplicationName() << " - help : ");
APPL_PRINT(" " << _argv[0] << " [options]");
APPL_PRINT(" --ip=XXX Server connection IP (default: 1.7.0.0.1)");
APPL_PRINT(" --port=XXX Server connection PORT (default: 1983)");
return -1;
}
}
while (true) {
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [START]");
APPL_INFO("===========================================================");
serviceInterface.connect(SERVICE_NAME);
if (serviceInterface.GateWayAlive() == false) {
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] Can not connect to the GateWay");
APPL_INFO("===========================================================");
APPL_INFO("wait 5 second ...");
usleep(5000000);
continue;
}
int32_t iii=0;
while (serviceInterface.GateWayAlive() == true) {
usleep(1000000);
serviceInterface.pingIsAlive();
APPL_INFO("service in waiting ... " << iii << "/inf");
iii++;
}
serviceInterface.disconnect();
APPL_INFO("===========================================================");
APPL_INFO("== JUS service: " << SERVICE_NAME << " [STOP] GateWay Stop");
APPL_INFO("===========================================================");
}
return 0;
}

View File

@ -32,6 +32,7 @@ def create(target, module_name):
'appl/debug.cpp',
'appl/main.cpp'
])
my_module.add_export_flag('c++', "-DSERVICE_NAME=\"\\\"" + module_name[4:] + "\\\"\"")
return my_module