From 54d124ba466bd68a65d7cadd2bb419ede24baed0 Mon Sep 17 00:00:00 2001 From: Csaba Kiraly Date: Thu, 3 Apr 2025 13:48:49 +0200 Subject: [PATCH] p2p/nat: retry UPnP mapping several times Changing ENR is a bit disruptive, so we better retry a few times. Signed-off-by: Csaba Kiraly --- p2p/nat/natupnp.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/p2p/nat/natupnp.go b/p2p/nat/natupnp.go index eb3d15c6b0..aa060d3335 100644 --- a/p2p/nat/natupnp.go +++ b/p2p/nat/natupnp.go @@ -35,6 +35,9 @@ import ( const ( soapRequestTimeout = 3 * time.Second rateLimit = 200 * time.Millisecond + retryInterval = 1 * time.Second // time to wait between retries + retryCount = 3 // number of retries after a failed AddPortMapping + randomCount = 3 // number of random ports to try ) type upnp struct { @@ -115,21 +118,26 @@ func (n *upnp) addAnyPortMapping(protocol string, extport, intport int, ip net.I return client.AddAnyPortMapping("", uint16(extport), protocol, uint16(intport), ip.String(), true, desc, lifetimeS) } // For IGDv1 and v1 services we should first try to add with extport. - err := n.client.AddPortMapping("", uint16(extport), protocol, uint16(intport), ip.String(), true, desc, lifetimeS) - if err == nil { - return uint16(extport), nil - } - log.Trace("Failed to add port mapping", "protocol", protocol, "extport", extport, "intport", intport, "err", err) - - // If above fails, we retry with a random port. - // We retry several times because of possible port conflicts. - for i := 0; i < 3; i++ { - extport = n.randomPort() + for i := 0; i < retryCount+1; i++ { err := n.client.AddPortMapping("", uint16(extport), protocol, uint16(intport), ip.String(), true, desc, lifetimeS) if err == nil { return uint16(extport), nil } + log.Trace("Failed to add port mapping", "protocol", protocol, "extport", extport, "intport", intport, "err", err) + time.Sleep(retryInterval) + } + + // If above fails, we retry with a random port. + // We retry several times because of possible port conflicts. + var err error + for i := 0; i < randomCount; i++ { + extport = n.randomPort() + err = n.client.AddPortMapping("", uint16(extport), protocol, uint16(intport), ip.String(), true, desc, lifetimeS) + if err == nil { + return uint16(extport), nil + } log.Trace("Failed to add random port mapping", "protocol", protocol, "extport", extport, "intport", intport, "err", err) + time.Sleep(retryInterval) } return 0, err }