Skip to content

Allow SIPServer to be configured with interceptors. - #777

Merged
alexfish8 merged 1 commit into
mainfrom
afish/interceptors
Aug 6, 2026
Merged

Allow SIPServer to be configured with interceptors.#777
alexfish8 merged 1 commit into
mainfrom
afish/interceptors

Conversation

@alexfish8

Copy link
Copy Markdown
Contributor

Currently, the SIP server is configured so that each handler is automatically wrapped with a panic recovery interceptor. This PR removes the panic interceptors and allows SIP servers to be configured with arbitrary interceptors (so as to provide greater flexibility to users). Also, allow update NewService so that callers might specify options to be passed to the underlying server.

@alexfish8
alexfish8 marked this pull request as ready for review August 6, 2026 21:31
@alexfish8
alexfish8 requested a review from a team as a code owner August 6, 2026 21:31

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread pkg/sip/server.go
Comment on lines +324 to 331
func (s *Server) wrapHandler(handler sipgo.RequestHandler) sipgo.RequestHandler {
ret := handler
for _, interceptor := range slices.Backward(s.interceptors) {
ret = interceptor(ret)
}
return ret
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 A single failing call can now crash the whole SIP service

The safety net that caught unexpected failures while handling incoming SIP messages was removed (wrapHandler at pkg/sip/server.go:324-331) and nothing replaces it in the production startup path, so one bad call can take down the entire service and every other call on it.
Impact: An unexpected error while processing one incoming call terminates the process, dropping all in-progress calls on that node.

Removal of the panic-recovery wrapper with no default replacement

Previously every handler registered in Start was wrapped by withRecovery, which deferred a recover() and logged the panic with method/Call-ID/stack. The new wrapHandler only applies the caller-supplied s.interceptors, and WithInterceptors (pkg/sip/server.go:212-216) is never used by any production caller: cmd/livekit-sip/main.go:102, test/cloud/service.go:21, and test/integration/sip_test.go:98 all call sip.NewService without options. Consequently a panic inside onInvite/onAck/onBye/onNotify/onOptions/OnNoRoute propagates up the sipgo serving goroutine and crashes the process.

Either keep a recovery interceptor applied by default inside wrapHandler, or export a RecoveryInterceptor and install it at the NewService/main.go level.

Prompt for agents
The PR removed withRecovery, which wrapped every SIP request handler in a deferred recover() so that a panic in handling an INVITE/ACK/BYE/NOTIFY/OPTIONS did not kill the process. The new wrapHandler in pkg/sip/server.go only applies user-supplied interceptors, and no production caller (cmd/livekit-sip/main.go, test/cloud/service.go, test/integration/sip_test.go) passes any interceptors, so panic protection is now completely gone in deployed builds. Restore the protection either by always applying a recovery interceptor as the outermost wrapper inside wrapHandler, or by exporting the recovery logic as a reusable HandlerInterceptor and wiring it in at NewService/main.go so default behaviour is unchanged.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread pkg/sip/server.go
Comment on lines +324 to 331
func (s *Server) wrapHandler(handler sipgo.RequestHandler) sipgo.RequestHandler {
ret := handler
for _, interceptor := range slices.Backward(s.interceptors) {
ret = interceptor(ret)
}
return ret
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Removal of default panic recovery enables remote denial of service via malformed SIP requests

The PR removes the default panic-recovery wrapper around all SIP request handlers (wrapHandler at pkg/sip/server.go:324-331) and no production caller supplies a replacement interceptor (cmd/livekit-sip/main.go:102, test/cloud/service.go:21). Any unauthenticated remote peer that can reach the SIP listening port and trigger a panic in INVITE/ACK/BYE/NOTIFY/OPTIONS processing now crashes the entire process, terminating all concurrent calls.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@alexlivekit alexlivekit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@alexfish8
alexfish8 merged commit 4259552 into main Aug 6, 2026
2 of 4 checks passed
@alexfish8
alexfish8 deleted the afish/interceptors branch August 6, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants