code format

This commit is contained in:
2022-12-14 14:13:52 +03:00
parent 430a41fefc
commit c2b8a8d6da
297 changed files with 27331 additions and 24162 deletions

View File

@@ -1,22 +1,22 @@
#include "cloudserver.h"
CloudServer::CloudServer(DispatcherClient * c, const PIByteArray & sname) : server(c) {
CloudServer::CloudServer(DispatcherClient * c, const PIByteArray & sname): server(c) {
setName(sname.toHex());
server_uuid = sname;
CONNECTL(c, dataReadedServer, ([this](uint id, PIByteArray & ba){
last_ping.reset();
mutex_clients.lock();
DispatcherClient * cl = index_clients.value(id, nullptr);
mutex_clients.unlock();
if (cl) cl->sendData(ba);
}));
CONNECTL(c, pingReceived, [this]() {last_ping.reset();});
CONNECTL(c, dataReadedServer, ([this](uint id, PIByteArray & ba) {
last_ping.reset();
mutex_clients.lock();
DispatcherClient * cl = index_clients.value(id, nullptr);
mutex_clients.unlock();
if (cl) cl->sendData(ba);
}));
CONNECTL(c, pingReceived, [this]() { last_ping.reset(); });
last_ping.reset();
}
CloudServer::~CloudServer() {
for (auto c :clients) {
for (auto c: clients) {
c->close();
}
}
@@ -36,10 +36,10 @@ void CloudServer::addClient(DispatcherClient * c) {
mutex_clients.unlock();
c->sendConnected(1);
server->sendConnected(cid);
CONNECTL(c, dataReaded, ([this, cid](PIByteArray & ba){
// piCoutObj << c->clientId() << "dataReaded";
server->sendDataToClient(ba, cid);
}));
CONNECTL(c, dataReaded, ([this, cid](PIByteArray & ba) {
// piCoutObj << c->clientId() << "dataReaded";
server->sendDataToClient(ba, cid);
}));
}
@@ -68,11 +68,10 @@ double CloudServer::lastPing() {
void CloudServer::printStatus() {
mutex_clients.lock();
piCout << " " << "Clients for" << server->address() << server_uuid.toHex() << ":";
piCout << " "
<< "Clients for" << server->address() << server_uuid.toHex() << ":";
for (auto c: clients) {
piCout << " " << c->address() << c->clientId();
}
mutex_clients.unlock();
}

View File

@@ -4,23 +4,24 @@
#include "dispatcherclient.h"
class CloudServer : public PIObject {
class CloudServer: public PIObject {
PIOBJECT(CloudServer)
public:
CloudServer(DispatcherClient * c, const PIByteArray & sname);
~CloudServer();
PIByteArray serverUUID() const;
void addClient(DispatcherClient * c);
void removeClient(DispatcherClient * c);
PIVector<DispatcherClient*> getClients();
PIVector<DispatcherClient *> getClients();
EVENT_HANDLER0(void, printStatus);
const DispatcherClient * getConnection() const {return server;}
const DispatcherClient * getConnection() const { return server; }
double lastPing();
private:
DispatcherClient * server;
PIVector<DispatcherClient*> clients;
PIMap<uint, DispatcherClient*> index_clients;
PIVector<DispatcherClient *> clients;
PIMap<uint, DispatcherClient *> index_clients;
PIByteArray server_uuid;
PITimeMeasurer last_ping;
PIMutex mutex_clients;

View File

@@ -1,8 +1,14 @@
#include "dispatcherclient.h"
#include "picloudtcp.h"
DispatcherClient::DispatcherClient(PIEthernet * eth_, int id) : authorised(false), eth(eth_), streampacker(eth_), tcp(&streampacker), client_id(id) {
DispatcherClient::DispatcherClient(PIEthernet * eth_, int id)
: authorised(false)
, eth(eth_)
, streampacker(eth_)
, tcp(&streampacker)
, client_id(id) {
eth->setName(PIString::fromNumber(id));
CONNECTU(&streampacker, packetReceiveEvent, this, readed);
CONNECTU(eth, disconnected, this, disconnected);
@@ -43,14 +49,18 @@ void DispatcherClient::sendDisconnected(uint client_id) {
void DispatcherClient::sendData(const PIByteArray & data) {
if (tcp.role() == PICloud::TCP::Client) tcp.sendData(data);
else piCoutObj << "error sendData, invalid role";
if (tcp.role() == PICloud::TCP::Client)
tcp.sendData(data);
else
piCoutObj << "error sendData, invalid role";
}
void DispatcherClient::sendDataToClient(const PIByteArray & data, uint client_id) {
if (tcp.role() == PICloud::TCP::Server) tcp.sendData(data, client_id);
else piCoutObj << "error sendDataToClient, invalid role";
if (tcp.role() == PICloud::TCP::Server)
tcp.sendData(data, client_id);
else
piCoutObj << "error sendDataToClient, invalid role";
}
@@ -67,7 +77,7 @@ void DispatcherClient::disconnected(bool withError) {
void DispatcherClient::readed(PIByteArray & ba) {
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
// piCoutObj << "readed" << hdr.first << hdr.second;
// piCoutObj << "readed" << hdr.first << hdr.second;
if (hdr.first == PICloud::TCP::InvalidType) {
piCoutObj << "invalid message";
disconnected(true);
@@ -76,34 +86,35 @@ void DispatcherClient::readed(PIByteArray & ba) {
if (authorised) {
if (hdr.second == tcp.role()) {
switch (hdr.first) {
case PICloud::TCP::Connect:
piCoutObj << "PICloud::TCP::Connect";
return;
case PICloud::TCP::Connect: piCoutObj << "PICloud::TCP::Connect"; return;
case PICloud::TCP::Disconnect:
piCoutObj << "PICloud::TCP::Disconnect";
disconnected(false);
return;
return;
case PICloud::TCP::Data:
//piCoutObj << "TCP::Data" << tcp.role();
// piCoutObj << "TCP::Data" << tcp.role();
if (tcp.role() == PICloud::TCP::Client) {
if (tcp.canParseData(ba)) dataReaded(ba);
else piCoutObj << "invalid data from client";
if (tcp.canParseData(ba))
dataReaded(ba);
else
piCoutObj << "invalid data from client";
}
if (tcp.role() == PICloud::TCP::Server) {
PIPair<uint, PIByteArray> dp = tcp.parseDataServer(ba);
if (!dp.second.isEmpty()) dataReadedServer(dp.first, dp.second);
else piCoutObj << "invalid data from server";
if (!dp.second.isEmpty())
dataReadedServer(dp.first, dp.second);
else
piCoutObj << "invalid data from server";
}
return;
case PICloud::TCP::Ping:
pingReceived();
return;
case PICloud::TCP::Ping: pingReceived(); return;
default:
piCoutObj << "unknown data";
//disconnected(true);
return;
// disconnected(true);
return;
}
} else piCoutObj << "invalid role";
} else
piCoutObj << "invalid role";
} else {
switch (hdr.first) {
case PICloud::TCP::Connect: {
@@ -116,12 +127,11 @@ void DispatcherClient::readed(PIByteArray & ba) {
case PICloud::TCP::Disconnect:
piCoutObj << "unauthorised PICloud::TCP::Disconnect";
disconnected(false);
return;
return;
default:
piCoutObj << "authorised invalid message";
disconnected(true);
return;
return;
}
}
}

View File

@@ -1,13 +1,14 @@
#ifndef DISPATCHERCLIENT_H
#define DISPATCHERCLIENT_H
#include "piethernet.h"
#include "picloudtcp.h"
#include "piethernet.h"
#include "pistreampacker.h"
class DispatcherClient: public PIObject {
PIOBJECT(DispatcherClient)
public:
DispatcherClient(PIEthernet * eth_, int id);
~DispatcherClient();
@@ -18,10 +19,10 @@ 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();}
bool isAuthorised() const { return authorised; }
PICloud::TCP::Role role() const { return tcp.role(); }
PIString address();
uint clientId() const {return client_id;}
uint clientId() const { return client_id; }
EVENT1(disconnectEvent, DispatcherClient *, client)
EVENT2(registerServer, const PIByteArray &, sname, DispatcherClient *, client)
EVENT2(registerClient, const PIByteArray &, sname, DispatcherClient *, client)

View File

@@ -1,13 +1,14 @@
#include "dispatcherserver.h"
#include "piscreentiles.h"
DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::TCP_Server) {
client_gid = 0;
DispatcherServer::DispatcherServer(PIEthernet::Address addr): eth(PIEthernet::TCP_Server) {
client_gid = 0;
max_connections = 1000;
eth.setParameter(PIEthernet::ReuseAddress);
eth.setReadAddress(addr);
// eth.setDebug(false);
// eth.setDebug(false);
CONNECTU(&eth, newConnection, this, newConnection);
CONNECTU(&timeout_timer, tickEvent, this, cleanClients);
}
@@ -15,7 +16,7 @@ DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::T
DispatcherServer::~DispatcherServer() {
eth.close();
//piCoutObj << "server stoped";
// piCoutObj << "server stoped";
}
@@ -35,7 +36,7 @@ void DispatcherServer::picoutStatus() {
}
piCout << "Servers:";
auto it = c_servers.makeIterator();
while(it.next()){
while (it.next()) {
piCout << " " << it.key();
it.value()->printStatus();
}
@@ -52,14 +53,15 @@ void DispatcherServer::cleanClients() {
for (auto c: clients) {
if (!index_c_servers.contains(c) && !index_c_clients.contains(c)) {
if (!rm_clients.contains(c)) rm_clients << c;
} else rm_clients.removeAll(c);
} else
rm_clients.removeAll(c);
}
auto ss = c_servers.values();
for (auto c: ss) {
if (c->lastPing() > 15.0) {
piCout << "remove Server by ping timeout" << c->getConnection()->clientId();
PIVector<DispatcherClient *> cscv = c->getClients();
for(auto csc : cscv) {
for (auto csc: cscv) {
clients.removeAll(csc);
index_c_clients.remove(csc);
c->removeClient(csc);
@@ -79,7 +81,7 @@ void DispatcherServer::cleanClients() {
}
for (auto c: rmrf_clients) {
clients.removeAll(c);
if(index_c_servers.contains(c)) {
if (index_c_servers.contains(c)) {
c_servers.remove(c_servers.key(index_c_servers[c]));
index_c_servers.remove(c);
}
@@ -96,18 +98,17 @@ void DispatcherServer::updateConnectionsTile(TileList * tl) {
for (auto c: clients) {
PIString role = "Invalid";
switch (c->role()) {
case PICloud::TCP::Client : {
role = "Client";
case PICloud::TCP::Client: {
role = "Client";
CloudServer * cs = index_c_clients.value(c, nullptr);
if (cs) role += " \"" + cs->serverUUID().toHex().left(8) + "...\"";
} break;
case PICloud::TCP::Server : {
role = "Server";
case PICloud::TCP::Server: {
role = "Server";
CloudServer * cs = index_c_servers.value(c, nullptr);
if (cs) role += " \"" + cs->serverUUID().toHex().left(8) + "...\"";
} break;
default:
break;
default: break;
}
tl->content << TileList::Row(c->address() + " " + role, PIScreenTypes::CellFormat());
}
@@ -126,7 +127,9 @@ void DispatcherServer::updateServersTile(TileList * tl, PISet<const DispatcherCl
tl->content.clear();
auto mi = c_servers.makeIterator();
while (mi.next()) {
tl->content << TileList::Row(mi.value()->serverUUID().toHex().left(8) + "... - " + PIString::fromNumber(mi.value()->getClients().size()), PIScreenTypes::CellFormat());
tl->content << TileList::Row(mi.value()->serverUUID().toHex().left(8) + "... - " +
PIString::fromNumber(mi.value()->getClients().size()),
PIScreenTypes::CellFormat());
if (servers.contains(mi.value()->getConnection())) tl->selected << (tl->content.size_s() - 1);
}
map_mutex.unlock();
@@ -138,7 +141,7 @@ void DispatcherServer::updateClientsTile(TileList * tl, PISet<const DispatcherCl
tl->content.clear();
auto mi = c_servers.makeIterator();
while (mi.next()) {
for (auto c : mi.value()->getClients()) {
for (auto c: mi.value()->getClients()) {
if (servers.isEmpty() || servers.contains(mi.value()->getConnection()))
tl->content << TileList::Row(c->address(), PIScreenTypes::CellFormat());
}
@@ -150,7 +153,7 @@ void DispatcherServer::updateClientsTile(TileList * tl, PISet<const DispatcherCl
const DispatcherClient * DispatcherServer::getConnection(int index) {
const DispatcherClient * ret = nullptr;
map_mutex.lock();
if (index >=0 && index < clients.size_s()) ret = clients[index];
if (index >= 0 && index < clients.size_s()) ret = clients[index];
map_mutex.unlock();
return ret;
}
@@ -159,7 +162,7 @@ const DispatcherClient * DispatcherServer::getConnection(int index) {
const DispatcherClient * DispatcherServer::getServer(int index) {
const DispatcherClient * ret = nullptr;
map_mutex.lock();
if (index >=0 && index < clients.size_s()) {
if (index >= 0 && index < clients.size_s()) {
if (index_c_servers.contains(clients[index])) ret = clients[index];
}
map_mutex.unlock();
@@ -171,7 +174,7 @@ PISet<const DispatcherClient *> DispatcherServer::getServers(PISet<int> ids) {
PISet<const DispatcherClient *> ret;
if (ids.isEmpty()) return ret;
map_mutex.lock();
int i = 0;
int i = 0;
auto mi = c_servers.makeIterator();
while (mi.next()) {
if (ids.contains(i)) ret << mi.value()->getConnection();
@@ -187,9 +190,9 @@ void DispatcherServer::setMaxConnections(uint max_count) {
}
void DispatcherServer::disconnectClient(DispatcherClient *client) {
void DispatcherServer::disconnectClient(DispatcherClient * client) {
if (!clients.contains(client)) {
//piCoutObj << "INVALID client" << client;
// piCoutObj << "INVALID client" << client;
return;
}
piCoutObj << "remove ..." << client->clientId();
@@ -200,7 +203,7 @@ void DispatcherServer::disconnectClient(DispatcherClient *client) {
if (cs) {
piCoutObj << "remove Server" << client->clientId();
PIVector<DispatcherClient *> cscv = cs->getClients();
for(auto csc : cscv) {
for (auto csc: cscv) {
clients.removeAll(csc);
index_c_clients.remove(csc);
cs->removeClient(csc);
@@ -217,21 +220,21 @@ void DispatcherServer::disconnectClient(DispatcherClient *client) {
cc->removeClient(client);
index_c_clients.remove(client);
}
//client->close();
// client->close();
rmrf_clients << client;
map_mutex.unlock();
piCoutObj << "remove done" << client->clientId();
}
void DispatcherServer::newConnection(PIEthernet *cl) {
void DispatcherServer::newConnection(PIEthernet * cl) {
if (clients.size() >= max_connections) {
delete cl;
return;
}
DispatcherClient * client = new DispatcherClient(cl, client_gid++);
CONNECTU(client, disconnectEvent, this, disconnectClient);
CONNECTL(client, registerServer, [this](const PIByteArray & sname, DispatcherClient * c){
CONNECTL(client, registerServer, [this](const PIByteArray & sname, DispatcherClient * c) {
map_mutex.lock();
CloudServer * cs = c_servers.value(sname, nullptr);
if (cs) {
@@ -246,7 +249,7 @@ void DispatcherServer::newConnection(PIEthernet *cl) {
}
map_mutex.unlock();
});
CONNECTL(client, registerClient, [this](const PIByteArray & sname, DispatcherClient * c){
CONNECTL(client, registerClient, [this](const PIByteArray & sname, DispatcherClient * c) {
map_mutex.lock();
CloudServer * cs = c_servers.value(sname, nullptr);
if (cs) {
@@ -260,7 +263,7 @@ void DispatcherServer::newConnection(PIEthernet *cl) {
}
map_mutex.unlock();
});
//piCoutObj << "add client" << client;
// piCoutObj << "add client" << client;
map_mutex.lock();
clients.push_back(client);
map_mutex.unlock();

View File

@@ -8,6 +8,7 @@ class TileList;
class DispatcherServer: public PIObject {
PIOBJECT(DispatcherServer)
public:
DispatcherServer(PIEthernet::Address addr);
~DispatcherServer();
@@ -20,21 +21,21 @@ public:
const DispatcherClient * getServer(int index);
PISet<const DispatcherClient *> getServers(PISet<int> ids);
void setMaxConnections(uint max_count);
uint maxConnections() const {return max_connections;}
uint maxConnections() const { return max_connections; }
EVENT_HANDLER0(void, picoutStatus);
private:
EVENT_HANDLER1(void, newConnection, PIEthernet * , cl);
EVENT_HANDLER1(void, newConnection, PIEthernet *, cl);
EVENT_HANDLER1(void, disconnectClient, DispatcherClient *, client);
EVENT_HANDLER0(void, cleanClients);
PIEthernet eth;
PIVector<DispatcherClient*> clients;
PIVector<DispatcherClient *> clients;
PIMap<PIByteArray, CloudServer *> c_servers;
PIMap<const DispatcherClient *, CloudServer *> index_c_servers;
PIMap<const DispatcherClient *, CloudServer *> index_c_clients;
PIVector<DispatcherClient*> rm_clients;
PIVector<DispatcherClient*> rmrf_clients;
PIVector<DispatcherClient *> rm_clients;
PIVector<DispatcherClient *> rmrf_clients;
PITimer timeout_timer;
PIMutex map_mutex;
uint client_gid;

View File

@@ -1,156 +1,159 @@
/*
PIP - Platform Independent Primitives
PICloud dispatcher
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pip.h"
#include "picrypt.h"
#include "piiostream.h"
#include "dispatcherserver.h"
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Cloud Dispatcher";
piCout << Cyan << "Version" << Bold << PIPVersion() << 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)";
}
PIString confDir() {
return
#ifdef WINDOWS
PIDir::home().path() + "/AppData/Local"
#elif defined(MAC_OS)
PIDir::home().path() + "/Library/Preferences"
#elif defined(ANDROID)
PIString(".")
#else
PIDir::home().path() + "/.config"
#endif
+ "/SHS";
}
int main (int argc, char * argv[]) {
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;
}
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
PIString conf_path = confDir();
PIDir::make(conf_path);
conf_path += "/picloud.conf";
uint max_connections = 1000;
if (!PIFile::isExists(conf_path)) {
PIFile f(conf_path, PIIODevice::ReadWrite);
PIIOTextStream ts(&f);
ts << "ip = " << addr.ipString() << "\n"
<< "port = " << addr.port() << "\n"
<< "max_connections = " << max_connections << "\n";
}
{
PIConfig conf(conf_path, PIIODevice::ReadOnly);
addr.setIP(conf.getValue("ip", addr.ipString()).toString());
addr.setPort(conf.getValue("port", addr.port()).toUShort());
max_connections = conf.getValue("max_connections", max_connections).toUInt();
}
PITimer status_timer;
if (cli.hasArgument("ip"))
addr.setIP(cli.argumentValue("ip"));
if (cli.hasArgument("port"))
addr.setPort(cli.argumentValue("port").toInt());
DispatcherServer server(addr);
server.setMaxConnections(max_connections);
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;
}
/*
PIP - Platform Independent Primitives
PICloud dispatcher
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dispatcherserver.h"
#include "picrypt.h"
#include "piiostream.h"
#include "pip.h"
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Cloud Dispatcher";
piCout << Cyan << "Version" << Bold << PIPVersion() << 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)";
}
PIString confDir() {
return
#ifdef WINDOWS
PIDir::home().path() + "/AppData/Local"
#elif defined(MAC_OS)
PIDir::home().path() + "/Library/Preferences"
#elif defined(ANDROID)
PIString(".")
#else
PIDir::home().path() + "/.config"
#endif
+ "/SHS";
}
int main(int argc, char * argv[]) {
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;
}
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
PIString conf_path = confDir();
PIDir::make(conf_path);
conf_path += "/picloud.conf";
uint max_connections = 1000;
if (!PIFile::isExists(conf_path)) {
PIFile f(conf_path, PIIODevice::ReadWrite);
PIIOTextStream ts(&f);
ts << "ip = " << addr.ipString() << "\n"
<< "port = " << addr.port() << "\n"
<< "max_connections = " << max_connections << "\n";
}
{
PIConfig conf(conf_path, PIIODevice::ReadOnly);
addr.setIP(conf.getValue("ip", addr.ipString()).toString());
addr.setPort(conf.getValue("port", addr.port()).toUShort());
max_connections = conf.getValue("max_connections", max_connections).toUInt();
}
PITimer status_timer;
if (cli.hasArgument("ip")) addr.setIP(cli.argumentValue("ip"));
if (cli.hasArgument("port")) addr.setPort(cli.argumentValue("port").toInt());
DispatcherServer server(addr);
server.setMaxConnections(max_connections);
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;
}

View File

@@ -1,600 +1,645 @@
/*
PIP - Platform Independent Primitives
Code model generator
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picli.h"
#include "picodeparser.h"
#include "piiostream.h"
#include <iostream>
using namespace PICoutManipulators;
PICodeParser parser;
const char help_string[] =
"-M (Metainfo)\n"
"Generate classes and structs info. It contains\n"
"names, subclass info, all methods and variables.\n"
"Place information:\n"
" * classes and structs - PICodeInfo::classesInfo\n"
" * methods - ClassInfo::functions\n"
" * variables - ClassInfo::variables\n"
"\n"
"-E (Enums)\n"
"Generate enumeration descriptions.\n"
"Useful for GUI integrations, because\n"
"you can obtain enumerators value and name.\n"
" * enums - PICodeInfo::enumsInfo\n"
"\n"
"-S (Stream operators)\n"
"Generate store/restore operators with format\n"
"BINARY_STREAM_WRITE(<type>);\n"
"BINARY_STREAM_READ (<type>);\n"
"Only public variables used. All variables stored/restored\n"
"using PIChunkStream. IDs are variable number, starting from 1.\n"
"You can override ID with PIMETA(id=<ID>). If in class or struct\n"
"PIMETA(simple-stream) presence, then variables stored/restored\n"
"with simple << and >> operators.\n"
"If PIMETA(no-stream) presence, then class or struct ignored.\n"
"\n"
"-G (Getter functions)\n"
"Generate anonymous access methods for member typenames and values.\n"
"Every class or struct member typename can be obtained with:\n"
"const char * getMemberType(const char * class_name, const char * member_name)\n"
"Member value can be obtained with:\n"
"PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name)\n"
"where \"p\" - class or struct pointer, and returns serialized value.\n"
"PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n"
"where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
""
;
void header() {
piCout << Bold << "PIP Code model generator";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-hHqPpsAMESTG] -o <output_file> [-I<include_dir1>] [-I<include_dir1>] [...] [-D<define1>] [-D<define1>] [...] <file1> [<file2>] [<file3>] [...]\"" << NewLine;
}
void usage() {
header();
piCout << Green << Bold << "Details:";
piCout << Bold << "Debug control";
piCout << "-h " << Green << "- display this message and exit";
piCout << "-H " << Green << "- display details help";
piCout << "-q " << Green << "- quiet, no debug output to console";
piCout << "-P " << Green << "- print list of all parsed files to console before exit";
piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit";
piCout << "";
piCout << Bold << "Parsing control";
piCout << "-s " << Green << "- single file (don`t follow includes)";
piCout << "-I<include_dir> " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)";
piCout << "-D<define> " << Green << "- add define to preprocessor, macro PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)";
piCout << "";
piCout << Bold << "Output control";
piCout << "-A " << Green << "- write all";
piCout << "-M " << Green << "- write metainfo";
piCout << "-E " << Green << "- write enums";
piCout << "-S " << Green << "- write stream operators";
piCout << "-G " << Green << "- write getter functions";
//piCout << "-T " << Green << "- write text serialize functions";
piCout << "-o <output_file> " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)";
piCout << "";
piCout << Bold << "Input control";
piCout << "<file> " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")";
}
void help() {
header();
piCout << help_string;
}
void printError(const PIString & msg) {
std::cerr << msg.data() << std::endl;
}
PIString toCName(const PIString &s) {
PIString ret(s.trimmed());
if (ret.isEmpty()) return ret;
ret.replaceAll('<', '_').replaceAll('>', '_');
for (int i = 0; i < ret.size_s(); ++i) {
if (i == 0) {
if (!(ret[i].isAlpha() || ret[i].toAscii() == '_')) {ret.pop_front(); --i;}
} else {
if (!(ret[i].isAlpha() || ret[i].isDigit() || ret[i].toAscii() == '_')) {ret.remove(i); --i;}
}
}
ret.replaceAll("__", "_");
return ret;
}
void makeClassInfo(PIIOTextStream & ts, const PICodeParser::Entity * e) {
ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n";
ts << "\tci->type = \"" << e->type << "\";\n";
ts << "\tci->name = \"" << e->name << "\";\n";
ts << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
ts << "\t(*classesInfo)[ci->name] = ci;\n";
if (e->parent_scope) {
ts << "\tpci = " << "classesInfo->value(\"" << e->parent_scope->name << "\", 0);\n";
ts << "\tif (pci) pci->children_info << ci;\n";
}
for (const PICodeParser::Entity * p: e->parents)
ts << "\tci->parents << \"" << p->name << "\";\n";
if (!e->members.isEmpty()) ts << "\n\tTypeInfo ti;\n";
for (const PICodeParser::Member & m: e->members) {
ts << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
if (m.attributes != 0) {
bool fir = true;
ts << ", ";
if (m.attributes[PICodeParser::Const ]) {if (fir) fir = false; else ts << " | "; ts << "Const";}
if (m.attributes[PICodeParser::Static ]) {if (fir) fir = false; else ts << " | "; ts << "Static";}
if (m.attributes[PICodeParser::Mutable ]) {if (fir) fir = false; else ts << " | "; ts << "Mutable";}
if (m.attributes[PICodeParser::Volatile]) {if (fir) fir = false; else ts << " | "; ts << "Volatile";}
if (m.attributes[PICodeParser::Inline ]) {if (fir) fir = false; else ts << " | "; ts << "Inline";}
if (m.attributes[PICodeParser::Virtual ]) {if (fir) fir = false; else ts << " | "; ts << "Virtual";}
} else {
if (m.isBitfield())
ts << ", 0";
}
if (m.isBitfield())
ts << ", " << m.bits;
ts << ");\n";
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
ts << "\tti.meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
ts << "\tci->variables << ti;\n";
}
PIString arg;
bool has_fi = false;
for (const PICodeParser::Member & m: e->functions) {
if (e->name.findCWord(m.name) >= 0) continue;
if (!has_fi)
ts << "\n\tFunctionInfo * fi;\n";
has_fi = true;
ts << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n";
ts << "\tfi->name = \"" << m.name << "\";";
ts << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\"";
if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) {
bool fir = true;
ts << ", ";
if (m.attributes[PICodeParser::Const ]) {if (fir) fir = false; else ts << " | "; ts << "Const";}
if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else ts << " | "; ts << "Static";}
}
ts << ");\n";
//piCout << "write func" << m.name;
for (const PIString & a: m.arguments_full) {
//piCout << "write arg" << a;
ts << "\tfi->arguments << TypeInfo(";
arg = a;
bool con = false;
arg.prepend(" ");
if (arg.find(" const ") >= 0) {
arg.replaceAll(" const ", " ");
con = true;
}
arg.trim();
int i = 0;
for (i = arg.size_s() - 1; i > 0; --i)
if (!_isCChar(arg[i]) && !(arg[i].isDigit())) break;
ts << "\"" << arg.takeRight(arg.size_s() - i - 1).trim() << "\", ";
ts << "\"" << arg.trim() << "\"";
if (con) ts << ", Const";
ts << ");\n";
}
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
ts << "\tfi->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
ts << "\n\t}";
}
void makeEnumInfo(PIIOTextStream & ts, const PICodeParser::Enum * e) {
if (e->name.isEmpty()) {
ts << "\n\tei = (*enumsInfo)[\"\"];\n";
} else {
ts << "\n\tei = new EnumInfo();\n";
ts << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n";
ts << "\tei->name = \"" << e->name << "\";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
ts << "\tei->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
for (const PICodeParser::EnumeratorInfo & m: e->members) {
ts << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n";
if (!m.meta.isEmpty()) {
auto i = m.meta.makeIterator();
while (i.next())
ts << "\tei->members.back().meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
}
bool writeClassStreamMembersOut(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
PISet<int> used_id;
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield())
continue;
if (m.meta.value("id") == "-") continue;
++cnt;
if (m.meta.contains("id"))
cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
return false;
}
if (m.dims.isEmpty()) {
if (simple) {
ts << "\ts << ";
if (parser.isEnum(m.type))
ts << "(int)";
ts << "v." << m.name << ";\n";
} else {
ts << "\tcs << cs.chunk(" << cnt << ", ";
if (parser.isEnum(m.type))
ts << "(int)";
ts << "v." << m.name << ");\n";
}
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
if (simple) {
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
ts << "\t\ts << ((const " << ptype << " *)(v." << m.name << "))[i];\n";
} else {
ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name << "), ";
ts << size << "));\n";
}
}
if (is_union)
break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersOut(ts, ce, cnt, simple)) return false;
}
return true;
}
bool writeClassStreamMembersIn(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
PISet<int> used_id;
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield())
continue;
if (m.meta.value("id") == "-") continue;
++cnt;
if (m.meta.contains("id"))
cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
return false;
}
used_id << cnt;
if (m.dims.isEmpty()) {
bool is_enum = parser.isEnum(m.type);
if (simple) {
ts << "\t";
if (is_enum) ts << "{int i; ";
ts << "s >> ";
if (is_enum) ts << "i;";
else ts << "v." << m.name << ";";
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
ts << "\n";
} else {
ts << "\t\tcase " << cnt << ":";
if (is_enum) ts << " {int i;";
ts << " cs.get(";
if (is_enum) ts << "i";
else ts << "v." << m.name;
ts << ");";
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
ts << " break;\n";
}
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
if (simple) {
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
ts << "\t\ts >> ((" << ptype << " *)(v." << m.name << "))[i];\n";
} else {
ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n";
ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n";
ts << "\t\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n";
ts << "\t\t\t}\n";
ts << "\t\t\tbreak;\n";
}
}
if (is_union)
break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersIn(ts, ce, cnt, simple)) return false;
}
return true;
}
bool needClassStream(const PICodeParser::Entity * e) {
if (e->meta.contains("no-stream")) return false;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
continue;
if (m.meta.value("id") == "-") continue;
return true;
}
return false;
}
bool makeClassStream(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return true;
bool simple = e->meta.contains("simple-stream");
ts << "\nBINARY_STREAM_WRITE(" << e->name << ") {\n";
if (!simple)
ts << "\tPIChunkStream cs;\n";
int cnt = 0;
if (!writeClassStreamMembersOut(ts, e, cnt, simple)) return false;
if (!simple)
ts << "\ts << cs.data();\n";
ts << "\treturn s;\n}\n";
ts << "BINARY_STREAM_READ (" << e->name << ") {\n";
if (!simple) {
//ts << "\tif (s.size_s() < 4) return s;\n";
ts << "\tPIByteArray csba; s >> csba;\n";
ts << "\tPIChunkStream cs(csba);\n";
ts << "\twhile (!cs.atEnd()) {\n";
ts << "\t\tswitch (cs.read()) {\n";
}
cnt = 0;
if (!writeClassStreamMembersIn(ts, e, cnt, simple)) return false;
if (!simple)
ts << "\t\t}\n\t}\n";
ts << "\treturn s;\n}\n";
return true;
}
void makeGetterType(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return;
ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
ts << "\tif (!name) return \"\";\n";
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
continue;
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) return \"" << m.type << "\";\n";
}
ts << "\treturn \"\";\n}\n";
}
void makeGetterValue(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return;
ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
ts << "\tPIByteArray ret;\n";
ts << "\tif (!p || !name) return ret;\n";
ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n";
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
continue;
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
}
ts << "\treturn ret;\n}\n";
}
bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool meta, bool enums, bool streams, bool texts, bool getters) {
PIString defname = "CCM_" + PIString::fromNumber(out.hash()) + "_H";
PISet<PIString> inc_files;
for (const PICodeParser::Entity * e: parser.entities)
if (!e->name.startsWith("_PI"))
inc_files << e->file;
PIString inc_string;
PIVector<PIString> incf = inc_files.toVector();
for (const PIString & i: incf) {
if ((i != parser.mainFile()) && (streams || texts || getters))
inc_string += "\n#include \"" + i + "\"";
}
PIFile f(out + ".cpp");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
return false;
}
PIIOTextStream ts(&f);
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
ts << "#include <string.h>\n";
ts << "#include \"" << out << ".h\"\n";
ts << "\nusing namespace PICodeInfo;\n";
if (meta || enums || getters) {
if (getters) {
ts << "\n\n// Getter funtions\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI")) continue;
makeGetterType(ts, e);
makeGetterValue(ts, e);
}
}
ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
ts << "\tif (_inited_) return;\n\t_inited_ = true;\n\n";
if (meta) {
ts << "\tClassInfo * pci = new ClassInfo();\n";
ts << "\t(*classesInfo)[\"\"] = pci;\n";
}
if (enums && !parser.enums.isEmpty()) {
ts << "\tEnumInfo * ei;\n";
ts << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n";
}
if (meta) {
ts << "\n\n// Classes\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (e->name.startsWith("_PI")) continue;
makeClassInfo(ts, e);
}
}
if (enums) {
ts << "\n// Enums\n";
for (const PICodeParser::Enum & e: parser.enums)
makeEnumInfo(ts, &e);
}
if (getters) {
ts << "\n// Getters\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!needClassStream(e)) continue;
if (!e->has_name || e->name.startsWith("_PI")) continue;
ts << "\t(*accessValueFunctions)[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n";
ts << "\t(*accessTypeFunctions)[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n";
}
}
ts << "}\n";
ts << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n";
}
f.close();
f.setPath(out + ".h");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
return false;
}
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
ts << "// Execute command:\n";
for (const PIString & _a: cli.rawArguments())
ts << "// \"" << _a << "\"\n";
ts << "\n";
ts << "#ifndef " << defname << "\n#define " << defname << "\n\n";
ts << "#include <pivariant.h>\n#include <picodeinfo.h>";
if (streams || texts)
ts << "\n#include <pichunkstream.h>";
ts << inc_string << "\n";
if (streams) {
ts << "\n\n// Stream operators\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI") ||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public)) continue;
if (!makeClassStream(ts, e))
return false;
}
}
if (meta || enums || getters) {
ts << "\n\n// Metainformation\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n";
ts << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n";
ts << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n";
}
ts << "\n\n#endif // " << defname << "\n";
f.close();
return true;
}
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
//piCout << cli.rawArguments();
cli.setOptionalArgumentsCount(-1);
cli.addArgument("output", true);
cli.addArgument("help");
cli.addArgument("Help");
cli.addArgument("quiet");
cli.addArgument("All");
cli.addArgument("Metainfo");
cli.addArgument("Enum");
cli.addArgument("Stream");
cli.addArgument("Getter");
cli.addArgument("Text");
cli.addArgument("print");
cli.addArgument("Print");
cli.addArgument("single");
if (cli.hasArgument("Help")) {
help();
return 0;
}
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) {
usage();
return 0;
}
piDebug = !cli.hasArgument("quiet");
for (const PIString & a: cli.rawArguments()) {
if (a.startsWith("-I")) parser.includeDirectory(a.mid(2));
if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString());
}
PIStringList files;
for (const PIString & a: cli.optionalArguments())
if (!a.startsWith("-")) files << a;
piCout << Cyan << Bold << "Parse files" << files << "...";
parser.parseFiles(files, !cli.hasArgument("single"));
piCout << Cyan << Bold << "Parsing done";
piCout << Cyan << Bold << "Writing code model ...";
bool all = cli.hasArgument("All");
if (!writeModel(parser, cli, cli.argumentValue("output"), cli.hasArgument("Metainfo") || all,
cli.hasArgument("Enum") || all,
cli.hasArgument("Stream") || all,
cli.hasArgument("Text") || all,
cli.hasArgument("Getter") || all))
return 1;
piCout << Cyan << Bold << "Writing done";
if (cli.hasArgument("print") || cli.hasArgument("Print")) {
bool womain = cli.hasArgument("print");
piDebug = true;
PIStringList pf(parser.parsedFiles());
for (const PIString & f: pf) {
if (!womain || (f != parser.mainFile()))
piCout << f;
}
}
return 0;
}
/*
PIP - Platform Independent Primitives
Code model generator
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picli.h"
#include "picodeparser.h"
#include "piiostream.h"
#include <iostream>
using namespace PICoutManipulators;
PICodeParser parser;
const char help_string[] = "-M (Metainfo)\n"
"Generate classes and structs info. It contains\n"
"names, subclass info, all methods and variables.\n"
"Place information:\n"
" * classes and structs - PICodeInfo::classesInfo\n"
" * methods - ClassInfo::functions\n"
" * variables - ClassInfo::variables\n"
"\n"
"-E (Enums)\n"
"Generate enumeration descriptions.\n"
"Useful for GUI integrations, because\n"
"you can obtain enumerators value and name.\n"
" * enums - PICodeInfo::enumsInfo\n"
"\n"
"-S (Stream operators)\n"
"Generate store/restore operators with format\n"
"BINARY_STREAM_WRITE(<type>);\n"
"BINARY_STREAM_READ (<type>);\n"
"Only public variables used. All variables stored/restored\n"
"using PIChunkStream. IDs are variable number, starting from 1.\n"
"You can override ID with PIMETA(id=<ID>). If in class or struct\n"
"PIMETA(simple-stream) presence, then variables stored/restored\n"
"with simple << and >> operators.\n"
"If PIMETA(no-stream) presence, then class or struct ignored.\n"
"\n"
"-G (Getter functions)\n"
"Generate anonymous access methods for member typenames and values.\n"
"Every class or struct member typename can be obtained with:\n"
"const char * getMemberType(const char * class_name, const char * member_name)\n"
"Member value can be obtained with:\n"
"PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name)\n"
"where \"p\" - class or struct pointer, and returns serialized value.\n"
"PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n"
"where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
"";
void header() {
piCout << Bold << "PIP Code model generator";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default
<< "\"pip_cmg [-hHqPpsAMESTG] -o <output_file> [-I<include_dir1>] [-I<include_dir1>] [...] [-D<define1>] [-D<define1>] [...] "
"<file1> [<file2>] [<file3>] [...]\""
<< NewLine;
}
void usage() {
header();
piCout << Green << Bold << "Details:";
piCout << Bold << "Debug control";
piCout << "-h " << Green << "- display this message and exit";
piCout << "-H " << Green << "- display details help";
piCout << "-q " << Green << "- quiet, no debug output to console";
piCout << "-P " << Green << "- print list of all parsed files to console before exit";
piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit";
piCout << "";
piCout << Bold << "Parsing control";
piCout << "-s " << Green << "- single file (don`t follow includes)";
piCout << "-I<include_dir> " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)";
piCout << "-D<define> " << Green
<< "- add define to preprocessor, macro PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)";
piCout << "";
piCout << Bold << "Output control";
piCout << "-A " << Green << "- write all";
piCout << "-M " << Green << "- write metainfo";
piCout << "-E " << Green << "- write enums";
piCout << "-S " << Green << "- write stream operators";
piCout << "-G " << Green << "- write getter functions";
// piCout << "-T " << Green << "- write text serialize functions";
piCout << "-o <output_file> " << Green
<< "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)";
piCout << "";
piCout << Bold << "Input control";
piCout << "<file> " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")";
}
void help() {
header();
piCout << help_string;
}
void printError(const PIString & msg) {
std::cerr << msg.data() << std::endl;
}
PIString toCName(const PIString & s) {
PIString ret(s.trimmed());
if (ret.isEmpty()) return ret;
ret.replaceAll('<', '_').replaceAll('>', '_');
for (int i = 0; i < ret.size_s(); ++i) {
if (i == 0) {
if (!(ret[i].isAlpha() || ret[i].toAscii() == '_')) {
ret.pop_front();
--i;
}
} else {
if (!(ret[i].isAlpha() || ret[i].isDigit() || ret[i].toAscii() == '_')) {
ret.remove(i);
--i;
}
}
}
ret.replaceAll("__", "_");
return ret;
}
void makeClassInfo(PIIOTextStream & ts, const PICodeParser::Entity * e) {
ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n";
ts << "\tci->type = \"" << e->type << "\";\n";
ts << "\tci->name = \"" << e->name << "\";\n";
ts << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
ts << "\t(*classesInfo)[ci->name] = ci;\n";
if (e->parent_scope) {
ts << "\tpci = "
<< "classesInfo->value(\"" << e->parent_scope->name << "\", 0);\n";
ts << "\tif (pci) pci->children_info << ci;\n";
}
for (const PICodeParser::Entity * p: e->parents)
ts << "\tci->parents << \"" << p->name << "\";\n";
if (!e->members.isEmpty()) ts << "\n\tTypeInfo ti;\n";
for (const PICodeParser::Member & m: e->members) {
ts << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
if (m.attributes != 0) {
bool fir = true;
ts << ", ";
if (m.attributes[PICodeParser::Const]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Const";
}
if (m.attributes[PICodeParser::Static]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Static";
}
if (m.attributes[PICodeParser::Mutable]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Mutable";
}
if (m.attributes[PICodeParser::Volatile]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Volatile";
}
if (m.attributes[PICodeParser::Inline]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Inline";
}
if (m.attributes[PICodeParser::Virtual]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Virtual";
}
} else {
if (m.isBitfield()) ts << ", 0";
}
if (m.isBitfield()) ts << ", " << m.bits;
ts << ");\n";
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
ts << "\tti.meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
ts << "\tci->variables << ti;\n";
}
PIString arg;
bool has_fi = false;
for (const PICodeParser::Member & m: e->functions) {
if (e->name.findCWord(m.name) >= 0) continue;
if (!has_fi) ts << "\n\tFunctionInfo * fi;\n";
has_fi = true;
ts << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n";
ts << "\tfi->name = \"" << m.name << "\";";
ts << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\"";
if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) {
bool fir = true;
ts << ", ";
if (m.attributes[PICodeParser::Const]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Const";
}
if (m.attributes[PICodeParser::Static]) {
if (fir)
fir = false;
else
ts << " | ";
ts << "Static";
}
}
ts << ");\n";
// piCout << "write func" << m.name;
for (const PIString & a: m.arguments_full) {
// piCout << "write arg" << a;
ts << "\tfi->arguments << TypeInfo(";
arg = a;
bool con = false;
arg.prepend(" ");
if (arg.find(" const ") >= 0) {
arg.replaceAll(" const ", " ");
con = true;
}
arg.trim();
int i = 0;
for (i = arg.size_s() - 1; i > 0; --i)
if (!_isCChar(arg[i]) && !(arg[i].isDigit())) break;
ts << "\"" << arg.takeRight(arg.size_s() - i - 1).trim() << "\", ";
ts << "\"" << arg.trim() << "\"";
if (con) ts << ", Const";
ts << ");\n";
}
if (!m.meta.isEmpty()) {
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
ts << "\tfi->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
ts << "\n\t}";
}
void makeEnumInfo(PIIOTextStream & ts, const PICodeParser::Enum * e) {
if (e->name.isEmpty()) {
ts << "\n\tei = (*enumsInfo)[\"\"];\n";
} else {
ts << "\n\tei = new EnumInfo();\n";
ts << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n";
ts << "\tei->name = \"" << e->name << "\";\n";
if (!e->meta.isEmpty()) {
auto i = e->meta.makeIterator();
while (i.next())
ts << "\tei->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
for (const PICodeParser::EnumeratorInfo & m: e->members) {
ts << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n";
if (!m.meta.isEmpty()) {
auto i = m.meta.makeIterator();
while (i.next())
ts << "\tei->members.back().meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
}
}
}
bool writeClassStreamMembersOut(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
PISet<int> used_id;
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue;
if (m.meta.value("id") == "-") continue;
++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
return false;
}
if (m.dims.isEmpty()) {
if (simple) {
ts << "\ts << ";
if (parser.isEnum(m.type)) ts << "(int)";
ts << "v." << m.name << ";\n";
} else {
ts << "\tcs << cs.chunk(" << cnt << ", ";
if (parser.isEnum(m.type)) ts << "(int)";
ts << "v." << m.name << ");\n";
}
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
if (simple) {
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
ts << "\t\ts << ((const " << ptype << " *)(v." << m.name << "))[i];\n";
} else {
ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name << "), ";
ts << size << "));\n";
}
}
if (is_union) break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersOut(ts, ce, cnt, simple)) return false;
}
return true;
}
bool writeClassStreamMembersIn(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
PISet<int> used_id;
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue;
if (m.meta.value("id") == "-") continue;
++cnt;
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (used_id[cnt]) {
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
return false;
}
used_id << cnt;
if (m.dims.isEmpty()) {
bool is_enum = parser.isEnum(m.type);
if (simple) {
ts << "\t";
if (is_enum) ts << "{int i; ";
ts << "s >> ";
if (is_enum)
ts << "i;";
else
ts << "v." << m.name << ";";
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
ts << "\n";
} else {
ts << "\t\tcase " << cnt << ":";
if (is_enum) ts << " {int i;";
ts << " cs.get(";
if (is_enum)
ts << "i";
else
ts << "v." << m.name;
ts << ");";
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
ts << " break;\n";
}
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
if (simple) {
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
ts << "\t\ts >> ((" << ptype << " *)(v." << m.name << "))[i];\n";
} else {
ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n";
ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n";
ts << "\t\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n";
ts << "\t\t\t}\n";
ts << "\t\t\tbreak;\n";
}
}
if (is_union) break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassStreamMembersIn(ts, ce, cnt, simple)) return false;
}
return true;
}
bool needClassStream(const PICodeParser::Entity * e) {
if (e->meta.contains("no-stream")) return false;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
if (m.meta.value("id") == "-") continue;
return true;
}
return false;
}
bool makeClassStream(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return true;
bool simple = e->meta.contains("simple-stream");
ts << "\nBINARY_STREAM_WRITE(" << e->name << ") {\n";
if (!simple) ts << "\tPIChunkStream cs;\n";
int cnt = 0;
if (!writeClassStreamMembersOut(ts, e, cnt, simple)) return false;
if (!simple) ts << "\ts << cs.data();\n";
ts << "\treturn s;\n}\n";
ts << "BINARY_STREAM_READ (" << e->name << ") {\n";
if (!simple) {
// ts << "\tif (s.size_s() < 4) return s;\n";
ts << "\tPIByteArray csba; s >> csba;\n";
ts << "\tPIChunkStream cs(csba);\n";
ts << "\twhile (!cs.atEnd()) {\n";
ts << "\t\tswitch (cs.read()) {\n";
}
cnt = 0;
if (!writeClassStreamMembersIn(ts, e, cnt, simple)) return false;
if (!simple) ts << "\t\t}\n\t}\n";
ts << "\treturn s;\n}\n";
return true;
}
void makeGetterType(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return;
ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
ts << "\tif (!name) return \"\";\n";
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) return \"" << m.type << "\";\n";
}
ts << "\treturn \"\";\n}\n";
}
void makeGetterValue(PIIOTextStream & ts, const PICodeParser::Entity * e) {
if (!needClassStream(e)) return;
ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
ts << "\tPIByteArray ret;\n";
ts << "\tif (!p || !name) return ret;\n";
ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n";
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
}
ts << "\treturn ret;\n}\n";
}
bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool meta, bool enums, bool streams, bool texts, bool getters) {
PIString defname = "CCM_" + PIString::fromNumber(out.hash()) + "_H";
PISet<PIString> inc_files;
for (const PICodeParser::Entity * e: parser.entities)
if (!e->name.startsWith("_PI")) inc_files << e->file;
PIString inc_string;
PIVector<PIString> incf = inc_files.toVector();
for (const PIString & i: incf) {
if ((i != parser.mainFile()) && (streams || texts || getters)) inc_string += "\n#include \"" + i + "\"";
}
PIFile f(out + ".cpp");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
return false;
}
PIIOTextStream ts(&f);
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
ts << "#include <string.h>\n";
ts << "#include \"" << out << ".h\"\n";
ts << "\nusing namespace PICodeInfo;\n";
if (meta || enums || getters) {
if (getters) {
ts << "\n\n// Getter funtions\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI")) continue;
makeGetterType(ts, e);
makeGetterValue(ts, e);
}
}
ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
ts << "\tif (_inited_) return;\n\t_inited_ = true;\n\n";
if (meta) {
ts << "\tClassInfo * pci = new ClassInfo();\n";
ts << "\t(*classesInfo)[\"\"] = pci;\n";
}
if (enums && !parser.enums.isEmpty()) {
ts << "\tEnumInfo * ei;\n";
ts << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n";
}
if (meta) {
ts << "\n\n// Classes\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (e->name.startsWith("_PI")) continue;
makeClassInfo(ts, e);
}
}
if (enums) {
ts << "\n// Enums\n";
for (const PICodeParser::Enum & e: parser.enums)
makeEnumInfo(ts, &e);
}
if (getters) {
ts << "\n// Getters\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!needClassStream(e)) continue;
if (!e->has_name || e->name.startsWith("_PI")) continue;
ts << "\t(*accessValueFunctions)[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n";
ts << "\t(*accessTypeFunctions)[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n";
}
}
ts << "}\n";
ts << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n";
}
f.close();
f.setPath(out + ".h");
f.clear();
if (!f.open(PIIODevice::WriteOnly)) {
piCout << "Error: can`t open out file" << f.path();
return false;
}
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
ts << "// Execute command:\n";
for (const PIString & _a: cli.rawArguments())
ts << "// \"" << _a << "\"\n";
ts << "\n";
ts << "#ifndef " << defname << "\n#define " << defname << "\n\n";
ts << "#include <pivariant.h>\n#include <picodeinfo.h>";
if (streams || texts) ts << "\n#include <pichunkstream.h>";
ts << inc_string << "\n";
if (streams) {
ts << "\n\n// Stream operators\n";
for (const PICodeParser::Entity * e: parser.entities) {
if (!e->has_name || e->name.startsWith("_PI") ||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public))
continue;
if (!makeClassStream(ts, e)) return false;
}
}
if (meta || enums || getters) {
ts << "\n\n// Metainformation\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n";
ts << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n";
ts << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n";
}
ts << "\n\n#endif // " << defname << "\n";
f.close();
return true;
}
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
// piCout << cli.rawArguments();
cli.setOptionalArgumentsCount(-1);
cli.addArgument("output", true);
cli.addArgument("help");
cli.addArgument("Help");
cli.addArgument("quiet");
cli.addArgument("All");
cli.addArgument("Metainfo");
cli.addArgument("Enum");
cli.addArgument("Stream");
cli.addArgument("Getter");
cli.addArgument("Text");
cli.addArgument("print");
cli.addArgument("Print");
cli.addArgument("single");
if (cli.hasArgument("Help")) {
help();
return 0;
}
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) {
usage();
return 0;
}
piDebug = !cli.hasArgument("quiet");
for (const PIString & a: cli.rawArguments()) {
if (a.startsWith("-I")) parser.includeDirectory(a.mid(2));
if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString());
}
PIStringList files;
for (const PIString & a: cli.optionalArguments())
if (!a.startsWith("-")) files << a;
piCout << Cyan << Bold << "Parse files" << files << "...";
parser.parseFiles(files, !cli.hasArgument("single"));
piCout << Cyan << Bold << "Parsing done";
piCout << Cyan << Bold << "Writing code model ...";
bool all = cli.hasArgument("All");
if (!writeModel(parser,
cli,
cli.argumentValue("output"),
cli.hasArgument("Metainfo") || all,
cli.hasArgument("Enum") || all,
cli.hasArgument("Stream") || all,
cli.hasArgument("Text") || all,
cli.hasArgument("Getter") || all))
return 1;
piCout << Cyan << Bold << "Writing done";
if (cli.hasArgument("print") || cli.hasArgument("Print")) {
bool womain = cli.hasArgument("print");
piDebug = true;
PIStringList pf(parser.parsedFiles());
for (const PIString & f: pf) {
if (!womain || (f != parser.mainFile())) piCout << f;
}
}
return 0;
}

View File

@@ -1,121 +1,129 @@
/*
PIP - Platform Independent Primitives
Crypth / decrypth files utility
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pip.h"
#include "picrypt.h"
#include <stdio.h>
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Crypt Utility";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"picrypt [-thr] [-g <pass>] [-o <out_file>] [{[-c <file>] [-d <file>]} {[-p <pass>] [-s <hash>] [-k <key_file>] [-x <hex_key>]}]\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-g --genhash " << Green << "- generate hash from <pass> string";
piCout << "-t --text " << Green << "- output in text base64";
piCout << "-o --out <out_file> " << Green << "- write out to file <out_file>";
piCout << "-c --crypt <file> " << Green << "- crypt file <file> using secret <pass> or <hash> or <key_file>";
piCout << "-d --decrypt <file> " << Green << "- decrypt file <file> using secret <pass> or <hash> or <key_file>";
piCout << "-p --pass <pass> " << Green << "- use secret from passphrase <pass>";
piCout << "-s --secret <hash> " << Green << "- use secret from hash <hash>";
piCout << "-k --key <key_file> " << Green << "- use secret from binary key_file <key_file>";
piCout << "-x --hex [<hex_key>] " << Green << "- use secret from hex hash <hex_key> or output in text hex";
piCout << "-r --random " << Green << "- generate random secret key";
}
int main (int argc, char * argv[]) {
PICrypt::hash("");
PICrypt crypt;
PIByteArray bout;
PICLI cli(argc, argv);
cli.addArgument("genhash", true);
cli.addArgument("out", true);
cli.addArgument("crypt", true);
cli.addArgument("decrypt", true);
cli.addArgument("pass", true);
cli.addArgument("secret", true);
cli.addArgument("key", true);
cli.addArgument("hex", 'x', "hex", true);
cli.addArgument("help");
cli.addArgument("text");
cli.addArgument("random");
if (!(cli.hasArgument("genhash") ||
cli.hasArgument("crypt") ||
cli.hasArgument("decrypt") ||
cli.hasArgument("random")) ||
cli.hasArgument("help")) {
usage();
return 0;
}
PIString out_file = cli.argumentValue("out");
PIFile outf;
if (!out_file.isEmpty()) {
if (outf.open(out_file, PIIODevice::ReadWrite)) {
outf.resize(0);
} else piCout << "error: while open out file";
}
if (cli.hasArgument("genhash")) {
PIString s = cli.argumentValue("genhash");
bout = crypt.hash(s);
} else if (cli.hasArgument("random")) bout = crypt.generateKey();
if (cli.hasArgument("crypt") || cli.hasArgument("decrypt")) {
PIByteArray secret;
if (cli.hasArgument("key")) {
PIFile keyf(cli.argumentValue("key"), PIIODevice::ReadOnly);
if (keyf.open()) secret = keyf.readAll();
else piCout << "error: while open key file";
}
if (cli.hasArgument("pass")) secret = crypt.hash(cli.argumentValue("pass"));
if (cli.hasArgument("secret")) secret = PIByteArray::fromBase64(cli.argumentValue("secret").toByteArray());
if (cli.hasArgument("hex")) secret = PIByteArray::fromHex(cli.argumentValue("hex").toByteArray());
if (secret.size() == crypt.sizeKey()) {
PIFile inf;
PIString in_file;
PIByteArray bin;
crypt.setKey(secret);
if (cli.hasArgument("crypt")) in_file = cli.argumentValue("crypt");
if (cli.hasArgument("decrypt")) in_file = cli.argumentValue("decrypt");
if (inf.open(in_file, PIIODevice::ReadOnly)) {
bin = inf.readAll();
if (cli.hasArgument("crypt")) bout = crypt.crypt(bin);
if (cli.hasArgument("decrypt")) bout = crypt.decrypt(bin);
} else piCout << "error: while open input file";
} else piCout << "error: invalid secret";
}
if (!bout.isEmpty()) {
if (cli.hasArgument("text")) bout.convertToBase64();
else if (cli.hasArgument("hex") && cli.argumentValue("hex").isEmpty()) bout = bout.toHex().toByteArray();
if (outf.isOpened()) {
outf.write(bout);
outf.close();
}
else fwrite(bout.data(), 1, bout.size(), stdout);
}
return 0;
}
/*
PIP - Platform Independent Primitives
Crypth / decrypth files utility
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picrypt.h"
#include "pip.h"
#include <stdio.h>
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Crypt Utility";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default
<< "\"picrypt [-thr] [-g <pass>] [-o <out_file>] [{[-c <file>] [-d <file>]} {[-p <pass>] [-s <hash>] [-k <key_file>] [-x "
"<hex_key>]}]\""
<< NewLine;
piCout << Green << Bold << "Details:";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-g --genhash " << Green << "- generate hash from <pass> string";
piCout << "-t --text " << Green << "- output in text base64";
piCout << "-o --out <out_file> " << Green << "- write out to file <out_file>";
piCout << "-c --crypt <file> " << Green << "- crypt file <file> using secret <pass> or <hash> or <key_file>";
piCout << "-d --decrypt <file> " << Green << "- decrypt file <file> using secret <pass> or <hash> or <key_file>";
piCout << "-p --pass <pass> " << Green << "- use secret from passphrase <pass>";
piCout << "-s --secret <hash> " << Green << "- use secret from hash <hash>";
piCout << "-k --key <key_file> " << Green << "- use secret from binary key_file <key_file>";
piCout << "-x --hex [<hex_key>] " << Green << "- use secret from hex hash <hex_key> or output in text hex";
piCout << "-r --random " << Green << "- generate random secret key";
}
int main(int argc, char * argv[]) {
PICrypt::hash("");
PICrypt crypt;
PIByteArray bout;
PICLI cli(argc, argv);
cli.addArgument("genhash", true);
cli.addArgument("out", true);
cli.addArgument("crypt", true);
cli.addArgument("decrypt", true);
cli.addArgument("pass", true);
cli.addArgument("secret", true);
cli.addArgument("key", true);
cli.addArgument("hex", 'x', "hex", true);
cli.addArgument("help");
cli.addArgument("text");
cli.addArgument("random");
if (!(cli.hasArgument("genhash") || cli.hasArgument("crypt") || cli.hasArgument("decrypt") || cli.hasArgument("random")) ||
cli.hasArgument("help")) {
usage();
return 0;
}
PIString out_file = cli.argumentValue("out");
PIFile outf;
if (!out_file.isEmpty()) {
if (outf.open(out_file, PIIODevice::ReadWrite)) {
outf.resize(0);
} else
piCout << "error: while open out file";
}
if (cli.hasArgument("genhash")) {
PIString s = cli.argumentValue("genhash");
bout = crypt.hash(s);
} else if (cli.hasArgument("random"))
bout = crypt.generateKey();
if (cli.hasArgument("crypt") || cli.hasArgument("decrypt")) {
PIByteArray secret;
if (cli.hasArgument("key")) {
PIFile keyf(cli.argumentValue("key"), PIIODevice::ReadOnly);
if (keyf.open())
secret = keyf.readAll();
else
piCout << "error: while open key file";
}
if (cli.hasArgument("pass")) secret = crypt.hash(cli.argumentValue("pass"));
if (cli.hasArgument("secret")) secret = PIByteArray::fromBase64(cli.argumentValue("secret").toByteArray());
if (cli.hasArgument("hex")) secret = PIByteArray::fromHex(cli.argumentValue("hex").toByteArray());
if (secret.size() == crypt.sizeKey()) {
PIFile inf;
PIString in_file;
PIByteArray bin;
crypt.setKey(secret);
if (cli.hasArgument("crypt")) in_file = cli.argumentValue("crypt");
if (cli.hasArgument("decrypt")) in_file = cli.argumentValue("decrypt");
if (inf.open(in_file, PIIODevice::ReadOnly)) {
bin = inf.readAll();
if (cli.hasArgument("crypt")) bout = crypt.crypt(bin);
if (cli.hasArgument("decrypt")) bout = crypt.decrypt(bin);
} else
piCout << "error: while open input file";
} else
piCout << "error: invalid secret";
}
if (!bout.isEmpty()) {
if (cli.hasArgument("text"))
bout.convertToBase64();
else if (cli.hasArgument("hex") && cli.argumentValue("hex").isEmpty())
bout = bout.toHex().toByteArray();
if (outf.isOpened()) {
outf.write(bout);
outf.close();
} else
fwrite(bout.data(), 1, bout.size(), stdout);
}
return 0;
}

View File

@@ -1,26 +1,26 @@
/*
PIP - Platform Independent Primitives
Deploy tool
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Deploy tool
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "picli.h"
#include "pidir.h"
#include "piprocess.h"
#include "piiostream.h"
#include "piprocess.h"
#define DELIM "::"
@@ -31,15 +31,15 @@ PIString qplatforms;
void setCommands() {
#ifdef WINDOWS
cmd_copy = "copy /y ";
cmd_copy = "copy /y ";
cmd_copydir = "copy /y ";
cmd_suffix = " 1> NUL";
qplatforms = "windows";
cmd_suffix = " 1> NUL";
qplatforms = "windows";
#else
cmd_copy = "cp -f ";
cmd_copy = "cp -f ";
cmd_copydir = "cp -rf ";
# ifdef MAC_OS
qplatforms = "cocoa";
qplatforms = "cocoa";
# else
qplatforms = "xcb";
# endif
@@ -64,11 +64,13 @@ void usage() {
piCout << "Default regexp set by \"*=<regexp>\".";
piCout << "\"*=\" disable optional plugins.";
piCout << "";
piCout << Green << Bold << "Usage:" << Default << "\"deploy_tool [-hvfC] [--dependencies [--prefix <text>]] "
"[--qt-plugins-dir <d>] [-s <search_path>] [--ignore <libs>] [-S <styles>] "
"[-l <ldd>] [-D <dpkg>] [--dpkg-workdir <d>] [-L <readelf> | -W <objdump> | -M <otool>] "
"[--name-tool <pathS>] [--rpath] [-d <depth>] [-q <qtdir>] [-a <add_libs>] [-S <styles>] "
"[-P <platforms>] [--qt-plugins <d>] [--qt-modules <l>] [--qt-conf-dir <d>] -o <out_path> <file> [<file2> ...]\"" << NewLine;
piCout << Green << Bold << "Usage:" << Default
<< "\"deploy_tool [-hvfC] [--dependencies [--prefix <text>]] "
"[--qt-plugins-dir <d>] [-s <search_path>] [--ignore <libs>] [-S <styles>] "
"[-l <ldd>] [-D <dpkg>] [--dpkg-workdir <d>] [-L <readelf> | -W <objdump> | -M <otool>] "
"[--name-tool <pathS>] [--rpath] [-d <depth>] [-q <qtdir>] [-a <add_libs>] [-S <styles>] "
"[-P <platforms>] [--qt-plugins <d>] [--qt-modules <l>] [--qt-conf-dir <d>] -o <out_path> <file> [<file2> ...]\""
<< NewLine;
piCout << Green << Bold << "Details:";
piCout << Bold << "Debug control";
piCout << "-h, --help " << Green << "- display this message and exit";
@@ -76,7 +78,8 @@ void usage() {
piCout << "";
piCout << Bold << "Processing control";
piCout << "-f, --fake " << Green << "- don`t copy, only print";
piCout << "-s <search_path> " << Green << "- set search pathes for system libraries, may be separated by \"" DELIM "\", default \"/usr/lib\"";
piCout << "-s <search_path> " << Green
<< "- set search pathes for system libraries, may be separated by \"" DELIM "\", default \"/usr/lib\"";
piCout << "--ignore <libs> " << Green << "- ignore libraries names, may be separated by \"" DELIM "\", default \"\"";
piCout << "-l <ldd> " << Green << "- \"ldd\" path, default \"/usr/bin/ldd\"";
piCout << "-L <readelf> " << Green << "- \"readelf\" path, overrides \"ldd\"";
@@ -105,7 +108,8 @@ void usage() {
piCout << "";
piCout << Bold << "Input control";
piCout << "<file> ... " << Green << "- executable to process";
piCout << "-a <add_libs> " << Green << "- additional libs, separated by \"" DELIM "\". Libraries will be searched in <search_path>";
piCout << "-a <add_libs> " << Green
<< "- additional libs, separated by \"" DELIM "\". Libraries will be searched in <search_path>";
}
struct QtDep {
@@ -113,24 +117,27 @@ struct QtDep {
PIString lib;
PIStringList plugins;
};
QtDep qt_deps[] = {
QtDep("core" , PIStringList() << "platforms"),
QtDep("gui" , PIStringList() << "imageformats"),
QtDep("widgets" , PIStringList() << "styles"),
QtDep("sql" , PIStringList() << "sqldrivers"),
QtDep("positioning" , PIStringList() << "position"),
QtDep("location" , PIStringList() << "geoservices"),
QtDep("multimedia" , PIStringList() << "audio" << "mediaservice" << "playlistformats"),
QtDep("printsupport" , PIStringList() << "printsupport"),
QtDep("virtualkeyboard", PIStringList() << "platforminputcontexts"),
QtDep("sensors" , PIStringList() << "sensors" << "sensorgestures"),
QtDep("texttospeech" , PIStringList() << "texttospeech"),
QtDep("serialbus" , PIStringList() << "canbus"),
QtDep()
};
QtDep qt_deps[] = {QtDep("core", PIStringList() << "platforms"),
QtDep("gui", PIStringList() << "imageformats"),
QtDep("widgets", PIStringList() << "styles"),
QtDep("sql", PIStringList() << "sqldrivers"),
QtDep("positioning", PIStringList() << "position"),
QtDep("location", PIStringList() << "geoservices"),
QtDep("multimedia",
PIStringList() << "audio"
<< "mediaservice"
<< "playlistformats"),
QtDep("printsupport", PIStringList() << "printsupport"),
QtDep("virtualkeyboard", PIStringList() << "platforminputcontexts"),
QtDep("sensors",
PIStringList() << "sensors"
<< "sensorgestures"),
QtDep("texttospeech", PIStringList() << "texttospeech"),
QtDep("serialbus", PIStringList() << "canbus"),
QtDep()};
int depth = 8;
int depth = 8;
bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true, rpath = false, win_target = false;
PIString ldd, readelf, objdump, otool, dpkg, nametool, strip, out_dir, qt_dir, dpkg_workdir;
PIString qt_pref, qt_suff, qt_conf_dir, qt_plugins_dir, target_dir;
@@ -141,9 +148,8 @@ PIMap<PIString, PIStringList> qt_filters;
PIString findLib(const PIString & l) {
if (PIFile::isExists(l)) return l;
piForeachC (PIString & s, lib_dirs) {
if (PIFile::isExists(s + l))
return s + l;
piForeachC(PIString & s, lib_dirs) {
if (PIFile::isExists(s + l)) return s + l;
if (win_target || l.toLowerCase().endsWith("dll")) {
PIFile::FileInfo info(l);
PIString fn = info.baseName(), fe = info.extension(), nn;
@@ -166,7 +172,6 @@ PIString findLib(const PIString & l) {
if (PIFile::isExists(nn)) return nn;
nn = s + fn.toUpperCase() + "." + fe.toUpperCase();
if (PIFile::isExists(nn)) return nn;
}
}
return "";
@@ -176,7 +181,7 @@ PIString findLib(const PIString & l) {
PIString frameworkName(const PIString & l) {
if (!l.contains(".framework/")) return "";
PIStringList ll = l.split("/");
piForeachRC (PIString & _f, ll) {
piForeachRC(PIString & _f, ll) {
if (_f.endsWith(".framework")) {
return _f;
}
@@ -218,22 +223,37 @@ PIStringList filter(const PIString & in, const PIString & f) {
void checkQtLib(PIString lib) {
PIString base = lib.toLowerCase(), pref, suff;
if (base.startsWith("lib")) {pref += "lib"; base.cutLeft(3);}
if (base.startsWith("qt5")) {pref += "Qt5"; base.cutLeft(3);}
if (base.startsWith("qt6")) {pref += "Qt6"; base.cutLeft(3);}
if (base.startsWith("qt" )) {pref += "Qt" ; base.cutLeft(2);}
if (base.find('.') >= 0) {suff = base.right(base.size_s() - base.find('.')); base = base.left(base.find('.'));}
for (int i = 0; ; ++i) {
if (base.startsWith("lib")) {
pref += "lib";
base.cutLeft(3);
}
if (base.startsWith("qt5")) {
pref += "Qt5";
base.cutLeft(3);
}
if (base.startsWith("qt6")) {
pref += "Qt6";
base.cutLeft(3);
}
if (base.startsWith("qt")) {
pref += "Qt";
base.cutLeft(2);
}
if (base.find('.') >= 0) {
suff = base.right(base.size_s() - base.find('.'));
base = base.left(base.find('.'));
}
for (int i = 0;; ++i) {
if (qt_deps[i].lib.isEmpty()) break;
if (qt_deps[i].lib == base) {
qt_plugins << qt_deps[i].plugins;
//piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins;
// piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins;
need_qt = true;
qt_libs << lib;
if (make_qt_format) {
make_qt_format = false;
qt_pref = pref;
qt_suff = suff;
qt_pref = pref;
qt_suff = suff;
}
break;
}
@@ -262,28 +282,30 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
for (PIString & l: lines) {
l.cutRight(1);
l.cutLeft(l.find('[') + 1);
l.trim();//.append('.').prepend('.');
l.trim(); //.append('.').prepend('.');
}
}
if (!objdump.isEmpty()) {
PIString out = execute(objdump + " -p \"" + file + "\"");
lines = filter(out, "DLL Name:");
lines = filter(out, "DLL Name:");
lines << filter(out, "NEEDED");
for (PIString & l: lines) {
if (l.startsWith("DLL")) l.cutLeft(9);
else l.cutLeft(6);
l.trim();//.append('.').prepend('.');
if (l.startsWith("DLL"))
l.cutLeft(9);
else
l.cutLeft(6);
l.trim(); //.append('.').prepend('.');
}
}
if (!otool.isEmpty()) {
lines = filter(execute(otool + " -L \"" + file + "\""), "(");
piForeach (PIString & l, lines) {
piForeach(PIString & l, lines) {
l = l.left(l.find('('));
l.trim();//.append('.').prepend('.');
l.trim(); //.append('.').prepend('.');
}
}
}
piForeachC (PIString & sl, lines) {
piForeachC(PIString & sl, lines) {
PIString l = sl.trimmed();
if (!otool.isEmpty()) {
PIString fname = frameworkName(l);
@@ -297,26 +319,25 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
if (is_ldd) {
if (!l.contains("=>")) continue;
l.cutLeft(l.find("=>") + 2);
if (l.contains("("))
l.cutRight(l.length() - l.find("("));
if (l.contains("(")) l.cutRight(l.length() - l.find("("));
l.trim();
if (l.toLowerCase() == "not found") {
miss_libs << sl.left(sl.find("=>")).trim();
continue;
}
} else {
//l.cutLeft(1).cutRight(1).trim();
// l.cutLeft(1).cutRight(1).trim();
if (l.isEmpty()) continue;
if (!otool.isEmpty()) {
if (!l.startsWith("/usr/local/")) {
PIFile::FileInfo fi;
fi.path = l;
l = fi.name();
l = fi.name();
}
}
PIString flp = findLib(l);
if (flp.isEmpty()) {
//piCout << "Can`t find" << l;
// piCout << "Can`t find" << l;
miss_libs << l;
continue;
}
@@ -324,10 +345,10 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
}
if (all_libs[l]) continue;
PIFile::FileInfo fi;
fi.path = l;
fi.path = l;
PIString lname = fi.baseName();
if (lname.startsWith("lib")) lname.cutLeft(3);
//piCout << "check ignore" << lname << ignore_libs;
// piCout << "check ignore" << lname << ignore_libs;
if (ignore_libs.contains(lname)) {
continue;
}
@@ -336,9 +357,8 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
all_libs << l;
}
PIVector<PIString> clibs = cur_libs.toVector();
if (!clibs.isEmpty())
piCout << " new dependencies:\n -" << PIStringList(clibs).join("\n - ");
piForeachC (PIString & l, clibs) {
if (!clibs.isEmpty()) piCout << " new dependencies:\n -" << PIStringList(clibs).join("\n - ");
piForeachC(PIString & l, clibs) {
procLdd(l, false, cur_depth);
}
}
@@ -348,7 +368,8 @@ void copyWildcard(const PIString & from, const PIString & to) {
if (fake) return;
PIDir(to).make();
#ifdef WINDOWS
PIFile::FileInfo fi; fi.path = from;
PIFile::FileInfo fi;
fi.path = from;
system(("robocopy \"" + fi.dir() + "\" \"" + to + "\" \"" + fi.name() + "\" /NJH /NJS /NP /NDL /NS /NC /NFL 1> NUL").data());
#else
system((cmd_copy + from + " \"" + to + "/\"" + cmd_suffix).data());
@@ -357,7 +378,7 @@ void copyWildcard(const PIString & from, const PIString & to) {
void procQt() {
//piCout << "qmake ...";
// piCout << "qmake ...";
PIString vs;
if (qt_dir.isEmpty()) {
vs = execute("qmake -v");
@@ -367,11 +388,10 @@ void procQt() {
}
} else
vs = "QMake version ?.?\nUsing Qt version ?.?.? in " + qt_dir;
PIStringList vsl = vs.split("\n");
PIStringList vsl = vs.split("\n");
PIStringList pdirs = qt_plugins.toVector();
if (!fake)
PIDir(qt_plugins_dir).make(true);
piForeach (PIString l, vsl) {
if (!fake) PIDir(qt_plugins_dir).make(true);
piForeach(PIString l, vsl) {
if (l.trim().contains("Qt version")) {
l.cutLeft(l.find("Qt version") + 10).trim();
PIString qv = l.takeWord();
@@ -380,7 +400,7 @@ void procQt() {
piCout << "Qt" << qv << "in" << qloc;
PIString qdir;
PIStringList suffixes({".", "..", "qt5", "../qt5", "qt6", "../qt6"});
piForeachC (PIString s, suffixes) {
piForeachC(PIString s, suffixes) {
PIString qd = qloc + "/" + s + "/plugins/";
if (piDebug) PICout(AddSpaces) << "Qt plugins root try" << qd << "...";
if (PIDir::isExists(qd + "platforms")) {
@@ -390,15 +410,14 @@ void procQt() {
}
piCout << " no";
}
if (qdir.isEmpty())
break;
piForeachC (PIString & plugin, pdirs) {
if (qdir.isEmpty()) break;
piForeachC(PIString & plugin, pdirs) {
PIStringList filters = qt_filters[plugin];
piForeachC (PIString & f, filters) {
piForeachC(PIString & f, filters) {
if (f.isEmpty()) continue;
copyWildcard(qdir + plugin + "/" + f, qt_plugins_dir + plugin);
PIVector<PIFile::FileInfo> copied = PIDir(qt_plugins_dir + plugin).entries();
piForeachC (PIFile::FileInfo & fi, copied) {
piForeachC(PIFile::FileInfo & fi, copied) {
if (fi.isFile()) {
procLdd(fi.path);
plugin_libs << fi.path;
@@ -414,20 +433,18 @@ void procQt() {
bool procDpkg(const PIString & l) {
PIString dpkgdir;
if (!dpkg_workdir.isEmpty())
dpkgdir = " --admindir=" + dpkg_workdir;
if (!dpkg_workdir.isEmpty()) dpkgdir = " --admindir=" + dpkg_workdir;
PIFile::FileInfo fi;
fi.path = l;
fi.path = l;
PIString cmd = dpkg + dpkgdir + " -S " + fi.name() + " 2> /dev/null";
//PICout(true) << cmd;
PIString vs = execute(cmd);
// PICout(true) << cmd;
PIString vs = execute(cmd);
if (!vs.isEmpty()) {
vs = vs.left(vs.find(":"));
if (!vs.isEmpty())
all_deps << vs;
if (!vs.isEmpty()) all_deps << vs;
return true;
}
//piCout << "No dep on" << l;
// piCout << "No dep on" << l;
return false;
}
@@ -437,31 +454,31 @@ void patchNameTool() {
PIStringList clibs = all_libs.toVector(), flibs = framework_libs.toVector(), patch_list;
PIStringList dlibs;
PIString libname, cmd;
//PICout(DefaultControls) << "start patch" << clibs;
// PICout(DefaultControls) << "start patch" << clibs;
PIFile::FileInfo fi;
patch_list = input_files;
patch_list << plugin_libs;
piForeach (PIString l, clibs) {
piForeach(PIString l, clibs) {
fi.path = l;
patch_list << (out_dir + fi.name());
}
piForeach (PIString local_lib, patch_list) {
piForeach(PIString local_lib, patch_list) {
execute("chmod +w \"" + local_lib + "\"");
fi.path = local_lib;
cmd = nametool + " -id \"@executable_path/../Frameworks/" + fi.name() + "\"";
cmd = nametool + " -id \"@executable_path/../Frameworks/" + fi.name() + "\"";
cmd += " \"" + local_lib + "\" 2> /dev/null";
//piCout << " " << cmd;
// piCout << " " << cmd;
execute(cmd);
}
piForeach (PIString f, flibs) {
piForeach(PIString f, flibs) {
PIString fl = findLib(frameworkName(f));
if (fl.isEmpty()) continue;
patch_list << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
//PICout(DefaultControls) << "map" << f << "->" << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
// PICout(DefaultControls) << "map" << f << "->" << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
}
piForeach (PIString local_lib, patch_list) {
piForeach(PIString local_lib, patch_list) {
dlibs = filter(execute(otool + " -L \"" + local_lib + "\""), "(");
piForeach (PIString & l, dlibs) {
piForeach(PIString & l, dlibs) {
l = l.left(l.find('('));
l.trim();
}
@@ -469,12 +486,12 @@ void patchNameTool() {
execute("chmod +w \"" + local_lib + "\"");
}
piCout << "patch" << local_lib;
piForeach (PIString sys_lib, dlibs) {
piForeach(PIString sys_lib, dlibs) {
sys_lib.cutRight(1).trim();
fi.path = sys_lib;
libname = fi.name();
fi.path = sys_lib;
libname = fi.name();
PIString fl = findLib(libname), fname = frameworkName(sys_lib);
//piCout << " check" << sys_lib << fl;
// piCout << " check" << sys_lib << fl;
PIString new_path;
if (all_libs.contains(fl) || all_libs.contains(sys_lib)) {
new_path = "@executable_path/../Frameworks/" + libname;
@@ -491,12 +508,12 @@ void patchNameTool() {
cmd = nametool + " -change \"" + sys_lib + "\"";
cmd += " \"" + new_path + "\"";
cmd += " \"" + local_lib + "\" 2> /dev/null";
//piCout << " *" << cmd;
// piCout << " *" << cmd;
execute(cmd);
}
}
}
piForeach (PIString bin, input_files) {
piForeach(PIString bin, input_files) {
cmd = nametool + " -add_rpath \"@executable_path/../Frameworks\"";
cmd += " \"" + bin + "\" 2> /dev/null";
execute(cmd);
@@ -507,10 +524,9 @@ void patchNameTool() {
void patchRPathFile(const PIFile::FileInfo & file) {
PIString fo = execute("file \"" + file.path + "\"");
if (!fo.contains("ELF")) return;
PIString rp = "\\$ORIGIN:\\$ORIGIN/lib";
PIString rp = "\\$ORIGIN:\\$ORIGIN/lib";
PIString arp = PIDir(file.dir()).relative(out_dir);
if (!arp.isEmpty() && arp != "." && arp != "lib")
rp.append(":\\$ORIGIN/" + arp);
if (!arp.isEmpty() && arp != "." && arp != "lib") rp.append(":\\$ORIGIN/" + arp);
PIString cmd = "patchelf --set-rpath \"" + rp + "\" \"" + file.path + "\" 2> /dev/null";
piCout << "set rpath" << file.path << "to" << rp;
execute(cmd);
@@ -520,9 +536,9 @@ void patchRPathFile(const PIFile::FileInfo & file) {
void patchRPath() {
PIStringList dirs({out_dir, target_dir, qt_plugins_dir});
dirs.removeDuplicates().removeStrings(PIString());
piForeachC (PIString & d, dirs) {
piForeachC(PIString & d, dirs) {
PIVector<PIFile::FileInfo> files = PIDir(d).allEntries();
piForeachC (PIFile::FileInfo & f, files) {
piForeachC(PIFile::FileInfo & f, files) {
if (f.isDir()) continue;
patchRPathFile(f.path);
}
@@ -532,7 +548,7 @@ void patchRPath() {
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
//piCout << cli.rawArguments();
// piCout << cli.rawArguments();
cli.setOptionalArgumentsCount(-1);
cli.addArgument("help");
cli.addArgument("verbose");
@@ -567,26 +583,24 @@ int main(int argc, char * argv[]) {
}
setCommands();
fake = cli.hasArgument("fake");
piDebug = cli.hasArgument("verbose");
is_deps = cli.hasArgument("dependencies");
out_dir = cli.argumentValue("output");
lib_dirs = cli.argumentValue("search_path").split(DELIM);
add_libs = cli.argumentValue("add_libs").split(DELIM);
fake = cli.hasArgument("fake");
piDebug = cli.hasArgument("verbose");
is_deps = cli.hasArgument("dependencies");
out_dir = cli.argumentValue("output");
lib_dirs = cli.argumentValue("search_path").split(DELIM);
add_libs = cli.argumentValue("add_libs").split(DELIM);
ignore_libs = cli.argumentValue("ignore").split(DELIM);
qt_dir = cli.argumentValue("qtdir");
ldd = cli.argumentValue("ldd");
readelf = cli.argumentValue("Lreadelf");
objdump = cli.argumentValue("Wobjdump");
otool = cli.argumentValue("Motool");
nametool = cli.argumentValue("name-tool");
strip = cli.argumentValue("strip");
rpath = cli.hasArgument("rpath");
if (nametool.isEmpty())
nametool = "install_name_tool";
if (strip.isEmpty())
strip = "strip";
dpkg = cli.argumentValue("Dpkg");
qt_dir = cli.argumentValue("qtdir");
ldd = cli.argumentValue("ldd");
readelf = cli.argumentValue("Lreadelf");
objdump = cli.argumentValue("Wobjdump");
otool = cli.argumentValue("Motool");
nametool = cli.argumentValue("name-tool");
strip = cli.argumentValue("strip");
rpath = cli.hasArgument("rpath");
if (nametool.isEmpty()) nametool = "install_name_tool";
if (strip.isEmpty()) strip = "strip";
dpkg = cli.argumentValue("Dpkg");
dpkg_workdir = cli.argumentValue("dpkg-workdir");
#ifdef WINDOWS
readelf.replaceAll("/", "\\");
@@ -595,8 +609,7 @@ int main(int argc, char * argv[]) {
nametool.replaceAll("/", "\\");
dpkg.replaceAll("/", "\\");
#endif
if (dpkg.isEmpty())
dpkg = "/usr/bin/dpkg";
if (dpkg.isEmpty()) dpkg = "/usr/bin/dpkg";
int etcnt = 0;
if (!readelf.isEmpty()) ++etcnt;
if (!objdump.isEmpty()) ++etcnt;
@@ -611,7 +624,7 @@ int main(int argc, char * argv[]) {
if (!qroot.endsWith("/")) qroot.append("/");
lib_dirs << (qroot + "bin") << (qroot + "lib") << (qroot + "Frameworks");
}
piForeach (PIString & s, lib_dirs) {
piForeach(PIString & s, lib_dirs) {
s.trim();
if (!s.endsWith("/")) s += "/";
}
@@ -621,26 +634,25 @@ int main(int argc, char * argv[]) {
out_dir.replaceAll("//", "/");
for (int i = 0; ; ++i) {
for (int i = 0;; ++i) {
if (qt_deps[i].lib.isEmpty()) break;
qt_deps[i].plugins.forEach([](const PIString & p){qt_filters[p] = PIStringList("*");});
qt_deps[i].plugins.forEach([](const PIString & p) { qt_filters[p] = PIStringList("*"); });
}
if (!cli.argumentValue("Platforms").isEmpty())
qplatforms = cli.argumentValue("Platforms");
if (!cli.argumentValue("Platforms").isEmpty()) qplatforms = cli.argumentValue("Platforms");
if (platforms.contains("windows")) win_target = true;
platforms = qplatforms.split(",");
styles = cli.argumentValue("Styles").split(",");
styles = cli.argumentValue("Styles").split(",");
if (styles.isEmpty()) styles << "";
PIStringList qpd = cli.argumentValue("qt-plugins").toLowerCase().split(DELIM);
piForeachC (PIString & qp, qpd) {
piForeachC(PIString & qp, qpd) {
int _i = qp.find('=');
if (_i < 0) continue;
PIString pname = qp.left(_i).trim();
PIString pname = qp.left(_i).trim();
PIStringList pfilt = qp.mid(_i + 1).trim().split(",");
if (pname == "*") {
for (int i = 0; ; ++i) {
for (int i = 0;; ++i) {
if (qt_deps[i].lib.isEmpty()) break;
qt_deps[i].plugins.forEach([&pfilt](const PIString & p){qt_filters[p] = pfilt;});
qt_deps[i].plugins.forEach([&pfilt](const PIString & p) { qt_filters[p] = pfilt; });
}
} else {
qt_plugins << pname;
@@ -648,10 +660,10 @@ int main(int argc, char * argv[]) {
}
}
qt_filters["platforms"] = platforms;
qt_filters["styles" ] = styles ;
qt_filters["styles"] = styles;
qt_add_libs = cli.argumentValue("qt-modules").split(DELIM);
qt_conf_dir = cli.argumentValue("qt-conf-dir").trim();
qt_add_libs = cli.argumentValue("qt-modules").split(DELIM);
qt_conf_dir = cli.argumentValue("qt-conf-dir").trim();
if (qt_conf_dir.isEmpty()) qt_conf_dir = out_dir;
if (!qt_conf_dir.endsWith("/")) qt_conf_dir += "/";
qt_plugins_dir = cli.argumentValue("qt-plugins-dir").trim();
@@ -663,58 +675,51 @@ int main(int argc, char * argv[]) {
auto it = qt_filters.makeIterator();
while (it.next())
it.value().forEach([](PIString & i){
it.value().forEach([](PIString & i) {
if (!i.startsWith("*")) i.prepend("*");
if (!i.endsWith("*")) i.append("*");
});
//PICout(PICoutManipulators::DefaultControls) << qt_filters;
// PICout(PICoutManipulators::DefaultControls) << qt_filters;
if (!fake)
PIDir(out_dir).make();
if (!cli.argumentValue("depth").isEmpty())
depth = cli.argumentValue("depth").toInt();
if (!fake) PIDir(out_dir).make();
if (!cli.argumentValue("depth").isEmpty()) depth = cli.argumentValue("depth").toInt();
cli.optionalArguments().forEach([](const PIString & a){
cli.optionalArguments().forEach([](const PIString & a) {
if (PIDir::isExists(a)) {
if (target_dir.isEmpty())
target_dir = a;
PIDir(a).allEntries().forEach([](const PIFile::FileInfo & fi){
if (fi.isFile())
input_files << fi.path;
if (target_dir.isEmpty()) target_dir = a;
PIDir(a).allEntries().forEach([](const PIFile::FileInfo & fi) {
if (fi.isFile()) input_files << fi.path;
});
} else {
if (target_dir.isEmpty())
target_dir = PIFile::FileInfo(a).dir();
if (PIFile::isExists(a))
input_files << a;
if (target_dir.isEmpty()) target_dir = PIFile::FileInfo(a).dir();
if (PIFile::isExists(a)) input_files << a;
}
});
//piCout << files;
// piCout << files;
if (depth > 0) {
input_files.forEach([](const PIString & f){procLdd(f);});
qt_add_libs.forEach([](const PIString & f){
input_files.forEach([](const PIString & f) { procLdd(f); });
qt_add_libs.forEach([](const PIString & f) {
PIString l = findLib(qt_pref + f + qt_suff);
if (l.isEmpty()) return;
procLdd(l, true);
checkQtLib(f);
});
}
piForeach (PIString & s, add_libs) {
piForeach(PIString & s, add_libs) {
if (s.isEmpty()) continue;
PIString alib = findLib(s);
if (alib.isEmpty()) continue;
piCout << s << "->" << alib;
procLdd(alib, true);
if (!all_libs[alib])
all_libs << alib;
if (!all_libs[alib]) all_libs << alib;
}
if (need_qt) {
bool need_qt_plugins = true;
if (is_deps) { // if Qt in system, then no plugins copy
PIVector<PIString> qlibs = qt_libs.toVector();
piCout << "check for installed Qt" << qlibs;
piForeach (PIString l, qlibs) {
piForeach(PIString l, qlibs) {
l = findLib(l);
if (l.isEmpty()) continue;
if (procDpkg(l)) {
@@ -735,7 +740,7 @@ int main(int argc, char * argv[]) {
pp = "PlugIns";
lp = "Resources/lang";
}
//piCout << pp;
// piCout << pp;
PIIOTextStream ts(&qtc);
ts << "[Paths]\n\tPlugins = " << pp << "\n\tTranslations = " << lp << "\n";
}
@@ -746,15 +751,14 @@ int main(int argc, char * argv[]) {
out_dir.replaceAll("/", "\\");
#endif
PIVector<PIString> clibs = all_libs.toVector();
piForeach (PIString l, clibs) {
piForeach(PIString l, clibs) {
PIFile::FileInfo fi;
fi.path = l;
#ifdef WINDOWS
l.replaceAll("/", "\\");
#endif
bool need_cp = true;
if (is_deps)
need_cp = !procDpkg(l);
if (is_deps) need_cp = !procDpkg(l);
if (need_cp) {
piCout << "copy" << l;
if (!fake) {
@@ -767,31 +771,26 @@ int main(int argc, char * argv[]) {
}
}
PIVector<PIString> fwdirs = frameworks.toVector();
piForeachC (PIString & f, fwdirs) {
piForeachC(PIString & f, fwdirs) {
PIString fd = findLib(f);
if (!fd.isEmpty()) {
piCout << "copy framework" << f;
if (!fake)
system((cmd_copydir + "\"" + fd + "\" \"" + out_dir + "\"" + cmd_suffix).data());
if (!fake) system((cmd_copydir + "\"" + fd + "\" \"" + out_dir + "\"" + cmd_suffix).data());
} else
miss_frameworks << f;
}
if (!otool.isEmpty())
patchNameTool();
if (!otool.isEmpty()) patchNameTool();
if (rpath)
patchRPath();
if (rpath) patchRPath();
if (is_deps) {
PICout(PICoutManipulators::AddNone) << cli.argumentValue("prefix");
PICout(PICoutManipulators::AddNewLine) << PIStringList(all_deps.toVector()).join(", ");
} else {
piCout << "copied" << clibs.size_s() << "files";
if (!miss_libs.isEmpty())
piCout << "Missing libraries:\n -" << PIStringList(miss_libs.toVector()).join("\n - ");
if (!miss_frameworks.isEmpty())
piCout << "Missing frameworks:\n -" << PIStringList(miss_frameworks.toVector()).join("\n - ");
if (!miss_libs.isEmpty()) piCout << "Missing libraries:\n -" << PIStringList(miss_libs.toVector()).join("\n - ");
if (!miss_frameworks.isEmpty()) piCout << "Missing frameworks:\n -" << PIStringList(miss_frameworks.toVector()).join("\n - ");
}
return 0;

View File

@@ -1,39 +1,40 @@
/*
PIP - Platform Independent Primitives
Terminal client for windows, used by PITerminal and pisd
Ivan Pelipenko peri4ko@yandex.ru
PIP - Platform Independent Primitives
Terminal client for windows, used by PITerminal and pisd
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piincludes_p.h"
#ifndef WINDOWS
int main (int argc, char * argv[]) {
int main(int argc, char * argv[]) {
return 0;
}
#else
# define PIP_CONSOLE_STATIC_DEFINE
# include "../../libs/console/piterminal.cpp"
# include "pifile.h"
# include "pip_console_export.h"
# include "piscreentypes.h"
# include "pisharedmemory.h"
# include "pifile.h"
# include <wingdi.h>
# include <wincon.h>
# include "../../libs/console/piterminal.cpp"
# include <wingdi.h>
PIVector<PIVector<PIScreenTypes::Cell> > cells;
PIVector<PIVector<PIScreenTypes::Cell>> cells;
CONSOLE_SCREEN_BUFFER_INFO sbi;
CHAR_INFO * chars = 0;
HANDLE console = 0, cstdin = 0, pipe = 0, cmd_proc = 0;
@@ -44,23 +45,31 @@ int con_w = -1, con_h = -1;
PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) {
PIScreenTypes::Cell ret;
ret.symbol = PIChar::fromConsole(c.Char.AsciiChar);
ret.symbol = PIChar::fromConsole(c.Char.AsciiChar);
ret.format.color_char = PIScreenTypes::Black;
if ((c.Attributes & (FOREGROUND_RED)) == FOREGROUND_RED) ret.format.color_char = PIScreenTypes::Red;
if ((c.Attributes & (FOREGROUND_GREEN)) == FOREGROUND_GREEN) ret.format.color_char = PIScreenTypes::Green;
if ((c.Attributes & (FOREGROUND_BLUE)) == FOREGROUND_BLUE) ret.format.color_char = PIScreenTypes::Blue;
if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Cyan;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Magenta;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN)) ret.format.color_char = PIScreenTypes::Yellow;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::White;
if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE))
ret.format.color_char = PIScreenTypes::Cyan;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE))
ret.format.color_char = PIScreenTypes::Magenta;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN))
ret.format.color_char = PIScreenTypes::Yellow;
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE))
ret.format.color_char = PIScreenTypes::White;
ret.format.color_back = PIScreenTypes::Black;
if ((c.Attributes & (BACKGROUND_RED)) == (BACKGROUND_RED)) ret.format.color_back = PIScreenTypes::Red;
if ((c.Attributes & (BACKGROUND_GREEN)) == (BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Green;
if ((c.Attributes & (BACKGROUND_BLUE)) == (BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Blue;
if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Cyan;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Magenta;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Yellow;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_back = PIScreenTypes::White;
if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE))
ret.format.color_back = PIScreenTypes::Cyan;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE))
ret.format.color_back = PIScreenTypes::Magenta;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN))
ret.format.color_back = PIScreenTypes::Yellow;
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE))
ret.format.color_back = PIScreenTypes::White;
if ((c.Attributes & (FOREGROUND_INTENSITY)) > 0) ret.format.flags |= PIScreenTypes::Bold;
return ret;
}
@@ -68,32 +77,32 @@ PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) {
int SpecialKey2VirtualKeyCode(PIKbdListener::SpecialKey k) {
switch (k) {
case PIKbdListener::Tab : return '\t'; break;
case PIKbdListener::Return : return '\n'; break;
case PIKbdListener::Space : return ' '; break;
case PIKbdListener::Backspace : return 8 ;
case PIKbdListener::PageUp : return 33 ;
case PIKbdListener::PageDown : return 34 ;
case PIKbdListener::End : return 35 ;
case PIKbdListener::Home : return 36 ;
case PIKbdListener::LeftArrow : return 37 ;
case PIKbdListener::UpArrow : return 38 ;
case PIKbdListener::RightArrow: return 39 ;
case PIKbdListener::DownArrow : return 40 ;
case PIKbdListener::Insert : return 45 ;
case PIKbdListener::Delete : return 46 ;
case PIKbdListener::F1 : return 112;
case PIKbdListener::F2 : return 113;
case PIKbdListener::F3 : return 114;
case PIKbdListener::F4 : return 115;
case PIKbdListener::F5 : return 116;
case PIKbdListener::F6 : return 117;
case PIKbdListener::F7 : return 118;
case PIKbdListener::F8 : return 119;
case PIKbdListener::F9 : return 120;
case PIKbdListener::F10 : return 121;
case PIKbdListener::F11 : return 122;
case PIKbdListener::F12 : return 123;
case PIKbdListener::Tab: return '\t'; break;
case PIKbdListener::Return: return '\n'; break;
case PIKbdListener::Space: return ' '; break;
case PIKbdListener::Backspace: return 8;
case PIKbdListener::PageUp: return 33;
case PIKbdListener::PageDown: return 34;
case PIKbdListener::End: return 35;
case PIKbdListener::Home: return 36;
case PIKbdListener::LeftArrow: return 37;
case PIKbdListener::UpArrow: return 38;
case PIKbdListener::RightArrow: return 39;
case PIKbdListener::DownArrow: return 40;
case PIKbdListener::Insert: return 45;
case PIKbdListener::Delete: return 46;
case PIKbdListener::F1: return 112;
case PIKbdListener::F2: return 113;
case PIKbdListener::F3: return 114;
case PIKbdListener::F4: return 115;
case PIKbdListener::F5: return 116;
case PIKbdListener::F6: return 117;
case PIKbdListener::F7: return 118;
case PIKbdListener::F8: return 119;
case PIKbdListener::F9: return 120;
case PIKbdListener::F10: return 121;
case PIKbdListener::F11: return 122;
case PIKbdListener::F12: return 123;
default: break;
}
return 0;
@@ -119,7 +128,7 @@ void readConsole(int x, int y, int w, int h) {
ReadConsoleOutput(console, chars, bs, bc, &(sbi.srWindow));
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
cells[i][j] = CharInfo2Cell(chars[i * w + j]);
cells[i][j] = CharInfo2Cell(chars[i * w + j]);
}
@@ -137,13 +146,15 @@ void resizeConsole(int w, int h) {
con_w = w;
con_h = h;
GetConsoleScreenBufferInfo(console, &sbi);
sbi.srWindow.Left = 0;
sbi.srWindow.Right = sbi.srWindow.Left + w - 1;
sbi.srWindow.Left = 0;
sbi.srWindow.Right = sbi.srWindow.Left + w - 1;
sbi.srWindow.Bottom = sbi.srWindow.Top + h - 1;
COORD sz; sz.X = w; sz.Y = h;
COORD sz;
sz.X = w;
sz.Y = h;
SetConsoleScreenBufferSize(console, sz);
SetConsoleWindowInfo(console, TRUE, &(sbi.srWindow));
//system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii());
// system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii());
resizeCells(w, h);
}
@@ -152,12 +163,10 @@ class PipeReader: public PIThread {
public:
PipeReader(): PIThread() {
wrote = readed = 0;
msg_size = 0;
msg_size = 0;
start(1);
}
~PipeReader() {
stop();
}
~PipeReader() { stop(); }
void run() {
in.resize(PIPE_BUFFER_SIZE);
ReadFile(pipe, in.data(), in.size_s(), &readed, 0);
@@ -165,7 +174,7 @@ public:
stop();
return;
}
//piCout << errorString();
// piCout << errorString();
if (readed > 0) {
in.resize(readed);
stream.append(in);
@@ -185,8 +194,9 @@ public:
void parseMessage() {
if (msg.size_s() < 4) return;
PIMutexLocker _ml(con_mutex);
int type = 0; msg >> type;
//piCout << "msg" << type;
int type = 0;
msg >> type;
// piCout << "msg" << type;
switch ((PITerminalAuxMessageType)type) {
case mtKey: {
PIVector<PIKbdListener::KeyEvent> ke;
@@ -194,27 +204,27 @@ public:
PIVector<INPUT_RECORD> ir(ke.size() * 2);
for (int i = 0; i < ke.size_s(); ++i) {
PIKbdListener::KeyEvent k(ke[i]);
int j = i+i, z = j+1;
ir[j].EventType = KEY_EVENT;
ir[j].Event.KeyEvent.wRepeatCount = 1;
int j = i + i, z = j + 1;
ir[j].EventType = KEY_EVENT;
ir[j].Event.KeyEvent.wRepeatCount = 1;
ir[j].Event.KeyEvent.dwControlKeyState = KeyModifiers2ControlKeyState(k.modifiers);
if (PITerminal::isSpecialKey(k.key)) {
ir[j].Event.KeyEvent.wVirtualKeyCode = SpecialKey2VirtualKeyCode((PIKbdListener::SpecialKey)k.key);
ir[j].Event.KeyEvent.uChar.AsciiChar = PIChar((ushort)piMaxi(k.key, 0)).toAscii();
} else
ir[j].Event.KeyEvent.uChar.UnicodeChar = PIChar((ushort)piMaxi(k.key, 0)).toWChar();
//piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar);
// piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar);
ir[j].Event.KeyEvent.bKeyDown = true;
ir[z] = ir[j];
ir[z] = ir[j];
ir[z].Event.KeyEvent.bKeyDown = false;
}
WriteConsoleInput(cstdin, ir.data(), ir.size_s(), &wrote);
} break;
} break;
case mtResize: {
int rw = -1, rh = -1;
msg >> rw >> rh;
if (rw > 0 && rh > 0) resizeConsole(rw, rh);
} break;
} break;
default: break;
}
}
@@ -231,8 +241,8 @@ void getCursor(int & x, int & y) {
}
int main (int argc, char * argv[]) {
//piCout << "start";
int main(int argc, char * argv[]) {
// piCout << "start";
STARTUPINFOA si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
@@ -241,39 +251,39 @@ int main (int argc, char * argv[]) {
PIString shmh, pname;
if (argc > 1) shmh = argv[1];
if (argc > 2) pname = argv[2];
if(!CreateProcessA(0, (LPSTR)"cmd", 0, 0, true, 0, 0, 0, &si, &pi)) {
if (!CreateProcessA(0, (LPSTR) "cmd", 0, 0, true, 0, 0, 0, &si, &pi)) {
return 1;
}
PISharedMemory shm("piterm_aux" + shmh, 1024*1024);
PISharedMemory shm("piterm_aux" + shmh, 1024 * 1024);
pipe = CreateFileA((LPSTR)pname.dataAscii(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (pipe == INVALID_HANDLE_VALUE) {
return 1;
}
CloseHandle(pi.hThread);
cmd_proc = pi.hProcess;
console = GetStdHandle(STD_OUTPUT_HANDLE);
cstdin = GetStdHandle(STD_INPUT_HANDLE);
console = GetStdHandle(STD_OUTPUT_HANDLE);
cstdin = GetStdHandle(STD_INPUT_HANDLE);
resizeConsole(80, 24);
PipeReader pipe_reader;
pipe_reader.waitForStart();
PIByteArray scr;
while (true) {
//piCout << "loop";
// piCout << "loop";
if (!pipe_reader.isRunning()) break;
con_mutex.lock();
getCursor(data_out.cursor_x, data_out.cursor_y);
readConsole(0, 0, con_w, con_h);
scr.clear();
scr << cells;
data_out.size_x = con_w;
data_out.size_y = con_h;
data_out.size_x = con_w;
data_out.size_y = con_h;
data_out.cells_size = scr.size_s();
con_mutex.unlock();
shm.write(&data_out, sizeof(data_out));
shm.write(scr, sizeof(data_out));
piMSleep(25);
}
//piCout << "exit";
// piCout << "exit";
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hProcess);
return 0;

View File

@@ -1,86 +1,83 @@
#include "generator.h"
#include "piresourcesstorage.h"
#include "piiostream.h"
PIString initName(const PIString & n) {
return PIFile::fileInfo(n).baseName().replaceAll(".", "_").replaceAll("/", "_")
.replaceAll(":", "_").replaceAll("-", "_");
}
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files) {
if (!file.isOpened()) return false;
PIString fcname = initName(file.path());
PIString icname = "_PIRC_" + fcname + "_Initializer_";
PIString dataname = "_pirc_" + fcname + "_data_";
PIString descname = "_pirc_" + fcname + "_desc_";
PIString funcname = "_pirc_" + init_name + "_init_";
PIVector<PIResourcesStorage::__RCEntry> fv;
piForeachC (ParserSection & s, files) {
piForeachC (ParserEntry & p, s.files) {
PIFile f;
if (!f.open(p.path, PIIODevice::ReadOnly)) continue;
//piCout << "gen" << p.name << p.alias << p.path;
fv << PIResourcesStorage::__RCEntry(s.name, p.name, p.alias, p.path);
}
}
if (fv.isEmpty()) return false;
PIIOTextStream ts(&file);
ts << "#include \"piresourcesstorage.h\"\n\nstatic const uchar " << dataname << "[] = {\n";
bool first = true;
int rcnt = -1;
llong curoff = 0, curfile = 0;
piForeach (PIResourcesStorage::__RCEntry & e, fv) {
e.offset = curoff;
PIFile f;
f.open(e.file, PIIODevice::ReadOnly);
PIByteArray readed;
curfile = 0;
while (!f.isEnd()) {
readed = f.read(4096);
curfile += readed.size_s();
for (int i = 0; i < readed.size_s(); ++i) {
if (!first)
ts << ',';
first = false;
if (++rcnt >= 32) {
ts << '\n';
rcnt = 0;
}
ts << int(readed[i]);
}
}
e.size = curfile;
curoff += curfile;
}
ts << "\n};\n";
PIByteArray dba;
dba << fv;
ts << "\nstatic const uchar " << descname << "[] = {\n";
first = true;
rcnt = -1;
for (int i = 0; i < dba.size_s(); ++i) {
if (!first)
ts << ',';
first = false;
if (++rcnt >= 32) {
ts << '\n';
rcnt = 0;
}
ts << int(dba[i]);
}
ts << "\n};\n";
ts << "\nvoid " << funcname << "() {\n";
ts << "\tPIResourcesStorage::instance()->registerSection(" << dataname << ", " << descname << ", sizeof(" << descname << "));\n";
ts << "}\n";
ts << "\nclass " << icname << " {\n";
ts << "public:\n\t" << icname << "() {\n";
ts << "\t\t" << funcname << "();\n";
ts << "\t}\n";
ts << "} _pirc_" << fcname << "_initializer_;\n";
return true;
}
#include "generator.h"
#include "piiostream.h"
#include "piresourcesstorage.h"
PIString initName(const PIString & n) {
return PIFile::fileInfo(n).baseName().replaceAll(".", "_").replaceAll("/", "_").replaceAll(":", "_").replaceAll("-", "_");
}
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files) {
if (!file.isOpened()) return false;
PIString fcname = initName(file.path());
PIString icname = "_PIRC_" + fcname + "_Initializer_";
PIString dataname = "_pirc_" + fcname + "_data_";
PIString descname = "_pirc_" + fcname + "_desc_";
PIString funcname = "_pirc_" + init_name + "_init_";
PIVector<PIResourcesStorage::__RCEntry> fv;
piForeachC(ParserSection & s, files) {
piForeachC(ParserEntry & p, s.files) {
PIFile f;
if (!f.open(p.path, PIIODevice::ReadOnly)) continue;
// piCout << "gen" << p.name << p.alias << p.path;
fv << PIResourcesStorage::__RCEntry(s.name, p.name, p.alias, p.path);
}
}
if (fv.isEmpty()) return false;
PIIOTextStream ts(&file);
ts << "#include \"piresourcesstorage.h\"\n\nstatic const uchar " << dataname << "[] = {\n";
bool first = true;
int rcnt = -1;
llong curoff = 0, curfile = 0;
piForeach(PIResourcesStorage::__RCEntry & e, fv) {
e.offset = curoff;
PIFile f;
f.open(e.file, PIIODevice::ReadOnly);
PIByteArray readed;
curfile = 0;
while (!f.isEnd()) {
readed = f.read(4096);
curfile += readed.size_s();
for (int i = 0; i < readed.size_s(); ++i) {
if (!first) ts << ',';
first = false;
if (++rcnt >= 32) {
ts << '\n';
rcnt = 0;
}
ts << int(readed[i]);
}
}
e.size = curfile;
curoff += curfile;
}
ts << "\n};\n";
PIByteArray dba;
dba << fv;
ts << "\nstatic const uchar " << descname << "[] = {\n";
first = true;
rcnt = -1;
for (int i = 0; i < dba.size_s(); ++i) {
if (!first) ts << ',';
first = false;
if (++rcnt >= 32) {
ts << '\n';
rcnt = 0;
}
ts << int(dba[i]);
}
ts << "\n};\n";
ts << "\nvoid " << funcname << "() {\n";
ts << "\tPIResourcesStorage::instance()->registerSection(" << dataname << ", " << descname << ", sizeof(" << descname << "));\n";
ts << "}\n";
ts << "\nclass " << icname << " {\n";
ts << "public:\n\t" << icname << "() {\n";
ts << "\t\t" << funcname << "();\n";
ts << "\t}\n";
ts << "} _pirc_" << fcname << "_initializer_;\n";
return true;
}

View File

@@ -1,9 +1,9 @@
#ifndef PIRC_GENERATOR_H
#define PIRC_GENERATOR_H
#include "parser.h"
PIString initName(const PIString & n);
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files);
#endif // PIRC_GENERATOR_H
#ifndef PIRC_GENERATOR_H
#define PIRC_GENERATOR_H
#include "parser.h"
PIString initName(const PIString & n);
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files);
#endif // PIRC_GENERATOR_H

View File

@@ -1,98 +1,95 @@
/*
PIP - Platform Independent Primitives
Resources compiller
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parser.h"
#include "generator.h"
#include "picli.h"
#include "piiostream.h"
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Resources Compiler";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"pip_rc [-hl] [-n <name>] -i <in_file> -o <out_file>\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-n --name <name> " << Green << "- name of initialize function, by default is <out_file> base name";
piCout << "-i --input <in_file> " << Green << "- resources description file";
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
piCout << "-l --list " << Green << "- print readed files from description and exit";
piCout << "-s --silent " << Green << "- no console output";
}
int main (int argc, char * argv[]) {
PICLI cli(argc, argv);
cli.addArgument("input", true);
cli.addArgument("out", true);
cli.addArgument("name", true);
cli.addArgument("help");
cli.addArgument("list");
cli.addArgument("silent");
if (cli.hasArgument("silent"))
piDebug = false;
if (cli.hasArgument("help") || !cli.hasArgument("input") ||
(!cli.hasArgument("out") && !cli.hasArgument("list"))) {
usage();
return 0;
}
PIVector<ParserSection> files = parse(cli.argumentValue("input"));
if (files.isEmpty()) {
piCout << "Error: resources description file is empty";
return 0;
}
if (cli.hasArgument("list")) {
piForeachC (ParserSection & s, files) {
piForeachC (ParserEntry & e, s.files) {
piCout << e.path;
}
}
return 0;
}
PIString out_file = cli.argumentValue("out");
PIString init_name = cli.argumentValue("name");
init_name = initName(init_name.isEmpty() ? out_file : init_name);
PIFile outf;
if (!out_file.isEmpty()) {
if (outf.open(out_file, PIIODevice::ReadWrite)) {
outf.clear();
} else {
piCout << "Error: can`t open out file" << out_file;
return 1;
}
PIIOTextStream ts(&outf);
ts << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
ts << "// Execute command:\n";
piForeachC (PIString & _a, cli.rawArguments())
ts << "// \"" << _a << "\"\n";
ts << "\n";
if (!generate(init_name, outf, files)) {
piCout << "Error: generate fail";
return 1;
}
}
return 0;
}
/*
PIP - Platform Independent Primitives
Resources compiller
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "generator.h"
#include "parser.h"
#include "picli.h"
#include "piiostream.h"
using namespace PICoutManipulators;
void usage() {
piCout << Bold << "PIP Resources Compiler";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"pip_rc [-hl] [-n <name>] -i <in_file> -o <out_file>\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-n --name <name> " << Green << "- name of initialize function, by default is <out_file> base name";
piCout << "-i --input <in_file> " << Green << "- resources description file";
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
piCout << "-l --list " << Green << "- print readed files from description and exit";
piCout << "-s --silent " << Green << "- no console output";
}
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
cli.addArgument("input", true);
cli.addArgument("out", true);
cli.addArgument("name", true);
cli.addArgument("help");
cli.addArgument("list");
cli.addArgument("silent");
if (cli.hasArgument("silent")) piDebug = false;
if (cli.hasArgument("help") || !cli.hasArgument("input") || (!cli.hasArgument("out") && !cli.hasArgument("list"))) {
usage();
return 0;
}
PIVector<ParserSection> files = parse(cli.argumentValue("input"));
if (files.isEmpty()) {
piCout << "Error: resources description file is empty";
return 0;
}
if (cli.hasArgument("list")) {
piForeachC(ParserSection & s, files) {
piForeachC(ParserEntry & e, s.files) {
piCout << e.path;
}
}
return 0;
}
PIString out_file = cli.argumentValue("out");
PIString init_name = cli.argumentValue("name");
init_name = initName(init_name.isEmpty() ? out_file : init_name);
PIFile outf;
if (!out_file.isEmpty()) {
if (outf.open(out_file, PIIODevice::ReadWrite)) {
outf.clear();
} else {
piCout << "Error: can`t open out file" << out_file;
return 1;
}
PIIOTextStream ts(&outf);
ts << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
ts << "// Execute command:\n";
piForeachC(PIString & _a, cli.rawArguments())
ts << "// \"" << _a << "\"\n";
ts << "\n";
if (!generate(init_name, outf, files)) {
piCout << "Error: generate fail";
return 1;
}
}
return 0;
}

View File

@@ -1,121 +1,119 @@
#include "parser.h"
#include "piconfig.h"
#include "piiostream.h"
PIVector<ParserSection> parse(const PIString & path) {
PIVector<ParserSection> ret;
PIFile f;
if (!f.open(path, PIIODevice::ReadOnly))
return ret;
PIString ext = f.fileInfo().extension().toLowerCase();
PIString dir = PIDir(f.fileInfo().dir()).absolutePath() + "/";
//piCout << dir;
if (ext == "conf") return parseConf(f, dir);
if (ext == "qrc") return parseQRC(f, dir);
return ret;
}
ParserEntry makeEntry(PIString filename, const PIString & dir) {
ParserEntry ret;
ret.path = filename;
if (!PIDir(PIFile::fileInfo(filename).dir()).isAbsolute()) {
//piCout << "rel, add dir";
ret.path.insert(0, dir);
}
//piCout << line << path;
ret.name = filename;
return ret;
}
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir) {
PIVector<ParserSection> ret;
if (!file.isOpened()) return ret;
PIIOTextStream ts(&file);
ParserSection ps;
while (!ts.isEnd()) {
PIString line = ts.readLine().trim();
if (line.isEmpty()) continue;
if (line.startsWith("[") && line.endsWith("]")) {
if (!ps.files.isEmpty()) ret << ps;
ps.name = line.cutLeft(1).cutRight(1).trim();
ps.files.clear();
continue;
}
PIString alias;
int i = line.findLast("=");
if (i > 0) {
alias = line.takeMid(i + 1).trim();
line.cutRight(1).trim();
}
ParserEntry e = makeEntry(line, dir);
if (!alias.isEmpty())
e.alias = alias;
ps.files << e;
}
if (!ps.files.isEmpty()) ret << ps;
return ret;
}
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir) {
PIVector<ParserSection> ret;
if (!file.isOpened()) return ret;
PIIOTextStream ts(&file);
ParserSection ps;
bool is_files = false;
while (!ts.isEnd()) {
PIString line = ts.readLine().trim();
if (line.isEmpty()) continue;
if (line.startsWith("<qresource")) {
if (!ps.files.isEmpty()) ret << ps;
ps.name.clear();
ps.files.clear();
line.cutLeft(10);
if (line.endsWith(">")) line.cutRight(1);
line.trim();
if (line.endsWith("/")) {
is_files = false;
continue;
}
is_files = true;
if (line.startsWith("prefix")) {
int i = line.find("=");
if (i > 0) {
line.cutLeft(i + 1).trim();
if (line.startsWith("\"")) line.cutLeft(1);
if (line.endsWith("\"")) line.cutRight(1);
ps.name = line;
}
}
//piCout << "section \"" << ps.name << "\"";
continue;
}
if (line == "</qresource>") {
is_files = false;
continue;
}
if (!is_files) continue;
if (!line.startsWith("<file")) continue;
PIString alias = line.takeRange('<', '>', '\0');
alias.cutLeft(4).trim();
if (alias.startsWith("alias")) {
int i = alias.find("=");
if (i > 0) {
alias.cutLeft(i + 1).trim();
if (alias.startsWith("\"")) alias.cutLeft(1);
if (alias.endsWith("\"")) alias.cutRight(1);
}
}
if (line.endsWith("</file>")) line.cutRight(7).trim();
ParserEntry e = makeEntry(line, dir);
if (!alias.isEmpty())
e.alias = alias;
ps.files << e;
//piCout << "file =" << line << "alias =" << alias;
}
if (!ps.files.isEmpty()) ret << ps;
return ret;
}
#include "parser.h"
#include "piconfig.h"
#include "piiostream.h"
PIVector<ParserSection> parse(const PIString & path) {
PIVector<ParserSection> ret;
PIFile f;
if (!f.open(path, PIIODevice::ReadOnly)) return ret;
PIString ext = f.fileInfo().extension().toLowerCase();
PIString dir = PIDir(f.fileInfo().dir()).absolutePath() + "/";
// piCout << dir;
if (ext == "conf") return parseConf(f, dir);
if (ext == "qrc") return parseQRC(f, dir);
return ret;
}
ParserEntry makeEntry(PIString filename, const PIString & dir) {
ParserEntry ret;
ret.path = filename;
if (!PIDir(PIFile::fileInfo(filename).dir()).isAbsolute()) {
// piCout << "rel, add dir";
ret.path.insert(0, dir);
}
// piCout << line << path;
ret.name = filename;
return ret;
}
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir) {
PIVector<ParserSection> ret;
if (!file.isOpened()) return ret;
PIIOTextStream ts(&file);
ParserSection ps;
while (!ts.isEnd()) {
PIString line = ts.readLine().trim();
if (line.isEmpty()) continue;
if (line.startsWith("[") && line.endsWith("]")) {
if (!ps.files.isEmpty()) ret << ps;
ps.name = line.cutLeft(1).cutRight(1).trim();
ps.files.clear();
continue;
}
PIString alias;
int i = line.findLast("=");
if (i > 0) {
alias = line.takeMid(i + 1).trim();
line.cutRight(1).trim();
}
ParserEntry e = makeEntry(line, dir);
if (!alias.isEmpty()) e.alias = alias;
ps.files << e;
}
if (!ps.files.isEmpty()) ret << ps;
return ret;
}
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir) {
PIVector<ParserSection> ret;
if (!file.isOpened()) return ret;
PIIOTextStream ts(&file);
ParserSection ps;
bool is_files = false;
while (!ts.isEnd()) {
PIString line = ts.readLine().trim();
if (line.isEmpty()) continue;
if (line.startsWith("<qresource")) {
if (!ps.files.isEmpty()) ret << ps;
ps.name.clear();
ps.files.clear();
line.cutLeft(10);
if (line.endsWith(">")) line.cutRight(1);
line.trim();
if (line.endsWith("/")) {
is_files = false;
continue;
}
is_files = true;
if (line.startsWith("prefix")) {
int i = line.find("=");
if (i > 0) {
line.cutLeft(i + 1).trim();
if (line.startsWith("\"")) line.cutLeft(1);
if (line.endsWith("\"")) line.cutRight(1);
ps.name = line;
}
}
// piCout << "section \"" << ps.name << "\"";
continue;
}
if (line == "</qresource>") {
is_files = false;
continue;
}
if (!is_files) continue;
if (!line.startsWith("<file")) continue;
PIString alias = line.takeRange('<', '>', '\0');
alias.cutLeft(4).trim();
if (alias.startsWith("alias")) {
int i = alias.find("=");
if (i > 0) {
alias.cutLeft(i + 1).trim();
if (alias.startsWith("\"")) alias.cutLeft(1);
if (alias.endsWith("\"")) alias.cutRight(1);
}
}
if (line.endsWith("</file>")) line.cutRight(7).trim();
ParserEntry e = makeEntry(line, dir);
if (!alias.isEmpty()) e.alias = alias;
ps.files << e;
// piCout << "file =" << line << "alias =" << alias;
}
if (!ps.files.isEmpty()) ret << ps;
return ret;
}

View File

@@ -1,27 +1,27 @@
#ifndef PIRC_PARSER_H
#define PIRC_PARSER_H
#include "pidir.h"
#include "pifile.h"
struct ParserEntry {
ParserEntry(const PIString & n = PIString(), const PIString & a = PIString(), const PIString & p = PIString()) {
name = n;
alias = a;
path = p;
}
PIString name;
PIString alias;
PIString path;
};
struct ParserSection {
PIString name;
PIVector<ParserEntry> files;
};
PIVector<ParserSection> parse(const PIString & path);
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir);
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir);
#endif // PIRC_PARSER_H
#ifndef PIRC_PARSER_H
#define PIRC_PARSER_H
#include "pidir.h"
#include "pifile.h"
struct ParserEntry {
ParserEntry(const PIString & n = PIString(), const PIString & a = PIString(), const PIString & p = PIString()) {
name = n;
alias = a;
path = p;
}
PIString name;
PIString alias;
PIString path;
};
struct ParserSection {
PIString name;
PIVector<ParserEntry> files;
};
PIVector<ParserSection> parse(const PIString & path);
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir);
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir);
#endif // PIRC_PARSER_H

View File

@@ -1,885 +1,880 @@
#include "daemon.h"
#include "shared.h"
#include "pisysteminfo.h"
#include "picrypt.h"
const char self_name[] = "__self__";
extern PIScreen * screen;
extern PISystemMonitor sys_mon;
Daemon::Remote::Remote(const PIString & n): PIThread() {
setName(n);
term = 0;
ft.setName(n);
ft.setPacketSize(3984);
ft.setCRCEnabled(false);
CONNECTU(&ft, sendRequest, this, ftSendRequest)
CONNECTU(&ft, receiveFilesFinished, this, ftReceived)
CONNECTU(&ft, sendFilesFinished, this, ftSended)
CONNECTU(&term_timer, tickEvent, this, termTimerTick)
dir_my = PIDir::current();
}
Daemon::Remote::~Remote() {
shellClose();
ft.stop();
stopAndWait();
}
void Daemon::Remote::shellOpen() {
if (term) return;
piCoutObj << "shell open";
term = new PITerminal();
term->initialize();
term_timer.start(50);
}
void Daemon::Remote::shellClose() {
if (!term) return;
piCoutObj << "shell close";
term_timer.stop();
term->destroy();
delete term;
term = 0;
//piCoutObj << "shellClose ok";
}
void Daemon::Remote::shellResize(int w, int h) {
if (!term) return;
term->resize(w, h);
}
void Daemon::Remote::shellKeySend(PIKbdListener::KeyEvent k) {
if (!term) return;
term->write(k);
}
void Daemon::Remote::termTimerTick() {
if (!term) return;
PIVector<PIVector<PIScreenTypes::Cell> > cells = term->content();
if (pcells == cells) return;
pcells = cells;
PIByteArray ba;
ba << int(ShellContent) << cells;
//piCout << ba.size_s() << pcells.back().back().symbol.unicode16Code() << cells.back().back().symbol.unicode16Code();
sendRequest(name(), ba);
}
void Daemon::Remote::startAction(Daemon::PacketType a, const PIString & dir, const PIStringList & fl) {
_fl = fl;
if (!dir.isEmpty())
piForeach (PIString & s, _fl)
s.prepend(dir);
//piCout << "send" << _fl;
action = a;
startOnce();
}
void Daemon::Remote::run() {
PIDir d(dir_my);
switch (action) {
case CopyFiles:
ft.send(_fl);
break;
case RemoveFiles:
::removeFiles(d, _fl);
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case RequestChangeDir:
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case MkDir:
if (!_fl.isEmpty()) PIDir::make(d.absolutePath() + PIDir::separator + _fl.at(0));
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case CryptFiles:
piCoutObj << "CryptFiles";
if (!_fl.isEmpty()) {
PIString p = askUserInput("Password:");
::cryptFiles(d, _fl, PICrypt::hash(p));
}
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
default: break;
};
}
void Daemon::Remote::updateDirEntries() {
//piCout << dir_my;
if (!dir_my.isExists()) dir_my = PIDir::current();
my_filelist = dir_my.entries();
piForeach (PIFile::FileInfo & f, my_filelist) f.path = f.name();
}
Daemon::TileFileProgress::TileFileProgress(): PIScreenTile() {
size_policy = PIScreenTypes::Fixed;
ft = 0;
rec = false;
setMargins(1, 1, 1, 1);
spacing = 1;
back_format.color_back = Yellow;
label_file = new TileSimple();
label_speed = new TileSimple();
label_cnt = new TileSimple();
prog_file = new TileProgress();
prog_all = new TileProgress();
buttons = new TileButtons("fd_buttons");
buttons->content << TileButtons::Button("Pause", CellFormat());
buttons->content << TileButtons::Button("Cancel", CellFormat());
label_file->content.resize(1);
label_speed->content.resize(1);
label_cnt->content.resize(1);
buttons->back_format.color_back = Yellow;
label_file->back_format.color_back = label_speed->back_format.color_back = label_cnt->back_format.color_back = Yellow;
label_file->content[0].second = label_speed->content[0].second = label_cnt->content[0].second = CellFormat(Black, Transparent);
addTile(label_file);
addTile(label_speed);
addTile(label_cnt);
addTile(prog_file);
addTile(prog_all);
addTile(buttons);
CONNECTU((::screen), tileEvent, this, tileEvent)
}
void Daemon::TileFileProgress::resizeEvent(int w, int h) {
PIScreenTile::resizeEvent(w, h);
w = ::screen->windowWidth() / 1.4;
minimumWidth = maximumWidth = w;
}
void Daemon::TileFileProgress::sizeHint(int & w, int & h) const {
PIScreenTile::sizeHint(w, h);
w = ::screen->windowWidth() / 1.4;
}
void Daemon::TileFileProgress::drawEvent(PIScreenDrawer * d) {
if (ft) {
label_file->content[0].first = ft->stateString() + " " + ft->curFile();
if (!label_file->content[0].first.isEmpty())
label_file->content[0].first[0] = label_file->content[0].first[0].toUpper();
PIString spd("Speed: "), cnt;
if (ft->isReceiving()) spd = ft->diagnostic().receiveSpeed();
else spd = ft->diagnostic().sendSpeed().expandRightTo(10, ' ');
spd += " ETA: ";
if (!ft->isReceiving() && !ft->isSending()) {
tm.reset();
spd += "-";
} else {
double el = tm.elapsed_s();
int cb = ft->bytesCur();
if ((el <= 0.) || (cb <= 0)) spd += "-";
else {
double s = (el / cb) * (ft->bytesAll() - cb);
spd += readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(s)));
}
}
spd += " Elapsed: " + readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(tme.elapsed_s())));
label_speed->content[0].first = spd;
cnt = "File: " + PIString::readableSize(ft->bytesFileCur()).expandLeftTo(8, ' ');
cnt += " / " + PIString::readableSize(ft->bytesFileAll()).expandLeftTo(8, ' ');
cnt += " All: " + PIString::readableSize(ft->bytesCur()).expandLeftTo(8, ' ');
cnt += " / " + PIString::readableSize(ft->bytesAll()).expandLeftTo(8, ' ');
label_cnt->content[0].first = cnt;
if (ft->bytesFileAll() > 0)
prog_file->value = piRoundd(ft->bytesFileCur() / double(ft->bytesFileAll()) * 100.);
if (ft->bytesAll() > 0)
prog_all->value = piRoundd(ft->bytesCur() / double(ft->bytesAll()) * 100.);
}
PIScreenTile::drawEvent(d);
}
void Daemon::TileFileProgress::show(PIFileTransfer * f) {
ft = f;
if (ft) {
conn_name = ft->name();
::screen->setDialogTile(this);
label_file->content[0].first = "Preparing ...";
prog_file->value = prog_all->value = 0;
buttons->cur = 0;
buttons->setFocus();
tm.reset();
tme.reset();
}
}
void Daemon::TileFileProgress::close(bool ok) {
buttons->content[0].first = "Pause";
ft = 0;
::screen->setDialogTile(0);
if (!ok) {
piCout << "file transfer aborted";
showInfo("Error while file transfer, files may be invalid");
}
}
void Daemon::TileFileProgress::tileEvent(PIScreenTile * t, TileEvent e) {
if (t->name() == "fd_buttons") {
if (e.type != TileButtons::ButtonSelected || !ft) return;
switch (e.data.toInt()) {
case 0:
if (buttons->content[0].first == "Pause") {
buttons->content[0].first = "Resume";
ft->pause();
} else {
buttons->content[0].first = "Pause";
ft->resume();
}
break;
case 1:
ft->stop();
close();
break;
};
}
}
Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString::fromNumber(randomi() % 100)) {
// setName("Daemon");
dtimer.setName("__S__Daemon_timer");
mode = rmNone;
offset = cur = height = 0;
CONNECTU(screen, keyPressed, this, keyEvent)
CONNECTU(&dtimer, tickEvent, this, timerEvent)
CONNECTU(&fm, tileKey, this, fmKeyEvent)
CONNECTU(&fm, actionRequest, this, fmActionRequest)
_self = new Remote(self_name);
CONNECTU(_self, sendRequest, this, localSend)
CONNECTU(_self, receiveFinished, this, closeFileDialog)
CONNECTU(_self, sendFinished, this, closeFileDialog)
CONNECTU(_self, changeDirFinished, this, dirChanged)
localft.setName(self_name);
localft.setCRCEnabled(false);
CONNECTU(&localft, sendRequest, _self, received)
dtimer.addDelimiter(5);
dtimer.start(200);
tile_root = new PIScreenTile();
tile_root->direction = Vertical;
tile_header = new TileSimple("daemon header");
tile_header->size_policy = Fixed;
list_daemons = new TileList("daemons list");
list_daemons->hide();
list_actions = new TileList("actions list");
list_actions->hide();
list_actions->content << TileList::Row("Information", CellFormat());
list_actions->content << TileList::Row("File manager", CellFormat());
list_actions->content << TileList::Row("Shell", CellFormat());
tile_info = new TileSimple("daemon info");
tile_info->hide();
fm.setRemote();
tile_fm = fm.tile();
tile_fm->hide();
tile_file_progress = new TileFileProgress();
tile_shell = new TileTerminal("shell");
tile_shell->hide();
CONNECTU(tile_shell, resizeRequest, this, shResizeRequest)
CONNECTU(tile_shell, keyPressed, this, shKeyEvent)
CONNECTU(tile_shell, closeRequest, this, requestCloseShell)
CONNECTU(tile_shell, closeRequest, this, escPressed)
tile_root->addTile(tile_header);
tile_root->addTile(list_daemons);
tile_root->addTile(list_actions);
tile_root->addTile(tile_info);
tile_root->addTile(tile_fm);
tile_root->addTile(tile_shell);
CONNECTU(screen, tileEvent, this, tileEvent)
reinit();
inited__ = true;
}
Daemon::~Daemon() {
requestCloseShell();
PIVector<Remote*> rl = remotes.values();
piForeach (Remote * r, rl) {
r->shellClose();
delete r;
}
remotes.clear();
delete _self;
}
PIScreenTile * Daemon::tile() const {
return tile_root;
}
void Daemon::escPressed() {
if (mode == rmNone || mode == rmLocalFileManager)
menuRequest();
else {
if (mode > rmSelectMode) {
mode = rmSelectMode;
screen->lock();
tile_info->content.clear();
screen->unlock();
showActionList();
} else
disconnect();
}
}
void Daemon::shResizeRequest() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
PIByteArray ba;
ba << int(ShellResizeRequest) << int(tile_shell->width()) << int(tile_shell->height());
send(conn_name, ba);
}
void Daemon::shKeyEvent(PIKbdListener::KeyEvent k) {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
PIByteArray ba;
ba << int(ShellKeyEvent) << k;
send(conn_name, ba);
}
void Daemon::localSend(const PIString & p_name, const PIByteArray & data) {
//piCoutObj << "localSend" << localft.stateString();
PIByteArray h; h << int(FileTransfer);
PIByteArray ba = data;
ba.remove(0, h.size());
localft.received(ba);
}
void Daemon::hideAll() {
list_actions->hide();
tile_info->hide();
list_daemons->hide();
tile_fm->hide();
tile_shell->hide();
}
void Daemon::showTile(PIScreenTile * t, const PIString & header) {
hideAll();
t->show();
t->setFocus();
tile_header->content.resize(1);
tile_header->content[0].first = header;
tile_header->content[0].second.flags = Bold;
lock();
if (!conn_name.isEmpty())
tile_header->content[0].first.insert(0, PIString("Daemon \"") + connectedDaemon() + "\": ");
unlock();
}
void Daemon::fillInfoTile(const Daemon::HostInfo & hi) {
screen->lock();
tile_info->content.clear();
tile_info->content << TileSimple::Row("Exec command: " + hi.execCommand, CellFormat());
tile_info->content << TileSimple::Row(" Executed on " + hi.execDateTime.toString(), CellFormat());
tile_info->content << TileSimple::Row(" Hostname: " + hi.hostname, CellFormat());
tile_info->content << TileSimple::Row(" Username: " + hi.user, CellFormat());
tile_info->content << TileSimple::Row(" OS name: " + hi.OS_name, CellFormat());
tile_info->content << TileSimple::Row(" OS version: " + hi.OS_version, CellFormat());
tile_info->content << TileSimple::Row("Architecture: " + hi.architecture, CellFormat());
tile_info->content << TileSimple::Row(" CPU count: " + PIString::fromNumber(hi.processorsCount), CellFormat());
screen->unlock();
}
void Daemon::tileEvent(PIScreenTile * t, TileEvent e) {
if (t == list_daemons) {
if (e.type == TileList::RowPressed) {
PIMutexLocker ml(remote_mutex);
connectToDaemon(list_daemons->content[e.data.toInt()].first);
showActionList();
}
return;
}
if (t == list_actions) {
if (e.type == TileList::RowPressed) {
PIMutexLocker ml(remote_mutex);
switch (e.data.toInt()) {
case 0:
mode = rmInformation;
showTile(tile_info, "Information");
break;
case 1:
mode = rmFileManager;
showTile(tile_fm, "File manager");
requestChDir(".");
break;
case 2:
mode = rmShell;
showTile(tile_shell, "Shell");
requestOpenShell();
break;
default: break;
}
}
return;
}
}
void Daemon::keyEvent(PIKbdListener::KeyEvent key) {
if (!tile_root->visible) return;
if (screen->dialogTile()) return;
switch (key.key) {
case PIKbdListener::Esc:
escPressed();
break;
default: break;
}
}
void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) {
PIMutexLocker ml(remote_mutex);
// piCoutObj << key.key << key.modifiers;
switch (key.key) {
case PIKbdListener::Return:
{
PIFile::FileInfo fi = fm.currentRemoteEntry();
if (!fi.isDir()) break;
requestChDir(fi.name());
}
break;
case 'R':
requestChDir(".");
break;
default: break;
}
}
void Daemon::fmActionRequest(bool remote_tile, FileManager::Action type, PIVariant data) {
Remote * r = 0;
r = remotes.value(conn_name, 0);
if (!r && type != FileManager::LocalCopy && type != FileManager::LocalCrypt) return;
switch (type) {
case FileManager::Copy:
if (remote_tile) {
PIByteArray ba;
//piCout << fm.selectedRemote();
ba << int(CopyFiles) << fm.selectedRemote();
r->ft.setDirectory(fm.localDir());
send(conn_name, ba);
tile_file_progress->rec = true;
tile_file_progress->show(&(r->ft));
} else {
r->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
tile_file_progress->rec = false;
tile_file_progress->show(&(r->ft));
}
break;
case FileManager::Remove:
if (remote_tile) {
PIByteArray ba;
ba << int(RemoveFiles) << fm.selectedRemote();
send(conn_name, ba);
}
break;
case FileManager::MkDir:
if (remote_tile) {
PIByteArray ba;
ba << int(MkDir) << data.toString();
send(conn_name, ba);
}
break;
case FileManager::LocalCopy:
//piCoutObj << "localCopy";
if (remote_tile) {
localft.setDirectory(fm.localDir());
_self->sendFiles(fm.remoteDir() + PIDir::separator, data.toStringList());
} else {
localft.setDirectory(fm.remoteDir());
_self->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
}
tile_file_progress->rec = false;
tile_file_progress->show(&(_self->ft));
case FileManager::Crypt:
if (remote_tile) {
PIByteArray ba;
ba << int(CryptFiles) << fm.selectedRemote();
send(conn_name, ba);
} else {
_self->dir_my.setDir(fm.localDir());
_self->cryptFiles(data.toStringList());
}
break;
case FileManager::LocalCrypt:
piCoutObj << "LocalCrypt";
if (remote_tile) {
_self->dir_my.setDir(fm.remoteDir());
} else {
_self->dir_my.setDir(fm.localDir());
}
_self->cryptFiles(data.toStringList());
break;
default: break;
};
//piCout << remote_tile << type << data;
}
void Daemon::timerEvent(void * _d, int delim) {
screen->lock();
list_daemons->content.clear();
availableDaemons();
piForeachC (PIString & i, available_daemons)
list_daemons->content << TileList::Row(i, CellFormat());
screen->unlock();
if (delim == 5 && mode == rmInformation) {
if (conn_name.isEmpty()) return;
PIByteArray ba; ba << int(RequestHostInfo);
send(conn_name, ba);
//std::cout << "send " << std::hex << ba;
}
}
PIStringList Daemon::availableDaemons() {
available_daemons.clear();
lock();
piForeachC (PIPeer::PeerInfo & p, allPeers()) {
if (!p.name.startsWith(pisd_prefix)) continue;
available_daemons << p.name.mid(6);
}
unlock();
return available_daemons;
}
void Daemon::connectToDaemon(const PIString & dn) {
if (dn.isEmpty()) return;
conn_name = pisd_prefix + dn;
mode = rmSelectMode;
}
void Daemon::disconnect() {
screen->enableExitCapture(PIKbdListener::F10);
conn_name.clear();
mode = rmNone;
showMainList();
}
PIString Daemon::connectedDaemon() const {
return conn_name.mid(6);
}
void Daemon::peerConnected(const PIString & p_name) {
while (!inited__) piMSleep(PIP_MIN_MSLEEP*5);
if (!p_name.startsWith(pisd_prefix)) return;
Remote * r = new Remote(p_name);
piCoutObj << "peer connected" << p_name;
CONNECTU(r, sendRequest, this, sendRequest)
CONNECTU(r, receiveFinished, this, filesReceived)
CONNECTU(r, sendFinished, this, filesSended)
CONNECTU(r, changeDirFinished, this, dirChanged)
PIMutexLocker ml2(remote_mutex);
remotes.insert(p_name, r);
}
void Daemon::peerDisconnected(const PIString & p_name) {
while (!inited__) piMSleep(PIP_MIN_MSLEEP*5);
piCoutObj << "peer disconnect" << p_name;
if (p_name == conn_name) {
disconnect();
}
PIMutexLocker ml(remote_mutex);
Remote * dt = remotes.value(p_name, 0);
if (!dt) return;
dt->shellClose();
if (tile_file_progress->ft == &(dt->ft)) {
tile_file_progress->close(false);
}
remotes.remove(p_name);
delete dt;
}
void Daemon::filesReceived(const PIString & p_name, bool ok) {
if (ok) {
piCout << "files received from" << p_name;
} else {
piCout << "warning, files not received fromsended" << p_name;
}
closeFileDialog(p_name, ok);
Remote * r = remotes.value(p_name, 0);
if (!r) return;
r->updateDir();
}
void Daemon::filesSended(const PIString & p_name, bool ok) {
if (ok) {
piCout << "files sended to" << p_name;
} else {
piCout << "warning, files not sended to" << p_name;
}
closeFileDialog(p_name, ok);
}
void Daemon::dirChanged(const PIString & p_name, const PIString & dir) {
if (p_name == self_name) {
fm.clearSelectionLocal();
fm.clearSelectionRemote();
fm.updateLocalDir();
fm.updateRemoteDir();
return;
}
PIMutexLocker ml(remote_mutex);
Remote * r = remotes.value(p_name, 0);
if (!r) return;
if (r->dir_my.absolutePath() != dir) return;
sendDirToRemote(r);
}
void Daemon::closeFileDialog(const PIString & p_name, bool ok) {
//piCout << "CLOSE" << tile_file_progress->conn_name << name << ok;
if (p_name == self_name) {
tile_file_progress->close(ok);
fm.clearSelectionLocal();
fm.clearSelectionRemote();
fm.updateLocalDir();
fm.updateRemoteDir();
return;
}
//piCout << "file transfer with" << p_name << (ok ? "success" : "failure");
if (tile_file_progress->conn_name != p_name) return;
tile_file_progress->close(ok);
if (tile_file_progress->rec) {
fm.remoteTile()->setFocus();
fm.clearSelectionRemote();
fm.updateLocalDir();
} else {
fm.localTile()->setFocus();
fm.clearSelectionLocal();
requestChDir(".");
}
}
void Daemon::dataReceived(const PIString & from, const PIByteArray & data) {
// piCout << "rec" << data.size();
if (data.size() < 4) return;
PIMutexLocker ml(remote_mutex);
// piCout << "lock in dataReceived";
PIByteArray ba(data), rba;
Remote * r = remotes.value(from);
PIString dir;
int type; ba >> type;
//piCout << "rec from " << from << type << r;
switch (type) {
case RequestHostInfo:
makeMyHostInfo();
rba << int(ReplyHostInfo) << info_my;
break;
case RequestChangeDir:
if (!r) break;
ba >> dir;
r->dir_my.cd(dir);
r->ft.setDirectory(r->dir_my);
//piCout << "store to" << r->dir_my.absolutePath();
piCoutObj << "cd to" << r->dir_my.absolutePath();
r->updateDir();
break;
case ReplyHostInfo:
ba >> info_other;
makeOtherHostInfo();
fillInfoTile(info_other);
break;
case ReplyChangeDir:
if (!r) break;
{
PIVector<PIFile::FileInfo> fil;
ba >> dir >> fil;
fm.setRemoteDir(dir);
fm.setRemoteContent(fil);
fm.remoteRestoreDir();
}
break;
case CopyFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->sendFiles(r->dir_my.absolutePath() + PIDir::separator, files);
}
break;
case RemoveFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->removeFiles(files);
}
break;
case MkDir:
if (!r) return;
{
PIString dn;
ba >> dn;
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->makeDir(dn);
}
break;
case FileTransfer:
if (r) r->received(ba);
break;
case CryptFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
r->cryptFiles(files);
}
break;
case ShellOpen:
if (!r) return;
r->shellOpen();
break;
case ShellClose:
if (!r) return;
r->shellClose();
break;
case ShellContent: {
if (!r) return;
PIVector<PIVector<PIScreenTypes::Cell> > cells;
ba >> cells;
tile_shell->setContent(cells);
} break;
case ShellResizeRequest: {
if (!r) return;
int w, h;
ba >> w >> h;
r->shellResize(w, h);
} break;
case ShellKeyEvent: {
if (!r) return;
PIKbdListener::KeyEvent k;
ba >> k;
r->shellKeySend(k);
} break;
};
if (!rba.isEmpty()) send(from, rba);
}
void Daemon::sendDirToRemote(Remote * r) {
if (!r) return;
PIVector<PIFile::FileInfo> fil = r->my_filelist;
PIByteArray ba;
ba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil;
send(r->name(), ba);
}
void Daemon::requestOpenShell() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
screen->disableExitCapture();
PIByteArray ba;
ba << int(ShellOpen);
send(conn_name, ba);
executeQueued(this, "shResizeRequest");
}
void Daemon::requestCloseShell() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
screen->enableExitCapture(PIKbdListener::F10);
PIByteArray ba;
ba << int(ShellClose);
send(conn_name, ba);
}
void Daemon::makeMyHostInfo() {
info_my.execCommand = PISystemInfo::instance()->execCommand;
info_my.hostname = PISystemInfo::instance()->hostname;
info_my.user = PISystemInfo::instance()->user;
info_my.OS_name = PISystemInfo::instance()->OS_name;
info_my.OS_version = PISystemInfo::instance()->OS_version;
info_my.architecture = PISystemInfo::instance()->architecture;
info_my.execDateTime = PISystemInfo::instance()->execDateTime;
info_my.processorsCount = PISystemInfo::instance()->processorsCount;
info_my.ID = sys_mon.statistic().ID;
info_my.threads = sys_mon.statistic().threads;
info_my.priority = sys_mon.statistic().priority;
info_my.physical_memsize = sys_mon.statistic().physical_memsize;
info_my.share_memsize = sys_mon.statistic().share_memsize;
info_my.cpu_load_system = sys_mon.statistic().cpu_load_system;
info_my.cpu_load_user = sys_mon.statistic().cpu_load_user;
}
void Daemon::makeOtherHostInfo() {
PISystemMonitor::ProcessStats ps(sys_mon_other.statistic());
ps.ID = info_other.ID;
ps.threads = info_other.threads;
ps.priority = info_other.priority;
ps.physical_memsize = info_other.physical_memsize;
ps.share_memsize = info_other.share_memsize;
ps.cpu_load_system = info_other.cpu_load_system;
ps.cpu_load_user = info_other.cpu_load_user;
sys_mon_other.setStatistic(ps);
}
void Daemon::requestChDir(const PIString & d) {
if (d.isEmpty()) return;
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
fm.remoteSaveDir();
fm.readingRemote();
PIByteArray ba;
ba << int(RequestChangeDir) << d;
send(conn_name, ba);
}
#include "daemon.h"
#include "picrypt.h"
#include "pisysteminfo.h"
#include "shared.h"
const char self_name[] = "__self__";
extern PIScreen * screen;
extern PISystemMonitor sys_mon;
Daemon::Remote::Remote(const PIString & n): PIThread() {
setName(n);
term = 0;
ft.setName(n);
ft.setPacketSize(3984);
ft.setCRCEnabled(false);
CONNECTU(&ft, sendRequest, this, ftSendRequest)
CONNECTU(&ft, receiveFilesFinished, this, ftReceived)
CONNECTU(&ft, sendFilesFinished, this, ftSended)
CONNECTU(&term_timer, tickEvent, this, termTimerTick)
dir_my = PIDir::current();
}
Daemon::Remote::~Remote() {
shellClose();
ft.stop();
stopAndWait();
}
void Daemon::Remote::shellOpen() {
if (term) return;
piCoutObj << "shell open";
term = new PITerminal();
term->initialize();
term_timer.start(50);
}
void Daemon::Remote::shellClose() {
if (!term) return;
piCoutObj << "shell close";
term_timer.stop();
term->destroy();
delete term;
term = 0;
// piCoutObj << "shellClose ok";
}
void Daemon::Remote::shellResize(int w, int h) {
if (!term) return;
term->resize(w, h);
}
void Daemon::Remote::shellKeySend(PIKbdListener::KeyEvent k) {
if (!term) return;
term->write(k);
}
void Daemon::Remote::termTimerTick() {
if (!term) return;
PIVector<PIVector<PIScreenTypes::Cell>> cells = term->content();
if (pcells == cells) return;
pcells = cells;
PIByteArray ba;
ba << int(ShellContent) << cells;
// piCout << ba.size_s() << pcells.back().back().symbol.unicode16Code() << cells.back().back().symbol.unicode16Code();
sendRequest(name(), ba);
}
void Daemon::Remote::startAction(Daemon::PacketType a, const PIString & dir, const PIStringList & fl) {
_fl = fl;
if (!dir.isEmpty())
piForeach(PIString & s, _fl)
s.prepend(dir);
// piCout << "send" << _fl;
action = a;
startOnce();
}
void Daemon::Remote::run() {
PIDir d(dir_my);
switch (action) {
case CopyFiles: ft.send(_fl); break;
case RemoveFiles:
::removeFiles(d, _fl);
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case RequestChangeDir:
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case MkDir:
if (!_fl.isEmpty()) PIDir::make(d.absolutePath() + PIDir::separator + _fl.at(0));
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
case CryptFiles:
piCoutObj << "CryptFiles";
if (!_fl.isEmpty()) {
PIString p = askUserInput("Password:");
::cryptFiles(d, _fl, PICrypt::hash(p));
}
updateDirEntries();
changeDirFinished(name(), d.absolutePath());
break;
default: break;
};
}
void Daemon::Remote::updateDirEntries() {
// piCout << dir_my;
if (!dir_my.isExists()) dir_my = PIDir::current();
my_filelist = dir_my.entries();
piForeach(PIFile::FileInfo & f, my_filelist)
f.path = f.name();
}
Daemon::TileFileProgress::TileFileProgress(): PIScreenTile() {
size_policy = PIScreenTypes::Fixed;
ft = 0;
rec = false;
setMargins(1, 1, 1, 1);
spacing = 1;
back_format.color_back = Yellow;
label_file = new TileSimple();
label_speed = new TileSimple();
label_cnt = new TileSimple();
prog_file = new TileProgress();
prog_all = new TileProgress();
buttons = new TileButtons("fd_buttons");
buttons->content << TileButtons::Button("Pause", CellFormat());
buttons->content << TileButtons::Button("Cancel", CellFormat());
label_file->content.resize(1);
label_speed->content.resize(1);
label_cnt->content.resize(1);
buttons->back_format.color_back = Yellow;
label_file->back_format.color_back = label_speed->back_format.color_back = label_cnt->back_format.color_back = Yellow;
label_file->content[0].second = label_speed->content[0].second = label_cnt->content[0].second = CellFormat(Black, Transparent);
addTile(label_file);
addTile(label_speed);
addTile(label_cnt);
addTile(prog_file);
addTile(prog_all);
addTile(buttons);
CONNECTU((::screen), tileEvent, this, tileEvent)
}
void Daemon::TileFileProgress::resizeEvent(int w, int h) {
PIScreenTile::resizeEvent(w, h);
w = ::screen->windowWidth() / 1.4;
minimumWidth = maximumWidth = w;
}
void Daemon::TileFileProgress::sizeHint(int & w, int & h) const {
PIScreenTile::sizeHint(w, h);
w = ::screen->windowWidth() / 1.4;
}
void Daemon::TileFileProgress::drawEvent(PIScreenDrawer * d) {
if (ft) {
label_file->content[0].first = ft->stateString() + " " + ft->curFile();
if (!label_file->content[0].first.isEmpty()) label_file->content[0].first[0] = label_file->content[0].first[0].toUpper();
PIString spd("Speed: "), cnt;
if (ft->isReceiving())
spd = ft->diagnostic().receiveSpeed();
else
spd = ft->diagnostic().sendSpeed().expandRightTo(10, ' ');
spd += " ETA: ";
if (!ft->isReceiving() && !ft->isSending()) {
tm.reset();
spd += "-";
} else {
double el = tm.elapsed_s();
int cb = ft->bytesCur();
if ((el <= 0.) || (cb <= 0))
spd += "-";
else {
double s = (el / cb) * (ft->bytesAll() - cb);
spd += readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(s)));
}
}
spd += " Elapsed: " + readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(tme.elapsed_s())));
label_speed->content[0].first = spd;
cnt = "File: " + PIString::readableSize(ft->bytesFileCur()).expandLeftTo(8, ' ');
cnt += " / " + PIString::readableSize(ft->bytesFileAll()).expandLeftTo(8, ' ');
cnt += " All: " + PIString::readableSize(ft->bytesCur()).expandLeftTo(8, ' ');
cnt += " / " + PIString::readableSize(ft->bytesAll()).expandLeftTo(8, ' ');
label_cnt->content[0].first = cnt;
if (ft->bytesFileAll() > 0) prog_file->value = piRoundd(ft->bytesFileCur() / double(ft->bytesFileAll()) * 100.);
if (ft->bytesAll() > 0) prog_all->value = piRoundd(ft->bytesCur() / double(ft->bytesAll()) * 100.);
}
PIScreenTile::drawEvent(d);
}
void Daemon::TileFileProgress::show(PIFileTransfer * f) {
ft = f;
if (ft) {
conn_name = ft->name();
::screen->setDialogTile(this);
label_file->content[0].first = "Preparing ...";
prog_file->value = prog_all->value = 0;
buttons->cur = 0;
buttons->setFocus();
tm.reset();
tme.reset();
}
}
void Daemon::TileFileProgress::close(bool ok) {
buttons->content[0].first = "Pause";
ft = 0;
::screen->setDialogTile(0);
if (!ok) {
piCout << "file transfer aborted";
showInfo("Error while file transfer, files may be invalid");
}
}
void Daemon::TileFileProgress::tileEvent(PIScreenTile * t, TileEvent e) {
if (t->name() == "fd_buttons") {
if (e.type != TileButtons::ButtonSelected || !ft) return;
switch (e.data.toInt()) {
case 0:
if (buttons->content[0].first == "Pause") {
buttons->content[0].first = "Resume";
ft->pause();
} else {
buttons->content[0].first = "Pause";
ft->resume();
}
break;
case 1:
ft->stop();
close();
break;
};
}
}
Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString::fromNumber(randomi() % 100)) {
// setName("Daemon");
dtimer.setName("__S__Daemon_timer");
mode = rmNone;
offset = cur = height = 0;
CONNECTU(screen, keyPressed, this, keyEvent)
CONNECTU(&dtimer, tickEvent, this, timerEvent)
CONNECTU(&fm, tileKey, this, fmKeyEvent)
CONNECTU(&fm, actionRequest, this, fmActionRequest)
_self = new Remote(self_name);
CONNECTU(_self, sendRequest, this, localSend)
CONNECTU(_self, receiveFinished, this, closeFileDialog)
CONNECTU(_self, sendFinished, this, closeFileDialog)
CONNECTU(_self, changeDirFinished, this, dirChanged)
localft.setName(self_name);
localft.setCRCEnabled(false);
CONNECTU(&localft, sendRequest, _self, received)
dtimer.addDelimiter(5);
dtimer.start(200);
tile_root = new PIScreenTile();
tile_root->direction = Vertical;
tile_header = new TileSimple("daemon header");
tile_header->size_policy = Fixed;
list_daemons = new TileList("daemons list");
list_daemons->hide();
list_actions = new TileList("actions list");
list_actions->hide();
list_actions->content << TileList::Row("Information", CellFormat());
list_actions->content << TileList::Row("File manager", CellFormat());
list_actions->content << TileList::Row("Shell", CellFormat());
tile_info = new TileSimple("daemon info");
tile_info->hide();
fm.setRemote();
tile_fm = fm.tile();
tile_fm->hide();
tile_file_progress = new TileFileProgress();
tile_shell = new TileTerminal("shell");
tile_shell->hide();
CONNECTU(tile_shell, resizeRequest, this, shResizeRequest)
CONNECTU(tile_shell, keyPressed, this, shKeyEvent)
CONNECTU(tile_shell, closeRequest, this, requestCloseShell)
CONNECTU(tile_shell, closeRequest, this, escPressed)
tile_root->addTile(tile_header);
tile_root->addTile(list_daemons);
tile_root->addTile(list_actions);
tile_root->addTile(tile_info);
tile_root->addTile(tile_fm);
tile_root->addTile(tile_shell);
CONNECTU(screen, tileEvent, this, tileEvent)
reinit();
inited__ = true;
}
Daemon::~Daemon() {
requestCloseShell();
PIVector<Remote *> rl = remotes.values();
piForeach(Remote * r, rl) {
r->shellClose();
delete r;
}
remotes.clear();
delete _self;
}
PIScreenTile * Daemon::tile() const {
return tile_root;
}
void Daemon::escPressed() {
if (mode == rmNone || mode == rmLocalFileManager)
menuRequest();
else {
if (mode > rmSelectMode) {
mode = rmSelectMode;
screen->lock();
tile_info->content.clear();
screen->unlock();
showActionList();
} else
disconnect();
}
}
void Daemon::shResizeRequest() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
PIByteArray ba;
ba << int(ShellResizeRequest) << int(tile_shell->width()) << int(tile_shell->height());
send(conn_name, ba);
}
void Daemon::shKeyEvent(PIKbdListener::KeyEvent k) {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
PIByteArray ba;
ba << int(ShellKeyEvent) << k;
send(conn_name, ba);
}
void Daemon::localSend(const PIString & p_name, const PIByteArray & data) {
// piCoutObj << "localSend" << localft.stateString();
PIByteArray h;
h << int(FileTransfer);
PIByteArray ba = data;
ba.remove(0, h.size());
localft.received(ba);
}
void Daemon::hideAll() {
list_actions->hide();
tile_info->hide();
list_daemons->hide();
tile_fm->hide();
tile_shell->hide();
}
void Daemon::showTile(PIScreenTile * t, const PIString & header) {
hideAll();
t->show();
t->setFocus();
tile_header->content.resize(1);
tile_header->content[0].first = header;
tile_header->content[0].second.flags = Bold;
lock();
if (!conn_name.isEmpty()) tile_header->content[0].first.insert(0, PIString("Daemon \"") + connectedDaemon() + "\": ");
unlock();
}
void Daemon::fillInfoTile(const Daemon::HostInfo & hi) {
screen->lock();
tile_info->content.clear();
tile_info->content << TileSimple::Row("Exec command: " + hi.execCommand, CellFormat());
tile_info->content << TileSimple::Row(" Executed on " + hi.execDateTime.toString(), CellFormat());
tile_info->content << TileSimple::Row(" Hostname: " + hi.hostname, CellFormat());
tile_info->content << TileSimple::Row(" Username: " + hi.user, CellFormat());
tile_info->content << TileSimple::Row(" OS name: " + hi.OS_name, CellFormat());
tile_info->content << TileSimple::Row(" OS version: " + hi.OS_version, CellFormat());
tile_info->content << TileSimple::Row("Architecture: " + hi.architecture, CellFormat());
tile_info->content << TileSimple::Row(" CPU count: " + PIString::fromNumber(hi.processorsCount), CellFormat());
screen->unlock();
}
void Daemon::tileEvent(PIScreenTile * t, TileEvent e) {
if (t == list_daemons) {
if (e.type == TileList::RowPressed) {
PIMutexLocker ml(remote_mutex);
connectToDaemon(list_daemons->content[e.data.toInt()].first);
showActionList();
}
return;
}
if (t == list_actions) {
if (e.type == TileList::RowPressed) {
PIMutexLocker ml(remote_mutex);
switch (e.data.toInt()) {
case 0:
mode = rmInformation;
showTile(tile_info, "Information");
break;
case 1:
mode = rmFileManager;
showTile(tile_fm, "File manager");
requestChDir(".");
break;
case 2:
mode = rmShell;
showTile(tile_shell, "Shell");
requestOpenShell();
break;
default: break;
}
}
return;
}
}
void Daemon::keyEvent(PIKbdListener::KeyEvent key) {
if (!tile_root->visible) return;
if (screen->dialogTile()) return;
switch (key.key) {
case PIKbdListener::Esc: escPressed(); break;
default: break;
}
}
void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) {
PIMutexLocker ml(remote_mutex);
// piCoutObj << key.key << key.modifiers;
switch (key.key) {
case PIKbdListener::Return: {
PIFile::FileInfo fi = fm.currentRemoteEntry();
if (!fi.isDir()) break;
requestChDir(fi.name());
} break;
case 'R': requestChDir("."); break;
default: break;
}
}
void Daemon::fmActionRequest(bool remote_tile, FileManager::Action type, PIVariant data) {
Remote * r = 0;
r = remotes.value(conn_name, 0);
if (!r && type != FileManager::LocalCopy && type != FileManager::LocalCrypt) return;
switch (type) {
case FileManager::Copy:
if (remote_tile) {
PIByteArray ba;
// piCout << fm.selectedRemote();
ba << int(CopyFiles) << fm.selectedRemote();
r->ft.setDirectory(fm.localDir());
send(conn_name, ba);
tile_file_progress->rec = true;
tile_file_progress->show(&(r->ft));
} else {
r->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
tile_file_progress->rec = false;
tile_file_progress->show(&(r->ft));
}
break;
case FileManager::Remove:
if (remote_tile) {
PIByteArray ba;
ba << int(RemoveFiles) << fm.selectedRemote();
send(conn_name, ba);
}
break;
case FileManager::MkDir:
if (remote_tile) {
PIByteArray ba;
ba << int(MkDir) << data.toString();
send(conn_name, ba);
}
break;
case FileManager::LocalCopy:
// piCoutObj << "localCopy";
if (remote_tile) {
localft.setDirectory(fm.localDir());
_self->sendFiles(fm.remoteDir() + PIDir::separator, data.toStringList());
} else {
localft.setDirectory(fm.remoteDir());
_self->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
}
tile_file_progress->rec = false;
tile_file_progress->show(&(_self->ft));
case FileManager::Crypt:
if (remote_tile) {
PIByteArray ba;
ba << int(CryptFiles) << fm.selectedRemote();
send(conn_name, ba);
} else {
_self->dir_my.setDir(fm.localDir());
_self->cryptFiles(data.toStringList());
}
break;
case FileManager::LocalCrypt:
piCoutObj << "LocalCrypt";
if (remote_tile) {
_self->dir_my.setDir(fm.remoteDir());
} else {
_self->dir_my.setDir(fm.localDir());
}
_self->cryptFiles(data.toStringList());
break;
default: break;
};
// piCout << remote_tile << type << data;
}
void Daemon::timerEvent(void * _d, int delim) {
screen->lock();
list_daemons->content.clear();
availableDaemons();
piForeachC(PIString & i, available_daemons)
list_daemons->content << TileList::Row(i, CellFormat());
screen->unlock();
if (delim == 5 && mode == rmInformation) {
if (conn_name.isEmpty()) return;
PIByteArray ba;
ba << int(RequestHostInfo);
send(conn_name, ba);
// std::cout << "send " << std::hex << ba;
}
}
PIStringList Daemon::availableDaemons() {
available_daemons.clear();
lock();
piForeachC(PIPeer::PeerInfo & p, allPeers()) {
if (!p.name.startsWith(pisd_prefix)) continue;
available_daemons << p.name.mid(6);
}
unlock();
return available_daemons;
}
void Daemon::connectToDaemon(const PIString & dn) {
if (dn.isEmpty()) return;
conn_name = pisd_prefix + dn;
mode = rmSelectMode;
}
void Daemon::disconnect() {
screen->enableExitCapture(PIKbdListener::F10);
conn_name.clear();
mode = rmNone;
showMainList();
}
PIString Daemon::connectedDaemon() const {
return conn_name.mid(6);
}
void Daemon::peerConnected(const PIString & p_name) {
while (!inited__)
piMSleep(PIP_MIN_MSLEEP * 5);
if (!p_name.startsWith(pisd_prefix)) return;
Remote * r = new Remote(p_name);
piCoutObj << "peer connected" << p_name;
CONNECTU(r, sendRequest, this, sendRequest)
CONNECTU(r, receiveFinished, this, filesReceived)
CONNECTU(r, sendFinished, this, filesSended)
CONNECTU(r, changeDirFinished, this, dirChanged)
PIMutexLocker ml2(remote_mutex);
remotes.insert(p_name, r);
}
void Daemon::peerDisconnected(const PIString & p_name) {
while (!inited__)
piMSleep(PIP_MIN_MSLEEP * 5);
piCoutObj << "peer disconnect" << p_name;
if (p_name == conn_name) {
disconnect();
}
PIMutexLocker ml(remote_mutex);
Remote * dt = remotes.value(p_name, 0);
if (!dt) return;
dt->shellClose();
if (tile_file_progress->ft == &(dt->ft)) {
tile_file_progress->close(false);
}
remotes.remove(p_name);
delete dt;
}
void Daemon::filesReceived(const PIString & p_name, bool ok) {
if (ok) {
piCout << "files received from" << p_name;
} else {
piCout << "warning, files not received fromsended" << p_name;
}
closeFileDialog(p_name, ok);
Remote * r = remotes.value(p_name, 0);
if (!r) return;
r->updateDir();
}
void Daemon::filesSended(const PIString & p_name, bool ok) {
if (ok) {
piCout << "files sended to" << p_name;
} else {
piCout << "warning, files not sended to" << p_name;
}
closeFileDialog(p_name, ok);
}
void Daemon::dirChanged(const PIString & p_name, const PIString & dir) {
if (p_name == self_name) {
fm.clearSelectionLocal();
fm.clearSelectionRemote();
fm.updateLocalDir();
fm.updateRemoteDir();
return;
}
PIMutexLocker ml(remote_mutex);
Remote * r = remotes.value(p_name, 0);
if (!r) return;
if (r->dir_my.absolutePath() != dir) return;
sendDirToRemote(r);
}
void Daemon::closeFileDialog(const PIString & p_name, bool ok) {
// piCout << "CLOSE" << tile_file_progress->conn_name << name << ok;
if (p_name == self_name) {
tile_file_progress->close(ok);
fm.clearSelectionLocal();
fm.clearSelectionRemote();
fm.updateLocalDir();
fm.updateRemoteDir();
return;
}
// piCout << "file transfer with" << p_name << (ok ? "success" : "failure");
if (tile_file_progress->conn_name != p_name) return;
tile_file_progress->close(ok);
if (tile_file_progress->rec) {
fm.remoteTile()->setFocus();
fm.clearSelectionRemote();
fm.updateLocalDir();
} else {
fm.localTile()->setFocus();
fm.clearSelectionLocal();
requestChDir(".");
}
}
void Daemon::dataReceived(const PIString & from, const PIByteArray & data) {
// piCout << "rec" << data.size();
if (data.size() < 4) return;
PIMutexLocker ml(remote_mutex);
// piCout << "lock in dataReceived";
PIByteArray ba(data), rba;
Remote * r = remotes.value(from);
PIString dir;
int type;
ba >> type;
// piCout << "rec from " << from << type << r;
switch (type) {
case RequestHostInfo:
makeMyHostInfo();
rba << int(ReplyHostInfo) << info_my;
break;
case RequestChangeDir:
if (!r) break;
ba >> dir;
r->dir_my.cd(dir);
r->ft.setDirectory(r->dir_my);
// piCout << "store to" << r->dir_my.absolutePath();
piCoutObj << "cd to" << r->dir_my.absolutePath();
r->updateDir();
break;
case ReplyHostInfo:
ba >> info_other;
makeOtherHostInfo();
fillInfoTile(info_other);
break;
case ReplyChangeDir:
if (!r) break;
{
PIVector<PIFile::FileInfo> fil;
ba >> dir >> fil;
fm.setRemoteDir(dir);
fm.setRemoteContent(fil);
fm.remoteRestoreDir();
}
break;
case CopyFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->sendFiles(r->dir_my.absolutePath() + PIDir::separator, files);
}
break;
case RemoveFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->removeFiles(files);
}
break;
case MkDir:
if (!r) return;
{
PIString dn;
ba >> dn;
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
r->makeDir(dn);
}
break;
case FileTransfer:
if (r) r->received(ba);
break;
case CryptFiles:
if (!r) return;
if (r->isRunning()) return;
{
PIStringList files;
ba >> files;
r->cryptFiles(files);
}
break;
case ShellOpen:
if (!r) return;
r->shellOpen();
break;
case ShellClose:
if (!r) return;
r->shellClose();
break;
case ShellContent: {
if (!r) return;
PIVector<PIVector<PIScreenTypes::Cell>> cells;
ba >> cells;
tile_shell->setContent(cells);
} break;
case ShellResizeRequest: {
if (!r) return;
int w, h;
ba >> w >> h;
r->shellResize(w, h);
} break;
case ShellKeyEvent: {
if (!r) return;
PIKbdListener::KeyEvent k;
ba >> k;
r->shellKeySend(k);
} break;
};
if (!rba.isEmpty()) send(from, rba);
}
void Daemon::sendDirToRemote(Remote * r) {
if (!r) return;
PIVector<PIFile::FileInfo> fil = r->my_filelist;
PIByteArray ba;
ba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil;
send(r->name(), ba);
}
void Daemon::requestOpenShell() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
screen->disableExitCapture();
PIByteArray ba;
ba << int(ShellOpen);
send(conn_name, ba);
executeQueued(this, "shResizeRequest");
}
void Daemon::requestCloseShell() {
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
screen->enableExitCapture(PIKbdListener::F10);
PIByteArray ba;
ba << int(ShellClose);
send(conn_name, ba);
}
void Daemon::makeMyHostInfo() {
info_my.execCommand = PISystemInfo::instance()->execCommand;
info_my.hostname = PISystemInfo::instance()->hostname;
info_my.user = PISystemInfo::instance()->user;
info_my.OS_name = PISystemInfo::instance()->OS_name;
info_my.OS_version = PISystemInfo::instance()->OS_version;
info_my.architecture = PISystemInfo::instance()->architecture;
info_my.execDateTime = PISystemInfo::instance()->execDateTime;
info_my.processorsCount = PISystemInfo::instance()->processorsCount;
info_my.ID = sys_mon.statistic().ID;
info_my.threads = sys_mon.statistic().threads;
info_my.priority = sys_mon.statistic().priority;
info_my.physical_memsize = sys_mon.statistic().physical_memsize;
info_my.share_memsize = sys_mon.statistic().share_memsize;
info_my.cpu_load_system = sys_mon.statistic().cpu_load_system;
info_my.cpu_load_user = sys_mon.statistic().cpu_load_user;
}
void Daemon::makeOtherHostInfo() {
PISystemMonitor::ProcessStats ps(sys_mon_other.statistic());
ps.ID = info_other.ID;
ps.threads = info_other.threads;
ps.priority = info_other.priority;
ps.physical_memsize = info_other.physical_memsize;
ps.share_memsize = info_other.share_memsize;
ps.cpu_load_system = info_other.cpu_load_system;
ps.cpu_load_user = info_other.cpu_load_user;
sys_mon_other.setStatistic(ps);
}
void Daemon::requestChDir(const PIString & d) {
if (d.isEmpty()) return;
Remote * r = remotes.value(conn_name, 0);
if (!r) return;
fm.remoteSaveDir();
fm.readingRemote();
PIByteArray ba;
ba << int(RequestChangeDir) << d;
send(conn_name, ba);
}

View File

@@ -1,215 +1,219 @@
#ifndef DAEMON_H
#define DAEMON_H
#include "piscreentiles.h"
#include "pipeer.h"
#include "pisystemmonitor.h"
#include "pidatatransfer.h"
#include "pifiletransfer.h"
#include "file_manager.h"
#include "terminal_tile.h"
#include "piterminal.h"
extern PISystemMonitor sys_mon;
class Daemon: public PIPeer {
PIOBJECT_SUBCLASS(Daemon, PIPeer)
public:
Daemon();
~Daemon();
struct HostInfo {
HostInfo() {
processorsCount = ID = threads = priority = -1;
physical_memsize = share_memsize = 0;
cpu_load_system = cpu_load_user = 0.;
}
PIString execCommand;
PIString hostname;
PIString user;
PIString OS_name;
PIString OS_version;
PIString architecture;
PIDateTime execDateTime;
int processorsCount;
int ID;
int threads;
int priority;
ulong physical_memsize;
ulong share_memsize;
float cpu_load_system;
float cpu_load_user;
};
void showMainList() {showTile(list_daemons, "Select daemon");}
void showActionList() {showTile(list_actions, "Select action");}
void showLocalFilemanager() {mode = rmLocalFileManager; showTile(tile_fm, "File manager");}
PIStringList availableDaemons();
void connectToDaemon(const PIString & dn);
void disconnect();
PIString connectedDaemon() const;
PIString thisDaemonName() const {return selfInfo().name.mid(6);}
PIScreenTile * tile() const;
FileManager fm;
private:
enum PacketType {
RequestHostInfo = 10,
RequestChangeDir,
ReplyHostInfo = 20,
ReplyChangeDir,
CopyFiles,
RemoveFiles,
MkDir,
CryptFiles,
FileTransfer = 30,
ShellOpen = 40,
ShellClose,
ShellContent,
ShellResizeRequest,
ShellKeyEvent
};
enum RemoteMode {
rmNone,
rmLocalFileManager,
rmSelectMode,
rmInformation,
rmFileManager,
rmShell
};
class Remote: public PIThread {
PIOBJECT_SUBCLASS(Remote, PIThread)
public:
explicit Remote(const PIString & n = PIString());
~Remote();
void sendFiles(const PIString & dir, const PIStringList & fl) {startAction(Daemon::CopyFiles, dir, fl);}
void removeFiles(const PIStringList & fl) {startAction(Daemon::RemoveFiles, PIString(), fl);}
void updateDir() {startAction(Daemon::RequestChangeDir, PIString(), PIStringList());}
void makeDir(const PIString & dir) {startAction(Daemon::MkDir, dir, PIStringList() << "");}
void cryptFiles(const PIStringList & fl) {startAction(Daemon::CryptFiles, PIString(), fl);}
void shellOpen();
void shellClose();
void shellResize(int w, int h);
void shellKeySend(PIKbdListener::KeyEvent k);
EVENT_HANDLER1(void, ftSendRequest, PIByteArray &, data) {PIByteArray h; h << int(FileTransfer); data.insert(0, h); sendRequest(name(), data);}
EVENT_HANDLER1(void, ftReceived, bool, ok) {receiveFinished(name(), ok);}
EVENT_HANDLER1(void, ftSended, bool, ok) {sendFinished(name(), ok);}
EVENT2(sendRequest, const PIString &, p_name, const PIByteArray &, data)
EVENT2(receiveFinished, const PIString & , p_name, bool, ok)
EVENT2(sendFinished, const PIString & , p_name, bool, ok)
EVENT2(changeDirFinished, const PIString & , p_name, const PIString & , dir)
EVENT_HANDLER1(void, received, PIByteArray & , data) {ft.received(data);}
EVENT_HANDLER(void, termTimerTick);
void startAction(PacketType a, const PIString & dir, const PIStringList & fl);
void run() override;
PIDir dir_my;
PIVector<PIFile::FileInfo> my_filelist;
PIVector<PIVector<PIScreenTypes::Cell> > pcells;
PIFileTransfer ft;
PIStringList _fl;
PacketType action;
PITimer term_timer;
PITerminal * term;
private:
void updateDirEntries();
};
class TileFileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileFileProgress, PIScreenTile)
public:
TileFileProgress();
void show(PIFileTransfer * f);
void close(bool ok = true);
TileSimple * label_file, * label_speed, * label_cnt;
TileProgress * prog_file, * prog_all;
TileButtons * buttons;
PIFileTransfer * ft;
PITimeMeasurer tm, tme;
void resizeEvent(int w, int h) override;
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool rec;
PIString conn_name;
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
};
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key);
EVENT_HANDLER2(void, sendRequest, const PIString &, p_name, const PIByteArray &, data) {send(p_name, data);}
EVENT_HANDLER1(void, fmKeyEvent, PIKbdListener::KeyEvent, key);
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
EVENT_HANDLER (void, shResizeRequest);
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
EVENT_HANDLER2(void, timerEvent, void * , _d, int, delim);
EVENT_HANDLER2(void, filesReceived, const PIString & , p_name, bool, ok);
EVENT_HANDLER2(void, filesSended, const PIString & , p_name, bool, ok);
EVENT_HANDLER2(void, dirChanged, const PIString & , p_name, const PIString & , dir);
EVENT_HANDLER2(void, closeFileDialog, const PIString & , p_name, bool, ok);
EVENT_HANDLER2(void, localSend, const PIString & , p_name, const PIByteArray &, data);
EVENT_HANDLER (void, escPressed);
EVENT_HANDLER (void, requestOpenShell);
EVENT_HANDLER (void, requestCloseShell);
EVENT(menuRequest)
void hideAll();
void showTile(PIScreenTile * t, const PIString & header = PIString());
void fillInfoTile(const HostInfo & hi);
void peerConnected(const PIString & p_name) override;
void peerDisconnected(const PIString & p_name) override;
void dataReceived(const PIString & from, const PIByteArray & data) override;
void makeMyHostInfo();
void makeOtherHostInfo();
void requestChDir(const PIString & d);
void sendDirToRemote(Remote * r);
mutable PIStringList available_daemons;
PITimer dtimer;
PIString conn_name;
PIMutex remote_mutex;
PIMap<PIString, Remote*> remotes;
PISystemMonitor sys_mon_other;
HostInfo info_my, info_other;
PIScreenTile * tile_root, * tile_fm;
TileSimple * tile_info, * tile_header;
TileList * list_daemons, * list_actions;
TileFileProgress * tile_file_progress;
TileTerminal * tile_shell;
PIFileTransfer localft;
Remote * _self;
RemoteMode mode;
int offset, cur, height;
};
BINARY_STREAM_WRITE(Daemon::HostInfo) {
s << v.execCommand << v.hostname << v.user << v.OS_name
<< v.OS_version << v.architecture << v.execDateTime
<< v.processorsCount << v.ID << v.threads << v.priority
<< v.physical_memsize << v.share_memsize
<< v.cpu_load_system << v.cpu_load_user;
return s;
}
BINARY_STREAM_READ (Daemon::HostInfo) {
s >> v.execCommand >> v.hostname >> v.user >> v.OS_name
>> v.OS_version >> v.architecture >> v.execDateTime
>> v.processorsCount >> v.ID >> v.threads >> v.priority
>> v.physical_memsize >> v.share_memsize
>> v.cpu_load_system >> v.cpu_load_user;
return s;
}
#endif // DAEMON_H
#ifndef DAEMON_H
#define DAEMON_H
#include "file_manager.h"
#include "pidatatransfer.h"
#include "pifiletransfer.h"
#include "pipeer.h"
#include "piscreentiles.h"
#include "pisystemmonitor.h"
#include "piterminal.h"
#include "terminal_tile.h"
extern PISystemMonitor sys_mon;
class Daemon: public PIPeer {
PIOBJECT_SUBCLASS(Daemon, PIPeer)
public:
Daemon();
~Daemon();
struct HostInfo {
HostInfo() {
processorsCount = ID = threads = priority = -1;
physical_memsize = share_memsize = 0;
cpu_load_system = cpu_load_user = 0.;
}
PIString execCommand;
PIString hostname;
PIString user;
PIString OS_name;
PIString OS_version;
PIString architecture;
PIDateTime execDateTime;
int processorsCount;
int ID;
int threads;
int priority;
ulong physical_memsize;
ulong share_memsize;
float cpu_load_system;
float cpu_load_user;
};
void showMainList() { showTile(list_daemons, "Select daemon"); }
void showActionList() { showTile(list_actions, "Select action"); }
void showLocalFilemanager() {
mode = rmLocalFileManager;
showTile(tile_fm, "File manager");
}
PIStringList availableDaemons();
void connectToDaemon(const PIString & dn);
void disconnect();
PIString connectedDaemon() const;
PIString thisDaemonName() const { return selfInfo().name.mid(6); }
PIScreenTile * tile() const;
FileManager fm;
private:
enum PacketType {
RequestHostInfo = 10,
RequestChangeDir,
ReplyHostInfo = 20,
ReplyChangeDir,
CopyFiles,
RemoveFiles,
MkDir,
CryptFiles,
FileTransfer = 30,
ShellOpen = 40,
ShellClose,
ShellContent,
ShellResizeRequest,
ShellKeyEvent
};
enum RemoteMode {
rmNone,
rmLocalFileManager,
rmSelectMode,
rmInformation,
rmFileManager,
rmShell
};
class Remote: public PIThread {
PIOBJECT_SUBCLASS(Remote, PIThread)
public:
explicit Remote(const PIString & n = PIString());
~Remote();
void sendFiles(const PIString & dir, const PIStringList & fl) { startAction(Daemon::CopyFiles, dir, fl); }
void removeFiles(const PIStringList & fl) { startAction(Daemon::RemoveFiles, PIString(), fl); }
void updateDir() { startAction(Daemon::RequestChangeDir, PIString(), PIStringList()); }
void makeDir(const PIString & dir) { startAction(Daemon::MkDir, dir, PIStringList() << ""); }
void cryptFiles(const PIStringList & fl) { startAction(Daemon::CryptFiles, PIString(), fl); }
void shellOpen();
void shellClose();
void shellResize(int w, int h);
void shellKeySend(PIKbdListener::KeyEvent k);
EVENT_HANDLER1(void, ftSendRequest, PIByteArray &, data) {
PIByteArray h;
h << int(FileTransfer);
data.insert(0, h);
sendRequest(name(), data);
}
EVENT_HANDLER1(void, ftReceived, bool, ok) { receiveFinished(name(), ok); }
EVENT_HANDLER1(void, ftSended, bool, ok) { sendFinished(name(), ok); }
EVENT2(sendRequest, const PIString &, p_name, const PIByteArray &, data)
EVENT2(receiveFinished, const PIString &, p_name, bool, ok)
EVENT2(sendFinished, const PIString &, p_name, bool, ok)
EVENT2(changeDirFinished, const PIString &, p_name, const PIString &, dir)
EVENT_HANDLER1(void, received, PIByteArray &, data) { ft.received(data); }
EVENT_HANDLER(void, termTimerTick);
void startAction(PacketType a, const PIString & dir, const PIStringList & fl);
void run() override;
PIDir dir_my;
PIVector<PIFile::FileInfo> my_filelist;
PIVector<PIVector<PIScreenTypes::Cell>> pcells;
PIFileTransfer ft;
PIStringList _fl;
PacketType action;
PITimer term_timer;
PITerminal * term;
private:
void updateDirEntries();
};
class TileFileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileFileProgress, PIScreenTile)
public:
TileFileProgress();
void show(PIFileTransfer * f);
void close(bool ok = true);
TileSimple *label_file, *label_speed, *label_cnt;
TileProgress *prog_file, *prog_all;
TileButtons * buttons;
PIFileTransfer * ft;
PITimeMeasurer tm, tme;
void resizeEvent(int w, int h) override;
void sizeHint(int & w, int & h) const override;
void drawEvent(PIScreenDrawer * d) override;
bool rec;
PIString conn_name;
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
};
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key);
EVENT_HANDLER2(void, sendRequest, const PIString &, p_name, const PIByteArray &, data) { send(p_name, data); }
EVENT_HANDLER1(void, fmKeyEvent, PIKbdListener::KeyEvent, key);
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
EVENT_HANDLER(void, shResizeRequest);
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
EVENT_HANDLER2(void, timerEvent, void *, _d, int, delim);
EVENT_HANDLER2(void, filesReceived, const PIString &, p_name, bool, ok);
EVENT_HANDLER2(void, filesSended, const PIString &, p_name, bool, ok);
EVENT_HANDLER2(void, dirChanged, const PIString &, p_name, const PIString &, dir);
EVENT_HANDLER2(void, closeFileDialog, const PIString &, p_name, bool, ok);
EVENT_HANDLER2(void, localSend, const PIString &, p_name, const PIByteArray &, data);
EVENT_HANDLER(void, escPressed);
EVENT_HANDLER(void, requestOpenShell);
EVENT_HANDLER(void, requestCloseShell);
EVENT(menuRequest)
void hideAll();
void showTile(PIScreenTile * t, const PIString & header = PIString());
void fillInfoTile(const HostInfo & hi);
void peerConnected(const PIString & p_name) override;
void peerDisconnected(const PIString & p_name) override;
void dataReceived(const PIString & from, const PIByteArray & data) override;
void makeMyHostInfo();
void makeOtherHostInfo();
void requestChDir(const PIString & d);
void sendDirToRemote(Remote * r);
mutable PIStringList available_daemons;
PITimer dtimer;
PIString conn_name;
PIMutex remote_mutex;
PIMap<PIString, Remote *> remotes;
PISystemMonitor sys_mon_other;
HostInfo info_my, info_other;
PIScreenTile *tile_root, *tile_fm;
TileSimple *tile_info, *tile_header;
TileList *list_daemons, *list_actions;
TileFileProgress * tile_file_progress;
TileTerminal * tile_shell;
PIFileTransfer localft;
Remote * _self;
RemoteMode mode;
int offset, cur, height;
};
BINARY_STREAM_WRITE(Daemon::HostInfo) {
s << v.execCommand << v.hostname << v.user << v.OS_name << v.OS_version << v.architecture << v.execDateTime << v.processorsCount << v.ID
<< v.threads << v.priority << v.physical_memsize << v.share_memsize << v.cpu_load_system << v.cpu_load_user;
return s;
}
BINARY_STREAM_READ(Daemon::HostInfo) {
s >> v.execCommand >> v.hostname >> v.user >> v.OS_name >> v.OS_version >> v.architecture >> v.execDateTime >> v.processorsCount >>
v.ID >> v.threads >> v.priority >> v.physical_memsize >> v.share_memsize >> v.cpu_load_system >> v.cpu_load_user;
return s;
}
#endif // DAEMON_H

View File

@@ -1,340 +1,342 @@
#include "file_manager.h"
#include "shared.h"
FileManager::TileDir::TileDir(): TileList() {
label_path = 0;
selection_mode = TileList::MultiSelection;
dir = PIDir::current();
resized = is_right = remote_mode = false;
}
PIStringList FileManager::TileDir::selectedNames() const {
PIStringList ret;
PIMutexLocker ml(e_mutex);
PIVector<int> sind = selected.toVector();
piForeachC (int i, sind)
ret << entries[i].name();
ret.removeOne("..");
return ret;
}
bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) {
bool pass = false;
PIString nd;
switch (key.key) {
case 'R': if (!(is_right && remote_mode)) updateDir(); pass = true; break;
case PIKbdListener::F5:
if (selected.isEmpty())
selected << cur;
if (!askQuestion("Copy selected files?")) return true;
setFocus();
//piCoutObj << "remote" << remote_mode;
if (remote_mode) actionRequest(is_right, Copy, selectedNames());
else actionRequest(is_right, LocalCopy, selectedNames());
break;
case PIKbdListener::F6:
if (key.modifiers[PIKbdListener::Shift]) {
if (selected.isEmpty())
selected << cur;
if (!askQuestion("Crypt selected files?")) return true;
setFocus();
if (remote_mode) actionRequest(is_right, Crypt, selectedNames());
else actionRequest(is_right, LocalCrypt, selectedNames());
}
break;
case PIKbdListener::F7:
nd = askUserInput("Enter new directory name:");
setFocus();
if (nd.isEmpty()) return true;
if (is_right && remote_mode)
actionRequest(is_right, MkDir, nd);
else {
PIDir::make(dir.absolutePath() + PIDir::separator + nd);
updateDir();
}
pass = true;
break;
case PIKbdListener::F8:
if (selected.isEmpty())
selected << cur;
if (!askQuestion("Delete selected?")) {
setFocus();
return false;
}
setFocus();
if (is_right && remote_mode) {
actionRequest(is_right, Remove, selectedNames());
} else {
removeFiles(dir, selectedNames());
selected.clear();
updateDir();
}
pass = true;
break;
case PIKbdListener::Return:
{
e_mutex.lock();
bool ud = false;
if (cur < entries.size_s() && cur >= 0) {
if (!(is_right && remote_mode)) {
//piCout << entries[cur];
if (entries[cur].isDir()) {
prev_pos[dir.path()] = PIPair<int, int>(cur, offset);
dir.cd(entries[cur].name());
PIPair<int, int> cp = prev_pos.value(dir.path());
cur = cp.first;
offset = cp.second;
selected.clear();
ud = true;
}
}
pass = true;
}
e_mutex.unlock();
if (ud) updateDir();
}
break;
}
// piCout << is_right << remote_mode << pass;
if (is_right && remote_mode && pass) {
((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key);
return true;
}
return TileList::keyEvent(key);
}
void FileManager::TileDir::lock() {
if (screen && !resized) ((PIScreen*)screen)->lock();
}
void FileManager::TileDir::unlock() {
if (screen && !resized) ((PIScreen*)screen)->unlock();
}
void FileManager::TileDir::showReading() {
PIMutexLocker ml(e_mutex);
cur = -1;
offset = 0;
entries.clear();
content.resize(1);
content[0] = Row("... Reading ...", CellFormat());
}
void FileManager::TileDir::setContent(const PIVector<PIFile::FileInfo> & l) {
PIMutexLocker ml(e_mutex);
PIVector<PIFile::FileInfo> fl, dl;
entries.clear();
if (l.isEmpty()) {
PIFile::FileInfo fi;
fi.path = "..";
fi.flags |= PIFile::FileInfo::DotDot | PIFile::FileInfo::Dir;
entries << fi;
} else {
bool root = dir.path() == PIDir::separator;
for (int i = 0; i < l.size_s(); ++i) {
if (l[i].name() == ".") continue;
if (l[i].name() == "..") {
if (!root) dl.push_front(l[i]);
continue;
}
if (l[i].isDir()) dl << l[i];
else fl << l[i];
}
entries << dl << fl;
}
}
void FileManager::TileDir::updateDir() {
lock();
int pc = cur, po = offset;
showReading();
unlock();
setContent(dir.entries());
if (label_path) {
label_path->content.resize(1);
label_path->content[0].first = dir.absolutePath();
}
cur = pc;
offset = po;
buildNames();
}
void FileManager::TileDir::buildNames() {
lock();
PIMutexLocker ml(e_mutex);
content.clear();
PIChar t;
CharFlags cf = 0;
Color cc = Default;
PIString fcol, scol;
piForeachC (PIFile::FileInfo & e, entries) {
if (e.isDir()) {
t = '/';
cf = Bold;
scol = " dir";
} else {
if (e.perm_user.exec || e.perm_group.exec || e.perm_other.exec) {
cf = Bold;
cc = Green;
t = '*';
} else {
t = ' ';
cc = Default;
cf = 0;
}
scol = PIString::readableSize(e.size);
}
if (e.isSymbolicLink() && (t != '*')) t = '~';
scol = scol.expandRightTo(9, ' ') + "| " + e.time_modification.toString("dd.MM hh:mm:ss") + " | "
+ e.perm_user.toString() + " " + e.perm_group.toString() + " " + e.perm_other.toString();
fcol = t + e.name();
if (fcol.size_s() >= width_ - 2 - scol.size_s())
fcol = fcol.left(width_ - 5 - scol.size_s()) + "...";
fcol.expandRightTo(width_ - 1 - scol.size_s(), ' ');
content << Row(fcol + scol, CellFormat(cc, Transparent, cf));
}
unlock();
}
void FileManager::TileDir::sizeHint(int & w, int & h) const {
w = h = 4;
}
void FileManager::TileDir::resizeEvent(int w, int h) {
resized = true;
buildNames();
resized = false;
TileList::resizeEvent(w, h);
}
FileManager::FileManager() {
setName("FileManager");
TileSimple * tl;
tile_root = new PIScreenTile();
tile_root->direction = Vertical;
PIScreenTile * pt = new PIScreenTile();
pt->direction = Horizontal;
pt->spacing = 1;
pt->back_format.color_back = Cyan;
for (int i = 0; i < 2; ++i) {
PIScreenTile * panel = new PIScreenTile();
TileSimple * plabel = new TileSimple();
plabel->size_policy = Fixed;
plabel->maximumWidth = 1;
panel->direction = Vertical;
panels[i] = new TileDir();
panels[i]->fm = this;
panels[i]->key_func = (void*)tileKey_s;
panels[i]->setName("file panel " + PIString::fromNumber(i));
panels[i]->label_path = plabel;
CONNECTU(panels[i], actionRequest, this, actionRequest)
panel->addTile(plabel);
panel->addTile(panels[i]);
panels[i]->updateDir();
pt->addTile(panel);
}
panels[1]->is_right = true;
tile_root->addTile(pt);
PIScreenTile * labels = new PIScreenTile();
labels->size_policy = Fixed;
labels->direction = Horizontal;
PIVector<SSPair> ll;
ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F7", "MkDir") << SSPair(" F8", "Delete");
piForeachC (SSPair & l, ll) {
tl = new TileSimple(); labels->addTile(tl);
tl->content << TileSimple::Row(l.first, CellFormat(White, Transparent, Bold));
tl = new TileSimple(); labels->addTile(tl);
tl->content << TileSimple::Row(l.second, CellFormat(Black, Cyan));
}
tl = new TileSimple(); labels->addTile(tl);
tl->size_policy = Expanding;
tile_root->addTile(labels);
}
PIScreenTile * FileManager::tile() const {
return tile_root;
}
void FileManager::setLocal() {
if (panels[1]->remote_mode) setRemoteDir(panels[0]->dir.absolutePath());
panels[0]->remote_mode = panels[1]->remote_mode = false;
}
void FileManager::setRemote() {
panels[0]->remote_mode = panels[1]->remote_mode = true;
}
void FileManager::setRemoteDir(const PIString & d) {
panels[1]->dir.setDir(d);
if (panels[1]->label_path) {
panels[1]->label_path->content.resize(1);
panels[1]->label_path->content[0].first = panels[1]->dir.path();
}
}
void FileManager::setRemoteContent(const PIVector< PIFile::FileInfo > & el) {
panels[1]->setContent(el);
panels[1]->buildNames();
}
int FileManager::selectedPanel() const {
for (int i = 0; i < 2; i++)
if (panels[i]->hasFocus()) return i;
return -1;
}
PIStringList FileManager::selectedRemote() const {
PIStringList ret;
panels[1]->lock();
PIVector<int> sil = panels[1]->selected.toVector();
piForeachC (int i, sil)
ret << panels[1]->entries[i].path;
panels[1]->unlock();
return ret;
}
PIFile::FileInfo FileManager::currentRemoteEntry() const {
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) return PIFile::FileInfo();
return panels[1]->entries[panels[1]->cur];
}
void FileManager::remoteSaveDir() {
panels[1]->prev_pos[panels[1]->dir.path()] = PIPair<int, int>(panels[1]->cur, panels[1]->offset);
}
void FileManager::remoteRestoreDir() {
PIPair<int, int> cp = panels[1]->prev_pos.value(panels[1]->dir.path());
panels[1]->selected.clear();
panels[1]->cur = cp.first;
panels[1]->offset = cp.second;
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s()))
panels[1]->cur = 0;
}
#include "file_manager.h"
#include "shared.h"
FileManager::TileDir::TileDir(): TileList() {
label_path = 0;
selection_mode = TileList::MultiSelection;
dir = PIDir::current();
resized = is_right = remote_mode = false;
}
PIStringList FileManager::TileDir::selectedNames() const {
PIStringList ret;
PIMutexLocker ml(e_mutex);
PIVector<int> sind = selected.toVector();
piForeachC(int i, sind)
ret << entries[i].name();
ret.removeOne("..");
return ret;
}
bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) {
bool pass = false;
PIString nd;
switch (key.key) {
case 'R':
if (!(is_right && remote_mode)) updateDir();
pass = true;
break;
case PIKbdListener::F5:
if (selected.isEmpty()) selected << cur;
if (!askQuestion("Copy selected files?")) return true;
setFocus();
// piCoutObj << "remote" << remote_mode;
if (remote_mode)
actionRequest(is_right, Copy, selectedNames());
else
actionRequest(is_right, LocalCopy, selectedNames());
break;
case PIKbdListener::F6:
if (key.modifiers[PIKbdListener::Shift]) {
if (selected.isEmpty()) selected << cur;
if (!askQuestion("Crypt selected files?")) return true;
setFocus();
if (remote_mode)
actionRequest(is_right, Crypt, selectedNames());
else
actionRequest(is_right, LocalCrypt, selectedNames());
}
break;
case PIKbdListener::F7:
nd = askUserInput("Enter new directory name:");
setFocus();
if (nd.isEmpty()) return true;
if (is_right && remote_mode)
actionRequest(is_right, MkDir, nd);
else {
PIDir::make(dir.absolutePath() + PIDir::separator + nd);
updateDir();
}
pass = true;
break;
case PIKbdListener::F8:
if (selected.isEmpty()) selected << cur;
if (!askQuestion("Delete selected?")) {
setFocus();
return false;
}
setFocus();
if (is_right && remote_mode) {
actionRequest(is_right, Remove, selectedNames());
} else {
removeFiles(dir, selectedNames());
selected.clear();
updateDir();
}
pass = true;
break;
case PIKbdListener::Return: {
e_mutex.lock();
bool ud = false;
if (cur < entries.size_s() && cur >= 0) {
if (!(is_right && remote_mode)) {
// piCout << entries[cur];
if (entries[cur].isDir()) {
prev_pos[dir.path()] = PIPair<int, int>(cur, offset);
dir.cd(entries[cur].name());
PIPair<int, int> cp = prev_pos.value(dir.path());
cur = cp.first;
offset = cp.second;
selected.clear();
ud = true;
}
}
pass = true;
}
e_mutex.unlock();
if (ud) updateDir();
} break;
}
// piCout << is_right << remote_mode << pass;
if (is_right && remote_mode && pass) {
((void (*)(void *, PIKbdListener::KeyEvent))key_func)(fm, key);
return true;
}
return TileList::keyEvent(key);
}
void FileManager::TileDir::lock() {
if (screen && !resized) ((PIScreen *)screen)->lock();
}
void FileManager::TileDir::unlock() {
if (screen && !resized) ((PIScreen *)screen)->unlock();
}
void FileManager::TileDir::showReading() {
PIMutexLocker ml(e_mutex);
cur = -1;
offset = 0;
entries.clear();
content.resize(1);
content[0] = Row("... Reading ...", CellFormat());
}
void FileManager::TileDir::setContent(const PIVector<PIFile::FileInfo> & l) {
PIMutexLocker ml(e_mutex);
PIVector<PIFile::FileInfo> fl, dl;
entries.clear();
if (l.isEmpty()) {
PIFile::FileInfo fi;
fi.path = "..";
fi.flags |= PIFile::FileInfo::DotDot | PIFile::FileInfo::Dir;
entries << fi;
} else {
bool root = dir.path() == PIDir::separator;
for (int i = 0; i < l.size_s(); ++i) {
if (l[i].name() == ".") continue;
if (l[i].name() == "..") {
if (!root) dl.push_front(l[i]);
continue;
}
if (l[i].isDir())
dl << l[i];
else
fl << l[i];
}
entries << dl << fl;
}
}
void FileManager::TileDir::updateDir() {
lock();
int pc = cur, po = offset;
showReading();
unlock();
setContent(dir.entries());
if (label_path) {
label_path->content.resize(1);
label_path->content[0].first = dir.absolutePath();
}
cur = pc;
offset = po;
buildNames();
}
void FileManager::TileDir::buildNames() {
lock();
PIMutexLocker ml(e_mutex);
content.clear();
PIChar t;
CharFlags cf = 0;
Color cc = Default;
PIString fcol, scol;
piForeachC(PIFile::FileInfo & e, entries) {
if (e.isDir()) {
t = '/';
cf = Bold;
scol = " dir";
} else {
if (e.perm_user.exec || e.perm_group.exec || e.perm_other.exec) {
cf = Bold;
cc = Green;
t = '*';
} else {
t = ' ';
cc = Default;
cf = 0;
}
scol = PIString::readableSize(e.size);
}
if (e.isSymbolicLink() && (t != '*')) t = '~';
scol = scol.expandRightTo(9, ' ') + "| " + e.time_modification.toString("dd.MM hh:mm:ss") + " | " + e.perm_user.toString() + " " +
e.perm_group.toString() + " " + e.perm_other.toString();
fcol = t + e.name();
if (fcol.size_s() >= width_ - 2 - scol.size_s()) fcol = fcol.left(width_ - 5 - scol.size_s()) + "...";
fcol.expandRightTo(width_ - 1 - scol.size_s(), ' ');
content << Row(fcol + scol, CellFormat(cc, Transparent, cf));
}
unlock();
}
void FileManager::TileDir::sizeHint(int & w, int & h) const {
w = h = 4;
}
void FileManager::TileDir::resizeEvent(int w, int h) {
resized = true;
buildNames();
resized = false;
TileList::resizeEvent(w, h);
}
FileManager::FileManager() {
setName("FileManager");
TileSimple * tl;
tile_root = new PIScreenTile();
tile_root->direction = Vertical;
PIScreenTile * pt = new PIScreenTile();
pt->direction = Horizontal;
pt->spacing = 1;
pt->back_format.color_back = Cyan;
for (int i = 0; i < 2; ++i) {
PIScreenTile * panel = new PIScreenTile();
TileSimple * plabel = new TileSimple();
plabel->size_policy = Fixed;
plabel->maximumWidth = 1;
panel->direction = Vertical;
panels[i] = new TileDir();
panels[i]->fm = this;
panels[i]->key_func = (void *)tileKey_s;
panels[i]->setName("file panel " + PIString::fromNumber(i));
panels[i]->label_path = plabel;
CONNECTU(panels[i], actionRequest, this, actionRequest)
panel->addTile(plabel);
panel->addTile(panels[i]);
panels[i]->updateDir();
pt->addTile(panel);
}
panels[1]->is_right = true;
tile_root->addTile(pt);
PIScreenTile * labels = new PIScreenTile();
labels->size_policy = Fixed;
labels->direction = Horizontal;
PIVector<SSPair> ll;
ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F7", "MkDir") << SSPair(" F8", "Delete");
piForeachC(SSPair & l, ll) {
tl = new TileSimple();
labels->addTile(tl);
tl->content << TileSimple::Row(l.first, CellFormat(White, Transparent, Bold));
tl = new TileSimple();
labels->addTile(tl);
tl->content << TileSimple::Row(l.second, CellFormat(Black, Cyan));
}
tl = new TileSimple();
labels->addTile(tl);
tl->size_policy = Expanding;
tile_root->addTile(labels);
}
PIScreenTile * FileManager::tile() const {
return tile_root;
}
void FileManager::setLocal() {
if (panels[1]->remote_mode) setRemoteDir(panels[0]->dir.absolutePath());
panels[0]->remote_mode = panels[1]->remote_mode = false;
}
void FileManager::setRemote() {
panels[0]->remote_mode = panels[1]->remote_mode = true;
}
void FileManager::setRemoteDir(const PIString & d) {
panels[1]->dir.setDir(d);
if (panels[1]->label_path) {
panels[1]->label_path->content.resize(1);
panels[1]->label_path->content[0].first = panels[1]->dir.path();
}
}
void FileManager::setRemoteContent(const PIVector<PIFile::FileInfo> & el) {
panels[1]->setContent(el);
panels[1]->buildNames();
}
int FileManager::selectedPanel() const {
for (int i = 0; i < 2; i++)
if (panels[i]->hasFocus()) return i;
return -1;
}
PIStringList FileManager::selectedRemote() const {
PIStringList ret;
panels[1]->lock();
PIVector<int> sil = panels[1]->selected.toVector();
piForeachC(int i, sil)
ret << panels[1]->entries[i].path;
panels[1]->unlock();
return ret;
}
PIFile::FileInfo FileManager::currentRemoteEntry() const {
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) return PIFile::FileInfo();
return panels[1]->entries[panels[1]->cur];
}
void FileManager::remoteSaveDir() {
panels[1]->prev_pos[panels[1]->dir.path()] = PIPair<int, int>(panels[1]->cur, panels[1]->offset);
}
void FileManager::remoteRestoreDir() {
PIPair<int, int> cp = panels[1]->prev_pos.value(panels[1]->dir.path());
panels[1]->selected.clear();
panels[1]->cur = cp.first;
panels[1]->offset = cp.second;
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) panels[1]->cur = 0;
}

View File

@@ -1,74 +1,83 @@
#ifndef FILE_MANAGER_H
#define FILE_MANAGER_H
#include "piscreentiles.h"
#include "pidir.h"
class FileManager: public PIObject {
PIOBJECT(FileManager)
public:
FileManager();
PIScreenTile * tile() const;
PIScreenTile * localTile() const {return panels[0];}
PIScreenTile * remoteTile() const {return panels[1];}
enum Action {MkDir, Remove, Copy, Move, LocalCopy, Crypt, LocalCrypt};
void setLocal();
void setRemote();
void setRemoteDir(const PIString & d);
void setRemoteContent(const PIVector<PIFile::FileInfo> & el);
PIString remoteDir() const {return panels[1]->dir.absolutePath();}
PIString localDir() const {return panels[0]->dir.absolutePath();}
int selectedPanel() const;
PIStringList selectedRemote() const;
PIFile::FileInfo currentRemoteEntry() const;
PIFile::FileInfo selectedRemoteEntry(int index) const {return panels[1]->entries[index];}
void remoteSaveDir();
void remoteRestoreDir();
void readingRemote() const {panels[1]->showReading();}
void updateLocalDir() {panels[0]->updateDir();}
void updateRemoteDir() {panels[1]->updateDir();}
void clearSelectionLocal() {panels[0]->selected.clear();}
void clearSelectionRemote() {panels[1]->selected.clear();}
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
private:
class TileDir: public TileList {
PIOBJECT_SUBCLASS(TileDir, TileList)
public:
TileDir();
void updateDir();
void buildNames();
bool keyEvent(PIKbdListener::KeyEvent key) override;
void sizeHint(int & w, int & h) const override;
void resizeEvent(int w, int h) override;
void lock();
void unlock();
void showReading();
void setContent(const PIVector<PIFile::FileInfo> & l);
PIStringList selectedNames() const;
TileSimple * label_path;
PIVector<PIFile::FileInfo> entries;
PIDir dir;
PIMap<PIString, PIPair<int, int> > prev_pos;
mutable PIMutex e_mutex;
bool resized, is_right, remote_mode;
void * fm, * key_func;
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
};
EVENT1(tileKey, PIKbdListener::KeyEvent, key)
static void tileKey_s(void * fm, PIKbdListener::KeyEvent key) {((FileManager*)fm)->tileKey(key);}
TileDir * panels[2];
PIScreenTile * tile_root;
typedef PIPair<PIString, PIString> SSPair;
};
#endif // FILE_MANAGER_H
#ifndef FILE_MANAGER_H
#define FILE_MANAGER_H
#include "pidir.h"
#include "piscreentiles.h"
class FileManager: public PIObject {
PIOBJECT(FileManager)
public:
FileManager();
PIScreenTile * tile() const;
PIScreenTile * localTile() const { return panels[0]; }
PIScreenTile * remoteTile() const { return panels[1]; }
enum Action {
MkDir,
Remove,
Copy,
Move,
LocalCopy,
Crypt,
LocalCrypt
};
void setLocal();
void setRemote();
void setRemoteDir(const PIString & d);
void setRemoteContent(const PIVector<PIFile::FileInfo> & el);
PIString remoteDir() const { return panels[1]->dir.absolutePath(); }
PIString localDir() const { return panels[0]->dir.absolutePath(); }
int selectedPanel() const;
PIStringList selectedRemote() const;
PIFile::FileInfo currentRemoteEntry() const;
PIFile::FileInfo selectedRemoteEntry(int index) const { return panels[1]->entries[index]; }
void remoteSaveDir();
void remoteRestoreDir();
void readingRemote() const { panels[1]->showReading(); }
void updateLocalDir() { panels[0]->updateDir(); }
void updateRemoteDir() { panels[1]->updateDir(); }
void clearSelectionLocal() { panels[0]->selected.clear(); }
void clearSelectionRemote() { panels[1]->selected.clear(); }
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
private:
class TileDir: public TileList {
PIOBJECT_SUBCLASS(TileDir, TileList)
public:
TileDir();
void updateDir();
void buildNames();
bool keyEvent(PIKbdListener::KeyEvent key) override;
void sizeHint(int & w, int & h) const override;
void resizeEvent(int w, int h) override;
void lock();
void unlock();
void showReading();
void setContent(const PIVector<PIFile::FileInfo> & l);
PIStringList selectedNames() const;
TileSimple * label_path;
PIVector<PIFile::FileInfo> entries;
PIDir dir;
PIMap<PIString, PIPair<int, int>> prev_pos;
mutable PIMutex e_mutex;
bool resized, is_right, remote_mode;
void *fm, *key_func;
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
};
EVENT1(tileKey, PIKbdListener::KeyEvent, key)
static void tileKey_s(void * fm, PIKbdListener::KeyEvent key) { ((FileManager *)fm)->tileKey(key); }
TileDir * panels[2];
PIScreenTile * tile_root;
typedef PIPair<PIString, PIString> SSPair;
};
#endif // FILE_MANAGER_H

View File

@@ -1,414 +1,435 @@
/*
PIP - Platform Independent Primitives
PIP System Daemon
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pisingleapplication.h"
#include "pisystemmonitor.h"
#include "pisysteminfo.h"
#include "piprocess.h"
#include "picli.h"
#include "file_manager.h"
#include "daemon.h"
#include "shared.h"
#include "piintrospection_server.h"
class _Init {
public:
_Init() {randomize();}
};
_Init _pisd_init;
PISystemMonitor sys_mon;
PIScreen * screen = 0;
class MainMenu: public PITimer {
PIOBJECT_SUBCLASS(MainMenu, PITimer)
public:
MainMenu(Daemon & d): daemon_(d) {
cur_peer = -1;
title = new TileSimple("title");
updateTitle(title);
title->back_format.color_back = Yellow;
title->size_policy = Fixed;
screen->rootTile()->addTile(title);
PIScreenTile * center = new PIScreenTile("center");
center->back_format.color_back = Cyan;
center->size_policy = Expanding;
center->setMargins(2, 2, 1, 1);
screen->rootTile()->addTile(center);
PIScreenTile * mt = tmenu = menuTile();
mt->show(); mt->name() = "main menu";
center->addTile(mt); mtiles << mt;
mt = tinfo = infoTile();
mt->hide(); mt->name() = "local info";
center->addTile(mt); mtiles << mt;
mt = tdaemon = daemon_.tile();
mt->hide(); mt->name() = "daemon";
center->addTile(mt); mtiles << mt;
mt = tpeer = peerTile();
mt->hide(); mt->name() = "peer info";
center->addTile(mt); mtiles << mt;
mt = tpeerdiag = peerDiagTile();
mt->hide(); mt->name() = "peer diag";
center->addTile(mt); mtiles << mt;
tpicout = new TilePICout();
tpicout->hide();
tpicout->size_policy = PIScreenTypes::Expanding;
screen->rootTile()->addTile(tpicout);
CONNECTU(screen, tileEvent, this, tileEvent)
CONNECTU(screen, keyPressed, this, keyEvent)
CONNECTU(&daemon_, menuRequest, this, menuRequest)
start(25);
}
PIScreenTile * menuTile() {
TileList * ret = new TileList();
ret->content << TileList::Row("Show local info", CellFormat());
ret->content << TileList::Row("Local file manager", CellFormat());
ret->content << TileList::Row("Connect to another daemon", CellFormat());
ret->content << TileList::Row("Peer info", CellFormat());
ret->content << TileList::Row("Peer reinit", CellFormat());
ret->content << TileList::Row("Peer diagnostics", CellFormat());
ret->content << TileList::Row("Peer change self name", CellFormat());
ret->content << TileList::Row("Exit", CellFormat());
ret->selection_mode = TileList::NoSelection;
return ret;
}
PIScreenTile * infoTile() {
TileList * ret = new TileList();
local_info_base << TileList::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat());
local_info_base << TileList::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat());
local_info_base << TileList::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat());
local_info_base << TileList::Row(" Username: " + PISystemInfo::instance()->user, CellFormat());
local_info_base << TileList::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat());
local_info_base << TileList::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat());
local_info_base << TileList::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat());
local_info_base << TileList::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat());
local_info_base << TileList::Row("", CellFormat());
return ret;
}
PIScreenTile * peerDiagTile() {
PIScreenTile * ret = new PIScreenTile();
TileSimple * htl = new TileSimple();
htl->size_policy = PIScreenTypes::Fixed;
ret->direction = PIScreenTypes::Vertical;
htl->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
PIScreenTile * diag = new PIScreenTile();
diag->direction = PIScreenTypes::Horizontal;
peerdiagdata_tl = new TileSimple();
peerdiagservice_tl = new TileSimple();
ret->addTile(htl);
ret->addTile(diag);
diag->addTile(peerdiagdata_tl);
diag->addTile(peerdiagservice_tl);
return ret;
}
PIScreenTile * peerTile() {
PIScreenTile* ret = new PIScreenTile();
ret->direction = PIScreenTypes::Vertical;
peerinfo_header = new TileSimple();
peerinfo_header->size_policy = PIScreenTypes::Fixed;
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
addrs_tl = new TileList();
peers_tl = new TileList();
peerinfo_tl = new TileSimple();
peermap_tl = new TileList();
peerinfo_tl->size_policy = PIScreenTypes::Fixed;
ret->addTile(peerinfo_header);
ret->addTile(peers_tl);
ret->addTile(peerinfo_tl);
ret->addTile(addrs_tl);
ret->addTile(peermap_tl);
return ret;
}
void updateTitle(TileSimple * tl) {
tl->content.clear();
tl->content << TileSimple::Row("pisd (PI System Daemon, PIP version " + PIPVersion() + ")", CellFormat(Black, Transparent));
tl->content << TileSimple::Row("This daemon: \"" + daemon_.thisDaemonName() + "\"", CellFormat(Black, Transparent));
}
void updatePeerDiag(TileSimple * tl, const PIDiagnostics & diag) {
tl->content.clear();
PIDiagnostics::State ds = diag.state();
tl->content << TileSimple::Row(diag.name() + " diagnostics", CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
tl->content << TileSimple::Row("Received count: " + PIString::fromNumber(ds.received_packets), CellFormat());
tl->content << TileSimple::Row("Invalid count: " + PIString::fromNumber(ds.received_packets_wrong), CellFormat());
tl->content << TileSimple::Row("Sended count: " + PIString::fromNumber(ds.sended_packets), CellFormat());
tl->content << TileSimple::Row("Immediate Frequency, Hz: " + PIString::fromNumber(ds.immediate_freq), CellFormat());
tl->content << TileSimple::Row("Integral Frequency, Hz: " + PIString::fromNumber(ds.integral_freq), CellFormat());
tl->content << TileSimple::Row("Receive speed: " + ds.receive_speed, CellFormat());
tl->content << TileSimple::Row("Send speed: " + ds.send_speed, CellFormat());
tl->content << TileSimple::Row("Quality: " + PIString::fromNumber((int)ds.quality), CellFormat());
}
void updatePeerInfo() {
// bool pm = daemon_.lockedPeers();
screen->lock();
daemon_.lock();
peers_tl->content.clear();
addrs_tl->content.clear();
peerinfo_tl->content.clear();
peermap_tl->content.clear();
peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ", "
// "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", "
// "sm = " + PIString::fromBool(daemon_.lockedSends()) + ", "
// "ms = " + PIString::fromBool(daemon_.lockedMCSends()) + ", "
// "pm = " + PIString::fromBool(pm) + "]"
, CellFormat());
piForeachC(PIPeer::PeerInfo &p , daemon_.allPeers())
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) +
" | p = " + PIString::fromNumber(p.ping()) +
" | n = " + PIString::fromBool(p.isNeighbour())
, CellFormat());
PIPeer::PeerInfo pi = daemon_.selfInfo();
if (cur_peer >= 0 && cur_peer < daemon_.allPeers().size_s()) pi = daemon_.allPeers()[cur_peer];
peerinfo_tl->content << TileSimple::Row("Name: " + pi.name, CellFormat());
peerinfo_tl->content << TileSimple::Row("Addreses: " + PIString::fromNumber(pi.addresses.size()), CellFormat());
peerinfo_tl->content << TileSimple::Row("Neighbours: " + pi.neighbours.join(", "), CellFormat());
piForeachC(PIPeer::PeerInfo::PeerAddress &a , pi.addresses)
addrs_tl->content << TileList::Row(a.address.toString() +
" | p = " + PIString::fromNumber(a.ping) +
" | a = " + PIString::fromBool(a.isAvailable()), CellFormat());
PIStringList peermap;
for (auto p = daemon_._peerMap().begin(); p != daemon_._peerMap().end(); p++) {
PIString s = p.key() + " | ";
piForeachCR(PIPeer::PeerInfo * pp, p.value()) s += " -> " + pp->name;
peermap << s;
}
piForeachC(PIString &s , peermap)
peermap_tl->content << TileList::Row(s, CellFormat());
updatePeerDiag(peerdiagdata_tl, daemon_.diagnosticData());
updatePeerDiag(peerdiagservice_tl, daemon_.diagnosticService());
daemon_.unlock();
screen->unlock();
}
void updateSysMon() {
TileList * tile = (TileList*)tinfo;
PIVector<PISystemMonitor::ThreadStats> ts = sys_mon.threadsStatistic();
screen->lock();
tile->content = local_info_base;
int num = 0, maxlen = 0;
PIString line = "Process load: k ";
PIString ns = PIString::fromNumber(sys_mon.statistic().cpu_load_system, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %, u ";
ns = PIString::fromNumber(sys_mon.statistic().cpu_load_user, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %";
tile->content << TileList::Row("PID: " + PIString::fromNumber(sys_mon.statistic().ID), CellFormat());
tile->content << TileList::Row(line, CellFormat());
tile->content << TileList::Row("Threads:", CellFormat());
piForeachC (PISystemMonitor::ThreadStats & t, ts)
maxlen = piMaxi(maxlen, t.name.length());
piForeachC (PISystemMonitor::ThreadStats & t, ts) {
line = PIString::fromNumber(++num).expandLeftTo(2, ' ') + ": ";
line += PIString(t.name).expandRightTo(maxlen, ' ') + ": k ";
PIString ns = PIString::fromNumber(t.cpu_load_kernel, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %, u ";
ns = PIString::fromNumber(t.cpu_load_user, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %";
tile->content << TileList::Row(line, CellFormat());
}
screen->unlock();
}
void tick(void* data_, int delimiter) override {
if (tpeerdiag->visible || tpeer->visible)
updatePeerInfo();
if (tinfo->visible)
updateSysMon();
}
EVENT_HANDLER(void, menuRequest) {
piForeach (PIScreenTile * t, mtiles)
t->hide();
daemon_.disconnect();
tmenu->show();
tmenu->setFocus();
}
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e) {
if (t == tmenu) {
if (e.type == TileList::RowPressed) {
piForeach (PIScreenTile * t, mtiles)
t->hide();
switch (e.data.toInt()) {
case 0: tinfo->show(); break;
case 1: daemon_.fm.setLocal(); daemon_.showLocalFilemanager(); tdaemon->show(); break;
case 2: daemon_.fm.setRemote(); daemon_.showMainList(); tdaemon->show(); break;
case 3: tpeer->show(); peers_tl->setFocus(); break;
case 4: daemon_.reinit(); tmenu->show(); break;
case 5: tpeerdiag->show(); break;
case 6:
{
PIString nn = askUserInput("Peer name:");
if (!nn.isEmpty()) {
daemon_.changeName(pisd_prefix + nn);
peerinfo_header->content.clear();
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
updateTitle(title);
}
menuRequest();
}
break;
case 7: PIKbdListener::exiting = true; break;
}
}
return;
}
if (t == peers_tl) {
if (e.type == TileList::RowPressed) {
cur_peer = e.data.toInt() - 1;
updatePeerInfo();
}
return;
}
}
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, e) {
if (e.key == PIKbdListener::F9) {
tpicout->visible = !tpicout->visible;
return;
}
if (e.key == PIKbdListener::Esc && e.modifiers[PIKbdListener::Shift]) {
PIKbdListener::exiting = true;
return;
}
if (screen->dialogTile()) return;
if (tpeer->visible || tinfo->visible || tpeerdiag->visible)
if (e.key == PIKbdListener::Esc) menuRequest();
//piCout << "key" << e.key;
}
EVENT_HANDLER1(void, messageFromApp, PIByteArray, m) {
if (m[0] == 'k') PIKbdListener::exiting = true;
}
Daemon & daemon_;
PIScreenTile * tmenu, * tinfo, * tfm, * tdaemon, * tpeer, * tpeerdiag;
TileList * peers_tl, * addrs_tl, * peermap_tl;
TilePICout * tpicout;
TileSimple * title;
TileSimple * peerinfo_tl, * peerinfo_header;
TileSimple * peerdiagdata_tl, * peerdiagservice_tl;
PIVector<PIScreenTile * > mtiles;
PIDeque<TileList::Row> local_info_base;
int cur_peer;
};
void usage() {
piCout << PICoutManipulators::Bold << "PIP System Daemon";
piCout << PICoutManipulators::Cyan << "Version" << PICoutManipulators::Bold << PIPVersion() << PICoutManipulators::NewLine;
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Usage:" << PICoutManipulators::Default
<< "\"pisd [-1hdfk] [-n <name>] [-a <ip>]\"" << PICoutManipulators::NewLine;
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Details:";
piCout << "-h --help " << PICoutManipulators::Green << "- display this message and exit";
piCout << "-d --daemon " << PICoutManipulators::Green << "- start as daemon";
piCout << "-k --kill " << PICoutManipulators::Green << "- kill daemon";
piCout << "-f --force " << PICoutManipulators::Green << "- don`t check for another running instance";
piCout << "-n --name <name> " << PICoutManipulators::Green << "- set daemon name";
piCout << "-a --address <ip>" << PICoutManipulators::Green << "- connect to remote daemon via tcp";
piCout << "-s --silent " << PICoutManipulators::Green << "- run without user interfase";
}
int main(int argc, char * argv[]) {
sys_mon.startOnSelf();
//piDebug = false;
PICLI cli(argc, argv);
cli.addArgument("help");
cli.addArgument("daemon");
cli.addArgument("force");
cli.addArgument("kill");
cli.addArgument("1");
cli.addArgument("silent");
cli.addArgument("name", true);
cli.addArgument("address", true);
if (cli.hasArgument("help")) {
usage();
return 0;
}
PIString name = cli.argumentValue("name");
PIString sip = cli.argumentValue("address");
PISingleApplication * sapp = 0;
if ((cli.hasArgument("1") && !cli.hasArgument("force")) || cli.hasArgument("kill")) {
sapp = new PISingleApplication("pisd");
if (cli.hasArgument("1")) {
if (!sapp->isFirst()) {
piCout << "Another pisd is running, exit";
delete sapp;
return 0;
}
}
if (cli.hasArgument("kill")) {
sapp->sendMessage(PIByteArray("k", 1));
delete sapp;
return 0;
}
}
PIINTROSPECTION_START(pisd)
if (cli.hasArgument("daemon")) {
PIStringList args;
args << "-1" << "-s";
if (cli.hasArgument("force"))
args << "-f";
if (cli.hasArgument("address"))
args << "-a" << sip;
if (!name.isEmpty())
args << "-n" << name;
PIString exe;
#ifdef WINDOWS
exe = PISystemInfo::instance()->execCommand;
#else
exe = PIProcess::getEnvironmentVariable("_");
#endif
piCout << "start in background:" << exe;// << "; with args" << args;
PIProcess::execIndependent(exe, args);
return 0;
}
screen = new PIScreen(false);
screen->setMouseEnabled(true);
Daemon * daemon = new Daemon();
if (!sip.isEmpty()) daemon->setTcpServerIP(sip);
screen->enableExitCapture(PIKbdListener::F10);
if (!name.isEmpty())
daemon->changeName(pisd_prefix + name);
MainMenu * menu = new MainMenu(*daemon);
if (sapp) CONNECTU(sapp, messageReceived, menu, messageFromApp);
if (cli.hasArgument("silent")) {
PICout::setOutputDevices(PICout::StdOut);
PIKbdListener ls;
ls.enableExitCapture(PIKbdListener::F10);
ls.start();
WAIT_FOR_EXIT
ls.stop();
} else {
screen->start();
screen->waitForFinish();
screen->stop(true);
}
sys_mon.stop();
delete menu;
delete daemon;
delete screen;
if (sapp) delete sapp;
return 0;
}
/*
PIP - Platform Independent Primitives
PIP System Daemon
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "daemon.h"
#include "file_manager.h"
#include "picli.h"
#include "piintrospection_server.h"
#include "piprocess.h"
#include "pisingleapplication.h"
#include "pisysteminfo.h"
#include "pisystemmonitor.h"
#include "shared.h"
class _Init {
public:
_Init() { randomize(); }
};
_Init _pisd_init;
PISystemMonitor sys_mon;
PIScreen * screen = 0;
class MainMenu: public PITimer {
PIOBJECT_SUBCLASS(MainMenu, PITimer)
public:
MainMenu(Daemon & d): daemon_(d) {
cur_peer = -1;
title = new TileSimple("title");
updateTitle(title);
title->back_format.color_back = Yellow;
title->size_policy = Fixed;
screen->rootTile()->addTile(title);
PIScreenTile * center = new PIScreenTile("center");
center->back_format.color_back = Cyan;
center->size_policy = Expanding;
center->setMargins(2, 2, 1, 1);
screen->rootTile()->addTile(center);
PIScreenTile * mt = tmenu = menuTile();
mt->show();
mt->name() = "main menu";
center->addTile(mt);
mtiles << mt;
mt = tinfo = infoTile();
mt->hide();
mt->name() = "local info";
center->addTile(mt);
mtiles << mt;
mt = tdaemon = daemon_.tile();
mt->hide();
mt->name() = "daemon";
center->addTile(mt);
mtiles << mt;
mt = tpeer = peerTile();
mt->hide();
mt->name() = "peer info";
center->addTile(mt);
mtiles << mt;
mt = tpeerdiag = peerDiagTile();
mt->hide();
mt->name() = "peer diag";
center->addTile(mt);
mtiles << mt;
tpicout = new TilePICout();
tpicout->hide();
tpicout->size_policy = PIScreenTypes::Expanding;
screen->rootTile()->addTile(tpicout);
CONNECTU(screen, tileEvent, this, tileEvent)
CONNECTU(screen, keyPressed, this, keyEvent)
CONNECTU(&daemon_, menuRequest, this, menuRequest)
start(25);
}
PIScreenTile * menuTile() {
TileList * ret = new TileList();
ret->content << TileList::Row("Show local info", CellFormat());
ret->content << TileList::Row("Local file manager", CellFormat());
ret->content << TileList::Row("Connect to another daemon", CellFormat());
ret->content << TileList::Row("Peer info", CellFormat());
ret->content << TileList::Row("Peer reinit", CellFormat());
ret->content << TileList::Row("Peer diagnostics", CellFormat());
ret->content << TileList::Row("Peer change self name", CellFormat());
ret->content << TileList::Row("Exit", CellFormat());
ret->selection_mode = TileList::NoSelection;
return ret;
}
PIScreenTile * infoTile() {
TileList * ret = new TileList();
local_info_base << TileList::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat());
local_info_base << TileList::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat());
local_info_base << TileList::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat());
local_info_base << TileList::Row(" Username: " + PISystemInfo::instance()->user, CellFormat());
local_info_base << TileList::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat());
local_info_base << TileList::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat());
local_info_base << TileList::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat());
local_info_base << TileList::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat());
local_info_base << TileList::Row("", CellFormat());
return ret;
}
PIScreenTile * peerDiagTile() {
PIScreenTile * ret = new PIScreenTile();
TileSimple * htl = new TileSimple();
htl->size_policy = PIScreenTypes::Fixed;
ret->direction = PIScreenTypes::Vertical;
htl->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
PIScreenTile * diag = new PIScreenTile();
diag->direction = PIScreenTypes::Horizontal;
peerdiagdata_tl = new TileSimple();
peerdiagservice_tl = new TileSimple();
ret->addTile(htl);
ret->addTile(diag);
diag->addTile(peerdiagdata_tl);
diag->addTile(peerdiagservice_tl);
return ret;
}
PIScreenTile * peerTile() {
PIScreenTile * ret = new PIScreenTile();
ret->direction = PIScreenTypes::Vertical;
peerinfo_header = new TileSimple();
peerinfo_header->size_policy = PIScreenTypes::Fixed;
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
addrs_tl = new TileList();
peers_tl = new TileList();
peerinfo_tl = new TileSimple();
peermap_tl = new TileList();
peerinfo_tl->size_policy = PIScreenTypes::Fixed;
ret->addTile(peerinfo_header);
ret->addTile(peers_tl);
ret->addTile(peerinfo_tl);
ret->addTile(addrs_tl);
ret->addTile(peermap_tl);
return ret;
}
void updateTitle(TileSimple * tl) {
tl->content.clear();
tl->content << TileSimple::Row("pisd (PI System Daemon, PIP version " + PIPVersion() + ")", CellFormat(Black, Transparent));
tl->content << TileSimple::Row("This daemon: \"" + daemon_.thisDaemonName() + "\"", CellFormat(Black, Transparent));
}
void updatePeerDiag(TileSimple * tl, const PIDiagnostics & diag) {
tl->content.clear();
PIDiagnostics::State ds = diag.state();
tl->content << TileSimple::Row(diag.name() + " diagnostics",
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
tl->content << TileSimple::Row("Received count: " + PIString::fromNumber(ds.received_packets), CellFormat());
tl->content << TileSimple::Row("Invalid count: " + PIString::fromNumber(ds.received_packets_wrong), CellFormat());
tl->content << TileSimple::Row("Sended count: " + PIString::fromNumber(ds.sended_packets), CellFormat());
tl->content << TileSimple::Row("Immediate Frequency, Hz: " + PIString::fromNumber(ds.immediate_freq), CellFormat());
tl->content << TileSimple::Row("Integral Frequency, Hz: " + PIString::fromNumber(ds.integral_freq), CellFormat());
tl->content << TileSimple::Row("Receive speed: " + ds.receive_speed, CellFormat());
tl->content << TileSimple::Row("Send speed: " + ds.send_speed, CellFormat());
tl->content << TileSimple::Row("Quality: " + PIString::fromNumber((int)ds.quality), CellFormat());
}
void updatePeerInfo() {
// bool pm = daemon_.lockedPeers();
screen->lock();
daemon_.lock();
peers_tl->content.clear();
addrs_tl->content.clear();
peerinfo_tl->content.clear();
peermap_tl->content.clear();
peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ",
//" "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", " "sm = " +
//PIString::fromBool(daemon_.lockedSends()) + ", " "ms = " +
//PIString::fromBool(daemon_.lockedMCSends()) + ", " "pm = " + PIString::fromBool(pm) + "]"
,
CellFormat());
piForeachC(PIPeer::PeerInfo & p, daemon_.allPeers())
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) + " | p = " +
PIString::fromNumber(p.ping()) + " | n = " + PIString::fromBool(p.isNeighbour()),
CellFormat());
PIPeer::PeerInfo pi = daemon_.selfInfo();
if (cur_peer >= 0 && cur_peer < daemon_.allPeers().size_s()) pi = daemon_.allPeers()[cur_peer];
peerinfo_tl->content << TileSimple::Row("Name: " + pi.name, CellFormat());
peerinfo_tl->content << TileSimple::Row("Addreses: " + PIString::fromNumber(pi.addresses.size()), CellFormat());
peerinfo_tl->content << TileSimple::Row("Neighbours: " + pi.neighbours.join(", "), CellFormat());
piForeachC(PIPeer::PeerInfo::PeerAddress & a, pi.addresses)
addrs_tl->content << TileList::Row(a.address.toString() + " | p = " + PIString::fromNumber(a.ping) +
" | a = " + PIString::fromBool(a.isAvailable()),
CellFormat());
PIStringList peermap;
for (auto p = daemon_._peerMap().begin(); p != daemon_._peerMap().end(); p++) {
PIString s = p.key() + " | ";
piForeachCR(PIPeer::PeerInfo * pp, p.value())
s += " -> " + pp->name;
peermap << s;
}
piForeachC(PIString & s, peermap)
peermap_tl->content << TileList::Row(s, CellFormat());
updatePeerDiag(peerdiagdata_tl, daemon_.diagnosticData());
updatePeerDiag(peerdiagservice_tl, daemon_.diagnosticService());
daemon_.unlock();
screen->unlock();
}
void updateSysMon() {
TileList * tile = (TileList *)tinfo;
PIVector<PISystemMonitor::ThreadStats> ts = sys_mon.threadsStatistic();
screen->lock();
tile->content = local_info_base;
int num = 0, maxlen = 0;
PIString line = "Process load: k ";
PIString ns = PIString::fromNumber(sys_mon.statistic().cpu_load_system, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %, u ";
ns = PIString::fromNumber(sys_mon.statistic().cpu_load_user, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %";
tile->content << TileList::Row("PID: " + PIString::fromNumber(sys_mon.statistic().ID), CellFormat());
tile->content << TileList::Row(line, CellFormat());
tile->content << TileList::Row("Threads:", CellFormat());
piForeachC(PISystemMonitor::ThreadStats & t, ts)
maxlen = piMaxi(maxlen, t.name.length());
piForeachC(PISystemMonitor::ThreadStats & t, ts) {
line = PIString::fromNumber(++num).expandLeftTo(2, ' ') + ": ";
line += PIString(t.name).expandRightTo(maxlen, ' ') + ": k ";
PIString ns = PIString::fromNumber(t.cpu_load_kernel, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %, u ";
ns = PIString::fromNumber(t.cpu_load_user, 'f', 2);
line += ns.expandLeftTo(5, ' ') + " %";
tile->content << TileList::Row(line, CellFormat());
}
screen->unlock();
}
void tick(void * data_, int delimiter) override {
if (tpeerdiag->visible || tpeer->visible) updatePeerInfo();
if (tinfo->visible) updateSysMon();
}
EVENT_HANDLER(void, menuRequest) {
piForeach(PIScreenTile * t, mtiles)
t->hide();
daemon_.disconnect();
tmenu->show();
tmenu->setFocus();
}
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e) {
if (t == tmenu) {
if (e.type == TileList::RowPressed) {
piForeach(PIScreenTile * t, mtiles)
t->hide();
switch (e.data.toInt()) {
case 0: tinfo->show(); break;
case 1:
daemon_.fm.setLocal();
daemon_.showLocalFilemanager();
tdaemon->show();
break;
case 2:
daemon_.fm.setRemote();
daemon_.showMainList();
tdaemon->show();
break;
case 3:
tpeer->show();
peers_tl->setFocus();
break;
case 4:
daemon_.reinit();
tmenu->show();
break;
case 5: tpeerdiag->show(); break;
case 6: {
PIString nn = askUserInput("Peer name:");
if (!nn.isEmpty()) {
daemon_.changeName(pisd_prefix + nn);
peerinfo_header->content.clear();
peerinfo_header->content
<< TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
updateTitle(title);
}
menuRequest();
} break;
case 7: PIKbdListener::exiting = true; break;
}
}
return;
}
if (t == peers_tl) {
if (e.type == TileList::RowPressed) {
cur_peer = e.data.toInt() - 1;
updatePeerInfo();
}
return;
}
}
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, e) {
if (e.key == PIKbdListener::F9) {
tpicout->visible = !tpicout->visible;
return;
}
if (e.key == PIKbdListener::Esc && e.modifiers[PIKbdListener::Shift]) {
PIKbdListener::exiting = true;
return;
}
if (screen->dialogTile()) return;
if (tpeer->visible || tinfo->visible || tpeerdiag->visible)
if (e.key == PIKbdListener::Esc) menuRequest();
// piCout << "key" << e.key;
}
EVENT_HANDLER1(void, messageFromApp, PIByteArray, m) {
if (m[0] == 'k') PIKbdListener::exiting = true;
}
Daemon & daemon_;
PIScreenTile *tmenu, *tinfo, *tfm, *tdaemon, *tpeer, *tpeerdiag;
TileList *peers_tl, *addrs_tl, *peermap_tl;
TilePICout * tpicout;
TileSimple * title;
TileSimple *peerinfo_tl, *peerinfo_header;
TileSimple *peerdiagdata_tl, *peerdiagservice_tl;
PIVector<PIScreenTile *> mtiles;
PIDeque<TileList::Row> local_info_base;
int cur_peer;
};
void usage() {
piCout << PICoutManipulators::Bold << "PIP System Daemon";
piCout << PICoutManipulators::Cyan << "Version" << PICoutManipulators::Bold << PIPVersion() << PICoutManipulators::NewLine;
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Usage:" << PICoutManipulators::Default
<< "\"pisd [-1hdfk] [-n <name>] [-a <ip>]\"" << PICoutManipulators::NewLine;
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Details:";
piCout << "-h --help " << PICoutManipulators::Green << "- display this message and exit";
piCout << "-d --daemon " << PICoutManipulators::Green << "- start as daemon";
piCout << "-k --kill " << PICoutManipulators::Green << "- kill daemon";
piCout << "-f --force " << PICoutManipulators::Green << "- don`t check for another running instance";
piCout << "-n --name <name> " << PICoutManipulators::Green << "- set daemon name";
piCout << "-a --address <ip>" << PICoutManipulators::Green << "- connect to remote daemon via tcp";
piCout << "-s --silent " << PICoutManipulators::Green << "- run without user interfase";
}
int main(int argc, char * argv[]) {
sys_mon.startOnSelf();
// piDebug = false;
PICLI cli(argc, argv);
cli.addArgument("help");
cli.addArgument("daemon");
cli.addArgument("force");
cli.addArgument("kill");
cli.addArgument("1");
cli.addArgument("silent");
cli.addArgument("name", true);
cli.addArgument("address", true);
if (cli.hasArgument("help")) {
usage();
return 0;
}
PIString name = cli.argumentValue("name");
PIString sip = cli.argumentValue("address");
PISingleApplication * sapp = 0;
if ((cli.hasArgument("1") && !cli.hasArgument("force")) || cli.hasArgument("kill")) {
sapp = new PISingleApplication("pisd");
if (cli.hasArgument("1")) {
if (!sapp->isFirst()) {
piCout << "Another pisd is running, exit";
delete sapp;
return 0;
}
}
if (cli.hasArgument("kill")) {
sapp->sendMessage(PIByteArray("k", 1));
delete sapp;
return 0;
}
}
PIINTROSPECTION_START(pisd)
if (cli.hasArgument("daemon")) {
PIStringList args;
args << "-1"
<< "-s";
if (cli.hasArgument("force")) args << "-f";
if (cli.hasArgument("address")) args << "-a" << sip;
if (!name.isEmpty()) args << "-n" << name;
PIString exe;
#ifdef WINDOWS
exe = PISystemInfo::instance()->execCommand;
#else
exe = PIProcess::getEnvironmentVariable("_");
#endif
piCout << "start in background:" << exe; // << "; with args" << args;
PIProcess::execIndependent(exe, args);
return 0;
}
screen = new PIScreen(false);
screen->setMouseEnabled(true);
Daemon * daemon = new Daemon();
if (!sip.isEmpty()) daemon->setTcpServerIP(sip);
screen->enableExitCapture(PIKbdListener::F10);
if (!name.isEmpty()) daemon->changeName(pisd_prefix + name);
MainMenu * menu = new MainMenu(*daemon);
if (sapp) CONNECTU(sapp, messageReceived, menu, messageFromApp);
if (cli.hasArgument("silent")) {
PICout::setOutputDevices(PICout::StdOut);
PIKbdListener ls;
ls.enableExitCapture(PIKbdListener::F10);
ls.start();
WAIT_FOR_EXIT
ls.stop();
} else {
screen->start();
screen->waitForFinish();
screen->stop(true);
}
sys_mon.stop();
delete menu;
delete daemon;
delete screen;
if (sapp) delete sapp;
return 0;
}

View File

@@ -1,176 +1,181 @@
#include "shared.h"
#include "picrypt.h"
extern PIScreen * screen;
class DlgWatcher: public PIThread {
PIOBJECT(DlgWatcher)
public:
DlgWatcher() {close = ok = false;}
EVENT_HANDLER2(void, tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e) {
if (e.type == TileButtons::ButtonSelected) {
ok = e.data.toInt() == 0;
close = true;
}
}
EVENT_HANDLER1(void, keyPressed, PIKbdListener::KeyEvent, key) {
if (key.key == PIKbdListener::Return) {
ok = true;
close = true;
}
if (key.key == PIKbdListener::Esc) {
ok = false;
close = true;
}
}
bool ok;
bool close;
};
PIString readableTime(const PITime & t) {
PIString ret;
bool pt = false;
if (t.hours > 0) {ret += PIString::fromNumber(t.hours).expandLeftTo(2, '0') + " h "; pt = true;}
if ((t.minutes > 0) || pt) {ret += PIString::fromNumber(t.minutes).expandLeftTo(2, '0') + " m "; pt = true;}
if ((t.seconds > 0) || pt) ret += PIString::fromNumber(t.seconds).expandLeftTo(2, '0') + " s";
return ret;
}
PIString askUserInput(const PIString & desc) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileInput * input = new TileInput();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(desc, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
btns->content << TileButtons::Button("Cancel", CellFormat());
dlg.addTile(lbl);
dlg.addTile(input);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
if (!w.ok) return PIString();
return input->text;
}
bool askQuestion(const PIString & t) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
btns->content << TileButtons::Button("Cancel", CellFormat());
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
return w.ok;
}
void showInfo(const PIString & t) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
}
void removeFiles(const PIDir & dir, PIStringList l) {
l.removeAll("..");
PIString ap = dir.absolutePath();
//piCout << "remove from" << ap;
piForeachC (PIString & s, l) {
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
if (fi.isDir()) {
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
piForeachCR (PIFile::FileInfo & e, el) {
//piCout << "remove" << e.path;
PIFile::remove(e.path);
}
}
//piCout << "remove" << fi.path;
PIFile::remove(fi.path);
}
}
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret) {
if (secret.size() != PICrypt::sizeKey() || secret.isEmpty()) return false;
l.removeAll("..");
PIString ap = dir.absolutePath();
piForeachC (PIString & s, l) {
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
if (fi.isDir()) {
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
piForeachCR (PIFile::FileInfo & e, el) {
if (e.size != 0)
cryptFile(e.path, secret);
}
}
if (fi.size != 0)
cryptFile(fi.path, secret);
}
return false;
}
bool cryptFile(const PIString & path, const PIByteArray & secret){
PIFile inf;
PIByteArray ba;
PICrypt crypt;
if (!crypt.setKey(secret)) return false;
if (!inf.open(path, PIIODevice::ReadOnly)) return false;
ba = inf.readAll();
ba = crypt.crypt(ba);
if (ba.isEmpty()) return false;
PIFile outf;
if (!outf.open(path + ".crypt", PIIODevice::ReadWrite)) return false;
outf.resize(0);
outf.write(ba);
outf.close();
return true;
}
#include "shared.h"
#include "picrypt.h"
extern PIScreen * screen;
class DlgWatcher: public PIThread {
PIOBJECT(DlgWatcher)
public:
DlgWatcher() { close = ok = false; }
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e) {
if (e.type == TileButtons::ButtonSelected) {
ok = e.data.toInt() == 0;
close = true;
}
}
EVENT_HANDLER1(void, keyPressed, PIKbdListener::KeyEvent, key) {
if (key.key == PIKbdListener::Return) {
ok = true;
close = true;
}
if (key.key == PIKbdListener::Esc) {
ok = false;
close = true;
}
}
bool ok;
bool close;
};
PIString readableTime(const PITime & t) {
PIString ret;
bool pt = false;
if (t.hours > 0) {
ret += PIString::fromNumber(t.hours).expandLeftTo(2, '0') + " h ";
pt = true;
}
if ((t.minutes > 0) || pt) {
ret += PIString::fromNumber(t.minutes).expandLeftTo(2, '0') + " m ";
pt = true;
}
if ((t.seconds > 0) || pt) ret += PIString::fromNumber(t.seconds).expandLeftTo(2, '0') + " s";
return ret;
}
PIString askUserInput(const PIString & desc) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileInput * input = new TileInput();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(desc, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
btns->content << TileButtons::Button("Cancel", CellFormat());
dlg.addTile(lbl);
dlg.addTile(input);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
if (!w.ok) return PIString();
return input->text;
}
bool askQuestion(const PIString & t) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
btns->content << TileButtons::Button("Cancel", CellFormat());
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
return w.ok;
}
void showInfo(const PIString & t) {
PIScreenTile dlg;
dlg.setMargins(1, 1, 1, 1);
dlg.spacing = 1;
dlg.back_format.color_back = Yellow;
TileSimple * lbl = new TileSimple();
TileButtons * btns = new TileButtons();
lbl->back_format.color_back = Yellow;
btns->back_format.color_back = Yellow;
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
btns->content << TileButtons::Button(" Ok ", CellFormat());
dlg.addTile(lbl);
dlg.addTile(btns);
DlgWatcher w;
CONNECTU(screen, keyPressed, &w, keyPressed)
CONNECTU(screen, tileEvent, &w, tileEvent)
screen->setDialogTile(&dlg);
while (!w.close) {
PIKbdListener::instance()->readKeyboard();
piMSleep(10);
}
}
void removeFiles(const PIDir & dir, PIStringList l) {
l.removeAll("..");
PIString ap = dir.absolutePath();
// piCout << "remove from" << ap;
piForeachC(PIString & s, l) {
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
if (fi.isDir()) {
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
piForeachCR(PIFile::FileInfo & e, el) {
// piCout << "remove" << e.path;
PIFile::remove(e.path);
}
}
// piCout << "remove" << fi.path;
PIFile::remove(fi.path);
}
}
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret) {
if (secret.size() != PICrypt::sizeKey() || secret.isEmpty()) return false;
l.removeAll("..");
PIString ap = dir.absolutePath();
piForeachC(PIString & s, l) {
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
if (fi.isDir()) {
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
piForeachCR(PIFile::FileInfo & e, el) {
if (e.size != 0) cryptFile(e.path, secret);
}
}
if (fi.size != 0) cryptFile(fi.path, secret);
}
return false;
}
bool cryptFile(const PIString & path, const PIByteArray & secret) {
PIFile inf;
PIByteArray ba;
PICrypt crypt;
if (!crypt.setKey(secret)) return false;
if (!inf.open(path, PIIODevice::ReadOnly)) return false;
ba = inf.readAll();
ba = crypt.crypt(ba);
if (ba.isEmpty()) return false;
PIFile outf;
if (!outf.open(path + ".crypt", PIIODevice::ReadWrite)) return false;
outf.resize(0);
outf.write(ba);
outf.close();
return true;
}

View File

@@ -1,21 +1,21 @@
#ifndef SHARED_H
#define SHARED_H
#include "pidir.h"
#include "piscreen.h"
#include "piscreentiles.h"
static const char pisd_prefix[] = "_pisd_";
using namespace PIScreenTypes;
PIString readableTime(const PITime & t);
PIString askUserInput(const PIString &desc);
bool askQuestion(const PIString & t);
void showInfo(const PIString & t);
void removeFiles(const PIDir & dir, PIStringList l);
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret);
bool cryptFile(const PIString & path, const PIByteArray & secret);
#endif // SHARED_H
#ifndef SHARED_H
#define SHARED_H
#include "pidir.h"
#include "piscreen.h"
#include "piscreentiles.h"
static const char pisd_prefix[] = "_pisd_";
using namespace PIScreenTypes;
PIString readableTime(const PITime & t);
PIString askUserInput(const PIString & desc);
bool askQuestion(const PIString & t);
void showInfo(const PIString & t);
void removeFiles(const PIDir & dir, PIStringList l);
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret);
bool cryptFile(const PIString & path, const PIByteArray & secret);
#endif // SHARED_H

View File

@@ -1,34 +1,35 @@
#include "terminal_tile.h"
#include "piscreendrawer.h"
TileTerminal::TileTerminal(const PIString & n): PIScreenTile(n) {
focus_flags = PIScreenTypes::CanHasFocus;
size_policy = PIScreenTypes::Expanding;
lastp[0] = lastp[1] = lastp[2] = 0;
}
void TileTerminal::drawEvent(PIScreenDrawer * d) {
//piCout << "draw" << visible;
d->fillRect(x_, y_, x_ + width_, y_ + height_, cells);
}
bool TileTerminal::keyEvent(PIKbdListener::KeyEvent key) {
lastp[0] = lastp[1];
lastp[1] = lastp[2];
lastp[2] = char(key.key);
if (lastp[0] == '\e' && lastp[1] == '~' && lastp[2] == '.') {
closeRequest();
return true;
}
//piCout << "key";
keyPressed(key);
return true;
}
void TileTerminal::resizeEvent(int w, int h) {
resizeRequest();
}
#include "terminal_tile.h"
#include "piscreendrawer.h"
TileTerminal::TileTerminal(const PIString & n): PIScreenTile(n) {
focus_flags = PIScreenTypes::CanHasFocus;
size_policy = PIScreenTypes::Expanding;
lastp[0] = lastp[1] = lastp[2] = 0;
}
void TileTerminal::drawEvent(PIScreenDrawer * d) {
// piCout << "draw" << visible;
d->fillRect(x_, y_, x_ + width_, y_ + height_, cells);
}
bool TileTerminal::keyEvent(PIKbdListener::KeyEvent key) {
lastp[0] = lastp[1];
lastp[1] = lastp[2];
lastp[2] = char(key.key);
if (lastp[0] == '\e' && lastp[1] == '~' && lastp[2] == '.') {
closeRequest();
return true;
}
// piCout << "key";
keyPressed(key);
return true;
}
void TileTerminal::resizeEvent(int w, int h) {
resizeRequest();
}

View File

@@ -1,30 +1,30 @@
#ifndef TERMINAL_TILE_H
#define TERMINAL_TILE_H
#include "piscreentile.h"
#include "pikbdlistener.h"
class TileTerminal: public PIScreenTile {
PIOBJECT_SUBCLASS(TileTerminal, PIScreenTile)
public:
TileTerminal(const PIString & n);
void setContent(const PIVector<PIVector<PIScreenTypes::Cell> > & c) {cells = c;}
EVENT(resizeRequest)
EVENT1(keyPressed, PIKbdListener::KeyEvent, k)
EVENT(closeRequest)
private:
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
void resizeEvent(int w, int h) override;
PIVector<PIVector<PIScreenTypes::Cell> > cells;
char lastp[3];
};
#endif // TERMINAL_TILE_H
#ifndef TERMINAL_TILE_H
#define TERMINAL_TILE_H
#include "pikbdlistener.h"
#include "piscreentile.h"
class TileTerminal: public PIScreenTile {
PIOBJECT_SUBCLASS(TileTerminal, PIScreenTile)
public:
TileTerminal(const PIString & n);
void setContent(const PIVector<PIVector<PIScreenTypes::Cell>> & c) { cells = c; }
EVENT(resizeRequest)
EVENT1(keyPressed, PIKbdListener::KeyEvent, k)
EVENT(closeRequest)
private:
void drawEvent(PIScreenDrawer * d) override;
bool keyEvent(PIKbdListener::KeyEvent key) override;
void resizeEvent(int w, int h) override;
PIVector<PIVector<PIScreenTypes::Cell>> cells;
char lastp[3];
};
#endif // TERMINAL_TILE_H

View File

@@ -1,106 +1,106 @@
/*
PIP - Platform Independent Primitives
System tests program
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pip.h"
#include "pisystemtests.h"
#ifdef CC_GCC
# include <unistd.h>
#endif
int main(int argc, char * argv[]) {
#if defined(WINDOWS) || defined(MAC_OS)
piCout << "This program is useless for Windows";
return 0;
#else
if (getuid() != 0) {
piCout << "You should run this program as root!";
return 0;
}
PIConfig conf(
#ifndef WINDOWS
"/etc/pip.conf"
#else
"pip.conf"
#endif
);
PITimeMeasurer timer, tm;
timespec ts;
long stc = 0;
double st;
llong sts = 0;
clock_getres(CLOCK_REALTIME, &ts);
stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec);
conf.setValue("time_resolution_ns", stc);
piCout << "Timer resolution is " << stc << " ns";
piCout << "\"PITimer.elapsed_*\" test ... ";
stc = 0;
ts.tv_sec = 0;
ts.tv_nsec = 1000;
PIVector<double> times;
times.resize(8192);
tm.reset();
PISystemTests::time_elapsed_ns = 0;
while (tm.elapsed_s() < 3.) {
for (int i = 0; i < times.size_s(); ++i) {
timer.reset();
times[i] = timer.elapsed_m();
times[i] = timer.elapsed_s();
times[i] = timer.elapsed_u();
}
st = 0;
for (int i = 0; i < times.size_s(); ++i)
st += times[i];
//cout << times[0] << endl;
//cout << st / times.size_s() / 3. * 1000. << endl;
sts += piRoundd(st / times.size_s() / 3. * 1000.);
//cout << sts << endl;
stc++;
}
sts /= stc;
conf.setValue("time_elapsed_ns", long(sts));
piCout << "ok, cost" << sts << "ns, average in" << stc << "series (" << (stc * 3 * times.size_s()) << "executes)";
piCout << "\"usleep\" offset test ... ";
PISystemTests::time_elapsed_ns = sts;
tm.reset();
stc = 0;
sts = 0;
times.resize(128);
while (tm.elapsed_s() < 3.) {
for (int i = 0; i < times.size_s(); ++i) {
timer.reset();
usleep(1000);
times[i] = timer.elapsed_u();
}
st = 0;
for (int i = 0; i < times.size_s(); ++i)
st += times[i] - 1000;
//cout << times[0] << endl;
//cout << st / times.size_s() / 3. * 1000. << endl;
sts += piRoundd(st / times.size_s());
//cout << sts << endl;
stc++;
}
sts /= stc;
conf.setValue("usleep_offset_us", long(sts));
piCout << "ok," << sts << "us, average in" << stc << "series (" << (stc * times.size_s()) << "executes)";
return 0;
#endif
};
/*
PIP - Platform Independent Primitives
System tests program
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pip.h"
#include "pisystemtests.h"
#ifdef CC_GCC
# include <unistd.h>
#endif
int main(int argc, char * argv[]) {
#if defined(WINDOWS) || defined(MAC_OS)
piCout << "This program is useless for Windows";
return 0;
#else
if (getuid() != 0) {
piCout << "You should run this program as root!";
return 0;
}
PIConfig conf(
# ifndef WINDOWS
"/etc/pip.conf"
# else
"pip.conf"
# endif
);
PITimeMeasurer timer, tm;
timespec ts;
long stc = 0;
double st;
llong sts = 0;
clock_getres(CLOCK_REALTIME, &ts);
stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec);
conf.setValue("time_resolution_ns", stc);
piCout << "Timer resolution is " << stc << " ns";
piCout << "\"PITimer.elapsed_*\" test ... ";
stc = 0;
ts.tv_sec = 0;
ts.tv_nsec = 1000;
PIVector<double> times;
times.resize(8192);
tm.reset();
PISystemTests::time_elapsed_ns = 0;
while (tm.elapsed_s() < 3.) {
for (int i = 0; i < times.size_s(); ++i) {
timer.reset();
times[i] = timer.elapsed_m();
times[i] = timer.elapsed_s();
times[i] = timer.elapsed_u();
}
st = 0;
for (int i = 0; i < times.size_s(); ++i)
st += times[i];
// cout << times[0] << endl;
// cout << st / times.size_s() / 3. * 1000. << endl;
sts += piRoundd(st / times.size_s() / 3. * 1000.);
// cout << sts << endl;
stc++;
}
sts /= stc;
conf.setValue("time_elapsed_ns", long(sts));
piCout << "ok, cost" << sts << "ns, average in" << stc << "series (" << (stc * 3 * times.size_s()) << "executes)";
piCout << "\"usleep\" offset test ... ";
PISystemTests::time_elapsed_ns = sts;
tm.reset();
stc = 0;
sts = 0;
times.resize(128);
while (tm.elapsed_s() < 3.) {
for (int i = 0; i < times.size_s(); ++i) {
timer.reset();
usleep(1000);
times[i] = timer.elapsed_u();
}
st = 0;
for (int i = 0; i < times.size_s(); ++i)
st += times[i] - 1000;
// cout << times[0] << endl;
// cout << st / times.size_s() / 3. * 1000. << endl;
sts += piRoundd(st / times.size_s());
// cout << sts << endl;
stc++;
}
sts /= stc;
conf.setValue("usleep_offset_us", long(sts));
piCout << "ok," << sts << "us, average in" << stc << "series (" << (stc * times.size_s()) << "executes)";
return 0;
#endif
};

View File

@@ -1,251 +1,245 @@
/*
PIP - Platform Independent Primitives
UDP file transfer (send /receive files) utility
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pip.h"
#include "pifiletransfer.h"
#include "pidatatransfer.h"
#include "piscreen.h"
#include "piscreentiles.h"
TileSimple pmt;
using namespace PICoutManipulators;
class UDPFileTransfer: public PITimer {
PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer)
public:
UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port, bool test = false) {
quet_ = false;
test_ = test;
eth.setReadAddress(src_ip_port);
eth.setSendAddress(dst_ip_port);
if (test_) {
testt.setCRCEnabled(false);
testt.setName("TEST");
CONNECT1(void, PIByteArray &, &testt, sendRequest, this, ftsend);
} else {
ft.setPacketSize(65000);
ft.setName("PIFT");
CONNECT1(void, PIByteArray &, &ft, sendRequest, this, ftsend);
CONNECTU(&ft, sendFilesStarted, this, ftevent);
CONNECTU(&ft, receiveFilesStarted, this, ftevent);
CONNECTU(&ft, sendFilesFinished, this, ftevent);
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
}
CONNECT2(void, const uchar *, ssize_t, &eth, threadedReadEvent, this, received);
start(50);
eth.setParameter(PIEthernet::SeparateSockets);
eth.startThreadedRead();
}
void setQuet(bool quet) {quet_ = quet;}
void startSend(const PIStringList &file) {
ft.send(file);
}
void startTest() {
PIByteArray ba(1024*1024*8);
testt.send(ba);
}
PIFileTransfer ft;
PIDataTransfer testt;
bool test_;
private:
PIEthernet eth;
bool quet_;
void tick(void *, int) override {
if (ft.isStarted()) {
ftevent();
updatePMT();
if (PIKbdListener::exiting) {
ft.stopSend();
ft.stopReceive();
}
}
if (testt.isSending() || testt.isReceiving()) {
ftevent();
updatePMT();
}
}
EVENT_HANDLER(void, ftevent) {
if (test_) {
#ifdef WINDOWS
piCout
#else
PICout(AddSpaces) << ClearLine
#endif
<< testt.stateString()
<< testt.diagnostic().receiveSpeed()
<< testt.diagnostic().sendSpeed()
<< "("
<< PIString::readableSize(testt.bytesCur()) << "/" << PIString::readableSize(testt.bytesAll())
<< ")"
#ifndef WINDOWS
<< Flush
#endif
;
return;
}
if (quet_) return;
#ifdef WINDOWS
piCout
#else
PICout(AddSpaces) << ClearLine
#endif
<< ft.stateString() << ft.curFile()
<< ft.diagnostic().receiveSpeed()
<< ft.diagnostic().sendSpeed()
<< "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", "
<< PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")"
<< "ETA" << (ft.diagnostic().state().received_bytes_per_sec > 0 ?
PIString::fromNumber(PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) /
ft.diagnostic().state().received_bytes_per_sec).toSeconds())
: PIString("unknown"))
#ifndef WINDOWS
<< Flush
#endif
;
}
EVENT_HANDLER1(void, ftsend, PIByteArray &, data) {
eth.send(data);
}
EVENT_HANDLER2(void, received, const uchar * , readed, ssize_t, size) {
PIByteArray ba(readed, size);
if(test_) {
testt.received(ba);
return;
}
ft.received(ba);
}
void updatePMT() {
PIString pm;
if (test_) pm = testt.packetMap();
else pm = ft.packetMap();
int wd = 110;
pmt.content.resize(pm.size() / wd + 1);
for (int i=0; i<pmt.content.size_s(); i++) {
pmt.content[i].first = pm.mid(wd*i, piMini(pm.size() - i*wd, wd));
}
}
};
void usage() {
piCout << Bold << "PIP UDP file transfer";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default << "\"pift [-hqf] -r <receive_ip> -s <send_ip> [-d <work_dir>] [-p <port>] [<path1>] [<path2>] [<path3>] [...]\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-f --fullpath " << Green << "- full path in <receive_ip> and <send_ip>";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-q --quet " << Green << "- quiet, no debug output to console";
piCout << "-r --receive <receive_ip> " << Green << "- set receive ip address, must be ip address of this computer";
piCout << "-s --send <send_ip> " << Green << "- set send ip address, address of computer which communicate with you";
piCout << "-p --port <port> " << Green << "- UDP port for transfer, by default 50005";
piCout << "-d --dir <work_dir> " << Green << "- directory, where place received files";
piCout << "<path> " << Green << "- add path to send, if no path, then \"pift\" working in receive mode";
piCout << "-t --test " << Green << "- test mode";
}
int main (int argc, char * argv[]) {
PICLI cli(argc, argv);
cli.setOptionalArgumentsCount(-1);
cli.addArgument("send", true);
cli.addArgument("receive", true);
cli.addArgument("dir", true);
cli.addArgument("port", true);
cli.addArgument("help");
cli.addArgument("quet");
cli.addArgument("fullpath");
cli.addArgument("test", true);
if (cli.hasArgument("test")) {
PIString src;
PIString dst;
bool send_ = false;
if (cli.argumentValue("test") == "1") {
src = "127.0.0.1:50005";
dst = "127.0.0.1:50006";
send_ = true;
} else {
src = "127.0.0.1:50006";
dst = "127.0.0.1:50005";
}
if (cli.hasArgument("send") && cli.hasArgument("receive") && cli.hasArgument("fullpath")) {
src = cli.argumentValue("receive");
dst = cli.argumentValue("send");
}
PIScreen screen(false);
screen.enableExitCapture();
screen.rootTile()->addTile(new TilePICout());
screen.rootTile()->addTile(&pmt);
UDPFileTransfer tuf(src, dst, true);
screen.start();
if (send_) tuf.startTest();
screen.waitForFinish();
return 0;
}
if ((!cli.hasArgument("send") || !cli.hasArgument("receive")) || cli.hasArgument("help")) {
usage();
return 0;
}
PIString src = cli.argumentValue("receive");
PIString dst = cli.argumentValue("send");
int port = -1;
if (cli.hasArgument("port")) port = cli.argumentValue("port").toInt();
if (port <=0) port = 50005;
if (!cli.hasArgument("fullpath")) {
src += ":"+PIString::fromNumber(port);
dst += ":"+PIString::fromNumber(port);
}
PIScreen screen(false);
screen.enableExitCapture();
screen.rootTile()->addTile(new TilePICout());
screen.rootTile()->addTile(&pmt);
screen.start();
UDPFileTransfer f(src, dst);
if (cli.hasArgument("dir")) f.ft.setDirectory(cli.argumentValue("dir"));
if (cli.hasArgument("quet")) f.setQuet(true);
piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst;
PIStringList fls = cli.optionalArguments();
if (fls.size() > 0) {
piCout << "send files" << fls;
f.startSend(fls);
PICout(PICoutManipulators::AddNone) << "\n";
return 0;
} else {
piCout << "wait for receiving";
}
PICout(PICoutManipulators::AddNone) << "\n";
screen.waitForFinish();
return 0;
}
/*
PIP - Platform Independent Primitives
UDP file transfer (send /receive files) utility
Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pidatatransfer.h"
#include "pifiletransfer.h"
#include "pip.h"
#include "piscreen.h"
#include "piscreentiles.h"
TileSimple pmt;
using namespace PICoutManipulators;
class UDPFileTransfer: public PITimer {
PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer)
public:
UDPFileTransfer(const PIString & src_ip_port, const PIString & dst_ip_port, bool test = false) {
quet_ = false;
test_ = test;
eth.setReadAddress(src_ip_port);
eth.setSendAddress(dst_ip_port);
if (test_) {
testt.setCRCEnabled(false);
testt.setName("TEST");
CONNECT1(void, PIByteArray &, &testt, sendRequest, this, ftsend);
} else {
ft.setPacketSize(65000);
ft.setName("PIFT");
CONNECT1(void, PIByteArray &, &ft, sendRequest, this, ftsend);
CONNECTU(&ft, sendFilesStarted, this, ftevent);
CONNECTU(&ft, receiveFilesStarted, this, ftevent);
CONNECTU(&ft, sendFilesFinished, this, ftevent);
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
}
CONNECT2(void, const uchar *, ssize_t, &eth, threadedReadEvent, this, received);
start(50);
eth.setParameter(PIEthernet::SeparateSockets);
eth.startThreadedRead();
}
void setQuet(bool quet) { quet_ = quet; }
void startSend(const PIStringList & file) { ft.send(file); }
void startTest() {
PIByteArray ba(1024 * 1024 * 8);
testt.send(ba);
}
PIFileTransfer ft;
PIDataTransfer testt;
bool test_;
private:
PIEthernet eth;
bool quet_;
void tick(void *, int) override {
if (ft.isStarted()) {
ftevent();
updatePMT();
if (PIKbdListener::exiting) {
ft.stopSend();
ft.stopReceive();
}
}
if (testt.isSending() || testt.isReceiving()) {
ftevent();
updatePMT();
}
}
EVENT_HANDLER(void, ftevent) {
if (test_) {
#ifdef WINDOWS
piCout
#else
PICout(AddSpaces) << ClearLine
#endif
<< testt.stateString() << testt.diagnostic().receiveSpeed() << testt.diagnostic().sendSpeed() << "("
<< PIString::readableSize(testt.bytesCur()) << "/" << PIString::readableSize(testt.bytesAll()) << ")"
#ifndef WINDOWS
<< Flush
#endif
;
return;
}
if (quet_) return;
#ifdef WINDOWS
piCout
#else
PICout(AddSpaces)
<< ClearLine
#endif
<< ft.stateString() << ft.curFile() << ft.diagnostic().receiveSpeed() << ft.diagnostic().sendSpeed() << "("
<< PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", "
<< PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")"
<< "ETA"
<< (ft.diagnostic().state().received_bytes_per_sec > 0
? PIString::fromNumber(
PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) / ft.diagnostic().state().received_bytes_per_sec)
.toSeconds())
: PIString("unknown"))
#ifndef WINDOWS
<< Flush
#endif
;
}
EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { eth.send(data); }
EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size) {
PIByteArray ba(readed, size);
if (test_) {
testt.received(ba);
return;
}
ft.received(ba);
}
void updatePMT() {
PIString pm;
if (test_)
pm = testt.packetMap();
else
pm = ft.packetMap();
int wd = 110;
pmt.content.resize(pm.size() / wd + 1);
for (int i = 0; i < pmt.content.size_s(); i++) {
pmt.content[i].first = pm.mid(wd * i, piMini(pm.size() - i * wd, wd));
}
}
};
void usage() {
piCout << Bold << "PIP UDP file transfer";
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
piCout << Green << Bold << "Usage:" << Default
<< "\"pift [-hqf] -r <receive_ip> -s <send_ip> [-d <work_dir>] [-p <port>] [<path1>] [<path2>] [<path3>] [...]\"" << NewLine;
piCout << Green << Bold << "Details:";
piCout << "-f --fullpath " << Green << "- full path in <receive_ip> and <send_ip>";
piCout << "-h --help " << Green << "- display this message and exit";
piCout << "-q --quet " << Green << "- quiet, no debug output to console";
piCout << "-r --receive <receive_ip> " << Green << "- set receive ip address, must be ip address of this computer";
piCout << "-s --send <send_ip> " << Green << "- set send ip address, address of computer which communicate with you";
piCout << "-p --port <port> " << Green << "- UDP port for transfer, by default 50005";
piCout << "-d --dir <work_dir> " << Green << "- directory, where place received files";
piCout << "<path> " << Green << "- add path to send, if no path, then \"pift\" working in receive mode";
piCout << "-t --test " << Green << "- test mode";
}
int main(int argc, char * argv[]) {
PICLI cli(argc, argv);
cli.setOptionalArgumentsCount(-1);
cli.addArgument("send", true);
cli.addArgument("receive", true);
cli.addArgument("dir", true);
cli.addArgument("port", true);
cli.addArgument("help");
cli.addArgument("quet");
cli.addArgument("fullpath");
cli.addArgument("test", true);
if (cli.hasArgument("test")) {
PIString src;
PIString dst;
bool send_ = false;
if (cli.argumentValue("test") == "1") {
src = "127.0.0.1:50005";
dst = "127.0.0.1:50006";
send_ = true;
} else {
src = "127.0.0.1:50006";
dst = "127.0.0.1:50005";
}
if (cli.hasArgument("send") && cli.hasArgument("receive") && cli.hasArgument("fullpath")) {
src = cli.argumentValue("receive");
dst = cli.argumentValue("send");
}
PIScreen screen(false);
screen.enableExitCapture();
screen.rootTile()->addTile(new TilePICout());
screen.rootTile()->addTile(&pmt);
UDPFileTransfer tuf(src, dst, true);
screen.start();
if (send_) tuf.startTest();
screen.waitForFinish();
return 0;
}
if ((!cli.hasArgument("send") || !cli.hasArgument("receive")) || cli.hasArgument("help")) {
usage();
return 0;
}
PIString src = cli.argumentValue("receive");
PIString dst = cli.argumentValue("send");
int port = -1;
if (cli.hasArgument("port")) port = cli.argumentValue("port").toInt();
if (port <= 0) port = 50005;
if (!cli.hasArgument("fullpath")) {
src += ":" + PIString::fromNumber(port);
dst += ":" + PIString::fromNumber(port);
}
PIScreen screen(false);
screen.enableExitCapture();
screen.rootTile()->addTile(new TilePICout());
screen.rootTile()->addTile(&pmt);
screen.start();
UDPFileTransfer f(src, dst);
if (cli.hasArgument("dir")) f.ft.setDirectory(cli.argumentValue("dir"));
if (cli.hasArgument("quet")) f.setQuet(true);
piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst;
PIStringList fls = cli.optionalArguments();
if (fls.size() > 0) {
piCout << "send files" << fls;
f.startSend(fls);
PICout(PICoutManipulators::AddNone) << "\n";
return 0;
} else {
piCout << "wait for receiving";
}
PICout(PICoutManipulators::AddNone) << "\n";
screen.waitForFinish();
return 0;
}