mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 20:17:08 +00:00
128 lines
2.7 KiB
Go
128 lines
2.7 KiB
Go
package xmppsig
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"dev.narayana.im/narayana/telegabber/calls/signaling"
|
|
"dev.narayana.im/narayana/telegabber/xmpp/jingle"
|
|
|
|
"github.com/pion/webrtc/v4"
|
|
)
|
|
|
|
// per-call state shared by Caller and Callee
|
|
type xmppBase struct {
|
|
a *Adapter
|
|
remote string
|
|
// full JID we act as on the wire; falls back to a.cfg.LocalJID
|
|
localJID string
|
|
// CallerSide/CalleeSide for Bind's MediaConnected wiring
|
|
side signaling.Side
|
|
|
|
mu sync.Mutex
|
|
sid string
|
|
session *jingle.Session
|
|
bridge *signaling.Bridge
|
|
pc *webrtc.PeerConnection
|
|
remoteSDPSeen bool
|
|
onRemoteSDP func(sdp string)
|
|
|
|
// pion fires OnTrack during SetRemoteDescription, before any handler
|
|
// the orchestrator might want to install - so hookTrack runs a permanent
|
|
// forwarder at PC construction and buffers into pendingTracks until
|
|
// SetTrackHandler arrives
|
|
onTrackFn func(t *webrtc.TrackRemote)
|
|
pendingTracks []*webrtc.TrackRemote
|
|
}
|
|
|
|
func (b *xmppBase) set(sid string, sess *jingle.Session) {
|
|
b.mu.Lock()
|
|
b.sid, b.session = sid, sess
|
|
b.mu.Unlock()
|
|
}
|
|
|
|
// attaches the bridge and wires pion's connection-state callback
|
|
func (b *xmppBase) Bind(br *signaling.Bridge) {
|
|
b.mu.Lock()
|
|
b.bridge = br
|
|
pc := b.pc
|
|
side := b.side
|
|
b.mu.Unlock()
|
|
hookPCState(pc, br, side)
|
|
}
|
|
|
|
func (b *xmppBase) bridgeRef() *signaling.Bridge {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
return b.bridge
|
|
}
|
|
|
|
func (b *xmppBase) sessionRef() *jingle.Session {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
return b.session
|
|
}
|
|
|
|
func (b *xmppBase) cleanup() {
|
|
b.mu.Lock()
|
|
sid := b.sid
|
|
b.mu.Unlock()
|
|
if sid == "" {
|
|
return
|
|
}
|
|
b.a.cfg.Manager.Unregister(sid)
|
|
}
|
|
|
|
func (b *xmppBase) PeerConnection() *webrtc.PeerConnection {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
return b.pc
|
|
}
|
|
|
|
func (b *xmppBase) SetOnRemoteSDP(fn func(sdp string)) {
|
|
b.mu.Lock()
|
|
b.onRemoteSDP = fn
|
|
b.mu.Unlock()
|
|
}
|
|
|
|
// must run before the first SetRemoteDescription, or pion's first
|
|
// OnTrack event is lost
|
|
func (b *xmppBase) hookTrack(pc *webrtc.PeerConnection) {
|
|
pc.OnTrack(func(t *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
|
|
b.mu.Lock()
|
|
fn := b.onTrackFn
|
|
if fn == nil {
|
|
b.pendingTracks = append(b.pendingTracks, t)
|
|
b.mu.Unlock()
|
|
return
|
|
}
|
|
b.mu.Unlock()
|
|
fn(t)
|
|
})
|
|
}
|
|
|
|
// swaps in the real handler and drains buffered tracks
|
|
func (b *xmppBase) SetTrackHandler(fn func(t *webrtc.TrackRemote)) {
|
|
b.mu.Lock()
|
|
b.onTrackFn = fn
|
|
pending := b.pendingTracks
|
|
b.pendingTracks = nil
|
|
b.mu.Unlock()
|
|
for _, t := range pending {
|
|
fn(t)
|
|
}
|
|
}
|
|
|
|
// fires the orchestrator hook exactly once per call
|
|
func (b *xmppBase) onRemoteDescription(sdp string) {
|
|
b.mu.Lock()
|
|
if b.remoteSDPSeen {
|
|
b.mu.Unlock()
|
|
return
|
|
}
|
|
b.remoteSDPSeen = true
|
|
hook := b.onRemoteSDP
|
|
b.mu.Unlock()
|
|
if hook != nil {
|
|
hook(sdp)
|
|
}
|
|
}
|