session

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package session binds pkg/sip1/rtp to pkg/media using pkg/sip1/sdp negotiation (no duplicate codec math).

Use NewMediaLeg after sdp.Parse on the INVITE body and configuring the RTP session remote address from the offer. Media uses pkg/media/encoder CreateDecode/CreateEncode only.

Index

Constants

View Source
const (
	RecordingDirUser = recDirUser
	RecordingDirAI   = recDirAI
)

RecordingDirUser / RecordingDirAI match SN3 dir bytes for AppendRecordingSample (e.g. SIP transfer raw relay).

Variables

This section is empty.

Functions

func ApplyRemoteSDP

func ApplyRemoteSDP(sess *siprtp.Session, info *sdp.Info) error

ApplyRemoteSDP sets RTP remote address from sdp.Info (m= / c=).

func InternalPCMSampleRate

func InternalPCMSampleRate(src media.CodecConfig) int

InternalPCMSampleRate chooses the MediaSession PCM bridge rate for a negotiated RTP codec so decode/encode avoids unnecessary resampling (e.g. keep G.711 at 8 kHz, Opus at negotiated clock, G.722 at 16 kHz PCM).

func NegotiateOffer

func NegotiateOffer(offer []sdp.Codec) (src media.CodecConfig, neg sdp.Codec, err error)

NegotiateOffer picks the first supported audio codec from a remote SDP offer (ordered by preference).

Types

type CallSession

type CallSession struct {
	CallID string
	// contains filtered or unexported fields
}

CallSession binds an RTP session to a MediaSession for SIP calls.

Uplink: RTP -> decode -> PCM for ASR processors. Downlink: only synthesized (TTS) PCM is encoded and sent as RTP; uplink is not echoed (see media.KeySIPSuppressUplinkEcho).

func NewCallSession

func NewCallSession(callID string, rtpSess *rtp.Session, sdpCodecs []sdp.Codec) (*CallSession, error)

NewCallSession creates a call session with codec negotiation from SDP.

func (*CallSession) AppendRecordingSample

func (cs *CallSession) AppendRecordingSample(dir byte, seq uint16, ts uint32, payload []byte)

AppendRecordingSample appends one RTP payload to the SN3 blob (used during transfer bridge when media bypasses the original rx/tx transports).

func (*CallSession) ArmSessionTimerWatchdog

func (cs *CallSession) ArmSessionTimerWatchdog(interval time.Duration, onExpiry func())

ArmSessionTimerWatchdog starts an RFC 4028 watchdog. If no TouchSessionTimer call arrives within `interval`, onExpiry runs (the SIP server wires this to "send BYE with Reason: SIP;cause=408").

Calling Arm a second time replaces any prior watchdog (e.g. timer was renegotiated by a re-INVITE). interval <= 0 stops the watchdog.

Safe to call on nil receiver (no-op).

func (*CallSession) AttachVoiceConversation

func (cs *CallSession) AttachVoiceConversation(fn func() error) error

AttachVoiceConversation runs fn once before media Serve() (typically from ACK) to register processors or other hooks. If fn fails, a later call may retry.

func (*CallSession) CloseRTPOnly

func (cs *CallSession) CloseRTPOnly()

CloseRTPOnly closes the RTP UDP socket after a bridge or full teardown path.

func (*CallSession) DTMFPayloadType

func (cs *CallSession) DTMFPayloadType() uint8

DTMFPayloadType is the negotiated telephone-event PT, or 0 if none.

func (*CallSession) EnableRecorder

func (cs *CallSession) EnableRecorder(cfg RecorderConfig) bool

EnableRecorder arms stereo PCM taps when the sink accepts BeginRecording.

func (*CallSession) FlushRecorder

func (cs *CallSession) FlushRecorder(ctx context.Context) (RecordingInfo, bool)

FlushRecorder delivers the SN3 blob to RecordingSink.FinishRecording.

func (*CallSession) HasRecorder

func (cs *CallSession) HasRecorder() bool

HasRecorder reports whether stereo PCM taps are armed.

func (*CallSession) InboundRetargetHeaders

func (cs *CallSession) InboundRetargetHeaders() (string, string, string)

InboundRetargetHeaders returns (rawTo, rawHistoryInfo, rawDiversion) captured at INVITE intake. Empty strings when not set (e.g. outbound- originated CallSession). Consumers should treat the strings as opaque SIP header values and pass them through historyinfo.ParseChain / ParseDiversionChain.

func (*CallSession) InboundUnboundTenant

func (cs *CallSession) InboundUnboundTenant() bool

InboundUnboundTenant is true when the inbound number is not bound to a tenant (play not_bind.wav).

func (*CallSession) MediaSession

func (cs *CallSession) MediaSession() *media.MediaSession

MediaSession exposes the underlying media pipeline for voice processors (ASR/TTS hooks).

func (*CallSession) NegotiatedCodec

func (cs *CallSession) NegotiatedCodec() sdp.Codec

func (*CallSession) PCMSampleRate

func (cs *CallSession) PCMSampleRate() int

PCMSampleRate is the internal mono PCM rate produced by RTP decode (and fed to ASR processors).

func (*CallSession) RTCPStats

func (cs *CallSession) RTCPStats() rtp.RTCPStats

RTCPStats returns a one-shot RTCP counter snapshot (safe at BYE; O(1)).

func (*CallSession) RTPSession

func (cs *CallSession) RTPSession() *rtp.Session

RTPSession returns the underlying RTP/UDP session (for building a transfer bridge).

func (*CallSession) RemoteFromHeader

func (cs *CallSession) RemoteFromHeader() string

RemoteFromHeader 返回入站 INVITE 的 From header;nil 或未注入时返回 ""。

func (*CallSession) SetInboundRetargetHeaders

func (cs *CallSession) SetInboundRetargetHeaders(toHdr, historyInfo, diversion string)

SetInboundRetargetHeaders captures the raw To header plus any pre-existing History-Info / Diversion headers from the inbound INVITE. Called by sip/server at INVITE intake. Arguments are trimmed; empty ones are ignored so re-calling with partial info doesn't clobber previously-stored values.

func (*CallSession) SetInboundUnboundTenant

func (cs *CallSession) SetInboundUnboundTenant(v bool)

SetInboundUnboundTenant marks inbound calls where the called DID is not assigned to any tenant.

func (*CallSession) SetRemoteFromHeader

func (cs *CallSession) SetRemoteFromHeader(v string)

SetRemoteFromHeader 由 sip/server 在 INVITE 入站时调用,记录 PSTN 主叫 的原始 From header 供转接路径回显。nil-safe / 空值跳过。

func (*CallSession) SetTenantID

func (cs *CallSession) SetTenantID(id uint)

SetTenantID records the tenant scope for media/AI (inbound DID or outbound campaign).

func (*CallSession) SourceCodec

func (cs *CallSession) SourceCodec() media.CodecConfig

SourceCodec is the negotiated RTP codec (PCMU/PCMA/G722/OPUS) for this leg.

func (*CallSession) Start

func (cs *CallSession) Start()

Start starts MediaSession serving in background.

func (*CallSession) StartOnACK

func (cs *CallSession) StartOnACK()

StartOnACK starts media pipeline once (idempotent) when ACK is received.

func (*CallSession) Stop

func (cs *CallSession) Stop()

Stop stops the session and closes underlying RTP resources.

func (*CallSession) StopMediaPreserveRTP

func (cs *CallSession) StopMediaPreserveRTP()

StopMediaPreserveRTP stops the MediaSession (AI pipeline, RTP read/write loops) but keeps the UDP socket open so new SIPRTPTransport instances can attach for bridging.

func (*CallSession) StopSessionTimer

func (cs *CallSession) StopSessionTimer()

StopSessionTimer cancels any pending watchdog. Called automatically from Stop(); also called by the server when BYE arrives before expiry.

func (*CallSession) TakeRecording

func (cs *CallSession) TakeRecording() []byte

TakeRecording returns buffered RTP recording (SN3 …) and clears the buffer.

func (*CallSession) TenantID

func (cs *CallSession) TenantID() uint

TenantID returns the tenant id bound to this call (0 = none / legacy).

func (*CallSession) TouchSessionTimer

func (cs *CallSession) TouchSessionTimer()

TouchSessionTimer resets the watchdog back to the full interval. Call this every time we accept a refresh re-INVITE or UPDATE in the dialog. No-op when no watchdog is armed.

func (*CallSession) WireTransferBridgeRecording

func (cs *CallSession) WireTransferBridgeRecording(callerRx, callerTx *rtp.SIPRTPTransport)

WireTransferBridgeRecording attaches SN3 callbacks to PCM-bridge transports sharing inbound RTP session.

func (*CallSession) WriteAIPCM

func (cs *CallSession) WriteAIPCM(pcm []byte)

WriteAIPCM forwards decoded agent/AI PCM to the recording sink when armed.

func (*CallSession) WriteCallerPCM

func (cs *CallSession) WriteCallerPCM(pcm []byte)

WriteCallerPCM forwards decoded caller PCM to the recording sink when armed.

type MediaLeg

type MediaLeg struct {
	// contains filtered or unexported fields
}

MediaLeg is one RTP leg wired to a MediaSession (decode uplink / encode downlink) using pkg/media/encoder.

func NewMediaLeg

func NewMediaLeg(parent context.Context, callID string, rtpSess *siprtp.Session, offer []sdp.Codec, cfg MediaLegConfig) (*MediaLeg, error)

NewMediaLeg builds decode/encode chain from the remote SDP offer codecs and attaches RTP transports. rtpSess must already be listening; call ApplyRemoteSDP before Start if offer contains c=/m=.

func (*MediaLeg) CloseRTPOnly

func (l *MediaLeg) CloseRTPOnly()

CloseRTPOnly closes the RTP UDP socket without touching a nil MediaSession (e.g. after WebRTC bridge teardown).

func (*MediaLeg) DTMFPayloadType

func (l *MediaLeg) DTMFPayloadType() uint8

DTMFPayloadType returns the negotiated RFC 2833 telephone-event PT, or 0.

func (*MediaLeg) MediaSession

func (l *MediaLeg) MediaSession() *media.MediaSession

MediaSession exposes the underlying media pipeline.

func (*MediaLeg) NegotiatedSDP

func (l *MediaLeg) NegotiatedSDP() sdp.Codec

NegotiatedSDP returns the chosen sdp.Codec line.

func (*MediaLeg) PCMSampleRate

func (l *MediaLeg) PCMSampleRate() int

PCMSampleRate returns the internal mono PCM sample rate between decode and encode.

func (*MediaLeg) RTPSession

func (l *MediaLeg) RTPSession() *siprtp.Session

RTPSession exposes the RTP UDP session.

func (*MediaLeg) SourceCodec

func (l *MediaLeg) SourceCodec() media.CodecConfig

SourceCodec returns the negotiated RTP media.CodecConfig.

func (*MediaLeg) Start

func (l *MediaLeg) Start()

Start runs MediaSession.Serve in a background goroutine (idempotent).

func (*MediaLeg) Stop

func (l *MediaLeg) Stop()

Stop closes media and RTP.

func (*MediaLeg) StopMediaPreserveRTP

func (l *MediaLeg) StopMediaPreserveRTP()

StopMediaPreserveRTP stops the MediaSession and RTP transport loops but keeps the UDP socket open so new SIPRTPTransport instances can attach for a two-leg bridge (same idea as pkg/sip/session.CallSession).

type MediaLegConfig

type MediaLegConfig struct {
	OutputQueueSize   int  // default 512
	MaxSessionSeconds int  // 0 = no limit; passed to media.MediaSession.MaxSessionDuration (seconds)
	AllowUplinkEcho   bool // if false (default), set media.KeySIPSuppressUplinkEcho
}

MediaLegConfig optional tuning for MediaLeg.

type RecorderConfig

type RecorderConfig struct {
	Meta       hooks.CallMeta
	SampleRate int
	Codec      string
	Sink       hooks.RecordingSink // nil → hooks.DefaultRegistry.Recording
}

RecorderConfig configures optional stereo PCM taps via hooks.RecordingSink. SN3 RTP capture in CallSession is always available via TakeRecording regardless of this config.

type RecordingInfo

type RecordingInfo struct {
	CallID    string
	URL       string
	ObjectKey string
}

RecordingInfo is a durable handle returned after FlushRecorder (URL/object key from hooks.RecordingSink).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL