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() }