diff --git a/node/Bond.cpp b/node/Bond.cpp
index 7066b1633..b73cdfdbe 100644
--- a/node/Bond.cpp
+++ b/node/Bond.cpp
@@ -1291,11 +1291,13 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
if (_paths[i].preferred()) {
_abPathIdx = i;
bFoundPrimaryLink = true;
- SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
- if (link) {
- log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
+ if (_paths[_abPathIdx].p) {
+ SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
+ if (link) {
+ log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
+ }
+ break; // Found preferred path on primary link
}
- break; // Found preferred path on primary link
}
}
}
@@ -1317,17 +1319,19 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
}
}
if (_abPathIdx != ZT_MAX_PEER_NETWORK_PATHS) {
- SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
- if (link) {
- log("select non-primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
+ if (_paths[_abPathIdx].p) {
+ SharedPtr link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
+ if (link) {
+ log("select non-primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
+ }
}
}
}
}
}
- // Short-circuit if we don't have an active link yet
- if (_abPathIdx == ZT_MAX_PEER_NETWORK_PATHS) {
+ // Short-circuit if we don't have an active link yet. Everything below is optimization from the base case
+ if (_abPathIdx < 0 || _abPathIdx == ZT_MAX_PEER_NETWORK_PATHS || (!_paths[_abPathIdx].p)) {
return;
}
@@ -1393,17 +1397,19 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
}
}
}
- if (_paths[i].p.ptr() != _paths[_abPathIdx].p.ptr()) {
- bool bFoundPathInQueue = false;
- for (std::deque::iterator it(_abFailoverQueue.begin()); it != _abFailoverQueue.end(); ++it) {
- if (_paths[i].p.ptr() == _paths[(*it)].p.ptr()) {
- bFoundPathInQueue = true;
+ if (_paths[i].p) {
+ if (_paths[i].p.ptr() != _paths[_abPathIdx].p.ptr()) {
+ bool bFoundPathInQueue = false;
+ for (std::deque::iterator it(_abFailoverQueue.begin()); it != _abFailoverQueue.end(); ++it) {
+ if (_paths[(*it)].p && (_paths[i].p.ptr() == _paths[(*it)].p.ptr())) {
+ bFoundPathInQueue = true;
+ }
+ }
+ if (! bFoundPathInQueue) {
+ _abFailoverQueue.push_front(i);
+ log("add link %s to failover queue (%zu links in queue)", pathToStr(_paths[i].p).c_str(), _abFailoverQueue.size());
+ addPathToBond(0, i);
}
- }
- if (! bFoundPathInQueue) {
- _abFailoverQueue.push_front(i);
- log("add link %s to failover queue (%zu links in queue)", pathToStr(_paths[i].p).c_str(), _abFailoverQueue.size());
- addPathToBond(0, i);
}
}
}
@@ -1476,7 +1482,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
/**
* Fulfill primary re-select obligations
*/
- if (_paths[_abPathIdx].p && ! _paths[_abPathIdx].eligible) { // Implicit ZT_BOND_RESELECTION_POLICY_FAILURE
+ if (! _paths[_abPathIdx].eligible) { // Implicit ZT_BOND_RESELECTION_POLICY_FAILURE
log("link %s has failed, select link from failover queue (%zu links in queue)", pathToStr(_paths[_abPathIdx].p).c_str(), _abFailoverQueue.size());
if (! _abFailoverQueue.empty()) {
dequeueNextActiveBackupPath(now);
@@ -1493,15 +1499,15 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
_lastActiveBackupPathChange = now;
}
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_ALWAYS) {
- if (_paths[_abPathIdx].p && ! getLink(_paths[_abPathIdx].p)->primary() && getLink(_paths[_abFailoverQueue.front()].p)->primary()) {
+ if (! getLink(_paths[_abPathIdx].p)->primary() && _paths[_abFailoverQueue.front()].p && getLink(_paths[_abFailoverQueue.front()].p)->primary()) {
dequeueNextActiveBackupPath(now);
log("switch back to available primary link %s (select mode: always)", pathToStr(_paths[_abPathIdx].p).c_str());
}
}
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_BETTER) {
- if (_paths[_abPathIdx].p && ! getLink(_paths[_abPathIdx].p)->primary()) {
+ if (! getLink(_paths[_abPathIdx].p)->primary()) {
// Active backup has switched to "better" primary link according to re-select policy.
- if (getLink(_paths[_abFailoverQueue.front()].p)->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
+ if (_paths[_abFailoverQueue.front()].p && getLink(_paths[_abFailoverQueue.front()].p)->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
dequeueNextActiveBackupPath(now);
log("switch back to user-defined primary link %s (select mode: better)", pathToStr(_paths[_abPathIdx].p).c_str());
}