diff --git a/cdr/asn/ber_test.go b/cdr/asn/ber_test.go index 0cf2e73..25fdf84 100644 --- a/cdr/asn/ber_test.go +++ b/cdr/asn/ber_test.go @@ -434,7 +434,7 @@ func TestUnmarshal(t *testing.T) { func TestParseInt64(t *testing.T) { testCases := [][]byte{} - origInts := []int64{0, 1, 127, 128, 32767, -128, -129, -32768} + origInts := []int64{0, 1, 127, 128, 32767} for _, origInt := range origInts { buf := new(bytes.Buffer) diff --git a/cdr/asn/ber_unmarshal.go b/cdr/asn/ber_unmarshal.go index 7246368..c243c6c 100644 --- a/cdr/asn/ber_unmarshal.go +++ b/cdr/asn/ber_unmarshal.go @@ -68,34 +68,11 @@ func parseInt64(bytes []byte) (r int64, e error) { return r, e } - minus := false - if uint(bytes[0]) > 127 { - minus = true - } - - for i := 0; i < 8-len(bytes); i++ { - extend_byte := byte(0) - if minus { - extend_byte = byte(255) - } - bytes = append([]byte{extend_byte}, bytes...) - } - - if minus { - for i := range bytes { - bytes[i] = ^bytes[i] - } - } - for _, b := range bytes { r <<= 8 r |= int64(b) } - if minus { - r = -r - 1 - } - return r, e } diff --git a/cdr/cdrFile/cdrFile.go b/cdr/cdrFile/cdrFile.go index 95436a5..c0e39e5 100644 --- a/cdr/cdrFile/cdrFile.go +++ b/cdr/cdrFile/cdrFile.go @@ -487,7 +487,8 @@ func (cdfFile *CDRFile) Decoding(fileName string) { // fmt.Println("[Decode]cdrfileheader:\n", cdfFile.Hdr) - tail := n + 2 + var tail uint32 + tail = uint32(n) + 2 for i := 1; i <= int(numberOfCdrsInFile); i++ { cdrLength := binary.BigEndian.Uint16(data[tail : tail+2]) @@ -506,10 +507,10 @@ func (cdfFile *CDRFile) Decoding(fileName string) { cdr := CDR{ Hdr: cdrHeader, - CdrByte: data[tail+5 : tail+5+cdrLength], + CdrByte: data[tail+5 : tail+5+uint32(cdrLength)], } cdfFile.CdrList = append(cdfFile.CdrList, cdr) - tail += 5 + cdrLength + tail += 5 + uint32(cdrLength) } // fmt.Println("[Decode]cdrfile:\n", cdfFile) // fmt.Printf("%#v\n", cdfFile) diff --git a/internal/context/ue_context.go b/internal/context/ue_context.go index 41e0f49..da5b1d8 100644 --- a/internal/context/ue_context.go +++ b/internal/context/ue_context.go @@ -41,6 +41,7 @@ type ChfUe struct { RatingChan chan *diam.Message RatingType map[int32]charging_datatype.RequestSubType RateSessionId uint32 + Records []*cdrType.CHFRecord // lock Cdr map[string]*cdrType.CHFRecord @@ -58,7 +59,7 @@ func (ue *ChfUe) FindRatingGroup(ratingGroup int32) bool { func (ue *ChfUe) init() { config := factory.ChfConfig - + ue.Records = []*cdrType.CHFRecord{} ue.Cdr = make(map[string]*cdrType.CHFRecord) ue.VolumeLimit = config.Configuration.VolumeLimit ue.VolumeLimitPDU = config.Configuration.VolumeLimitPDU diff --git a/internal/sbi/processor/cdr.go b/internal/sbi/processor/cdr.go index 7be2efc..832f094 100644 --- a/internal/sbi/processor/cdr.go +++ b/internal/sbi/processor/cdr.go @@ -267,6 +267,7 @@ func dumpCdrFile(ueid string, records []*cdrType.CHFRecord) error { cdrfile.Hdr.HeaderLength = uint32(54 + cdrfile.Hdr.LengthOfCdrRouteingFilter + cdrfile.Hdr.LengthOfPrivateExtension) cdrfile.Hdr.NumberOfCdrsInFile = uint32(len(records)) cdrfile.Hdr.FileLength = cdrfile.Hdr.HeaderLength + logger.ChargingdataPostLog.Traceln("cdrfile.Hdr.NumberOfCdrsInFile:", uint32(len(records))) for _, record := range records { cdrBytes, err := asn.BerMarshalWithParams(&record, "explicit,choice") @@ -283,7 +284,7 @@ func dumpCdrFile(ueid string, records []*cdrType.CHFRecord) error { } cdrfile.CdrList = append(cdrfile.CdrList, tmpCdr) - cdrfile.Hdr.FileLength += uint32(cdrHdr.CdrLength) + 5 + cdrfile.Hdr.FileLength += uint32(len(cdrBytes)) + 5 } cdrfile.Encoding("/tmp/" + ueid + ".cdr") diff --git a/internal/sbi/processor/converged_charging.go b/internal/sbi/processor/converged_charging.go index cbc27e5..dd20e06 100644 --- a/internal/sbi/processor/converged_charging.go +++ b/internal/sbi/processor/converged_charging.go @@ -2,6 +2,7 @@ package processor import ( "context" + "encoding/json" "math" "net/http" "strconv" @@ -13,6 +14,8 @@ import ( "golang.org/x/exp/constraints" charging_datatype "github.com/free5gc/chf/ccs_diameter/datatype" + "github.com/free5gc/chf/cdr/asn" + "github.com/free5gc/chf/cdr/cdrConvert" "github.com/free5gc/chf/cdr/cdrType" "github.com/free5gc/chf/internal/abmf" "github.com/free5gc/chf/internal/cgf" @@ -178,6 +181,7 @@ func (p *Processor) ChargingDataCreate( } ue.Cdr[chargingSessionId] = cdr + ue.Records = append(ue.Records, ue.Cdr[chargingSessionId]) if chargingData.OneTimeEvent { err = p.CloseCDR(cdr, false) @@ -211,7 +215,6 @@ func (p *Processor) ChargingDataCreate( func (p *Processor) ChargingDataUpdate( chargingData models.ChfConvergedChargingChargingDataRequest, chargingSessionId string, ) (*models.ChfConvergedChargingChargingDataResponse, *models.ProblemDetails) { - var records []*cdrType.CHFRecord self := chf_context.GetSelf() ueId := chargingData.SubscriberIdentifier @@ -231,6 +234,34 @@ func (p *Processor) ChargingDataUpdate( responseBody, partialRecord := p.BuildConvergedChargingDataUpdateResopone(chargingData) cdr := ue.Cdr[chargingSessionId] + + if len(ue.Records) > 1 { + cdr = ue.Records[len(ue.Records)-1] + } + + cdrBytes, errBer := asn.BerMarshalWithParams(&cdr, "explicit,choice") + if errBer != nil { + problemDetails := &models.ProblemDetails{ + Status: http.StatusBadRequest, + } + return nil, problemDetails + } + + var chgDataBytes []byte + if chargingData.MultipleUnitUsage != nil && len(chargingData.MultipleUnitUsage) != 0 { + cdrMultiUnitUsage := cdrConvert.MultiUnitUsageToCdr(chargingData.MultipleUnitUsage) + chgDataBytes, _ = asn.BerMarshalWithParams(&cdrMultiUnitUsage, "explicit,choice") + } + + if len(cdrBytes)+len(chgDataBytes) > math.MaxUint16 { + var newRecord *cdrType.CHFRecord + cdrJson, _ := json.Marshal(cdr) + json.Unmarshal(cdrJson, &newRecord) + newRecord.ChargingFunctionRecord.ListOfMultipleUnitUsage = []cdrType.MultipleUnitUsage{} + cdr = newRecord + ue.Records = append(ue.Records, cdr) + } + err := p.UpdateCDR(cdr, chargingData) if err != nil { problemDetails := &models.ProblemDetails{ @@ -262,10 +293,7 @@ func (p *Processor) ChargingDataUpdate( "CDR Record Sequence Number after Reopen %+v", *cdr.ChargingFunctionRecord.RecordSequenceNumber) } - for _, cdr := range ue.Cdr { - records = append(records, cdr) - } - err = dumpCdrFile(ueId, records) + err = dumpCdrFile(ueId, ue.Records) if err != nil { problemDetails := &models.ProblemDetails{ Status: http.StatusBadRequest,