Browse Source

Background resolver.

Adam Ierymenko 10 years ago
parent
commit
2ad69237cf
3 changed files with 258 additions and 0 deletions
  1. 1 0
      objects.mk
  2. 130 0
      osdep/BackgroundResolver.cpp
  3. 127 0
      osdep/BackgroundResolver.hpp

+ 1 - 0
objects.mk

@@ -23,6 +23,7 @@ OBJS=\
 	node/Switch.o \
 	node/Switch.o \
 	node/Topology.o \
 	node/Topology.o \
 	node/Utils.o \
 	node/Utils.o \
+	osdep/BackgroundResolver.o \
 	osdep/Http.o \
 	osdep/Http.o \
 	osdep/OSUtils.o \
 	osdep/OSUtils.o \
 	service/ControlPlane.o \
 	service/ControlPlane.o \

+ 130 - 0
osdep/BackgroundResolver.cpp

@@ -0,0 +1,130 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2015  ZeroTier, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
+#include "OSUtils.hpp"
+#include "Thread.hpp"
+#include "BackgroundResolver.hpp"
+
+namespace ZeroTier {
+
+/*
+ * We can't actually abort a job. This is a legacy characteristic of the
+ * ancient synchronous resolver APIs. So to abort jobs, we just abandon
+ * them by setting their parent to null.
+ */
+class BackgroundResolverJob
+{
+public:
+	std::string name;
+	BackgroundResolver *volatile parent;
+	Mutex lock;
+
+	void threadMain()
+		throw()
+	{
+		std::vector<InetAddress> ips;
+		try {
+			ips = OSUtils::resolve(name.c_str());
+		} catch ( ... ) {}
+		{
+			Mutex::Lock _l(lock);
+			BackgroundResolver *p = parent;
+			if (p)
+				p->_postResult(ips);
+		}
+		delete this;
+	}
+};
+
+BackgroundResolver::BackgroundResolver(const char *name) :
+	_name(name),
+	_job((BackgroundResolverJob *)0),
+	_callback(0),
+	_arg((void *)0),
+	_ips(),
+	_lock()
+{
+}
+
+BackgroundResolver::~BackgroundResolver()
+{
+	abort();
+}
+
+std::vector<InetAddress> BackgroundResolver::get() const
+{
+	Mutex::Lock _l(_lock);
+	return _ips;
+}
+
+void BackgroundResolver::resolveNow(void (*callback)(BackgroundResolver *,void *),void *arg)
+{
+	Mutex::Lock _l(_lock);
+
+	if (_job) {
+		Mutex::Lock _l2(_job->lock);
+		_job->parent = (BackgroundResolver *)0;
+		_job = (BackgroundResolverJob *)0;
+	}
+
+	BackgroundResolverJob *j = new BackgroundResolverJob();
+	j->name = _name;
+	j->parent = this;
+
+	_job = j;
+	_callback = callback;
+	_arg = arg;
+
+	_jobThread = Thread::start(j);
+}
+
+void BackgroundResolver::abort()
+{
+	Mutex::Lock _l(_lock);
+	if (_job) {
+		Mutex::Lock _l2(_job->lock);
+		_job->parent = (BackgroundResolver *)0;
+		_job = (BackgroundResolverJob *)0;
+	}
+}
+
+void BackgroundResolver::_postResult(const std::vector<InetAddress> &ips)
+{
+	void (*cb)(BackgroundResolver *,void *);
+	void *a;
+	{
+		Mutex::Lock _l(_lock);
+		_job = (BackgroundResolverJob *)0;
+		cb = _callback;
+		a = _arg;
+		_ips = ips;
+	}
+	if (cb)
+		cb(this,a);
+}
+
+} // namespace ZeroTier

+ 127 - 0
osdep/BackgroundResolver.hpp

@@ -0,0 +1,127 @@
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2015  ZeroTier, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
+#ifndef ZT_BACKGROUNDRESOLVER_HPP
+#define ZT_BACKGROUNDRESOLVER_HPP
+
+#include <vector>
+#include <string>
+
+#include "../node/Constants.hpp"
+#include "../node/Mutex.hpp"
+#include "../node/InetAddress.hpp"
+#include "../node/NonCopyable.hpp"
+#include "Thread.hpp"
+
+namespace ZeroTier {
+
+class BackgroundResolverJob;
+
+/**
+ * A simple background resolver
+ */
+class BackgroundResolver : NonCopyable
+{
+	friend class BackgroundResolverJob;
+
+public:
+	/**
+	 * Construct a new resolver
+	 *
+	 * resolveNow() must be called to actually initiate background resolution.
+	 *
+	 * @param name Name to resolve
+	 */
+	BackgroundResolver(const char *name);
+
+	~BackgroundResolver();
+
+	/**
+	 * @return Most recent resolver results or empty vector if none
+	 */
+	std::vector<InetAddress> get() const;
+
+	/**
+	 * Launch a background resolve job now
+	 *
+	 * If a resolve job is currently in progress, it is aborted and another
+	 * job is started.
+	 *
+	 * Note that jobs can't actually be aborted due to the limitations of the
+	 * ancient synchronous OS resolver APIs. As a result, in progress jobs
+	 * that are aborted are simply abandoned. Don't call this too frequently
+	 * or background threads might pile up.
+	 *
+	 * @param callback Callback function to receive notification or NULL if none
+	 * @praam arg Second argument to callback function
+	 */
+	void resolveNow(void (*callback)(BackgroundResolver *,void *),void *arg);
+
+	/**
+	 * Abort (abandon) any current resolve jobs
+	 */
+	void abort();
+
+	/**
+	 * @return True if a background job is in progress
+	 */
+	inline bool running() const
+	{
+		Mutex::Lock _l(_lock);
+		return (_job != (BackgroundResolverJob *)0);
+	}
+
+	/**
+	 * Wait for pending job to complete (if any)
+	 */
+	inline void wait() const
+	{
+		Thread t;
+		{
+			Mutex::Lock _l(_lock);
+			if (!_job)
+				return;
+			t = _jobThread;
+		}
+		Thread::join(t);
+	}
+
+private:
+	void _postResult(const std::vector<InetAddress> &ips);
+
+	std::string _name;
+	BackgroundResolverJob *_job;
+	Thread _jobThread;
+	void (*_callback)(BackgroundResolver *,void *);
+	void *_arg;
+	std::vector<InetAddress> _ips;
+	Mutex _lock;
+};
+
+} // namespace ZeroTier
+
+#endif