387aa03adb
This commit changes the internals of the mapper to track all the changes to peers over its lifetime. This means that it no longer depends on the database and this should hopefully help with locks and timing issues. When the mapper is created, it needs the current list of peers, the world view, when the polling session was started. Then as update changes are called, it tracks the changes and generates responses based on its internal list. As a side, the types.Machines and types.MachinesP, as well as types.Machine being passed as a full struct and pointer has been changed to always be pointers, everywhere. Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
137 lines
3.2 KiB
Go
137 lines
3.2 KiB
Go
package types
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/netip"
|
|
|
|
"tailscale.com/tailcfg"
|
|
)
|
|
|
|
var ErrCannotParsePrefix = errors.New("cannot parse prefix")
|
|
|
|
// This is a "wrapper" type around tailscales
|
|
// Hostinfo to allow us to add database "serialization"
|
|
// methods. This allows us to use a typed values throughout
|
|
// the code and not have to marshal/unmarshal and error
|
|
// check all over the code.
|
|
type HostInfo tailcfg.Hostinfo
|
|
|
|
func (hi *HostInfo) Scan(destination interface{}) error {
|
|
switch value := destination.(type) {
|
|
case []byte:
|
|
return json.Unmarshal(value, hi)
|
|
|
|
case string:
|
|
return json.Unmarshal([]byte(value), hi)
|
|
|
|
default:
|
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
|
}
|
|
}
|
|
|
|
// Value return json value, implement driver.Valuer interface.
|
|
func (hi HostInfo) Value() (driver.Value, error) {
|
|
bytes, err := json.Marshal(hi)
|
|
|
|
return string(bytes), err
|
|
}
|
|
|
|
type IPPrefix netip.Prefix
|
|
|
|
func (i *IPPrefix) Scan(destination interface{}) error {
|
|
switch value := destination.(type) {
|
|
case string:
|
|
prefix, err := netip.ParsePrefix(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*i = IPPrefix(prefix)
|
|
|
|
return nil
|
|
default:
|
|
return fmt.Errorf("%w: unexpected data type %T", ErrCannotParsePrefix, destination)
|
|
}
|
|
}
|
|
|
|
// Value return json value, implement driver.Valuer interface.
|
|
func (i IPPrefix) Value() (driver.Value, error) {
|
|
prefixStr := netip.Prefix(i).String()
|
|
|
|
return prefixStr, nil
|
|
}
|
|
|
|
type IPPrefixes []netip.Prefix
|
|
|
|
func (i *IPPrefixes) Scan(destination interface{}) error {
|
|
switch value := destination.(type) {
|
|
case []byte:
|
|
return json.Unmarshal(value, i)
|
|
|
|
case string:
|
|
return json.Unmarshal([]byte(value), i)
|
|
|
|
default:
|
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
|
}
|
|
}
|
|
|
|
// Value return json value, implement driver.Valuer interface.
|
|
func (i IPPrefixes) Value() (driver.Value, error) {
|
|
bytes, err := json.Marshal(i)
|
|
|
|
return string(bytes), err
|
|
}
|
|
|
|
type StringList []string
|
|
|
|
func (i *StringList) Scan(destination interface{}) error {
|
|
switch value := destination.(type) {
|
|
case []byte:
|
|
return json.Unmarshal(value, i)
|
|
|
|
case string:
|
|
return json.Unmarshal([]byte(value), i)
|
|
|
|
default:
|
|
return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
|
|
}
|
|
}
|
|
|
|
// Value return json value, implement driver.Valuer interface.
|
|
func (i StringList) Value() (driver.Value, error) {
|
|
bytes, err := json.Marshal(i)
|
|
|
|
return string(bytes), err
|
|
}
|
|
|
|
type StateUpdateType int
|
|
|
|
const (
|
|
StateFullUpdate StateUpdateType = iota
|
|
StatePeerChanged
|
|
StatePeerRemoved
|
|
StateDERPUpdated
|
|
)
|
|
|
|
// StateUpdate is an internal message containing information about
|
|
// a state change that has happened to the network.
|
|
type StateUpdate struct {
|
|
// The type of update
|
|
Type StateUpdateType
|
|
|
|
// Changed must be set when Type is StatePeerChanged and
|
|
// contain the Machine IDs of machines that has changed.
|
|
Changed Machines
|
|
|
|
// Removed must be set when Type is StatePeerRemoved and
|
|
// contain a list of the nodes that has been removed from
|
|
// the network.
|
|
Removed []tailcfg.NodeID
|
|
|
|
// DERPMap must be set when Type is StateDERPUpdated and
|
|
// contain the new DERP Map.
|
|
DERPMap tailcfg.DERPMap
|
|
}
|