check failed port mapping

handle failed mapping

set retry to 20
This commit is contained in:
Hongbo Zhang 2020-06-14 16:08:09 -04:00
parent 3cfba77c70
commit fb51e6a443
3 changed files with 59 additions and 62 deletions

View File

@ -40,10 +40,6 @@ func main() {
defer log.StopOnPanic()
defer Config.DB.Close()
if Config.StakingIP.IsZero() {
log.Warn("NAT traversal has failed. It will be able to connect to less nodes.")
}
// Track if sybil control is enforced
if !Config.EnableStaking && Config.EnableP2PTLS {
log.Warn("Staking is disabled. Sybil control is not enforced.")
@ -72,7 +68,10 @@ func main() {
defer mapper.UnmapAllPorts()
Config.StakingIP.Port = mapper.Map("TCP", Config.StakingLocalPort, Config.StakingIP.Port, "gecko")
Config.HTTPPort = mapper.Map("TCP", Config.HTTPPort, Config.HTTPPort, "gecko http")
if Config.StakingIP.IsZero() {
log.Warn("NAT traversal has failed. It will be able to connect to less nodes.")
}
node := node.Node{}

View File

@ -16,10 +16,10 @@ const (
)
type NATRouter interface {
MapPort(protocol string, intport, extport uint16, desc string, duration time.Duration) error
UnmapPort(protocol string, extport uint16) error
MapPort(protocol string, intPort, extPort uint16, desc string, duration time.Duration) error
UnmapPort(protocol string, extPort uint16) error
ExternalIP() (net.IP, error)
GetPortMappingEntry(extport uint16, protocol string) (
GetPortMappingEntry(extPort uint16, protocol string) (
InternalIP string,
InternalPort uint16,
Description string,
@ -56,11 +56,10 @@ func NewPortMapper(log logging.Logger, r NATRouter) Mapper {
// Map sets up port mapping using given protocol, internal and external ports
// and returns the final port mapped. It returns 0 if mapping failed after the
// maximun number of retries
func (dev *Mapper) Map(protocol string, intport, extport uint16, desc string) uint16 {
func (dev *Mapper) Map(protocol string, intPort, extPort uint16, desc string) uint16 {
mappedPort := make(chan uint16)
dev.wg.Add(1)
go dev.keepPortMapping(mappedPort, protocol, intport, extport, desc)
go dev.keepPortMapping(mappedPort, protocol, intPort, extPort, desc)
return <-mappedPort
}
@ -68,66 +67,65 @@ func (dev *Mapper) Map(protocol string, intport, extport uint16, desc string) ui
// keepPortMapping runs in the background to keep a port mapped. It renews the
// the port mapping in mapUpdateTimeout.
func (dev *Mapper) keepPortMapping(mappedPort chan<- uint16, protocol string,
intport, extport uint16, desc string) {
intPort, extPort uint16, desc string) {
updateTimer := time.NewTimer(mapUpdateTimeout)
var port uint16 = 0
defer func() {
updateTimer.Stop()
dev.log.Info("Unmap protocol %s external port %d", protocol, port)
if port > 0 {
dev.errLock.Lock()
dev.errs.Add(dev.r.UnmapPort(protocol, port))
dev.errLock.Unlock()
}
dev.wg.Done()
}()
for i := 0; i < maxRetries; i++ {
port = extport + uint16(i)
if intaddr, intport, desc, err := dev.r.GetPortMappingEntry(port, protocol); err == nil {
for i := 0; i <= maxRetries; i++ {
port := extPort + uint16(i)
if intaddr, intPort, desc, err := dev.r.GetPortMappingEntry(port, protocol); err == nil {
dev.log.Info("Port %d is mapped to %s:%d: %s, retry with the next port",
port, intaddr, intport, desc)
port, intaddr, intPort, desc)
port = 0
continue
}
if err := dev.r.MapPort(protocol, intport, port, desc, mapTimeout); err != nil {
if err := dev.r.MapPort(protocol, intPort, port, desc, mapTimeout); err != nil {
dev.log.Error("Map port failed. Protocol %s Internal %d External %d. %s",
protocol, intport, port, err)
protocol, intPort, port, err)
dev.errLock.Lock()
dev.errs.Add(err)
dev.errLock.Unlock()
} else {
dev.log.Info("Mapped Protocol %s Internal %d External %d.", protocol,
intport, port)
intPort, port)
mappedPort <- port
dev.wg.Add(1)
defer func(port uint16) {
updateTimer.Stop()
dev.log.Info("Unmap protocol %s external port %d", protocol, port)
if port > 0 {
dev.errLock.Lock()
dev.errs.Add(dev.r.UnmapPort(protocol, port))
dev.errLock.Unlock()
}
dev.wg.Done()
}(port)
for {
select {
case <-updateTimer.C:
if err := dev.r.MapPort(protocol, intPort, port, desc, mapTimeout); err != nil {
dev.log.Error("Renew port mapping failed. Protocol %s Internal %d External %d. %s",
protocol, intPort, port, err)
} else {
dev.log.Info("Renew port mapping Protocol %s Internal %d External %d.", protocol,
intPort, port)
}
updateTimer.Reset(mapUpdateTimeout)
case _, _ = <-dev.closer:
return
}
}
break
}
}
if port == 0 {
dev.log.Error("Unable to map port %d", extport)
mappedPort <- port
return
}
for {
select {
case <-updateTimer.C:
if err := dev.r.MapPort(protocol, intport, port, desc, mapTimeout); err != nil {
dev.log.Error("Renew port mapping failed. Protocol %s Internal %d External %d. %s",
protocol, intport, port, err)
} else {
dev.log.Info("Renew port mapping Protocol %s Internal %d External %d.", protocol,
intport, port)
}
updateTimer.Reset(mapUpdateTimeout)
case _, _ = <-dev.closer:
return
}
}
dev.log.Warn("Unable to map port %d~%d", extPort, extPort+maxRetries)
mappedPort <- 0
}
func (dev *Mapper) UnmapAllPorts() error {

View File

@ -107,7 +107,7 @@ func (r *upnpRouter) ExternalIP() (net.IP, error) {
return ip, nil
}
func (r *upnpRouter) MapPort(protocol string, intport, extport uint16,
func (r *upnpRouter) MapPort(protocol string, intPort, extPort uint16,
desc string, duration time.Duration) error {
ip, err := r.localIP()
if err != nil {
@ -115,17 +115,17 @@ func (r *upnpRouter) MapPort(protocol string, intport, extport uint16,
}
lifetime := uint32(duration / time.Second)
return r.client.AddPortMapping("", extport, protocol, intport,
return r.client.AddPortMapping("", extPort, protocol, intPort,
ip.String(), true, desc, lifetime)
}
func (r *upnpRouter) UnmapPort(protocol string, extport uint16) error {
return r.client.DeletePortMapping("", extport, protocol)
func (r *upnpRouter) UnmapPort(protocol string, extPort uint16) error {
return r.client.DeletePortMapping("", extPort, protocol)
}
func (r *upnpRouter) GetPortMappingEntry(extport uint16, protocol string) (string, uint16, string, error) {
intport, intaddr, _, desc, _, err := r.client.GetSpecificPortMappingEntry("", extport, protocol)
return intaddr, intport, desc, err
func (r *upnpRouter) GetPortMappingEntry(extPort uint16, protocol string) (string, uint16, string, error) {
intPort, intAddr, _, desc, _, err := r.client.GetSpecificPortMappingEntry("", extPort, protocol)
return intAddr, intPort, desc, err
}
// create UPnP SOAP service client with URN