Browse Source

Make UPnP timeout configurable

Audrius Butkevicius 10 years ago
parent
commit
d148cd8ccc

+ 4 - 2
cmd/syncthing/main.go

@@ -727,7 +727,7 @@ func setupUPnP() {
 		} else {
 			// Set up incoming port forwarding, if necessary and possible
 			port, _ := strconv.Atoi(portStr)
-			igds := upnp.Discover()
+			igds := upnp.Discover(time.Duration(cfg.Options().UPnPTimeoutS) * time.Second)
 			if len(igds) > 0 {
 				// Configure the first discovered IGD only. This is a work-around until we have a better mechanism
 				// for handling multiple IGDs, which will require changes to the global discovery service
@@ -769,13 +769,15 @@ func renewUPnP(port int) {
 	for {
 		opts := cfg.Options()
 		time.Sleep(time.Duration(opts.UPnPRenewal) * time.Minute)
+		// Some values might have changed while we were sleeping
+		opts = cfg.Options()
 
 		// Make sure our IGD reference isn't nil
 		if igd == nil {
 			if debugNet {
 				l.Debugln("Undefined IGD during UPnP port renewal. Re-discovering...")
 			}
-			igds := upnp.Discover()
+			igds := upnp.Discover(time.Duration(opts.UPnPTimeoutS) * time.Second)
 			if len(igds) > 0 {
 				// Configure the first discovered IGD only. This is a work-around until we have a better mechanism
 				// for handling multiple IGDs, which will require changes to the global discovery service

+ 1 - 0
internal/config/config.go

@@ -229,6 +229,7 @@ type OptionsConfiguration struct {
 	UPnPEnabled             bool     `xml:"upnpEnabled" json:"upnpEnabled" default:"true"`
 	UPnPLease               int      `xml:"upnpLeaseMinutes" json:"upnpLeaseMinutes" default:"0"`
 	UPnPRenewal             int      `xml:"upnpRenewalMinutes" json:"upnpRenewalMinutes" default:"30"`
+	UPnPTimeoutS            int      `xml:"upnpTimeoutSeconds" json:"upnpTimeoutSeconds" default:"3"`
 	URAccepted              int      `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently)
 	URUniqueID              string   `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on.
 	RestartOnWakeup         bool     `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true"`

+ 2 - 0
internal/config/config_test.go

@@ -44,6 +44,7 @@ func TestDefaultValues(t *testing.T) {
 		UPnPEnabled:             true,
 		UPnPLease:               0,
 		UPnPRenewal:             30,
+		UPnPTimeoutS:            3,
 		RestartOnWakeup:         true,
 		AutoUpgradeIntervalH:    12,
 		KeepTemporariesH:        24,
@@ -149,6 +150,7 @@ func TestOverriddenValues(t *testing.T) {
 		UPnPEnabled:             false,
 		UPnPLease:               60,
 		UPnPRenewal:             15,
+		UPnPTimeoutS:            15,
 		RestartOnWakeup:         false,
 		AutoUpgradeIntervalH:    24,
 		KeepTemporariesH:        48,

+ 1 - 0
internal/config/testdata/overridenvalues.xml

@@ -15,6 +15,7 @@
         <upnpEnabled>false</upnpEnabled>
         <upnpLeaseMinutes>60</upnpLeaseMinutes>
         <upnpRenewalMinutes>15</upnpRenewalMinutes>
+        <upnpTimeoutSeconds>15</upnpTimeoutSeconds>
         <restartOnWakeup>false</restartOnWakeup>
         <autoUpgradeIntervalH>24</autoUpgradeIntervalH>
         <keepTemporariesH>48</keepTemporariesH>

+ 4 - 6
internal/upnp/upnp.go

@@ -92,12 +92,10 @@ type upnpRoot struct {
 
 // Discover discovers UPnP InternetGatewayDevices.
 // The order in which the devices appear in the result list is not deterministic.
-func Discover() []IGD {
+func Discover(timeout time.Duration) []IGD {
 	var result []IGD
 	l.Infoln("Starting UPnP discovery...")
 
-	timeout := 3
-
 	// Search for InternetGatewayDevice:2 devices
 	result = append(result, discover("urn:schemas-upnp-org:device:InternetGatewayDevice:2", timeout, result)...)
 
@@ -128,7 +126,7 @@ func Discover() []IGD {
 
 // Search for UPnP InternetGatewayDevices for <timeout> seconds, ignoring responses from any devices listed in knownDevices.
 // The order in which the devices appear in the result list is not deterministic
-func discover(deviceType string, timeout int, knownDevices []IGD) []IGD {
+func discover(deviceType string, timeout time.Duration, knownDevices []IGD) []IGD {
 	ssdp := &net.UDPAddr{IP: []byte{239, 255, 255, 250}, Port: 1900}
 
 	tpl := `M-SEARCH * HTTP/1.1
@@ -138,7 +136,7 @@ Man: "ssdp:discover"
 Mx: %d
 
 `
-	searchStr := fmt.Sprintf(tpl, deviceType, timeout)
+	searchStr := fmt.Sprintf(tpl, deviceType, timeout/time.Second)
 
 	search := []byte(strings.Replace(searchStr, "\n", "\r\n", -1))
 
@@ -156,7 +154,7 @@ Mx: %d
 	}
 	defer socket.Close() // Make sure our socket gets closed
 
-	err = socket.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
+	err = socket.SetDeadline(time.Now().Add(timeout))
 	if err != nil {
 		l.Infoln(err)
 		return results