mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2026-04-22 23:57:20 +08:00
135 lines
2.8 KiB
Go
135 lines
2.8 KiB
Go
package streams
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
)
|
|
|
|
type Handler func(source string) (core.Producer, error)
|
|
|
|
var handlers = map[string]Handler{}
|
|
|
|
func HandleFunc(scheme string, handler Handler) {
|
|
handlers[scheme] = handler
|
|
}
|
|
|
|
func SupportedSchemes() []string {
|
|
uniqueKeys := make(map[string]struct{}, len(handlers)+len(redirects))
|
|
for scheme := range handlers {
|
|
uniqueKeys[scheme] = struct{}{}
|
|
}
|
|
for scheme := range redirects {
|
|
uniqueKeys[scheme] = struct{}{}
|
|
}
|
|
resultKeys := make([]string, 0, len(uniqueKeys))
|
|
for key := range uniqueKeys {
|
|
resultKeys = append(resultKeys, key)
|
|
}
|
|
return resultKeys
|
|
}
|
|
|
|
func HasProducer(url string) bool {
|
|
if i := strings.IndexByte(url, ':'); i > 0 {
|
|
scheme := url[:i]
|
|
|
|
if _, ok := handlers[scheme]; ok {
|
|
return true
|
|
}
|
|
|
|
if _, ok := redirects[scheme]; ok {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func GetProducer(url string) (core.Producer, error) {
|
|
if i := strings.IndexByte(url, ':'); i > 0 {
|
|
scheme := url[:i]
|
|
|
|
if redirect, ok := redirects[scheme]; ok {
|
|
location, err := redirect(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if location != "" {
|
|
return GetProducer(location)
|
|
}
|
|
}
|
|
|
|
if handler, ok := handlers[scheme]; ok {
|
|
return handler(url)
|
|
}
|
|
}
|
|
|
|
return nil, errors.New("streams: unsupported scheme: " + url)
|
|
}
|
|
|
|
// Redirect can return: location URL or error or empty URL and error
|
|
type Redirect func(url string) (string, error)
|
|
|
|
var redirects = map[string]Redirect{}
|
|
|
|
func RedirectFunc(scheme string, redirect Redirect) {
|
|
redirects[scheme] = redirect
|
|
}
|
|
|
|
func Location(url string) (string, error) {
|
|
if i := strings.IndexByte(url, ':'); i > 0 {
|
|
scheme := url[:i]
|
|
|
|
if redirect, ok := redirects[scheme]; ok {
|
|
return redirect(url)
|
|
}
|
|
}
|
|
|
|
return "", nil
|
|
}
|
|
|
|
// TODO: rework
|
|
|
|
type ConsumerHandler func(url string) (core.Consumer, func(), error)
|
|
|
|
var consumerHandlers = map[string]ConsumerHandler{}
|
|
|
|
func HandleConsumerFunc(scheme string, handler ConsumerHandler) {
|
|
consumerHandlers[scheme] = handler
|
|
}
|
|
|
|
func GetConsumer(url string) (core.Consumer, func(), error) {
|
|
if i := strings.IndexByte(url, ':'); i > 0 {
|
|
scheme := url[:i]
|
|
|
|
if handler, ok := consumerHandlers[scheme]; ok {
|
|
return handler(url)
|
|
}
|
|
}
|
|
|
|
return nil, nil, errors.New("streams: unsupported scheme: " + url)
|
|
}
|
|
|
|
var insecure = map[string]bool{}
|
|
|
|
func MarkInsecure(scheme string) {
|
|
insecure[scheme] = true
|
|
}
|
|
|
|
var sanitize = regexp.MustCompile(`\s`)
|
|
|
|
func Validate(source string) error {
|
|
// TODO: Review the entire logic of insecure sources
|
|
if i := strings.IndexByte(source, ':'); i > 0 {
|
|
if insecure[source[:i]] {
|
|
return errors.New("streams: source from insecure producer")
|
|
}
|
|
}
|
|
if sanitize.MatchString(source) {
|
|
return errors.New("streams: source with spaces may be insecure")
|
|
}
|
|
return nil
|
|
}
|