From 6f1154fc4d8765dd69951203bcad958ac0a2edd2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Smigielski Date: Tue, 10 May 2022 13:11:25 +0200 Subject: [PATCH] ws-discovery: Return an error instead of printing & ignoring --- Device.go | 50 +++++++++++------------------- api/api.go | 62 +++++++++++++++++++------------------- examples/discovery_test.go | 16 +++++----- ws-discovery/networking.go | 24 ++++++--------- 4 files changed, 67 insertions(+), 85 deletions(-) diff --git a/Device.go b/Device.go index 14d0178..d5ae766 100644 --- a/Device.go +++ b/Device.go @@ -3,7 +3,6 @@ package onvif import ( "encoding/xml" "errors" - "fmt" "io/ioutil" "net/http" "net/url" @@ -108,50 +107,37 @@ func readResponse(resp *http.Response) string { } //GetAvailableDevicesAtSpecificEthernetInterface ... -func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) []Device { - /* - Call an ws-discovery Probe Message to Discover NVT type Devices - */ - devices := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:" + NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) +func GetAvailableDevicesAtSpecificEthernetInterface(interfaceName string) ([]Device, error) { + // Call a ws-discovery Probe Message to Discover NVT type Devices + devices, err := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:" + NVT.String()}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + if err != nil { + return nil, err + } + + nvtDevicesSeen := make(map[string]bool) nvtDevices := make([]Device, 0) for _, j := range devices { doc := etree.NewDocument() if err := doc.ReadFromString(j); err != nil { - fmt.Errorf("%s", err.Error()) - return nil + return nil, err } - endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") - for _, xaddr := range endpoints { + for _, xaddr := range doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") { xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2] - //fmt.Println(xaddr) - c := 0 - - for c = 0; c < len(nvtDevices); c++ { - if nvtDevices[c].params.Xaddr == xaddr { - fmt.Println(nvtDevices[c].params.Xaddr, "==", xaddr) - break + if !nvtDevicesSeen[xaddr] { + dev, err := NewDevice(DeviceParams{Xaddr: strings.Split(xaddr, " ")[0]}) + if err != nil { + // TODO(jfsmig) print a warning + } else { + nvtDevicesSeen[xaddr] = true + nvtDevices = append(nvtDevices, *dev) } } - - if c < len(nvtDevices) { - continue - } - - dev, err := NewDevice(DeviceParams{Xaddr: strings.Split(xaddr, " ")[0]}) - - if err != nil { - fmt.Println("Error", xaddr) - fmt.Println(err) - continue - } else { - nvtDevices = append(nvtDevices, *dev) - } } } - return nvtDevices + return nvtDevices, nil } func (dev *Device) getSupportedServices(resp *http.Response) { diff --git a/api/api.go b/api/api.go index 233585f..71f362c 100644 --- a/api/api.go +++ b/api/api.go @@ -49,45 +49,45 @@ func RunApi() { interfaceName := context.GetHeader("interface") - var response = "[" - devices := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + devices, err := wsdiscovery.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + if err != nil { + context.String(http.StatusInternalServerError, "error") + } else { + response := "[" - for _, j := range devices { - doc := etree.NewDocument() - if err := doc.ReadFromString(j); err != nil { - context.XML(http.StatusBadRequest, err.Error()) - } else { + for _, j := range devices { + doc := etree.NewDocument() + if err := doc.ReadFromString(j); err != nil { + context.XML(http.StatusBadRequest, err.Error()) + } else { - endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") - scopes := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/Scopes") + endpoints := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/XAddrs") + scopes := doc.Root().FindElements("./Body/ProbeMatches/ProbeMatch/Scopes") - flag := false + flag := false - for _, xaddr := range endpoints { - xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2] - if strings.Contains(response, xaddr) { - flag = true + for _, xaddr := range endpoints { + xaddr := strings.Split(strings.Split(xaddr.Text(), " ")[0], "/")[2] + if strings.Contains(response, xaddr) { + flag = true + break + } + response += "{" + response += `"url":"` + xaddr + `",` + } + if flag { break } - response += "{" - response += `"url":"` + xaddr + `",` + for _, scope := range scopes { + re := regexp.MustCompile(`onvif:\/\/www\.onvif\.org\/name\/[A-Za-z0-9-]+`) + match := re.FindStringSubmatch(scope.Text()) + response += `"name":"` + path.Base(match[0]) + `"` + } + response += "}," } - if flag { - break - } - for _, scope := range scopes { - re := regexp.MustCompile(`onvif:\/\/www\.onvif\.org\/name\/[A-Za-z0-9-]+`) - match := re.FindStringSubmatch(scope.Text()) - response += `"name":"` + path.Base(match[0]) + `"` - } - response += "}," - } - - } - response = strings.TrimRight(response, ",") - response += "]" - if response != "" { + response = strings.TrimRight(response, ",") + response += "]" context.String(http.StatusOK, response) } }) diff --git a/examples/discovery_test.go b/examples/discovery_test.go index 630b28b..a055b8f 100644 --- a/examples/discovery_test.go +++ b/examples/discovery_test.go @@ -1,4 +1,4 @@ -package example +package main import ( "encoding/json" @@ -16,12 +16,8 @@ import ( ) func TestGetAvailableDevicesAtSpecificEthernetInterface(t *testing.T) { - - // client() - // runDiscovery("en0") - s := onvif.GetAvailableDevicesAtSpecificEthernetInterface("en0") - - log.Printf("%s", s) + s, err := onvif.GetAvailableDevicesAtSpecificEthernetInterface("en0") + log.Printf("%v %v", err, s) } func client() { @@ -45,7 +41,11 @@ type Host struct { func runDiscovery(interfaceName string) { var hosts []*Host - devices := discover.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + devices, err := discover.SendProbe(interfaceName, nil, []string{"dn:NetworkVideoTransmitter"}, map[string]string{"dn": "http://www.onvif.org/ver10/network/wsdl"}) + if err != nil { + log.Printf("error %s", err) + return + } for _, j := range devices { doc := etree.NewDocument() if err := doc.ReadFromString(j); err != nil { diff --git a/ws-discovery/networking.go b/ws-discovery/networking.go index ca70e23..7c1dc4f 100644 --- a/ws-discovery/networking.go +++ b/ws-discovery/networking.go @@ -11,8 +11,6 @@ package wsdiscovery import ( "errors" - "fmt" - "log" "net" "os" "time" @@ -24,7 +22,7 @@ import ( const bufSize = 8192 //SendProbe to device -func SendProbe(interfaceName string, scopes, types []string, namespaces map[string]string) []string { +func SendProbe(interfaceName string, scopes, types []string, namespaces map[string]string) ([]string, error) { // Creating UUID Version 4 uuidV4 := uuid.Must(uuid.NewV4()) //fmt.Printf("UUIDv4: %s\n", uuidV4) @@ -45,42 +43,40 @@ func SendProbe(interfaceName string, scopes, types []string, namespaces map[stri //` return sendUDPMulticast(probeSOAP.String(), interfaceName) - } -func sendUDPMulticast(msg string, interfaceName string) []string { +func sendUDPMulticast(msg string, interfaceName string) ([]string, error) { c, err := net.ListenPacket("udp4", "0.0.0.0:0") if err != nil { - fmt.Println(err) - return nil + return nil, err } defer c.Close() iface, err := net.InterfaceByName(interfaceName) if err != nil { - fmt.Println(err) + return nil, err } p := ipv4.NewPacketConn(c) group := net.IPv4(239, 255, 255, 250) if err := p.JoinGroup(iface, &net.UDPAddr{IP: group}); err != nil { - fmt.Println(err) + return nil, err } dst := &net.UDPAddr{IP: group, Port: 3702} data := []byte(msg) for _, ifi := range []*net.Interface{iface} { if err := p.SetMulticastInterface(ifi); err != nil { - fmt.Println(err) + return nil, err } p.SetMulticastTTL(2) if _, err := p.WriteTo(data, nil, dst); err != nil { - fmt.Println(err) + return nil, err } } if err := p.SetReadDeadline(time.Now().Add(time.Second * 1)); err != nil { - log.Fatal(err) + return nil, err } var result []string @@ -89,11 +85,11 @@ func sendUDPMulticast(msg string, interfaceName string) []string { n, _, _, err := p.ReadFrom(b) if err != nil { if !errors.Is(err, os.ErrDeadlineExceeded) { - fmt.Println(err) + return nil, err } break } result = append(result, string(b[0:n])) } - return result + return result, nil }