(ip netip.Addr, peer tailcfg.NodeView, res *ipnstate.PingResult, cb func(*ipnstate.PingResult))
| 1437 | } |
| 1438 | |
| 1439 | func (e *userspaceEngine) sendTSMPPing(ip netip.Addr, peer tailcfg.NodeView, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) { |
| 1440 | srcIP, err := e.mySelfIPMatchingFamily(ip) |
| 1441 | if err != nil { |
| 1442 | res.Err = err.Error() |
| 1443 | cb(res) |
| 1444 | return |
| 1445 | } |
| 1446 | var iph packet.Header |
| 1447 | if srcIP.Is4() { |
| 1448 | iph = packet.IP4Header{ |
| 1449 | IPProto: ipproto.TSMP, |
| 1450 | Src: srcIP, |
| 1451 | Dst: ip, |
| 1452 | } |
| 1453 | } else { |
| 1454 | iph = packet.IP6Header{ |
| 1455 | IPProto: ipproto.TSMP, |
| 1456 | Src: srcIP, |
| 1457 | Dst: ip, |
| 1458 | } |
| 1459 | } |
| 1460 | |
| 1461 | var data [8]byte |
| 1462 | crand.Read(data[:]) |
| 1463 | |
| 1464 | expireTimer := time.AfterFunc(10*time.Second, func() { |
| 1465 | e.setTSMPPongCallback(data, nil) |
| 1466 | }) |
| 1467 | t0 := time.Now() |
| 1468 | e.setTSMPPongCallback(data, func(pong packet.TSMPPongReply) { |
| 1469 | expireTimer.Stop() |
| 1470 | d := time.Since(t0) |
| 1471 | res.LatencySeconds = d.Seconds() |
| 1472 | res.NodeIP = ip.String() |
| 1473 | res.NodeName = peer.ComputedName() |
| 1474 | res.PeerAPIPort = pong.PeerAPIPort |
| 1475 | cb(res) |
| 1476 | }) |
| 1477 | |
| 1478 | var tsmpPayload [9]byte |
| 1479 | tsmpPayload[0] = byte(packet.TSMPTypePing) |
| 1480 | copy(tsmpPayload[1:], data[:]) |
| 1481 | |
| 1482 | tsmpPing := packet.Generate(iph, tsmpPayload[:]) |
| 1483 | e.tundev.InjectOutbound(tsmpPing) |
| 1484 | } |
| 1485 | |
| 1486 | func (e *userspaceEngine) sendTSMPDiscoAdvertisement(ip netip.Addr) { |
| 1487 | srcIP, err := e.mySelfIPMatchingFamily(ip) |
no test coverage detected