PICloud Dispatcher screen mode

This commit is contained in:
2021-04-09 16:44:05 +03:00
parent f0e2410929
commit f75ce1e8e0
8 changed files with 194 additions and 29 deletions

View File

@@ -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; alignment = Left;
focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel; focus_flags = CanHasFocus | NextByArrowsHorizontal | NextByTab | FocusOnMouseOrWheel;
lhei = offset = cur = 0; lhei = offset = cur = 0;
mouse_sel = false; mouse_sel = false;
selection_mode = NoSelection; selection_mode = sm;
scroll = new TileScrollBar(); scroll = new TileScrollBar();
scroll->size_policy = Ignore; scroll->size_policy = Ignore;
addTile(scroll); addTile(scroll);

View File

@@ -70,8 +70,6 @@ protected:
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile { class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile) PIOBJECT_SUBCLASS(TileList, PIScreenTile)
public: public:
TileList(const PIString & n = PIString());
virtual ~TileList() {}
enum SelectionMode { enum SelectionMode {
NoSelection, NoSelection,
SingleSelection, SingleSelection,
@@ -81,6 +79,10 @@ public:
SelectionChanged, SelectionChanged,
RowPressed RowPressed
}; };
TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection);
virtual ~TileList() {}
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
PIDeque<Row> content; PIDeque<Row> content;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;

View File

@@ -3,7 +3,7 @@ set(PIP_UTILS_LIST ${PIP_UTILS_LIST} PARENT_SCOPE)
file(GLOB CPPS "*.cpp") file(GLOB CPPS "*.cpp")
file(GLOB HDRS "*.h") file(GLOB HDRS "*.h")
add_executable(picloud ${CPPS} ${HDRS}) add_executable(picloud ${CPPS} ${HDRS})
target_link_libraries(picloud pip pip_cloud) target_link_libraries(picloud pip pip_cloud pip_console)
if (DEFINED LIB) if (DEFINED LIB)
install(TARGETS picloud DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS picloud DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
else() else()

View File

@@ -14,6 +14,7 @@ public:
void removeClient(DispatcherClient * c); void removeClient(DispatcherClient * c);
PIVector<DispatcherClient*> getClients(); PIVector<DispatcherClient*> getClients();
EVENT_HANDLER0(void, printStatus); EVENT_HANDLER0(void, printStatus);
const DispatcherClient * getConnection() const {return server;}
private: private:
DispatcherClient * server; DispatcherClient * server;

View File

@@ -18,6 +18,8 @@ public:
void sendData(const PIByteArray & data); void sendData(const PIByteArray & data);
void sendDataToClient(const PIByteArray & data, uint client_id); void sendDataToClient(const PIByteArray & data, uint client_id);
void authorise(bool ok); void authorise(bool ok);
bool isAuthorised() const {return authorised;}
PICloud::TCP::Role role() const {return tcp.role();}
PIString address(); PIString address();
uint clientId() const {return client_id;} uint clientId() const {return client_id;}
EVENT1(disconnectEvent, DispatcherClient *, client) EVENT1(disconnectEvent, DispatcherClient *, client)

View File

@@ -1,16 +1,13 @@
#include "dispatcherserver.h" #include "dispatcherserver.h"
#include "piscreentiles.h"
DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::TCP_Server) { DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::TCP_Server) {
client_gid = 0; client_gid = 0;
eth.setParameter(PIEthernet::ReuseAddress); eth.setParameter(PIEthernet::ReuseAddress);
eth.setReadAddress(addr);
CONNECTU(&eth, newConnection, this, newConnection); CONNECTU(&eth, newConnection, this, newConnection);
eth.listen(addr, true);
piCoutObj << "server started" << addr;
CONNECTU(&status_timer, tickEvent, this, printStatus);
CONNECTU(&timeout_timer, tickEvent, this, cleanClients); 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() { void DispatcherServer::cleanClients() {
PIVector<DispatcherClient*> rm; PIVector<DispatcherClient*> rm;
map_mutex.lock(); map_mutex.lock();
@@ -40,23 +61,94 @@ void DispatcherServer::cleanClients() {
} }
void DispatcherServer::printStatus() { void DispatcherServer::updateConnectionsTile(TileList * tl) {
map_mutex.lock(); map_mutex.lock();
piCout << PICoutManipulators::NewLine; tl->content.clear();
piCout << "Connections:";
for (auto c: clients) { for (auto c: clients) {
piCout << " " << c->address(); 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;
} }
piCout << "Servers:"; tl->content << TileList::Row(c->address() + " " + role, PIScreenTypes::CellFormat());
auto it = c_servers.makeIterator();
while(it.next()){
piCout << " " << it.key();
it.value()->printStatus();
} }
map_mutex.unlock(); map_mutex.unlock();
} }
void DispatcherServer::updateServersTile(TileList * tl, PISet<const DispatcherClient *> 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<const DispatcherClient *> 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<const DispatcherClient *> DispatcherServer::getServers(PISet<int> ids) {
PISet<const DispatcherClient *> 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) { void DispatcherServer::disconnectClient(DispatcherClient *client) {
if (!clients.contains(client)) { if (!clients.contains(client)) {
//piCoutObj << "INVALID client" << client; //piCoutObj << "INVALID client" << client;

View File

@@ -3,13 +3,23 @@
#include "cloudserver.h" #include "cloudserver.h"
class TileList;
class DispatcherServer: public PIObject { class DispatcherServer: public PIObject {
PIOBJECT(DispatcherServer) PIOBJECT(DispatcherServer)
public: public:
DispatcherServer(PIEthernet::Address addr); DispatcherServer(PIEthernet::Address addr);
~DispatcherServer(); ~DispatcherServer();
EVENT_HANDLER0(void, printStatus); void start();
void updateConnectionsTile(TileList * tl);
void updateServersTile(TileList * tl, PISet<const DispatcherClient *> servers = PISet<const DispatcherClient *>());
void updateClientsTile(TileList * tl, PISet<const DispatcherClient *> servers = PISet<const DispatcherClient *>());
const DispatcherClient * getConnection(int index);
const DispatcherClient * getServer(int index);
PISet<const DispatcherClient *> getServers(PISet<int> ids);
EVENT_HANDLER0(void, picoutStatus);
private: private:
EVENT_HANDLER1(void, newConnection, PIEthernet * , cl); EVENT_HANDLER1(void, newConnection, PIEthernet * , cl);
@@ -22,7 +32,6 @@ private:
PIMap<const DispatcherClient *, CloudServer *> index_c_servers; PIMap<const DispatcherClient *, CloudServer *> index_c_servers;
PIMap<const DispatcherClient *, CloudServer *> index_c_clients; PIMap<const DispatcherClient *, CloudServer *> index_c_clients;
PIVector<DispatcherClient*> rm_clients; PIVector<DispatcherClient*> rm_clients;
PITimer status_timer;
PITimer timeout_timer; PITimer timeout_timer;
PIMutex map_mutex; PIMutex map_mutex;
uint client_gid; uint client_gid;

View File

@@ -24,39 +24,98 @@
using namespace PICoutManipulators; using namespace PICoutManipulators;
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
void usage() { void usage() {
piCout << Bold << "PIP Cloud Dispatcher"; piCout << Bold << "PIP Cloud Dispatcher";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"picloud [-h] [-i <ip>] [-p <port>]\"" << NewLine; piCout << Green << Bold << "Usage:" << Default << "\"picloud [-hsv] [-i <ip>] [-p <port>]\"" << NewLine;
piCout << Green << Bold << "Details:"; piCout << Green << Bold << "Details:";
piCout << "-h --help " << Green << "- display this message and exit"; piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-i --ip " << Green << "- listen address, default \"0.0.0.0\""; piCout << "-i --ip " << Green << "- listen address, default \"0.0.0.0\"";
piCout << "-p --port " << Green << "- listen port, default 10101"; 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[]) { int main (int argc, char * argv[]) {
PICrypt::hash("");
PICLI cli(argc, argv); PICLI cli(argc, argv);
cli.addArgument("help"); cli.addArgument("help");
cli.addArgument("ip", true); cli.addArgument("ip", true);
cli.addArgument("port", true); cli.addArgument("port", true);
cli.addArgument("screen");
cli.addArgument("verbose");
if (cli.hasArgument("help")) { if (cli.hasArgument("help")) {
usage(); usage();
return 0; return 0;
} }
PITimer status_timer;
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
if (cli.hasArgument("ip")) if (cli.hasArgument("ip"))
addr.setIP(cli.argumentValue("ip")); addr.setIP(cli.argumentValue("ip"));
if (cli.hasArgument("port")) if (cli.hasArgument("port"))
addr.setPort(cli.argumentValue("port").toInt()); addr.setPort(cli.argumentValue("port").toInt());
DispatcherServer server(addr); DispatcherServer server(addr);
if (cli.hasArgument("screen")) {
PISet<const DispatcherClient *> 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; PIKbdListener ls;
ls.enableExitCapture(PIKbdListener::F10); ls.enableExitCapture(PIKbdListener::F10);
ls.start(); ls.start();
server.start();
if (cli.hasArgument("verbose")) {
CONNECTU(&status_timer, tickEvent, &server, picoutStatus);
status_timer.start(1000);
}
WAIT_FOR_EXIT WAIT_FOR_EXIT
}
return 0; return 0;
} }