Documentation
¶
Index ¶
- func ComputeSignature(authToken, rawURL string, params url.Values) string
- func DefaultHandleStream(ctx context.Context, conn *websocket.Conn, start Frame) error
- func EncodeClear(streamSID string) ([]byte, error)
- func EncodeConnected() ([]byte, error)
- func EncodeDTMF(streamSID, digit string) ([]byte, error)
- func EncodeMark(streamSID, name string) ([]byte, error)
- func EncodeMedia(streamSID string, payload []byte) ([]byte, error)
- func EncodeMediaWithMetadata(streamSID string, payload []byte, chunk, seqNum int) ([]byte, error)
- func EncodeStart(streamSID, callSID, accountSID string, seqNum int) ([]byte, error)
- func EncodeStop(streamSID, callSID, accountSID string, seqNum int) ([]byte, error)
- func HandleStreamWithOpts(ctx context.Context, conn *websocket.Conn, start Frame, ...) error
- func ValidateSignature(authToken, rawURL string, params url.Values, signature string) bool
- type Demux
- type EventType
- type Frame
- type InboundSMS
- type SMSHandler
- type Server
- type StreamHandler
- type Tap
- type TeardownSignaler
- type TwilioControlPlaneInput
- type TwilioControlPlaneOutput
- type TwilioDataPlaneInput
- type TwilioDataPlaneOutput
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ComputeSignature ¶
ComputeSignature returns the base64-encoded HMAC-SHA1 signature Twilio expects for a webhook request: the raw URL followed by each sorted POST param key and value, keyed with authToken. See https://www.twilio.com/docs/usage/webhooks/webhooks-security
func DefaultHandleStream ¶
DefaultHandleStream is the default session handler. It drives a live telephony.Session for the call: media frames are pumped into the session for VAD processing, and the session is closed exactly once when the call ends (a stop frame, a read error, or context cancellation).
func EncodeClear ¶
EncodeClear encodes a Twilio clear event (flushes Twilio's audio buffer).
func EncodeConnected ¶
EncodeConnected encodes a Twilio connected event (sent by client to acknowledge connection).
func EncodeDTMF ¶
EncodeDTMF is a panic-stub for DTMF encoding (not yet implemented).
func EncodeMark ¶
func EncodeMediaWithMetadata ¶
EncodeMediaWithMetadata encodes an outgoing media frame with monotonic chunk numbering and its ms-offset timestamp from stream start. chunk is 1-based; timestamp is the frame's start offset, so chunk 1 → "0", chunk 2 → "20", etc. (frames are muLawFrame20ms wide). seqNum is the per-message sequence number for this Media Streams WebSocket session. Per the Twilio spec, sequenceNumber, chunk, and timestamp are all emitted as JSON strings.
func EncodeStart ¶
EncodeStart encodes the Twilio start event that a client sends at the beginning of a Media Streams WebSocket session. seqNum is the per-message sequence number for this session, emitted as a JSON string.
func EncodeStop ¶
EncodeStop encodes the Twilio stop event that a client sends at the end of a Media Streams WebSocket session. seqNum is the per-message sequence number for this Media Streams WebSocket session, emitted as a JSON string.
func HandleStreamWithOpts ¶
func HandleStreamWithOpts(ctx context.Context, conn *websocket.Conn, start Frame, extraOpts ...telephony.SessionOption) error
HandleStreamWithOpts is like DefaultHandleStream but accepts additional SessionOptions to be passed to the session factory.
func ValidateSignature ¶
params should be the parsed POST body (r.PostForm); pass nil for GET requests. See https://www.twilio.com/docs/usage/webhooks/webhooks-security
Types ¶
type Demux ¶
type Demux struct {
Data TwilioDataPlaneInput
Control TwilioControlPlaneInput
// contains filtered or unexported fields
}
Demux is a single WebSocket-reading goroutine's decode-and-route point: it decodes Twilio Media Streams frames and routes them by event type — EventMedia to the data plane, everything else to the control plane — while detecting gaps in the media chunk sequence. session.go integration (wiring these planes into a live session) is deferred to SOP-115/F.
func NewDemux ¶
func NewDemux() *Demux
NewDemux builds a Demux with production buffer depths: the data plane sized per SOP-116's ComputeDepth(DataPlaneBufferMS, MuLawFrameMS), and a depth-16 control plane.
func NewDemuxWithPlanes ¶
func NewDemuxWithPlanes(data TwilioDataPlaneInput, control TwilioControlPlaneInput) *Demux
NewDemuxWithPlanes builds a Demux from existing data/control planes — used by tests that need non-default buffer depths.
func (*Demux) CloseData ¶
func (d *Demux) CloseData()
CloseData closes the data plane if its concrete type supports it, marking the teardown boundary so the data pump drains and terminates on the resulting errPlaneClosed rather than on context cancellation. A no-op for a data plane that is not a closer.
type Frame ¶
type Frame struct {
Event EventType
StreamSID string
Payload []byte // decoded μ-law audio; non-nil only for EventMedia
Chunk int // monotonic frame sequence number; only set for EventMedia
Timestamp string // ms offset from stream start; only set for EventMedia
MarkName string // non-empty only for EventMark
CallSID string // non-empty only for EventStart
}
Frame is a decoded Twilio Media Streams WebSocket message.
func DecodeFrame ¶
type InboundSMS ¶
type InboundSMS struct {
MessageSID string // Twilio MessageSid
From string // sender, E.164
To string // the Twilio number that received it, E.164
Body string // message text
}
InboundSMS is the parsed subset of a Twilio inbound-message webhook. Additional fields (NumMedia, MediaUrl0…, NumSegments, …) remain available on the raw form if a consumer needs them later.
type SMSHandler ¶
type SMSHandler func(ctx context.Context, msg InboundSMS)
SMSHandler is called by ServeSMS for each validated inbound-SMS webhook. It is fire-and-forget: ServeSMS always answers Twilio with empty TwiML regardless, so a synchronous reply is not modeled here (a future reply path is a separate change).
type Server ¶
type Server struct {
AuthToken string
HandleStream StreamHandler
HandleSMS SMSHandler
// StreamScheme selects the scheme advertised in the TwiML <Stream url>
// and, correspondingly, the scheme used to reconstruct the URL for
// signature validation. "ws" advertises/validates over ws/http; "wss"
// or the zero value "" advertise/validate over wss/https (secure by
// default — a directly-constructed Server{} is never accidentally
// insecure).
StreamScheme string
}
Server handles Twilio HTTP webhook requests and WebSocket Media Streams connections. Set AuthToken to the Twilio auth token for the account; every inbound webhook request is validated against the X-Twilio-Signature header before processing. Set HandleStream to handle incoming Media Streams WebSocket connections, and HandleSMS to handle inbound SMS webhooks.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler for the Twilio call webhook. It validates the request signature (403 on failure, including an empty AuthToken), then validates the caller's E.164 From number (403 on failure), logs From and CallSid, and responds with TwiML instructing Twilio to open the Media Streams WebSocket at /streams.
func (*Server) ServeSMS ¶
func (s *Server) ServeSMS(w http.ResponseWriter, r *http.Request)
ServeSMS handles a Twilio inbound-SMS webhook. It validates the request signature (403 on failure, including an empty AuthToken), parses the message fields into InboundSMS, hands them to HandleSMS if set, and answers with empty TwiML so Twilio sends no automatic reply.
func (*Server) ServeStreams ¶
func (s *Server) ServeStreams(w http.ResponseWriter, r *http.Request)
ServeStreams handles a Twilio Media Streams WebSocket connection. It upgrades the HTTP connection to WebSocket, reads the mandatory start frame (optionally preceded by a connected frame), then calls HandleStream. If HandleStream is nil, inbound frames are read and discarded until the client disconnects.
type StreamHandler ¶
StreamHandler is called by ServeStreams for each accepted Twilio Media Streams WebSocket connection, after the mandatory start frame has been decoded. The handler owns the connection for the duration of the call and returns when done.
type TeardownSignaler ¶
type TeardownSignaler interface {
// Teardown returns a channel that is closed exactly once, when the
// control plane overflows.
Teardown() <-chan struct{}
}
TeardownSignaler is implemented by control-plane inputs that can signal a fatal, unrecoverable overflow requiring the call to be torn down.
type TwilioControlPlaneInput ¶
type TwilioControlPlaneInput = telephony.ServiceInput[Frame]
TwilioControlPlaneInput is the SOP-116 ServiceInput pattern specialized to Frame for the Twilio control plane (start/stop/mark/clear events). Its concrete implementation (controlPlaneInput) treats a full buffer as fatal rather than dropping or blocking indefinitely.
func NewControlPlane ¶
func NewControlPlane(depth int) TwilioControlPlaneInput
NewControlPlane returns a new TwilioControlPlaneInput with the given buffer depth. Sending into a full control plane is fatal — see Send.
type TwilioControlPlaneOutput ¶
type TwilioControlPlaneOutput = telephony.ServiceOutput[telephony.ControlOutMessage]
TwilioControlPlaneOutput is the send side of the channel a Session writes outbound control-plane messages to (mark/clear) (SOP-125).
func NewControlPlaneOutput ¶
func NewControlPlaneOutput(conn *websocket.Conn, streamSID string) TwilioControlPlaneOutput
NewControlPlaneOutput builds a TwilioControlPlaneOutput that writes outbound control-plane messages for streamSID to conn.
type TwilioDataPlaneInput ¶
type TwilioDataPlaneInput = telephony.ServiceInput[Frame]
TwilioDataPlaneInput is the SOP-116 ServiceInput pattern specialized to Frame for the Twilio data plane (audio media frames). Its concrete implementation (dropOldestPlane) evicts the oldest buffered frame rather than blocking when full.
func NewDataPlane ¶
func NewDataPlane(depth int) TwilioDataPlaneInput
NewDataPlane returns a new drop-oldest TwilioDataPlaneInput with the given buffer depth: once full, Send evicts the oldest buffered frame to make room for the newest one.
This is the one place the data plane's clock is read. Everything below it takes the reading, which is what lets a test assert a drop episode's reported duration exactly rather than sleeping and hoping.
type TwilioDataPlaneOutput ¶
type TwilioDataPlaneOutput = telephony.ServiceOutput[[]byte]
TwilioDataPlaneOutput is the send side of the channel a Session writes outbound media frames to (SOP-125). Twilio-package-local alias, following the same cross-package-alias-with-different-T pattern as TwilioDataPlaneInput above (avoids an import cycle: this package already imports telephony, so telephony cannot import it back).
func NewDataPlaneOutput ¶
func NewDataPlaneOutput(conn *websocket.Conn, streamSID string, tap *Tap) TwilioDataPlaneOutput
NewDataPlaneOutput builds a TwilioDataPlaneOutput that writes outbound media frames for streamSID to conn. tap may be nil (capture disabled), which is a no-op on the WriteOut call in Send below.