@@ -264,6 +264,7 @@ func NewConn(options *Options) (conn *Conn, err error) {
264
264
nodeUp .setAddresses (options .Addresses )
265
265
nodeUp .setBlockEndpoints (options .BlockEndpoints )
266
266
267
+ ctx , ctxCancel := context .WithCancel (context .Background ())
267
268
server := & Conn {
268
269
id : uuid .New (),
269
270
closed : make (chan struct {}),
@@ -283,6 +284,8 @@ func NewConn(options *Options) (conn *Conn, err error) {
283
284
telemetrySink : options .TelemetrySink ,
284
285
telemetryStore : telemetryStore ,
285
286
createdAt : time .Now (),
287
+ watchCtx : ctx ,
288
+ watchCancel : ctxCancel ,
286
289
}
287
290
defer func () {
288
291
if err != nil {
@@ -293,8 +296,17 @@ func NewConn(options *Options) (conn *Conn, err error) {
293
296
server .wireguardEngine .SetNetInfoCallback (func (ni * tailcfg.NetInfo ) {
294
297
server .telemetryStore .setNetInfo (ni )
295
298
nodeUp .setNetInfo (ni )
299
+ if server .telemetryStore .connectedIP != nil {
300
+ _ , _ , _ , _ = server .Ping (ctx , * server .telemetryStore .connectedIP )
301
+ }
296
302
})
297
- server .wireguardEngine .AddNetworkMapCallback (server .networkMapCallback )
303
+ server .wireguardEngine .AddNetworkMapCallback (func (nm * netmap.NetworkMap ) {
304
+ server .telemetryStore .updateNetworkMap (nm )
305
+ if server .telemetryStore .connectedIP != nil {
306
+ _ , _ , _ , _ = server .Ping (ctx , * server .telemetryStore .connectedIP )
307
+ }
308
+ })
309
+ go server .watchConnChange ()
298
310
} else {
299
311
server .wireguardEngine .SetNetInfoCallback (nodeUp .setNetInfo )
300
312
}
@@ -361,6 +373,9 @@ type Conn struct {
361
373
telemetryStore * TelemetryStore
362
374
telemetryWg sync.WaitGroup
363
375
376
+ watchCtx context.Context
377
+ watchCancel func ()
378
+
364
379
trafficStats * connstats.Statistics
365
380
}
366
381
@@ -542,6 +557,7 @@ func (c *Conn) Closed() <-chan struct{} {
542
557
// Close shuts down the Wireguard connection.
543
558
func (c * Conn ) Close () error {
544
559
c .logger .Info (context .Background (), "closing tailnet Conn" )
560
+ c .watchCancel ()
545
561
c .telemetryWg .Wait ()
546
562
c .configMaps .close ()
547
563
c .nodeUpdater .close ()
@@ -771,13 +787,6 @@ func (c *Conn) newTelemetryEvent() *proto.TelemetryEvent {
771
787
return event
772
788
}
773
789
774
- func (c * Conn ) networkMapCallback (nm * netmap.NetworkMap ) {
775
- c .telemetryStore .updateNetworkMap (nm )
776
- if c .telemetryStore .connectedIP != nil {
777
- _ , _ , _ , _ = c .Ping (context .Background (), * c .telemetryStore .connectedIP )
778
- }
779
- }
780
-
781
790
func (c * Conn ) sendTelemetryBackground (e * proto.TelemetryEvent ) {
782
791
c .telemetryWg .Add (1 )
783
792
go func () {
@@ -786,6 +795,32 @@ func (c *Conn) sendTelemetryBackground(e *proto.TelemetryEvent) {
786
795
}()
787
796
}
788
797
798
+ // Watch for changes in the connection type (P2P<->DERP) and send telemetry events.
799
+ func (c * Conn ) watchConnChange () {
800
+ ticker := time .NewTicker (time .Millisecond * 50 )
801
+ defer ticker .Stop ()
802
+ for {
803
+ select {
804
+ case <- c .watchCtx .Done ():
805
+ return
806
+ case <- ticker .C :
807
+ }
808
+ status := c .Status ()
809
+ peers := status .Peers ()
810
+ if len (peers ) > 1 {
811
+ // Not a CLI<->agent connection, stop watching
812
+ return
813
+ } else if len (peers ) == 0 {
814
+ continue
815
+ }
816
+ peer := status .Peer [peers [0 ]]
817
+ // If the connection type has changed, send a telemetry event with the latest ping stats
818
+ if c .telemetryStore .checkConnType (peer .Relay ) && c .telemetryStore .connectedIP != nil {
819
+ _ , _ , _ , _ = c .Ping (c .watchCtx , * c .telemetryStore .connectedIP )
820
+ }
821
+ }
822
+ }
823
+
789
824
// PeerDiagnostics is a checklist of human-readable conditions necessary to establish an encrypted
790
825
// tunnel to a peer via a Conn
791
826
type PeerDiagnostics struct {
0 commit comments