code: func (s *Service) tryNATDevice(natd Device, intPort, extPort int, leaseTime time.Duration) (Address, error) {
  	var err error
  	var port int
  
  	// Generate a predictable random which is based on device ID + local port + hash of the device ID
  	// number so that the ports we'd try to acquire for the mapping would always be the same for the
  	// same device trying to get the same internal port.
  	predictableRand := rand.New(rand.NewSource(int64(s.id.Short()) + int64(intPort) + hash(natd.ID())))
  
  	if extPort != 0 {
  		// First try renewing our existing mapping, if we have one.
  		name := fmt.Sprintf("syncthing-%d", extPort)
  		port, err = natd.AddPortMapping(TCP, intPort, extPort, name, leaseTime)
  		if err == nil {
  			extPort = port
  			goto findIP
  		}
  		l.Debugln("Error extending lease on", natd.ID(), err)
  	}
  
  	for i := 0; i < 10; i++ {
  		// Then try up to ten random ports.
  		extPort = 1024 + predictableRand.Intn(65535-1024)
  		name := fmt.Sprintf("syncthing-%d", extPort)
  		port, err = natd.AddPortMapping(TCP, intPort, extPort, name, leaseTime)
  		if err == nil {
  			extPort = port
  			goto findIP
  		}
  		l.Debugln("Error getting new lease on", natd.ID(), err)
  	}
  
  	return Address{}, err
  
  findIP:
  	ip, err := natd.GetExternalIPAddress()
  	if err != nil {
  		l.Debugln("Error getting external ip on", natd.ID(), err)
  		ip = nil
  	}
  	return Address{
  		IP:   ip,
  		Port: extPort,
  	}, nil
  }
docs: // tryNATDevice tries to acquire a port mapping for the given internal address to
  // the given external port. If external port is 0, picks a pseudo-random port.