|
@@ -81,7 +81,7 @@ Network::~Network()
|
|
|
Utils::rm(std::string(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".mcerts"));
|
|
|
} else {
|
|
|
clean();
|
|
|
- _dumpMulticastCerts();
|
|
|
+ _dumpMembershipCerts();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -338,45 +338,58 @@ Network::Status Network::status() const
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
|
|
|
+void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
|
|
{
|
|
|
- if ((!((Network *)arg)->_enabled)||(((Network *)arg)->status() != NETWORK_OK))
|
|
|
- return;
|
|
|
-
|
|
|
- const RuntimeEnvironment *RR = ((Network *)arg)->RR;
|
|
|
- if (RR->shutdownInProgress)
|
|
|
- return;
|
|
|
+ Mutex::Lock _l(_lock);
|
|
|
+ _remoteBridgeRoutes[mac] = addr;
|
|
|
|
|
|
- try {
|
|
|
- RR->sw->onLocalEthernet(SharedPtr<Network>((Network *)arg),from,to,etherType,data);
|
|
|
- } catch (std::exception &exc) {
|
|
|
- TRACE("unexpected exception handling local packet: %s",exc.what());
|
|
|
- } catch ( ... ) {
|
|
|
- TRACE("unexpected exception handling local packet");
|
|
|
+ // If _remoteBridgeRoutes exceeds sanity limit, trim worst offenders until below -- denial of service circuit breaker
|
|
|
+ while (_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
|
|
|
+ std::map<Address,unsigned long> counts;
|
|
|
+ Address maxAddr;
|
|
|
+ unsigned long maxCount = 0;
|
|
|
+ for(std::map<MAC,Address>::iterator br(_remoteBridgeRoutes.begin());br!=_remoteBridgeRoutes.end();++br) {
|
|
|
+ unsigned long c = ++counts[br->second];
|
|
|
+ if (c > maxCount) {
|
|
|
+ maxCount = c;
|
|
|
+ maxAddr = br->second;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for(std::map<MAC,Address>::iterator br(_remoteBridgeRoutes.begin());br!=_remoteBridgeRoutes.end();) {
|
|
|
+ if (br->second == maxAddr)
|
|
|
+ _remoteBridgeRoutes.erase(br++);
|
|
|
+ else ++br;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t now)
|
|
|
+void Network::setEnabled(bool enabled)
|
|
|
{
|
|
|
- uint64_t pushTimeout = _config->com().timestampMaxDelta() / 2;
|
|
|
- if (!pushTimeout)
|
|
|
- return; // still waiting on my own cert
|
|
|
- if (pushTimeout > 1000)
|
|
|
- pushTimeout -= 1000;
|
|
|
+ Mutex::Lock _l(_lock);
|
|
|
+ _enabled = enabled;
|
|
|
+ if (_tap)
|
|
|
+ _tap->setEnabled(enabled);
|
|
|
+}
|
|
|
|
|
|
- uint64_t &lastPushed = _lastPushedMembershipCertificate[peer];
|
|
|
- if ((force)||((now - lastPushed) > pushTimeout)) {
|
|
|
- lastPushed = now;
|
|
|
- TRACE("pushing membership cert for %.16llx to %s",(unsigned long long)_id,peer.toString().c_str());
|
|
|
+void Network::destroy()
|
|
|
+{
|
|
|
+ Mutex::Lock _l(_lock);
|
|
|
|
|
|
- Packet outp(peer,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
|
|
|
- _config->com().serialize(outp);
|
|
|
- RR->sw->send(outp,true);
|
|
|
- }
|
|
|
+ _enabled = false;
|
|
|
+ _destroyed = true;
|
|
|
+
|
|
|
+ if (_setupThread)
|
|
|
+ Thread::join(_setupThread);
|
|
|
+ _setupThread = Thread();
|
|
|
+
|
|
|
+ if (_tap)
|
|
|
+ RR->tapFactory->close(_tap,true);
|
|
|
+ _tap = (EthernetTap *)0;
|
|
|
}
|
|
|
|
|
|
// Ethernet tap creation thread -- required on some platforms where tap
|
|
|
-// creation may be time consuming (e.g. Windows).
|
|
|
+// creation may be time consuming (e.g. Windows). Thread exits after tap
|
|
|
+// device setup.
|
|
|
void Network::threadMain()
|
|
|
throw()
|
|
|
{
|
|
@@ -420,53 +433,46 @@ void Network::threadMain()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
|
|
+void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data)
|
|
|
{
|
|
|
- Mutex::Lock _l(_lock);
|
|
|
- _remoteBridgeRoutes[mac] = addr;
|
|
|
+ if ((!((Network *)arg)->_enabled)||(((Network *)arg)->status() != NETWORK_OK))
|
|
|
+ return;
|
|
|
|
|
|
- // If _remoteBridgeRoutes exceeds sanity limit, trim worst offenders until below -- denial of service circuit breaker
|
|
|
- while (_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
|
|
|
- std::map<Address,unsigned long> counts;
|
|
|
- Address maxAddr;
|
|
|
- unsigned long maxCount = 0;
|
|
|
- for(std::map<MAC,Address>::iterator br(_remoteBridgeRoutes.begin());br!=_remoteBridgeRoutes.end();++br) {
|
|
|
- unsigned long c = ++counts[br->second];
|
|
|
- if (c > maxCount) {
|
|
|
- maxCount = c;
|
|
|
- maxAddr = br->second;
|
|
|
- }
|
|
|
- }
|
|
|
- for(std::map<MAC,Address>::iterator br(_remoteBridgeRoutes.begin());br!=_remoteBridgeRoutes.end();) {
|
|
|
- if (br->second == maxAddr)
|
|
|
- _remoteBridgeRoutes.erase(br++);
|
|
|
- else ++br;
|
|
|
- }
|
|
|
+ const RuntimeEnvironment *RR = ((Network *)arg)->RR;
|
|
|
+ if (RR->shutdownInProgress)
|
|
|
+ return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ RR->sw->onLocalEthernet(SharedPtr<Network>((Network *)arg),from,to,etherType,data);
|
|
|
+ } catch (std::exception &exc) {
|
|
|
+ TRACE("unexpected exception handling local packet: %s",exc.what());
|
|
|
+ } catch ( ... ) {
|
|
|
+ TRACE("unexpected exception handling local packet");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Network::setEnabled(bool enabled)
|
|
|
+void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t now)
|
|
|
{
|
|
|
- Mutex::Lock _l(_lock);
|
|
|
- _enabled = enabled;
|
|
|
- if (_tap)
|
|
|
- _tap->setEnabled(enabled);
|
|
|
-}
|
|
|
+ // assumes _lock is locked
|
|
|
+ uint64_t pushTimeout = _config->com().timestampMaxDelta() / 2;
|
|
|
|
|
|
-void Network::destroy()
|
|
|
-{
|
|
|
- Mutex::Lock _l(_lock);
|
|
|
+ // Zero means we're still waiting on our own cert
|
|
|
+ if (!pushTimeout)
|
|
|
+ return;
|
|
|
|
|
|
- _enabled = false;
|
|
|
- _destroyed = true;
|
|
|
+ // Give a 1s margin around +/- 1/2 max delta to account for latency
|
|
|
+ if (pushTimeout > 1000)
|
|
|
+ pushTimeout -= 1000;
|
|
|
|
|
|
- if (_setupThread)
|
|
|
- Thread::join(_setupThread);
|
|
|
- _setupThread = Thread();
|
|
|
+ uint64_t &lastPushed = _lastPushedMembershipCertificate[peer];
|
|
|
+ if ((force)||((now - lastPushed) > pushTimeout)) {
|
|
|
+ lastPushed = now;
|
|
|
+ TRACE("pushing membership cert for %.16llx to %s",(unsigned long long)_id,peer.toString().c_str());
|
|
|
|
|
|
- if (_tap)
|
|
|
- RR->tapFactory->close(_tap,true);
|
|
|
- _tap = (EthernetTap *)0;
|
|
|
+ Packet outp(peer,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
|
|
|
+ _config->com().serialize(outp);
|
|
|
+ RR->sw->send(outp,true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void Network::_restoreState()
|
|
@@ -537,7 +543,7 @@ void Network::_restoreState()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Network::_dumpMulticastCerts()
|
|
|
+void Network::_dumpMembershipCerts()
|
|
|
{
|
|
|
Buffer<ZT_NETWORK_CERT_WRITE_BUF_SIZE> buf;
|
|
|
std::string mcdbPath(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + idString() + ".mcerts");
|