telegabber/calls/signaling/xmppsig/caller.go
2026-05-25 06:27:20 -07:00

86 lines
2.1 KiB
Go

package xmppsig
import (
"context"
"dev.narayana.im/narayana/telegabber/calls/signaling"
"dev.narayana.im/narayana/telegabber/xmpp/jingle"
log "github.com/sirupsen/logrus"
)
// xmpp-side Caller for TG-originated calls; the gateway is the JMI initiator
type Caller struct {
xmppBase
}
// invoked by Bridge under its mutex; bridge re-entry must be deferred
func (c *Caller) Start() {
sess := c.sessionRef()
entry := log.WithFields(log.Fields{
"sid": sess.SID(),
"remote": c.remote,
"local_jid": c.localJID,
})
c.a.cfg.Manager.Register(sess)
if err := sess.Propose(context.Background()); err != nil {
entry.WithError(err).Error("xmppsig.Caller.Start: Session.Propose failed")
if b := c.bridgeRef(); b != nil {
go b.Terminate(signaling.ReasonUnknown)
}
return
}
}
// pick the right verb for the current session state: Close, Retract, or
// session-terminate
func (c *Caller) Terminate(reason signaling.TerminationReason) {
sess := c.sessionRef()
cond := mapReason(reason)
var err error
switch sess.State() {
case jingle.StateNew:
err = sess.Close()
case jingle.StateProposed:
err = sess.Retract(context.Background())
case jingle.StateTerminated:
// already torn down
default:
err = sess.Terminate(context.Background(), cond)
}
if err != nil {
log.WithFields(log.Fields{"reason": reason, "remote": c.remote}).
WithError(err).Debug("xmppsig.Caller.Terminate: tear-down send failed")
}
c.cleanup()
}
// jingle.SessionObserver
func (c *Caller) OnRinging(_ string) {
if b := c.bridgeRef(); b != nil {
go b.Ringing()
}
}
func (c *Caller) OnProceeded(_ string) {
if b := c.bridgeRef(); b != nil {
go b.CalleeAccepted()
}
}
func (c *Caller) OnRemoteDescriptionApplied(sdp string) {
c.onRemoteDescription(sdp)
}
// the local Terminate then no-ops on the wire because the session is
// already StateTerminated; cleanup runs early to shorten the window
// the session stays registered
func (c *Caller) OnTerminated(reason string) {
if b := c.bridgeRef(); b != nil {
go b.Terminate(reasonFromCondition(reason))
}
c.cleanup()
}