summaryrefslogtreecommitdiff
path: root/node/Network.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Network.cpp')
-rw-r--r--node/Network.cpp83
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