#include "dispatcherserver.h" #include "piscreentiles.h" DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::TCP_Server) { client_gid = 0; eth.setParameter(PIEthernet::ReuseAddress); eth.setReadAddress(addr); CONNECTU(ð, newConnection, this, newConnection); CONNECTU(&timeout_timer, tickEvent, this, cleanClients); } DispatcherServer::~DispatcherServer() { eth.close(); //piCoutObj << "server stoped"; } void DispatcherServer::start() { eth.listen(true); timeout_timer.start(5000); piCoutObj << "server started" << eth.readAddress(); } void DispatcherServer::picoutStatus() { map_mutex.lock(); piCout << PICoutManipulators::NewLine; piCout << "Connections:"; for (auto c: clients) { piCout << " " << c->address(); } piCout << "Servers:"; auto it = c_servers.makeIterator(); while(it.next()){ piCout << " " << it.key(); it.value()->printStatus(); } map_mutex.unlock(); } void DispatcherServer::cleanClients() { PIVector rm; map_mutex.lock(); for (auto c: clients) { if (!index_c_servers.contains(c) && !index_c_clients.contains(c)) { if (rm_clients.contains(c)) rm << c; else rm_clients << c; } else rm_clients.removeAll(c); } for (auto c: rm_clients) { if (clients.contains(c)) rm << c; } map_mutex.unlock(); for (auto c: rm) { c->close(); // c->deleteLater(); } } void DispatcherServer::updateConnectionsTile(TileList * tl) { map_mutex.lock(); tl->content.clear(); for (auto c: clients) { PIString role = "Invalid"; switch (c->role()) { case PICloud::TCP::Client : { role = "Client"; CloudServer * cs = index_c_clients.value(c, nullptr); if (cs) role += " \"" + cs->serverName() + "\""; } break; case PICloud::TCP::Server : { role = "Server"; CloudServer * cs = index_c_servers.value(c, nullptr); if (cs) role += " \"" + cs->serverName() + "\""; } break; default: break; } tl->content << TileList::Row(c->address() + " " + role, PIScreenTypes::CellFormat()); } map_mutex.unlock(); } void DispatcherServer::updateServersTile(TileList * tl, PISet servers) { map_mutex.lock(); tl->content.clear(); auto mi = c_servers.makeIterator(); while (mi.next()) { tl->content << TileList::Row(mi.value()->serverName() + " - " + PIString::fromNumber(mi.value()->getClients().size()), PIScreenTypes::CellFormat()); if (servers.contains(mi.value()->getConnection())) tl->selected << (tl->content.size_s() - 1); } map_mutex.unlock(); } void DispatcherServer::updateClientsTile(TileList * tl, PISet servers) { map_mutex.lock(); tl->content.clear(); auto mi = c_servers.makeIterator(); while (mi.next()) { for (auto c : mi.value()->getClients()) { if (servers.isEmpty() || servers.contains(mi.value()->getConnection())) tl->content << TileList::Row(c->address(), PIScreenTypes::CellFormat()); } } map_mutex.unlock(); } const DispatcherClient * DispatcherServer::getConnection(int index) { const DispatcherClient * ret = nullptr; map_mutex.lock(); if (index >=0 && index < clients.size_s()) ret = clients[index]; map_mutex.unlock(); return ret; } const DispatcherClient * DispatcherServer::getServer(int index) { const DispatcherClient * ret = nullptr; const DispatcherClient * tmp; map_mutex.lock(); if (index >=0 && index < clients.size_s()) { tmp = clients[index]; } if (index_c_servers.contains(tmp)) ret = tmp; map_mutex.unlock(); return ret; } PISet DispatcherServer::getServers(PISet ids) { PISet ret; if (ids.isEmpty()) return ret; map_mutex.lock(); int i = 0; auto mi = c_servers.makeIterator(); while (mi.next()) { if (ids.contains(i)) ret << mi.value()->getConnection(); i++; } map_mutex.unlock(); return ret; } void DispatcherServer::disconnectClient(DispatcherClient *client) { if (!clients.contains(client)) { //piCoutObj << "INVALID client" << client; return; } //piCoutObj << "remove client" << client; map_mutex.lock(); clients.removeOne(client); CloudServer * cs = index_c_servers.value(client, nullptr); if (cs) { PIVector cscv = cs->getClients(); for(auto csc : cscv) { clients.removeOne(csc); index_c_clients.removeOne(csc); cs->removeClient(csc); csc->close(); csc->deleteLater(); } c_servers.remove(cs->serverName()); index_c_servers.removeOne(client); delete cs; } CloudServer * cc = index_c_clients.value(client, nullptr); if (cc) { cc->removeClient(client); index_c_clients.removeOne(client); } client->close(); map_mutex.unlock(); client->deleteLater(); } void DispatcherServer::newConnection(PIEthernet *cl) { DispatcherClient * client = new DispatcherClient(cl, client_gid++); CONNECTU(client, disconnectEvent, this, disconnectClient); CONNECTL(client, registerServer, [this](PIString sname, DispatcherClient * c){ map_mutex.lock(); CloudServer * cs = c_servers.value(sname, nullptr); if (cs) { rm_clients << c; } else { piCoutObj << "add new Server ->" << sname; CloudServer * cs = new CloudServer(c, sname); c_servers.insert(sname, cs); index_c_servers.insert(c, cs); c->authorise(true); } map_mutex.unlock(); }); CONNECTL(client, registerClient, [this](PIString sname, DispatcherClient * c){ map_mutex.lock(); CloudServer * cs = c_servers.value(sname, nullptr); if (cs) { piCoutObj << "add new Client to Server ->" << sname; cs->addClient(c); index_c_clients.insert(c, cs); c->authorise(true); } else { rm_clients << c; } map_mutex.unlock(); }); //piCoutObj << "add client" << client; client->start(); map_mutex.lock(); clients.push_back(client); map_mutex.unlock(); }