diff --git a/router/state.go b/router/state.go index c34baeb0..4c047480 100644 --- a/router/state.go +++ b/router/state.go @@ -37,11 +37,13 @@ type state struct { phony.Inbox r *Router _peers []*peer // All switch ports, connected and disconnected + _peercount int // Number of connected peerings in total _highest *virtualSnakeEntry // The highest entry we've seen recently _descending *virtualSnakeEntry // Next descending node in keyspace _table virtualSnakeTable // Virtual snake DHT entries _snaketimer *time.Timer // Virtual snake maintenance timer _lastbootstrap time.Time // When did we last bootstrap? + _interval time.Duration // How often should we send bootstraps? _filterPacket FilterFn // Function called when forwarding packets } @@ -50,7 +52,7 @@ func (s *state) _start() { s._setDescendingNode(nil) s._highest = s._getHighest() - + s._interval = virtualSnakeBootstrapMinInterval s._table = virtualSnakeTable{} if s._snaketimer == nil { @@ -118,13 +120,16 @@ func (s *state) _addPeer(conn net.Conn, public types.PublicKey, uri ConnectionUR traffic: newFairFIFOQueue(queues, s.r.log), } s._peers[i] = new + s._peercount++ s.r.log.Println("Connected to peer", new.public.String(), "on port", new.port) v, _ := s.r.active.LoadOrStore(hex.EncodeToString(new.public[:])+string(zone), atomic.NewUint64(0)) v.(*atomic.Uint64).Inc() new.started.Store(true) new.reader.Act(nil, new._read) new.writer.Act(nil, new._write) - + if s._peercount == 1 { + s._interval = virtualSnakeBootstrapMinInterval + } s.r.Act(nil, func() { s.r._publish(events.PeerAdded{Port: types.SwitchPortID(i), PeerID: new.public.String()}) }) @@ -138,6 +143,7 @@ func (s *state) _addPeer(conn net.Conn, public types.PublicKey, uri ConnectionUR func (s *state) _removePeer(port types.SwitchPortID) { peerID := s._peers[port].public.String() s._peers[port] = nil + s._peercount-- s.r.Act(nil, func() { s.r._publish(events.PeerRemoved{Port: port, PeerID: peerID}) }) diff --git a/router/state_snek.go b/router/state_snek.go index 6ee54257..b8fc9b41 100644 --- a/router/state_snek.go +++ b/router/state_snek.go @@ -25,8 +25,9 @@ import ( // NOTE: Functions prefixed with an underscore (_) are only safe to be called // from the actor that owns them, in order to prevent data races. -const virtualSnakeMaintainInterval = time.Second -const virtualSnakeBootstrapInterval = time.Second * 5 +const virtualSnakeMaintainInterval = time.Second / 2 +const virtualSnakeBootstrapMinInterval = time.Second +const virtualSnakeBootstrapInterval = virtualSnakeBootstrapMinInterval * 5 const virtualSnakeNeighExpiryPeriod = virtualSnakeBootstrapInterval * 2 type virtualSnakeTable map[virtualSnakeIndex]*virtualSnakeEntry @@ -58,6 +59,9 @@ func (s *state) _maintainSnake() { return default: defer s._maintainSnakeIn(virtualSnakeMaintainInterval) + if s._peercount == 0 { + return + } } // The descending node is the node with the next lowest key. @@ -73,9 +77,12 @@ func (s *state) _maintainSnake() { } // Send a new bootstrap. - if time.Since(s._lastbootstrap) >= virtualSnakeBootstrapInterval { + if time.Since(s._lastbootstrap) >= s._interval { s._bootstrapNow() } + if s._interval < virtualSnakeBootstrapInterval { + s._interval += time.Second + } } // _bootstrapSoon will reset the bootstrap timer so that we will bootstrap on