@@ -139,7 +139,7 @@ func ValidateDispatchRules(rules []*livekit.SIPDispatchRuleInfo) error {
139
139
}
140
140
for _ , trunk := range trunks {
141
141
for _ , number := range numbers {
142
- key := ruleKey {Pin : pin , Trunk : trunk , Number : number }
142
+ key := ruleKey {Pin : pin , Trunk : trunk , Number : normalizeNumber ( number ) }
143
143
r2 := byRuleKey [key ]
144
144
if r2 != nil {
145
145
return fmt .Errorf ("Conflicting SIP Dispatch Rules: same Trunk+Number+PIN combination for for %q and %q" ,
@@ -190,6 +190,18 @@ func printNumber(s string) string {
190
190
return strconv .Quote (s )
191
191
}
192
192
193
+ func normalizeNumber (num string ) string {
194
+ if num == "" {
195
+ return ""
196
+ }
197
+ // TODO: Always keep "number" as-is if it's not E.164.
198
+ // This will only matter for native SIP clients which have '+' in the username.
199
+ if ! strings .HasPrefix (num , `+` ) {
200
+ num = "+" + num
201
+ }
202
+ return num
203
+ }
204
+
193
205
// ValidateTrunks checks a set of trunks for conflicts.
194
206
func ValidateTrunks (trunks []* livekit.SIPTrunkInfo ) error {
195
207
if len (trunks ) == 0 {
@@ -200,10 +212,11 @@ func ValidateTrunks(trunks []*livekit.SIPTrunkInfo) error {
200
212
if len (t .InboundNumbersRegex ) != 0 {
201
213
continue // can't effectively validate these
202
214
}
203
- byInbound := byOutboundAndInbound [t .OutboundNumber ]
215
+ outboundKey := normalizeNumber (t .OutboundNumber )
216
+ byInbound := byOutboundAndInbound [outboundKey ]
204
217
if byInbound == nil {
205
218
byInbound = make (map [string ]* livekit.SIPTrunkInfo )
206
- byOutboundAndInbound [t . OutboundNumber ] = byInbound
219
+ byOutboundAndInbound [outboundKey ] = byInbound
207
220
}
208
221
if len (t .InboundNumbers ) == 0 {
209
222
if t2 := byInbound ["" ]; t2 != nil {
@@ -213,19 +226,20 @@ func ValidateTrunks(trunks []*livekit.SIPTrunkInfo) error {
213
226
byInbound ["" ] = t
214
227
} else {
215
228
for _ , num := range t .InboundNumbers {
216
- t2 := byInbound [num ]
229
+ inboundKey := normalizeNumber (num )
230
+ t2 := byInbound [inboundKey ]
217
231
if t2 != nil {
218
232
return fmt .Errorf ("Conflicting SIP Trunks: %q and %q, using the same OutboundNumber %s and InboundNumber %q" ,
219
233
printID (t .SipTrunkId ), printID (t2 .SipTrunkId ), printNumber (t .OutboundNumber ), num )
220
234
}
221
- byInbound [num ] = t
235
+ byInbound [inboundKey ] = t
222
236
}
223
237
}
224
238
}
225
239
return nil
226
240
}
227
241
228
- func matchAddrs (addr string , mask string ) bool {
242
+ func matchAddrMask (addr string , mask string ) bool {
229
243
if ! strings .Contains (mask , "/" ) {
230
244
return addr == mask
231
245
}
@@ -240,16 +254,29 @@ func matchAddrs(addr string, mask string) bool {
240
254
return pref .Contains (ip )
241
255
}
242
256
243
- func matchAddr (addr string , masks []string ) bool {
244
- if addr == "" {
257
+ func matchAddrMasks (addr string , masks []string ) bool {
258
+ if addr == "" || len ( masks ) == 0 {
245
259
return true
246
260
}
247
261
for _ , mask := range masks {
248
- if ! matchAddrs (addr , mask ) {
249
- return false
262
+ if matchAddrMask (addr , mask ) {
263
+ return true
264
+ }
265
+ }
266
+ return false
267
+ }
268
+
269
+ func matchNumbers (num string , allowed []string ) bool {
270
+ if len (allowed ) == 0 {
271
+ return true
272
+ }
273
+ num = normalizeNumber (num )
274
+ for _ , allow := range allowed {
275
+ if num == normalizeNumber (allow ) {
276
+ return true
250
277
}
251
278
}
252
- return true
279
+ return false
253
280
}
254
281
255
282
// MatchTrunk finds a SIP Trunk definition matching the request.
@@ -260,12 +287,13 @@ func MatchTrunk(trunks []*livekit.SIPTrunkInfo, srcIP, calling, called string) (
260
287
defaultTrunk * livekit.SIPTrunkInfo
261
288
defaultTrunkCnt int // to error in case there are multiple ones
262
289
)
290
+ calledNorm := normalizeNumber (called )
263
291
for _ , tr := range trunks {
264
292
// Do not consider it if number doesn't match.
265
- if len ( tr . InboundNumbers ) != 0 && ! slices . Contains ( tr .InboundNumbers , calling ) {
293
+ if ! matchNumbers ( calling , tr .InboundNumbers ) {
266
294
continue
267
295
}
268
- if ! matchAddr (srcIP , tr .InboundAddresses ) {
296
+ if ! matchAddrMasks (srcIP , tr .InboundAddresses ) {
269
297
continue
270
298
}
271
299
// Deprecated, but we still check it for backward compatibility.
@@ -289,7 +317,7 @@ func MatchTrunk(trunks []*livekit.SIPTrunkInfo, srcIP, calling, called string) (
289
317
// Default/wildcard trunk.
290
318
defaultTrunk = tr
291
319
defaultTrunkCnt ++
292
- } else if tr .OutboundNumber == called {
320
+ } else if normalizeNumber ( tr .OutboundNumber ) == calledNorm {
293
321
// Trunk specific to the number.
294
322
if selectedTrunk != nil {
295
323
return nil , fmt .Errorf ("Multiple SIP Trunks matched for %q" , called )
0 commit comments