refactor-for-testability #3

Merged
johnnylee merged 26 commits from refactor-for-testability into main 2025-03-01 20:02:27 +00:00
19 changed files with 110 additions and 333 deletions
Showing only changes of commit e1a5f50e1a - Show all commits

View File

@ -1,40 +1,44 @@
package peer package peer
import ( import (
"io"
"log" "log"
"net/netip" "net/netip"
"sync/atomic" "sync/atomic"
) )
type connReader struct { type connReader struct {
conn udpReader // Input
iface ifWriter readFromUDPAddrPort func([]byte) (int, netip.AddrPort, error)
sender encryptedPacketSender
super controlMsgHandler // Output
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error)
iface io.Writer
handleControlMsg func(fromIP byte, pkt any)
localIP byte localIP byte
peers [256]*atomic.Pointer[remotePeer] rt *atomic.Pointer[routingTable]
buf []byte buf []byte
decBuf []byte decBuf []byte
} }
func newConnReader( func newConnReader(
conn udpReader, readFromUDPAddrPort func([]byte) (int, netip.AddrPort, error),
ifWriter ifWriter, writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error),
sender encryptedPacketSender, iface io.Writer,
super controlMsgHandler, handleControlMsg func(fromIP byte, pkt any),
localIP byte, rt *atomic.Pointer[routingTable],
peers [256]*atomic.Pointer[remotePeer],
) *connReader { ) *connReader {
return &connReader{ return &connReader{
conn: conn, readFromUDPAddrPort: readFromUDPAddrPort,
iface: ifWriter, writeToUDPAddrPort: writeToUDPAddrPort,
sender: sender, iface: iface,
super: super, handleControlMsg: handleControlMsg,
localIP: localIP, localIP: rt.Load().LocalIP,
peers: peers, rt: rt,
buf: make([]byte, bufferSize), buf: newBuf(),
decBuf: make([]byte, bufferSize), decBuf: newBuf(),
} }
} }
@ -44,13 +48,11 @@ func (r *connReader) Run() {
} }
} }
func (r *connReader) logf(s string, args ...any) {
log.Printf("[ConnReader] "+s, args...)
}
func (r *connReader) handleNextPacket() { func (r *connReader) handleNextPacket() {
buf := r.buf[:bufferSize] buf := r.buf[:bufferSize]
n, remoteAddr, err := r.conn.ReadFromUDPAddrPort(buf) log.Printf("Getting next packet...")
n, remoteAddr, err := r.readFromUDPAddrPort(buf)
log.Printf("Packet from %v...", remoteAddr)
if err != nil { if err != nil {
log.Fatalf("Failed to read from UDP port: %v", err) log.Fatalf("Failed to read from UDP port: %v", err)
} }
@ -64,23 +66,22 @@ func (r *connReader) handleNextPacket() {
buf = buf[:n] buf = buf[:n]
h := parseHeader(buf) h := parseHeader(buf)
peer := r.peers[h.SourceIP].Load() rt := r.rt.Load()
peer := rt.Peers[h.SourceIP]
switch h.StreamID { switch h.StreamID {
case controlStreamID: case controlStreamID:
r.handleControlPacket(peer, remoteAddr, h, buf) r.handleControlPacket(remoteAddr, peer, h, buf)
case dataStreamID: case dataStreamID:
r.handleDataPacket(peer, h, buf) r.handleDataPacket(rt, peer, h, buf)
default: default:
r.logf("Unknown stream ID: %d", h.StreamID) r.logf("Unknown stream ID: %d", h.StreamID)
} }
} }
func (r *connReader) handleControlPacket( func (r *connReader) handleControlPacket(
peer *remotePeer, remoteAddr netip.AddrPort,
addr netip.AddrPort, peer remotePeer,
h header, h header,
enc []byte, enc []byte,
) { ) {
@ -93,22 +94,27 @@ func (r *connReader) handleControlPacket(
return return
} }
msg, err := decryptControlPacket(peer, addr, h, enc, r.decBuf) msg, err := peer.DecryptControlPacket(remoteAddr, h, enc, r.decBuf)
if err != nil { if err != nil {
r.logf("Failed to decrypt control packet: %v", err) r.logf("Failed to decrypt control packet: %v", err)
return return
} }
r.super.HandleControlMsg(msg) r.handleControlMsg(h.SourceIP, msg)
} }
func (r *connReader) handleDataPacket(peer *remotePeer, h header, enc []byte) { func (r *connReader) handleDataPacket(
rt *routingTable,
peer remotePeer,
h header,
enc []byte,
) {
if !peer.Up { if !peer.Up {
r.logf("Not connected (recv).") r.logf("Not connected (recv).")
return return
} }
data, err := decryptDataPacket(peer, h, enc, r.decBuf) data, err := peer.DecryptDataPacket(h, enc, r.decBuf)
if err != nil { if err != nil {
r.logf("Failed to decrypt data packet: %v", err) r.logf("Failed to decrypt data packet: %v", err)
return return
@ -121,11 +127,15 @@ func (r *connReader) handleDataPacket(peer *remotePeer, h header, enc []byte) {
return return
} }
destPeer := r.peers[h.DestIP].Load() relay, ok := rt.GetRelay()
if !destPeer.Up { if !ok {
r.logf("Not connected (relay): %d", destPeer.IP) r.logf("Relay not available.")
return return
} }
r.sender.SendEncryptedDataPacket(data, destPeer) r.writeToUDPAddrPort(data, relay.DirectAddr)
}
func (r *connReader) logf(format string, args ...any) {
log.Printf("[ConnReader] "+format, args...)
} }

View File

@ -1,141 +0,0 @@
package peer
import (
"io"
"log"
"net/netip"
"sync/atomic"
)
type ConnReader struct {
// Input
readFromUDPAddrPort func([]byte) (int, netip.AddrPort, error)
// Output
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error)
iface io.Writer
handleControlMsg func(fromIP byte, pkt any)
localIP byte
rt *atomic.Pointer[routingTable]
buf []byte
decBuf []byte
}
func NewConnReader(
readFromUDPAddrPort func([]byte) (int, netip.AddrPort, error),
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error),
iface io.Writer,
handleControlMsg func(fromIP byte, pkt any),
rt *atomic.Pointer[routingTable],
) *ConnReader {
return &ConnReader{
readFromUDPAddrPort: readFromUDPAddrPort,
writeToUDPAddrPort: writeToUDPAddrPort,
iface: iface,
handleControlMsg: handleControlMsg,
localIP: rt.Load().LocalIP,
rt: rt,
buf: newBuf(),
decBuf: newBuf(),
}
}
func (r *ConnReader) Run() {
for {
r.handleNextPacket()
}
}
func (r *ConnReader) handleNextPacket() {
buf := r.buf[:bufferSize]
log.Printf("Getting next packet...")
n, remoteAddr, err := r.readFromUDPAddrPort(buf)
log.Printf("Packet from %v...", remoteAddr)
if err != nil {
log.Fatalf("Failed to read from UDP port: %v", err)
}
if n < headerSize {
return
}
remoteAddr = netip.AddrPortFrom(remoteAddr.Addr().Unmap(), remoteAddr.Port())
buf = buf[:n]
h := parseHeader(buf)
rt := r.rt.Load()
peer := rt.Peers[h.SourceIP]
switch h.StreamID {
case controlStreamID:
r.handleControlPacket(remoteAddr, peer, h, buf)
case dataStreamID:
r.handleDataPacket(rt, peer, h, buf)
default:
r.logf("Unknown stream ID: %d", h.StreamID)
}
}
func (r *ConnReader) handleControlPacket(
remoteAddr netip.AddrPort,
peer remotePeer,
h header,
enc []byte,
) {
if peer.ControlCipher == nil {
return
}
if h.DestIP != r.localIP {
r.logf("Incorrect destination IP on control packet: %d", h.DestIP)
return
}
msg, err := peer.DecryptControlPacket(remoteAddr, h, enc, r.decBuf)
if err != nil {
r.logf("Failed to decrypt control packet: %v", err)
return
}
r.handleControlMsg(h.SourceIP, msg)
}
func (r *ConnReader) handleDataPacket(
rt *routingTable,
peer remotePeer,
h header,
enc []byte,
) {
if !peer.Up {
r.logf("Not connected (recv).")
return
}
data, err := peer.DecryptDataPacket(h, enc, r.decBuf)
if err != nil {
r.logf("Failed to decrypt data packet: %v", err)
return
}
if h.DestIP == r.localIP {
if _, err := r.iface.Write(data); err != nil {
log.Fatalf("Failed to write to interface: %v", err)
}
return
}
relay, ok := rt.GetRelay()
if !ok {
r.logf("Relay not available.")
return
}
r.writeToUDPAddrPort(data, relay.DirectAddr)
}
func (r *ConnReader) logf(format string, args ...any) {
log.Printf("[ConnReader] "+format, args...)
}

View File

@ -37,7 +37,7 @@ func generateKeys() cryptoKeys {
func encryptControlPacket( func encryptControlPacket(
localIP byte, localIP byte,
peer *remotePeer, peer *remotePeer,
pkt Marshaller, pkt marshaller,
tmp []byte, tmp []byte,
out []byte, out []byte,
) []byte { ) []byte {

View File

@ -13,12 +13,12 @@ func newRoutePairForTesting() (*remotePeer, *remotePeer) {
keys1 := generateKeys() keys1 := generateKeys()
keys2 := generateKeys() keys2 := generateKeys()
r1 := NewRemotePeer(1) r1 := newRemotePeer(1)
r1.PubSignKey = keys1.PubSignKey r1.PubSignKey = keys1.PubSignKey
r1.ControlCipher = newControlCipher(keys1.PrivKey, keys2.PubKey) r1.ControlCipher = newControlCipher(keys1.PrivKey, keys2.PubKey)
r1.DataCipher = newDataCipher() r1.DataCipher = newDataCipher()
r2 := NewRemotePeer(2) r2 := newRemotePeer(2)
r2.PubSignKey = keys2.PubSignKey r2.PubSignKey = keys2.PubSignKey
r2.ControlCipher = newControlCipher(keys2.PrivKey, keys1.PubKey) r2.ControlCipher = newControlCipher(keys2.PrivKey, keys1.PubKey)
r2.DataCipher = r1.DataCipher r2.DataCipher = r1.DataCipher

View File

@ -27,3 +27,7 @@ var multicastAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom(
func newBuf() []byte { func newBuf() []byte {
return make([]byte, bufferSize) return make([]byte, bufferSize)
} }
type marshaller interface {
Marshal([]byte) []byte
}

View File

@ -7,7 +7,7 @@ import (
"sync/atomic" "sync/atomic"
) )
type IFReader struct { type ifReader struct {
iface io.Reader iface io.Reader
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error) writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error)
rt *atomic.Pointer[routingTable] rt *atomic.Pointer[routingTable]
@ -15,22 +15,22 @@ type IFReader struct {
buf2 []byte buf2 []byte
} }
func NewIFReader( func newIFReader(
iface io.Reader, iface io.Reader,
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error), writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error),
rt *atomic.Pointer[routingTable], rt *atomic.Pointer[routingTable],
) *IFReader { ) *ifReader {
return &IFReader{iface, writeToUDPAddrPort, rt, newBuf(), newBuf()} return &ifReader{iface, writeToUDPAddrPort, rt, newBuf(), newBuf()}
} }
func (r *IFReader) Run() { func (r *ifReader) Run() {
packet := newBuf() packet := newBuf()
for { for {
r.handleNextPacket(packet) r.handleNextPacket(packet)
} }
} }
func (r *IFReader) handleNextPacket(packet []byte) { func (r *ifReader) handleNextPacket(packet []byte) {
packet = r.readNextPacket(packet) packet = r.readNextPacket(packet)
remoteIP, ok := r.parsePacket(packet) remoteIP, ok := r.parsePacket(packet)
if !ok { if !ok {
@ -60,7 +60,7 @@ func (r *IFReader) handleNextPacket(packet []byte) {
r.writeToUDPAddrPort(enc, relay.DirectAddr) r.writeToUDPAddrPort(enc, relay.DirectAddr)
} }
func (r *IFReader) readNextPacket(buf []byte) []byte { func (r *ifReader) readNextPacket(buf []byte) []byte {
n, err := r.iface.Read(buf[:cap(buf)]) n, err := r.iface.Read(buf[:cap(buf)])
if err != nil { if err != nil {
log.Fatalf("Failed to read from interface: %v", err) log.Fatalf("Failed to read from interface: %v", err)
@ -69,7 +69,7 @@ func (r *IFReader) readNextPacket(buf []byte) []byte {
return buf[:n] return buf[:n]
} }
func (r *IFReader) parsePacket(buf []byte) (byte, bool) { func (r *ifReader) parsePacket(buf []byte) (byte, bool) {
n := len(buf) n := len(buf)
if n == 0 { if n == 0 {
return 0, false return 0, false
@ -98,6 +98,6 @@ func (r *IFReader) parsePacket(buf []byte) (byte, bool) {
} }
} }
func (*IFReader) logf(s string, args ...any) { func (*ifReader) logf(s string, args ...any) {
log.Printf("[IFReader] "+s, args...) log.Printf("[IFReader] "+s, args...)
} }

View File

@ -3,7 +3,6 @@ package peer
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"net" "net"
"os" "os"
"syscall" "syscall"
@ -11,45 +10,6 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
// Get next packet, returning packet, ip, and possible error.
func readNextPacket(iface io.ReadWriteCloser, buf []byte) ([]byte, byte, error) {
var (
version byte
ip byte
)
for {
n, err := iface.Read(buf[:cap(buf)])
if err != nil {
return nil, ip, err
}
buf = buf[:n]
version = buf[0] >> 4
switch version {
case 4:
if n < 20 {
log.Printf("Short IPv4 packet: %d", len(buf))
continue
}
ip = buf[19]
case 6:
if len(buf) < 40 {
log.Printf("Short IPv6 packet: %d", len(buf))
continue
}
ip = buf[39]
default:
log.Printf("Invalid IP packet version: %v", version)
continue
}
return buf, ip, nil
}
}
func openInterface(network []byte, localIP byte, name string) (io.ReadWriteCloser, error) { func openInterface(network []byte, localIP byte, name string) (io.ReadWriteCloser, error) {
if len(network) != 4 { if len(network) != 4 {
return nil, fmt.Errorf("expected network to be 4 bytes, got %d", len(network)) return nil, fmt.Errorf("expected network to be 4 bytes, got %d", len(network))

View File

@ -1,49 +0,0 @@
package peer
import (
"io"
"net"
"net/netip"
)
type UDPConn interface {
ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error)
WriteToUDP([]byte, *net.UDPAddr) (int, error)
}
type ifWriter io.Writer
type udpReader interface {
ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
}
type udpWriter interface {
WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error)
}
type mcUDPWriter interface {
WriteToUDP([]byte, *net.UDPAddr) (int, error)
}
type Marshaller interface {
Marshal([]byte) []byte
}
type dataPacketSender interface {
SendDataPacket(pkt []byte, peer *remotePeer)
RelayDataPacket(pkt []byte, peer, relay *remotePeer)
}
type controlPacketSender interface {
SendControlPacket(pkt Marshaller, peer *remotePeer)
RelayControlPacket(pkt Marshaller, peer, relay *remotePeer)
}
type encryptedPacketSender interface {
SendEncryptedDataPacket(pkt []byte, peer *remotePeer)
}
type controlMsgHandler interface {
HandleControlMsg(pkt any)
}

View File

@ -6,7 +6,7 @@ import (
) )
func Main() { func Main() {
conf := Config{} conf := peerConfig{}
flag.StringVar(&conf.NetName, "name", "", "[REQUIRED] The network name.") flag.StringVar(&conf.NetName, "name", "", "[REQUIRED] The network name.")
flag.StringVar(&conf.HubAddress, "hub-address", "", "[REQUIRED] The hub address.") flag.StringVar(&conf.HubAddress, "hub-address", "", "[REQUIRED] The hub address.")
@ -18,6 +18,6 @@ func Main() {
os.Exit(1) os.Exit(1)
} }
peer := New(conf) peer := newPeerMain(conf)
peer.Run() peer.Run()
} }

View File

@ -1,10 +1,6 @@
package peer package peer
import ( /*
"log"
"sync/atomic"
)
type mcReader struct { type mcReader struct {
conn udpReader conn udpReader
super controlMsgHandler super controlMsgHandler
@ -55,3 +51,4 @@ func (r *mcReader) handleNextPacket() {
SrcAddr: remoteAddr, SrcAddr: remoteAddr,
}) })
} }
*/

View File

@ -1,8 +1,6 @@
package peer package peer
import ( import (
"log"
"golang.org/x/crypto/nacl/sign" "golang.org/x/crypto/nacl/sign"
) )
@ -34,7 +32,9 @@ func verifyLocalDiscoveryPacket(pkt, buf []byte, pubSignKey []byte) bool {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/*
type mcWriter struct { type mcWriter struct {
conn mcUDPWriter conn mcUDPWriter
discoveryPacket []byte discoveryPacket []byte
} }
@ -50,4 +50,4 @@ func (w *mcWriter) SendLocalDiscovery() {
if _, err := w.conn.WriteToUDP(w.discoveryPacket, multicastAddr); err != nil { if _, err := w.conn.WriteToUDP(w.discoveryPacket, multicastAddr); err != nil {
log.Printf("[MCWriter] Failed to write multicast UDP packet: %v", err) log.Printf("[MCWriter] Failed to write multicast UDP packet: %v", err)
} }
} }*/

View File

@ -1,11 +1,6 @@
package peer package peer
import ( /*
"bytes"
"net"
"testing"
)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Testing that we can create and verify a local discovery packet. // Testing that we can create and verify a local discovery packet.
@ -100,3 +95,4 @@ func TestMCWriter_SendLocalDiscovery(t *testing.T) {
t.Fatal("Verification should succeed.") t.Fatal("Verification should succeed.")
} }
} }
*/

View File

@ -15,21 +15,21 @@ import (
"vppn/m" "vppn/m"
) )
type Peer struct { type peerMain struct {
ifReader *IFReader ifReader *ifReader
connReader *ConnReader connReader *connReader
iface io.Writer iface io.Writer
hubPoller *hubPoller hubPoller *hubPoller
super *Super super *supervisor
} }
type Config struct { type peerConfig struct {
NetName string NetName string
HubAddress string HubAddress string
APIKey string APIKey string
} }
func New(conf Config) *Peer { func newPeerMain(conf peerConfig) *peerMain {
config, err := loadPeerConfig(conf.NetName) config, err := loadPeerConfig(conf.NetName)
if err != nil { if err != nil {
log.Printf("Failed to load configuration: %v", err) log.Printf("Failed to load configuration: %v", err)
@ -83,15 +83,15 @@ func New(conf Config) *Peer {
rtPtr := &atomic.Pointer[routingTable]{} rtPtr := &atomic.Pointer[routingTable]{}
rtPtr.Store(&rt) rtPtr.Store(&rt)
ifReader := NewIFReader(iface, writeToUDPAddrPort, rtPtr) ifReader := newIFReader(iface, writeToUDPAddrPort, rtPtr)
super := NewSuper(writeToUDPAddrPort, rtPtr, config.PrivKey) super := newSupervisor(writeToUDPAddrPort, rtPtr, config.PrivKey)
connReader := NewConnReader(conn.ReadFromUDPAddrPort, writeToUDPAddrPort, iface, super.HandleControlMsg, rtPtr) connReader := newConnReader(conn.ReadFromUDPAddrPort, writeToUDPAddrPort, iface, super.HandleControlMsg, rtPtr)
hubPoller, err := newHubPoller(config.PeerIP, conf.NetName, conf.HubAddress, conf.APIKey, super.HandleControlMsg) hubPoller, err := newHubPoller(config.PeerIP, conf.NetName, conf.HubAddress, conf.APIKey, super.HandleControlMsg)
if err != nil { if err != nil {
log.Fatalf("Failed to create hub poller: %v", err) log.Fatalf("Failed to create hub poller: %v", err)
} }
return &Peer{ return &peerMain{
iface: iface, iface: iface,
ifReader: ifReader, ifReader: ifReader,
connReader: connReader, connReader: connReader,
@ -100,14 +100,14 @@ func New(conf Config) *Peer {
} }
} }
func (p *Peer) Run() { func (p *peerMain) Run() {
go p.ifReader.Run() go p.ifReader.Run()
go p.connReader.Run() go p.connReader.Run()
p.super.Start() p.super.Start()
p.hubPoller.Run() p.hubPoller.Run()
} }
func initPeerWithHub(conf Config) { func initPeerWithHub(conf peerConfig) {
keys := generateKeys() keys := generateKeys()
initURL, err := url.Parse(conf.HubAddress) initURL, err := url.Parse(conf.HubAddress)

View File

@ -14,8 +14,8 @@ type P struct {
RT *atomic.Pointer[routingTable] RT *atomic.Pointer[routingTable]
Conn *TestUDPConn Conn *TestUDPConn
IFace *TestIFace IFace *TestIFace
ConnReader *ConnReader ConnReader *connReader
IFReader *IFReader IFReader *ifReader
} }
func NewPeerForTesting(n *TestNetwork, ip byte, addr netip.AddrPort) P { func NewPeerForTesting(n *TestNetwork, ip byte, addr netip.AddrPort) P {

View File

@ -25,7 +25,7 @@ type peerState interface {
type pState struct { type pState struct {
// Output. // Output.
publish func(remotePeer) publish func(remotePeer)
sendControlPacket func(remotePeer, Marshaller) sendControlPacket func(remotePeer, marshaller)
// Immutable data. // Immutable data.
localIP byte localIP byte
@ -124,7 +124,7 @@ func (s *pState) logf(format string, args ...any) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
func (s *pState) SendTo(pkt Marshaller, addr netip.AddrPort) { func (s *pState) SendTo(pkt marshaller, addr netip.AddrPort) {
if !addr.IsValid() { if !addr.IsValid() {
return return
} }
@ -134,7 +134,7 @@ func (s *pState) SendTo(pkt Marshaller, addr netip.AddrPort) {
s.Send(route, pkt) s.Send(route, pkt)
} }
func (s *pState) Send(peer remotePeer, pkt Marshaller) { func (s *pState) Send(peer remotePeer, pkt marshaller) {
if err := s.limiter.Limit(); err != nil { if err := s.limiter.Limit(); err != nil {
s.logf("Rate limited.") s.logf("Rate limited.")
return return

View File

@ -31,7 +31,7 @@ func NewPeerStateTestHarness() *PeerStateTestHarness {
publish: func(rp remotePeer) { publish: func(rp remotePeer) {
h.Published = rp h.Published = rp
}, },
sendControlPacket: func(rp remotePeer, pkt Marshaller) { sendControlPacket: func(rp remotePeer, pkt marshaller) {
h.Sent = append(h.Sent, PeerStateControlMsg{rp, pkt}) h.Sent = append(h.Sent, PeerStateControlMsg{rp, pkt})
}, },
localIP: 2, localIP: 2,

View File

@ -11,26 +11,26 @@ import (
"git.crumpington.com/lib/go/ratelimiter" "git.crumpington.com/lib/go/ratelimiter"
) )
type Super struct { type supervisor struct {
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error) writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error)
staged routingTable staged routingTable
shared *atomic.Pointer[routingTable] shared *atomic.Pointer[routingTable]
peers [256]*PeerSuper peers [256]*peerSuper
lock sync.Mutex lock sync.Mutex
buf1 []byte buf1 []byte
buf2 []byte buf2 []byte
} }
func NewSuper( func newSupervisor(
writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error), writeToUDPAddrPort func([]byte, netip.AddrPort) (int, error),
rt *atomic.Pointer[routingTable], rt *atomic.Pointer[routingTable],
privKey []byte, privKey []byte,
) *Super { ) *supervisor {
routes := rt.Load() routes := rt.Load()
s := &Super{ s := &supervisor{
writeToUDPAddrPort: writeToUDPAddrPort, writeToUDPAddrPort: writeToUDPAddrPort,
staged: *routes, staged: *routes,
shared: rt, shared: rt,
@ -55,23 +55,23 @@ func NewSuper(
MaxWaitCount: 1, MaxWaitCount: 1,
}), }),
} }
s.peers[i] = NewPeerSuper(state) s.peers[i] = newPeerSuper(state)
} }
return s return s
} }
func (s *Super) Start() { func (s *supervisor) Start() {
for i := range s.peers { for i := range s.peers {
go s.peers[i].Run() go s.peers[i].Run()
} }
} }
func (s *Super) HandleControlMsg(destIP byte, msg any) { func (s *supervisor) HandleControlMsg(destIP byte, msg any) {
s.peers[destIP].HandleControlMsg(msg) s.peers[destIP].HandleControlMsg(msg)
} }
func (s *Super) send(peer remotePeer, pkt Marshaller) { func (s *supervisor) send(peer remotePeer, pkt marshaller) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -90,7 +90,7 @@ func (s *Super) send(peer remotePeer, pkt Marshaller) {
s.writeToUDPAddrPort(enc, relay.DirectAddr) s.writeToUDPAddrPort(enc, relay.DirectAddr)
} }
func (s *Super) publish(rp remotePeer) { func (s *supervisor) publish(rp remotePeer) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -100,7 +100,7 @@ func (s *Super) publish(rp remotePeer) {
s.shared.Store(&copy) s.shared.Store(&copy)
} }
func (s *Super) ensureRelay() { func (s *supervisor) ensureRelay() {
if _, ok := s.staged.GetRelay(); ok { if _, ok := s.staged.GetRelay(); ok {
return return
} }
@ -116,26 +116,26 @@ func (s *Super) ensureRelay() {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
type PeerSuper struct { type peerSuper struct {
messages chan any messages chan any
state peerState state peerState
} }
func NewPeerSuper(state *pState) *PeerSuper { func newPeerSuper(state *pState) *peerSuper {
return &PeerSuper{ return &peerSuper{
messages: make(chan any, 8), messages: make(chan any, 8),
state: state.OnPeerUpdate(nil), state: state.OnPeerUpdate(nil),
} }
} }
func (s *PeerSuper) HandleControlMsg(msg any) { func (s *peerSuper) HandleControlMsg(msg any) {
select { select {
case s.messages <- msg: case s.messages <- msg:
default: default:
} }
} }
func (s *PeerSuper) Run() { func (s *peerSuper) Run() {
go func() { go func() {
// Randomize ping timers. // Randomize ping timers.
time.Sleep(time.Duration(rand.Intn(4000)) * time.Millisecond) time.Sleep(time.Duration(rand.Intn(4000)) * time.Millisecond)

View File

@ -7,7 +7,7 @@ import (
) )
// TODO: Remove // TODO: Remove
func NewRemotePeer(ip byte) *remotePeer { func newRemotePeer(ip byte) *remotePeer {
counter := uint64(time.Now().Unix()<<30 + 1) counter := uint64(time.Now().Unix()<<30 + 1)
return &remotePeer{ return &remotePeer{
IP: ip, IP: ip,
@ -58,7 +58,7 @@ func (p remotePeer) DecryptDataPacket(h header, enc, out []byte) ([]byte, error)
} }
// Peer must have a ControlCipher. // Peer must have a ControlCipher.
func (p remotePeer) EncryptControlPacket(pkt Marshaller, tmp, out []byte) []byte { func (p remotePeer) EncryptControlPacket(pkt marshaller, tmp, out []byte) []byte {
tmp = pkt.Marshal(tmp) tmp = pkt.Marshal(tmp)
h := header{ h := header{
StreamID: controlStreamID, StreamID: controlStreamID,