Add alternative streamid format for SRT

The streamid format that starts with #!: is recommended in the SRT
specs but it usually causes trouble where you're limited in the
use of such characters. Some hardware devices will not accept such
streamids.

The alternative format is simpler and has the form
[resource](,token:[token])?(,mode:[mode])?

token and mode are optional. mode can have the values "publish" or
"request". If mode is not provided, a value of "request" is
assumed.
This commit is contained in:
Ingo Oppermann
2022-10-25 14:00:27 +02:00
parent 07e2898857
commit 35c5c9f077
2 changed files with 76 additions and 4 deletions

View File

@@ -5,6 +5,7 @@ import (
"context"
"fmt"
"net"
"regexp"
"strings"
"sync"
"time"
@@ -365,6 +366,59 @@ type streamInfo struct {
func parseStreamId(streamid string) (streamInfo, error) {
si := streamInfo{}
if strings.HasPrefix(streamid, "#!:") {
return parseOldStreamId(streamid)
}
re := regexp.MustCompile(`,(token|mode):(.+)`)
results := map[string]string{}
idEnd := -1
value := streamid
key := ""
for {
matches := re.FindStringSubmatchIndex(value)
if matches == nil {
break
}
if idEnd < 0 {
idEnd = matches[2] - 1
}
if len(key) != 0 {
results[key] = value[:matches[2]-1]
}
key = value[matches[2]:matches[3]]
value = value[matches[4]:matches[5]]
results[key] = value
}
if idEnd < 0 {
idEnd = len(streamid)
}
si.resource = streamid[:idEnd]
if token, ok := results["token"]; ok {
si.token = token
}
if mode, ok := results["mode"]; ok {
si.mode = mode
} else {
si.mode = "request"
}
return si, nil
}
func parseOldStreamId(streamid string) (streamInfo, error) {
si := streamInfo{}
if !strings.HasPrefix(streamid, "#!:") {
return si, fmt.Errorf("unknown streamid format")
}
@@ -373,7 +427,7 @@ func parseStreamId(streamid string) (streamInfo, error) {
kvs := strings.Split(streamid, ",")
split := func(s, sep string) (string, string, error) {
splitFn := func(s, sep string) (string, string, error) {
splitted := strings.SplitN(s, sep, 2)
if len(splitted) != 2 {
@@ -384,7 +438,7 @@ func parseStreamId(streamid string) (streamInfo, error) {
}
for _, kv := range kvs {
key, value, err := split(kv, "=")
key, value, err := splitFn(kv, "=")
if err != nil {
continue
}

View File

@@ -8,7 +8,25 @@ import (
func TestParseStreamId(t *testing.T) {
streamids := map[string]streamInfo{
"bla": {},
"bla": {resource: "bla", mode: "request"},
"bla,mode:publish": {resource: "bla", mode: "publish"},
"123456789": {resource: "123456789", mode: "request"},
"bla,token:foobar": {resource: "bla", token: "foobar", mode: "request"},
"bla,token:foo,bar": {resource: "bla", token: "foo,bar", mode: "request"},
"123456789,mode:publish,token:foobar": {resource: "123456789", token: "foobar", mode: "publish"},
"mode:publish": {resource: "mode:publish", mode: "request"},
}
for streamid, wantsi := range streamids {
si, err := parseStreamId(streamid)
require.NoError(t, err)
require.Equal(t, wantsi, si)
}
}
func TestParseOldStreamId(t *testing.T) {
streamids := map[string]streamInfo{
"#!:": {},
"#!:key=value": {},
"#!:m=publish": {mode: "publish"},
@@ -19,7 +37,7 @@ func TestParseStreamId(t *testing.T) {
}
for streamid, wantsi := range streamids {
si, _ := parseStreamId(streamid)
si, _ := parseOldStreamId(streamid)
require.Equal(t, wantsi, si)
}