Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

feat: cache interface addresses for 1 minute #129

Merged
merged 3 commits into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions swarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
goprocessctx "github.com/jbenet/goprocess/context"

filter "github.com/libp2p/go-maddr-filter"
ma "github.com/multiformats/go-multiaddr"
mafilter "github.com/whyrusleeping/multiaddr-filter"
)

Expand Down Expand Up @@ -58,6 +59,10 @@ type Swarm struct {

listeners struct {
sync.RWMutex

ifaceListenAddres []ma.Multiaddr
cacheEOL time.Time

m map[transport.Listener]struct{}
}

Expand Down
46 changes: 45 additions & 1 deletion swarm_addr.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package swarm

import (
"time"

addrutil "github.com/libp2p/go-addr-util"
ma "github.com/multiformats/go-multiaddr"
)
Expand All @@ -9,16 +11,58 @@ import (
func (s *Swarm) ListenAddresses() []ma.Multiaddr {
s.listeners.RLock()
defer s.listeners.RUnlock()
return s.listenAddressesNoLock()
}

func (s *Swarm) listenAddressesNoLock() []ma.Multiaddr {
addrs := make([]ma.Multiaddr, 0, len(s.listeners.m))
for l := range s.listeners.m {
addrs = append(addrs, l.Multiaddr())
}
return addrs
}

const ifaceAddrsCacheDuration = 1 * time.Minute

// InterfaceListenAddresses returns a list of addresses at which this swarm
// listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to
// use the known local interfaces.
func (s *Swarm) InterfaceListenAddresses() ([]ma.Multiaddr, error) {
return addrutil.ResolveUnspecifiedAddresses(s.ListenAddresses(), nil)
s.listeners.RLock() // RLock start

ifaceListenAddres := s.listeners.ifaceListenAddres
isEOL := time.Now().After(s.listeners.cacheEOL)
s.listeners.RUnlock() // RLock end

if ifaceListenAddres != nil && !isEOL {
// Cache is valid
return ifaceListenAddres, nil
}

// Cache is not valid
// Perfrom double checked locking

s.listeners.Lock() // Lock start

ifaceListenAddres = s.listeners.ifaceListenAddres
isEOL = time.Now().After(s.listeners.cacheEOL)
if ifaceListenAddres == nil || isEOL {
// Cache is still invalid

var err error
ifaceListenAddres, err = addrutil.ResolveUnspecifiedAddresses(
s.listenAddressesNoLock(), nil)

if err != nil {
s.listeners.Unlock() // Lock early exit
return nil, err
}

s.listeners.ifaceListenAddres = ifaceListenAddres
s.listeners.cacheEOL = time.Now().Add(ifaceAddrsCacheDuration)
}

s.listeners.Unlock() // Lock end

return ifaceListenAddres, nil
}