- introduces `NodeMeta` to `memberlist` gossip messages so we can see all the IP addresses a node is listening on and not just its advertised address. - introduces an `AddressBook` to map between advertised IP addresses and reachable IP addresses based on a peer's bind addresses and the local network interfaces a node is bound to. - introduces an `Alive` delegate to filter unreachable nodes from `memberlist` All this is to support multi-clan scenarios where only a subset of bridge nodes share a common network interface (VPN) with other clans.
78 lines
1.7 KiB
Go
78 lines
1.7 KiB
Go
// Package msgpack provides msgpack encoding/decoding with deterministic output.
|
|
package msgpack
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"reflect"
|
|
|
|
"github.com/hashicorp/go-msgpack/v2/codec"
|
|
)
|
|
|
|
var handle = &codec.MsgpackHandle{
|
|
WriteExt: true,
|
|
}
|
|
|
|
// netIPExt implements codec.BytesExt for net.IP encoding/decoding.
|
|
type netIPExt struct{}
|
|
|
|
func (netIPExt) WriteExt(v any) []byte {
|
|
ip, ok := v.(net.IP)
|
|
if !ok {
|
|
panic(fmt.Sprintf("expected net.IP, received %T", v))
|
|
}
|
|
|
|
return ip
|
|
}
|
|
|
|
func (netIPExt) ReadExt(dst any, src []byte) {
|
|
ip, ok := dst.(*net.IP)
|
|
if !ok {
|
|
panic(fmt.Sprintf("expected *net.IP, received %T", dst))
|
|
}
|
|
|
|
*ip = make(net.IP, len(src))
|
|
copy(*ip, src)
|
|
}
|
|
|
|
func init() {
|
|
handle.Canonical = true
|
|
|
|
if err := handle.SetBytesExt(reflect.TypeFor[net.IP](), 1, netIPExt{}); err != nil {
|
|
panic(fmt.Sprintf("failed to register msgpack handler for net.IP: %s", err))
|
|
}
|
|
}
|
|
|
|
// NewDecoder creates a new Decoder instance for decoding data from the provided io.Reader.
|
|
func NewDecoder(r io.Reader) *codec.Decoder {
|
|
return codec.NewDecoder(r, handle)
|
|
}
|
|
|
|
// NewEncoder creates a new Encoder instance for encoding data to the provided io.Writer.
|
|
func NewEncoder(w io.Writer) *codec.Encoder {
|
|
return codec.NewEncoder(w, handle)
|
|
}
|
|
|
|
// Marshal encodes v to msgpack with canonical (deterministic) encoding.
|
|
func Marshal(v any) ([]byte, error) {
|
|
var buf []byte
|
|
|
|
enc := codec.NewEncoderBytes(&buf, handle)
|
|
if err := enc.Encode(v); err != nil {
|
|
return nil, fmt.Errorf("msgpack marshal: %w", err)
|
|
}
|
|
|
|
return buf, nil
|
|
}
|
|
|
|
// Unmarshal decodes msgpack data into v.
|
|
func Unmarshal(data []byte, v any) error {
|
|
dec := codec.NewDecoderBytes(data, handle)
|
|
if err := dec.Decode(v); err != nil {
|
|
return fmt.Errorf("msgpack unmarshal: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|