diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/EthernetTap.cpp | 8 | ||||
-rw-r--r-- | node/EthernetTap.hpp | 11 | ||||
-rw-r--r-- | node/Network.cpp | 8 | ||||
-rw-r--r-- | node/Network.hpp | 54 | ||||
-rw-r--r-- | node/Node.cpp | 2 | ||||
-rw-r--r-- | node/NodeConfig.cpp | 4 | ||||
-rw-r--r-- | node/Service.cpp | 12 | ||||
-rw-r--r-- | node/Service.hpp | 11 | ||||
-rw-r--r-- | node/Thread.cpp | 182 | ||||
-rw-r--r-- | node/Thread.hpp | 104 | ||||
-rw-r--r-- | node/Topology.cpp | 10 | ||||
-rw-r--r-- | node/Topology.hpp | 11 | ||||
-rw-r--r-- | node/UdpSocket.cpp | 5 | ||||
-rw-r--r-- | node/UdpSocket.hpp | 11 |
14 files changed, 134 insertions, 299 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp index c45d50c2..870baceb 100644 --- a/node/EthernetTap.cpp +++ b/node/EthernetTap.cpp @@ -187,7 +187,7 @@ EthernetTap::EthernetTap( TRACE("tap %s created",_dev); - start(); + _thread = Thread<EthernetTap>::start(this); } #endif // __LINUX__ @@ -271,14 +271,14 @@ EthernetTap::EthernetTap( ::pipe(_shutdownSignalPipe); - start(); + _thread = Thread<EthernetTap>::start(this); } #endif // __APPLE__ EthernetTap::~EthernetTap() { ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit - join(); + Thread<EthernetTap>::join(_thread); ::close(_fd); } @@ -549,7 +549,7 @@ bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups) } #endif // __APPLE__ -void EthernetTap::main() +void EthernetTap::threadMain() throw() { fd_set readfds,nullfds; diff --git a/node/EthernetTap.hpp b/node/EthernetTap.hpp index 3bc7cad8..6fb4c134 100644 --- a/node/EthernetTap.hpp +++ b/node/EthernetTap.hpp @@ -51,7 +51,7 @@ class RuntimeEnvironment; /** * System ethernet tap device */ -class EthernetTap : protected Thread +class EthernetTap { public: /** @@ -79,7 +79,7 @@ public: * * This may block for a few seconds while thread exits. */ - virtual ~EthernetTap(); + ~EthernetTap(); /** * Perform OS dependent actions on network configuration change detection @@ -169,8 +169,10 @@ public: */ bool updateMulticastGroups(std::set<MulticastGroup> &groups); -protected: - virtual void main() + /** + * Thread main method; do not call elsewhere + */ + void threadMain() throw(); private: @@ -178,6 +180,7 @@ private: const unsigned int _mtu; const RuntimeEnvironment *_r; + Thread<EthernetTap> _thread; std::set<InetAddress> _ips; Mutex _ips_m; diff --git a/node/Network.cpp b/node/Network.cpp index 37761aff..6deb31fe 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -108,6 +108,8 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id) _id(id), _lastConfigUpdate(0) { + if (controller() == _r->identity.address()) + throw std::runtime_error("configuration error: cannot add a network for which I am the netconf master"); } Network::~Network() @@ -118,6 +120,7 @@ void Network::setConfiguration(const Network::Config &conf) { Mutex::Lock _l(_lock); if ((conf.networkId() == _id)&&(conf.peerAddress() == _r->identity.address())) { // sanity check + TRACE("network %.16llx got netconf:\n%s",(unsigned long long)_id,conf.toString().c_str()); _configuration = conf; _myCertificate = conf.certificateOfMembership(); _lastConfigUpdate = Utils::now(); @@ -126,6 +129,11 @@ void Network::setConfiguration(const Network::Config &conf) void Network::requestConfiguration() { + if (controller() == _r->identity.address()) { + LOG("unable to request network configuration for network %.16llx: I am the network master, cannot query self",(unsigned long long)_id); + return; + } + TRACE("requesting netconf for network %.16llx from netconf master %s",(unsigned long long)_id,controller().toString().c_str()); Packet outp(controller(),_r->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); outp.append((uint64_t)_id); _r->sw->send(outp,true); diff --git a/node/Network.hpp b/node/Network.hpp index 4155d5d8..d3bb5ad7 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -99,10 +99,10 @@ public: { } - /** - * @return Read-only underlying dictionary - */ - inline const Dictionary &dictionary() const { return *this; } + inline std::string toString() const + { + return Dictionary::toString(); + } inline void setNetworkId(uint64_t id) { @@ -208,11 +208,9 @@ public: { } - inline void setNetworkId(uint64_t id) + inline std::string toString() const { - char buf[32]; - sprintf(buf,"%.16llx",(unsigned long long)id); - (*this)["nwid"] = buf; + return Dictionary::toString(); } inline uint64_t networkId() const @@ -221,11 +219,6 @@ public: return strtoull(get("nwid").c_str(),(char **)0,16); } - inline void setPeerAddress(Address &a) - { - (*this)["peer"] = a.toString(); - } - inline Address peerAddress() const throw(std::invalid_argument) { @@ -265,41 +258,6 @@ public: sa.insert(InetAddress(*i)); return sa; } - - /** - * Set static IPv4 and IPv6 addresses - * - * This sets the ipv4Static and ipv6Static fields to comma-delimited - * lists of assignments. The port field in InetAddress must be the - * number of bits in the netmask. - * - * @param begin Start of container or array of addresses (InetAddress) - * @param end End of container or array of addresses (InetAddress) - * @tparam I Type of container or array - */ - template<typename I> - inline void setStaticInetAddresses(const I &begin,const I &end) - { - std::string v4; - std::string v6; - for(I i(begin);i!=end;++i) { - if (i->isV4()) { - if (v4.length()) - v4.push_back(','); - v4.append(i->toString()); - } else if (i->isV6()) { - if (v6.length()) - v6.push_back(','); - v6.append(i->toString()); - } - } - if (v4.length()) - (*this)["ipv4Static"] = v4; - else erase("ipv4Static"); - if (v6.length()) - (*this)["ipv6Static"] = v6; - else erase("ipv6Static"); - } }; private: diff --git a/node/Node.cpp b/node/Node.cpp index ef2a801c..da752bb2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -426,7 +426,7 @@ Node::ReasonForTermination Node::run() if (lastDelayDelta >= ZT_SLEEP_WAKE_DETECTION_THRESHOLD) { resynchronize = true; LOG("probable suspend/resume detected, pausing a moment for things to settle..."); - Thread::sleep(ZT_SLEEP_WAKE_SETTLE_TIME); + Thread<Node>::sleep(ZT_SLEEP_WAKE_SETTLE_TIME); } // Periodically check our network environment, sending pings out to all diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index 4a174535..0a6c014f 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -243,8 +243,10 @@ void NodeConfig::_CBcontrolPacketHandler(UdpSocket *sock,void *arg,const InetAdd for(std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> >::iterator p(resultPackets.begin());p!=resultPackets.end();++p) sock->send(remoteAddr,p->data(),p->size(),-1); } + } catch (std::exception &exc) { + TRACE("exception handling control bus packet from %s: %s",remoteAddr.toString().c_str(),exc.what()); } catch ( ... ) { - TRACE("exception handling control bus packet from %s",remoteAddr.toString().c_str()); + TRACE("exception handling control bus packet from %s: (unknown)",remoteAddr.toString().c_str()); } } diff --git a/node/Service.cpp b/node/Service.cpp index c614e4e4..0d4702f8 100644 --- a/node/Service.cpp +++ b/node/Service.cpp @@ -62,7 +62,7 @@ Service::Service(const RuntimeEnvironment *renv,const char *name,const char *pat _childStderr(0), _run(true) { - start(); + _thread = Thread<Service>::start(this); } Service::~Service() @@ -77,14 +77,14 @@ Service::~Service() pid = 0; break; } - Thread::sleep(100); + Thread<Service>::sleep(100); } if (pid > 0) { ::kill(pid,SIGKILL); waitpid(pid,&st,0); } } - join(); + Thread<Service>::join(_thread); } bool Service::send(const Dictionary &msg) @@ -107,7 +107,7 @@ bool Service::send(const Dictionary &msg) return true; } -void Service::main() +void Service::threadMain() throw() { char buf[131072]; @@ -136,7 +136,7 @@ void Service::main() close(in[0]); close(out[1]); close(err[1]); - Thread::sleep(500); // give child time to start + Thread<Service>::sleep(500); // give child time to start _childStdin = in[1]; _childStdout = out[0]; _childStderr = err[0]; @@ -168,7 +168,7 @@ void Service::main() LOG("service %s exited with exit code: %d, delaying 1s to attempt relaunch",_name.c_str(),st); - Thread::sleep(1000); // wait to relaunch + Thread<Service>::sleep(1000); // wait to relaunch continue; } } diff --git a/node/Service.hpp b/node/Service.hpp index c8b729c7..0b00d81d 100644 --- a/node/Service.hpp +++ b/node/Service.hpp @@ -60,7 +60,7 @@ class RuntimeEnvironment; * logged via the standard Logger instance. If the subprocess dies, an * attempt is made to restart it every second. */ -class Service : protected Thread +class Service { public: /** @@ -78,7 +78,7 @@ public: void (*handler)(void *,Service &,const Dictionary &), void *arg); - virtual ~Service(); + ~Service(); /** * Send a message to service subprocess @@ -106,12 +106,15 @@ public: return (_pid > 0); } -protected: - virtual void main() + /** + * Thread main method; do not call elsewhere + */ + void threadMain() throw(); private: const RuntimeEnvironment *_r; + Thread<Service> _thread; std::string _path; std::string _name; void *_arg; diff --git a/node/Thread.cpp b/node/Thread.cpp deleted file mode 100644 index f650f6fc..00000000 --- a/node/Thread.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/*
- * ZeroTier One - Global Peer to Peer Ethernet
- * Copyright (C) 2012-2013 ZeroTier Networks LLC
- *
- * 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 "Thread.hpp"
-
-#if defined(__APPLE__) || defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux)
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <stdexcept>
-
-extern "C" {
-static void *__m_thread_main(void *ptr)
-{
- ((ZeroTier::Thread *)ptr)->__intl_run();
- return (void *)0;
-}
-}
-
-namespace ZeroTier {
-
-Thread::Thread() :
- _impl(malloc(sizeof(pthread_t))),
- _running()
-{
- memset(_impl,0,sizeof(pthread_t));
-}
-
-Thread::~Thread()
-{
- free(_impl);
-}
-
-void Thread::start()
-{
- if (!*_running) {
- ++_running;
- pthread_create((pthread_t *)_impl,(const pthread_attr_t *)0,&__m_thread_main,(void *)this);
- }
-}
-
-void Thread::join()
-{
- void *tmp;
- if (*_running)
- pthread_join(*((pthread_t *)_impl),&tmp);
-}
-
-void Thread::sleep(unsigned long ms)
-{
- usleep(ms * 1000);
-}
-
-void Thread::__intl_run()
-{
- for(;;) {
- _notInit = false;
- this->main();
- if (_notInit) // UGLY ASS HACK: see main()
- usleep(50);
- else break;
- }
- --_running;
-}
-
-void Thread::main()
- throw()
-{
- _notInit = true; // UGLY ASS HACK: retry if subclass has not defined virtual function pointer yet
-}
-
-} // namespace ZeroTier
-
-#endif
-
-#ifdef _WIN32
-
-#include <Windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-DWORD WINAPI __m_thread_main(LPVOID lpParam)
-{
- ((ZeroTier::Thread *)lpParam)->__intl_run();
- return 0;
-}
-
-struct __m_thread_info
-{
- HANDLE threadHandle;
- DWORD threadId;
- bool started;
-};
-
-namespace ZeroTier {
-
-Thread::Thread() :
- _impl(malloc(sizeof(__m_thread_info))),
- _running()
-{
- memset(_impl,0,sizeof(__m_thread_info));
-}
-
-Thread::~Thread()
-{
- if (((__m_thread_info *)_impl)->started)
- CloseHandle(((__m_thread_info *)_impl)->threadHandle);
- free(_impl);
-}
-
-void Thread::start()
-{
- if (!*_running) {
- ++_running;
- if ((((__m_thread_info *)_impl)->threadHandle = CreateThread(NULL,0,__m_thread_main,this,0,&(((__m_thread_info *)_impl)->threadId))) != NULL) {
- ((__m_thread_info *)_impl)->started = true;
- }
- }
-}
-
-void Thread::join()
-{
- if (*_running)
- WaitForSingleObject(((__m_thread_info *)_impl)->threadHandle,INFINITE);
-}
-
-void Thread::__intl_run()
-{
- for(;;) {
- _notInit = false;
- this->main();
- if (_notInit)
- Thread::sleep(50);
- else break;
- }
- --_running;
-}
-
-void Thread::main()
- throw()
-{
- _notInit = true; // HACK: retry if subclass has not defined virtual function pointer yet
-}
-
-struct _Thread_RunInBackgroundData
-{
- void (*func)(void *);
- void *ptr;
- HANDLE threadHandle;
- DWORD threadId;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/Thread.hpp b/node/Thread.hpp index 9b399a00..444da2be 100644 --- a/node/Thread.hpp +++ b/node/Thread.hpp @@ -28,62 +28,104 @@ #ifndef _ZT_THREAD_HPP
#define _ZT_THREAD_HPP
-#include "NonCopyable.hpp"
+#include <stdexcept>
+
+#include "Constants.hpp"
#include "AtomicCounter.hpp"
+#ifdef __WINDOWS__
+
+todo need windows;
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
namespace ZeroTier {
+template<typename C>
+static void *___zt_threadMain(void *instance)
+{
+ try {
+ ((C *)instance)->threadMain();
+ } catch ( ... ) {}
+ return (void *)0;
+}
+
/**
- * Wrapper for OS-dependent thread functions like pthread_create, etc.
+ * A thread of a given class type
+ *
+ * @tparam C Class using Thread
*/
-class Thread : NonCopyable
+template<typename C>
+class Thread
{
public:
- Thread();
- virtual ~Thread();
+ Thread()
+ throw()
+ {
+ memset(&_tid,0,sizeof(_tid));
+ }
- /**
- * Start thread -- can only be called once
- */
- void start();
+ Thread(const Thread &t)
+ throw()
+ {
+ memcpy(&_tid,&(t._tid),sizeof(_tid));
+ }
- /**
- * Wait for thread to terminate
- *
- * More than one thread should not simultaneously use join().
- */
- void join();
+ inline Thread &operator=(const Thread &t)
+ throw()
+ {
+ memcpy(&_tid,&(t._tid),sizeof(_tid));
+ return *this;
+ }
/**
- * @return True if thread is running
+ * Start a new thread
+ *
+ * @param instance Instance whose threadMain() method gets called by new thread
+ * @return Thread identifier
+ * @throws std::runtime_error Unable to create thread
*/
- inline bool running() const { return (*_running > 0); }
+ static inline Thread start(C *instance)
+ throw(std::runtime_error)
+ {
+ Thread t;
+ if (pthread_create(&t._tid,(const pthread_attr_t *)0,&___zt_threadMain<C>,instance))
+ throw std::runtime_error("pthread_create() failed, unable to create thread");
+ return t;
+ }
/**
- * Internal bounce method; do not call or override
+ * Join to a thread, waiting for it to terminate
+ *
+ * @param t Thread to join
*/
- void __intl_run();
+ static inline void join(const Thread &t)
+ {
+ pthread_join(t._tid,(void **)0);
+ }
/**
* Sleep the current thread
*
- * @param ms Milliseconds to sleep
+ * @param ms Number of milliseconds to sleep
*/
- static void sleep(unsigned long ms);
-
-protected:
- /**
- * Override to set a thread main function
- */
- virtual void main()
- throw();
+ static inline void sleep(unsigned long ms)
+ {
+ usleep(ms * 1000);
+ }
private:
- void *_impl;
- AtomicCounter _running;
- volatile bool _notInit;
+ pthread_t _tid;
};
} // namespace ZeroTier
+#endif // __WINDOWS__ / !__WINDOWS__
+
#endif
diff --git a/node/Topology.cpp b/node/Topology.cpp index 8487684e..ff012eaa 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -38,7 +38,6 @@ namespace ZeroTier { Topology::Topology(const RuntimeEnvironment *renv,const char *dbpath) throw(std::runtime_error) : - Thread(), _r(renv), _amSupernode(false) { @@ -55,7 +54,7 @@ Topology::Topology(const RuntimeEnvironment *renv,const char *dbpath) Utils::lockDownFile(dbpath,false); // node.db caches secrets - start(); + _thread = Thread<Topology>::start(this); } Topology::~Topology() @@ -68,10 +67,7 @@ Topology::~Topology() _peerDeepVerifyJobs.back().type = _PeerDeepVerifyJob::EXIT_THREAD; } _peerDeepVerifyJobs_c.signal(); - - while (running()) - Thread::sleep(10); // wait for thread to terminate without join() - + Thread<Topology>::join(_thread); KISSDB_close(&_dbm); } @@ -223,7 +219,7 @@ void Topology::clean() _peerDeepVerifyJobs_c.signal(); } -void Topology::main() +void Topology::threadMain() throw() { for(;;) { diff --git a/node/Topology.hpp b/node/Topology.hpp index 104ad344..b917738e 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -55,7 +55,7 @@ class RuntimeEnvironment; /** * Database of network topology */ -class Topology : protected Thread +class Topology { public: /** @@ -74,7 +74,7 @@ public: Topology(const RuntimeEnvironment *renv,const char *dbpath) throw(std::runtime_error); - virtual ~Topology(); + ~Topology(); /** * Set up supernodes for this network @@ -276,8 +276,10 @@ public: std::vector< SharedPtr<Peer> > &_v; }; -protected: - virtual void main() + /** + * Thread main method; do not call elsewhere + */ + void threadMain() throw(); private: @@ -297,6 +299,7 @@ private: }; const RuntimeEnvironment *const _r; + Thread<Topology> _thread; std::map< Address,SharedPtr<Peer> > _activePeers; Mutex _activePeers_m; diff --git a/node/UdpSocket.cpp b/node/UdpSocket.cpp index 6178d16e..db2c4b56 100644 --- a/node/UdpSocket.cpp +++ b/node/UdpSocket.cpp @@ -55,7 +55,6 @@ UdpSocket::UdpSocket( void (*packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int), void *arg) throw(std::runtime_error) : - Thread(), _packetHandler(packetHandler), _arg(arg), _localPort(localPort), @@ -121,7 +120,7 @@ UdpSocket::UdpSocket( } } - start(); + _thread = Thread<UdpSocket>::start(this); } UdpSocket::~UdpSocket() @@ -146,7 +145,7 @@ bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int } } -void UdpSocket::main() +void UdpSocket::threadMain() throw() { char buf[32768]; diff --git a/node/UdpSocket.hpp b/node/UdpSocket.hpp index a3223f1f..3f624387 100644 --- a/node/UdpSocket.hpp +++ b/node/UdpSocket.hpp @@ -40,7 +40,7 @@ namespace ZeroTier { * * The socket listens in a background thread and sends packets to Switch. */ -class UdpSocket : protected Thread +class UdpSocket { public: /** @@ -61,7 +61,7 @@ public: void *arg) throw(std::runtime_error); - virtual ~UdpSocket(); + ~UdpSocket(); /** * @return Locally bound port @@ -87,11 +87,14 @@ public: bool send(const InetAddress &to,const void *data,unsigned int len,int hopLimit) throw(); -protected: - virtual void main() + /** + * Thread main method; do not call elsewhere + */ + void threadMain() throw(); private: + Thread<UdpSocket> _thread; void (*_packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int); void *_arg; int _localPort; |