diff --git a/agents/libdiam.go b/agents/libdiam.go index 0499c2a9f..a026c46de 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -210,6 +210,7 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string, dictAVPs[i] = dictAVP } } + lastAVPIdx := len(path) - 1 if dictAVPs[lastAVPIdx].Data.Type == diam.GroupedAVPType { return errors.New("last AVP in path cannot be GroupedAVP") @@ -227,15 +228,22 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string, } newMsgAVP := diam.NewAVP(dictAVPs[i].Code, avp.Mbit, dictAVPs[i].VendorID, typeVal) // FixMe: maybe Mbit with dictionary one if i == lastAVPIdx-1 && !newBranch { - avps, err := m.FindAVPsWithPath(path[:lastAVPIdx], dict.UndefinedVendorID) - if err != nil { - return err - } - if len(avps) != 0 { // Group AVP already in the message - prevGrpData := avps[len(avps)-1].Data.(*diam.GroupedAVP) // Take the last avp found to append there - prevGrpData.AVP = append(prevGrpData.AVP, msgAVP) - m.Header.MessageLength += uint32(msgAVP.Len()) - return nil + for idx := i + 1; idx > 0; idx-- { //check if we can append to the last AVP + avps, err := m.FindAVPsWithPath(path[:idx], dict.UndefinedVendorID) + if err != nil { + return err + } + if len(avps) != 0 { // Group AVP already in the message + prevGrpData := avps[len(avps)-1].Data.(*diam.GroupedAVP) // Take the last avp found to append there + if newMsgAVP.Data.Type() == diam.GroupedAVPType && idx != lastAVPIdx { // check if we need to add a group to last avp + prevGrpData.AVP = append(prevGrpData.AVP, newMsgAVP) + m.Header.MessageLength += uint32(newMsgAVP.Len()) + } else { + prevGrpData.AVP = append(prevGrpData.AVP, msgAVP) + m.Header.MessageLength += uint32(msgAVP.Len()) + } + return nil + } } } msgAVP = newMsgAVP @@ -406,6 +414,7 @@ func diamAnswer(m *diam.Message, resCode uint32, errFlag bool, // write reply into message pathIdx := make(map[string]int) // group items for same path for _, val := range rply.Values() { + nmItms, isNMItems := val.([]*config.NMItem) if !isNMItems { return nil, fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val)) @@ -426,6 +435,7 @@ func diamAnswer(m *diam.Message, resCode uint32, errFlag bool, } } } + if itm == nil { continue // all attributes, not writable to diameter packet } diff --git a/agents/libdiam_test.go b/agents/libdiam_test.go index 954d13cdb..6e26535f4 100644 --- a/agents/libdiam_test.go +++ b/agents/libdiam_test.go @@ -204,3 +204,137 @@ func TestMessageSetAVPsWithPath2(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", eMessage, m) } } + +func TestMessageSetAVPsWithPath3(t *testing.T) { + eMessage := diam.NewRequest(diam.CreditControl, 4, nil) + eMessage.NewAVP("Multiple-Services-Credit-Control", avp.Mbit, 0, &diam.GroupedAVP{ + AVP: []*diam.AVP{ + diam.NewAVP(430, avp.Mbit, 0, &diam.GroupedAVP{ // 430 code for Final-Unit-Indication + AVP: []*diam.AVP{ + diam.NewAVP(449, avp.Mbit, 0, datatype.Enumerated(1)), // 449 code for Final-Unit-Action + diam.NewAVP(434, avp.Mbit, 0, &diam.GroupedAVP{ // 434 code for Redirect-Server + AVP: []*diam.AVP{ + diam.NewAVP(433, avp.Mbit, 0, datatype.Enumerated(2)), // 433 code for Redirect-Address-Type + diam.NewAVP(435, avp.Mbit, 0, datatype.UTF8String("http://172.10.88.88/")), //435 code for Redirect-Server-Address + }, + }, + ), + }, + }, + ), + }, + }, + ) + m := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4, + eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil) + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, "1", + false, "UTC"); err != nil { + t.Error(err) + } + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, "2", + false, "UTC"); err != nil { + t.Error(err) + } + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, "http://172.10.88.88/", + false, "UTC"); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(eMessage.String(), m.String()) { + t.Errorf("Expecting: %+v \n, received: %+v \n", eMessage, m) + } +} + +func TestMessageSetAVPsWithPath4(t *testing.T) { + eMessage := diam.NewRequest(diam.CreditControl, 4, nil) + eMessage.NewAVP("Multiple-Services-Credit-Control", avp.Mbit, 0, &diam.GroupedAVP{ + AVP: []*diam.AVP{ + diam.NewAVP(430, avp.Mbit, 0, &diam.GroupedAVP{ // 430 code for Final-Unit-Indication + AVP: []*diam.AVP{ + diam.NewAVP(434, avp.Mbit, 0, &diam.GroupedAVP{ // 434 code for Redirect-Server + AVP: []*diam.AVP{ + diam.NewAVP(433, avp.Mbit, 0, datatype.Enumerated(2)), // 433 code for Redirect-Address-Type + diam.NewAVP(435, avp.Mbit, 0, datatype.UTF8String("http://172.10.88.88/")), //435 code for Redirect-Server-Address + }, + }, + ), + diam.NewAVP(449, avp.Mbit, 0, datatype.Enumerated(1)), // 449 code for Final-Unit-Action + }, + }, + ), + }, + }, + ) + m := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4, + eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil) + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, "2", + false, "UTC"); err != nil { + t.Error(err) + } + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, "1", + false, "UTC"); err != nil { + t.Error(err) + } + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, "http://172.10.88.88/", + false, "UTC"); err != nil { + t.Error(err) + } + if !reflect.DeepEqual(eMessage.String(), m.String()) { + t.Errorf("Expecting: %+v \n, received: %+v \n", eMessage, m) + } +} + +func TestMessageSetAVPsWithPath5(t *testing.T) { + eMessage := diam.NewRequest(diam.CreditControl, 4, nil) + eMessage.NewAVP("Multiple-Services-Credit-Control", avp.Mbit, 0, &diam.GroupedAVP{ + AVP: []*diam.AVP{ + diam.NewAVP(430, avp.Mbit, 0, &diam.GroupedAVP{ // 430 code for Final-Unit-Indication + AVP: []*diam.AVP{ + diam.NewAVP(434, avp.Mbit, 0, &diam.GroupedAVP{ // 434 code for Redirect-Server + AVP: []*diam.AVP{ + diam.NewAVP(433, avp.Mbit, 0, datatype.Enumerated(2)), // 433 code for Redirect-Address-Type + diam.NewAVP(435, avp.Mbit, 0, datatype.UTF8String("http://172.10.88.88/")), //435 code for Redirect-Server-Address + }, + }, + ), + diam.NewAVP(449, avp.Mbit, 0, datatype.Enumerated(1)), // 449 code for Final-Unit-Action + }, + }, + ), + }, + }, + ) + m := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4, + eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil) + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, "2", + false, "UTC"); err != nil { + t.Error(err) + } + + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, "http://172.10.88.88/", + false, "UTC"); err != nil { + t.Error(err) + } + if err := messageSetAVPsWithPath(m, + []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, "1", + false, "UTC"); err != nil { + t.Error(err) + } + + if !reflect.DeepEqual(eMessage.String(), m.String()) { + t.Errorf("Expecting: %+v \n, received: %+v \n", eMessage, m) + } +}