Multiple filter selectors in diameter group AVP rules

This commit is contained in:
DanB
2018-09-24 13:14:26 +02:00
parent 6f03e18aa4
commit 23a27afaa2
2 changed files with 50 additions and 22 deletions

View File

@@ -176,30 +176,43 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err
slectedIdx := 0 // by default we select AVP[0]
if slctrStr != "" {
if slectedIdx, err = strconv.Atoi(slctrStr); err != nil { // not int, compile it as RSRParser
var slctr config.RSRParsers
if slctr, err = config.NewRSRParsersFromSlice(strings.Split(slctrStr, "|"), true); err != nil {
return nil, err
} else if len(slctr) == 0 {
return nil, fmt.Errorf("unsupported filter selector: <%s>", slctrStr)
}
pathIface[len(pathIface)-1] = slctr[0].AttrName() // search for AVPs which are having common path but different end element
fltrAVPs, err := dP.m.FindAVPsWithPath(pathIface, dict.UndefinedVendorID)
if err != nil {
return nil, err
} else if len(fltrAVPs) == 0 || len(fltrAVPs) != len(avps) {
return nil, utils.ErrFilterNotPassingNoCaps
}
for k, fAVP := range fltrAVPs {
if dataAVP, err := diamAVPAsIface(fAVP); err != nil {
selIndxs := make(map[int][]struct{}) // use it to find intersection of all matched filters
slctrStrs := strings.Split(slctrStr, "|")
for _, slctrStr := range slctrStrs {
slctr, err := config.NewRSRParser(slctrStr, true)
if err != nil {
return nil, err
} else if _, err := slctr.ParseValue(dataAVP); err != nil { // filter not passing
if err != utils.ErrFilterNotPassingNoCaps {
return nil, err
}
continue // filter not passing, not really error
} else {
slectedIdx = k // filter passing, found our match, select the index of AVP to return
}
pathIface[len(pathIface)-1] = slctr.AttrName() // search for AVPs which are having common path but different end element
fltrAVPs, err := dP.m.FindAVPsWithPath(pathIface, dict.UndefinedVendorID)
if err != nil {
return nil, err
} else if len(fltrAVPs) == 0 || len(fltrAVPs) != len(avps) {
return nil, utils.ErrFilterNotPassingNoCaps
}
for k, fAVP := range fltrAVPs {
if dataAVP, err := diamAVPAsIface(fAVP); err != nil {
return nil, err
} else if _, err := slctr.ParseValue(dataAVP); err != nil {
if err != utils.ErrFilterNotPassingNoCaps {
return nil, err
}
continue // filter not passing, not really error
} else {
selIndxs[k] = append(selIndxs[k], struct{}{}) // filter passing, index it
}
}
}
var oneMatches bool
for idx, matches := range selIndxs {
if len(matches) == len(slctrStrs) { // all filters in selection matching
oneMatches = true
slectedIdx = idx
break
}
}
if !oneMatches {
return nil, utils.ErrFilterNotPassingNoCaps
}
}
}

View File

@@ -48,11 +48,19 @@ func TestDPFieldAsInterface(t *testing.T) {
AVP: []*diam.AVP{
diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(0)), // Subscription-Id-Type
diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("33708000003")), // Subscription-Id-Data
diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(10000)),
}})
m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{
AVP: []*diam.AVP{
diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(1)), // Subscription-Id-Type
diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000003")), // Subscription-Id-Data
diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(20000)),
}})
m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{
AVP: []*diam.AVP{
diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(1)), // Subscription-Id-Type
diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000004")), // Subscription-Id-Data
diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(30000)),
}})
dP := newDADataProvider(m)
@@ -81,6 +89,13 @@ func TestDPFieldAsInterface(t *testing.T) {
} else if eOut != out {
t.Errorf("Expecting: %v, received: %v", eOut, out)
}
eOut = interface{}("208708000004")
if out, err := dP.FieldAsInterface([]string{"Subscription-Id",
"Subscription-Id-Data[~Subscription-Id-Type(1)|~Value-Digits(30000)]"}); err != nil { // on multiple filter
t.Error(err)
} else if eOut != out {
t.Errorf("Expecting: %v, received: %v", eOut, out)
}
eOut = interface{}("33708000003")
if out, err := dP.FieldAsInterface([]string{"Subscription-Id", "Subscription-Id-Data"}); err != nil {
t.Error(err)