#include "daemon.h" #include "shared.h" #include "pisysteminfo.h" const char pisd_prefix[] = "_pisd_"; const char self_name[] = "__self__"; extern PIScreen screen; //bool Daemon::inited__ = false; 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(); } Daemon::Remote::~Remote() { ft.stop(); stop(true); } 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(); removeFinished(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; 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 << "Achtung! Alarm!! Error!!!"; showInfo("Error while files transfer..."); } } 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(): inited__(false), PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString(rand() % 100)), fm(this) { setName("Daemon"); dtimer.setName("__S__Daemon_timer"); mode = 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) localft.setName(self_name); CONNECTU(&localft, sendRequest, _self, received) dtimer.addDelimiter(5); dtimer.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(); 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) inited__ = true; } Daemon::~Daemon() { PIVector rl = remotes.values(); piForeach (Remote * r, rl) delete r; remotes.clear(); } PIScreenTile * Daemon::tile() const { return tile_root; } 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(); } 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) { 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 = 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) { PIMutexLocker ml(remote_mutex); //Remote * r = remotes.value(conn_name); // 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) 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)); 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 & p_name) { while (!inited__) piMSleep(5); // PIMutexLocker ml(peers_mutex); /*piCout << "connected" << name; mode = 2; conn_name = name;*/ if (!p_name.startsWith(pisd_prefix)) return; Remote * r = new Remote(p_name); piCoutObj << "peer connected" << p_name; // piCout << r->methodsEH() << this->methodsEH(); CONNECTU(r, sendRequest, this, sendRequest) CONNECTU(r, receiveFinished, this, filesReceived) CONNECTU(r, receiveFinished, this, closeFileDialog) CONNECTU(r, sendFinished, this, closeFileDialog) CONNECTU(r, removeFinished, this, filesRemoved) CONNECTU(r, changeDirFinished, this, dirChanged) PIMutexLocker ml2(remote_mutex); remotes.insert(p_name, r); } void Daemon::peerDisconnected(const PIString & p_name) { while (!inited__) piMSleep(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; 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) { PIMutexLocker ml(remote_mutex); Remote * r = remotes.value(p_name, 0); if (!r) return; r->updateDir(); } void Daemon::dirChanged(const PIString & p_name, const PIString & dir) { 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::filesRemoved(const PIString & p_name, const PIString & dir) { 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; } piCoutObj << "file transfer with" << p_name << (ok ? "success" : "failure"); if (tile_file_progress->conn_name != p_name) return; tile_file_progress->close(ok); // if (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) { //if (conn_name != from) return; if (data.size() < 4) return; PIMutexLocker ml(remote_mutex); 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(); piCout << "cd to" << r->dir_my.absolutePath(); r->updateDir(); // sendDirToRemote(r); break; case ReplyHostInfo: ba >> info_other; makeOtherHostInfo(); fillInfoTile(info_other); break; case ReplyChangeDir: if (!r) break; { PIVector fil; ba >> dir >> fil; // r->dir_remote.setDir(dir); 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); //answer_dirs = true; } 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; }; if (!rba.isEmpty()) send(from, rba); } void Daemon::sendDirToRemote(Remote * r) { if (!r) return; PIVector fil = r->my_filelist; PIByteArray ba; ba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil; send(r->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(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::requestChDir(const PIString & d) { if (d.isEmpty()) return; Remote * r = remotes.value(conn_name, 0); //piCout << "request chdir" << d << conn_name << r; if (d.isEmpty()) return; if (!r) return; fm.remoteSaveDir(); fm.readingRemote(); PIByteArray ba; ba << int(RequestChangeDir) << d; send(conn_name, ba); }