mirror of
https://github.com/livekit/livekit.git
synced 2026-05-24 23:26:11 +00:00
Differently handling the case of no trunks defined vs trunks defined but none matching the call
This commit is contained in:
@@ -38,14 +38,26 @@ func (s *IOInfoService) matchSIPTrunk(ctx context.Context, trunkID string, call
|
||||
if trunkID != "" {
|
||||
// This is a best-effort optimization. Fallthrough to listing trunks if it doesn't work.
|
||||
if tr, err := s.ss.LoadSIPInboundTrunk(ctx, trunkID); err == nil {
|
||||
tr, err = sip.MatchTrunkIter(iters.Slice([]*livekit.SIPInboundTrunkInfo{tr}), call)
|
||||
if err == nil {
|
||||
return tr, nil
|
||||
result, err := sip.MatchTrunkDetailed(iters.Slice([]*livekit.SIPInboundTrunkInfo{tr}), call)
|
||||
if err == nil && result.MatchType != sip.TrunkMatchNone {
|
||||
return result.Trunk, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
it := s.SelectSIPInboundTrunk(ctx, call.To.User)
|
||||
return sip.MatchTrunkIter(it, call)
|
||||
result, err := sip.MatchTrunkDetailed(it, call)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If trunks exist but none matched, return a specific error
|
||||
if result.MatchType == sip.TrunkMatchNone {
|
||||
return nil, ErrSIPTrunkNotFound
|
||||
}
|
||||
// If no trunks were defined at all, return nil (this is different from TrunkMatchNone)
|
||||
if result.MatchType == sip.TrunkMatchEmpty {
|
||||
return nil, nil
|
||||
}
|
||||
return result.Trunk, nil
|
||||
}
|
||||
|
||||
func (s *IOInfoService) SelectSIPInboundTrunk(ctx context.Context, called string) iters.Iter[*livekit.SIPInboundTrunkInfo] {
|
||||
@@ -143,12 +155,18 @@ func (s *IOInfoService) GetSIPTrunkAuthentication(ctx context.Context, req *rpc.
|
||||
}
|
||||
trunk, err := s.matchSIPTrunk(ctx, "", call)
|
||||
if err != nil {
|
||||
// Check if this is the specific "no SIP trunk matched" error
|
||||
if err == ErrSIPTrunkNotFound {
|
||||
err := twirp.NotFoundError(fmt.Sprintf("sip trunk not found for destination %q", req.Call.To))
|
||||
log.Errorw("No SIP trunk matched for auth", err, "sipTrunk", "", "to", req.Call.To)
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if trunk == nil {
|
||||
err := twirp.NotFoundError(fmt.Sprintf("sip trunk not found for destination %q", req.Call.To))
|
||||
log.Errorw("No SIP trunk matched for auth", err, "sipTrunk", "", "to", req.Call.To)
|
||||
return nil, err
|
||||
// This case is for TrunkMatchEmpty (no trunks defined at all)
|
||||
// We don't return an error in this case
|
||||
return nil, nil
|
||||
}
|
||||
log.Debugw("SIP trunk matched for auth", "sipTrunk", trunk.SipTrunkId)
|
||||
return &rpc.GetSIPTrunkAuthenticationResponse{
|
||||
|
||||
@@ -141,6 +141,13 @@ func TestGetSIPTrunkAuthentication(t *testing.T) {
|
||||
AuthUsername: "user2",
|
||||
AuthPassword: "pass2",
|
||||
},
|
||||
{
|
||||
SipTrunkId: "restricted-trunk",
|
||||
Numbers: []string{"9999"},
|
||||
AllowedAddresses: []string{"10.0.0.0/8"}, // Only allow calls from 10.x.x.x
|
||||
AuthUsername: "restricted-user",
|
||||
AuthPassword: "restricted-pass",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tr := range trunks {
|
||||
@@ -182,11 +189,11 @@ func TestGetSIPTrunkAuthentication(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no matching trunk",
|
||||
name: "trunk exists but source IP not allowed (TrunkMatchNone)",
|
||||
call: &rpc.SIPCall{
|
||||
To: &livekit.SIPUri{User: "9999"},
|
||||
From: &livekit.SIPUri{User: "8888"},
|
||||
SourceIp: "192.168.1.1",
|
||||
SourceIp: "192.168.1.1", // Not in 10.0.0.0/8 range
|
||||
},
|
||||
wantErr: true,
|
||||
wantErrMsg: `sip trunk not found for destination "user:\"9999\""`,
|
||||
@@ -225,3 +232,50 @@ func TestGetSIPTrunkAuthentication(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSIPTrunkAuthenticationEmpty(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s, _ := ioStoreDocker(t)
|
||||
|
||||
// No trunks defined at all
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
call *rpc.SIPCall
|
||||
wantTrunkID string
|
||||
wantUser string
|
||||
wantPass string
|
||||
wantErr bool
|
||||
wantErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "no trunks defined (TrunkMatchEmpty)",
|
||||
call: &rpc.SIPCall{
|
||||
To: &livekit.SIPUri{User: "9999"},
|
||||
From: &livekit.SIPUri{User: "8888"},
|
||||
SourceIp: "192.168.1.1",
|
||||
},
|
||||
wantErr: false, // TrunkMatchEmpty - no error
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := &rpc.GetSIPTrunkAuthenticationRequest{
|
||||
Call: tt.call,
|
||||
}
|
||||
resp, err := s.GetSIPTrunkAuthentication(ctx, req)
|
||||
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
if tt.wantErrMsg != "" {
|
||||
require.Contains(t, err.Error(), tt.wantErrMsg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, resp) // For TrunkMatchEmpty, we expect no response
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user