#include "daemon.h" #include "shared.h" #include "pisysteminfo.h" const char pisd_prefix[] = "_pisd_"; extern PIScreen screen; Daemon::Remote::Remote(const PIString & n): PIThread() { setName(n); ft.setName(n); ft.setPacketSize(3984); CONNECTU(&ft, sendRequest, this, ftSendRequest) CONNECTU(&ft, receiveFilesFinished, this, ftReceived) CONNECTU(&ft, sendFilesFinished, this, ftSended) dir_my = PIDir::current(); } void Daemon::Remote::sendFiles(const PIString & dir, const PIStringList & fl) { _fl = fl; piForeach (PIString & s, _fl) s.prepend(dir); piCout << "send" << _fl; startOnce(); } void Daemon::Remote::run() { ft.send(_fl); } Daemon::TileFileProgress::TileFileProgress(): PIScreenTile() { size_policy = PIScreenTypes::Fixed; ft = 0; setMargins(1, 1, 1, 1); spacing = 1; back_format.color_back = Yellow; label_file = new TileSimple(""); label_speed = new TileSimple(""); prog_file = new TileProgress(); prog_all = new TileProgress(); buttons = new TileButtons(); buttons->content << TileButtons::Button("Ok", CellFormat()); buttons->content << TileButtons::Button("Cancel", CellFormat()); buttons->back_format.color_back = label_file->back_format.color_back = label_speed->back_format.color_back = Yellow; label_file->back_format.color_char = label_speed->back_format.color_char = Black; label_file->content.resize(1); label_speed->content.resize(1); label_file->content[0].second = label_speed->content[0].second = CellFormat(Black, Transparent); addTile(label_file); addTile(label_speed); addTile(prog_file); addTile(prog_all); addTile(buttons); } 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(); PIString spd; if (ft->isReceiving()) spd = ft->diagnostic().receiveSpeed(); else spd = ft->diagnostic().sendSpeed(); label_speed->content[0].first = spd; 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); } Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString(rand() % 100)), fm(this) { setName("Daemon"); timer.setName("__S__Daemon_timer"); mode = offset = cur = height = 0; CONNECTU(&screen, keyPressed, this, keyEvent) CONNECTU(&timer, tickEvent, this, timerEvent) CONNECTU(&fm, tileKey, this, fmKeyEvent) CONNECTU(&fm, actionRequest, this, fmActionRequest) timer.addDelimiter(5); timer.start(200); //CONNECTU(&console, keyPressed, this, keyEvent) //dir.setDir("/home/peri4/Documents"); //TileSimple * tl; 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(true); tile_fm = fm.tile(); tile_fm->hide(); tile_file_progress = new TileFileProgress(); 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); CONNECTU(&screen, tileEvent, this, tileEvent) } Daemon::~Daemon() { PIVector rl = remotes.values(); piForeach (Remote * r, rl) delete r; remotes.clear(); } PIScreenTile * Daemon::tile() const { return tile_root; } void Daemon::hideAll() { list_actions->hide(); tile_info->hide(); list_daemons->hide(); tile_fm->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() + "\": "); /*PIString s; if (!conn_name.isEmpty()) s = "Daemon \"" + connectedDaemon() + "\": "; s += header; tile_header->content.resize(1); tile_header->content[0].first = s; tile_header->content[0].second.flags = Bold;*/ 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) { connectToDaemon(list_daemons->content[e.data.toInt()].first); showActionList(); } return; } if (t == list_actions) { if (e.type == TileList::RowPressed) { switch (e.data.toInt()) { case 0: mode = 2; showTile(tile_info, "Information"); break; case 1: mode = 3; showTile(tile_fm, "File manager"); requestChDir("."); 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: if (mode == 0) menuRequest(); else { if (mode > 1) { mode = 1; screen.lock(); tile_info->content.clear(); screen.unlock(); showActionList(); } else disconnect(); } break; default: break; } } void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) { PIByteArray ba; //Remote * r = remotes.value(conn_name); piCout << 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) { switch (type) { case FileManager::Copy: if (remote_tile) { } else { Remote * r = remotes.value(conn_name, 0); if (!r) return; r->sendFiles(fm.localDir() + PIDir::separator, data.toStringList()); tile_file_progress->ft = &(r->ft); screen.setDialogTile(tile_file_progress); } 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 == 2) { 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 = 1; } void Daemon::disconnect() { conn_name.clear(); mode = 0; showMainList(); } PIString Daemon::connectedDaemon() const { return conn_name.mid(6); } void Daemon::peerConnected(const PIString & name) { /*piCout << "connected" << name; mode = 2; conn_name = name;*/ if (!name.startsWith(pisd_prefix)) return; Remote * r = new Remote(name); CONNECTU(r, sendRequest, this, sendRequest) CONNECTU(r, receiveFinished, this, filesReceived) remotes.insert(name, r); } void Daemon::peerDisconnected(const PIString & name) { if (name == conn_name) { disconnect(); } Remote * dt = remotes.value(name, 0); if (!dt) return; delete dt; remotes.remove(name); } void Daemon::filesReceived(const PIString & name, bool ok) { } void Daemon::dataReceived(const PIString & from, const PIByteArray & data) { //if (conn_name != from) return; if (data.size() < 4) return; PIByteArray ba(data), rba; Remote * r(0); PIString dir; int type; ba >> type; //piCout << "rec from " << from << type; switch (type) { case RequestHostInfo: makeMyHostInfo(); rba << int(ReplyHostInfo) << info_my; break; case RequestChangeDir: r = remotes.value(from); if (!r) break; ba >> dir; r->dir_my.cd(dir); r->ft.setDirectory(r->dir_my); piCout << "store to" << r->dir_my.absolutePath(); { PIVector fil = r->dir_my.entries(); piForeach (PIFile::FileInfo & f, fil) f.path = f.name(); rba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil; piCout << "cd to" << dir << ", abs =" << r->dir_my.absolutePath(); } break; case ReplyHostInfo: ba >> info_other; makeOtherHostInfo(); fillInfoTile(info_other); break; case ReplyChangeDir: r = remotes.value(from); if (!r) break; { PIVector fil; ba >> dir >> fil; r->dir_remote.setDir(dir); fm.setRemoteDir(dir); fm.setRemoteContent(fil); fm.remoteRestoreDir(); } break; case FileTransfer: r = remotes.value(from); if (r) r->received(ba); break; }; if (!rba.isEmpty()) send(from, rba); } 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(const_cast(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::updateConsole() { switch (mode) { case 0: tabConnect(); break; case 1: tabFeature(); break; case RequestHostInfo: tabInfo(); break; } } void Daemon::tabConnectedHeader(int cols) { /*console.addString("Connected to: " + connectedDaemon(), 1, PIConsole::BackGreen | PIConsole::Bold); for (int i = 2; i <= cols; ++i) console.addString(" ", i, PIConsole::Green | PIConsole::Inverse);*/ } void Daemon::tabConnect() { /*startTab(); console.addString("Available daemons:"); int num = 0; dnames.clear(); PIStringList adl = availableDaemons(); piForeachC (PIString & p, adl) { dnames[num] = p; console.addString(" " + PIString(num++) + " - " + p); } finishTab();*/ } void Daemon::tabFeature() { /*startTab(); tabConnectedHeader(); console.addString("What do you wish to do with this daemon?"); console.addString(" 0 - show host info"); console.addString(" 1 - file manager"); console.addString(" 2 - execute command"); finishTab();*/ } void Daemon::tabInfo() { /*startTab(2); tabConnectedHeader(2); console.addString("Exec command: " + info_other.execCommand); console.addString(" Executed on " + info_other.execDateTime.toString()); console.addString(" Hostname: " + info_other.hostname); console.addString(" Username: " + info_other.user); console.addString(" OS name: " + info_other.OS_name); console.addString(" OS version: " + info_other.OS_version); console.addString("Architecture: " + info_other.architecture); console.addString(" CPU count: " + PIString::fromNumber(info_other.processorsCount)); console.addVariable("of this process", &sys_mon_other, 2); finishTab();*/ } void Daemon::requestChDir(const PIString & d) { if (d.isEmpty()) return; fm.remoteSaveDir(); fm.readingRemote(); PIByteArray ba; ba << int(RequestChangeDir) << d; send(conn_name, ba); //piCout << "request chdir" << d; }