Documentation
¶
Overview ¶
Package stack is the SIP/2.0 signaling layer for pkg/sip.
It provides:
- Message parsing and serialization (RFC 3261–style text format)
- UDP datagram transport abstraction
- A minimal signaling Endpoint (listen, parse, dispatch requests; pass responses to a hook; optional OnResponseSent after a successful response send for UAS server-tx binding)
This package intentionally does not implement full SIP transaction state machines, digest authentication, or TCP/TLS transports yet; those belong in higher layers built on top of Message + Endpoint.
Design goals:
- No process-wide mutable defaults; configure via structs and context.
- Read loop returns on non-timeout transport errors (after optional OnReadError logging).
- SIP wire parsing (Parse/String/BodyBytesLen) and UDP signaling live in this package.
Audio codecs for RTP live in pkg/media/encoder (CreateEncode/CreateDecode); stack does not implement codecs.
Index ¶
- Constants
- func BodyBytesLen(body string) int
- func IsSignalingNoiseDatagram(b []byte) bool
- func ParseCSeqNum(cseq string) int
- func ParseRAck(h string) (rseq uint32, cseqNum int, method string, err error)
- func WithCSeqACK(inviteCSeq int) string
- type DatagramTransport
- type Endpoint
- func (e *Endpoint) AppendOnResponseSent(fn func(*Message, *Message, *net.UDPAddr))
- func (e *Endpoint) Close() error
- func (e *Endpoint) DispatchRequest(req *Message, addr *net.UDPAddr) *Message
- func (e *Endpoint) InvokeOnSIPResponse(resp *Message, addr *net.UDPAddr)
- func (e *Endpoint) ListenAddr() net.Addr
- func (e *Endpoint) Open() error
- func (e *Endpoint) RegisterHandler(method string, h HandlerFunc)
- func (e *Endpoint) Send(msg *Message, addr *net.UDPAddr) error
- func (e *Endpoint) Serve(ctx context.Context) error
- func (e *Endpoint) SetNoRouteHandler(h HandlerFunc)
- func (e *Endpoint) Transport() DatagramTransport
- type EndpointConfig
- type Event
- type EventType
- type HandlerFunc
- type Message
- type UDPTransport
- func (t *UDPTransport) Close() error
- func (t *UDPTransport) LocalAddr() net.Addr
- func (t *UDPTransport) ReadFrom(ctx context.Context, buf []byte) (int, *net.UDPAddr, error)
- func (t *UDPTransport) String() string
- func (t *UDPTransport) WriteTo(ctx context.Context, p []byte, addr *net.UDPAddr) (int, error)
Constants ¶
const ( // RFC 3261 core MethodInvite = "INVITE" MethodAck = "ACK" MethodBye = "BYE" MethodCancel = "CANCEL" MethodOptions = "OPTIONS" MethodRegister = "REGISTER" // RFC 3262 reliable provisional responses MethodPrack = "PRACK" // RFC 3265 / 6665 event state; RFC 3856 presence MethodSubscribe = "SUBSCRIBE" MethodNotify = "NOTIFY" MethodPublish = "PUBLISH" // RFC 6086 session-info; RFC 3515 transfer; RFC 3428 instant messages MethodInfo = "INFO" MethodRefer = "REFER" MethodMessage = "MESSAGE" // RFC 3311 mid-dialog parameter refresh MethodUpdate = "UPDATE" )
SIP method names (RFC 3261 and common extensions), upper-case as on the wire.
IANA registry: https://www.iana.org/assignments/sip-methods/sip-methods.xhtml Not every deployment uses all of these; stack only needs constants for registration and builders.
Variables ¶
This section is empty.
Functions ¶
func BodyBytesLen ¶
BodyBytesLen returns the byte length of the body after CRLF normalization.
func IsSignalingNoiseDatagram ¶
IsSignalingNoiseDatagram reports payloads that are never valid SIP but often hit a UDP signaling port: NAT / CRLF keepalives (e.g. "\r\n\r\n", RFC 5626 style), or whitespace-only pings. Parsing them yields "empty message" noise; callers may skip them silently.
func ParseCSeqNum ¶
ParseCSeqNum returns the sequence number from a CSeq header value (e.g. "1 INVITE" -> 1).
func WithCSeqACK ¶
WithCSeqACK returns a CSeq header value for ACK matching an INVITE CSeq number.
Types ¶
type DatagramTransport ¶
type DatagramTransport interface {
ReadFrom(ctx context.Context, buf []byte) (n int, addr *net.UDPAddr, err error)
WriteTo(ctx context.Context, p []byte, addr *net.UDPAddr) (n int, err error)
Close() error
LocalAddr() net.Addr
String() string
}
DatagramTransport is SIP message I/O over connectionless datagrams. Implementations must be safe for use from one reader and concurrent writers unless documented otherwise.
type Endpoint ¶
type Endpoint struct {
// contains filtered or unexported fields
}
Endpoint listens for SIP over UDP, parses datagrams, and dispatches requests. It provides context-aware Serve and non-timeout read errors exiting the loop (after optional OnReadError).
func NewEndpoint ¶
func NewEndpoint(cfg EndpointConfig) *Endpoint
NewEndpoint constructs an endpoint. Call Open then Serve.
func (*Endpoint) AppendOnResponseSent ¶
AppendOnResponseSent chains fn after the existing OnResponseSent callback. Call before Serve starts, or only from the setup goroutine (not concurrently with the read loop).
func (*Endpoint) DispatchRequest ¶
DispatchRequest runs the registered method handler (or NoRouteHandler) without sending on UDP. Used by alternate transports (e.g. TCP/TLS) that write responses themselves.
func (*Endpoint) InvokeOnSIPResponse ¶
InvokeOnSIPResponse calls the configured OnSIPResponse hook (e.g. for responses received on TCP).
func (*Endpoint) ListenAddr ¶
ListenAddr returns the bound UDP address after Open, or nil.
func (*Endpoint) RegisterHandler ¶
func (e *Endpoint) RegisterHandler(method string, h HandlerFunc)
RegisterHandler registers a SIP method handler (method is case-insensitive).
func (*Endpoint) Serve ¶
Serve runs the read/dispatch loop until ctx is cancelled, Close is called, or a non-timeout read error occurs (then returns a wrapped error after optional OnReadError). It returns ctx.Err() when the context was cancelled before a read completes.
func (*Endpoint) SetNoRouteHandler ¶
func (e *Endpoint) SetNoRouteHandler(h HandlerFunc)
SetNoRouteHandler sets the fallback handler for unknown methods (same as EndpointConfig.NoRouteHandler).
func (*Endpoint) Transport ¶
func (e *Endpoint) Transport() DatagramTransport
Transport returns the datagram transport after Open, or nil.
type EndpointConfig ¶
type EndpointConfig struct {
// Host and Port are the listen address (UDP IPv4).
Host string
Port int
ReadBufSize int // default 65535
ReadDeadline time.Duration // per read; default 1s (poll + responsive shutdown)
// OnReadError is called once for non-timeout read errors before Serve returns.
OnReadError func(err error)
OnDatagram func(raw []byte, addr *net.UDPAddr)
OnParseErr func(raw []byte, addr *net.UDPAddr, err error)
OnRequest func(req *Message, addr *net.UDPAddr)
OnResponse func(req *Message, resp *Message, addr *net.UDPAddr)
// OnResponseSent is invoked after a response has been successfully sent to addr (UAS final + server tx).
OnResponseSent func(req *Message, resp *Message, addr *net.UDPAddr)
OnSIPResponse func(resp *Message, addr *net.UDPAddr)
// OnMessageSent is invoked after a message is written to the UDP socket (requests and responses).
OnMessageSent func(msg *Message, addr *net.UDPAddr)
OnEvent func(e Event)
NoRouteHandler HandlerFunc
}
EndpointConfig configures a UDP signaling Endpoint.
type Event ¶
type Event struct {
Type EventType
Addr *net.UDPAddr
Raw []byte
Request *Message
Response *Message
Err error
}
Event is a lightweight observation from the read loop.
func (Event) RequestMethod ¶
RequestMethod returns the SIP method for events that carry a request (e.g. EventRequestReceived). Empty string if Request is nil.
func (Event) ResponseStatus ¶
ResponseStatus returns the SIP status code for events that carry a response (e.g. EventResponseReceived). Zero if Response is nil.
type HandlerFunc ¶
HandlerFunc handles an incoming SIP request and returns a response (or nil to send nothing).
type Message ¶
type Message struct {
Method string
RequestURI string
StatusCode int
StatusText string
Version string
Headers map[string]string // first value per canonical header name
HeadersMulti map[string][]string // all values per canonical header name (e.g. Via)
Body string
IsRequest bool
}
Message is a parsed SIP message (request or response).
func Parse ¶
Parse parses a raw SIP message into a Message. Header lines use ":"; body follows the first empty line. CRLF and bare LF are accepted.
Header folding (RFC 3261 continuation lines) is not implemented; folded headers may parse incorrectly.
func ReadMessage ¶
ReadMessage reads one SIP message from r using CRLF framing (Content-Length when body present).
func (*Message) GetHeaders ¶
GetHeaders returns all values for a header name (case-insensitive).
type UDPTransport ¶
type UDPTransport struct {
// contains filtered or unexported fields
}
UDPTransport adapts *net.UDPConn to DatagramTransport.
func NewUDPTransport ¶
func NewUDPTransport(conn *net.UDPConn) *UDPTransport
NewUDPTransport wraps an existing UDP connection.
func (*UDPTransport) Close ¶
func (t *UDPTransport) Close() error
func (*UDPTransport) LocalAddr ¶
func (t *UDPTransport) LocalAddr() net.Addr
func (*UDPTransport) ReadFrom ¶
ReadFrom reads a datagram. If ctx is cancelled, returns ctx.Err() without blocking indefinitely (requires SetReadDeadline on the conn by the caller, or Endpoint sets deadlines each iteration).
func (*UDPTransport) String ¶
func (t *UDPTransport) String() string