From f75ce1e8e03d69ffedfcf0bddac5106e68e4e93b Mon Sep 17 00:00:00 2001 From: andrey Date: Fri, 9 Apr 2021 16:44:05 +0300 Subject: [PATCH] PICloud Dispatcher screen mode --- libs/console/piscreentiles.cpp | 4 +- libs/main/console/piscreentiles.h | 6 +- utils/cloud_dispatcher/CMakeLists.txt | 2 +- utils/cloud_dispatcher/cloudserver.h | 1 + utils/cloud_dispatcher/dispatcherclient.h | 2 + utils/cloud_dispatcher/dispatcherserver.cpp | 122 +++++++++++++++++--- utils/cloud_dispatcher/dispatcherserver.h | 13 ++- utils/cloud_dispatcher/main.cpp | 73 ++++++++++-- 8 files changed, 194 insertions(+), 29 deletions(-) diff --git a/libs/console/piscreentiles.cpp b/libs/console/piscreentiles.cpp index 2a085642..1fea2e93 100644 --- a/libs/console/piscreentiles.cpp +++ b/libs/console/piscreentiles.cpp @@ -124,12 +124,12 @@ bool TileScrollBar::mouseEvent(PIKbdListener::MouseEvent me) { -TileList::TileList(const PIString & n): PIScreenTile(n) { +TileList::TileList(const PIString & n, SelectionMode sm): PIScreenTile(n) { alignment = Left; focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel; lhei = offset = cur = 0; mouse_sel = false; - selection_mode = NoSelection; + selection_mode = sm; scroll = new TileScrollBar(); scroll->size_policy = Ignore; addTile(scroll); diff --git a/libs/main/console/piscreentiles.h b/libs/main/console/piscreentiles.h index ee617156..34815d9f 100644 --- a/libs/main/console/piscreentiles.h +++ b/libs/main/console/piscreentiles.h @@ -70,8 +70,6 @@ protected: class PIP_CONSOLE_EXPORT TileList: public PIScreenTile { PIOBJECT_SUBCLASS(TileList, PIScreenTile) public: - TileList(const PIString & n = PIString()); - virtual ~TileList() {} enum SelectionMode { NoSelection, SingleSelection, @@ -81,6 +79,10 @@ public: SelectionChanged, RowPressed }; + + TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection); + virtual ~TileList() {} + typedef PIPair Row; PIDeque content; PIScreenTypes::Alignment alignment; diff --git a/utils/cloud_dispatcher/CMakeLists.txt b/utils/cloud_dispatcher/CMakeLists.txt index e48f86f4..d3e8c563 100644 --- a/utils/cloud_dispatcher/CMakeLists.txt +++ b/utils/cloud_dispatcher/CMakeLists.txt @@ -3,7 +3,7 @@ set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE) file(GLOB CPPS "*.cpp") file(GLOB HDRS "*.h") add_executable(picloud ${CPPS} ${HDRS}) -target_link_libraries(picloud pip pip_cloud) +target_link_libraries(picloud pip pip_cloud pip_console) if (DEFINED LIB) install(TARGETS picloud DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) else() diff --git a/utils/cloud_dispatcher/cloudserver.h b/utils/cloud_dispatcher/cloudserver.h index 8800e0bf..8b3864b9 100644 --- a/utils/cloud_dispatcher/cloudserver.h +++ b/utils/cloud_dispatcher/cloudserver.h @@ -14,6 +14,7 @@ public: void removeClient(DispatcherClient * c); PIVector getClients(); EVENT_HANDLER0(void, printStatus); + const DispatcherClient * getConnection() const {return server;} private: DispatcherClient * server; diff --git a/utils/cloud_dispatcher/dispatcherclient.h b/utils/cloud_dispatcher/dispatcherclient.h index de6d016e..3b4dd1c2 100644 --- a/utils/cloud_dispatcher/dispatcherclient.h +++ b/utils/cloud_dispatcher/dispatcherclient.h @@ -18,6 +18,8 @@ public: void sendData(const PIByteArray & data); void sendDataToClient(const PIByteArray & data, uint client_id); void authorise(bool ok); + bool isAuthorised() const {return authorised;} + PICloud::TCP::Role role() const {return tcp.role();} PIString address(); uint clientId() const {return client_id;} EVENT1(disconnectEvent, DispatcherClient *, client) diff --git a/utils/cloud_dispatcher/dispatcherserver.cpp b/utils/cloud_dispatcher/dispatcherserver.cpp index f3cc127a..d161e62c 100644 --- a/utils/cloud_dispatcher/dispatcherserver.cpp +++ b/utils/cloud_dispatcher/dispatcherserver.cpp @@ -1,16 +1,13 @@ #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); - eth.listen(addr, true); - piCoutObj << "server started" << addr; - CONNECTU(&status_timer, tickEvent, this, printStatus); CONNECTU(&timeout_timer, tickEvent, this, cleanClients); - status_timer.start(1000); - timeout_timer.start(5000); } @@ -20,6 +17,30 @@ DispatcherServer::~DispatcherServer() { } +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(); @@ -40,23 +61,94 @@ void DispatcherServer::cleanClients() { } -void DispatcherServer::printStatus() { +void DispatcherServer::updateConnectionsTile(TileList * tl) { map_mutex.lock(); - piCout << PICoutManipulators::NewLine; - piCout << "Connections:"; + tl->content.clear(); for (auto c: clients) { - piCout << " " << c->address(); - } - piCout << "Servers:"; - auto it = c_servers.makeIterator(); - while(it.next()){ - piCout << " " << it.key(); - it.value()->printStatus(); + 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; diff --git a/utils/cloud_dispatcher/dispatcherserver.h b/utils/cloud_dispatcher/dispatcherserver.h index e1d6fa9a..b8320fd6 100644 --- a/utils/cloud_dispatcher/dispatcherserver.h +++ b/utils/cloud_dispatcher/dispatcherserver.h @@ -3,13 +3,23 @@ #include "cloudserver.h" +class TileList; + class DispatcherServer: public PIObject { PIOBJECT(DispatcherServer) public: DispatcherServer(PIEthernet::Address addr); ~DispatcherServer(); - EVENT_HANDLER0(void, printStatus); + void start(); + + void updateConnectionsTile(TileList * tl); + void updateServersTile(TileList * tl, PISet servers = PISet()); + void updateClientsTile(TileList * tl, PISet servers = PISet()); + const DispatcherClient * getConnection(int index); + const DispatcherClient * getServer(int index); + PISet getServers(PISet ids); + EVENT_HANDLER0(void, picoutStatus); private: EVENT_HANDLER1(void, newConnection, PIEthernet * , cl); @@ -22,7 +32,6 @@ private: PIMap index_c_servers; PIMap index_c_clients; PIVector rm_clients; - PITimer status_timer; PITimer timeout_timer; PIMutex map_mutex; uint client_gid; diff --git a/utils/cloud_dispatcher/main.cpp b/utils/cloud_dispatcher/main.cpp index 0fcf610a..a5eb76f1 100644 --- a/utils/cloud_dispatcher/main.cpp +++ b/utils/cloud_dispatcher/main.cpp @@ -24,39 +24,98 @@ using namespace PICoutManipulators; -PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101); void usage() { piCout << Bold << "PIP Cloud Dispatcher"; piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; - piCout << Green << Bold << "Usage:" << Default << "\"picloud [-h] [-i ] [-p ]\"" << NewLine; + piCout << Green << Bold << "Usage:" << Default << "\"picloud [-hsv] [-i ] [-p ]\"" << NewLine; piCout << Green << Bold << "Details:"; piCout << "-h --help " << Green << "- display this message and exit"; piCout << "-i --ip " << Green << "- listen address, default \"0.0.0.0\""; piCout << "-p --port " << Green << "- listen port, default 10101"; + piCout << "-s --screen " << Green << "- start with console UI"; + piCout << "-v --verbose" << Green << "- print state (--screen ignore this flag)"; } int main (int argc, char * argv[]) { - PICrypt::hash(""); PICLI cli(argc, argv); cli.addArgument("help"); cli.addArgument("ip", true); cli.addArgument("port", true); + cli.addArgument("screen"); + cli.addArgument("verbose"); if (cli.hasArgument("help")) { usage(); return 0; } + PITimer status_timer; + PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101); if (cli.hasArgument("ip")) addr.setIP(cli.argumentValue("ip")); if (cli.hasArgument("port")) addr.setPort(cli.argumentValue("port").toInt()); DispatcherServer server(addr); - PIKbdListener ls; - ls.enableExitCapture(PIKbdListener::F10); - ls.start(); - WAIT_FOR_EXIT + if (cli.hasArgument("screen")) { + PISet sel_servers; + PIScreen screen(false); + PIScreenTile maintile("PICloud Dispatcher", PIScreenTypes::Horizontal, PIScreenTypes::Expanding); + PIScreenTile tls[3]; + TileList conn_tl(PIString(), TileList::MultiSelection); + TileList server_tl(PIString(), TileList::MultiSelection); + TileList client_tl(PIString(), TileList::MultiSelection); + tls[0].addTile(new TileSimple(TileSimple::Row("Connections", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse)))); + tls[0].addTile(&conn_tl); + tls[1].addTile(new TileSimple(TileSimple::Row("Servers", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse)))); + tls[1].addTile(&server_tl); + tls[2].addTile(new TileSimple(TileSimple::Row("Clients", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse)))); + tls[2].addTile(&client_tl); + CONNECTL(&screen, tileEvent, ([&](PIScreenTile * t, PIScreenTypes::TileEvent e){ + if (t == (PIScreenTile *)&server_tl) { + if (e.type == TileList::SelectionChanged) { + sel_servers = server.getServers(server_tl.selected); + } + } + if (t == (PIScreenTile *)&conn_tl) { + if (e.type == TileList::RowPressed) { + sel_servers.clear(); + server_tl.selected.clear(); + const DispatcherClient * dc = server.getServer(e.data.toInt()); + if (dc) sel_servers << dc; + } + } + })); + for (auto & a : tls) { + a.children()[0]->size_policy = PIScreenTypes::Fixed; + maintile.addTile(&a); + } + CONNECTL(&status_timer, tickEvent, [&](void *, int){ + screen.lock(); + server.updateConnectionsTile(&conn_tl); + server.updateServersTile(&server_tl, sel_servers); + server.updateClientsTile(&client_tl, server.getServers(server_tl.selected)); + screen.unlock(); + }); + screen.enableExitCapture(PIKbdListener::F10); + screen.rootTile()->addTile(new TileSimple(TileSimple::Row("PICloud Dispatcher " + addr.toString(), PIScreenTypes::CellFormat(PIScreenTypes::Yellow, PIScreenTypes::Default, PIScreenTypes::Bold)))); + screen.rootTile()->addTile(&maintile); + screen.rootTile()->addTile(new TilePICout()); + screen.start(); + server.start(); + status_timer.start(100); + screen.waitForFinish(); + } else { + PIKbdListener ls; + ls.enableExitCapture(PIKbdListener::F10); + ls.start(); + server.start(); + if (cli.hasArgument("verbose")) { + CONNECTU(&status_timer, tickEvent, &server, picoutStatus); + status_timer.start(1000); + } + WAIT_FOR_EXIT + } return 0; }