mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
Utilities for Diameter, convert from StoredCdr to CCR, disect usage and rebuild out of CCR
This commit is contained in:
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/rpcclient"
|
||||
"github.com/fiorix/go-diameter/diam"
|
||||
//"github.com/fiorix/go-diameter/diam/avp"
|
||||
"github.com/fiorix/go-diameter/diam/datatype"
|
||||
"github.com/fiorix/go-diameter/diam/dict"
|
||||
"github.com/fiorix/go-diameter/diam/sm"
|
||||
|
||||
120
agents/libdmt.go
Normal file
120
agents/libdmt.go
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Real-time Charging System for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package agents
|
||||
|
||||
/*
|
||||
Build various type of packets here
|
||||
*/
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/fiorix/go-diameter/diam"
|
||||
"github.com/fiorix/go-diameter/diam/avp"
|
||||
"github.com/fiorix/go-diameter/diam/datatype"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
// Returns reqType, requestNr and ccTime in seconds
|
||||
func disectUsageForCCR(usage time.Duration, debitInterval time.Duration, callEnded bool) (int, int, int) {
|
||||
usageSecs := usage.Seconds()
|
||||
debitIntervalSecs := debitInterval.Seconds()
|
||||
reqType := 1
|
||||
if usage > 0 {
|
||||
reqType = 2
|
||||
}
|
||||
if callEnded {
|
||||
reqType = 3
|
||||
}
|
||||
reqNr := int(usageSecs / debitIntervalSecs)
|
||||
if callEnded {
|
||||
reqNr += 1
|
||||
}
|
||||
ccTime := debitInterval.Seconds()
|
||||
if callEnded {
|
||||
ccTime = math.Mod(usageSecs, debitIntervalSecs)
|
||||
}
|
||||
return reqType, reqNr, int(ccTime)
|
||||
}
|
||||
|
||||
func getUsageFromCCR(reqType, reqNr, ccTime int, debitIterval time.Duration) time.Duration {
|
||||
dISecs := debitIterval.Seconds()
|
||||
if reqType == 3 {
|
||||
reqNr -= 1 // decrease request number to reach the real number
|
||||
}
|
||||
ccTime += int(dISecs) * reqNr
|
||||
return time.Duration(ccTime) * time.Second
|
||||
}
|
||||
|
||||
func storedCdrToCCR(cdr *engine.StoredCdr, originHost, originRealm string, vendorId int, productName string, firmwareRev int, debitInterval time.Duration, callEnded bool) *diam.Message {
|
||||
sid := "session;" + strconv.Itoa(int(rand.Uint32()))
|
||||
reqType, reqNr, ccTime := disectUsageForCCR(cdr.Usage, debitInterval, callEnded)
|
||||
m := diam.NewRequest(272, 4, nil)
|
||||
m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(sid))
|
||||
m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity(originHost))
|
||||
m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity(originRealm))
|
||||
m.NewAVP(avp.DestinationHost, avp.Mbit, 0, datatype.DiameterIdentity(originHost))
|
||||
m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, datatype.DiameterIdentity(originRealm))
|
||||
m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4))
|
||||
m.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.UTF8String("voice@huawei.com"))
|
||||
m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(reqType))
|
||||
m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Enumerated(reqNr))
|
||||
m.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Time(cdr.AnswerTime))
|
||||
m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(0)),
|
||||
diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String(cdr.Account)),
|
||||
}})
|
||||
m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(1)),
|
||||
diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String("20921006232651")),
|
||||
}})
|
||||
m.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(0))
|
||||
m.NewAVP(avp.RequestedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(ccTime))}})
|
||||
m.NewAVP(avp.ServiceInformation, avp.Mbit, 0, &diam.GroupedAVP{
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(20300, avp.Mbit, 0, &diam.GroupedAVP{ // IN-Information
|
||||
AVP: []*diam.AVP{
|
||||
diam.NewAVP(avp.CallingPartyAddress, avp.Mbit, 0, datatype.UTF8String(cdr.Account)),
|
||||
diam.NewAVP(avp.CalledPartyAddress, avp.Mbit, 0, datatype.UTF8String(cdr.Destination)),
|
||||
diam.NewAVP(20327, avp.Mbit, 0, datatype.UTF8String(cdr.Destination)), // Real-Called-Number
|
||||
diam.NewAVP(20339, avp.Mbit, 0, datatype.Unsigned32(0)), // Charge-Flow-Type
|
||||
diam.NewAVP(20302, avp.Mbit, 0, datatype.UTF8String("33657954968")), // Calling-Vlr-Number
|
||||
diam.NewAVP(20303, avp.Mbit, 0, datatype.UTF8String("31901485301525")), // Calling-CellID-Or-SAI
|
||||
diam.NewAVP(avp.BearerCapability, avp.Mbit, 0, datatype.UTF8String("31901485301525")),
|
||||
diam.NewAVP(20321, avp.Mbit, 0, datatype.UTF8String("31901485301525")), // Call-Reference-Number
|
||||
diam.NewAVP(avp.MSCAddress, avp.Mbit, 0, datatype.UTF8String("")),
|
||||
diam.NewAVP(20324, avp.Mbit, 0, datatype.UTF8String("0")), // Time-Zone
|
||||
diam.NewAVP(20385, avp.Mbit, 0, datatype.UTF8String("")), // Called-Party-NP
|
||||
diam.NewAVP(20386, avp.Mbit, 0, datatype.UTF8String("20091020120101")), // SSP-Time
|
||||
},
|
||||
}),
|
||||
}})
|
||||
return m
|
||||
}
|
||||
61
agents/libdmt_test.go
Normal file
61
agents/libdmt_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Real-time Charging System for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package agents
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDisectUsageForCCR(t *testing.T) {
|
||||
if reqType, reqNr, ccTime := disectUsageForCCR(time.Duration(0)*time.Second, time.Duration(300)*time.Second, false); reqType != 1 || reqNr != 0 || ccTime != 300 {
|
||||
t.Error(reqType, reqNr, ccTime)
|
||||
}
|
||||
if reqType, reqNr, ccTime := disectUsageForCCR(time.Duration(35)*time.Second, time.Duration(300)*time.Second, false); reqType != 2 || reqNr != 0 || ccTime != 300 {
|
||||
t.Error(reqType, reqNr, ccTime)
|
||||
}
|
||||
if reqType, reqNr, ccTime := disectUsageForCCR(time.Duration(935)*time.Second, time.Duration(300)*time.Second, false); reqType != 2 || reqNr != 3 || ccTime != 300 {
|
||||
t.Error(reqType, reqNr, ccTime)
|
||||
}
|
||||
if reqType, reqNr, ccTime := disectUsageForCCR(time.Duration(35)*time.Second, time.Duration(300)*time.Second, true); reqType != 3 || reqNr != 1 || ccTime != 35 {
|
||||
t.Error(reqType, reqNr, ccTime)
|
||||
}
|
||||
if reqType, reqNr, ccTime := disectUsageForCCR(time.Duration(935)*time.Second, time.Duration(300)*time.Second, true); reqType != 3 || reqNr != 4 || ccTime != 35 {
|
||||
t.Error(reqType, reqNr, ccTime)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetUsageFromCCR(t *testing.T) {
|
||||
if usage := getUsageFromCCR(1, 0, 300, time.Duration(300)*time.Second); usage != time.Duration(300)*time.Second {
|
||||
t.Error(usage)
|
||||
}
|
||||
if usage := getUsageFromCCR(2, 0, 300, time.Duration(300)*time.Second); usage != time.Duration(300)*time.Second {
|
||||
t.Error(usage)
|
||||
}
|
||||
if usage := getUsageFromCCR(2, 3, 300, time.Duration(300)*time.Second); usage != time.Duration(1200)*time.Second {
|
||||
t.Error(usage)
|
||||
}
|
||||
if usage := getUsageFromCCR(3, 4, 35, time.Duration(300)*time.Second); usage != time.Duration(935)*time.Second {
|
||||
t.Error(usage)
|
||||
}
|
||||
if usage := getUsageFromCCR(3, 1, 35, time.Duration(300)*time.Second); usage != time.Duration(35)*time.Second {
|
||||
t.Error(usage)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user