install go2rtc on bob

This commit is contained in:
2026-04-04 19:36:14 +02:00
parent f0b56e63d1
commit ccf88187b8
537 changed files with 69213 additions and 0 deletions
@@ -0,0 +1,7 @@
# Credentials
This module allows you to get variables:
- from custom storage (ex. config file)
- from [credential files](https://systemd.io/CREDENTIALS/)
- from environment variables
@@ -0,0 +1,79 @@
package creds
import (
"errors"
"os"
"path/filepath"
"regexp"
"strings"
)
type Storage interface {
SetValue(name, value string) error
GetValue(name string) (string, bool)
}
var storage Storage
func SetStorage(s Storage) {
storage = s
}
func SetValue(name, value string) error {
if storage == nil {
return errors.New("credentials: storage not initialized")
}
if err := storage.SetValue(name, value); err != nil {
return err
}
AddSecret(value)
return nil
}
func GetValue(name string) (value string, ok bool) {
value, ok = getValue(name)
AddSecret(value)
return
}
func getValue(name string) (string, bool) {
if storage != nil {
if value, ok := storage.GetValue(name); ok {
return value, true
}
}
if dir, ok := os.LookupEnv("CREDENTIALS_DIRECTORY"); ok {
if value, _ := os.ReadFile(filepath.Join(dir, name)); value != nil {
return strings.TrimSpace(string(value)), true
}
}
return os.LookupEnv(name)
}
// ReplaceVars - support format ${CAMERA_PASSWORD} and ${RTSP_USER:admin}
func ReplaceVars(data []byte) []byte {
re := regexp.MustCompile(`\${([^}{]+)}`)
return re.ReplaceAllFunc(data, func(match []byte) []byte {
key := string(match[2 : len(match)-1])
var def string
var defok bool
if i := strings.IndexByte(key, ':'); i > 0 {
key, def = key[:i], key[i+1:]
defok = true
}
if value, ok := GetValue(key); ok {
return []byte(value)
}
if defok {
return []byte(def)
}
return match
})
}
@@ -0,0 +1,94 @@
package creds
import (
"io"
"net/http"
"regexp"
"slices"
"strings"
"sync"
)
func AddSecret(value string) {
if value == "" {
return
}
secretsMu.Lock()
defer secretsMu.Unlock()
if slices.Contains(secrets, value) {
return
}
secrets = append(secrets, value)
secretsReplacer = nil
}
var secrets []string
var secretsMu sync.Mutex
var secretsReplacer *strings.Replacer
var userinfoRegexp *regexp.Regexp
func getReplacer() *strings.Replacer {
secretsMu.Lock()
defer secretsMu.Unlock()
if secretsReplacer == nil {
oldnew := make([]string, 0, 2*len(secrets))
for _, s := range secrets {
oldnew = append(oldnew, s, "***")
}
secretsReplacer = strings.NewReplacer(oldnew...)
}
if userinfoRegexp == nil {
userinfoRegexp = regexp.MustCompile(`://[` + userinfo + `]+@`)
}
return secretsReplacer
}
// Uniform Resource Identifier (URI)
// https://datatracker.ietf.org/doc/html/rfc3986
const (
unreserved = `A-Za-z0-9-._~`
subdelims = `!$&'()*+,;=`
userinfo = unreserved + subdelims + `%:`
)
func SecretString(s string) string {
re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.Replace(s)
}
func SecretWrite(w io.Writer, s string) (n int, err error) {
re := getReplacer()
s = userinfoRegexp.ReplaceAllString(s, `://***@`)
return re.WriteString(w, s)
}
func SecretWriter(w io.Writer) io.Writer {
return &secretWriter{w}
}
type secretWriter struct {
w io.Writer
}
func (s *secretWriter) Write(b []byte) (int, error) {
return SecretWrite(s.w, string(b))
}
func SecretResponse(w http.ResponseWriter) http.ResponseWriter {
return &secretResponse{w}
}
type secretResponse struct {
http.ResponseWriter
}
func (s *secretResponse) Write(b []byte) (int, error) {
return SecretWrite(s.ResponseWriter, string(b))
}
@@ -0,0 +1,15 @@
package creds
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestString(t *testing.T) {
AddSecret("admin")
AddSecret("pa$$word")
s := SecretString("rtsp://admin:pa$$word@192.168.1.123/stream1")
require.Equal(t, "rtsp://***:***@192.168.1.123/stream1", s)
}