diff --git a/ZeroTierUI/aboutwindow.cpp b/ZeroTierUI/aboutwindow.cpp index 83d680b1d..1a2b22907 100644 --- a/ZeroTierUI/aboutwindow.cpp +++ b/ZeroTierUI/aboutwindow.cpp @@ -1,11 +1,17 @@ #include "aboutwindow.h" #include "ui_aboutwindow.h" +#include +#include "../node/Defaults.hpp" + AboutWindow::AboutWindow(QWidget *parent) : QDialog(parent), ui(new Ui::AboutWindow) { ui->setupUi(this); +#ifndef __APPLE__ + ui->uninstallButton->hide(); +#endif } AboutWindow::~AboutWindow() @@ -15,4 +21,11 @@ AboutWindow::~AboutWindow() void AboutWindow::on_uninstallButton_clicked() { + // Apple only... other OSes have more intrinsic mechanisms for uninstalling. + QMessageBox::information( + this, + "Uninstalling ZeroTier One", + QString("Uninstalling ZeroTier One is easy!\n\nJust remove ZeroTier One from your Applications folder and the service will automatically shut down within a few seconds. Then, on your next reboot, all other support files will be automatically deleted.\n\nIf you wish to uninstall the service and support files now, you can run the 'uninstall.sh' script found in ") + ZeroTier::ZT_DEFAULTS.defaultHomePath.c_str() + " using the 'sudo' command in a terminal.", + QMessageBox::Ok, + QMessageBox::NoButton); } diff --git a/ZeroTierUI/aboutwindow.ui b/ZeroTierUI/aboutwindow.ui index 34ad0235c..84aab4347 100644 --- a/ZeroTierUI/aboutwindow.ui +++ b/ZeroTierUI/aboutwindow.ui @@ -11,7 +11,7 @@ - Dialog + About ZeroTier One diff --git a/ZeroTierUI/mainwindow.cpp b/ZeroTierUI/mainwindow.cpp index e427a6a16..6e972c73c 100644 --- a/ZeroTierUI/mainwindow.cpp +++ b/ZeroTierUI/mainwindow.cpp @@ -52,9 +52,10 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow) { ui->setupUi(this); - this->startTimer(1000); + this->startTimer(1000); // poll service every second this->setEnabled(false); // gets enabled when updates are received mainWindow = this; + this->cyclesSinceResponseFromService = 0; } MainWindow::~MainWindow() @@ -101,6 +102,11 @@ void MainWindow::timerEvent(QTimerEvent *event) zeroTierClient = new ZeroTier::Node::LocalClient(authToken.c_str(),0,&handleZTMessage,this); } + // TODO: do something more user-friendly here... or maybe try to restart + // the service? + if (++this->cyclesSinceResponseFromService == 3) + QMessageBox::critical(this,"No Response from Service","The ZeroTier One service does not appear to be running.",QMessageBox::Ok,QMessageBox::NoButton); + zeroTierClient->send("info"); zeroTierClient->send("listnetworks"); zeroTierClient->send("listpeers"); @@ -119,9 +125,7 @@ void MainWindow::customEvent(QEvent *event) if (hdr[0] != "200") return; - // Enable main window on valid communication with service - if (!this->isEnabled()) - this->setEnabled(true); + this->cyclesSinceResponseFromService = 0; if (hdr[1] == "info") { if (hdr.size() >= 3) @@ -134,8 +138,8 @@ void MainWindow::customEvent(QEvent *event) std::map< std::string,std::vector > byNwid; for(unsigned long i=1;iztMessage.size();++i) { std::vector l(ZeroTier::Node::LocalClient::splitLine(m->ztMessage[i])); - // 200 listnetworks - if ((l.size() == 8)&&(l[2].length() == 16)) + // 200 listnetworks + if ((l.size() == 9)&&(l[2].length() == 16)) byNwid[l[2]] = l; } @@ -149,10 +153,10 @@ void MainWindow::customEvent(QEvent *event) if (byNwid.count(i->first)) { std::vector &l = byNwid[i->first]; i->second.second->setNetworkName(l[3]); - i->second.second->setStatus(l[4]); - i->second.second->setNetworkType(l[5]); - i->second.second->setNetworkDeviceName(l[6]); - i->second.second->setIps(l[7]); + i->second.second->setStatus(l[4],l[5]); + i->second.second->setNetworkType(l[6]); + i->second.second->setNetworkDeviceName(l[7]); + i->second.second->setIps(l[8]); } else { delete ui->networkListWidget->takeItem(i->second.first); } @@ -163,10 +167,10 @@ void MainWindow::customEvent(QEvent *event) std::vector &l = i->second; Network *nw = new Network((QWidget *)0,i->first); nw->setNetworkName(l[3]); - nw->setStatus(l[4]); - nw->setNetworkType(l[5]); - nw->setNetworkDeviceName(l[6]); - nw->setIps(l[7]); + nw->setStatus(l[4],l[5]); + nw->setNetworkType(l[6]); + nw->setNetworkDeviceName(l[7]); + nw->setIps(l[8]); QListWidgetItem *item = new QListWidgetItem(); item->setSizeHint(nw->sizeHint()); ui->networkListWidget->addItem(item); @@ -186,13 +190,23 @@ void MainWindow::customEvent(QEvent *event) QString st(this->myAddress); st += " ("; st += this->myStatus; + st += ", v"; + st += this->myVersion; st += ", "; st += QString::number(this->numPeers); st += " peers)"; - while (st.size() < 38) + while (st.size() < 45) st += QChar::Space; ui->statusAndAddressButton->setText(st); } + + if (this->myStatus == "ONLINE") { + if (!this->isEnabled()) + this->setEnabled(true); + } else { + if (this->isEnabled()) + this->setEnabled(false); + } } void MainWindow::on_joinNetworkButton_clicked() @@ -217,12 +231,6 @@ void MainWindow::on_actionAbout_triggered() about->show(); } -void MainWindow::on_actionJoin_Network_triggered() -{ - // Does the same thing as clicking join button on main UI - on_joinNetworkButton_clicked(); -} - void MainWindow::on_networkIdLineEdit_textChanged(const QString &text) { QString newText; diff --git a/ZeroTierUI/mainwindow.h b/ZeroTierUI/mainwindow.h index ed11ff44b..66a0b350c 100644 --- a/ZeroTierUI/mainwindow.h +++ b/ZeroTierUI/mainwindow.h @@ -45,8 +45,7 @@ protected: private slots: void on_joinNetworkButton_clicked(); void on_actionAbout_triggered(); - void on_actionJoin_Network_triggered(); - void on_networkIdLineEdit_textChanged(const QString &arg1); + void on_networkIdLineEdit_textChanged(const QString &text); void on_statusAndAddressButton_clicked(); private: @@ -56,6 +55,7 @@ private: QString myStatus; QString myVersion; unsigned int numPeers; + unsigned int cyclesSinceResponseFromService; }; #endif // MAINWINDOW_H diff --git a/ZeroTierUI/mainwindow.ui b/ZeroTierUI/mainwindow.ui index 025ac6cd4..c51036246 100644 --- a/ZeroTierUI/mainwindow.ui +++ b/ZeroTierUI/mainwindow.ui @@ -110,7 +110,7 @@ border: 0; - 0000000000 (OFFLINE, 0 peers) + 0000000000 (OFFLINE, v0.0.0, 0 peers) Qt::ToolButtonTextOnly @@ -203,7 +203,6 @@ File - @@ -215,11 +214,6 @@ About - - - Join Network - - Exit diff --git a/ZeroTierUI/network.cpp b/ZeroTierUI/network.cpp index 1631c816c..e23bc6baa 100644 --- a/ZeroTierUI/network.cpp +++ b/ZeroTierUI/network.cpp @@ -28,9 +28,12 @@ Network::~Network() delete ui; } -void Network::setStatus(const std::string &status) +void Network::setStatus(const std::string &status,const std::string &age) { ui->statusLabel->setText(QString(status.c_str())); + if (status == "OK") + ui->ageLabel->setText(QString("(configuration is ") + age.c_str() + " seconds old)"); + else ui->ageLabel->setText(QString()); } void Network::setNetworkName(const std::string &name) diff --git a/ZeroTierUI/network.h b/ZeroTierUI/network.h index a47915e10..a50354afc 100644 --- a/ZeroTierUI/network.h +++ b/ZeroTierUI/network.h @@ -17,7 +17,7 @@ public: explicit Network(QWidget *parent = 0,const std::string &nwid = std::string()); virtual ~Network(); - void setStatus(const std::string &status); + void setStatus(const std::string &status,const std::string &age); void setNetworkName(const std::string &name); void setNetworkType(const std::string &type); void setNetworkDeviceName(const std::string &dev); diff --git a/ZeroTierUI/network.ui b/ZeroTierUI/network.ui index 9ea3cb85e..e6dc65241 100644 --- a/ZeroTierUI/network.ui +++ b/ZeroTierUI/network.ui @@ -174,28 +174,6 @@ - - - - - 0 - 0 - - - - - 75 - true - - - - ? - - - Qt::PlainText - - - @@ -222,6 +200,76 @@ + + + + + 0 + 0 + + + + + 12 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 75 + true + + + + ? + + + Qt::PlainText + + + + + + + + 0 + 0 + + + + + 10 + + + + (configuration is 0 seconds old) + + + Qt::PlainText + + + + + + diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index d56c73aeb..ce5943c56 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -200,7 +200,7 @@ std::vector NodeConfig::execute(const char *command) _r->topology->eachPeer(_DumpPeerStatistics(r)); } else if (cmd[0] == "listnetworks") { Mutex::Lock _l(_networks_m); - _P("200 listnetworks "); + _P("200 listnetworks "); for(std::map< uint64_t,SharedPtr >::const_iterator nw(_networks.begin());nw!=_networks.end();++nw) { std::string tmp; std::set ips(nw->second->tap().ips()); @@ -211,10 +211,17 @@ std::vector NodeConfig::execute(const char *command) } SharedPtr nconf(nw->second->config2()); - _P("200 listnetworks %.16llx %s %s %s %s %s", + + long long age = (nconf) ? ((long long)Utils::now() - (long long)nconf->timestamp()) : (long long)0; + if (age < 0) + age = 0; + age /= 1000; + + _P("200 listnetworks %.16llx %s %s %lld %s %s %s", (unsigned long long)nw->first, ((nconf) ? nconf->name().c_str() : "?"), Network::statusString(nw->second->status()), + age, ((nconf) ? (nconf->isOpen() ? "public" : "private") : "?"), nw->second->tap().deviceName().c_str(), ((tmp.length() > 0) ? tmp.c_str() : "-"));