Restore synchronous method calls from LocalBackend to magicsock.Conn
for node views, filter, and delta mutations. The eventbus delivery
introduced in 8e6f63cf1 was invalid for these updates because
subsequent operations in the same call chain depend on magicsock
already having the current state. The Synchronize/settleEventBus
workaround was fragile and kept requiring more workarounds and
introducing new mystery bugs.
Since eventbus was added, we've since learned more about when to use
eventbus, and this wasn't one of the cases.
We can take another swing at using eventbus for netmap changes in a
future change.
Fixes#16369
Updates #18575 (likely fixes)
Change-Id: I79057cc9259993368bb1e350ff0e073adf6b9a8f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
derpMap*tailcfg.DERPMap// nil (or zero regions/nodes) means DERP is disabled
selftailcfg.NodeView// from last onNodeViewsUpdate
peersviews.Slice[tailcfg.NodeView]// from last onNodeViewsUpdate, sorted by Node.ID; Note: [netmap.NodeMutation]'s rx'd in onNodeMutationsUpdate are never applied
filt*filter.Filter// from last onFilterUpdate
selftailcfg.NodeView// from last SetNetworkMap
peersviews.Slice[tailcfg.NodeView]// from last SetNetworkMap, sorted by Node.ID; Note: [netmap.NodeMutation]'s rx'd in UpdateNetmapDelta are never applied
filt*filter.Filter// from last SetFilter
relayClientEnabledbool// whether we can allocate UDP relay endpoints on UDP relay servers or receive CallMeMaybeVia messages from peers
lastFlagsdebugFlags// at time of last onNodeViewsUpdate
lastFlagsdebugFlags// at time of last SetNetworkMap
privateKeykey.NodePrivate// WireGuard private key for this node
everHadKeybool// whether we ever had a non-zero private key
myDerpint// nearest DERP region ID; 0 means none/unknown
@ -521,47 +518,6 @@ func (o *Options) derpActiveFunc() func() {
returno.DERPActiveFunc
}
// NodeViewsUpdate represents an update event of [tailcfg.NodeView] for all
// nodes. This event is published over an [eventbus.Bus]. It may be published
// with an invalid SelfNode, and/or zero/nil Peers. [magicsock.Conn] is the sole
// subscriber as of 2025-06. If you are adding more subscribers consider moving
// this type out of magicsock.
typeNodeViewsUpdatestruct{
SelfNodetailcfg.NodeView
Peers[]tailcfg.NodeView// sorted by Node.ID
}
// NodeMutationsUpdate represents an update event of one or more
// [netmap.NodeMutation]. This event is published over an [eventbus.Bus].
// [magicsock.Conn] is the sole subscriber as of 2025-06. If you are adding more
// subscribers consider moving this type out of magicsock.
typeNodeMutationsUpdatestruct{
Mutations[]netmap.NodeMutation
}
// FilterUpdate represents an update event for a [*filter.Filter]. This event is
// signaled over an [eventbus.Bus]. [magicsock.Conn] is the sole subscriber as
// of 2025-06. If you are adding more subscribers consider moving this type out
// of magicsock.
typeFilterUpdatestruct{
*filter.Filter
}
// syncPoint is an event published over an [eventbus.Bus] by [Conn.Synchronize].
// It serves as a synchronization point, allowing to wait until magicsock
// has processed all pending events.
typesyncPointchanstruct{}
// Wait blocks until [syncPoint.Signal] is called.
func(ssyncPoint)Wait(){
<-s
}
// Signal signals the sync point, unblocking the [syncPoint.Wait] call.
func(ssyncPoint)Signal(){
close(s)
}
// UDPRelayAllocReq represents a [*disco.AllocateUDPRelayEndpointRequest]
// reception event. This is signaled over an [eventbus.Bus] from
// [magicsock.Conn] towards [relayserver.extension].