diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/changelog golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/changelog --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/changelog 2016-10-30 14:37:38.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/changelog 2017-10-31 22:51:34.000000000 +0000 @@ -1,3 +1,11 @@ +golang-github-nebulouslabs-go-upnp (0.0~git20171003.0.1be4557-1) unstable; urgency=medium + + * New upstream version 0.0~git20171003.0.1be4557 + * Change priority to optional + * Bump standards-version to 4.1.1 + + -- Free Ekanayaka Tue, 31 Oct 2017 22:51:34 +0000 + golang-github-nebulouslabs-go-upnp (0.0~git20160920.0.73e8530-1) unstable; urgency=medium * Initial release (Closes: #852107) diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/control golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/control --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/control 2016-10-30 14:37:38.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/control 2017-10-31 22:51:34.000000000 +0000 @@ -1,14 +1,16 @@ Source: golang-github-nebulouslabs-go-upnp Section: devel -Priority: extra +Priority: optional Maintainer: Debian Go Packaging Team Uploaders: Free Ekanayaka Build-Depends: debhelper (>= 9), dh-golang, golang-go, golang-golang-x-net-dev, - golang-github-huin-goupnp-dev -Standards-Version: 3.9.8 + golang-github-huin-goupnp-dev, + golang-github-nebulouslabs-fastrand-dev, + golang-github-dchest-blake2b-dev +Standards-Version: 4.1.1 Homepage: https://github.com/nebulouslabs/go-upnp Vcs-Browser: https://anonscm.debian.org/cgit/pkg-go/packages/golang-github-nebulouslabs-go-upnp.git Vcs-Git: https://anonscm.debian.org/git/pkg-go/packages/golang-github-nebulouslabs-go-upnp.git diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/patches/0001-local-randintn.patch golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/patches/0001-local-randintn.patch --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/patches/0001-local-randintn.patch 2016-10-30 14:37:38.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/patches/0001-local-randintn.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -From: Free Ekanayaka -Date: Sun, 30 Oct 2016 14:51:23 +0000 -Subject: local-randintn - -Get rid of the circular dependency with Sia/crypto by inlining the -definition of randintn. ---- - upnp.go | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/upnp.go b/upnp.go -index 63c065a..d9ba715 100644 ---- a/upnp.go -+++ b/upnp.go -@@ -26,16 +26,24 @@ - package upnp - - import ( -+ "crypto/rand" - "errors" -+ "math/big" - "net" - "net/url" - "time" - -- "github.com/NebulousLabs/Sia/crypto" - "github.com/huin/goupnp" - "github.com/huin/goupnp/dcps/internetgateway1" - ) - -+// RandIntn returns a non-negative random integer in the range [0,n). It panics -+// if n <= 0. -+func RandIntn(n int) (int, error) { -+ r, err := rand.Int(rand.Reader, big.NewInt(int64(n))) -+ return int(r.Int64()), err -+} -+ - // An IGD provides an interface to the most commonly used functions of an - // Internet Gateway Device: discovering the external IP, and forwarding ports. - type IGD struct { -@@ -124,7 +132,7 @@ func (d *IGD) getInternalIP() (string, error) { - // subnet as the user? - func Discover() (*IGD, error) { - maxTries := 3 -- sleepMs, _ := crypto.RandIntn(5000) -+ sleepMs, _ := RandIntn(5000) - for try := 0; try < maxTries; try++ { - time.Sleep(time.Millisecond * time.Duration(sleepMs)) - pppclients, _, _ := internetgateway1.NewWANPPPConnection1Clients() diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/patches/series golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/patches/series --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/debian/patches/series 2016-10-30 14:37:38.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -0001-local-randintn.patch diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/dcps/internetgateway1/internetgateway1.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/dcps/internetgateway1/internetgateway1.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/dcps/internetgateway1/internetgateway1.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/dcps/internetgateway1/internetgateway1.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,3718 @@ +// Client for UPnP Device Control Protocol Internet Gateway Device v1. +// +// This DCP is documented in detail at: http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf +// +// Typically, use one of the New* functions to create clients for services. +package internetgateway1 + +// Generated file - do not edit by hand. See README.md + +import ( + "context" + "net/url" + "time" + + "github.com/NebulousLabs/go-upnp/goupnp" + "github.com/NebulousLabs/go-upnp/goupnp/soap" +) + +// Hack to avoid Go complaining if time isn't used. +var _ time.Time + +// Device URNs: +const ( + URN_LANDevice_1 = "urn:schemas-upnp-org:device:LANDevice:1" + URN_WANConnectionDevice_1 = "urn:schemas-upnp-org:device:WANConnectionDevice:1" + URN_WANDevice_1 = "urn:schemas-upnp-org:device:WANDevice:1" +) + +// Service URNs: +const ( + URN_LANHostConfigManagement_1 = "urn:schemas-upnp-org:service:LANHostConfigManagement:1" + URN_Layer3Forwarding_1 = "urn:schemas-upnp-org:service:Layer3Forwarding:1" + URN_WANCableLinkConfig_1 = "urn:schemas-upnp-org:service:WANCableLinkConfig:1" + URN_WANCommonInterfaceConfig_1 = "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" + URN_WANDSLLinkConfig_1 = "urn:schemas-upnp-org:service:WANDSLLinkConfig:1" + URN_WANEthernetLinkConfig_1 = "urn:schemas-upnp-org:service:WANEthernetLinkConfig:1" + URN_WANIPConnection_1 = "urn:schemas-upnp-org:service:WANIPConnection:1" + URN_WANPOTSLinkConfig_1 = "urn:schemas-upnp-org:service:WANPOTSLinkConfig:1" + URN_WANPPPConnection_1 = "urn:schemas-upnp-org:service:WANPPPConnection:1" +) + +// LANHostConfigManagement1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:LANHostConfigManagement:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type LANHostConfigManagement1 struct { + goupnp.ServiceClient +} + +// NewLANHostConfigManagement1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewLANHostConfigManagement1Clients() (clients []*LANHostConfigManagement1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_LANHostConfigManagement_1); err != nil { + return + } + clients = newLANHostConfigManagement1ClientsFromGenericClients(genericClients) + return +} + +// NewLANHostConfigManagement1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewLANHostConfigManagement1ClientsByURL(loc *url.URL) ([]*LANHostConfigManagement1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_LANHostConfigManagement_1) + if err != nil { + return nil, err + } + return newLANHostConfigManagement1ClientsFromGenericClients(genericClients), nil +} + +// NewLANHostConfigManagement1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewLANHostConfigManagement1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*LANHostConfigManagement1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_LANHostConfigManagement_1) + if err != nil { + return nil, err + } + return newLANHostConfigManagement1ClientsFromGenericClients(genericClients), nil +} + +func newLANHostConfigManagement1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*LANHostConfigManagement1 { + clients := make([]*LANHostConfigManagement1, len(genericClients)) + for i := range genericClients { + clients[i] = &LANHostConfigManagement1{genericClients[i]} + } + return clients +} + +func (client *LANHostConfigManagement1) SetDHCPServerConfigurable(NewDHCPServerConfigurable bool) (err error) { + // Request structure. + request := &struct { + NewDHCPServerConfigurable string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDHCPServerConfigurable, err = soap.MarshalBoolean(NewDHCPServerConfigurable); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetDHCPServerConfigurable", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetDHCPServerConfigurable() (NewDHCPServerConfigurable bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDHCPServerConfigurable string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetDHCPServerConfigurable", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDHCPServerConfigurable, err = soap.UnmarshalBoolean(response.NewDHCPServerConfigurable); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetDHCPRelay(NewDHCPRelay bool) (err error) { + // Request structure. + request := &struct { + NewDHCPRelay string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDHCPRelay, err = soap.MarshalBoolean(NewDHCPRelay); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetDHCPRelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetDHCPRelay() (NewDHCPRelay bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDHCPRelay string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetDHCPRelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDHCPRelay, err = soap.UnmarshalBoolean(response.NewDHCPRelay); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetSubnetMask(NewSubnetMask string) (err error) { + // Request structure. + request := &struct { + NewSubnetMask string + }{} + // BEGIN Marshal arguments into request. + + if request.NewSubnetMask, err = soap.MarshalString(NewSubnetMask); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetSubnetMask", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetSubnetMask() (NewSubnetMask string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewSubnetMask string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetSubnetMask", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewSubnetMask, err = soap.UnmarshalString(response.NewSubnetMask); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetIPRouter(NewIPRouters string) (err error) { + // Request structure. + request := &struct { + NewIPRouters string + }{} + // BEGIN Marshal arguments into request. + + if request.NewIPRouters, err = soap.MarshalString(NewIPRouters); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetIPRouter", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) DeleteIPRouter(NewIPRouters string) (err error) { + // Request structure. + request := &struct { + NewIPRouters string + }{} + // BEGIN Marshal arguments into request. + + if request.NewIPRouters, err = soap.MarshalString(NewIPRouters); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "DeleteIPRouter", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetIPRoutersList() (NewIPRouters string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewIPRouters string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetIPRoutersList", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewIPRouters, err = soap.UnmarshalString(response.NewIPRouters); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetDomainName(NewDomainName string) (err error) { + // Request structure. + request := &struct { + NewDomainName string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDomainName, err = soap.MarshalString(NewDomainName); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetDomainName", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetDomainName() (NewDomainName string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDomainName string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetDomainName", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDomainName, err = soap.UnmarshalString(response.NewDomainName); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetAddressRange(NewMinAddress string, NewMaxAddress string) (err error) { + // Request structure. + request := &struct { + NewMinAddress string + + NewMaxAddress string + }{} + // BEGIN Marshal arguments into request. + + if request.NewMinAddress, err = soap.MarshalString(NewMinAddress); err != nil { + return + } + if request.NewMaxAddress, err = soap.MarshalString(NewMaxAddress); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetAddressRange", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetAddressRange() (NewMinAddress string, NewMaxAddress string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewMinAddress string + + NewMaxAddress string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetAddressRange", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewMinAddress, err = soap.UnmarshalString(response.NewMinAddress); err != nil { + return + } + if NewMaxAddress, err = soap.UnmarshalString(response.NewMaxAddress); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetReservedAddress(NewReservedAddresses string) (err error) { + // Request structure. + request := &struct { + NewReservedAddresses string + }{} + // BEGIN Marshal arguments into request. + + if request.NewReservedAddresses, err = soap.MarshalString(NewReservedAddresses); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetReservedAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) DeleteReservedAddress(NewReservedAddresses string) (err error) { + // Request structure. + request := &struct { + NewReservedAddresses string + }{} + // BEGIN Marshal arguments into request. + + if request.NewReservedAddresses, err = soap.MarshalString(NewReservedAddresses); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "DeleteReservedAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetReservedAddresses() (NewReservedAddresses string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewReservedAddresses string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetReservedAddresses", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewReservedAddresses, err = soap.UnmarshalString(response.NewReservedAddresses); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) SetDNSServer(NewDNSServers string) (err error) { + // Request structure. + request := &struct { + NewDNSServers string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDNSServers, err = soap.MarshalString(NewDNSServers); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "SetDNSServer", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) DeleteDNSServer(NewDNSServers string) (err error) { + // Request structure. + request := &struct { + NewDNSServers string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDNSServers, err = soap.MarshalString(NewDNSServers); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "DeleteDNSServer", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *LANHostConfigManagement1) GetDNSServers() (NewDNSServers string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDNSServers string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_LANHostConfigManagement_1, "GetDNSServers", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDNSServers, err = soap.UnmarshalString(response.NewDNSServers); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// Layer3Forwarding1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:Layer3Forwarding:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type Layer3Forwarding1 struct { + goupnp.ServiceClient +} + +// NewLayer3Forwarding1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewLayer3Forwarding1Clients() (clients []*Layer3Forwarding1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_Layer3Forwarding_1); err != nil { + return + } + clients = newLayer3Forwarding1ClientsFromGenericClients(genericClients) + return +} + +// NewLayer3Forwarding1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewLayer3Forwarding1ClientsByURL(loc *url.URL) ([]*Layer3Forwarding1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_Layer3Forwarding_1) + if err != nil { + return nil, err + } + return newLayer3Forwarding1ClientsFromGenericClients(genericClients), nil +} + +// NewLayer3Forwarding1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewLayer3Forwarding1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*Layer3Forwarding1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_Layer3Forwarding_1) + if err != nil { + return nil, err + } + return newLayer3Forwarding1ClientsFromGenericClients(genericClients), nil +} + +func newLayer3Forwarding1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*Layer3Forwarding1 { + clients := make([]*Layer3Forwarding1, len(genericClients)) + for i := range genericClients { + clients[i] = &Layer3Forwarding1{genericClients[i]} + } + return clients +} + +func (client *Layer3Forwarding1) SetDefaultConnectionService(NewDefaultConnectionService string) (err error) { + // Request structure. + request := &struct { + NewDefaultConnectionService string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDefaultConnectionService, err = soap.MarshalString(NewDefaultConnectionService); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_Layer3Forwarding_1, "SetDefaultConnectionService", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *Layer3Forwarding1) GetDefaultConnectionService() (NewDefaultConnectionService string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDefaultConnectionService string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_Layer3Forwarding_1, "GetDefaultConnectionService", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDefaultConnectionService, err = soap.UnmarshalString(response.NewDefaultConnectionService); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANCableLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCableLinkConfig:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANCableLinkConfig1 struct { + goupnp.ServiceClient +} + +// NewWANCableLinkConfig1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANCableLinkConfig1Clients() (clients []*WANCableLinkConfig1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_WANCableLinkConfig_1); err != nil { + return + } + clients = newWANCableLinkConfig1ClientsFromGenericClients(genericClients) + return +} + +// NewWANCableLinkConfig1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANCableLinkConfig1ClientsByURL(loc *url.URL) ([]*WANCableLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANCableLinkConfig_1) + if err != nil { + return nil, err + } + return newWANCableLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +// NewWANCableLinkConfig1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANCableLinkConfig1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANCableLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANCableLinkConfig_1) + if err != nil { + return nil, err + } + return newWANCableLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +func newWANCableLinkConfig1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANCableLinkConfig1 { + clients := make([]*WANCableLinkConfig1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANCableLinkConfig1{genericClients[i]} + } + return clients +} + +// +// Return values: +// +// * NewCableLinkConfigState: allowed values: notReady, dsSyncComplete, usParamAcquired, rangingComplete, ipComplete, todEstablished, paramTransferComplete, registrationComplete, operational, accessDenied +// +// * NewLinkType: allowed values: Ethernet +func (client *WANCableLinkConfig1) GetCableLinkConfigInfo() (NewCableLinkConfigState string, NewLinkType string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewCableLinkConfigState string + + NewLinkType string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetCableLinkConfigInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewCableLinkConfigState, err = soap.UnmarshalString(response.NewCableLinkConfigState); err != nil { + return + } + if NewLinkType, err = soap.UnmarshalString(response.NewLinkType); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetDownstreamFrequency() (NewDownstreamFrequency uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDownstreamFrequency string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetDownstreamFrequency", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDownstreamFrequency, err = soap.UnmarshalUi4(response.NewDownstreamFrequency); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewDownstreamModulation: allowed values: 64QAM, 256QAM +func (client *WANCableLinkConfig1) GetDownstreamModulation() (NewDownstreamModulation string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDownstreamModulation string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetDownstreamModulation", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDownstreamModulation, err = soap.UnmarshalString(response.NewDownstreamModulation); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetUpstreamFrequency() (NewUpstreamFrequency uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUpstreamFrequency string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetUpstreamFrequency", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUpstreamFrequency, err = soap.UnmarshalUi4(response.NewUpstreamFrequency); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewUpstreamModulation: allowed values: QPSK, 16QAM +func (client *WANCableLinkConfig1) GetUpstreamModulation() (NewUpstreamModulation string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUpstreamModulation string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetUpstreamModulation", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUpstreamModulation, err = soap.UnmarshalString(response.NewUpstreamModulation); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetUpstreamChannelID() (NewUpstreamChannelID uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUpstreamChannelID string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetUpstreamChannelID", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUpstreamChannelID, err = soap.UnmarshalUi4(response.NewUpstreamChannelID); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetUpstreamPowerLevel() (NewUpstreamPowerLevel uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUpstreamPowerLevel string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetUpstreamPowerLevel", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUpstreamPowerLevel, err = soap.UnmarshalUi4(response.NewUpstreamPowerLevel); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetBPIEncryptionEnabled() (NewBPIEncryptionEnabled bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewBPIEncryptionEnabled string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetBPIEncryptionEnabled", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewBPIEncryptionEnabled, err = soap.UnmarshalBoolean(response.NewBPIEncryptionEnabled); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetConfigFile() (NewConfigFile string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewConfigFile string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetConfigFile", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewConfigFile, err = soap.UnmarshalString(response.NewConfigFile); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCableLinkConfig1) GetTFTPServer() (NewTFTPServer string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewTFTPServer string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCableLinkConfig_1, "GetTFTPServer", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewTFTPServer, err = soap.UnmarshalString(response.NewTFTPServer); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANCommonInterfaceConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANCommonInterfaceConfig1 struct { + goupnp.ServiceClient +} + +// NewWANCommonInterfaceConfig1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANCommonInterfaceConfig1Clients() (clients []*WANCommonInterfaceConfig1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_WANCommonInterfaceConfig_1); err != nil { + return + } + clients = newWANCommonInterfaceConfig1ClientsFromGenericClients(genericClients) + return +} + +// NewWANCommonInterfaceConfig1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANCommonInterfaceConfig1ClientsByURL(loc *url.URL) ([]*WANCommonInterfaceConfig1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANCommonInterfaceConfig_1) + if err != nil { + return nil, err + } + return newWANCommonInterfaceConfig1ClientsFromGenericClients(genericClients), nil +} + +// NewWANCommonInterfaceConfig1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANCommonInterfaceConfig1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANCommonInterfaceConfig1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANCommonInterfaceConfig_1) + if err != nil { + return nil, err + } + return newWANCommonInterfaceConfig1ClientsFromGenericClients(genericClients), nil +} + +func newWANCommonInterfaceConfig1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANCommonInterfaceConfig1 { + clients := make([]*WANCommonInterfaceConfig1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANCommonInterfaceConfig1{genericClients[i]} + } + return clients +} + +func (client *WANCommonInterfaceConfig1) SetEnabledForInternet(NewEnabledForInternet bool) (err error) { + // Request structure. + request := &struct { + NewEnabledForInternet string + }{} + // BEGIN Marshal arguments into request. + + if request.NewEnabledForInternet, err = soap.MarshalBoolean(NewEnabledForInternet); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "SetEnabledForInternet", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetEnabledForInternet() (NewEnabledForInternet bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewEnabledForInternet string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetEnabledForInternet", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewEnabledForInternet, err = soap.UnmarshalBoolean(response.NewEnabledForInternet); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewWANAccessType: allowed values: DSL, POTS, Cable, Ethernet +// +// * NewPhysicalLinkStatus: allowed values: Up, Down +func (client *WANCommonInterfaceConfig1) GetCommonLinkProperties() (NewWANAccessType string, NewLayer1UpstreamMaxBitRate uint32, NewLayer1DownstreamMaxBitRate uint32, NewPhysicalLinkStatus string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewWANAccessType string + + NewLayer1UpstreamMaxBitRate string + + NewLayer1DownstreamMaxBitRate string + + NewPhysicalLinkStatus string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetCommonLinkProperties", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewWANAccessType, err = soap.UnmarshalString(response.NewWANAccessType); err != nil { + return + } + if NewLayer1UpstreamMaxBitRate, err = soap.UnmarshalUi4(response.NewLayer1UpstreamMaxBitRate); err != nil { + return + } + if NewLayer1DownstreamMaxBitRate, err = soap.UnmarshalUi4(response.NewLayer1DownstreamMaxBitRate); err != nil { + return + } + if NewPhysicalLinkStatus, err = soap.UnmarshalString(response.NewPhysicalLinkStatus); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetWANAccessProvider() (NewWANAccessProvider string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewWANAccessProvider string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetWANAccessProvider", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewWANAccessProvider, err = soap.UnmarshalString(response.NewWANAccessProvider); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewMaximumActiveConnections: allowed value range: minimum=1, step=1 +func (client *WANCommonInterfaceConfig1) GetMaximumActiveConnections() (NewMaximumActiveConnections uint16, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewMaximumActiveConnections string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetMaximumActiveConnections", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewMaximumActiveConnections, err = soap.UnmarshalUi2(response.NewMaximumActiveConnections); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetTotalBytesSent() (NewTotalBytesSent uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewTotalBytesSent string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetTotalBytesSent", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewTotalBytesSent, err = soap.UnmarshalUi4(response.NewTotalBytesSent); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetTotalBytesReceived() (NewTotalBytesReceived uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewTotalBytesReceived string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetTotalBytesReceived", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewTotalBytesReceived, err = soap.UnmarshalUi4(response.NewTotalBytesReceived); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetTotalPacketsSent() (NewTotalPacketsSent uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewTotalPacketsSent string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetTotalPacketsSent", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewTotalPacketsSent, err = soap.UnmarshalUi4(response.NewTotalPacketsSent); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetTotalPacketsReceived() (NewTotalPacketsReceived uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewTotalPacketsReceived string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetTotalPacketsReceived", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewTotalPacketsReceived, err = soap.UnmarshalUi4(response.NewTotalPacketsReceived); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANCommonInterfaceConfig1) GetActiveConnection(NewActiveConnectionIndex uint16) (NewActiveConnDeviceContainer string, NewActiveConnectionServiceID string, err error) { + // Request structure. + request := &struct { + NewActiveConnectionIndex string + }{} + // BEGIN Marshal arguments into request. + + if request.NewActiveConnectionIndex, err = soap.MarshalUi2(NewActiveConnectionIndex); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewActiveConnDeviceContainer string + + NewActiveConnectionServiceID string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANCommonInterfaceConfig_1, "GetActiveConnection", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewActiveConnDeviceContainer, err = soap.UnmarshalString(response.NewActiveConnDeviceContainer); err != nil { + return + } + if NewActiveConnectionServiceID, err = soap.UnmarshalString(response.NewActiveConnectionServiceID); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANDSLLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANDSLLinkConfig:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANDSLLinkConfig1 struct { + goupnp.ServiceClient +} + +// NewWANDSLLinkConfig1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANDSLLinkConfig1Clients() (clients []*WANDSLLinkConfig1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_WANDSLLinkConfig_1); err != nil { + return + } + clients = newWANDSLLinkConfig1ClientsFromGenericClients(genericClients) + return +} + +// NewWANDSLLinkConfig1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANDSLLinkConfig1ClientsByURL(loc *url.URL) ([]*WANDSLLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANDSLLinkConfig_1) + if err != nil { + return nil, err + } + return newWANDSLLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +// NewWANDSLLinkConfig1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANDSLLinkConfig1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANDSLLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANDSLLinkConfig_1) + if err != nil { + return nil, err + } + return newWANDSLLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +func newWANDSLLinkConfig1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANDSLLinkConfig1 { + clients := make([]*WANDSLLinkConfig1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANDSLLinkConfig1{genericClients[i]} + } + return clients +} + +func (client *WANDSLLinkConfig1) SetDSLLinkType(NewLinkType string) (err error) { + // Request structure. + request := &struct { + NewLinkType string + }{} + // BEGIN Marshal arguments into request. + + if request.NewLinkType, err = soap.MarshalString(NewLinkType); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "SetDSLLinkType", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewLinkStatus: allowed values: Up, Down +func (client *WANDSLLinkConfig1) GetDSLLinkInfo() (NewLinkType string, NewLinkStatus string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewLinkType string + + NewLinkStatus string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetDSLLinkInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewLinkType, err = soap.UnmarshalString(response.NewLinkType); err != nil { + return + } + if NewLinkStatus, err = soap.UnmarshalString(response.NewLinkStatus); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) GetAutoConfig() (NewAutoConfig bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewAutoConfig string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetAutoConfig", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewAutoConfig, err = soap.UnmarshalBoolean(response.NewAutoConfig); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) GetModulationType() (NewModulationType string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewModulationType string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetModulationType", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewModulationType, err = soap.UnmarshalString(response.NewModulationType); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) SetDestinationAddress(NewDestinationAddress string) (err error) { + // Request structure. + request := &struct { + NewDestinationAddress string + }{} + // BEGIN Marshal arguments into request. + + if request.NewDestinationAddress, err = soap.MarshalString(NewDestinationAddress); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "SetDestinationAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) GetDestinationAddress() (NewDestinationAddress string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDestinationAddress string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetDestinationAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDestinationAddress, err = soap.UnmarshalString(response.NewDestinationAddress); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) SetATMEncapsulation(NewATMEncapsulation string) (err error) { + // Request structure. + request := &struct { + NewATMEncapsulation string + }{} + // BEGIN Marshal arguments into request. + + if request.NewATMEncapsulation, err = soap.MarshalString(NewATMEncapsulation); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "SetATMEncapsulation", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) GetATMEncapsulation() (NewATMEncapsulation string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewATMEncapsulation string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetATMEncapsulation", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewATMEncapsulation, err = soap.UnmarshalString(response.NewATMEncapsulation); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) SetFCSPreserved(NewFCSPreserved bool) (err error) { + // Request structure. + request := &struct { + NewFCSPreserved string + }{} + // BEGIN Marshal arguments into request. + + if request.NewFCSPreserved, err = soap.MarshalBoolean(NewFCSPreserved); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "SetFCSPreserved", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANDSLLinkConfig1) GetFCSPreserved() (NewFCSPreserved bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewFCSPreserved string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANDSLLinkConfig_1, "GetFCSPreserved", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewFCSPreserved, err = soap.UnmarshalBoolean(response.NewFCSPreserved); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANEthernetLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANEthernetLinkConfig:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANEthernetLinkConfig1 struct { + goupnp.ServiceClient +} + +// NewWANEthernetLinkConfig1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANEthernetLinkConfig1Clients() (clients []*WANEthernetLinkConfig1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_WANEthernetLinkConfig_1); err != nil { + return + } + clients = newWANEthernetLinkConfig1ClientsFromGenericClients(genericClients) + return +} + +// NewWANEthernetLinkConfig1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANEthernetLinkConfig1ClientsByURL(loc *url.URL) ([]*WANEthernetLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANEthernetLinkConfig_1) + if err != nil { + return nil, err + } + return newWANEthernetLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +// NewWANEthernetLinkConfig1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANEthernetLinkConfig1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANEthernetLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANEthernetLinkConfig_1) + if err != nil { + return nil, err + } + return newWANEthernetLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +func newWANEthernetLinkConfig1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANEthernetLinkConfig1 { + clients := make([]*WANEthernetLinkConfig1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANEthernetLinkConfig1{genericClients[i]} + } + return clients +} + +// +// Return values: +// +// * NewEthernetLinkStatus: allowed values: Up, Down +func (client *WANEthernetLinkConfig1) GetEthernetLinkStatus() (NewEthernetLinkStatus string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewEthernetLinkStatus string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANEthernetLinkConfig_1, "GetEthernetLinkStatus", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewEthernetLinkStatus, err = soap.UnmarshalString(response.NewEthernetLinkStatus); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANIPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANIPConnection:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANIPConnection1 struct { + goupnp.ServiceClient +} + +// NewWANIPConnection1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANIPConnection1Clients(ctx context.Context) (clients []*WANIPConnection1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClientsCtx(ctx, URN_WANIPConnection_1); err != nil { + return + } + clients = newWANIPConnection1ClientsFromGenericClients(genericClients) + return +} + +// NewWANIPConnection1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANIPConnection1ClientsByURL(loc *url.URL) ([]*WANIPConnection1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANIPConnection_1) + if err != nil { + return nil, err + } + return newWANIPConnection1ClientsFromGenericClients(genericClients), nil +} + +// NewWANIPConnection1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANIPConnection1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANIPConnection1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANIPConnection_1) + if err != nil { + return nil, err + } + return newWANIPConnection1ClientsFromGenericClients(genericClients), nil +} + +func newWANIPConnection1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANIPConnection1 { + clients := make([]*WANIPConnection1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANIPConnection1{genericClients[i]} + } + return clients +} + +func (client *WANIPConnection1) SetConnectionType(NewConnectionType string) (err error) { + // Request structure. + request := &struct { + NewConnectionType string + }{} + // BEGIN Marshal arguments into request. + + if request.NewConnectionType, err = soap.MarshalString(NewConnectionType); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "SetConnectionType", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewPossibleConnectionTypes: allowed values: Unconfigured, IP_Routed, IP_Bridged +func (client *WANIPConnection1) GetConnectionTypeInfo() (NewConnectionType string, NewPossibleConnectionTypes string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewConnectionType string + + NewPossibleConnectionTypes string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetConnectionTypeInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewConnectionType, err = soap.UnmarshalString(response.NewConnectionType); err != nil { + return + } + if NewPossibleConnectionTypes, err = soap.UnmarshalString(response.NewPossibleConnectionTypes); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) RequestConnection() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "RequestConnection", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) RequestTermination() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "RequestTermination", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) ForceTermination() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "ForceTermination", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) SetAutoDisconnectTime(NewAutoDisconnectTime uint32) (err error) { + // Request structure. + request := &struct { + NewAutoDisconnectTime string + }{} + // BEGIN Marshal arguments into request. + + if request.NewAutoDisconnectTime, err = soap.MarshalUi4(NewAutoDisconnectTime); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "SetAutoDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) SetIdleDisconnectTime(NewIdleDisconnectTime uint32) (err error) { + // Request structure. + request := &struct { + NewIdleDisconnectTime string + }{} + // BEGIN Marshal arguments into request. + + if request.NewIdleDisconnectTime, err = soap.MarshalUi4(NewIdleDisconnectTime); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "SetIdleDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) SetWarnDisconnectDelay(NewWarnDisconnectDelay uint32) (err error) { + // Request structure. + request := &struct { + NewWarnDisconnectDelay string + }{} + // BEGIN Marshal arguments into request. + + if request.NewWarnDisconnectDelay, err = soap.MarshalUi4(NewWarnDisconnectDelay); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "SetWarnDisconnectDelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewConnectionStatus: allowed values: Unconfigured, Connected, Disconnected +// +// * NewLastConnectionError: allowed values: ERROR_NONE +func (client *WANIPConnection1) GetStatusInfo() (NewConnectionStatus string, NewLastConnectionError string, NewUptime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewConnectionStatus string + + NewLastConnectionError string + + NewUptime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetStatusInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewConnectionStatus, err = soap.UnmarshalString(response.NewConnectionStatus); err != nil { + return + } + if NewLastConnectionError, err = soap.UnmarshalString(response.NewLastConnectionError); err != nil { + return + } + if NewUptime, err = soap.UnmarshalUi4(response.NewUptime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) GetAutoDisconnectTime() (NewAutoDisconnectTime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewAutoDisconnectTime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetAutoDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewAutoDisconnectTime, err = soap.UnmarshalUi4(response.NewAutoDisconnectTime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) GetIdleDisconnectTime() (NewIdleDisconnectTime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewIdleDisconnectTime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetIdleDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewIdleDisconnectTime, err = soap.UnmarshalUi4(response.NewIdleDisconnectTime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) GetWarnDisconnectDelay() (NewWarnDisconnectDelay uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewWarnDisconnectDelay string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetWarnDisconnectDelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewWarnDisconnectDelay, err = soap.UnmarshalUi4(response.NewWarnDisconnectDelay); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewNATEnabled bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewRSIPAvailable string + + NewNATEnabled string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetNATRSIPStatus", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewRSIPAvailable, err = soap.UnmarshalBoolean(response.NewRSIPAvailable); err != nil { + return + } + if NewNATEnabled, err = soap.UnmarshalBoolean(response.NewNATEnabled); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewProtocol: allowed values: TCP, UDP +func (client *WANIPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex uint16) (NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { + // Request structure. + request := &struct { + NewPortMappingIndex string + }{} + // BEGIN Marshal arguments into request. + + if request.NewPortMappingIndex, err = soap.MarshalUi2(NewPortMappingIndex); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetGenericPortMappingEntry", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewRemoteHost, err = soap.UnmarshalString(response.NewRemoteHost); err != nil { + return + } + if NewExternalPort, err = soap.UnmarshalUi2(response.NewExternalPort); err != nil { + return + } + if NewProtocol, err = soap.UnmarshalString(response.NewProtocol); err != nil { + return + } + if NewInternalPort, err = soap.UnmarshalUi2(response.NewInternalPort); err != nil { + return + } + if NewInternalClient, err = soap.UnmarshalString(response.NewInternalClient); err != nil { + return + } + if NewEnabled, err = soap.UnmarshalBoolean(response.NewEnabled); err != nil { + return + } + if NewPortMappingDescription, err = soap.UnmarshalString(response.NewPortMappingDescription); err != nil { + return + } + if NewLeaseDuration, err = soap.UnmarshalUi4(response.NewLeaseDuration); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANIPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetSpecificPortMappingEntry", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewInternalPort, err = soap.UnmarshalUi2(response.NewInternalPort); err != nil { + return + } + if NewInternalClient, err = soap.UnmarshalString(response.NewInternalClient); err != nil { + return + } + if NewEnabled, err = soap.UnmarshalBoolean(response.NewEnabled); err != nil { + return + } + if NewPortMappingDescription, err = soap.UnmarshalString(response.NewPortMappingDescription); err != nil { + return + } + if NewLeaseDuration, err = soap.UnmarshalUi4(response.NewLeaseDuration); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANIPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + if request.NewInternalPort, err = soap.MarshalUi2(NewInternalPort); err != nil { + return + } + if request.NewInternalClient, err = soap.MarshalString(NewInternalClient); err != nil { + return + } + if request.NewEnabled, err = soap.MarshalBoolean(NewEnabled); err != nil { + return + } + if request.NewPortMappingDescription, err = soap.MarshalString(NewPortMappingDescription); err != nil { + return + } + if request.NewLeaseDuration, err = soap.MarshalUi4(NewLeaseDuration); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "AddPortMapping", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANIPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "DeletePortMapping", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANIPConnection1) GetExternalIPAddress() (NewExternalIPAddress string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewExternalIPAddress string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANIPConnection_1, "GetExternalIPAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewExternalIPAddress, err = soap.UnmarshalString(response.NewExternalIPAddress); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANPOTSLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPOTSLinkConfig:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANPOTSLinkConfig1 struct { + goupnp.ServiceClient +} + +// NewWANPOTSLinkConfig1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANPOTSLinkConfig1Clients() (clients []*WANPOTSLinkConfig1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClients(URN_WANPOTSLinkConfig_1); err != nil { + return + } + clients = newWANPOTSLinkConfig1ClientsFromGenericClients(genericClients) + return +} + +// NewWANPOTSLinkConfig1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANPOTSLinkConfig1ClientsByURL(loc *url.URL) ([]*WANPOTSLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANPOTSLinkConfig_1) + if err != nil { + return nil, err + } + return newWANPOTSLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +// NewWANPOTSLinkConfig1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANPOTSLinkConfig1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANPOTSLinkConfig1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANPOTSLinkConfig_1) + if err != nil { + return nil, err + } + return newWANPOTSLinkConfig1ClientsFromGenericClients(genericClients), nil +} + +func newWANPOTSLinkConfig1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANPOTSLinkConfig1 { + clients := make([]*WANPOTSLinkConfig1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANPOTSLinkConfig1{genericClients[i]} + } + return clients +} + +// +// Arguments: +// +// * NewLinkType: allowed values: PPP_Dialup + +func (client *WANPOTSLinkConfig1) SetISPInfo(NewISPPhoneNumber string, NewISPInfo string, NewLinkType string) (err error) { + // Request structure. + request := &struct { + NewISPPhoneNumber string + + NewISPInfo string + + NewLinkType string + }{} + // BEGIN Marshal arguments into request. + + if request.NewISPPhoneNumber, err = soap.MarshalString(NewISPPhoneNumber); err != nil { + return + } + if request.NewISPInfo, err = soap.MarshalString(NewISPInfo); err != nil { + return + } + if request.NewLinkType, err = soap.MarshalString(NewLinkType); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "SetISPInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) SetCallRetryInfo(NewNumberOfRetries uint32, NewDelayBetweenRetries uint32) (err error) { + // Request structure. + request := &struct { + NewNumberOfRetries string + + NewDelayBetweenRetries string + }{} + // BEGIN Marshal arguments into request. + + if request.NewNumberOfRetries, err = soap.MarshalUi4(NewNumberOfRetries); err != nil { + return + } + if request.NewDelayBetweenRetries, err = soap.MarshalUi4(NewDelayBetweenRetries); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "SetCallRetryInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewLinkType: allowed values: PPP_Dialup +func (client *WANPOTSLinkConfig1) GetISPInfo() (NewISPPhoneNumber string, NewISPInfo string, NewLinkType string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewISPPhoneNumber string + + NewISPInfo string + + NewLinkType string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetISPInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewISPPhoneNumber, err = soap.UnmarshalString(response.NewISPPhoneNumber); err != nil { + return + } + if NewISPInfo, err = soap.UnmarshalString(response.NewISPInfo); err != nil { + return + } + if NewLinkType, err = soap.UnmarshalString(response.NewLinkType); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetCallRetryInfo() (NewNumberOfRetries uint32, NewDelayBetweenRetries uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewNumberOfRetries string + + NewDelayBetweenRetries string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetCallRetryInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewNumberOfRetries, err = soap.UnmarshalUi4(response.NewNumberOfRetries); err != nil { + return + } + if NewDelayBetweenRetries, err = soap.UnmarshalUi4(response.NewDelayBetweenRetries); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetFclass() (NewFclass string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewFclass string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetFclass", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewFclass, err = soap.UnmarshalString(response.NewFclass); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetDataModulationSupported() (NewDataModulationSupported string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDataModulationSupported string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetDataModulationSupported", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDataModulationSupported, err = soap.UnmarshalString(response.NewDataModulationSupported); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetDataProtocol() (NewDataProtocol string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDataProtocol string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetDataProtocol", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDataProtocol, err = soap.UnmarshalString(response.NewDataProtocol); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetDataCompression() (NewDataCompression string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewDataCompression string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetDataCompression", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewDataCompression, err = soap.UnmarshalString(response.NewDataCompression); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPOTSLinkConfig1) GetPlusVTRCommandSupported() (NewPlusVTRCommandSupported bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewPlusVTRCommandSupported string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPOTSLinkConfig_1, "GetPlusVTRCommandSupported", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewPlusVTRCommandSupported, err = soap.UnmarshalBoolean(response.NewPlusVTRCommandSupported); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// WANPPPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPPPConnection:1". See +// goupnp.ServiceClient, which contains RootDevice and Service attributes which +// are provided for informational value. +type WANPPPConnection1 struct { + goupnp.ServiceClient +} + +// NewWANPPPConnection1Clients discovers instances of the service on the network, +// and returns clients to any that are found. errors will contain an error for +// any devices that replied but which could not be queried, and err will be set +// if the discovery process failed outright. +// +// This is a typical entry calling point into this package. +func NewWANPPPConnection1Clients(ctx context.Context) (clients []*WANPPPConnection1, errors []error, err error) { + var genericClients []goupnp.ServiceClient + if genericClients, errors, err = goupnp.NewServiceClientsCtx(ctx, URN_WANPPPConnection_1); err != nil { + return + } + clients = newWANPPPConnection1ClientsFromGenericClients(genericClients) + return +} + +// NewWANPPPConnection1ClientsByURL discovers instances of the service at the given +// URL, and returns clients to any that are found. An error is returned if +// there was an error probing the service. +// +// This is a typical entry calling point into this package when reusing an +// previously discovered service URL. +func NewWANPPPConnection1ClientsByURL(loc *url.URL) ([]*WANPPPConnection1, error) { + genericClients, err := goupnp.NewServiceClientsByURL(loc, URN_WANPPPConnection_1) + if err != nil { + return nil, err + } + return newWANPPPConnection1ClientsFromGenericClients(genericClients), nil +} + +// NewWANPPPConnection1ClientsFromRootDevice discovers instances of the service in +// a given root device, and returns clients to any that are found. An error is +// returned if there was not at least one instance of the service within the +// device. The location parameter is simply assigned to the Location attribute +// of the wrapped ServiceClient(s). +// +// This is a typical entry calling point into this package when reusing an +// previously discovered root device. +func NewWANPPPConnection1ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*WANPPPConnection1, error) { + genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, URN_WANPPPConnection_1) + if err != nil { + return nil, err + } + return newWANPPPConnection1ClientsFromGenericClients(genericClients), nil +} + +func newWANPPPConnection1ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*WANPPPConnection1 { + clients := make([]*WANPPPConnection1, len(genericClients)) + for i := range genericClients { + clients[i] = &WANPPPConnection1{genericClients[i]} + } + return clients +} + +func (client *WANPPPConnection1) SetConnectionType(NewConnectionType string) (err error) { + // Request structure. + request := &struct { + NewConnectionType string + }{} + // BEGIN Marshal arguments into request. + + if request.NewConnectionType, err = soap.MarshalString(NewConnectionType); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "SetConnectionType", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewPossibleConnectionTypes: allowed values: Unconfigured, IP_Routed, DHCP_Spoofed, PPPoE_Bridged, PPTP_Relay, L2TP_Relay, PPPoE_Relay +func (client *WANPPPConnection1) GetConnectionTypeInfo() (NewConnectionType string, NewPossibleConnectionTypes string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewConnectionType string + + NewPossibleConnectionTypes string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetConnectionTypeInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewConnectionType, err = soap.UnmarshalString(response.NewConnectionType); err != nil { + return + } + if NewPossibleConnectionTypes, err = soap.UnmarshalString(response.NewPossibleConnectionTypes); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) ConfigureConnection(NewUserName string, NewPassword string) (err error) { + // Request structure. + request := &struct { + NewUserName string + + NewPassword string + }{} + // BEGIN Marshal arguments into request. + + if request.NewUserName, err = soap.MarshalString(NewUserName); err != nil { + return + } + if request.NewPassword, err = soap.MarshalString(NewPassword); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "ConfigureConnection", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) RequestConnection() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "RequestConnection", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) RequestTermination() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "RequestTermination", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) ForceTermination() (err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "ForceTermination", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) SetAutoDisconnectTime(NewAutoDisconnectTime uint32) (err error) { + // Request structure. + request := &struct { + NewAutoDisconnectTime string + }{} + // BEGIN Marshal arguments into request. + + if request.NewAutoDisconnectTime, err = soap.MarshalUi4(NewAutoDisconnectTime); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "SetAutoDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) SetIdleDisconnectTime(NewIdleDisconnectTime uint32) (err error) { + // Request structure. + request := &struct { + NewIdleDisconnectTime string + }{} + // BEGIN Marshal arguments into request. + + if request.NewIdleDisconnectTime, err = soap.MarshalUi4(NewIdleDisconnectTime); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "SetIdleDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) SetWarnDisconnectDelay(NewWarnDisconnectDelay uint32) (err error) { + // Request structure. + request := &struct { + NewWarnDisconnectDelay string + }{} + // BEGIN Marshal arguments into request. + + if request.NewWarnDisconnectDelay, err = soap.MarshalUi4(NewWarnDisconnectDelay); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "SetWarnDisconnectDelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewConnectionStatus: allowed values: Unconfigured, Connected, Disconnected +// +// * NewLastConnectionError: allowed values: ERROR_NONE +func (client *WANPPPConnection1) GetStatusInfo() (NewConnectionStatus string, NewLastConnectionError string, NewUptime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewConnectionStatus string + + NewLastConnectionError string + + NewUptime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetStatusInfo", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewConnectionStatus, err = soap.UnmarshalString(response.NewConnectionStatus); err != nil { + return + } + if NewLastConnectionError, err = soap.UnmarshalString(response.NewLastConnectionError); err != nil { + return + } + if NewUptime, err = soap.UnmarshalUi4(response.NewUptime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetLinkLayerMaxBitRates() (NewUpstreamMaxBitRate uint32, NewDownstreamMaxBitRate uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUpstreamMaxBitRate string + + NewDownstreamMaxBitRate string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetLinkLayerMaxBitRates", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUpstreamMaxBitRate, err = soap.UnmarshalUi4(response.NewUpstreamMaxBitRate); err != nil { + return + } + if NewDownstreamMaxBitRate, err = soap.UnmarshalUi4(response.NewDownstreamMaxBitRate); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetPPPEncryptionProtocol() (NewPPPEncryptionProtocol string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewPPPEncryptionProtocol string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetPPPEncryptionProtocol", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewPPPEncryptionProtocol, err = soap.UnmarshalString(response.NewPPPEncryptionProtocol); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetPPPCompressionProtocol() (NewPPPCompressionProtocol string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewPPPCompressionProtocol string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetPPPCompressionProtocol", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewPPPCompressionProtocol, err = soap.UnmarshalString(response.NewPPPCompressionProtocol); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetPPPAuthenticationProtocol() (NewPPPAuthenticationProtocol string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewPPPAuthenticationProtocol string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetPPPAuthenticationProtocol", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewPPPAuthenticationProtocol, err = soap.UnmarshalString(response.NewPPPAuthenticationProtocol); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetUserName() (NewUserName string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewUserName string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetUserName", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewUserName, err = soap.UnmarshalString(response.NewUserName); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetPassword() (NewPassword string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewPassword string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetPassword", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewPassword, err = soap.UnmarshalString(response.NewPassword); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetAutoDisconnectTime() (NewAutoDisconnectTime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewAutoDisconnectTime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetAutoDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewAutoDisconnectTime, err = soap.UnmarshalUi4(response.NewAutoDisconnectTime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetIdleDisconnectTime() (NewIdleDisconnectTime uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewIdleDisconnectTime string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetIdleDisconnectTime", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewIdleDisconnectTime, err = soap.UnmarshalUi4(response.NewIdleDisconnectTime); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetWarnDisconnectDelay() (NewWarnDisconnectDelay uint32, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewWarnDisconnectDelay string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetWarnDisconnectDelay", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewWarnDisconnectDelay, err = soap.UnmarshalUi4(response.NewWarnDisconnectDelay); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetNATRSIPStatus() (NewRSIPAvailable bool, NewNATEnabled bool, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewRSIPAvailable string + + NewNATEnabled string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetNATRSIPStatus", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewRSIPAvailable, err = soap.UnmarshalBoolean(response.NewRSIPAvailable); err != nil { + return + } + if NewNATEnabled, err = soap.UnmarshalBoolean(response.NewNATEnabled); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Return values: +// +// * NewProtocol: allowed values: TCP, UDP +func (client *WANPPPConnection1) GetGenericPortMappingEntry(NewPortMappingIndex uint16) (NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { + // Request structure. + request := &struct { + NewPortMappingIndex string + }{} + // BEGIN Marshal arguments into request. + + if request.NewPortMappingIndex, err = soap.MarshalUi2(NewPortMappingIndex); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetGenericPortMappingEntry", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewRemoteHost, err = soap.UnmarshalString(response.NewRemoteHost); err != nil { + return + } + if NewExternalPort, err = soap.UnmarshalUi2(response.NewExternalPort); err != nil { + return + } + if NewProtocol, err = soap.UnmarshalString(response.NewProtocol); err != nil { + return + } + if NewInternalPort, err = soap.UnmarshalUi2(response.NewInternalPort); err != nil { + return + } + if NewInternalClient, err = soap.UnmarshalString(response.NewInternalClient); err != nil { + return + } + if NewEnabled, err = soap.UnmarshalBoolean(response.NewEnabled); err != nil { + return + } + if NewPortMappingDescription, err = soap.UnmarshalString(response.NewPortMappingDescription); err != nil { + return + } + if NewLeaseDuration, err = soap.UnmarshalUi4(response.NewLeaseDuration); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANPPPConnection1) GetSpecificPortMappingEntry(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32, err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetSpecificPortMappingEntry", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewInternalPort, err = soap.UnmarshalUi2(response.NewInternalPort); err != nil { + return + } + if NewInternalClient, err = soap.UnmarshalString(response.NewInternalClient); err != nil { + return + } + if NewEnabled, err = soap.UnmarshalBoolean(response.NewEnabled); err != nil { + return + } + if NewPortMappingDescription, err = soap.UnmarshalString(response.NewPortMappingDescription); err != nil { + return + } + if NewLeaseDuration, err = soap.UnmarshalUi4(response.NewLeaseDuration); err != nil { + return + } + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANPPPConnection1) AddPortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string, NewInternalPort uint16, NewInternalClient string, NewEnabled bool, NewPortMappingDescription string, NewLeaseDuration uint32) (err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + + NewInternalPort string + + NewInternalClient string + + NewEnabled string + + NewPortMappingDescription string + + NewLeaseDuration string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + if request.NewInternalPort, err = soap.MarshalUi2(NewInternalPort); err != nil { + return + } + if request.NewInternalClient, err = soap.MarshalString(NewInternalClient); err != nil { + return + } + if request.NewEnabled, err = soap.MarshalBoolean(NewEnabled); err != nil { + return + } + if request.NewPortMappingDescription, err = soap.MarshalString(NewPortMappingDescription); err != nil { + return + } + if request.NewLeaseDuration, err = soap.MarshalUi4(NewLeaseDuration); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "AddPortMapping", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +// +// Arguments: +// +// * NewProtocol: allowed values: TCP, UDP + +func (client *WANPPPConnection1) DeletePortMapping(NewRemoteHost string, NewExternalPort uint16, NewProtocol string) (err error) { + // Request structure. + request := &struct { + NewRemoteHost string + + NewExternalPort string + + NewProtocol string + }{} + // BEGIN Marshal arguments into request. + + if request.NewRemoteHost, err = soap.MarshalString(NewRemoteHost); err != nil { + return + } + if request.NewExternalPort, err = soap.MarshalUi2(NewExternalPort); err != nil { + return + } + if request.NewProtocol, err = soap.MarshalString(NewProtocol); err != nil { + return + } + // END Marshal arguments into request. + + // Response structure. + response := interface{}(nil) + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "DeletePortMapping", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + // END Unmarshal arguments from response. + return +} + +func (client *WANPPPConnection1) GetExternalIPAddress() (NewExternalIPAddress string, err error) { + // Request structure. + request := interface{}(nil) + // BEGIN Marshal arguments into request. + + // END Marshal arguments into request. + + // Response structure. + response := &struct { + NewExternalIPAddress string + }{} + + // Perform the SOAP call. + if err = client.SOAPClient.PerformAction(URN_WANPPPConnection_1, "GetExternalIPAddress", request, response); err != nil { + return + } + + // BEGIN Unmarshal arguments from response. + + if NewExternalIPAddress, err = soap.UnmarshalString(response.NewExternalIPAddress); err != nil { + return + } + // END Unmarshal arguments from response. + return +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/device.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/device.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/device.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/device.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,184 @@ +// This file contains XML structures for communicating with UPnP devices. + +package goupnp + +import ( + "encoding/xml" + "errors" + "fmt" + "net/url" + + "github.com/NebulousLabs/go-upnp/goupnp/scpd" + "github.com/NebulousLabs/go-upnp/goupnp/soap" +) + +const ( + DeviceXMLNamespace = "urn:schemas-upnp-org:device-1-0" +) + +// RootDevice is the device description as described by section 2.3 "Device +// description" in +// http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf +type RootDevice struct { + XMLName xml.Name `xml:"root"` + SpecVersion SpecVersion `xml:"specVersion"` + URLBase url.URL `xml:"-"` + URLBaseStr string `xml:"URLBase"` + Device Device `xml:"device"` +} + +// SetURLBase sets the URLBase for the RootDevice and its underlying components. +func (root *RootDevice) SetURLBase(urlBase *url.URL) { + root.URLBase = *urlBase + root.URLBaseStr = urlBase.String() + root.Device.SetURLBase(urlBase) +} + +// SpecVersion is part of a RootDevice, describes the version of the +// specification that the data adheres to. +type SpecVersion struct { + Major int32 `xml:"major"` + Minor int32 `xml:"minor"` +} + +// Device is a UPnP device. It can have child devices. +type Device struct { + DeviceType string `xml:"deviceType"` + FriendlyName string `xml:"friendlyName"` + Manufacturer string `xml:"manufacturer"` + ManufacturerURL URLField `xml:"manufacturerURL"` + ModelDescription string `xml:"modelDescription"` + ModelName string `xml:"modelName"` + ModelNumber string `xml:"modelNumber"` + ModelURL URLField `xml:"modelURL"` + SerialNumber string `xml:"serialNumber"` + UDN string `xml:"UDN"` + UPC string `xml:"UPC,omitempty"` + Icons []Icon `xml:"iconList>icon,omitempty"` + Services []Service `xml:"serviceList>service,omitempty"` + Devices []Device `xml:"deviceList>device,omitempty"` + + // Extra observed elements: + PresentationURL URLField `xml:"presentationURL"` +} + +// VisitDevices calls visitor for the device, and all its descendent devices. +func (device *Device) VisitDevices(visitor func(*Device)) { + visitor(device) + for i := range device.Devices { + device.Devices[i].VisitDevices(visitor) + } +} + +// VisitServices calls visitor for all Services under the device and all its +// descendent devices. +func (device *Device) VisitServices(visitor func(*Service)) { + device.VisitDevices(func(d *Device) { + for i := range d.Services { + visitor(&d.Services[i]) + } + }) +} + +// FindService finds all (if any) Services under the device and its descendents +// that have the given ServiceType. +func (device *Device) FindService(serviceType string) []*Service { + var services []*Service + device.VisitServices(func(s *Service) { + if s.ServiceType == serviceType { + services = append(services, s) + } + }) + return services +} + +// SetURLBase sets the URLBase for the Device and its underlying components. +func (device *Device) SetURLBase(urlBase *url.URL) { + device.ManufacturerURL.SetURLBase(urlBase) + device.ModelURL.SetURLBase(urlBase) + device.PresentationURL.SetURLBase(urlBase) + for i := range device.Icons { + device.Icons[i].SetURLBase(urlBase) + } + for i := range device.Services { + device.Services[i].SetURLBase(urlBase) + } + for i := range device.Devices { + device.Devices[i].SetURLBase(urlBase) + } +} + +func (device *Device) String() string { + return fmt.Sprintf("Device ID %s : %s (%s)", device.UDN, device.DeviceType, device.FriendlyName) +} + +// Icon is a representative image that a device might include in its +// description. +type Icon struct { + Mimetype string `xml:"mimetype"` + Width int32 `xml:"width"` + Height int32 `xml:"height"` + Depth int32 `xml:"depth"` + URL URLField `xml:"url"` +} + +// SetURLBase sets the URLBase for the Icon. +func (icon *Icon) SetURLBase(url *url.URL) { + icon.URL.SetURLBase(url) +} + +// Service is a service provided by a UPnP Device. +type Service struct { + ServiceType string `xml:"serviceType"` + ServiceId string `xml:"serviceId"` + SCPDURL URLField `xml:"SCPDURL"` + ControlURL URLField `xml:"controlURL"` + EventSubURL URLField `xml:"eventSubURL"` +} + +// SetURLBase sets the URLBase for the Service. +func (srv *Service) SetURLBase(urlBase *url.URL) { + srv.SCPDURL.SetURLBase(urlBase) + srv.ControlURL.SetURLBase(urlBase) + srv.EventSubURL.SetURLBase(urlBase) +} + +func (srv *Service) String() string { + return fmt.Sprintf("Service ID %s : %s", srv.ServiceId, srv.ServiceType) +} + +// RequestSCDP requests the SCPD (soap actions and state variables description) +// for the service. +func (srv *Service) RequestSCDP() (*scpd.SCPD, error) { + if !srv.SCPDURL.Ok { + return nil, errors.New("bad/missing SCPD URL, or no URLBase has been set") + } + s := new(scpd.SCPD) + if err := requestXml(srv.SCPDURL.URL.String(), scpd.SCPDXMLNamespace, s); err != nil { + return nil, err + } + return s, nil +} + +func (srv *Service) NewSOAPClient() *soap.SOAPClient { + return soap.NewSOAPClient(srv.ControlURL.URL) +} + +// URLField is a URL that is part of a device description. +type URLField struct { + URL url.URL `xml:"-"` + Ok bool `xml:"-"` + Str string `xml:",chardata"` +} + +func (uf *URLField) SetURLBase(urlBase *url.URL) { + refUrl, err := url.Parse(uf.Str) + if err != nil { + uf.URL = url.URL{} + uf.Ok = false + return + } + + uf.URL = *urlBase.ResolveReference(refUrl) + uf.Ok = true +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/goupnp.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/goupnp.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/goupnp.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/goupnp.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,137 @@ +// goupnp is an implementation of a client for various UPnP services. +// +// For most uses, it is recommended to use the code-generated packages under +// github.com/huin/goupnp/dcps. Example use is shown at +// http://godoc.org/github.com/huin/goupnp/example +// +// A commonly used client is internetgateway1.WANPPPConnection1: +// http://godoc.org/github.com/huin/goupnp/dcps/internetgateway1#WANPPPConnection1 +// +// Currently only a couple of schemas have code generated for them from the +// UPnP example XML specifications. Not all methods will work on these clients, +// because the generated stubs contain the full set of specified methods from +// the XML specifications, and the discovered services will likely support a +// subset of those methods. +package goupnp + +import ( + "context" + "encoding/xml" + "fmt" + "net/http" + "net/url" + "time" + + "github.com/NebulousLabs/go-upnp/goupnp/httpu" + "github.com/NebulousLabs/go-upnp/goupnp/ssdp" + + "golang.org/x/net/html/charset" +) + +// ContextError is an error that wraps an error with some context information. +type ContextError struct { + Context string + Err error +} + +func (err ContextError) Error() string { + return fmt.Sprintf("%s: %v", err.Context, err.Err) +} + +// MaybeRootDevice contains either a RootDevice or an error. +type MaybeRootDevice struct { + // Set iff Err == nil. + Root *RootDevice + + // 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 is deprecated. Use DiscoverDevicesCtx instead. +func DiscoverDevices(searchTarget string) ([]MaybeRootDevice, error) { + return DiscoverDevicesCtx(context.Background(), searchTarget) +} + +// DiscoverDevicesCtx attempts to find targets of the given type. This is +// typically the entry-point for this package. searchTarget is typically a URN +// in the form "urn:schemas-upnp-org:device:..." or +// "urn:schemas-upnp-org:service:...". A single error is returned for errors +// while attempting to send the query. An error or RootDevice is returned for +// each discovered RootDevice. +func DiscoverDevicesCtx(ctx context.Context, searchTarget string) ([]MaybeRootDevice, error) { + httpu, err := httpu.NewHTTPUClient() + if err != nil { + return nil, err + } + defer httpu.Close() + responses, err := ssdp.SSDPRawSearchCtx(ctx, httpu, string(searchTarget), 2, 3) + if err != nil { + return nil, err + } + + results := make([]MaybeRootDevice, len(responses)) + for i, response := range responses { + maybe := &results[i] + loc, err := response.Location() + if err != nil { + maybe.Err = ContextError{"unexpected bad location from search", err} + continue + } + maybe.Location = loc + if root, err := DeviceByURL(loc); err != nil { + maybe.Err = err + } else { + maybe.Root = root + } + } + + 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 { + timeout := time.Duration(3 * time.Second) + client := http.Client{ + Timeout: timeout, + } + resp, err := client.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + return fmt.Errorf("goupnp: got response status %s from %q", + resp.Status, url) + } + + decoder := xml.NewDecoder(resp.Body) + decoder.DefaultSpace = defaultSpace + decoder.CharsetReader = charset.NewReaderLabel + + return decoder.Decode(doc) +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/httpu/httpu.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/httpu/httpu.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/httpu/httpu.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/httpu/httpu.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,126 @@ +package httpu + +import ( + "bufio" + "bytes" + "fmt" + "net" + "net/http" + "sync" + "time" +) + +// HTTPUClient is a client for dealing with HTTPU (HTTP over UDP). Its typical +// function is for HTTPMU, and particularly SSDP. +type HTTPUClient struct { + connLock sync.Mutex // Protects use of conn. + conn net.PacketConn +} + +// NewHTTPUClient creates a new HTTPUClient, opening up a new UDP socket for the +// purpose. +func NewHTTPUClient() (*HTTPUClient, error) { + conn, err := net.ListenPacket("udp", ":0") + if err != nil { + return nil, err + } + return &HTTPUClient{conn: conn}, nil +} + +// Close shuts down the client. The client will no longer be useful following +// this. +func (httpu *HTTPUClient) Close() error { + httpu.connLock.Lock() + defer httpu.connLock.Unlock() + return httpu.conn.Close() +} + +// Do performs a request. The timeout is how long to wait for before returning +// the responses that were received. An error is only returned for failing to +// send the request. Failures in receipt simply do not add to the resulting +// responses. +// +// Note that at present only one concurrent connection will happen per +// HTTPUClient. +func (httpu *HTTPUClient) Do(req *http.Request, timeout time.Duration, numSends int) ([]*http.Response, error) { + httpu.connLock.Lock() + defer httpu.connLock.Unlock() + + // Create the request. This is a subset of what http.Request.Write does + // deliberately to avoid creating extra fields which may confuse some + // devices. + var requestBuf bytes.Buffer + method := req.Method + if method == "" { + method = "GET" + } + if _, err := fmt.Fprintf(&requestBuf, "%s %s HTTP/1.1\r\n", method, req.URL.RequestURI()); err != nil { + return nil, err + } + if err := req.Header.Write(&requestBuf); err != nil { + return nil, err + } + if _, err := requestBuf.Write([]byte{'\r', '\n'}); err != nil { + return nil, err + } + + destAddr, err := net.ResolveUDPAddr("udp", req.Host) + if err != nil { + return nil, err + } + if err = httpu.conn.SetDeadline(time.Now().Add(timeout)); err != nil { + return nil, err + } + + // Spawn cancellation goroutine + done := make(chan struct{}) + defer close(done) + go func() { + select { + case <-done: + case <-req.Context().Done(): + httpu.conn.SetDeadline(time.Unix(1, 0)) + } + }() + + // Send request. + for i := 0; i < numSends; i++ { + if n, err := httpu.conn.WriteTo(requestBuf.Bytes(), destAddr); err != nil { + return nil, err + } else if n < len(requestBuf.Bytes()) { + return nil, fmt.Errorf("httpu: wrote %d bytes rather than full %d in request", + n, len(requestBuf.Bytes())) + } + time.Sleep(5 * time.Millisecond) + } + + // Await responses until timeout. + var responses []*http.Response + responseBytes := make([]byte, 2048) + for { + // 2048 bytes should be sufficient for most networks. + n, _, err := httpu.conn.ReadFrom(responseBytes) + if err != nil { + if err, ok := err.(net.Error); ok { + if err.Timeout() { + break + } + if err.Temporary() { + // Sleep in case this is a persistent error to avoid pegging CPU until deadline. + time.Sleep(10 * time.Millisecond) + continue + } + } + return nil, err + } + + // Parse response. + response, err := http.ReadResponse(bufio.NewReader(bytes.NewBuffer(responseBytes[:n])), req) + if err != nil { + continue + } + + responses = append(responses, response) + } + return responses, err +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/httpu/serve.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/httpu/serve.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/httpu/serve.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/httpu/serve.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,106 @@ +package httpu + +import ( + "bufio" + "bytes" + "net" + "net/http" + "regexp" +) + +const ( + DefaultMaxMessageBytes = 2048 +) + +var ( + trailingWhitespaceRx = regexp.MustCompile(" +\r\n") + crlf = []byte("\r\n") +) + +// Handler is the interface by which received HTTPU messages are passed to +// handling code. +type Handler interface { + // ServeMessage is called for each HTTPU message received. peerAddr contains + // the address that the message was received from. + ServeMessage(r *http.Request) +} + +// HandlerFunc is a function-to-Handler adapter. +type HandlerFunc func(r *http.Request) + +func (f HandlerFunc) ServeMessage(r *http.Request) { + f(r) +} + +// A Server defines parameters for running an HTTPU server. +type Server struct { + Addr string // UDP address to listen on + Multicast bool // Should listen for multicast? + Interface *net.Interface // Network interface to listen on for multicast, nil for default multicast interface + Handler Handler // handler to invoke + MaxMessageBytes int // maximum number of bytes to read from a packet, DefaultMaxMessageBytes if 0 +} + +// ListenAndServe listens on the UDP network address srv.Addr. If srv.Multicast +// is true, then a multicast UDP listener will be used on srv.Interface (or +// default interface if nil). +func (srv *Server) ListenAndServe() error { + var err error + + var addr *net.UDPAddr + if addr, err = net.ResolveUDPAddr("udp", srv.Addr); err != nil { + return err + } + + var conn net.PacketConn + if srv.Multicast { + if conn, err = net.ListenMulticastUDP("udp", srv.Interface, addr); err != nil { + return err + } + } else { + if conn, err = net.ListenUDP("udp", addr); err != nil { + return err + } + } + + return srv.Serve(conn) +} + +// Serve messages received on the given packet listener to the srv.Handler. +func (srv *Server) Serve(l net.PacketConn) error { + maxMessageBytes := DefaultMaxMessageBytes + if srv.MaxMessageBytes != 0 { + maxMessageBytes = srv.MaxMessageBytes + } + for { + buf := make([]byte, maxMessageBytes) + n, peerAddr, err := l.ReadFrom(buf) + if err != nil { + return err + } + buf = buf[:n] + + go func(buf []byte, peerAddr net.Addr) { + // At least one router's UPnP implementation has added a trailing space + // after "HTTP/1.1" - trim it. + buf = trailingWhitespaceRx.ReplaceAllLiteral(buf, crlf) + + req, err := http.ReadRequest(bufio.NewReader(bytes.NewBuffer(buf))) + if err != nil { + return + } + req.RemoteAddr = peerAddr.String() + srv.Handler.ServeMessage(req) + // No need to call req.Body.Close - underlying reader is bytes.Buffer. + }(buf, peerAddr) + } +} + +// Serve messages received on the given packet listener to the given handler. +func Serve(l net.PacketConn, handler Handler) error { + srv := Server{ + Handler: handler, + MaxMessageBytes: DefaultMaxMessageBytes, + } + return srv.Serve(l) +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/LICENSE golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/LICENSE --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/LICENSE 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,23 @@ +Copyright (c) 2013, John Beisley +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/scpd/scpd.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/scpd/scpd.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/scpd/scpd.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/scpd/scpd.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,167 @@ +package scpd + +import ( + "encoding/xml" + "strings" +) + +const ( + SCPDXMLNamespace = "urn:schemas-upnp-org:service-1-0" +) + +func cleanWhitespace(s *string) { + *s = strings.TrimSpace(*s) +} + +// SCPD is the service description as described by section 2.5 "Service +// description" in +// http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf +type SCPD struct { + XMLName xml.Name `xml:"scpd"` + ConfigId string `xml:"configId,attr"` + SpecVersion SpecVersion `xml:"specVersion"` + Actions []Action `xml:"actionList>action"` + StateVariables []StateVariable `xml:"serviceStateTable>stateVariable"` +} + +// Clean attempts to remove stray whitespace etc. in the structure. It seems +// unfortunately common for stray whitespace to be present in SCPD documents, +// this method attempts to make it easy to clean them out. +func (scpd *SCPD) Clean() { + cleanWhitespace(&scpd.ConfigId) + for i := range scpd.Actions { + scpd.Actions[i].clean() + } + for i := range scpd.StateVariables { + scpd.StateVariables[i].clean() + } +} + +func (scpd *SCPD) GetStateVariable(variable string) *StateVariable { + for i := range scpd.StateVariables { + v := &scpd.StateVariables[i] + if v.Name == variable { + return v + } + } + return nil +} + +func (scpd *SCPD) GetAction(action string) *Action { + for i := range scpd.Actions { + a := &scpd.Actions[i] + if a.Name == action { + return a + } + } + return nil +} + +// SpecVersion is part of a SCPD document, describes the version of the +// specification that the data adheres to. +type SpecVersion struct { + Major int32 `xml:"major"` + Minor int32 `xml:"minor"` +} + +type Action struct { + Name string `xml:"name"` + Arguments []Argument `xml:"argumentList>argument"` +} + +func (action *Action) clean() { + cleanWhitespace(&action.Name) + for i := range action.Arguments { + action.Arguments[i].clean() + } +} + +func (action *Action) InputArguments() []*Argument { + var result []*Argument + for i := range action.Arguments { + arg := &action.Arguments[i] + if arg.IsInput() { + result = append(result, arg) + } + } + return result +} + +func (action *Action) OutputArguments() []*Argument { + var result []*Argument + for i := range action.Arguments { + arg := &action.Arguments[i] + if arg.IsOutput() { + result = append(result, arg) + } + } + return result +} + +type Argument struct { + Name string `xml:"name"` + Direction string `xml:"direction"` // in|out + RelatedStateVariable string `xml:"relatedStateVariable"` // ? + Retval string `xml:"retval"` // ? +} + +func (arg *Argument) clean() { + cleanWhitespace(&arg.Name) + cleanWhitespace(&arg.Direction) + cleanWhitespace(&arg.RelatedStateVariable) + cleanWhitespace(&arg.Retval) +} + +func (arg *Argument) IsInput() bool { + return arg.Direction == "in" +} + +func (arg *Argument) IsOutput() bool { + return arg.Direction == "out" +} + +type StateVariable struct { + Name string `xml:"name"` + SendEvents string `xml:"sendEvents,attr"` // yes|no + Multicast string `xml:"multicast,attr"` // yes|no + DataType DataType `xml:"dataType"` + DefaultValue string `xml:"defaultValue"` + AllowedValueRange *AllowedValueRange `xml:"allowedValueRange"` + AllowedValues []string `xml:"allowedValueList>allowedValue"` +} + +func (v *StateVariable) clean() { + cleanWhitespace(&v.Name) + cleanWhitespace(&v.SendEvents) + cleanWhitespace(&v.Multicast) + v.DataType.clean() + cleanWhitespace(&v.DefaultValue) + if v.AllowedValueRange != nil { + v.AllowedValueRange.clean() + } + for i := range v.AllowedValues { + cleanWhitespace(&v.AllowedValues[i]) + } +} + +type AllowedValueRange struct { + Minimum string `xml:"minimum"` + Maximum string `xml:"maximum"` + Step string `xml:"step"` +} + +func (r *AllowedValueRange) clean() { + cleanWhitespace(&r.Minimum) + cleanWhitespace(&r.Maximum) + cleanWhitespace(&r.Step) +} + +type DataType struct { + Name string `xml:",chardata"` + Type string `xml:"type,attr"` +} + +func (dt *DataType) clean() { + cleanWhitespace(&dt.Name) + cleanWhitespace(&dt.Type) +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/service_client.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/service_client.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/service_client.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/service_client.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,94 @@ +package goupnp + +import ( + "context" + "fmt" + "net/url" + + "github.com/NebulousLabs/go-upnp/goupnp/soap" +) + +// ServiceClient is a SOAP client, root device and the service for the SOAP +// client rolled into one value. The root device, location, and service are +// intended to be informational. Location can be used to later recreate a +// ServiceClient with NewServiceClientByURL if the service is still present; +// bypassing the discovery process. +type ServiceClient struct { + SOAPClient *soap.SOAPClient + RootDevice *RootDevice + Location *url.URL + Service *Service +} + +// NewServiceClients is deprecated. Use NewServiceClientsCtx instead. +func NewServiceClients(searchTarget string) (clients []ServiceClient, errors []error, err error) { + return NewServiceClientsCtx(context.Background(), searchTarget) +} + +// NewServiceClientsCtx discovers services, and returns clients for them. err will +// report any error with the discovery process (blocking any device/service +// discovery), errors reports errors on a per-root-device basis. +func NewServiceClientsCtx(ctx context.Context, searchTarget string) (clients []ServiceClient, errors []error, err error) { + var maybeRootDevices []MaybeRootDevice + if maybeRootDevices, err = DiscoverDevicesCtx(ctx, searchTarget); err != nil { + return + } + + clients = make([]ServiceClient, 0, len(maybeRootDevices)) + + for _, maybeRootDevice := range maybeRootDevices { + if maybeRootDevice.Err != nil { + errors = append(errors, maybeRootDevice.Err) + continue + } + + deviceClients, err := NewServiceClientsFromRootDevice(maybeRootDevice.Root, maybeRootDevice.Location, searchTarget) + if err != nil { + errors = append(errors, err) + continue + } + clients = append(clients, deviceClients...) + } + + return +} + +// NewServiceClientsByURL creates client(s) for the given service URN, for a +// root device at the given URL. +func NewServiceClientsByURL(loc *url.URL, searchTarget string) ([]ServiceClient, error) { + rootDevice, err := DeviceByURL(loc) + if err != nil { + return nil, err + } + return NewServiceClientsFromRootDevice(rootDevice, loc, searchTarget) +} + +// NewServiceClientsFromDevice creates client(s) for the given service URN, in +// a given root device. The loc parameter is simply assigned to the +// Location attribute of the returned ServiceClient(s). +func NewServiceClientsFromRootDevice(rootDevice *RootDevice, loc *url.URL, searchTarget string) ([]ServiceClient, error) { + device := &rootDevice.Device + srvs := device.FindService(searchTarget) + if len(srvs) == 0 { + return nil, fmt.Errorf("goupnp: service %q not found within device %q (UDN=%q)", + searchTarget, device.FriendlyName, device.UDN) + } + + clients := make([]ServiceClient, 0, len(srvs)) + for _, srv := range srvs { + clients = append(clients, ServiceClient{ + SOAPClient: srv.NewSOAPClient(), + RootDevice: rootDevice, + Location: loc, + Service: srv, + }) + } + return clients, nil +} + +// GetServiceClient returns the ServiceClient itself. This is provided so that the +// service client attributes can be accessed via an interface method on a +// wrapping type. +func (client *ServiceClient) GetServiceClient() *ServiceClient { + return client +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/soap/soap.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/soap/soap.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/soap/soap.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/soap/soap.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,158 @@ +// Definition for the SOAP structure required for UPnP's SOAP usage. + +package soap + +import ( + "bytes" + "encoding/xml" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "reflect" +) + +const ( + soapEncodingStyle = "http://schemas.xmlsoap.org/soap/encoding/" + soapPrefix = xml.Header + `` + soapSuffix = `` +) + +type SOAPClient struct { + EndpointURL url.URL + HTTPClient http.Client +} + +func NewSOAPClient(endpointURL url.URL) *SOAPClient { + return &SOAPClient{ + EndpointURL: endpointURL, + } +} + +// PerformSOAPAction makes a SOAP request, with the given action. +// inAction and outAction must both be pointers to structs with string fields +// only. +func (client *SOAPClient) PerformAction(actionNamespace, actionName string, inAction interface{}, outAction interface{}) error { + requestBytes, err := encodeRequestAction(actionNamespace, actionName, inAction) + if err != nil { + return err + } + + response, err := client.HTTPClient.Do(&http.Request{ + Method: "POST", + URL: &client.EndpointURL, + Header: http.Header{ + "SOAPACTION": []string{`"` + actionNamespace + "#" + actionName + `"`}, + "CONTENT-TYPE": []string{"text/xml; charset=\"utf-8\""}, + }, + Body: ioutil.NopCloser(bytes.NewBuffer(requestBytes)), + // Set ContentLength to avoid chunked encoding - some servers might not support it. + ContentLength: int64(len(requestBytes)), + }) + if err != nil { + return fmt.Errorf("goupnp: error performing SOAP HTTP request: %v", err) + } + defer response.Body.Close() + if response.StatusCode != 200 { + resp, _ := ioutil.ReadAll(response.Body) + return fmt.Errorf("goupnp: SOAP request got HTTP %s: %s", response.Status, resp) + } + + responseEnv := newSOAPEnvelope() + decoder := xml.NewDecoder(response.Body) + if err := decoder.Decode(responseEnv); err != nil { + return fmt.Errorf("goupnp: error decoding response body: %v", err) + } + + if responseEnv.Body.Fault != nil { + return responseEnv.Body.Fault + } + + if outAction != nil { + if err := xml.Unmarshal(responseEnv.Body.RawAction, outAction); err != nil { + return fmt.Errorf("goupnp: error unmarshalling out action: %v, %v", err, responseEnv.Body.RawAction) + } + } + + return nil +} + +// newSOAPAction creates a soapEnvelope with the given action and arguments. +func newSOAPEnvelope() *soapEnvelope { + return &soapEnvelope{ + EncodingStyle: soapEncodingStyle, + } +} + +// encodeRequestAction is a hacky way to create an encoded SOAP envelope +// containing the given action. Experiments with one router have shown that it +// 500s for requests where the outer default xmlns is set to the SOAP +// namespace, and then reassigning the default namespace within that to the +// service namespace. Hand-coding the outer XML to work-around this. +func encodeRequestAction(actionNamespace, actionName string, inAction interface{}) ([]byte, error) { + requestBuf := new(bytes.Buffer) + requestBuf.WriteString(soapPrefix) + requestBuf.WriteString(``) + if inAction != nil { + if err := encodeRequestArgs(requestBuf, inAction); err != nil { + return nil, err + } + } + requestBuf.WriteString(``) + requestBuf.WriteString(soapSuffix) + return requestBuf.Bytes(), nil +} + +func encodeRequestArgs(w *bytes.Buffer, inAction interface{}) error { + in := reflect.Indirect(reflect.ValueOf(inAction)) + if in.Kind() != reflect.Struct { + return fmt.Errorf("goupnp: SOAP inAction is not a struct but of type %v", in.Type()) + } + enc := xml.NewEncoder(w) + nFields := in.NumField() + inType := in.Type() + for i := 0; i < nFields; i++ { + field := inType.Field(i) + argName := field.Name + if nameOverride := field.Tag.Get("soap"); nameOverride != "" { + argName = nameOverride + } + value := in.Field(i) + if value.Kind() != reflect.String { + return fmt.Errorf("goupnp: SOAP arg %q is not of type string, but of type %v", argName, value.Type()) + } + if err := enc.EncodeElement(value.Interface(), xml.StartElement{xml.Name{"", argName}, nil}); err != nil { + return fmt.Errorf("goupnp: error encoding SOAP arg %q: %v", argName, err) + } + } + enc.Flush() + return nil +} + +type soapEnvelope struct { + XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` + EncodingStyle string `xml:"http://schemas.xmlsoap.org/soap/envelope/ encodingStyle,attr"` + Body soapBody `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` +} + +type soapBody struct { + Fault *SOAPFaultError `xml:"Fault"` + RawAction []byte `xml:",innerxml"` +} + +// SOAPFaultError implements error, and contains SOAP fault information. +type SOAPFaultError struct { + FaultCode string `xml:"faultcode"` + FaultString string `xml:"faultstring"` + Detail string `xml:"detail"` +} + +func (err *SOAPFaultError) Error() string { + return fmt.Sprintf("SOAP fault: %s", err.FaultString) +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/soap/types.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/soap/types.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/soap/types.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/soap/types.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,519 @@ +package soap + +import ( + "encoding/base64" + "encoding/hex" + "errors" + "fmt" + "net/url" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +var ( + // localLoc acts like time.Local for this package, but is faked out by the + // unit tests to ensure that things stay constant (especially when running + // this test in a place where local time is UTC which might mask bugs). + localLoc = time.Local +) + +func MarshalUi1(v uint8) (string, error) { + return strconv.FormatUint(uint64(v), 10), nil +} + +func UnmarshalUi1(s string) (uint8, error) { + v, err := strconv.ParseUint(s, 10, 8) + return uint8(v), err +} + +func MarshalUi2(v uint16) (string, error) { + return strconv.FormatUint(uint64(v), 10), nil +} + +func UnmarshalUi2(s string) (uint16, error) { + v, err := strconv.ParseUint(s, 10, 16) + return uint16(v), err +} + +func MarshalUi4(v uint32) (string, error) { + return strconv.FormatUint(uint64(v), 10), nil +} + +func UnmarshalUi4(s string) (uint32, error) { + v, err := strconv.ParseUint(s, 10, 32) + return uint32(v), err +} + +func MarshalI1(v int8) (string, error) { + return strconv.FormatInt(int64(v), 10), nil +} + +func UnmarshalI1(s string) (int8, error) { + v, err := strconv.ParseInt(s, 10, 8) + return int8(v), err +} + +func MarshalI2(v int16) (string, error) { + return strconv.FormatInt(int64(v), 10), nil +} + +func UnmarshalI2(s string) (int16, error) { + v, err := strconv.ParseInt(s, 10, 16) + return int16(v), err +} + +func MarshalI4(v int32) (string, error) { + return strconv.FormatInt(int64(v), 10), nil +} + +func UnmarshalI4(s string) (int32, error) { + v, err := strconv.ParseInt(s, 10, 32) + return int32(v), err +} + +func MarshalInt(v int64) (string, error) { + return strconv.FormatInt(v, 10), nil +} + +func UnmarshalInt(s string) (int64, error) { + return strconv.ParseInt(s, 10, 64) +} + +func MarshalR4(v float32) (string, error) { + return strconv.FormatFloat(float64(v), 'G', -1, 32), nil +} + +func UnmarshalR4(s string) (float32, error) { + v, err := strconv.ParseFloat(s, 32) + return float32(v), err +} + +func MarshalR8(v float64) (string, error) { + return strconv.FormatFloat(v, 'G', -1, 64), nil +} + +func UnmarshalR8(s string) (float64, error) { + v, err := strconv.ParseFloat(s, 64) + return float64(v), err +} + +// MarshalFixed14_4 marshals float64 to SOAP "fixed.14.4" type. +func MarshalFixed14_4(v float64) (string, error) { + if v >= 1e14 || v <= -1e14 { + return "", fmt.Errorf("soap fixed14.4: value %v out of bounds", v) + } + return strconv.FormatFloat(v, 'f', 4, 64), nil +} + +// UnmarshalFixed14_4 unmarshals float64 from SOAP "fixed.14.4" type. +func UnmarshalFixed14_4(s string) (float64, error) { + v, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, err + } + if v >= 1e14 || v <= -1e14 { + return 0, fmt.Errorf("soap fixed14.4: value %q out of bounds", s) + } + return v, nil +} + +// MarshalChar marshals rune to SOAP "char" type. +func MarshalChar(v rune) (string, error) { + if v == 0 { + return "", errors.New("soap char: rune 0 is not allowed") + } + return string(v), nil +} + +// UnmarshalChar unmarshals rune from SOAP "char" type. +func UnmarshalChar(s string) (rune, error) { + if len(s) == 0 { + return 0, errors.New("soap char: got empty string") + } + r, n := utf8.DecodeRune([]byte(s)) + if n != len(s) { + return 0, fmt.Errorf("soap char: value %q is not a single rune", s) + } + return r, nil +} + +func MarshalString(v string) (string, error) { + return v, nil +} + +func UnmarshalString(v string) (string, error) { + return v, nil +} + +func parseInt(s string, err *error) int { + v, parseErr := strconv.ParseInt(s, 10, 64) + if parseErr != nil { + *err = parseErr + } + return int(v) +} + +var dateRegexps = []*regexp.Regexp{ + // yyyy[-mm[-dd]] + regexp.MustCompile(`^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$`), + // yyyy[mm[dd]] + regexp.MustCompile(`^(\d{4})(?:(\d{2})(?:(\d{2}))?)?$`), +} + +func parseDateParts(s string) (year, month, day int, err error) { + var parts []string + for _, re := range dateRegexps { + parts = re.FindStringSubmatch(s) + if parts != nil { + break + } + } + if parts == nil { + err = fmt.Errorf("soap date: value %q is not in a recognized ISO8601 date format", s) + return + } + + year = parseInt(parts[1], &err) + month = 1 + day = 1 + if len(parts[2]) != 0 { + month = parseInt(parts[2], &err) + if len(parts[3]) != 0 { + day = parseInt(parts[3], &err) + } + } + + if err != nil { + err = fmt.Errorf("soap date: %q: %v", s, err) + } + + return +} + +var timeRegexps = []*regexp.Regexp{ + // hh[:mm[:ss]] + regexp.MustCompile(`^(\d{2})(?::(\d{2})(?::(\d{2}))?)?$`), + // hh[mm[ss]] + regexp.MustCompile(`^(\d{2})(?:(\d{2})(?:(\d{2}))?)?$`), +} + +func parseTimeParts(s string) (hour, minute, second int, err error) { + var parts []string + for _, re := range timeRegexps { + parts = re.FindStringSubmatch(s) + if parts != nil { + break + } + } + if parts == nil { + err = fmt.Errorf("soap time: value %q is not in ISO8601 time format", s) + return + } + + hour = parseInt(parts[1], &err) + if len(parts[2]) != 0 { + minute = parseInt(parts[2], &err) + if len(parts[3]) != 0 { + second = parseInt(parts[3], &err) + } + } + + if err != nil { + err = fmt.Errorf("soap time: %q: %v", s, err) + } + + return +} + +// (+|-)hh[[:]mm] +var timezoneRegexp = regexp.MustCompile(`^([+-])(\d{2})(?::?(\d{2}))?$`) + +func parseTimezone(s string) (offset int, err error) { + if s == "Z" { + return 0, nil + } + parts := timezoneRegexp.FindStringSubmatch(s) + if parts == nil { + err = fmt.Errorf("soap timezone: value %q is not in ISO8601 timezone format", s) + return + } + + offset = parseInt(parts[2], &err) * 3600 + if len(parts[3]) != 0 { + offset += parseInt(parts[3], &err) * 60 + } + if parts[1] == "-" { + offset = -offset + } + + if err != nil { + err = fmt.Errorf("soap timezone: %q: %v", s, err) + } + + return +} + +var completeDateTimeZoneRegexp = regexp.MustCompile(`^([^T]+)(?:T([^-+Z]+)(.+)?)?$`) + +// splitCompleteDateTimeZone splits date, time and timezone apart from an +// ISO8601 string. It does not ensure that the contents of each part are +// correct, it merely splits on certain delimiters. +// e.g "2010-09-08T12:15:10+0700" => "2010-09-08", "12:15:10", "+0700". +// Timezone can only be present if time is also present. +func splitCompleteDateTimeZone(s string) (dateStr, timeStr, zoneStr string, err error) { + parts := completeDateTimeZoneRegexp.FindStringSubmatch(s) + if parts == nil { + err = fmt.Errorf("soap date/time/zone: value %q is not in ISO8601 datetime format", s) + return + } + dateStr = parts[1] + timeStr = parts[2] + zoneStr = parts[3] + return +} + +// MarshalDate marshals time.Time to SOAP "date" type. Note that this converts +// to local time, and discards the time-of-day components. +func MarshalDate(v time.Time) (string, error) { + return v.In(localLoc).Format("2006-01-02"), nil +} + +var dateFmts = []string{"2006-01-02", "20060102"} + +// UnmarshalDate unmarshals time.Time from SOAP "date" type. This outputs the +// date as midnight in the local time zone. +func UnmarshalDate(s string) (time.Time, error) { + year, month, day, err := parseDateParts(s) + if err != nil { + return time.Time{}, err + } + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, localLoc), nil +} + +// TimeOfDay is used in cases where SOAP "time" or "time.tz" is used. +type TimeOfDay struct { + // Duration of time since midnight. + FromMidnight time.Duration + + // Set to true if Offset is specified. If false, then the timezone is + // unspecified (and by ISO8601 - implies some "local" time). + HasOffset bool + + // Offset is non-zero only if time.tz is used. It is otherwise ignored. If + // non-zero, then it is regarded as a UTC offset in seconds. Note that the + // sub-minutes is ignored by the marshal function. + Offset int +} + +// MarshalTimeOfDay marshals TimeOfDay to the "time" type. +func MarshalTimeOfDay(v TimeOfDay) (string, error) { + d := int64(v.FromMidnight / time.Second) + hour := d / 3600 + d = d % 3600 + minute := d / 60 + second := d % 60 + + return fmt.Sprintf("%02d:%02d:%02d", hour, minute, second), nil +} + +// UnmarshalTimeOfDay unmarshals TimeOfDay from the "time" type. +func UnmarshalTimeOfDay(s string) (TimeOfDay, error) { + t, err := UnmarshalTimeOfDayTz(s) + if err != nil { + return TimeOfDay{}, err + } else if t.HasOffset { + return TimeOfDay{}, fmt.Errorf("soap time: value %q contains unexpected timezone") + } + return t, nil +} + +// MarshalTimeOfDayTz marshals TimeOfDay to the "time.tz" type. +func MarshalTimeOfDayTz(v TimeOfDay) (string, error) { + d := int64(v.FromMidnight / time.Second) + hour := d / 3600 + d = d % 3600 + minute := d / 60 + second := d % 60 + + tz := "" + if v.HasOffset { + if v.Offset == 0 { + tz = "Z" + } else { + offsetMins := v.Offset / 60 + sign := '+' + if offsetMins < 1 { + offsetMins = -offsetMins + sign = '-' + } + tz = fmt.Sprintf("%c%02d:%02d", sign, offsetMins/60, offsetMins%60) + } + } + + return fmt.Sprintf("%02d:%02d:%02d%s", hour, minute, second, tz), nil +} + +// UnmarshalTimeOfDayTz unmarshals TimeOfDay from the "time.tz" type. +func UnmarshalTimeOfDayTz(s string) (tod TimeOfDay, err error) { + zoneIndex := strings.IndexAny(s, "Z+-") + var timePart string + var hasOffset bool + var offset int + if zoneIndex == -1 { + hasOffset = false + timePart = s + } else { + hasOffset = true + timePart = s[:zoneIndex] + if offset, err = parseTimezone(s[zoneIndex:]); err != nil { + return + } + } + + hour, minute, second, err := parseTimeParts(timePart) + if err != nil { + return + } + + fromMidnight := time.Duration(hour*3600+minute*60+second) * time.Second + + // ISO8601 special case - values up to 24:00:00 are allowed, so using + // strictly greater-than for the maximum value. + if fromMidnight > 24*time.Hour || minute >= 60 || second >= 60 { + return TimeOfDay{}, fmt.Errorf("soap time.tz: value %q has value(s) out of range", s) + } + + return TimeOfDay{ + FromMidnight: time.Duration(hour*3600+minute*60+second) * time.Second, + HasOffset: hasOffset, + Offset: offset, + }, nil +} + +// MarshalDateTime marshals time.Time to SOAP "dateTime" type. Note that this +// converts to local time. +func MarshalDateTime(v time.Time) (string, error) { + return v.In(localLoc).Format("2006-01-02T15:04:05"), nil +} + +// UnmarshalDateTime unmarshals time.Time from the SOAP "dateTime" type. This +// returns a value in the local timezone. +func UnmarshalDateTime(s string) (result time.Time, err error) { + dateStr, timeStr, zoneStr, err := splitCompleteDateTimeZone(s) + if err != nil { + return + } + + if len(zoneStr) != 0 { + err = fmt.Errorf("soap datetime: unexpected timezone in %q", s) + return + } + + year, month, day, err := parseDateParts(dateStr) + if err != nil { + return + } + + var hour, minute, second int + if len(timeStr) != 0 { + hour, minute, second, err = parseTimeParts(timeStr) + if err != nil { + return + } + } + + result = time.Date(year, time.Month(month), day, hour, minute, second, 0, localLoc) + return +} + +// MarshalDateTimeTz marshals time.Time to SOAP "dateTime.tz" type. +func MarshalDateTimeTz(v time.Time) (string, error) { + return v.Format("2006-01-02T15:04:05-07:00"), nil +} + +// UnmarshalDateTimeTz unmarshals time.Time from the SOAP "dateTime.tz" type. +// This returns a value in the local timezone when the timezone is unspecified. +func UnmarshalDateTimeTz(s string) (result time.Time, err error) { + dateStr, timeStr, zoneStr, err := splitCompleteDateTimeZone(s) + if err != nil { + return + } + + year, month, day, err := parseDateParts(dateStr) + if err != nil { + return + } + + var hour, minute, second int + var location *time.Location = localLoc + if len(timeStr) != 0 { + hour, minute, second, err = parseTimeParts(timeStr) + if err != nil { + return + } + if len(zoneStr) != 0 { + var offset int + offset, err = parseTimezone(zoneStr) + if offset == 0 { + location = time.UTC + } else { + location = time.FixedZone("", offset) + } + } + } + + result = time.Date(year, time.Month(month), day, hour, minute, second, 0, location) + return +} + +// MarshalBoolean marshals bool to SOAP "boolean" type. +func MarshalBoolean(v bool) (string, error) { + if v { + return "1", nil + } + return "0", nil +} + +// UnmarshalBoolean unmarshals bool from the SOAP "boolean" type. +func UnmarshalBoolean(s string) (bool, error) { + switch s { + case "0", "false", "no": + return false, nil + case "1", "true", "yes": + return true, nil + } + return false, fmt.Errorf("soap boolean: %q is not a valid boolean value", s) +} + +// MarshalBinBase64 marshals []byte to SOAP "bin.base64" type. +func MarshalBinBase64(v []byte) (string, error) { + return base64.StdEncoding.EncodeToString(v), nil +} + +// UnmarshalBinBase64 unmarshals []byte from the SOAP "bin.base64" type. +func UnmarshalBinBase64(s string) ([]byte, error) { + return base64.StdEncoding.DecodeString(s) +} + +// MarshalBinHex marshals []byte to SOAP "bin.hex" type. +func MarshalBinHex(v []byte) (string, error) { + return hex.EncodeToString(v), nil +} + +// UnmarshalBinHex unmarshals []byte from the SOAP "bin.hex" type. +func UnmarshalBinHex(s string) ([]byte, error) { + return hex.DecodeString(s) +} + +// MarshalURI marshals *url.URL to SOAP "uri" type. +func MarshalURI(v *url.URL) (string, error) { + return v.String(), nil +} + +// UnmarshalURI unmarshals *url.URL from the SOAP "uri" type. +func UnmarshalURI(s string) (*url.URL, error) { + return url.Parse(s) +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/ssdp/registry.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/ssdp/registry.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/ssdp/registry.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/ssdp/registry.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,305 @@ +package ssdp + +import ( + "fmt" + "net/http" + "net/url" + "regexp" + "strconv" + "sync" + "time" + + "github.com/NebulousLabs/go-upnp/goupnp/httpu" +) + +const ( + maxExpiryTimeSeconds = 24 * 60 * 60 +) + +var ( + maxAgeRx = regexp.MustCompile("max-age=([0-9]+)") +) + +const ( + EventAlive = EventType(iota) + EventUpdate + EventByeBye +) + +type EventType int8 + +func (et EventType) String() string { + switch et { + case EventAlive: + return "EventAlive" + case EventUpdate: + return "EventUpdate" + case EventByeBye: + return "EventByeBye" + default: + return fmt.Sprintf("EventUnknown(%d)", int8(et)) + } +} + +type Update struct { + // The USN of the service. + USN string + // What happened. + EventType EventType + // The entry, which is nil if the service was not known and + // EventType==EventByeBye. The contents of this must not be modified as it is + // shared with the registry and other listeners. Once created, the Registry + // does not modify the Entry value - any updates are replaced with a new + // Entry value. + Entry *Entry +} + +type Entry struct { + // The address that the entry data was actually received from. + RemoteAddr string + // Unique Service Name. Identifies a unique instance of a device or service. + USN string + // Notfication Type. The type of device or service being announced. + NT string + // Server's self-identifying string. + Server string + Host string + // Location of the UPnP root device description. + Location url.URL + + // Despite BOOTID,CONFIGID being required fields, apparently they are not + // always set by devices. Set to -1 if not present. + + BootID int32 + ConfigID int32 + + SearchPort uint16 + + // When the last update was received for this entry identified by this USN. + LastUpdate time.Time + // When the last update's cached values are advised to expire. + CacheExpiry time.Time +} + +func newEntryFromRequest(r *http.Request) (*Entry, error) { + now := time.Now() + expiryDuration, err := parseCacheControlMaxAge(r.Header.Get("CACHE-CONTROL")) + if err != nil { + return nil, fmt.Errorf("ssdp: error parsing CACHE-CONTROL max age: %v", err) + } + + loc, err := url.Parse(r.Header.Get("LOCATION")) + if err != nil { + return nil, fmt.Errorf("ssdp: error parsing entry Location URL: %v", err) + } + + bootID, err := parseUpnpIntHeader(r.Header, "BOOTID.UPNP.ORG", -1) + if err != nil { + return nil, err + } + configID, err := parseUpnpIntHeader(r.Header, "CONFIGID.UPNP.ORG", -1) + if err != nil { + return nil, err + } + searchPort, err := parseUpnpIntHeader(r.Header, "SEARCHPORT.UPNP.ORG", ssdpSearchPort) + if err != nil { + return nil, err + } + + if searchPort < 1 || searchPort > 65535 { + return nil, fmt.Errorf("ssdp: search port %d is out of range", searchPort) + } + + return &Entry{ + RemoteAddr: r.RemoteAddr, + USN: r.Header.Get("USN"), + NT: r.Header.Get("NT"), + Server: r.Header.Get("SERVER"), + Host: r.Header.Get("HOST"), + Location: *loc, + BootID: bootID, + ConfigID: configID, + SearchPort: uint16(searchPort), + LastUpdate: now, + CacheExpiry: now.Add(expiryDuration), + }, nil +} + +func parseCacheControlMaxAge(cc string) (time.Duration, error) { + matches := maxAgeRx.FindStringSubmatch(cc) + if len(matches) != 2 { + return 0, fmt.Errorf("did not find exactly one max-age in cache control header: %q", cc) + } + expirySeconds, err := strconv.ParseInt(matches[1], 10, 16) + if err != nil { + return 0, err + } + if expirySeconds < 1 || expirySeconds > maxExpiryTimeSeconds { + return 0, fmt.Errorf("rejecting bad expiry time of %d seconds", expirySeconds) + } + return time.Duration(expirySeconds) * time.Second, nil +} + +// parseUpnpIntHeader is intended to parse the +// {BOOT,CONFIGID,SEARCHPORT}.UPNP.ORG header fields. It returns the def if +// the head is empty or missing. +func parseUpnpIntHeader(headers http.Header, headerName string, def int32) (int32, error) { + s := headers.Get(headerName) + if s == "" { + return def, nil + } + v, err := strconv.ParseInt(s, 10, 32) + if err != nil { + return 0, fmt.Errorf("ssdp: could not parse header %s: %v", headerName, err) + } + return int32(v), nil +} + +var _ httpu.Handler = new(Registry) + +// Registry maintains knowledge of discovered devices and services. +// +// NOTE: the interface for this is experimental and may change, or go away +// entirely. +type Registry struct { + lock sync.Mutex + byUSN map[string]*Entry + + listenersLock sync.RWMutex + listeners map[chan<- Update]struct{} +} + +func NewRegistry() *Registry { + return &Registry{ + byUSN: make(map[string]*Entry), + listeners: make(map[chan<- Update]struct{}), + } +} + +// NewServerAndRegistry is a convenience function to create a registry, and an +// httpu server to pass it messages. Call ListenAndServe on the server for +// messages to be processed. +func NewServerAndRegistry() (*httpu.Server, *Registry) { + reg := NewRegistry() + srv := &httpu.Server{ + Addr: ssdpUDP4Addr, + Multicast: true, + Handler: reg, + } + return srv, reg +} + +func (reg *Registry) AddListener(c chan<- Update) { + reg.listenersLock.Lock() + defer reg.listenersLock.Unlock() + reg.listeners[c] = struct{}{} +} + +func (reg *Registry) RemoveListener(c chan<- Update) { + reg.listenersLock.Lock() + defer reg.listenersLock.Unlock() + delete(reg.listeners, c) +} + +func (reg *Registry) sendUpdate(u Update) { + reg.listenersLock.RLock() + defer reg.listenersLock.RUnlock() + for c := range reg.listeners { + c <- u + } +} + +// GetService returns known service (or device) entries for the given service +// URN. +func (reg *Registry) GetService(serviceURN string) []*Entry { + // Currently assumes that the map is small, so we do a linear search rather + // than indexed to avoid maintaining two maps. + var results []*Entry + reg.lock.Lock() + defer reg.lock.Unlock() + for _, entry := range reg.byUSN { + if entry.NT == serviceURN { + results = append(results, entry) + } + } + return results +} + +// ServeMessage implements httpu.Handler, and uses SSDP NOTIFY requests to +// maintain the registry of devices and services. +func (reg *Registry) ServeMessage(r *http.Request) { + if r.Method != methodNotify { + return + } + + nts := r.Header.Get("nts") + + switch nts { + case ntsAlive: + reg.handleNTSAlive(r) + case ntsUpdate: + reg.handleNTSUpdate(r) + case ntsByebye: + reg.handleNTSByebye(r) + } +} + +func (reg *Registry) handleNTSAlive(r *http.Request) error { + entry, err := newEntryFromRequest(r) + if err != nil { + return err + } + + reg.lock.Lock() + reg.byUSN[entry.USN] = entry + reg.lock.Unlock() + + reg.sendUpdate(Update{ + USN: entry.USN, + EventType: EventAlive, + Entry: entry, + }) + + return nil +} + +func (reg *Registry) handleNTSUpdate(r *http.Request) error { + entry, err := newEntryFromRequest(r) + if err != nil { + return err + } + nextBootID, err := parseUpnpIntHeader(r.Header, "NEXTBOOTID.UPNP.ORG", -1) + if err != nil { + return err + } + entry.BootID = nextBootID + + reg.lock.Lock() + reg.byUSN[entry.USN] = entry + reg.lock.Unlock() + + reg.sendUpdate(Update{ + USN: entry.USN, + EventType: EventUpdate, + Entry: entry, + }) + + return nil +} + +func (reg *Registry) handleNTSByebye(r *http.Request) error { + usn := r.Header.Get("USN") + + reg.lock.Lock() + entry := reg.byUSN[usn] + delete(reg.byUSN, usn) + reg.lock.Unlock() + + reg.sendUpdate(Update{ + USN: usn, + EventType: EventByeBye, + Entry: entry, + }) + + return nil +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/ssdp/ssdp.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/ssdp/ssdp.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/goupnp/ssdp/ssdp.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/goupnp/ssdp/ssdp.go 2017-10-05 02:11:21.000000000 +0000 @@ -0,0 +1,84 @@ +package ssdp + +import ( + "context" + "errors" + "net/http" + "net/url" + "strconv" + "time" + + "github.com/NebulousLabs/go-upnp/goupnp/httpu" +) + +const ( + ssdpDiscover = `"ssdp:discover"` + ntsAlive = `ssdp:alive` + ntsByebye = `ssdp:byebye` + ntsUpdate = `ssdp:update` + ssdpUDP4Addr = "239.255.255.250:1900" + ssdpSearchPort = 1900 + methodSearch = "M-SEARCH" + methodNotify = "NOTIFY" +) + +// SSDPRawSearch is deprecated; use SSDPRawSearchCtx instead +func SSDPRawSearch(httpu *httpu.HTTPUClient, searchTarget string, maxWaitSeconds int, numSends int) ([]*http.Response, error) { + return SSDPRawSearchCtx(context.Background(), httpu, searchTarget, maxWaitSeconds, numSends) +} + +// SSDPRawSearch performs a fairly raw SSDP search request, and returns the +// unique response(s) that it receives. Each response has the requested +// searchTarget, a USN, and a valid location. maxWaitSeconds states how long to +// wait for responses in seconds, and must be a minimum of 1 (the +// implementation waits an additional 100ms for responses to arrive), 2 is a +// reasonable value for this. numSends is the number of requests to send - 3 is +// a reasonable value for this. +func SSDPRawSearchCtx(ctx context.Context, httpu *httpu.HTTPUClient, searchTarget string, maxWaitSeconds int, numSends int) ([]*http.Response, error) { + if maxWaitSeconds < 1 { + return nil, errors.New("ssdp: maxWaitSeconds must be >= 1") + } + + seenUsns := make(map[string]bool) + var responses []*http.Response + req := (&http.Request{ + Method: methodSearch, + // TODO: Support both IPv4 and IPv6. + Host: ssdpUDP4Addr, + URL: &url.URL{Opaque: "*"}, + Header: http.Header{ + // Putting headers in here avoids them being title-cased. + // (The UPnP discovery protocol uses case-sensitive headers) + "HOST": []string{ssdpUDP4Addr}, + "MX": []string{strconv.FormatInt(int64(maxWaitSeconds), 10)}, + "MAN": []string{ssdpDiscover}, + "ST": []string{searchTarget}, + }, + }).WithContext(ctx) + allResponses, err := httpu.Do(req, time.Duration(maxWaitSeconds)*time.Second+100*time.Millisecond, numSends) + if err != nil { + return nil, err + } + for _, response := range allResponses { + if response.StatusCode != 200 { + continue + } + if st := response.Header.Get("ST"); st != searchTarget { + continue + } + location, err := response.Location() + if err != nil { + continue + } + usn := response.Header.Get("USN") + if usn == "" { + usn = location.String() + } + if _, alreadySeen := seenUsns[usn]; !alreadySeen { + seenUsns[usn] = true + responses = append(responses, response) + } + } + + return responses, nil +} diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/README.md golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/README.md --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/README.md 2016-10-30 14:36:56.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/README.md 2017-10-05 02:11:21.000000000 +0000 @@ -6,12 +6,12 @@ - When attempting to discover UPnP-enabled routers on the network, only the first such router is returned. If you have multiple routers, this may cause -some trouble. But why would you do that? +some trouble. - Forwarded ports are always symmetric, e.g. the router's port 9980 will be -mapped to the client's port 9980. This will be unacceptable for some -purposes, but too bad. Symmetric mappings are the desired behavior 99% of -the time, and they save a function argument. +mapped to the client's port 9980. This will be unacceptable for some purposes, +but symmetric mappings are the desired behavior 99% of the time, and they +simplify the API. - TCP and UDP protocols are forwarded together. @@ -31,34 +31,45 @@ ## example ## ```go -package main - import ( - "fmt" - + "log" "github.com/NebulousLabs/go-upnp" ) -// error handling omitted for concision func main() { - // connect to router - d, _ := upnp.Discover() - - // discover external IP - ip, _ := d.ExternalIP() - fmt.Println("Your external IP is:", ip) - - // forward a port - _ = d.Forward(9001, "upnp test") - - // un-forward a port - _ = d.Clear(9001) - - // record router's location - loc := d.Location() - - // connect to router directly - d, _ = upnp.Load(loc) + // connect to router + d, err := upnp.Discover() + if err != nil { + log.Fatal(err) + } + + // discover external IP + ip, err := d.ExternalIP() + if err != nil { + log.Fatal(err) + } + fmt.Println("Your external IP is:", ip) + + // forward a port + err = d.Forward(9001, "upnp test") + if err != nil { + log.Fatal(err) + } + + // un-forward a port + err = d.Clear(9001) + if err != nil { + log.Fatal(err) + } + + // record router's location + loc := d.Location() + + // connect to router directly + d, err = upnp.Load(loc) + if err != nil { + log.Fatal(err) + } } ``` diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/upnp.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/upnp.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/upnp.go 2016-10-30 14:36:56.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/upnp.go 2017-10-05 02:11:21.000000000 +0000 @@ -26,14 +26,15 @@ package upnp import ( + "context" "errors" "net" "net/url" "time" - "github.com/NebulousLabs/Sia/crypto" - "github.com/huin/goupnp" - "github.com/huin/goupnp/dcps/internetgateway1" + "github.com/NebulousLabs/fastrand" + "github.com/NebulousLabs/go-upnp/goupnp" + "github.com/NebulousLabs/go-upnp/goupnp/dcps/internetgateway1" ) // An IGD provides an interface to the most commonly used functions of an @@ -114,28 +115,36 @@ return "", errors.New("could not determine internal IP") } -// Discover scans the local network for routers and returns the first +// Discover is deprecated; use DiscoverCtx instead. +func Discover() (*IGD, error) { + return DiscoverCtx(context.Background()) +} + +// DiscoverCtx scans the local network for routers and returns the first // UPnP-enabled router it encounters. It will try up to 3 times to find a // router, sleeping a random duration between each attempt. This is to // mitigate a race condition with many callers attempting to discover // simultaneously. -// -// TODO: if more than one client is found, only return those on the same -// subnet as the user? -func Discover() (*IGD, error) { +func DiscoverCtx(ctx context.Context) (*IGD, error) { + // TODO: if more than one client is found, only return those on the same + // subnet as the user? maxTries := 3 - sleepMs, _ := crypto.RandIntn(5000) + sleepTime := time.Millisecond * time.Duration(fastrand.Intn(5000)) for try := 0; try < maxTries; try++ { - time.Sleep(time.Millisecond * time.Duration(sleepMs)) - pppclients, _, _ := internetgateway1.NewWANPPPConnection1Clients() + pppclients, _, _ := internetgateway1.NewWANPPPConnection1Clients(ctx) if len(pppclients) > 0 { return &IGD{pppclients[0]}, nil } - ipclients, _, _ := internetgateway1.NewWANIPConnection1Clients() + ipclients, _, _ := internetgateway1.NewWANIPConnection1Clients(ctx) if len(ipclients) > 0 { return &IGD{ipclients[0]}, nil } - sleepMs *= 2 + select { + case <-ctx.Done(): + return nil, context.Canceled + case <-time.After(sleepTime): + } + sleepTime *= 2 } return nil, errors.New("no UPnP-enabled gateway found") } diff -Nru golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/upnp_test.go golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/upnp_test.go --- golang-github-nebulouslabs-go-upnp-0.0~git20160920.0.73e8530/upnp_test.go 2016-10-30 14:36:56.000000000 +0000 +++ golang-github-nebulouslabs-go-upnp-0.0~git20171003.0.1be4557/upnp_test.go 2017-10-05 02:11:21.000000000 +0000 @@ -1,8 +1,10 @@ package upnp import ( + "context" "sync" "testing" + "time" ) // TestConcurrentUPNP tests that several threads calling Discover() concurrently @@ -12,7 +14,9 @@ t.SkipNow() } // verify that a router exists - _, err := Discover() + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + _, err := DiscoverCtx(ctx) if err != nil { t.Skip(err) } @@ -20,12 +24,14 @@ // now try to concurrently Discover() using 20 threads var wg sync.WaitGroup for i := 0; i < 20; i++ { + wg.Add(1) go func() { - wg.Add(1) defer wg.Done() - _, err := Discover() + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + _, err := DiscoverCtx(ctx) if err != nil { - t.Fatal(err) + t.Error(err) } }() } @@ -34,7 +40,9 @@ func TestIGD(t *testing.T) { // connect to router - d, err := Discover() + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + d, err := DiscoverCtx(ctx) if err != nil { t.Skip(err) }