[DEV] better interface of the connection process

This commit is contained in:
Edouard DUPIN 2016-05-25 23:26:59 +02:00
parent 5028352541
commit 5efffd975f
5 changed files with 255 additions and 188 deletions

View File

@ -83,7 +83,10 @@ void jus::Client::connect(const std::string& _remoteUserToConnect){
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\"}");
bool ret = call_b("connectToUser", _remoteUserToConnect, "jus-client");
if (ret == false) {
JUS_ERROR("Connection error");
}
JUS_DEBUG("connect [STOP]");
}

View File

@ -11,6 +11,7 @@
#include <unistd.h>
jus::GateWayClient::GateWayClient(enet::Tcp _connection, jus::GateWay* _gatewayInterface) :
m_state(jus::GateWayClient::state::unconnect),
m_gatewayInterface(_gatewayInterface),
m_interfaceClient(std::move(_connection)),
m_transactionLocalId(-1) {
@ -29,6 +30,7 @@ jus::GateWayClient::~GateWayClient() {
void jus::GateWayClient::start(size_t _uid) {
m_uid = _uid;
m_state = jus::GateWayClient::state::connect;
m_interfaceClient.connect(this, &jus::GateWayClient::onClientData);
m_interfaceClient.connect(true);
m_interfaceClient.setInterfaceName("cli-" + etk::to_string(m_uid));
@ -57,200 +59,249 @@ bool jus::GateWayClient::isAlive() {
return m_interfaceClient.isActive();
}
void jus::GateWayClient::protocolError(const std::string& _errorHelp) {
ejson::Object answer;
answer.add("error", ejson::String("PROTOCOL-ERROR"));
answer.add("error-help", ejson::String(_errorHelp));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
m_state = jus::GateWayClient::state::disconnect;
m_interfaceClient.disconnect(true);
}
void jus::GateWayClient::returnBool(int32_t _transactionId, bool _value) {
ejson::Object answer;
answer.add("id", ejson::Number(_transactionId));
answer.add("return", ejson::Boolean(_value));
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
}
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;
}
JUS_WARNING("[" << m_uid << "] Client must send conection to user name ...");
// TODO : Return something ...
if (transactionId == 0) {
JUS_ERROR("Protocol error ==>missing id");
protocolError("missing parameter: 'id'");
return;
}
std::string service = data["service"].toString().get();
// Thsi is 2 default service for the cient interface that manage the authorisation of view:
if (service == "") {
std::string call = data["call"].toString().get();
ejson::Object answer;
//answer.add("from-service", ejson::String(""));
answer.add("id", data["id"]);
if (call == "getServiceCount") {
// TODO : Do it better:
answer.add("return", ejson::Number(2));
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);
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);
switch (m_state) {
case jus::GateWayClient::state::unconnect:
{
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());
}));
JUS_ERROR("Must never appear");
protocolError("Gateway internal error");
return;
}
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:
auto it = m_listConnectedService.begin();
while (it != m_listConnectedService.end()) {
if (*it == nullptr) {
++it;
continue;
case jus::GateWayClient::state::connect:
{
if (m_userConnectionName != "") {
protocolError("Gateway internal error 2");
return;
}
if ((*it)->getName() != service) {
++it;
continue;
std::string call = data["call"].toString().get();
if (call == "connectToUser") {
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");
if (m_userService == nullptr) {
protocolError("Gateway internal error 'No user interface'");
} else {
ejson::Object linkService;
linkService.add("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
m_userService->SendData(-m_uid, linkService);
m_state = jus::GateWayClient::state::userIdentify;
returnBool(transactionId, true);
}
return;
}
break;
JUS_WARNING("[" << m_uid << "] Client must send conection to user name ...");
protocolError("Missing call of connectToUser");
return;
}
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("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
srv->SendData(m_uid, linkService);
m_listConnectedService.push_back(srv);
answer.add("return", ejson::Boolean(true));
case jus::GateWayClient::state::userIdentify:
{
std::string call = data["call"].toString().get();
if (call == "identify") {
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) {
JUS_ERROR(" ==> Tocken ckeck return ...");
if (_data["return"].toBoolean().get() == true) {
m_clientName = clientName;
m_clientgroups.clear();
// TODO : Update all service name and group ...
returnBool(transactionId, true);
} else {
returnBool(transactionId, false);
}
}));
}
if (m_userService != nullptr) {
m_userService->SendData(-m_uid, gwCall);
} else {
protocolError("gateWay internal error 3");
}
return;
}
if (call == "auth") {
std::string password = data["param"].toArray()[0].toString().get();
protocolError("Not implemented");
return;
}
if (call == "anonymous") {
protocolError("Not implemented");
return;
}
protocolError("Client must call: identify/auth/anonymous");
return;
}
break;
case jus::GateWayClient::state::clientIdentify:
{
std::string service = data["service"].toString().get();
// Thsi is 2 default service for the cient interface that manage the authorisation of view:
if (service == "") {
std::string call = data["call"].toString().get();
ejson::Object answer;
//answer.add("from-service", ejson::String(""));
answer.add("id", data["id"]);
if (call == "getServiceCount") {
// TODO : Do it better:
answer.add("return", ejson::Number(2));
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);
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
return;
}
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("event", ejson::String("new"));
linkService.add("user", ejson::String(m_userConnectionName));
srv->SendData(m_uid, linkService);
m_listConnectedService.push_back(srv);
answer.add("return", ejson::Boolean(true));
} else {
answer.add("return", ejson::Boolean(false));
}
} else {
// TODO : Service already connected;
answer.add("return", ejson::Boolean(false));
}
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:
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()) {
answer.add("return", ejson::Boolean(false));
} else {
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
(*it)->SendData(m_uid, linkService);
m_listConnectedService.erase(it);
answer.add("return", ejson::Boolean(true));
}
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
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 {
answer.add("return", ejson::Boolean(false));
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);
}
} else {
// TODO : Service already connected;
answer.add("return", ejson::Boolean(false));
}
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:
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()) {
answer.add("return", ejson::Boolean(false));
} else {
ejson::Object linkService;
linkService.add("event", ejson::String("delete"));
(*it)->SendData(m_uid, linkService);
m_listConnectedService.erase(it);
answer.add("return", ejson::Boolean(true));
}
JUS_DEBUG("answer: " << answer.generateHumanString());
m_interfaceClient.write(answer.generateMachineString());
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);
}
}

View File

@ -15,10 +15,21 @@
namespace jus {
class GateWay;
class GateWayClient {
using Observer = std::function<void(ejson::Object& _data)>;
private:
using Observer = std::function<void(ejson::Object& _data)>;
enum class state {
unconnect, // starting sate
connect, // just get a TCP connection
userIdentify, // client set the user it want to access
clientIdentify, // client defien the mode of the acces (anonymous,client/user)
disconnect // client is dead or loal disconnection
};
enum state m_state; // state machine ...
private:
jus::GateWay* m_gatewayInterface;
jus::TcpString m_interfaceClient;
void protocolError(const std::string& _errorHelp);
void returnBool(int32_t _transactionId, bool _value);
public:
esignal::Signal<bool> signalIsConnected;
ememory::SharedPtr<jus::GateWayService> m_userService;

View File

@ -79,7 +79,7 @@ void jus::TcpString::connect(bool _async){
}
}
void jus::TcpString::disconnect(){
void jus::TcpString::disconnect(bool _inThreadStop){
JUS_DEBUG("disconnect [START]");
if (m_thread != nullptr) {
m_threadRunning = false;
@ -91,10 +91,12 @@ void jus::TcpString::disconnect(){
if (m_connection.getConnectionStatus() != enet::Tcp::status::unlink) {
m_connection.unlink();
}
if (m_thread != nullptr) {
m_thread->join();
delete m_thread;
m_thread = nullptr;
if (_inThreadStop == false) {
if (m_thread != nullptr) {
m_thread->join();
delete m_thread;
m_thread = nullptr;
}
}
JUS_DEBUG("disconnect [STOP]");
}

View File

@ -39,7 +39,7 @@ namespace jus {
virtual ~TcpString();
void setInterface(enet::Tcp _connection);
void connect(bool _async = false);
void disconnect();
void disconnect(bool _inThreadStop = false);
bool isActive() const;
void setInterfaceName(const std::string& _name);
int32_t write(const std::string& _data);