Fixes #9 - reacquire previously discovered device by URL.

Some more changes will be required for this to be supported by the dcps
packages.
This commit is contained in:
John Beisley 2015-06-06 11:01:33 +01:00
parent 5cff77a69f
commit 9e7590f139
3 changed files with 67 additions and 19 deletions

View File

@ -2,6 +2,7 @@ package example_test
import ( import (
"fmt" "fmt"
"net/url"
"os" "os"
"github.com/huin/goupnp" "github.com/huin/goupnp"
@ -60,3 +61,33 @@ func DisplayExternalIPResults(clients []GetExternalIPAddresser, errors []error,
} }
} }
} }
func Example_ReuseDiscoveredDevice() {
var allMaybeRootDevices []goupnp.MaybeRootDevice
for _, urn := range []string{internetgateway1.URN_WANPPPConnection_1, internetgateway1.URN_WANIPConnection_1} {
maybeRootDevices, err := goupnp.DiscoverDevices(internetgateway1.URN_WANPPPConnection_1)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not discover %s devices: %v\n", urn, err)
}
allMaybeRootDevices = append(allMaybeRootDevices, maybeRootDevices...)
}
locations := make([]*url.URL, 0, len(allMaybeRootDevices))
fmt.Fprintf(os.Stderr, "Found %d devices:\n", len(allMaybeRootDevices))
for _, maybeRootDevice := range allMaybeRootDevices {
if maybeRootDevice.Err != nil {
fmt.Fprintln(os.Stderr, " Failed to probe device at ", maybeRootDevice.Location.String())
} else {
locations = append(locations, maybeRootDevice.Location)
fmt.Fprintln(os.Stderr, " Successfully probed device at ", maybeRootDevice.Location.String())
}
}
fmt.Fprintf(os.Stderr, "Attempt to re-acquire %d devices:\n", len(locations))
for _, location := range locations {
if _, err := goupnp.DeviceByURL(location); err != nil {
fmt.Fprintf(os.Stderr, " Failed to reacquire device at %s: %v\n", location.String(), err)
} else {
fmt.Fprintf(os.Stderr, " Successfully reacquired device at %s\n", location.String())
}
}
// Output:
}

View File

@ -20,6 +20,7 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"time" "time"
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
"github.com/huin/goupnp/httpu" "github.com/huin/goupnp/httpu"
@ -36,10 +37,18 @@ func (err ContextError) Error() string {
return fmt.Sprintf("%s: %v", err.Context, err.Err) return fmt.Sprintf("%s: %v", err.Context, err.Err)
} }
// MaybeRootDevice contains either a RootDevice or an error. // MaybeRootDevice contains either a RootDevice (and URL) or an error.
type MaybeRootDevice struct { type MaybeRootDevice struct {
// Set iff Err == nil.
Root *RootDevice Root *RootDevice
Err error
// The location the device was discovered at. This can be used with
// DeviceByURL, assuming the device is still present. A location represents
// the discovery of a device, regardless of if there was an error probing it.
Location *url.URL
// Any error encountered probing a discovered device.
Err error
} }
// DiscoverDevices attempts to find targets of the given type. This is // DiscoverDevices attempts to find targets of the given type. This is
@ -67,30 +76,37 @@ func DiscoverDevices(searchTarget string) ([]MaybeRootDevice, error) {
maybe.Err = ContextError{"unexpected bad location from search", err} maybe.Err = ContextError{"unexpected bad location from search", err}
continue continue
} }
locStr := loc.String() maybe.Location = loc
root := new(RootDevice) if root, err := DeviceByURL(loc); err != nil {
if err := requestXml(locStr, DeviceXMLNamespace, root); err != nil { maybe.Err = err
maybe.Err = ContextError{fmt.Sprintf("error requesting root device details from %q", locStr), err}
continue
}
var urlBaseStr string
if root.URLBaseStr != "" {
urlBaseStr = root.URLBaseStr
} else { } else {
urlBaseStr = locStr maybe.Root = root
} }
urlBase, err := url.Parse(urlBaseStr)
if err != nil {
maybe.Err = ContextError{fmt.Sprintf("error parsing location URL %q", locStr), err}
continue
}
root.SetURLBase(urlBase)
maybe.Root = root
} }
return results, nil return results, nil
} }
func DeviceByURL(loc *url.URL) (*RootDevice, error) {
locStr := loc.String()
root := new(RootDevice)
if err := requestXml(locStr, DeviceXMLNamespace, root); err != nil {
return nil, ContextError{fmt.Sprintf("error requesting root device details from %q", locStr), err}
}
var urlBaseStr string
if root.URLBaseStr != "" {
urlBaseStr = root.URLBaseStr
} else {
urlBaseStr = locStr
}
urlBase, err := url.Parse(urlBaseStr)
if err != nil {
return nil, ContextError{fmt.Sprintf("error parsing location URL %q", locStr), err}
}
root.SetURLBase(urlBase)
return root, nil
}
func requestXml(url string, defaultSpace string, doc interface{}) error { func requestXml(url string, defaultSpace string, doc interface{}) error {
timeout := time.Duration(3 * time.Second) timeout := time.Duration(3 * time.Second)
client := http.Client{ client := http.Client{

View File

@ -2,6 +2,7 @@ package goupnp
import ( import (
"fmt" "fmt"
"github.com/huin/goupnp/soap" "github.com/huin/goupnp/soap"
) )