Rework map session

This commit restructures the map session in to a struct
holding the state of what is needed during its lifetime.

For streaming sessions, the event loop is structured a
bit differently not hammering the clients with updates
but rather batching them over a short, configurable time
which should significantly improve cpu usage, and potentially
flakyness.

The use of Patch updates has been dialed back a little as
it does not look like its a 100% ready for prime time. Nodes
are now updated with full changes, except for a few things
like online status.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2024-02-23 10:59:24 +01:00 committed by Juan Font
parent dd693c444c
commit 58c94d2bd3
35 changed files with 1803 additions and 1716 deletions

View file

@ -7,11 +7,13 @@ import (
"fmt"
"net/netip"
"sort"
"strconv"
"strings"
"time"
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
"github.com/juanfont/headscale/hscontrol/policy/matcher"
"github.com/juanfont/headscale/hscontrol/util"
"github.com/rs/zerolog/log"
"go4.org/netipx"
"google.golang.org/protobuf/types/known/timestamppb"
@ -27,9 +29,24 @@ var (
ErrNodeUserHasNoName = errors.New("node user has no name")
)
type NodeID uint64
type NodeConnectedMap map[NodeID]bool
func (id NodeID) StableID() tailcfg.StableNodeID {
return tailcfg.StableNodeID(strconv.FormatUint(uint64(id), util.Base10))
}
func (id NodeID) NodeID() tailcfg.NodeID {
return tailcfg.NodeID(id)
}
func (id NodeID) Uint64() uint64 {
return uint64(id)
}
// Node is a Headscale client.
type Node struct {
ID uint64 `gorm:"primary_key"`
ID NodeID `gorm:"primary_key"`
// MachineKeyDatabaseField is the string representation of MachineKey
// it is _only_ used for reading and writing the key to the
@ -198,7 +215,7 @@ func (node Node) IsExpired() bool {
return false
}
return time.Now().UTC().After(*node.Expiry)
return time.Since(*node.Expiry) > 0
}
// IsEphemeral returns if the node is registered as an Ephemeral node.
@ -319,7 +336,7 @@ func (node *Node) AfterFind(tx *gorm.DB) error {
func (node *Node) Proto() *v1.Node {
nodeProto := &v1.Node{
Id: node.ID,
Id: uint64(node.ID),
MachineKey: node.MachineKey.String(),
NodeKey: node.NodeKey.String(),
@ -486,8 +503,8 @@ func (nodes Nodes) String() string {
return fmt.Sprintf("[ %s ](%d)", strings.Join(temp, ", "), len(temp))
}
func (nodes Nodes) IDMap() map[uint64]*Node {
ret := map[uint64]*Node{}
func (nodes Nodes) IDMap() map[NodeID]*Node {
ret := map[NodeID]*Node{}
for _, node := range nodes {
ret[node.ID] = node