mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
148 lines
3.5 KiB
Go
148 lines
3.5 KiB
Go
package webrtc
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/AlexxIT/go2rtc/internal/api/ws"
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/AlexxIT/go2rtc/pkg/webrtc"
|
|
"github.com/AlexxIT/go2rtc/pkg/xnet"
|
|
pion "github.com/pion/webrtc/v4"
|
|
)
|
|
|
|
type Address struct {
|
|
host string
|
|
Port string
|
|
Network string
|
|
Priority uint32
|
|
}
|
|
|
|
func (a *Address) Host() string {
|
|
if a.host == "stun" {
|
|
ip, err := webrtc.GetCachedPublicIP()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return ip.String()
|
|
}
|
|
return a.host
|
|
}
|
|
|
|
func (a *Address) Marshal() string {
|
|
if host := a.Host(); host != "" {
|
|
return webrtc.CandidateICE(a.Network, host, a.Port, a.Priority)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
var addresses []*Address
|
|
var filters webrtc.Filters
|
|
|
|
func AddCandidate(network, address string) {
|
|
if network == "" {
|
|
AddCandidate("tcp", address)
|
|
AddCandidate("udp", address)
|
|
return
|
|
}
|
|
|
|
host, port, err := net.SplitHostPort(address)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// start from 1, so manual candidates will be lower than built-in
|
|
// and every next candidate will have a lower priority
|
|
candidateIndex := 1 + len(addresses)
|
|
|
|
priority := webrtc.CandidateHostPriority(network, candidateIndex)
|
|
addresses = append(addresses, &Address{host, port, network, priority})
|
|
}
|
|
|
|
func GetCandidates() (candidates []string) {
|
|
for _, address := range addresses {
|
|
if candidate := address.Marshal(); candidate != "" {
|
|
candidates = append(candidates, candidate)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// FilterCandidate return true if candidate passed the check
|
|
func FilterCandidate(candidate *pion.ICECandidate) bool {
|
|
if candidate == nil {
|
|
return false
|
|
}
|
|
|
|
// remove any Docker-like IP from candidates
|
|
if ip := net.ParseIP(candidate.Address); ip != nil && xnet.Docker.Contains(ip) {
|
|
return false
|
|
}
|
|
|
|
// host candidate should be in the hosts list
|
|
if candidate.Typ == pion.ICECandidateTypeHost && filters.Candidates != nil {
|
|
if !core.Contains(filters.Candidates, candidate.Address) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
if filters.Networks != nil {
|
|
networkType := NetworkType(candidate.Protocol.String(), candidate.Address)
|
|
if !core.Contains(filters.Networks, networkType) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// NetworkType convert tcp/udp network to tcp4/tcp6/udp4/udp6
|
|
func NetworkType(network, host string) string {
|
|
if strings.IndexByte(host, ':') >= 0 {
|
|
return network + "6"
|
|
} else {
|
|
return network + "4"
|
|
}
|
|
}
|
|
|
|
func asyncCandidates(tr *ws.Transport, cons *webrtc.Conn) {
|
|
tr.WithContext(func(ctx map[any]any) {
|
|
if candidates, ok := ctx["candidate"].([]string); ok {
|
|
// process candidates that receive before this moment
|
|
for _, candidate := range candidates {
|
|
_ = cons.AddCandidate(candidate)
|
|
}
|
|
|
|
// remove already processed candidates
|
|
delete(ctx, "candidate")
|
|
}
|
|
|
|
// set variable for process candidates after this moment
|
|
ctx["webrtc"] = cons
|
|
})
|
|
|
|
for _, candidate := range GetCandidates() {
|
|
log.Trace().Str("candidate", candidate).Msg("[webrtc] config")
|
|
tr.Write(&ws.Message{Type: "webrtc/candidate", Value: candidate})
|
|
}
|
|
}
|
|
|
|
func candidateHandler(tr *ws.Transport, msg *ws.Message) error {
|
|
// process incoming candidate in sync function
|
|
tr.WithContext(func(ctx map[any]any) {
|
|
candidate := msg.String()
|
|
log.Trace().Str("candidate", candidate).Msg("[webrtc] remote")
|
|
|
|
if cons, ok := ctx["webrtc"].(*webrtc.Conn); ok {
|
|
// if webrtc.Server already initialized - process candidate
|
|
_ = cons.AddCandidate(candidate)
|
|
} else {
|
|
// or collect candidate and process it later
|
|
list, _ := ctx["candidate"].([]string)
|
|
ctx["candidate"] = append(list, candidate)
|
|
}
|
|
})
|
|
|
|
return nil
|
|
}
|