diff --git a/pkg/onvif/client.go b/pkg/onvif/client.go
index 090e9ef2..97bfd8dc 100644
--- a/pkg/onvif/client.go
+++ b/pkg/onvif/client.go
@@ -5,7 +5,6 @@ import (
"crypto/sha1"
"encoding/base64"
"errors"
- "github.com/AlexxIT/go2rtc/pkg/core"
"html"
"io"
"net/http"
@@ -13,6 +12,8 @@ import (
"regexp"
"strings"
"time"
+
+ "github.com/AlexxIT/go2rtc/pkg/core"
)
const PathDevice = "/onvif/device_service"
@@ -78,10 +79,10 @@ func (c *Client) GetURI() (string, error) {
return "", err
}
- uri := FindTagValue(b, "Uri")
- uri = html.UnescapeString(uri)
+ rawURL := FindTagValue(b, "Uri")
+ rawURL = strings.TrimSpace(html.UnescapeString(rawURL))
- u, err := url.Parse(uri)
+ u, err := url.Parse(rawURL)
if err != nil {
return "", err
}
diff --git a/pkg/onvif/helpers.go b/pkg/onvif/helpers.go
index fb65ecaf..fc9c8392 100644
--- a/pkg/onvif/helpers.go
+++ b/pkg/onvif/helpers.go
@@ -11,7 +11,7 @@ import (
)
func FindTagValue(b []byte, tag string) string {
- re := regexp.MustCompile(`(?s)<[^/>]*` + tag + `[^>]*>([^<]+)`)
+ re := regexp.MustCompile(`(?s)[:<]` + tag + `>([^<]+)`)
m := re.FindSubmatch(b)
if len(m) != 2 {
return ""
diff --git a/pkg/onvif/onvif_test.go b/pkg/onvif/onvif_test.go
new file mode 100644
index 00000000..cd57d60b
--- /dev/null
+++ b/pkg/onvif/onvif_test.go
@@ -0,0 +1,199 @@
+package onvif
+
+import (
+ "html"
+ "net/url"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestGetStreamUri(t *testing.T) {
+ tests := []struct {
+ name string
+ xml string
+ url string
+ }{
+ {
+ name: "Dahua stream default",
+ xml: `rtsp://192.168.1.123:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=OnviftruetruePT0S`,
+ url: "rtsp://192.168.1.123:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif",
+ },
+ {
+ name: "Dahua snapshot default",
+ xml: `http://192.168.1.123/onvifsnapshot/media_service/snapshot?channel=1&subtype=1falsefalsePT0S`,
+ url: "http://192.168.1.123/onvifsnapshot/media_service/snapshot?channel=1&subtype=1",
+ },
+ {
+ name: "Dahua stream formatted",
+ xml: `
+
+
+
+
+
+
+ rtsp://192.168.1.123:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
+ true
+ true
+ PT0S
+
+
+
+`,
+ url: "rtsp://192.168.1.123:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif",
+ },
+ {
+ name: "Dahua snapshot formatted",
+ xml: `
+
+
+
+
+
+
+ http://192.168.1.123/onvifsnapshot/media_service/snapshot?channel=1&subtype=1
+ false
+ false
+ PT0S
+
+
+
+`,
+ url: "http://192.168.1.123/onvifsnapshot/media_service/snapshot?channel=1&subtype=1",
+ },
+ {
+ name: "Unknown",
+ xml: `
+
+
+
+
+
+
+ rtsp://192.168.5.53:8090/profile1=r
+
+
+
+
+`,
+ url: "rtsp://192.168.5.53:8090/profile1=r",
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ uri := FindTagValue([]byte(test.xml), "Uri")
+ uri = strings.TrimSpace(html.UnescapeString(uri))
+ u, err := url.Parse(uri)
+ require.Nil(t, err)
+ require.Equal(t, test.url, u.String())
+ })
+ }
+}
+
+func TestGetCapabilities(t *testing.T) {
+ tests := []struct {
+ name string
+ xml string
+ }{
+ {
+ name: "Dahua default",
+ xml: `http://192.168.1.123/onvif/analytics_servicetruetruehttp://192.168.1.123/onvif/device_servicefalsefalsefalsefalsefalsefalsetruefalsefalsetruetrue200210220230240242161218061812190619122006truefalsefalsefalse21falsefalsefalsefalsefalsefalsefalsefalsefalsefalsefalse0falsehttp://192.168.1.123/onvif/event_servicetruetruefalsehttp://192.168.1.123/onvif/imaging_servicehttp://192.168.1.123/onvif/media_servicetruetruetrue6http://192.168.1.123/onvif/deviceIO_service10111`,
+ },
+ {
+ name: "Dahua formatted",
+ xml: `
+
+
+
+
+
+
+ http://192.168.1.123/onvif/analytics_service
+ true
+ true
+
+
+ http://192.168.1.123/onvif/device_service
+
+ false
+ false
+ false
+ false
+
+ false
+
+
+
+ ...
+
+
+ 2
+ 1
+
+ false
+
+
+
+
+
+ ...
+
+
+
+ http://192.168.1.123/onvif/event_service
+ true
+ true
+ false
+
+
+ http://192.168.1.123/onvif/imaging_service
+
+
+ http://192.168.1.123/onvif/media_service
+
+ true
+ true
+ true
+
+
+
+ 6
+
+
+
+
+
+ http://192.168.1.123/onvif/deviceIO_service
+ 1
+ 0
+ 1
+ 1
+ 1
+
+
+
+
+
+`,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ rawURL := FindTagValue([]byte(test.xml), "Media.+?XAddr")
+ require.Equal(t, "http://192.168.1.123/onvif/media_service", rawURL)
+
+ rawURL = FindTagValue([]byte(test.xml), "Imaging.+?XAddr")
+ require.Equal(t, "http://192.168.1.123/onvif/imaging_service", rawURL)
+ })
+ }
+}