diff --git a/p2p/nat/nat.go b/p2p/nat/nat.go index 7dac06df1d9a739b46b0be6e0c9837fafc18fb89..6324715bf5b4abb3bc3fa63ad205f0343d0ae139 100644 --- a/p2p/nat/nat.go +++ b/p2p/nat/nat.go @@ -155,12 +155,13 @@ type Mapping interface { type mapping struct { sync.Mutex // guards all fields - nat *NAT - proto string - intport int - extport int - intaddr ma.Multiaddr - proc goprocess.Process + nat *NAT + proto string + intport int + extport int + permanent bool + intaddr ma.Multiaddr + proc goprocess.Process cached ma.Multiaddr cacheTime time.Time @@ -197,6 +198,18 @@ func (m *mapping) setExternalPort(p int) { m.extport = p } +func (m *mapping) setPermanent(p bool) { + m.Lock() + defer m.Unlock() + m.permanent = p +} + +func (m *mapping) isPermanent() bool { + m.Lock() + defer m.Unlock() + return m.permanent +} + func (m *mapping) InternalAddr() ma.Multiaddr { m.Lock() defer m.Unlock() @@ -333,13 +346,26 @@ func (nat *NAT) NewMapping(maddr ma.Multiaddr) (Mapping, error) { func (nat *NAT) establishMapping(m *mapping) { oldport := m.ExternalPort() + if oldport != 0 && m.isPermanent() { + // mapping was already established and it is permanent + return + } + log.Debugf("Attempting port map: %s/%d", m.Protocol(), m.InternalPort()) - newport, err := nat.nat.AddPortMapping(m.Protocol(), m.InternalPort(), "http", MappingDuration) + permanent := false + + newport, err := nat.nat.AddPortMapping(m.Protocol(), m.InternalPort(), "libp2p", MappingDuration) + + if err != nil { + // Some hardware does not support mappings with timeout, so try that + newport, err = nat.nat.AddPortMapping(m.Protocol(), m.InternalPort(), "libp2p", 0) + permanent = (err == nil) + } failure := func() { m.setExternalPort(0) // clear mapping // TODO: log.Event - log.Debugf("failed to establish port mapping: %s", err) + log.Warningf("failed to establish port mapping: %s", err) nat.Notifier.notifyAll(func(n Notifiee) { n.MappingFailed(nat, m, oldport, err) }) @@ -353,6 +379,7 @@ func (nat *NAT) establishMapping(m *mapping) { return } + m.setPermanent(permanent) m.setExternalPort(newport) ext, err := m.ExternalAddr() if err != nil {