Diameter data provider with support for group filters

This commit is contained in:
DanB
2018-09-21 21:05:24 +02:00
parent 5c4b6e5da1
commit 11689ed842
3 changed files with 65 additions and 4 deletions

View File

@@ -151,14 +151,53 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err
return nil, err
}
err = nil // cancel previous err
// lastPath can contain selector inside
lastPath := fldPath[len(fldPath)-1]
var slctr *config.RSRParser
if splt := strings.Split(lastPath, "["); len(splt) != 1 {
lastPath = splt[0]
if splt[1][len(splt[1])-1:] != "]" {
return nil, fmt.Errorf("filter rule <%s> needs to end in ]", splt[1])
}
fltrStr := splt[1][:len(splt[1])-1] // also strip the last ]
if slctr, err = config.NewRSRParser(fltrStr, true); err != nil {
return nil, err
}
}
pathIface := utils.SliceStringToIface(fldPath)
if slctr != nil { // last path was having selector inside before
pathIface[len(pathIface)-1] = lastPath
}
var avps []*diam.AVP
if avps, err = dP.m.FindAVPsWithPath(
utils.SliceStringToIface(fldPath), dict.UndefinedVendorID); err != nil {
pathIface, dict.UndefinedVendorID); err != nil {
return nil, err
} else if len(avps) == 0 {
return nil, utils.ErrNotFound
}
if data, err = diamAVPAsIface(avps[0]); err != nil {
slectedIdx := 0 // by default we select AVP[0]
if len(avps) != 1 && slctr != nil {
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 { // 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
}
}
}
if data, err = diamAVPAsIface(avps[slectedIdx]); err != nil {
return nil, err
}
dP.cache.Set(fldPath, data, false)

View File

@@ -44,6 +44,17 @@ func TestDPFieldAsInterface(t *testing.T) {
}),
},
})
m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{
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
}})
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
}})
dP := newDADataProvider(m)
eOut := interface{}("simuhuawei;1449573472;00002")
if out, err := dP.FieldAsInterface([]string{"Session-Id"}); err != nil {
@@ -57,8 +68,14 @@ func TestDPFieldAsInterface(t *testing.T) {
} else if eOut != out {
t.Errorf("Expecting: %v, received: %v", eOut, out)
}
eOut = interface{}(uint32(33))
if out, err := dP.FieldAsInterface([]string{"Requested-Service-Unit", "CC-Money", "Currency-Code"}); err != nil {
eOut = interface{}("208708000003") // with filter on second group item
if out, err := dP.FieldAsInterface([]string{"Subscription-Id", "Subscription-Id-Data[~Subscription-Id-Type(1)]"}); err != nil {
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)
} else if eOut != out {
t.Errorf("Expecting: %v, received: %v", eOut, out)

View File

@@ -207,6 +207,11 @@ type RSRParser struct {
filters utils.RSRFilters // The value to compare when used as filter
}
// AttrName exports the attribute name of the RSRParser
func (prsr *RSRParser) AttrName() string {
return prsr.attrName
}
// Compile parses Rules string and repopulates other fields
func (prsr *RSRParser) Compile() (err error) {
var newPrsr *RSRParser