diff --git a/README.md b/README.md index 4f4a174..f24bbd7 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,7 @@ ## TO DO -* Replace time-based counter with startup counter - * 16 byte startupCounter - * (startupCount << 48) + counter - * pass startup count to newRoutingTable function (or global?) - * write / increment on startup -* Use startup counter for trace IDs as well (see Globals) * Double buffering in IFReader and ConnReader ? -* Clean up state machine - one class w/ - * type stateFunc func(msg any) stateFunc - * "init" funcs: func enterDisconnected() stateFunc -* ~~Idea: Use a bufferSet object to manager buffers. In function calls, buffers - should get used up, can panic if we run out of buffers to ensure we never - allocate~~ -* Idea: bufferSize should be large enough to split and use parts of the - buffer for encryption, etc. Yes. - -### Peer State Messages - -* peerUpdateMsg -* packetInit -* packetSyn -* packetAck -* packetProbe -* packetLocalDiscovery -* pingTimerMsg ## Hub Server Configuration diff --git a/peer/files.go b/peer/files.go index e7e7022..f4ee973 100644 --- a/peer/files.go +++ b/peer/files.go @@ -9,7 +9,7 @@ import ( ) type LocalConfig struct { - LocalPeerIP byte `json:"PeerIP"` + LocalPeerIP byte Network []byte PubKey []byte PrivKey []byte @@ -17,6 +17,10 @@ type LocalConfig struct { PrivSignKey []byte } +type startupCount struct { + Count uint16 +} + func configDir(netName string) string { d, err := os.UserHomeDir() if err != nil { @@ -33,6 +37,10 @@ func peerStatePath(netName string) string { return filepath.Join(configDir(netName), "state.json") } +func startupCountPath(netName string) string { + return filepath.Join(configDir(netName), "startup_count.json") +} + func storeJson(x any, outPath string) error { outDir := filepath.Dir(outPath) _ = os.MkdirAll(outDir, 0700) @@ -89,3 +97,11 @@ func loadPeerConfig(netName string) (pc LocalConfig, err error) { func loadNetworkState(netName string) (ps m.NetworkState, err error) { return ps, loadJson(peerStatePath(netName), &ps) } + +func loadStartupCount(netName string) (c startupCount, err error) { + return c, loadJson(startupCountPath(netName), &c) +} + +func storeStartupCount(netName string, c startupCount) error { + return storeJson(c, startupCountPath(netName)) +} diff --git a/peer/globals.go b/peer/globals.go index 16272d4..6a5bb0b 100644 --- a/peer/globals.go +++ b/peer/globals.go @@ -36,6 +36,9 @@ var multicastAddr = net.UDPAddrFromAddrPort(netip.AddrPortFrom( type Globals struct { LocalConfig // Embed, immutable. + // The number of startups + StartupCount uint16 + // Local public address (if available). Immutable. LocalAddr netip.AddrPort @@ -63,11 +66,13 @@ type Globals struct { func NewGlobals( localConfig LocalConfig, + startupCount startupCount, localAddr netip.AddrPort, conn *net.UDPConn, iface io.ReadWriteCloser, ) (g Globals) { g.LocalConfig = localConfig + g.StartupCount = startupCount.Count g.LocalAddr = localAddr g.LocalAddrValid = localAddr.IsValid() @@ -87,8 +92,7 @@ func NewGlobals( g.IFace = iface - // TODO: Initialize w/ startup count. - traceID := uint64(time.Now().Unix()<<30) + 1 + traceID := (uint64(g.StartupCount) << 48) + 1 g.NewTraceID = func() uint64 { return atomic.AddUint64(&traceID, 1) } diff --git a/peer/peer.go b/peer/peer.go index 8c7cfab..081b4f0 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -6,10 +6,12 @@ import ( "fmt" "io" "log" + "math" "net" "net/http" "net/netip" "net/url" + "os" "vppn/m" ) @@ -48,6 +50,22 @@ func newPeerMain(args mainArgs) *peerMain { log.Fatalf("Failed to load network state: %v", err) } + startupCount, err := loadStartupCount(args.NetName) + if err != nil { + if !os.IsNotExist(err) { + log.Fatalf("Failed to load startup count: %v", err) + } + } + + if startupCount.Count == math.MaxUint16 { + log.Fatalf("Startup counter overflow.") + } + startupCount.Count += 1 + + if err := storeStartupCount(args.NetName, startupCount); err != nil { + log.Fatalf("Failed to write startup count: %v", err) + } + iface, err := openInterface(config.Network, config.LocalPeerIP, args.NetName) if err != nil { log.Fatalf("Failed to open interface: %v", err) @@ -55,6 +73,7 @@ func newPeerMain(args mainArgs) *peerMain { localPeer := state.Peers[config.LocalPeerIP] + log.Printf("Local peer %d: %v", config.LocalPeerIP, localPeer) myAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", localPeer.Port)) if err != nil { log.Fatalf("Failed to resolve UDP address: %v", err) @@ -75,7 +94,7 @@ func newPeerMain(args mainArgs) *peerMain { localAddr = netip.AddrPortFrom(ip, localPeer.Port) } - g := NewGlobals(config, localAddr, conn, iface) + g := NewGlobals(config, startupCount, localAddr, conn, iface) hubPoller, err := NewHubPoller(g, args.NetName, args.HubAddress, args.APIKey) if err != nil { diff --git a/peer/remote.go b/peer/remote.go index dd63cd8..84b5c16 100644 --- a/peer/remote.go +++ b/peer/remote.go @@ -6,7 +6,6 @@ import ( "net/netip" "strings" "sync/atomic" - "time" "vppn/m" ) @@ -51,7 +50,7 @@ func newRemote(g Globals, remotePeerIP byte) *Remote { Globals: g, RemotePeerIP: remotePeerIP, dupCheck: newDupCheck(0), - sendCounter: uint64(time.Now().Unix()<<30) + 1, + sendCounter: (uint64(g.StartupCount) << 48) + 1, messages: make(chan any, 8), } r.config.Store(&remoteConfig{})