@ -94,6 +94,9 @@ type userspaceEngine struct {
// eventBus will eventually become required, but for now may be nil.
// eventBus will eventually become required, but for now may be nil.
// TODO(creachadair): Enforce that this is non-nil at construction.
// TODO(creachadair): Enforce that this is non-nil at construction.
eventBus * eventbus . Bus
eventBus * eventbus . Bus
eventClient * eventbus . Client
changeDeltaSub * eventbus . Subscriber [ netmon . ChangeDelta ]
subsDoneCh chan struct { } // closed when consumeEventbusTopics returns
logf logger . Logf
logf logger . Logf
wgLogger * wglog . Logger // a wireguard-go logging wrapper
wgLogger * wglog . Logger // a wireguard-go logging wrapper
@ -110,7 +113,6 @@ type userspaceEngine struct {
netMon * netmon . Monitor
netMon * netmon . Monitor
health * health . Tracker
health * health . Tracker
netMonOwned bool // whether we created netMon (and thus need to close it)
netMonOwned bool // whether we created netMon (and thus need to close it)
netMonUnregister func ( ) // unsubscribes from changes; used regardless of netMonOwned
birdClient BIRDClient // or nil
birdClient BIRDClient // or nil
controlKnobs * controlknobs . Knobs // or nil
controlKnobs * controlknobs . Knobs // or nil
@ -352,7 +354,11 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
controlKnobs : conf . ControlKnobs ,
controlKnobs : conf . ControlKnobs ,
reconfigureVPN : conf . ReconfigureVPN ,
reconfigureVPN : conf . ReconfigureVPN ,
health : conf . HealthTracker ,
health : conf . HealthTracker ,
subsDoneCh : make ( chan struct { } ) ,
}
}
e . eventClient = e . eventBus . Client ( "userspaceEngine" )
e . changeDeltaSub = eventbus . Subscribe [ netmon . ChangeDelta ] ( e . eventClient )
closePool . addFunc ( e . eventClient . Close )
if e . birdClient != nil {
if e . birdClient != nil {
// Disable the protocol at start time.
// Disable the protocol at start time.
@ -385,13 +391,6 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
logf ( "link state: %+v" , e . netMon . InterfaceState ( ) )
logf ( "link state: %+v" , e . netMon . InterfaceState ( ) )
unregisterMonWatch := e . netMon . RegisterChangeCallback ( func ( delta * netmon . ChangeDelta ) {
tshttpproxy . InvalidateCache ( )
e . linkChange ( delta )
} )
closePool . addFunc ( unregisterMonWatch )
e . netMonUnregister = unregisterMonWatch
endpointsFn := func ( endpoints [ ] tailcfg . Endpoint ) {
endpointsFn := func ( endpoints [ ] tailcfg . Endpoint ) {
e . mu . Lock ( )
e . mu . Lock ( )
e . endpoints = append ( e . endpoints [ : 0 ] , endpoints ... )
e . endpoints = append ( e . endpoints [ : 0 ] , endpoints ... )
@ -546,10 +545,31 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
}
}
}
}
go e . consumeEventbusTopics ( )
e . logf ( "Engine created." )
e . logf ( "Engine created." )
return e , nil
return e , nil
}
}
// consumeEventbusTopics consumes events from all relevant
// [eventbus.Subscriber]'s and passes them to their related handler. Events are
// always handled in the order they are received, i.e. the next event is not
// read until the previous event's handler has returned. It returns when the
// [eventbus.Client] is closed.
func ( e * userspaceEngine ) consumeEventbusTopics ( ) {
defer close ( e . subsDoneCh )
for {
select {
case <- e . eventClient . Done ( ) :
return
case changeDelta := <- e . changeDeltaSub . Events ( ) :
tshttpproxy . InvalidateCache ( )
e . linkChange ( & changeDelta )
}
}
}
// echoRespondToAll is an inbound post-filter responding to all echo requests.
// echoRespondToAll is an inbound post-filter responding to all echo requests.
func echoRespondToAll ( p * packet . Parsed , t * tstun . Wrapper , gro * gro . GRO ) ( filter . Response , * gro . GRO ) {
func echoRespondToAll ( p * packet . Parsed , t * tstun . Wrapper , gro * gro . GRO ) ( filter . Response , * gro . GRO ) {
if p . IsEchoRequest ( ) {
if p . IsEchoRequest ( ) {
@ -1208,6 +1228,9 @@ func (e *userspaceEngine) RequestStatus() {
}
}
func ( e * userspaceEngine ) Close ( ) {
func ( e * userspaceEngine ) Close ( ) {
e . eventClient . Close ( )
<- e . subsDoneCh
e . mu . Lock ( )
e . mu . Lock ( )
if e . closing {
if e . closing {
e . mu . Unlock ( )
e . mu . Unlock ( )
@ -1219,7 +1242,6 @@ func (e *userspaceEngine) Close() {
r := bufio . NewReader ( strings . NewReader ( "" ) )
r := bufio . NewReader ( strings . NewReader ( "" ) )
e . wgdev . IpcSetOperation ( r )
e . wgdev . IpcSetOperation ( r )
e . magicConn . Close ( )
e . magicConn . Close ( )
e . netMonUnregister ( )
if e . netMonOwned {
if e . netMonOwned {
e . netMon . Close ( )
e . netMon . Close ( )
}
}