Documentation
¶
Overview ¶
Package outbound implements SIP UAC (outbound) signaling without media binding.
It shares the UDP socket with inbound UAS via SignalingSender (see gateway.Endpoint). Responses are routed through Manager.HandleSIPResponse on stack.EndpointConfig.OnSIPResponse.
Supported signaling:
Index ¶
- Constants
- Variables
- type DialEvent
- type DialRequest
- type DialTarget
- type EstablishedLeg
- type Manager
- func (m *Manager) BindSender(s SignalingSender)
- func (m *Manager) CleanupLegIfPresent(callID, reasonClass string)
- func (m *Manager) ClosePool() error
- func (m *Manager) Dial(ctx context.Context, req DialRequest) (callID string, err error)
- func (m *Manager) HandleSIPResponse(resp *stack.Message, addr *net.UDPAddr)
- func (m *Manager) SendBYE(callID string) error
- func (m *Manager) SendCANCEL(callID string) error
- type ManagerConfig
- type Scenario
- type SignalingSender
- type Transport
Constants ¶
const ( DialEventInvited = "invited" DialEventProvisional = "provisional" DialEventEstablished = "established" DialEventFailed = "failed" )
Variables ¶
var ( // ErrNoSignalingSender is returned when Dial is called before BindSender. ErrNoSignalingSender = errors.New("sip/outbound: signaling sender not bound") // ErrNotImplemented marks transfer/bridge paths not yet wired. ErrNotImplemented = errors.New("sip/outbound: not implemented") )
Functions ¶
This section is empty.
Types ¶
type DialEvent ¶
type DialEvent struct {
CallID string
CorrelationID string
Scenario Scenario
State string
StatusCode int
Reason string
At time.Time
RequestURI string
StatusText string
RemoteAddr string
}
DialEvent streams dial lifecycle transitions.
type DialRequest ¶
type DialRequest struct {
Scenario Scenario
Target DialTarget
CorrelationID string
ScriptID string
CallerUser string
CallerDisplayName string
AssertedIdentityURI string
AssertedIdentityDisplayName string
PrivacyTokens []string
HistoryInfo []historyinfo.Entry
Diversion []historyinfo.Diversion
// RTPPort is advertised in the SDP offer only (signaling demo default 10000).
RTPPort int
// Codecs overrides the default outbound offer list when non-empty.
Codecs []sdp.Codec
// OfferSRTP adds SDES a=crypto to the SDP offer (RTP/SAVPF).
OfferSRTP bool
}
DialRequest is one outbound signaling attempt (no media binding).
type DialTarget ¶
type DialTarget struct {
RequestURI string // e.g. sip:1001@192.168.1.10;user=phone
SignalingAddr string // host:port of proxy or UAS
CallerUser string
CallerDisplayName string
Transport Transport
}
DialTarget describes the next SIP hop for an outbound INVITE.
func DialTargetFromReferTo ¶
func DialTargetFromReferTo(referTo string) (DialTarget, error)
DialTargetFromReferTo parses a Refer-To header value (possibly angle-bracketed) into a DialTarget. Host and port for SignalingAddr come from the SIP URI authority; default port is 5060 when omitted.
type EstablishedLeg ¶
type EstablishedLeg struct {
CallID string
Scenario Scenario
CorrelationID string
CreatedAt time.Time
FromHeader string
ToHeader string
RemoteSignalingAddr string
CSeqInvite string
Answer *sdp.Info
}
EstablishedLeg is delivered after 200 OK + ACK (signaling complete).
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns outbound SIP legs keyed by Call-ID.
func NewManager ¶
func NewManager(cfg ManagerConfig) *Manager
NewManager constructs a manager; call BindSender before Dial.
func (*Manager) BindSender ¶
func (m *Manager) BindSender(s SignalingSender)
BindSender wires the UDP signaling path (required for Dial).
func (*Manager) CleanupLegIfPresent ¶
CleanupLegIfPresent removes outbound leg state when no longer needed, e.g. after remote BYE. reasonClass is the bounded enum extracted from the peer's RFC 3326 Reason header (empty string → default "normal"). Both the BYE counter and the CDR hangup_reason inherit this value.
func (*Manager) HandleSIPResponse ¶
HandleSIPResponse routes inbound responses to outbound legs.
func (*Manager) SendBYE ¶
SendBYE sends an in-dialog BYE for an established outbound leg (after 200 OK to INVITE).
func (*Manager) SendCANCEL ¶
SendCANCEL emits a SIP CANCEL for a not-yet-established outbound INVITE leg (transfer-agent ring, campaign abandon, etc). Safe to call concurrently with the response handler; idempotent (second call is a no-op).
Behavior:
- if the INVITE has not yet received its first 1xx provisional, the CANCEL is QUEUED (RFC 3261 §9.1) and fires either when 1xx arrives or after a 500ms grace timer, whichever comes first
- if 1xx already received, CANCEL goes on the wire immediately and a retransmit goroutine starts (T1=500ms, capped at T2=4s, 6 attempts) per RFC 3261 §17.1.2
- second call is a no-op (cancelSent CompareAndSwap guard) so the inbound-BYE path and ring-timeout path can both invoke safely
Returns nil on success (queued or sent). Common error reasons:
- unknown call-id (leg already torn down / never existed)
- leg already established (CANCEL is illegal — caller should use SendBYE instead)
type ManagerConfig ¶
type ManagerConfig struct {
LocalIP string // SDP c= line
SIPHost string // Via / Contact host
SIPPort int
FromUser string
FromDisplayName string
DefaultRTPPort int
OnEstablished func(EstablishedLeg)
OnEvent func(DialEvent)
OnDialogCallIDAdopted func(oldID, newID, correlationID string)
OnSignalingSent func(*stack.Message, *net.UDPAddr)
TLSConfig *tls.Config
}
ManagerConfig configures outbound signaling (no RTP/media).
type SignalingSender ¶
SignalingSender sends SIP on a shared UDP socket.
type Transport ¶
type Transport string
Transport identifies the SIP signaling transport for an outbound leg. Stringer values are the lowercase RFC 3261 §7.1 form used in Via headers and Request-URI ;transport= parameters.
const ( // TransportUDP is unreliable datagram (RFC 3261 §18.1). Default. TransportUDP Transport = "udp" // TransportTCP is connection-oriented byte stream framed by // Content-Length (RFC 3261 §18.2). Connection reuse follows // RFC 5923. TransportTCP Transport = "tcp" // TransportTLS is TCP wrapped in TLS, paired with the SIPS URI // scheme on Contact / Via (RFC 3261 §26.2.1). TransportTLS Transport = "tls" // TransportUnset means "no preference" — selection falls through // to the next precedence layer or to TransportUDP. TransportUnset Transport = "" )
func ResolveTransport ¶
func ResolveTransport(target DialTarget) Transport
ResolveTransport applies the precedence rules above:
URI param > target.Transport (trunk config) > TransportUDP
Always returns a valid (non-Unset) transport.
func (Transport) IsConnectionOriented ¶
IsConnectionOriented reports whether the transport requires per-target conn lifecycle management (TCP/TLS) versus the shared-socket model (UDP).
func (Transport) IsTLS ¶
IsTLS reports whether the transport requires TLS handshaking. The caller should also use the `sips:` URI scheme in Contact / Via when this returns true (RFC 3261 §26.2.1).