diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-05-21 13:44:33 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-05-21 13:44:33 -0700 |
commit | 2ad69237cfc1f716351464dd05839699c066b80a (patch) | |
tree | 1612605cfb7f4bb5875c6b9ab5671a93cf99be99 | |
parent | 82f6b3f550fe7612bf5043e1c3361f74f1fa9244 (diff) | |
download | infinitytier-2ad69237cfc1f716351464dd05839699c066b80a.tar.gz infinitytier-2ad69237cfc1f716351464dd05839699c066b80a.zip |
Background resolver.
-rw-r--r-- | objects.mk | 1 | ||||
-rw-r--r-- | osdep/BackgroundResolver.cpp | 130 | ||||
-rw-r--r-- | osdep/BackgroundResolver.hpp | 127 |
3 files changed, 258 insertions, 0 deletions
@@ -23,6 +23,7 @@ OBJS=\ node/Switch.o \ node/Topology.o \ node/Utils.o \ + osdep/BackgroundResolver.o \ osdep/Http.o \ osdep/OSUtils.o \ service/ControlPlane.o \ diff --git a/osdep/BackgroundResolver.cpp b/osdep/BackgroundResolver.cpp new file mode 100644 index 00000000..e009fe06 --- /dev/null +++ b/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 diff --git a/osdep/BackgroundResolver.hpp b/osdep/BackgroundResolver.hpp new file mode 100644 index 00000000..7909d271 --- /dev/null +++ b/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 |