Skip to content

Commit

Permalink
Merge pull request #22 from jfsmig/fixes-ws-discovery-20220510
Browse files Browse the repository at this point in the history
Misc. fixes in the WS discovery
  • Loading branch information
crazybber authored Jul 26, 2022
2 parents d8d0fc3 + 9e25a01 commit bc3226e
Show file tree
Hide file tree
Showing 209 changed files with 6,363 additions and 157 deletions.
50 changes: 18 additions & 32 deletions Device.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package onvif
import (
"encoding/xml"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
Expand Down Expand Up @@ -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) {
Expand Down
134 changes: 64 additions & 70 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package api

import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"path"
"reflect"
"regexp"
"strings"
"time"

"github.com/juju/errors"
"github.com/rs/zerolog"

"github.com/beevik/etree"
"github.com/gin-gonic/gin"
Expand All @@ -18,6 +21,18 @@ import (
wsdiscovery "github.com/use-go/onvif/ws-discovery"
)

var (
// LoggerContext is the builder of a zerolog.Logger that is exposed to the application so that
// options at the CLI might alter the formatting and the output of the logs.
LoggerContext = zerolog.
New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).
With().Timestamp()

// Logger is a zerolog logger, that can be safely used from any part of the application.
// It gathers the format and the output.
Logger = LoggerContext.Logger()
)

func RunApi() {
router := gin.Default()

Expand All @@ -32,7 +47,7 @@ func RunApi() {
xaddr := c.GetHeader("xaddr")
acceptedData, err := c.GetRawData()
if err != nil {
fmt.Println(err)
Logger.Debug().Err(err).Msg("Failed to get rawx data")
}

message, err := callNecessaryMethod(serviceName, methodName, string(acceptedData), username, pass, xaddr)
Expand All @@ -49,71 +64,52 @@ 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 + `",`
}
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]) + `"`
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 += "},"

}

}
response = strings.TrimRight(response, ",")
response += "]"
if response != "" {
response = strings.TrimRight(response, ",")
response += "]"
context.String(http.StatusOK, response)
}
})

router.Run()
}

//func soapHandling(tp interface{}, tags* map[string]string) {
// ifaceValue := reflect.ValueOf(tp).Elem()
// typeOfStruct := ifaceValue.Type()
// if ifaceValue.Kind() != reflect.Struct {
// return
// }
// for i := 0; i < ifaceValue.NumField(); i++ {
// field := ifaceValue.Field(i)
// tg, err := typeOfStruct.FieldByName(typeOfStruct.Field(i).Name)
// if err == false {
// fmt.Println(err)
// }
// (*tags)[typeOfStruct.Field(i).Name] = string(tg.Tag)
//
// subStruct := reflect.New(reflect.TypeOf( field.Interface() ))
// soapHandling(subStruct.Interface(), tags)
// }
//}

func callNecessaryMethod(serviceName, methodName, acceptedData, username, password, xaddr string) (string, error) {
var methodStruct interface{}
var err error
Expand All @@ -129,17 +125,17 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo
return "", errors.New("there is no such service")
}
if err != nil { //done
return "", err
return "", errors.Annotate(err, "getStructByName")
}

resp, err := xmlAnalize(methodStruct, &acceptedData)
if err != nil {
return "", err
return "", errors.Annotate(err, "xmlAnalize")
}

endpoint, err := getEndpoint(serviceName, xaddr)
if err != nil {
return "", err
return "", errors.Annotate(err, "getEndpoint")
}

soap := gosoap.NewEmptySOAP()
Expand All @@ -149,12 +145,12 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo

servResp, err := networking.SendSoap(new(http.Client), endpoint, soap.String())
if err != nil {
return "", err
return "", errors.Annotate(err, "SendSoap")
}

rsp, err := ioutil.ReadAll(servResp.Body)
if err != nil {
return "", err
return "", errors.Annotate(err, "ReadAll")
}

return string(rsp), nil
Expand All @@ -163,7 +159,7 @@ func callNecessaryMethod(serviceName, methodName, acceptedData, username, passwo
func getEndpoint(service, xaddr string) (string, error) {
dev, err := onvif.NewDevice(onvif.DeviceParams{Xaddr: xaddr})
if err != nil {
return "", err
return "", errors.Annotate(err, "NewDevice")
}
pkg := strings.ToLower(service)

Expand Down Expand Up @@ -193,7 +189,7 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)

doc := etree.NewDocument()
if err := doc.ReadFromString(*acceptedData); err != nil {
return nil, err
return nil, errors.Annotate(err, "readFromString")
}
etr := doc.FindElements("./*")
xmlUnmarshal(etr, &testunMarshal, &mas)
Expand All @@ -207,7 +203,7 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)
lst := (testunMarshal)[lstIndex]
elemName, attr, value, err := xmlMaker(&lst, &test, lstIndex)
if err != nil {
return nil, err
return nil, errors.Annotate(err, "xmlMarker")
}

if mas[lstIndex] == "Push" && lstIndex == 0 { //done
Expand Down Expand Up @@ -251,10 +247,10 @@ func xmlAnalize(methodStruct interface{}, acceptedData *string) (*string, error)

resp, err := document.WriteToString()
if err != nil {
return nil, err
return nil, errors.Annotate(err, "writeToString")
}

return &resp, err
return &resp, nil
}

func xmlMaker(lst *[]interface{}, tags *[]map[string]string, lstIndex int) (string, map[string]string, string, error) {
Expand All @@ -273,13 +269,13 @@ func xmlMaker(lst *[]interface{}, tags *[]map[string]string, lstIndex int) (stri
if index == 0 && lstIndex == 0 {
res, err := xmlProcessing(tg["XMLName"])
if err != nil {
return "", nil, "", err
return "", nil, "", errors.Annotate(err, "xmlProcessing")
}
elemName = res
} else if index == 0 {
res, err := xmlProcessing(tg[conversion])
if err != nil {
return "", nil, "", err
return "", nil, "", errors.Annotate(err, "xmlProcessing")
}
elemName = res
} else {
Expand Down Expand Up @@ -314,8 +310,6 @@ func xmlProcessing(tg string) (string, error) {
} else {
return str[1][0:omitAttr], nil
}

return "", errors.New("something went wrong")
}

func mapProcessing(mapVar []map[string]string) []map[string]string {
Expand Down Expand Up @@ -343,9 +337,9 @@ func soapHandling(tp interface{}, tags *[]map[string]string) {
}
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
tmp, err := typeOfT.FieldByName(typeOfT.Field(i).Name)
if err == false {
fmt.Println(err)
tmp, ok := typeOfT.FieldByName(typeOfT.Field(i).Name)
if !ok {
Logger.Debug().Str("field", typeOfT.Field(i).Name).Msg("reflection failed")
}
*tags = append(*tags, map[string]string{typeOfT.Field(i).Name: string(tmp.Tag)})
subStruct := reflect.New(reflect.TypeOf(f.Interface()))
Expand Down
Loading

0 comments on commit bc3226e

Please sign in to comment.