Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate SIP validation errors with Twirp codes #879

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/unlucky-apples-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"github.com/livekit/protocol": patch
---

Annotate SIP errors with Twirp codes.
19 changes: 11 additions & 8 deletions sip/sip.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/twitchtv/twirp"
"maps"
"math"
"net/netip"
Expand Down Expand Up @@ -151,7 +152,7 @@ func ValidateDispatchRules(rules []*livekit.SIPDispatchRuleInfo) error {
key := ruleKey{Pin: pin, Trunk: trunk, Number: normalizeNumber(number)}
r2 := byRuleKey[key]
if r2 != nil {
return fmt.Errorf("Conflicting SIP Dispatch Rules: same Trunk+Number+PIN combination for for %q and %q",
return twirp.NewErrorf(twirp.InvalidArgument, "Conflicting SIP Dispatch Rules: same Trunk+Number+PIN combination for for %q and %q",
printID(r.SipDispatchRuleId), printID(r2.SipDispatchRuleId))
}
byRuleKey[key] = r
Expand Down Expand Up @@ -217,7 +218,7 @@ func normalizeNumber(num string) string {
func validateTrunkInbound(byInbound map[string]*livekit.SIPInboundTrunkInfo, t *livekit.SIPInboundTrunkInfo) error {
if len(t.AllowedNumbers) == 0 {
if t2 := byInbound[""]; t2 != nil {
return fmt.Errorf("Conflicting inbound SIP Trunks: %q and %q, using the same number(s) %s without AllowedNumbers set",
return twirp.NewErrorf(twirp.InvalidArgument, "Conflicting inbound SIP Trunks: %q and %q, using the same number(s) %s without AllowedNumbers set",
printID(t.SipTrunkId), printID(t2.SipTrunkId), printNumbers(t.Numbers))
}
byInbound[""] = t
Expand All @@ -226,7 +227,7 @@ func validateTrunkInbound(byInbound map[string]*livekit.SIPInboundTrunkInfo, t *
inboundKey := normalizeNumber(num)
t2 := byInbound[inboundKey]
if t2 != nil {
return fmt.Errorf("Conflicting inbound SIP Trunks: %q and %q, using the same number(s) %s and AllowedNumber %q",
return twirp.NewErrorf(twirp.InvalidArgument, "Conflicting inbound SIP Trunks: %q and %q, using the same number(s) %s and AllowedNumber %q",
printID(t.SipTrunkId), printID(t2.SipTrunkId), printNumbers(t.Numbers), num)
}
byInbound[inboundKey] = t
Expand Down Expand Up @@ -333,7 +334,7 @@ func MatchTrunk(trunks []*livekit.SIPInboundTrunkInfo, srcIP netip.Addr, calling
if normalizeNumber(num) == calledNorm {
// Trunk specific to the number.
if selectedTrunk != nil {
return nil, fmt.Errorf("Multiple SIP Trunks matched for %q", called)
return nil, twirp.NewErrorf(twirp.FailedPrecondition, "Multiple SIP Trunks matched for %q", called)
}
selectedTrunk = tr
// Keep searching! We want to know if there are any conflicting Trunk definitions.
Expand All @@ -345,7 +346,7 @@ func MatchTrunk(trunks []*livekit.SIPInboundTrunkInfo, srcIP netip.Addr, calling
return selectedTrunk, nil
}
if defaultTrunkCnt > 1 {
return nil, fmt.Errorf("Multiple default SIP Trunks matched for %q", called)
return nil, twirp.NewErrorf(twirp.FailedPrecondition, "Multiple default SIP Trunks matched for %q", called)
}
// Could still be nil here.
return defaultTrunk, nil
Expand All @@ -357,7 +358,8 @@ func MatchDispatchRule(trunk *livekit.SIPInboundTrunkInfo, rules []*livekit.SIPD
// Trunk can still be nil here in case none matched or were defined.
// This is still fine, but only in case we'll match exactly one wildcard dispatch rule.
if len(rules) == 0 {
return nil, &ErrNoDispatchMatched{NoRules: true, NoTrunks: trunk == nil, CalledNumber: req.CalledNumber}
err := &ErrNoDispatchMatched{NoRules: true, NoTrunks: trunk == nil, CalledNumber: req.CalledNumber}
return nil, twirp.WrapError(twirp.NewErrorf(twirp.FailedPrecondition, err.Error()), err)
}
// We split the matched dispatch rules into two sets in relation to Trunks: specific and default (aka wildcard).
// First, attempt to match any of the specific rules, where we did match the Trunk ID.
Expand Down Expand Up @@ -420,7 +422,8 @@ func MatchDispatchRule(trunk *livekit.SIPInboundTrunkInfo, rules []*livekit.SIPD
} else if best != nil {
return best, nil
}
return nil, &ErrNoDispatchMatched{NoRules: false, NoTrunks: trunk == nil, CalledNumber: req.CalledNumber}
err = &ErrNoDispatchMatched{NoRules: false, NoTrunks: trunk == nil, CalledNumber: req.CalledNumber}
return nil, twirp.WrapError(twirp.NewErrorf(twirp.FailedPrecondition, err.Error()), err)
}

// EvaluateDispatchRule checks a selected Dispatch Rule against the provided request.
Expand Down Expand Up @@ -477,7 +480,7 @@ func EvaluateDispatchRule(projectID string, trunk *livekit.SIPInboundTrunkInfo,
}
if rulePin != sentPin {
// This should never happen in practice, because matchSIPDispatchRule should remove rules with the wrong pin.
return nil, fmt.Errorf("Incorrect PIN for SIP room")
return nil, twirp.NewError(twirp.PermissionDenied, "Incorrect PIN for SIP room")
}
} else {
// Pin was sent, but room doesn't require one. Assume user accidentally pressed phone button.
Expand Down
Loading