From 150850b80012f852521c9935145cf966946334d5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 4 Jul 2013 16:56:19 -0400 Subject: New git repository for release - version 0.2.0 tagged --- node/NodeConfig.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 node/NodeConfig.cpp (limited to 'node/NodeConfig.cpp') diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp new file mode 100644 index 00000000..47310050 --- /dev/null +++ b/node/NodeConfig.cpp @@ -0,0 +1,206 @@ +/* + * 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 . + * + * -- + * + * 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 +#include +#include +#include + +#include + +#include "NodeConfig.hpp" +#include "RuntimeEnvironment.hpp" +#include "Defaults.hpp" +#include "Utils.hpp" +#include "Logger.hpp" + +namespace ZeroTier { + +NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const std::string &url) : + _r(renv), + _lastAutoconfigure(0), + _lastAutoconfigureLastModified(), + _url(url), + _autoconfigureLock(), + _networks(), + _networks_m() +{ +} + +NodeConfig::~NodeConfig() +{ + _autoconfigureLock.lock(); // wait for any autoconfs to finish + _autoconfigureLock.unlock(); +} + +void NodeConfig::refreshConfiguration() +{ + _autoconfigureLock.lock(); // unlocked when handler gets called + + TRACE("refreshing autoconfigure URL %s (if modified since: '%s')",_url.c_str(),_lastAutoconfigureLastModified.c_str()); + + std::map reqHeaders; + reqHeaders["X-ZT-ID"] = _r->identity.toString(false); + reqHeaders["X-ZT-OVSH"] = _r->ownershipVerificationSecretHash; + if (_lastAutoconfigureLastModified.length()) + reqHeaders["If-Modified-Since"] = _lastAutoconfigureLastModified; + + new Http::Request(Http::HTTP_METHOD_GET,_url,reqHeaders,std::string(),&NodeConfig::_CBautoconfHandler,this); +} + +void NodeConfig::__CBautoconfHandler(const std::string &lastModified,const std::string &body) +{ + try { + Json::Value root; + Json::Reader reader; + + std::string dec(_r->identity.decrypt(_r->configAuthority,body.data(),body.length())); + if (!dec.length()) { + LOG("autoconfigure from %s failed: data did not decrypt as from config authority %s",_url.c_str(),_r->configAuthority.address().toString().c_str()); + return; + } + TRACE("decrypted autoconf: %s",dec.c_str()); + + if (!reader.parse(dec,root,false)) { + LOG("autoconfigure from %s failed: JSON parse error: %s",_url.c_str(),reader.getFormattedErrorMessages().c_str()); + return; + } + + if (!root.isObject()) { + LOG("autoconfigure from %s failed: not a JSON object",_url.c_str()); + return; + } + + // Configure networks + const Json::Value &networks = root["_networks"]; + if (networks.isArray()) { + Mutex::Lock _l(_networks_m); + for(unsigned int ni=0;ni nw; + std::map< uint64_t,SharedPtr >::iterator nwent(_networks.find(nwid)); + if (nwent != _networks.end()) + nw = nwent->second; + else { + try { + nw = SharedPtr(new Network(_r,nwid)); + _networks[nwid] = nw; + } catch (std::exception &exc) { + LOG("unable to create network %llu: %s",nwid,exc.what()); + } catch ( ... ) { + LOG("unable to create network %llu: unknown exception",nwid); + } + } + + if (nw) { + Mutex::Lock _l2(nw->_lock); + nw->_open = networks[ni]["isOpen"].asBool(); + + // Ensure that TAP device has all the right IP addresses + // TODO: IPv6 might work a tad differently + std::set allIps; + const Json::Value &addresses = networks[ni]["_addresses"]; + if (addresses.isArray()) { + for(unsigned int ai=0;ai_tap.setIps(allIps); + + // NOTE: the _members field is optional for open networks, + // since members of open nets do not need to check membership + // of packet senders and mutlicasters. + const Json::Value &members = networks[ni]["_members"]; + nw->_members.clear(); + if (members.isArray()) { + for(unsigned int mi=0;mi_members.insert(addr); + } + } + } + } + } + } else { + TRACE("ignored networks[%u], 'id' field missing"); + } + } else { + TRACE("ignored networks[%u], not a JSON object",ni); + } + } + } + + _lastAutoconfigure = Utils::now(); + _lastAutoconfigureLastModified = lastModified; + } catch (std::exception &exc) { + TRACE("exception parsing autoconf URL response: %s",exc.what()); + } catch ( ... ) { + TRACE("unexpected exception parsing autoconf URL response"); + } +} + +bool NodeConfig::_CBautoconfHandler(Http::Request *req,void *arg,const std::string &url,int code,const std::map &headers,const std::string &body) +{ +#ifdef ZT_TRACE + const RuntimeEnvironment *_r = ((NodeConfig *)arg)->_r; +#endif + + if (code == 200) { + TRACE("200 got autoconfigure response from %s: %u bytes",url.c_str(),(unsigned int)body.length()); + + std::map::const_iterator lm(headers.find("Last-Modified")); + if (lm != headers.end()) + ((NodeConfig *)arg)->__CBautoconfHandler(lm->second,body); + else ((NodeConfig *)arg)->__CBautoconfHandler(std::string(),body); + } else if (code == 304) { + TRACE("304 autoconfigure deferred, remote URL %s not modified",url.c_str()); + ((NodeConfig *)arg)->_lastAutoconfigure = Utils::now(); // still considered a success + } else if (code == 409) { // conflict, ID address in use by another ID + TRACE("%d autoconfigure failed from %s",code,url.c_str()); + } else { + TRACE("%d autoconfigure failed from %s",code,url.c_str()); + } + + ((NodeConfig *)arg)->_autoconfigureLock.unlock(); + return false; // causes Request to delete itself +} + +} // namespace ZeroTier -- cgit v1.2.3