Browse Source

UI basically works, almost ready for testing and packaging...

Adam Ierymenko 11 years ago
parent
commit
902c8c38d2
5 changed files with 108 additions and 13 deletions
  1. 70 9
      ZeroTierUI/mainwindow.cpp
  2. 22 2
      ZeroTierUI/mainwindow.h
  3. 1 1
      ZeroTierUI/mainwindow.ui
  4. 5 0
      node/Node.cpp
  5. 10 1
      node/Node.hpp

+ 70 - 9
ZeroTierUI/mainwindow.cpp

@@ -17,24 +17,32 @@
 #include <QProcess>
 #include <QProcess>
 #include <QStringList>
 #include <QStringList>
 
 
-static std::map< unsigned long,std::vector<std::string> > ztReplies;
-static QMutex ztReplies_m;
+// Globally visible
+ZeroTier::Node::LocalClient *zeroTierClient = (ZeroTier::Node::LocalClient *)0;
+
+// Main window instance for app
+static MainWindow *mainWindow = (MainWindow *)0;
+
 static void handleZTMessage(void *arg,unsigned long id,const char *line)
 static void handleZTMessage(void *arg,unsigned long id,const char *line)
 {
 {
+	static std::map< unsigned long,std::vector<std::string> > ztReplies;
+	static QMutex ztReplies_m;
+
 	ztReplies_m.lock();
 	ztReplies_m.lock();
 	if (*line) {
 	if (*line) {
 		ztReplies[id].push_back(std::string(line));
 		ztReplies[id].push_back(std::string(line));
 		ztReplies_m.unlock();
 		ztReplies_m.unlock();
 	} else { // empty lines conclude transmissions
 	} else { // empty lines conclude transmissions
-		std::vector<std::string> resp(ztReplies[id]);
-		ztReplies.erase(id);
-		ztReplies_m.unlock();
+		std::map< unsigned long,std::vector<std::string> >::iterator r(ztReplies.find(id));
+		if (r != ztReplies.end()) {
+			MainWindow::ZTMessageEvent *event = new MainWindow::ZTMessageEvent(r->second);
+			ztReplies.erase(r);
+			ztReplies_m.unlock();
+			QCoreApplication::postEvent(mainWindow,event); // must post since this may be another thread
+		} else ztReplies_m.unlock();
 	}
 	}
 }
 }
 
 
-// Globally visible
-ZeroTier::Node::LocalClient *volatile zeroTierClient = (ZeroTier::Node::LocalClient *)0;
-
 MainWindow::MainWindow(QWidget *parent) :
 MainWindow::MainWindow(QWidget *parent) :
 	QMainWindow(parent),
 	QMainWindow(parent),
 	ui(new Ui::MainWindow)
 	ui(new Ui::MainWindow)
@@ -42,6 +50,7 @@ MainWindow::MainWindow(QWidget *parent) :
 	ui->setupUi(this);
 	ui->setupUi(this);
 	this->startTimer(1000);
 	this->startTimer(1000);
 	this->setEnabled(false); // gets enabled when updates are received
 	this->setEnabled(false); // gets enabled when updates are received
+	mainWindow = this;
 }
 }
 
 
 MainWindow::~MainWindow()
 MainWindow::~MainWindow()
@@ -49,6 +58,7 @@ MainWindow::~MainWindow()
 	delete ui;
 	delete ui;
 	delete zeroTierClient;
 	delete zeroTierClient;
 	zeroTierClient = (ZeroTier::Node::LocalClient *)0;
 	zeroTierClient = (ZeroTier::Node::LocalClient *)0;
+	mainWindow = (MainWindow *)0;
 }
 }
 
 
 void MainWindow::timerEvent(QTimerEvent *event)
 void MainWindow::timerEvent(QTimerEvent *event)
@@ -86,6 +96,57 @@ void MainWindow::timerEvent(QTimerEvent *event)
 
 
 		zeroTierClient = new ZeroTier::Node::LocalClient(authToken.c_str(),0,&handleZTMessage,this);
 		zeroTierClient = new ZeroTier::Node::LocalClient(authToken.c_str(),0,&handleZTMessage,this);
 	}
 	}
+
+	zeroTierClient->send("info");
+	zeroTierClient->send("listnetworks");
+	zeroTierClient->send("listpeers");
+}
+
+void MainWindow::customEvent(QEvent *event)
+{
+	ZTMessageEvent *m = (ZTMessageEvent *)event; // only one custom event type so far
+
+	if (m->ztMessage.size() == 0)
+		return;
+
+	std::vector<std::string> hdr(ZeroTier::Node::LocalClient::splitLine(m->ztMessage[0]));
+	if (hdr.size() < 2)
+		return;
+	if (hdr[0] != "200")
+		return;
+
+	// Enable main window on valid communication with service
+	if (!this->isEnabled())
+		this->setEnabled(true);
+
+	if (hdr[1] == "info") {
+		if (hdr.size() >= 3)
+			this->myAddress = hdr[2].c_str();
+		if (hdr.size() >= 4)
+			this->myStatus = hdr[3].c_str();
+		if (hdr.size() >= 5)
+			this->myVersion = hdr[4].c_str();
+	} else if (hdr[1] == "listnetworks") {
+	} else if (hdr[1] == "listpeers") {
+		this->numPeers = 0;
+		for(unsigned long i=1;i<m->ztMessage.size();++i) {
+			std::vector<std::string> l(ZeroTier::Node::LocalClient::splitLine(m->ztMessage[i]));
+			if ((l.size() >= 5)&&((l[3] != "-")||(l[4] != "-")))
+				++this->numPeers; // number of direct peers online -- check for active IPv4 and/or IPv6 address
+		}
+	}
+
+	if (this->myAddress.size()) {
+		QString st(this->myAddress);
+		st += "    (";
+		st += this->myStatus;
+		st += ", ";
+		st += QString::number(this->numPeers);
+		st += " peers)";
+		while (st.size() < 38)
+			st += QChar::Space;
+		ui->statusAndAddressButton->setText(st);
+	}
 }
 }
 
 
 void MainWindow::on_joinNetworkButton_clicked()
 void MainWindow::on_joinNetworkButton_clicked()
@@ -143,5 +204,5 @@ void MainWindow::on_networkIdLineEdit_textChanged(const QString &text)
 
 
 void MainWindow::on_statusAndAddressButton_clicked()
 void MainWindow::on_statusAndAddressButton_clicked()
 {
 {
-	//	QApplication::clipboard()->setText(ui->myAddressCopyButton->text());
+	QApplication::clipboard()->setText(this->myAddress);
 }
 }

+ 22 - 2
ZeroTierUI/mainwindow.h

@@ -2,6 +2,8 @@
 #define MAINWINDOW_H
 #define MAINWINDOW_H
 
 
 #include <QMainWindow>
 #include <QMainWindow>
+#include <QEvent>
+#include <QString>
 
 
 #include "../node/Node.hpp"
 #include "../node/Node.hpp"
 #include "../node/Utils.hpp"
 #include "../node/Utils.hpp"
@@ -12,18 +14,31 @@ class MainWindow;
 
 
 // Globally visible instance of local client for communicating with ZT1
 // Globally visible instance of local client for communicating with ZT1
 // Can be null if not connected, or will point to current
 // Can be null if not connected, or will point to current
-extern ZeroTier::Node::LocalClient *volatile zeroTierClient;
+extern ZeroTier::Node::LocalClient *zeroTierClient;
 
 
 class MainWindow : public QMainWindow
 class MainWindow : public QMainWindow
 {
 {
 	Q_OBJECT
 	Q_OBJECT
 
 
 public:
 public:
+	class ZTMessageEvent : public QEvent
+	{
+	public:
+		ZTMessageEvent(const std::vector<std::string> &m) :
+			QEvent(QEvent::User),
+			ztMessage(m)
+		{
+		}
+
+		std::vector<std::string> ztMessage;
+	};
+
 	explicit MainWindow(QWidget *parent = 0);
 	explicit MainWindow(QWidget *parent = 0);
-	~MainWindow();
+	virtual ~MainWindow();
 
 
 protected:
 protected:
 	virtual void timerEvent(QTimerEvent *event);
 	virtual void timerEvent(QTimerEvent *event);
+	virtual void customEvent(QEvent *event);
 
 
 private slots:
 private slots:
 	void on_joinNetworkButton_clicked();
 	void on_joinNetworkButton_clicked();
@@ -35,6 +50,11 @@ private slots:
 
 
 private:
 private:
 	Ui::MainWindow *ui;
 	Ui::MainWindow *ui;
+
+	QString myAddress;
+	QString myStatus;
+	QString myVersion;
+	unsigned int numPeers;
 };
 };
 
 
 #endif // MAINWINDOW_H
 #endif // MAINWINDOW_H

+ 1 - 1
ZeroTierUI/mainwindow.ui

@@ -131,7 +131,7 @@
           <string notr="true">border: 0;</string>
           <string notr="true">border: 0;</string>
          </property>
          </property>
          <property name="text">
          <property name="text">
-          <string>0000000000    (OFFLINE, 0 peers)   </string>
+          <string>0000000000    (OFFLINE, 0 peers)     </string>
          </property>
          </property>
          <property name="toolButtonStyle">
          <property name="toolButtonStyle">
           <enum>Qt::ToolButtonTextOnly</enum>
           <enum>Qt::ToolButtonTextOnly</enum>

+ 5 - 0
node/Node.cpp

@@ -182,6 +182,11 @@ unsigned long Node::LocalClient::send(const char *command)
 	}
 	}
 }
 }
 
 
+std::vector<std::string> Node::LocalClient::splitLine(const char *line)
+{
+	return Utils::split(line," ","\\","\"");
+}
+
 struct _NodeImpl
 struct _NodeImpl
 {
 {
 	RuntimeEnvironment renv;
 	RuntimeEnvironment renv;

+ 10 - 1
node/Node.hpp

@@ -71,6 +71,15 @@ public:
 		unsigned long send(const char *command)
 		unsigned long send(const char *command)
 			throw();
 			throw();
 
 
+		/**
+		 * Split a line of results by space
+		 *
+		 * @param line Line to split
+		 * @return Vector of fields
+		 */
+		static std::vector<std::string> splitLine(const char *line);
+		static inline std::vector<std::string> splitLine(const std::string &line) { return splitLine(line.c_str()); }
+
 	private:
 	private:
 		// LocalClient is not copyable
 		// LocalClient is not copyable
 		LocalClient(const LocalClient&);
 		LocalClient(const LocalClient&);
@@ -140,7 +149,7 @@ public:
 
 
 	/**
 	/**
 	 * Get the ZeroTier version in major.minor.revision string format
 	 * Get the ZeroTier version in major.minor.revision string format
-	 * 
+	 *
 	 * @return Version in string form
 	 * @return Version in string form
 	 */
 	 */
 	static const char *versionString()
 	static const char *versionString()