1 /*
2 * Copyright (c)2013-2020 ZeroTier, Inc.
3 *
4 * Use of this software is governed by the Business Source License included
5 * in the LICENSE.TXT file in the project's root directory.
6 *
7 * Change Date: 2025-01-01
8 *
9 * On the date above, in accordance with the Business Source License, use
10 * of this software will be governed by version 2.0 of the Apache License.
11 */
12 /****/
13
14 #include "../version.h"
15 #include "Constants.hpp"
16 #include "Peer.hpp"
17 #include "Switch.hpp"
18 #include "Network.hpp"
19 #include "SelfAwareness.hpp"
20 #include "Packet.hpp"
21 #include "Trace.hpp"
22 #include "InetAddress.hpp"
23 #include "RingBuffer.hpp"
24 #include "Utils.hpp"
25
26 namespace ZeroTier {
27
28 static unsigned char s_freeRandomByteCounter = 0;
29
Peer(const RuntimeEnvironment * renv,const Identity & myIdentity,const Identity & peerIdentity)30 Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
31 RR(renv),
32 _lastReceive(0),
33 _lastNontrivialReceive(0),
34 _lastTriedMemorizedPath(0),
35 _lastDirectPathPushSent(0),
36 _lastDirectPathPushReceive(0),
37 _lastEchoRequestReceived(0),
38 _lastCredentialRequestSent(0),
39 _lastWhoisRequestReceived(0),
40 _lastCredentialsReceived(0),
41 _lastTrustEstablishedPacketReceived(0),
42 _lastSentFullHello(0),
43 _lastEchoCheck(0),
44 _freeRandomByte((unsigned char)((uintptr_t)this >> 4) ^ ++s_freeRandomByteCounter),
45 _vProto(0),
46 _vMajor(0),
47 _vMinor(0),
48 _vRevision(0),
49 _id(peerIdentity),
50 _directPathPushCutoffCount(0),
51 _credentialsCutoffCount(0),
52 _echoRequestCutoffCount(0),
53 _localMultipathSupported(false),
54 _lastComputedAggregateMeanLatency(0)
55 {
56 if (!myIdentity.agree(peerIdentity,_key))
57 throw ZT_EXCEPTION_INVALID_ARGUMENT;
58
59 uint8_t ktmp[ZT_SYMMETRIC_KEY_SIZE];
60 KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K0,0,0,ktmp);
61 _aesKeys[0].init(ktmp);
62 KBKDFHMACSHA384(_key,ZT_KBKDF_LABEL_AES_GMAC_SIV_K1,0,0,ktmp);
63 _aesKeys[1].init(ktmp);
64 Utils::burn(ktmp,ZT_SYMMETRIC_KEY_SIZE);
65 }
66
received(void * tPtr,const SharedPtr<Path> & path,const unsigned int hops,const uint64_t packetId,const unsigned int payloadLength,const Packet::Verb verb,const uint64_t inRePacketId,const Packet::Verb inReVerb,const bool trustEstablished,const uint64_t networkId,const int32_t flowId)67 void Peer::received(
68 void *tPtr,
69 const SharedPtr<Path> &path,
70 const unsigned int hops,
71 const uint64_t packetId,
72 const unsigned int payloadLength,
73 const Packet::Verb verb,
74 const uint64_t inRePacketId,
75 const Packet::Verb inReVerb,
76 const bool trustEstablished,
77 const uint64_t networkId,
78 const int32_t flowId)
79 {
80 const int64_t now = RR->node->now();
81
82 _lastReceive = now;
83 switch (verb) {
84 case Packet::VERB_FRAME:
85 case Packet::VERB_EXT_FRAME:
86 case Packet::VERB_NETWORK_CONFIG_REQUEST:
87 case Packet::VERB_NETWORK_CONFIG:
88 case Packet::VERB_MULTICAST_FRAME:
89 _lastNontrivialReceive = now;
90 break;
91 default:
92 break;
93 }
94
95 recordIncomingPacket(path, packetId, payloadLength, verb, flowId, now);
96
97 if (trustEstablished) {
98 _lastTrustEstablishedPacketReceived = now;
99 path->trustedPacketReceived(now);
100 }
101
102 if (hops == 0) {
103 // If this is a direct packet (no hops), update existing paths or learn new ones
104 bool havePath = false;
105 {
106 Mutex::Lock _l(_paths_m);
107 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
108 if (_paths[i].p) {
109 if (_paths[i].p == path) {
110 _paths[i].lr = now;
111 havePath = true;
112 break;
113 }
114 } else {
115 break;
116 }
117 }
118 }
119
120 if ( (!havePath) && RR->node->shouldUsePathForZeroTierTraffic(tPtr,_id.address(),path->localSocket(),path->address()) ) {
121 if (verb == Packet::VERB_OK) {
122 Mutex::Lock _l(_paths_m);
123
124 unsigned int replacePath = ZT_MAX_PEER_NETWORK_PATHS;
125 long replacePathQuality = 0;
126 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
127 if (_paths[i].p) {
128 if ( (!_paths[i].p->alive(now)) || _paths[i].p->address().ipsEqual(path->address()) ) {
129 replacePath = i;
130 break;
131 } else {
132 const long q = _paths[i].p->quality(now) / _paths[i].priority;
133 if (q > replacePathQuality) {
134 replacePathQuality = q;
135 replacePath = i;
136 }
137 }
138 } else {
139 replacePath = i;
140 break;
141 }
142 }
143
144 if (replacePath != ZT_MAX_PEER_NETWORK_PATHS) {
145 RR->t->peerLearnedNewPath(tPtr, networkId, *this, path, packetId);
146 _paths[replacePath].lr = now;
147 _paths[replacePath].p = path;
148 _paths[replacePath].priority = 1;
149 Mutex::Lock _l(_bond_m);
150 if(_bond) {
151 _bond->nominatePathToBond(_paths[replacePath].p, now);
152 }
153 }
154 } else {
155 Mutex::Lock ltl(_lastTriedPath_m);
156
157 bool triedTooRecently = false;
158 for(std::list< std::pair< Path *, int64_t > >::iterator i(_lastTriedPath.begin());i!=_lastTriedPath.end();) {
159 if ((now - i->second) > 1000) {
160 _lastTriedPath.erase(i++);
161 } else if (i->first == path.ptr()) {
162 ++i;
163 triedTooRecently = true;
164 } else {
165 ++i;
166 }
167 }
168
169 if (!triedTooRecently) {
170 _lastTriedPath.push_back(std::pair< Path *, int64_t >(path.ptr(), now));
171 attemptToContactAt(tPtr,path->localSocket(),path->address(),now,true);
172 path->sent(now);
173 RR->t->peerConfirmingUnknownPath(tPtr,networkId,*this,path,packetId,verb);
174 }
175 }
176 }
177 }
178
179 // If we have a trust relationship periodically push a message enumerating
180 // all known external addresses for ourselves. If we already have a path this
181 // is done less frequently.
182 if (this->trustEstablished(now)) {
183 const int64_t sinceLastPush = now - _lastDirectPathPushSent;
184 if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH : ZT_DIRECT_PATH_PUSH_INTERVAL)) {
185 _lastDirectPathPushSent = now;
186 std::vector<InetAddress> pathsToPush(RR->node->directPaths());
187 if (!pathsToPush.empty()) {
188 std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
189 while (p != pathsToPush.end()) {
190 Packet *const outp = new Packet(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
191 outp->addSize(2); // leave room for count
192 unsigned int count = 0;
193 while ((p != pathsToPush.end())&&((outp->size() + 24) < 1200)) {
194 uint8_t addressType = 4;
195 switch(p->ss_family) {
196 case AF_INET:
197 break;
198 case AF_INET6:
199 addressType = 6;
200 break;
201 default: // we currently only push IP addresses
202 ++p;
203 continue;
204 }
205
206 outp->append((uint8_t)0); // no flags
207 outp->append((uint16_t)0); // no extensions
208 outp->append(addressType);
209 outp->append((uint8_t)((addressType == 4) ? 6 : 18));
210 outp->append(p->rawIpData(),((addressType == 4) ? 4 : 16));
211 outp->append((uint16_t)p->port());
212
213 ++count;
214 ++p;
215 }
216 if (count) {
217 outp->setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
218 outp->compress();
219 outp->armor(_key,true,aesKeysIfSupported());
220 path->send(RR,tPtr,outp->data(),outp->size(),now);
221 }
222 delete outp;
223 }
224 }
225 }
226 }
227 }
228
getAppropriatePath(int64_t now,bool includeExpired,int32_t flowId)229 SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired, int32_t flowId)
230 {
231 Mutex::Lock _l(_paths_m);
232 Mutex::Lock _lb(_bond_m);
233 if (!_bond) {
234 unsigned int bestPath = ZT_MAX_PEER_NETWORK_PATHS;
235 /**
236 * Send traffic across the highest quality path only. This algorithm will still
237 * use the old path quality metric from protocol version 9.
238 */
239 long bestPathQuality = 2147483647;
240 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
241 if (_paths[i].p) {
242 if ((includeExpired)||((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION)) {
243 const long q = _paths[i].p->quality(now) / _paths[i].priority;
244 if (q <= bestPathQuality) {
245 bestPathQuality = q;
246 bestPath = i;
247 }
248 }
249 } else break;
250 }
251 if (bestPath != ZT_MAX_PEER_NETWORK_PATHS) {
252 return _paths[bestPath].p;
253 }
254 return SharedPtr<Path>();
255 }
256 return _bond->getAppropriatePath(now, flowId);
257 }
258
introduce(void * const tPtr,const int64_t now,const SharedPtr<Peer> & other) const259 void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &other) const
260 {
261 unsigned int myBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
262 unsigned int myBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
263 long myBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
264 long myBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
265 unsigned int theirBestV4ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
266 unsigned int theirBestV6ByScope[ZT_INETADDRESS_MAX_SCOPE+1];
267 long theirBestV4QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
268 long theirBestV6QualityByScope[ZT_INETADDRESS_MAX_SCOPE+1];
269 for(int i=0;i<=ZT_INETADDRESS_MAX_SCOPE;++i) {
270 myBestV4ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
271 myBestV6ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
272 myBestV4QualityByScope[i] = 2147483647;
273 myBestV6QualityByScope[i] = 2147483647;
274 theirBestV4ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
275 theirBestV6ByScope[i] = ZT_MAX_PEER_NETWORK_PATHS;
276 theirBestV4QualityByScope[i] = 2147483647;
277 theirBestV6QualityByScope[i] = 2147483647;
278 }
279
280 Mutex::Lock _l1(_paths_m);
281
282 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
283 if (_paths[i].p) {
284 const long q = _paths[i].p->quality(now) / _paths[i].priority;
285 const unsigned int s = (unsigned int)_paths[i].p->ipScope();
286 switch(_paths[i].p->address().ss_family) {
287 case AF_INET:
288 if (q <= myBestV4QualityByScope[s]) {
289 myBestV4QualityByScope[s] = q;
290 myBestV4ByScope[s] = i;
291 }
292 break;
293 case AF_INET6:
294 if (q <= myBestV6QualityByScope[s]) {
295 myBestV6QualityByScope[s] = q;
296 myBestV6ByScope[s] = i;
297 }
298 break;
299 }
300 } else break;
301 }
302
303 Mutex::Lock _l2(other->_paths_m);
304
305 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
306 if (other->_paths[i].p) {
307 const long q = other->_paths[i].p->quality(now) / other->_paths[i].priority;
308 const unsigned int s = (unsigned int)other->_paths[i].p->ipScope();
309 switch(other->_paths[i].p->address().ss_family) {
310 case AF_INET:
311 if (q <= theirBestV4QualityByScope[s]) {
312 theirBestV4QualityByScope[s] = q;
313 theirBestV4ByScope[s] = i;
314 }
315 break;
316 case AF_INET6:
317 if (q <= theirBestV6QualityByScope[s]) {
318 theirBestV6QualityByScope[s] = q;
319 theirBestV6ByScope[s] = i;
320 }
321 break;
322 }
323 } else break;
324 }
325
326 unsigned int mine = ZT_MAX_PEER_NETWORK_PATHS;
327 unsigned int theirs = ZT_MAX_PEER_NETWORK_PATHS;
328
329 for(int s=ZT_INETADDRESS_MAX_SCOPE;s>=0;--s) {
330 if ((myBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)&&(theirBestV6ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
331 mine = myBestV6ByScope[s];
332 theirs = theirBestV6ByScope[s];
333 break;
334 }
335 if ((myBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)&&(theirBestV4ByScope[s] != ZT_MAX_PEER_NETWORK_PATHS)) {
336 mine = myBestV4ByScope[s];
337 theirs = theirBestV4ByScope[s];
338 break;
339 }
340 }
341
342 if (mine != ZT_MAX_PEER_NETWORK_PATHS) {
343 unsigned int alt = (unsigned int)RR->node->prng() & 1; // randomize which hint we send first for black magickal NAT-t reasons
344 const unsigned int completed = alt + 2;
345 while (alt != completed) {
346 if ((alt & 1) == 0) {
347 Packet outp(_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
348 outp.append((uint8_t)0);
349 other->_id.address().appendTo(outp);
350 outp.append((uint16_t)other->_paths[theirs].p->address().port());
351 if (other->_paths[theirs].p->address().ss_family == AF_INET6) {
352 outp.append((uint8_t)16);
353 outp.append(other->_paths[theirs].p->address().rawIpData(),16);
354 } else {
355 outp.append((uint8_t)4);
356 outp.append(other->_paths[theirs].p->address().rawIpData(),4);
357 }
358 outp.armor(_key,true,aesKeysIfSupported());
359 _paths[mine].p->send(RR,tPtr,outp.data(),outp.size(),now);
360 } else {
361 Packet outp(other->_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
362 outp.append((uint8_t)0);
363 _id.address().appendTo(outp);
364 outp.append((uint16_t)_paths[mine].p->address().port());
365 if (_paths[mine].p->address().ss_family == AF_INET6) {
366 outp.append((uint8_t)16);
367 outp.append(_paths[mine].p->address().rawIpData(),16);
368 } else {
369 outp.append((uint8_t)4);
370 outp.append(_paths[mine].p->address().rawIpData(),4);
371 }
372 outp.armor(other->_key,true,aesKeysIfSupported());
373 other->_paths[theirs].p->send(RR,tPtr,outp.data(),outp.size(),now);
374 }
375 ++alt;
376 }
377 }
378 }
379
sendHELLO(void * tPtr,const int64_t localSocket,const InetAddress & atAddress,int64_t now)380 void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now)
381 {
382 Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
383
384 outp.append((unsigned char)ZT_PROTO_VERSION);
385 outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
386 outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
387 outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
388 outp.append(now);
389 RR->identity.serialize(outp,false);
390 atAddress.serialize(outp);
391
392 outp.append((uint64_t)RR->topology->planetWorldId());
393 outp.append((uint64_t)RR->topology->planetWorldTimestamp());
394
395 const unsigned int startCryptedPortionAt = outp.size();
396
397 std::vector<World> moons(RR->topology->moons());
398 std::vector<uint64_t> moonsWanted(RR->topology->moonsWanted());
399 outp.append((uint16_t)(moons.size() + moonsWanted.size()));
400 for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
401 outp.append((uint8_t)m->type());
402 outp.append((uint64_t)m->id());
403 outp.append((uint64_t)m->timestamp());
404 }
405 for(std::vector<uint64_t>::const_iterator m(moonsWanted.begin());m!=moonsWanted.end();++m) {
406 outp.append((uint8_t)World::TYPE_MOON);
407 outp.append(*m);
408 outp.append((uint64_t)0);
409 }
410
411 outp.cryptField(_key,startCryptedPortionAt,outp.size() - startCryptedPortionAt);
412
413 if (atAddress) {
414 outp.armor(_key,false,nullptr); // false == don't encrypt full payload, but add MAC
415 RR->node->expectReplyTo(outp.packetId());
416 RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size());
417 } else {
418 RR->node->expectReplyTo(outp.packetId());
419 RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
420 }
421 }
422
attemptToContactAt(void * tPtr,const int64_t localSocket,const InetAddress & atAddress,int64_t now,bool sendFullHello)423 void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello)
424 {
425 if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
426 Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
427 outp.armor(_key,true,aesKeysIfSupported());
428 RR->node->expectReplyTo(outp.packetId());
429 RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size());
430 } else {
431 sendHELLO(tPtr,localSocket,atAddress,now);
432 }
433 }
434
tryMemorizedPath(void * tPtr,int64_t now)435 void Peer::tryMemorizedPath(void *tPtr,int64_t now)
436 {
437 if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
438 _lastTriedMemorizedPath = now;
439 InetAddress mp;
440 if (RR->node->externalPathLookup(tPtr,_id.address(),-1,mp))
441 attemptToContactAt(tPtr,-1,mp,now,true);
442 }
443 }
444
performMultipathStateCheck(void * tPtr,int64_t now)445 void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
446 {
447 Mutex::Lock _l(_bond_m);
448 if (_bond) {
449 // Once enabled the Bond object persists, no need to update state
450 return;
451 }
452 /**
453 * Check for conditions required for multipath bonding and create a bond
454 * if allowed.
455 */
456 int numAlivePaths = 0;
457 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
458 if (_paths[i].p && _paths[i].p->alive(now)) {
459 numAlivePaths++;
460 }
461 }
462 _localMultipathSupported = ((numAlivePaths >= 1) && (RR->bc->inUse()) && (ZT_PROTO_VERSION > 9));
463 if (_localMultipathSupported && !_bond) {
464 if (RR->bc) {
465 _bond = RR->bc->createTransportTriggeredBond(RR, this);
466 /**
467 * Allow new bond to retroactively learn all paths known to this peer
468 */
469 if (_bond) {
470 for (unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
471 if (_paths[i].p) {
472 _bond->nominatePathToBond(_paths[i].p, now);
473 }
474 }
475 }
476 }
477 }
478 }
479
doPingAndKeepalive(void * tPtr,int64_t now)480 unsigned int Peer::doPingAndKeepalive(void *tPtr,int64_t now)
481 {
482 unsigned int sent = 0;
483 Mutex::Lock _l(_paths_m);
484
485 performMultipathStateCheck(tPtr, now);
486
487 const bool sendFullHello = ((now - _lastSentFullHello) >= ZT_PEER_PING_PERIOD);
488 _lastSentFullHello = now;
489
490 // Right now we only keep pinging links that have the maximum priority. The
491 // priority is used to track cluster redirections, meaning that when a cluster
492 // redirects us its redirect target links override all other links and we
493 // let those old links expire.
494 long maxPriority = 0;
495 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
496 if (_paths[i].p)
497 maxPriority = std::max(_paths[i].priority,maxPriority);
498 else break;
499 }
500
501 unsigned int j = 0;
502 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
503 if (_paths[i].p) {
504 // Clean expired and reduced priority paths
505 if ( ((now - _paths[i].lr) < ZT_PEER_PATH_EXPIRATION) && (_paths[i].priority == maxPriority) ) {
506 if ((sendFullHello)||(_paths[i].p->needsHeartbeat(now))) {
507 attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,sendFullHello);
508 _paths[i].p->sent(now);
509 sent |= (_paths[i].p->address().ss_family == AF_INET) ? 0x1 : 0x2;
510 }
511 if (i != j)
512 _paths[j] = _paths[i];
513 ++j;
514 }
515 } else break;
516 }
517 return sent;
518 }
519
clusterRedirect(void * tPtr,const SharedPtr<Path> & originatingPath,const InetAddress & remoteAddress,const int64_t now)520 void Peer::clusterRedirect(void *tPtr,const SharedPtr<Path> &originatingPath,const InetAddress &remoteAddress,const int64_t now)
521 {
522 SharedPtr<Path> np(RR->topology->getPath(originatingPath->localSocket(),remoteAddress));
523 RR->t->peerRedirected(tPtr,0,*this,np);
524
525 attemptToContactAt(tPtr,originatingPath->localSocket(),remoteAddress,now,true);
526
527 {
528 Mutex::Lock _l(_paths_m);
529
530 // New priority is higher than the priority of the originating path (if known)
531 long newPriority = 1;
532 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
533 if (_paths[i].p) {
534 if (_paths[i].p == originatingPath) {
535 newPriority = _paths[i].priority;
536 break;
537 }
538 } else break;
539 }
540 newPriority += 2;
541
542 // Erase any paths with lower priority than this one or that are duplicate
543 // IPs and add this path.
544 unsigned int j = 0;
545 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
546 if (_paths[i].p) {
547 if ((_paths[i].priority >= newPriority)&&(!_paths[i].p->address().ipsEqual2(remoteAddress))) {
548 if (i != j)
549 _paths[j] = _paths[i];
550 ++j;
551 }
552 }
553 }
554 if (j < ZT_MAX_PEER_NETWORK_PATHS) {
555 _paths[j].lr = now;
556 _paths[j].p = np;
557 _paths[j].priority = newPriority;
558 ++j;
559 while (j < ZT_MAX_PEER_NETWORK_PATHS) {
560 _paths[j].lr = 0;
561 _paths[j].p.zero();
562 _paths[j].priority = 1;
563 ++j;
564 }
565 }
566 }
567 }
568
resetWithinScope(void * tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now)569 void Peer::resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now)
570 {
571 Mutex::Lock _l(_paths_m);
572 for(unsigned int i=0;i<ZT_MAX_PEER_NETWORK_PATHS;++i) {
573 if (_paths[i].p) {
574 if ((_paths[i].p->address().ss_family == inetAddressFamily)&&(_paths[i].p->ipScope() == scope)) {
575 attemptToContactAt(tPtr,_paths[i].p->localSocket(),_paths[i].p->address(),now,false);
576 _paths[i].p->sent(now);
577 _paths[i].lr = 0; // path will not be used unless it speaks again
578 }
579 } else break;
580 }
581 }
582
recordOutgoingPacket(const SharedPtr<Path> & path,const uint64_t packetId,uint16_t payloadLength,const Packet::Verb verb,const int32_t flowId,int64_t now)583 void Peer::recordOutgoingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
584 uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
585 {
586 if (_localMultipathSupported && _bond) {
587 _bond->recordOutgoingPacket(path, packetId, payloadLength, verb, flowId, now);
588 }
589 }
590
recordIncomingInvalidPacket(const SharedPtr<Path> & path)591 void Peer::recordIncomingInvalidPacket(const SharedPtr<Path>& path)
592 {
593 if (_localMultipathSupported && _bond) {
594 _bond->recordIncomingInvalidPacket(path);
595 }
596 }
597
recordIncomingPacket(const SharedPtr<Path> & path,const uint64_t packetId,uint16_t payloadLength,const Packet::Verb verb,const int32_t flowId,int64_t now)598 void Peer::recordIncomingPacket(const SharedPtr<Path> &path, const uint64_t packetId,
599 uint16_t payloadLength, const Packet::Verb verb, const int32_t flowId, int64_t now)
600 {
601 if (_localMultipathSupported && _bond) {
602 _bond->recordIncomingPacket(path, packetId, payloadLength, verb, flowId, now);
603 }
604 }
605
606 } // namespace ZeroTier
607