Skip to content

Commit

Permalink
rearrange poll, lock, notify
Browse files Browse the repository at this point in the history
Signed-off-by: Kristoffer Dalby <[email protected]>
  • Loading branch information
kradalby committed Sep 19, 2023
1 parent 593b3ad commit a8079a2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 50 deletions.
6 changes: 3 additions & 3 deletions hscontrol/notifier/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

type Notifier struct {
l sync.RWMutex
l sync.Mutex
nodes map[string]chan<- types.StateUpdate
}

Expand Down Expand Up @@ -54,8 +54,8 @@ func (n *Notifier) NotifyAll(update types.StateUpdate) {
}

func (n *Notifier) NotifyWithIgnore(update types.StateUpdate, ignore ...string) {
n.l.RLock()
defer n.l.RUnlock()
n.l.Lock()
defer n.l.Unlock()

for key, c := range n.nodes {
if util.IsStringInSlice(ignore, key) {
Expand Down
79 changes: 32 additions & 47 deletions hscontrol/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ func (h *Headscale) handlePoll(
mapRequest tailcfg.MapRequest,
isNoise bool,
) {
// Immediate open the channel and register it if the client wants
// a stream of MapResponses to prevent initial map response and
// following updates missing
var updateChan chan types.StateUpdate
if mapRequest.Stream {
h.pollNetMapStreamWG.Add(1)
defer h.pollNetMapStreamWG.Done()

updateChan = make(chan types.StateUpdate)
defer closeChanWithLog(updateChan, machine.Hostname, "updateChan")

// Register the node's update channel
h.nodeNotifier.AddNode(machine.MachineKey, updateChan)
defer h.nodeNotifier.RemoveNode(machine.MachineKey)
}

logInfo, logErr := logPollFunc(mapRequest, machine, isNoise)

mapp := mapper.NewMapper(
Expand Down Expand Up @@ -116,6 +132,21 @@ func (h *Headscale) handlePoll(
return
}

if !mapRequest.ReadOnly {
// It sounds like we should update the nodes when we have received a endpoint update
// even tho the comments in the tailscale code dont explicitly say so.
updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "endpoint-update").
Inc()

// Tell all the other nodes about the new endpoint, but dont update ourselves.
h.nodeNotifier.NotifyWithIgnore(
types.StateUpdate{
Type: types.StatePeerChanged,
Changed: []uint64{machine.ID},
},
machine.MachineKey)
}

// We update our peers if the client is not sending ReadOnly in the MapRequest
// so we don't distribute its initial request (it comes with
// empty endpoints to peers)
Expand Down Expand Up @@ -165,18 +196,6 @@ func (h *Headscale) handlePoll(
if err != nil {
logErr(err, "Failed to write response")
}
// It sounds like we should update the nodes when we have received a endpoint update
// even tho the comments in the tailscale code dont explicitly say so.
updateRequestsFromNode.WithLabelValues(machine.User.Name, machine.Hostname, "endpoint-update").
Inc()

// Tell all the other nodes about the new endpoint, but dont update ourselves.
h.nodeNotifier.NotifyWithIgnore(
types.StateUpdate{
Type: types.StatePeerChanged,
Changed: []uint64{machine.ID},
},
machine.MachineKey)

return
} else if mapRequest.OmitPeers && mapRequest.Stream {
Expand Down Expand Up @@ -213,43 +232,9 @@ func (h *Headscale) handlePoll(
return
}

h.pollNetMapStream(
writer,
ctx,
machine,
mapp,
mapRequest,
isNoise,
)

logInfo("Finished stream, closing PollNetMap session")
}

// pollNetMapStream stream logic for /machine/map,
// ensuring we communicate updates and data to the connected clients.
func (h *Headscale) pollNetMapStream(
writer http.ResponseWriter,
ctxReq context.Context,
machine *types.Machine,
mapp *mapper.Mapper,
mapRequest tailcfg.MapRequest,
isNoise bool,
) {
logInfo, logErr := logPollFunc(mapRequest, machine, isNoise)

keepAliveTicker := time.NewTicker(keepAliveInterval)

h.pollNetMapStreamWG.Add(1)
defer h.pollNetMapStreamWG.Done()

updateChan := make(chan types.StateUpdate)
defer closeChanWithLog(updateChan, machine.Hostname, "updateChan")

// Register the node's update channel
h.nodeNotifier.AddNode(machine.MachineKey, updateChan)
defer h.nodeNotifier.RemoveNode(machine.MachineKey)

ctx := context.WithValue(ctxReq, machineNameContextKey, machine.Hostname)
ctx = context.WithValue(ctx, machineNameContextKey, machine.Hostname)

ctx, cancel := context.WithCancel(ctx)
defer cancel()
Expand Down

0 comments on commit a8079a2

Please sign in to comment.