|
@@ -115,45 +115,50 @@ void Peer::received(
|
|
|
}
|
|
|
|
|
|
bool attemptToContact = false;
|
|
|
-
|
|
|
- int replaceIdx = ZT_MAX_PEER_NETWORK_PATHS;
|
|
|
if ((!havePath)&&(RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localSocket(),path->address()))) {
|
|
|
Mutex::Lock _l(_paths_m);
|
|
|
+
|
|
|
+ // Paths are redunant if they duplicate an alive path to the same IP or
|
|
|
+ // with the same local socket and address family.
|
|
|
+ bool redundant = false;
|
|
|
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
|
|
|
if (_paths[i].p) {
|
|
|
- // match addr
|
|
|
- if ( (_paths[i].p->alive(now)) && ( ((_paths[i].p->localSocket() == path->localSocket())&&(_paths[i].p->address().ss_family == path->address().ss_family)) && (_paths[i].p->address().ipsEqual2(path->address())) ) ) {
|
|
|
- // port
|
|
|
- if (_paths[i].p->address().port() == path->address().port()) {
|
|
|
- replaceIdx = i;
|
|
|
- break;
|
|
|
- }
|
|
|
+ if ( (_paths[i].p->alive(now)) && ( ((_paths[i].p->localSocket() == path->localSocket())&&(_paths[i].p->address().ss_family == path->address().ss_family)) || (_paths[i].p->address().ipsEqual2(path->address())) ) ) {
|
|
|
+ redundant = true;
|
|
|
+ break;
|
|
|
}
|
|
|
- }
|
|
|
+ } else break;
|
|
|
}
|
|
|
- if (replaceIdx == ZT_MAX_PEER_NETWORK_PATHS) {
|
|
|
+
|
|
|
+ if (!redundant) {
|
|
|
+ unsigned int replacePath = ZT_MAX_PEER_NETWORK_PATHS;
|
|
|
+ int replacePathQuality = 0;
|
|
|
for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
|
|
|
- if (!_paths[i].p) {
|
|
|
- replaceIdx = i;
|
|
|
+ if (_paths[i].p) {
|
|
|
+ const int q = _paths[i].p->quality(now);
|
|
|
+ if (q > replacePathQuality) {
|
|
|
+ replacePathQuality = q;
|
|
|
+ replacePath = i;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ replacePath = i;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- if (replaceIdx != ZT_MAX_PEER_NETWORK_PATHS) {
|
|
|
- if (verb == Packet::VERB_OK) {
|
|
|
- RR->t->peerLearnedNewPath(tPtr,networkId,*this,path,packetId);
|
|
|
- performMultipathStateCheck(now);
|
|
|
- if (_bondToPeer) {
|
|
|
- _bondToPeer->nominatePath(path, now);
|
|
|
+
|
|
|
+ if (replacePath != ZT_MAX_PEER_NETWORK_PATHS) {
|
|
|
+ if (verb == Packet::VERB_OK) {
|
|
|
+ RR->t->peerLearnedNewPath(tPtr,networkId,*this,path,packetId);
|
|
|
+ _paths[replacePath].lr = now;
|
|
|
+ _paths[replacePath].p = path;
|
|
|
+ _paths[replacePath].priority = 1;
|
|
|
+ } else {
|
|
|
+ attemptToContact = true;
|
|
|
}
|
|
|
- _paths[replaceIdx].lr = now;
|
|
|
- _paths[replaceIdx].p = path;
|
|
|
- _paths[replaceIdx].priority = 1;
|
|
|
- } else {
|
|
|
- attemptToContact = true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if (attemptToContact) {
|
|
|
attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true);
|
|
|
path->sent(now);
|