host our own shit
This commit is contained in:
@@ -103,6 +103,7 @@ func handleWebrtcPublish(ctx context.Context, env *runtime.Env, cmdID string, pa
|
||||
PublishToken: token,
|
||||
TLSInsecureSkipVerify: env.Cfg.TLSInsecureSkipVerify,
|
||||
TLSCAPath: env.Cfg.TLSCAPath,
|
||||
ICEServers: parseICEServers(payload["iceServers"]),
|
||||
HasVideo: hasVideo,
|
||||
HasAudio: hasAudio,
|
||||
}
|
||||
@@ -155,6 +156,7 @@ func handleWebrtcP2POffer(ctx context.Context, env *runtime.Env, cmdID string, p
|
||||
kindStr := string(kind)
|
||||
|
||||
callbacks := webrtcpub.P2POfferCallbacks{
|
||||
ICEServers: parseICEServers(payload["iceServers"]),
|
||||
OnICE: func(c webrtcpub.ICECandidate) {
|
||||
if c.Candidate == "" {
|
||||
return
|
||||
@@ -203,6 +205,64 @@ func handleWebrtcP2POffer(ctx context.Context, env *runtime.Env, cmdID string, p
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseICEServers(value interface{}) []webrtcpub.ICEServer {
|
||||
items, ok := value.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
servers := make([]webrtcpub.ICEServer, 0, len(items))
|
||||
for _, item := range items {
|
||||
if len(servers) >= 8 {
|
||||
break
|
||||
}
|
||||
entry, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var urls []string
|
||||
switch raw := entry["urls"].(type) {
|
||||
case string:
|
||||
urls = appendICEURL(urls, raw)
|
||||
case []interface{}:
|
||||
for _, value := range raw {
|
||||
if url, ok := value.(string); ok && len(urls) < 8 {
|
||||
urls = appendICEURL(urls, url)
|
||||
}
|
||||
}
|
||||
case []string:
|
||||
for _, url := range raw {
|
||||
if len(urls) < 8 {
|
||||
urls = appendICEURL(urls, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(urls) == 0 {
|
||||
continue
|
||||
}
|
||||
username, _ := entry["username"].(string)
|
||||
credential, _ := entry["credential"].(string)
|
||||
servers = append(servers, webrtcpub.ICEServer{URLs: urls, Username: username, Credential: credential})
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
func appendICEURL(urls []string, value string) []string {
|
||||
if len(value) == 0 || len(value) > 512 {
|
||||
return urls
|
||||
}
|
||||
valid := false
|
||||
for _, prefix := range []string{"stun:", "stuns:", "turn:", "turns:"} {
|
||||
if len(value) >= len(prefix) && value[:len(prefix)] == prefix {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
return urls
|
||||
}
|
||||
return append(urls, value)
|
||||
}
|
||||
|
||||
func handleWebrtcP2PIce(_ context.Context, env *runtime.Env, cmdID string, payload map[string]interface{}) error {
|
||||
sessionID, _ := payload["sessionId"].(string)
|
||||
candidate, _ := payload["candidate"].(string)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package handlers
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseICEServers(t *testing.T) {
|
||||
servers := parseICEServers([]interface{}{
|
||||
map[string]interface{}{"urls": []interface{}{"stun:turn.example.test:3478"}},
|
||||
map[string]interface{}{
|
||||
"urls": []interface{}{"turn:turn.example.test:3478?transport=udp", "turn:turn.example.test:3478?transport=tcp", "https://invalid.example"},
|
||||
"username": "expiry:agent",
|
||||
"credential": "derived-secret",
|
||||
},
|
||||
})
|
||||
if len(servers) != 2 {
|
||||
t.Fatalf("server count = %d, want 2", len(servers))
|
||||
}
|
||||
if len(servers[1].URLs) != 2 {
|
||||
t.Fatalf("TURN URL count = %d, want 2", len(servers[1].URLs))
|
||||
}
|
||||
if servers[1].Username != "expiry:agent" || servers[1].Credential != "derived-secret" {
|
||||
t.Fatal("TURN credentials were not preserved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseICEServersRejectsInvalidInput(t *testing.T) {
|
||||
servers := parseICEServers([]interface{}{
|
||||
map[string]interface{}{"urls": "https://not-an-ice-server"},
|
||||
"invalid",
|
||||
})
|
||||
if len(servers) != 0 {
|
||||
t.Fatalf("server count = %d, want 0", len(servers))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user