diff options
Diffstat (limited to 'node/Network.cpp')
-rw-r--r-- | node/Network.cpp | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/node/Network.cpp b/node/Network.cpp index d075bc7c..127de917 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -104,20 +104,10 @@ bool Network::Certificate::qualifyMembership(const Network::Certificate &mc) con return true; } -Network::Network(const RuntimeEnvironment *renv,uint64_t id) - throw(std::runtime_error) : - _r(renv), - _tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this), - _id(id), - _lastConfigUpdate(0), - _destroyOnDelete(false) -{ - if (controller() == _r->identity.address()) - throw std::runtime_error("cannot add a network for which I am the netconf master"); -} - Network::~Network() { + delete _tap; + if (_destroyOnDelete) { std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf"); std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts"); @@ -129,26 +119,25 @@ Network::~Network() } } -void Network::restoreState() +SharedPtr<Network> Network::newInstance(const RuntimeEnvironment *renv,uint64_t id) + throw(std::runtime_error) { - std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf"); - std::string confs; - if (Utils::readFile(confPath.c_str(),confs)) { - try { - if (confs.length()) { - Config conf(confs); - if (conf.containsAllFields()) - setConfiguration(conf); - } - } catch ( ... ) {} // ignore invalid config on disk, we will re-request - } else { - // If the conf file isn't present, "touch" it so we'll remember - // the existence of this network. - FILE *tmp = fopen(confPath.c_str(),"w"); - if (tmp) - fclose(tmp); - } - // TODO: restore membership certs + // We construct Network via a static method to ensure that it is immediately + // wrapped in a SharedPtr<>. Otherwise if there is traffic on the Ethernet + // tap device, a SharedPtr<> wrap can occur in the Ethernet frame handler + // that then causes the Network instance to be deleted before it is finished + // being constructed. C++ edge cases, how I love thee. + SharedPtr<Network> nw(new Network()); + nw->_r = renv; + nw->_tap = new EthernetTap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,nw.ptr()); + nw->_id = id; + nw->_lastConfigUpdate = 0; + nw->_destroyOnDelete = false; + if (nw->controller() == renv->identity.address()) // sanity check, this isn't supported for now + throw std::runtime_error("cannot add a network for which I am the netconf master"); + nw->_restoreState(); + nw->requestConfiguration(); + return nw; } void Network::setConfiguration(const Network::Config &conf) @@ -160,7 +149,7 @@ void Network::setConfiguration(const Network::Config &conf) _myCertificate = conf.certificateOfMembership(); _lastConfigUpdate = Utils::now(); - _tap.setIps(conf.staticAddresses()); + _tap->setIps(conf.staticAddresses()); std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf"); if (!Utils::writeFile(confPath.c_str(),conf.toString())) { @@ -210,11 +199,13 @@ bool Network::isAllowed(const Address &peer) const void Network::clean() { + std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts"); + Mutex::Lock _l(_lock); - if (_configuration.isOpen()) + if (_configuration.isOpen()) { _membershipCertificates.clear(); - else { - std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts"); + unlink(mcdbPath.c_str()); + } else { FILE *mcdb = fopen(mcdbPath.c_str(),"wb"); bool writeError = false; if (!mcdb) { @@ -263,4 +254,26 @@ void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned } } +void Network::_restoreState() +{ + std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf"); + std::string confs; + if (Utils::readFile(confPath.c_str(),confs)) { + try { + if (confs.length()) { + Config conf(confs); + if (conf.containsAllFields()) + setConfiguration(conf); + } + } catch ( ... ) {} // ignore invalid config on disk, we will re-request + } else { + // If the conf file isn't present, "touch" it so we'll remember + // the existence of this network. + FILE *tmp = fopen(confPath.c_str(),"w"); + if (tmp) + fclose(tmp); + } + // TODO: restore membership certs +} + } // namespace ZeroTier |