Add the option to pass ICE servers with an async WebRTC offer #1408

This commit is contained in:
Alex X
2024-10-24 23:31:21 +03:00
parent 9d709f0db8
commit 16e4831499
2 changed files with 46 additions and 30 deletions
+14 -14
View File
@@ -1,6 +1,7 @@
package ws package ws
import ( import (
"encoding/json"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
@@ -36,22 +37,16 @@ var log zerolog.Logger
type Message struct { type Message struct {
Type string `json:"type"` Type string `json:"type"`
Value any `json:"value,omitempty"` Value any `json:"value,omitempty"`
Raw []byte `json:"-"`
} }
func (m *Message) String() string { func (m *Message) String() (value string) {
if s, ok := m.Value.(string); ok { _ = json.Unmarshal(m.Raw, &value)
return s return
}
return ""
} }
func (m *Message) GetString(key string) string { func (m *Message) Unmarshal(v any) error {
if v, ok := m.Value.(map[string]any); ok { return json.Unmarshal(m.Raw, v)
if s, ok := v[key].(string); ok {
return s
}
}
return ""
} }
type WSHandler func(tr *Transport, msg *Message) error type WSHandler func(tr *Transport, msg *Message) error
@@ -118,8 +113,11 @@ func apiWS(w http.ResponseWriter, r *http.Request) {
}) })
for { for {
msg := new(Message) var raw struct {
if err = ws.ReadJSON(msg); err != nil { Type string `json:"type"`
Value json.RawMessage `json:"value"`
}
if err = ws.ReadJSON(&raw); err != nil {
if !websocket.IsCloseError(err, websocket.CloseNoStatusReceived) { if !websocket.IsCloseError(err, websocket.CloseNoStatusReceived) {
log.Trace().Err(err).Caller().Send() log.Trace().Err(err).Caller().Send()
} }
@@ -127,6 +125,8 @@ func apiWS(w http.ResponseWriter, r *http.Request) {
break break
} }
msg := &Message{Type: raw.Type, Raw: raw.Value}
log.Trace().Str("type", msg.Type).Msg("[api] ws msg") log.Trace().Str("type", msg.Type).Msg("[api] ws msg")
if handler := wsHandlers[msg.Type]; handler != nil { if handler := wsHandlers[msg.Type]; handler != nil {
+32 -16
View File
@@ -40,15 +40,17 @@ func Init() {
AddCandidate(network, candidate) AddCandidate(network, candidate)
} }
var err error
// create pionAPI with custom codecs list and custom network settings // create pionAPI with custom codecs list and custom network settings
serverAPI, err := webrtc.NewServerAPI(network, address, &filters) serverAPI, err = webrtc.NewServerAPI(network, address, &filters)
if err != nil { if err != nil {
log.Error().Err(err).Caller().Send() log.Error().Err(err).Caller().Send()
return return
} }
// use same API for WebRTC server and client if no address // use same API for WebRTC server and client if no address
clientAPI := serverAPI clientAPI = serverAPI
if address != "" { if address != "" {
log.Info().Str("addr", cfg.Mod.Listen).Msg("[webrtc] listen") log.Info().Str("addr", cfg.Mod.Listen).Msg("[webrtc] listen")
@@ -81,11 +83,13 @@ func Init() {
streams.HandleFunc("webrtc", streamsHandler) streams.HandleFunc("webrtc", streamsHandler)
} }
var serverAPI, clientAPI *pion.API
var log zerolog.Logger var log zerolog.Logger
var PeerConnection func(active bool) (*pion.PeerConnection, error) var PeerConnection func(active bool) (*pion.PeerConnection, error)
func asyncHandler(tr *ws.Transport, msg *ws.Message) error { func asyncHandler(tr *ws.Transport, msg *ws.Message) (err error) {
var stream *streams.Stream var stream *streams.Stream
var mode core.Mode var mode core.Mode
@@ -104,8 +108,30 @@ func asyncHandler(tr *ws.Transport, msg *ws.Message) error {
return errors.New(api.StreamNotFound) return errors.New(api.StreamNotFound)
} }
var offer struct {
Type string `json:"type"`
SDP string `json:"sdp"`
ICEServers []pion.ICEServer `json:"ice_servers"`
}
// V2 - json/object exchange, V1 - raw SDP exchange
apiV2 := msg.Type == "webrtc"
if apiV2 {
if err = msg.Unmarshal(&offer); err != nil {
return err
}
} else {
offer.SDP = msg.String()
}
// create new PeerConnection instance // create new PeerConnection instance
pc, err := PeerConnection(false) var pc *pion.PeerConnection
if offer.ICEServers == nil {
pc, err = PeerConnection(false)
} else {
pc, err = serverAPI.NewPeerConnection(pion.Configuration{ICEServers: offer.ICEServers})
}
if err != nil { if err != nil {
log.Error().Err(err).Caller().Send() log.Error().Err(err).Caller().Send()
return err return err
@@ -145,20 +171,10 @@ func asyncHandler(tr *ws.Transport, msg *ws.Message) error {
} }
}) })
// V2 - json/object exchange, V1 - raw SDP exchange log.Trace().Msgf("[webrtc] offer:\n%s", offer.SDP)
apiV2 := msg.Type == "webrtc"
// 1. SetOffer, so we can get remote client codecs // 1. SetOffer, so we can get remote client codecs
var offer string if err = conn.SetOffer(offer.SDP); err != nil {
if apiV2 {
offer = msg.GetString("sdp")
} else {
offer = msg.String()
}
log.Trace().Msgf("[webrtc] offer:\n%s", offer)
if err = conn.SetOffer(offer); err != nil {
log.Warn().Err(err).Caller().Send() log.Warn().Err(err).Caller().Send()
return err return err
} }