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

@@ -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()

View File

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

View File

@@ -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)

View File

@@ -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(&eth, 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<DispatcherClient*> 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<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) {
if (!clients.contains(client)) {
//piCoutObj << "INVALID client" << client;

View File

@@ -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<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:
EVENT_HANDLER1(void, newConnection, PIEthernet * , cl);
@@ -22,7 +32,6 @@ private:
PIMap<const DispatcherClient *, CloudServer *> index_c_servers;
PIMap<const DispatcherClient *, CloudServer *> index_c_clients;
PIVector<DispatcherClient*> rm_clients;
PITimer status_timer;
PITimer timeout_timer;
PIMutex map_mutex;
uint client_gid;

View File

@@ -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 <ip>] [-p <port>]\"" << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"picloud [-hsv] [-i <ip>] [-p <port>]\"" << 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<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;
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;
}