diff --git a/cmd/discoverigd/discoverigd.go b/cmd/discoverigd/discoverigd.go index 5eb594e..c2b329c 100644 --- a/cmd/discoverigd/discoverigd.go +++ b/cmd/discoverigd/discoverigd.go @@ -3,114 +3,41 @@ package main import ( - "encoding/xml" "fmt" "github.com/huin/goupnp" + "github.com/huin/goupnp/dcps/internetgateway1" ) -var spaces = " " - -type GetExternalIPAddressRequest struct { - XMLName xml.Name -} - -type GetExternalIPAddressResponse struct { - XMLName xml.Name - NewExternalIPAddress string -} - -type Uint16Value struct { - XMLName xml.Name - Value uint16 `xml:",chardata"` -} - -type GetGenericPortMappingEntryRequest struct { - XMLName xml.Name - NewPortMappingIndex Uint16Value -} - -type GetGenericPortMappingEntryResponse struct { - XMLName xml.Name - NewRemoteHost string - NewExternalPort uint16 - NewProtocol string - NewInternalPort uint16 - NewInternalClient string - NewEnabled string // boolean - NewLeaseDuration uint32 -} - -type indentLevel int - -func (i indentLevel) String() string { - return spaces[:i] -} - -func displayDevice(indent indentLevel, device *goupnp.Device) { - fmt.Println(indent.String(), device) - for _, srv := range device.Services { - fmt.Printf("%sService %s\n", indent+1, srv.ServiceType) - } - for i := range device.Devices { - displayDevice(indent+1, &device.Devices[i]) - } -} - func main() { - if results, err := goupnp.DiscoverDevices(goupnp.ServiceTypeWANPPPConnection); err != nil { + results, err := goupnp.DiscoverDevices(internetgateway1.URN_WANPPPConnection_1) + if err != nil { fmt.Println("Error discovering InternetGatewayDevice with UPnP: ", err) - } else { - fmt.Printf("Discovered %d InternetGatewayDevices:\n", len(results)) - for _, maybeRootDevice := range results { - if maybeRootDevice.Err != nil { - fmt.Println(maybeRootDevice.Err) - continue - } + return + } - device := &maybeRootDevice.Root.Device + fmt.Printf("Discovered %d InternetGatewayDevices:\n", len(results)) + for _, maybeRootDevice := range results { + if maybeRootDevice.Err != nil { + fmt.Println(maybeRootDevice.Err) + continue + } - displayDevice(0, device) - wanPPPSrvs := device.FindService(goupnp.ServiceTypeWANPPPConnection) - if len(wanPPPSrvs) < 1 { - fmt.Printf("Could not find expected service on device %s\n", device.FriendlyName) - continue - } else if len(wanPPPSrvs) > 1 { - fmt.Printf("Got more than one expected service on device %s\n", device.FriendlyName) - } - srv := wanPPPSrvs[0] + device := &maybeRootDevice.Root.Device - if scdp, err := srv.RequestSCDP(); err != nil { - fmt.Printf("Error requesting SCPD: %v\n", err) + fmt.Println("Device ", device.FriendlyName) + wanPPPSrvs := device.FindService(internetgateway1.URN_WANPPPConnection_1) + if len(wanPPPSrvs) < 1 { + fmt.Printf("Could not find expected service on device %s\n", device.FriendlyName) + continue + } + + for _, srv := range wanPPPSrvs { + client := internetgateway1.WANPPPConnection1{srv.NewSOAPClient()} + if addr, err := client.GetExternalIPAddress(); err != nil { + fmt.Printf("Failed to get external IP address: %v\n", err) } else { - fmt.Println("Available SCPD actions:") - for _, action := range scdp.Actions { - fmt.Println(" ", action.Name) - } - } - - srvClient := srv.NewSOAPClient() - - { - inAction := GetExternalIPAddressRequest{XMLName: xml.Name{Space: goupnp.ServiceTypeWANPPPConnection, Local: "GetExternalIPAddress"}} - var outAction GetExternalIPAddressResponse - err := srvClient.PerformAction(goupnp.ServiceTypeWANPPPConnection, "GetExternalIPAddress", &inAction, &outAction) - if err != nil { - fmt.Printf("Failed to GetExternalIPAddress from %s: %v\n", device.FriendlyName, err) - continue - } - fmt.Printf("Got GetExternalIPAddress result from %s: %+v\n", device.FriendlyName, outAction) - } - - for i := uint16(0); i < 10; i++ { - inAction := GetGenericPortMappingEntryRequest{XMLName: xml.Name{Space: goupnp.ServiceTypeWANPPPConnection, Local: "GetGenericPortMappingEntry"}, NewPortMappingIndex: Uint16Value{XMLName: xml.Name{"", "NewPortMappingIndex"}, Value: i}} - var outAction GetGenericPortMappingEntryResponse - err := srvClient.PerformAction(goupnp.ServiceTypeWANPPPConnection, "GetGenericPortMappingEntry", &inAction, &outAction) - if err != nil { - fmt.Printf("Failed to GetGenericPortMappingEntry on %s: %v\n", device.FriendlyName, err) - continue - } - fmt.Printf("Got GetGenericPortMappingEntry from %s: %+v\n", device.FriendlyName, outAction) + fmt.Printf("External IP address: %v\n", addr) } } } diff --git a/cmd/specgen/pkgtmpl.go b/cmd/specgen/pkgtmpl.go index 145c1fd..bfbe990 100644 --- a/cmd/specgen/pkgtmpl.go +++ b/cmd/specgen/pkgtmpl.go @@ -31,7 +31,7 @@ const ({{range .ServiceTypes}} // {{$srvIdent}} is a client for UPnP SOAP service with URN "{{.URN}}". type {{$srvIdent}} struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } {{range .SCPD.Actions}}{{/* loops over *SCPDWithURN values */}} diff --git a/dcps/internetgateway1/internetgateway1.go b/dcps/internetgateway1/internetgateway1.go index 43ee57e..acf262b 100644 --- a/dcps/internetgateway1/internetgateway1.go +++ b/dcps/internetgateway1/internetgateway1.go @@ -31,7 +31,7 @@ const ( // LANHostConfigManagement1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:LANHostConfigManagement:1". type LANHostConfigManagement1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -637,7 +637,7 @@ func (client *LANHostConfigManagement1) GetDNSServers() (NewDNSServers string, e // Layer3Forwarding1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:Layer3Forwarding:1". type Layer3Forwarding1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -704,7 +704,7 @@ func (client *Layer3Forwarding1) GetDefaultConnectionService() (NewDefaultConnec // WANCableLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCableLinkConfig:1". type WANCableLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // @@ -1025,7 +1025,7 @@ func (client *WANCableLinkConfig1) GetTFTPServer() (NewTFTPServer string, err er // WANCommonInterfaceConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1". type WANCommonInterfaceConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -1371,7 +1371,7 @@ func (client *WANCommonInterfaceConfig1) GetActiveConnection(NewActiveConnection // WANDSLLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANDSLLinkConfig:1". type WANDSLLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -1692,7 +1692,7 @@ func (client *WANDSLLinkConfig1) GetFCSPreserved() (NewFCSPreserved bool, err er // WANEthernetLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANEthernetLinkConfig:1". type WANEthernetLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // @@ -1728,7 +1728,7 @@ func (client *WANEthernetLinkConfig1) GetEthernetLinkStatus() (NewEthernetLinkSt // WANIPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANIPConnection:1". type WANIPConnection1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -2440,7 +2440,7 @@ func (client *WANIPConnection1) GetExternalIPAddress() (NewExternalIPAddress str // WANPOTSLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPOTSLinkConfig:1". type WANPOTSLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -2760,7 +2760,7 @@ func (client *WANPOTSLinkConfig1) GetPlusVTRCommandSupported() (NewPlusVTRComman // WANPPPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPPPConnection:1". type WANPPPConnection1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: diff --git a/dcps/internetgateway2/internetgateway2.go b/dcps/internetgateway2/internetgateway2.go index 45aa5ab..b493d9b 100644 --- a/dcps/internetgateway2/internetgateway2.go +++ b/dcps/internetgateway2/internetgateway2.go @@ -35,7 +35,7 @@ const ( // LANHostConfigManagement1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:LANHostConfigManagement:1". type LANHostConfigManagement1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -641,7 +641,7 @@ func (client *LANHostConfigManagement1) GetDNSServers() (NewDNSServers string, e // Layer3Forwarding1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:Layer3Forwarding:1". type Layer3Forwarding1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -708,7 +708,7 @@ func (client *Layer3Forwarding1) GetDefaultConnectionService() (NewDefaultConnec // WANCableLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCableLinkConfig:1". type WANCableLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // @@ -1029,7 +1029,7 @@ func (client *WANCableLinkConfig1) GetTFTPServer() (NewTFTPServer string, err er // WANCommonInterfaceConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1". type WANCommonInterfaceConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -1375,7 +1375,7 @@ func (client *WANCommonInterfaceConfig1) GetActiveConnection(NewActiveConnection // WANDSLLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANDSLLinkConfig:1". type WANDSLLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -1696,7 +1696,7 @@ func (client *WANDSLLinkConfig1) GetFCSPreserved() (NewFCSPreserved bool, err er // WANEthernetLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANEthernetLinkConfig:1". type WANEthernetLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // @@ -1732,7 +1732,7 @@ func (client *WANEthernetLinkConfig1) GetEthernetLinkStatus() (NewEthernetLinkSt // WANIPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANIPConnection:1". type WANIPConnection1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -2444,7 +2444,7 @@ func (client *WANIPConnection1) GetExternalIPAddress() (NewExternalIPAddress str // WANIPConnection2 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANIPConnection:2". type WANIPConnection2 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -3347,7 +3347,7 @@ func (client *WANIPConnection2) AddAnyPortMapping(NewRemoteHost string, NewExter // WANIPv6FirewallControl1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1". type WANIPv6FirewallControl1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // @@ -3663,7 +3663,7 @@ func (client *WANIPv6FirewallControl1) CheckPinholeWorking(UniqueID uint16) (IsW // WANPOTSLinkConfig1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPOTSLinkConfig:1". type WANPOTSLinkConfig1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: @@ -3983,7 +3983,7 @@ func (client *WANPOTSLinkConfig1) GetPlusVTRCommandSupported() (NewPlusVTRComman // WANPPPConnection1 is a client for UPnP SOAP service with URN "urn:schemas-upnp-org:service:WANPPPConnection:1". type WANPPPConnection1 struct { - SOAPClient soap.SOAPClient + SOAPClient *soap.SOAPClient } // Arguments: diff --git a/device.go b/device.go index 71e0953..e5b658b 100644 --- a/device.go +++ b/device.go @@ -85,7 +85,6 @@ func (device *Device) VisitServices(visitor func(*Service)) { func (device *Device) FindService(serviceType string) []*Service { var services []*Service device.VisitServices(func(s *Service) { - fmt.Println(s.ServiceType) if s.ServiceType == serviceType { services = append(services, s) } diff --git a/goupnp.go b/goupnp.go index 3118078..4608f11 100644 --- a/goupnp.go +++ b/goupnp.go @@ -11,23 +11,6 @@ import ( "github.com/huin/goupnp/ssdp" ) -// Non-exhaustive set of UPnP service types. -const ( - ServiceTypeLayer3Forwarding = "urn:schemas-upnp-org:service:Layer3Forwarding:1" - ServiceTypeWANCommonInterfaceConfig = "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" - // WANPPPConnection is typically useful with regard to the external IP and - // port forwarding. - // http://upnp.org/specs/gw/UPnP-gw-WANPPPConnection-v1-Service.pdf - ServiceTypeWANPPPConnection = "urn:schemas-upnp-org:service:WANPPPConnection:1" -) - -// Non-exhaustive set of UPnP device types. -const ( - // Device type for InternetGatewayDevice. - // http://upnp.org/specs/gw/upnp-gw-internetgatewaydevice-v1-device.pdf - DeviceTypeInternetGatewayDevice = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" -) - // ContextError is an error that wraps an error with some context information. type ContextError struct { Context string @@ -45,10 +28,11 @@ type MaybeRootDevice struct { } // DiscoverDevices attempts to find targets of the given type. This is -// typically the entry-point for this package. searchTarget is typically a -// value from a DeviceType* or ServiceType* constant. An error is returned for -// errors while attempting to send the query. An error or RootDevice is -// returned for each discovered RootDevice. +// 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 DiscoverDevices(searchTarget string) ([]MaybeRootDevice, error) { httpu, err := httpu.NewHTTPUClient() if err != nil {