diff --git a/agents/diam_it_test.go b/agents/diam_it_test.go index 678ddc81a..f7d4584f7 100644 --- a/agents/diam_it_test.go +++ b/agents/diam_it_test.go @@ -21,6 +21,7 @@ import ( "flag" "net/rpc" "net/rpc/jsonrpc" + "os/exec" "path" "strings" "testing" @@ -35,43 +36,63 @@ import ( "github.com/cgrates/go-diameter/diam/dict" ) -var waitRater = flag.Int("wait_rater", 100, "Number of miliseconds to wait for rater to start and cache") -var dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") -var interations = flag.Int("iterations", 1, "Number of iterations to do for dry run simulation") -var replyTimeout = flag.String("reply_timeout", "1s", "Maximum duration to wait for a reply") +var ( + waitRater = flag.Int("wait_rater", 100, "Number of miliseconds to wait for rater to start and cache") + dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") + interations = flag.Int("iterations", 1, "Number of iterations to do for dry run simulation") + replyTimeout = flag.String("reply_timeout", "1s", "Maximum duration to wait for a reply") -var daCfgPath, diamConfigDIR string -var daCfg *config.CGRConfig -var apierRpc *rpc.Client -var diamClnt *DiameterClient + daCfgPath, diamConfigDIR string + daCfg *config.CGRConfig + apierRpc *rpc.Client + diamClnt *DiameterClient -var rplyTimeout time.Duration + rplyTimeout time.Duration -var sTestsDiam = []func(t *testing.T){ - testDiamItInitCfg, - testDiamItResetDataDb, - testDiamItResetStorDb, - testDiamItStartEngine, - testDiamItConnectDiameterClient, - testDiamItApierRpcConn, - testDiamItTPFromFolder, - testDiamItDryRun, - testDiamItCCRInit, - testDiamItCCRUpdate, - testDiamItCCRTerminate, - testDiamItCCRSMS, - testDiamItKillEngine, -} + isDispatcherActive bool + + sTestsDiam = []func(t *testing.T){ + testDiamItInitCfg, + testDiamItResetDataDb, + testDiamItResetStorDb, + testDiamItStartEngine, + testDiamItConnectDiameterClient, + testDiamItApierRpcConn, + testDiamItTPFromFolder, + testDiamItDryRun, + testDiamItCCRInit, + testDiamItCCRUpdate, + testDiamItCCRTerminate, + testDiamItCCRSMS, + testDiamItKillEngine, + } +) // Test start here func TestDiamItTcp(t *testing.T) { + engine.KillEngine(0) diamConfigDIR = "diamagent" for _, stest := range sTestsDiam { t.Run(diamConfigDIR, stest) } } +// Test start here +func TestDiamItDispatcher(t *testing.T) { + isDispatcherActive = true + engine.StartEngine(path.Join(*dataDir, "conf", "samples", "dispatchers", "all"), 200) + engine.StartEngine(path.Join(*dataDir, "conf", "samples", "dispatchers", "all2"), 200) + diamConfigDIR = "dispatchers/diamagent" + testDiamItResetAllDB(t) + for _, stest := range sTestsDiam { + t.Run(diamConfigDIR, stest) + } + engine.KillEngine(100) + isDispatcherActive = false +} + func TestDiamItSctp(t *testing.T) { + engine.KillEngine(0) diamConfigDIR = "diamsctpagent" for _, stest := range sTestsDiam { t.Run(diamConfigDIR, stest) @@ -79,6 +100,7 @@ func TestDiamItSctp(t *testing.T) { } func TestDiamItMaxConn(t *testing.T) { + engine.KillEngine(0) diamConfigDIR = "diamagentmaxconn" for _, stest := range sTestsDiam[:7] { t.Run(diamConfigDIR, stest) @@ -88,6 +110,7 @@ func TestDiamItMaxConn(t *testing.T) { } func TestDiamItSessionDisconnect(t *testing.T) { + engine.KillEngine(0) diamConfigDIR = "diamagent" for _, stest := range sTestsDiam[:7] { t.Run(diamConfigDIR, stest) @@ -102,11 +125,28 @@ func testDiamItInitCfg(t *testing.T) { var err error daCfg, err = config.NewCGRConfigFromPath(daCfgPath) if err != nil { - t.Error(err) + t.Fatal(err) } daCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() config.SetCgrConfig(daCfg) rplyTimeout, _ = utils.ParseDurationWithSecs(*replyTimeout) + if isDispatcherActive { + daCfg.ListenCfg().RPCJSONListen = ":6012" + } +} + +func testDiamItResetAllDB(t *testing.T) { + cfgPath1 := path.Join(*dataDir, "conf", "samples", "dispatchers", "all") + allCfg, err := config.NewCGRConfigFromPath(cfgPath1) + if err != nil { + t.Fatal(err) + } + if err := engine.InitDataDb(allCfg); err != nil { + t.Fatal(err) + } + if err := engine.InitStorDb(allCfg); err != nil { + t.Fatal(err) + } } // Remove data in both rating and accounting db @@ -125,7 +165,7 @@ func testDiamItResetStorDb(t *testing.T) { // Start CGR Engine func testDiamItStartEngine(t *testing.T) { - if _, err := engine.StopStartEngine(daCfgPath, 200); err != nil { + if _, err := engine.StartEngine(daCfgPath, 500); err != nil { t.Fatal(err) } } @@ -156,9 +196,34 @@ func testDiamItTPFromFolder(t *testing.T) { if err := apierRpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil { t.Error(err) } + if isDispatcherActive { + testDiamItTPLoadData(t) + } time.Sleep(time.Duration(1 * time.Second)) // Give time for scheduler to execute topups } +func testDiamItTPLoadData(t *testing.T) { + wchan := make(chan struct{}, 1) + go func() { + loaderPath, err := exec.LookPath("cgr-loader") + if err != nil { + t.Error(err) + } + loader := exec.Command(loaderPath, "-config_path", daCfgPath, "-path", path.Join(*dataDir, "tariffplans", "dispatchers")) + + if err := loader.Start(); err != nil { + t.Error(err) + } + loader.Wait() + wchan <- struct{}{} + }() + select { + case <-wchan: + case <-time.After(5 * time.Second): + t.Errorf("cgr-loader failed: ") + } +} + func testDiamItDryRun(t *testing.T) { ccr := diam.NewRequest(diam.CreditControl, 4, nil) ccr.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String("cgrates;1451911932;00082")) diff --git a/apier/v1/dispatchersv1_it_test.go b/apier/v1/dispatchersv1_it_test.go index 344e84f95..b132e915c 100644 --- a/apier/v1/dispatchersv1_it_test.go +++ b/apier/v1/dispatchersv1_it_test.go @@ -46,7 +46,7 @@ var ( testDspITResetStorDb, testDspITStartEngine, testDspITRPCConn, - testDspITLoadData2, + testDspITLoadData, testDspDspv1GetProfileForEvent, @@ -102,7 +102,7 @@ func testDspITRPCConn(t *testing.T) { } } -func testDspITLoadData2(t *testing.T) { +func testDspITLoadData(t *testing.T) { wchan := make(chan struct{}, 1) go func() { loaderPath, err := exec.LookPath("cgr-loader") diff --git a/config/config.go b/config/config.go index 7d6a190ba..2e2692a43 100755 --- a/config/config.go +++ b/config/config.go @@ -590,7 +590,7 @@ func (self *CGRConfig) checkConfigSanity() error { } } // DAgent checks - if self.diameterAgentCfg.Enabled { + if self.diameterAgentCfg.Enabled && !self.dispatcherSCfg.Enabled { if !self.sessionSCfg.Enabled { for _, daSMGConn := range self.diameterAgentCfg.SessionSConns { if daSMGConn.Address == utils.MetaInternal { @@ -600,7 +600,7 @@ func (self *CGRConfig) checkConfigSanity() error { } } } - if self.radiusAgentCfg.Enabled && !self.sessionSCfg.Enabled { + if self.radiusAgentCfg.Enabled && !self.sessionSCfg.Enabled && !self.dispatcherSCfg.Enabled { for _, raSMGConn := range self.radiusAgentCfg.SessionSConns { if raSMGConn.Address == utils.MetaInternal { return errors.New("SMGeneric not enabled but referenced by RadiusAgent component") diff --git a/data/conf/samples/dispatchers/all/cgrates.json b/data/conf/samples/dispatchers/all/cgrates.json index 32696efad..ddc578545 100644 --- a/data/conf/samples/dispatchers/all/cgrates.json +++ b/data/conf/samples/dispatchers/all/cgrates.json @@ -82,6 +82,12 @@ "rals_conns": [ {"address": "*internal"} ], + "chargers_conns": [ + {"address": "*internal"} + ], + "cdrs_conns": [ + {"address": "*internal"} + ], }, "apier": { diff --git a/data/conf/samples/dispatchers/diamagent/cgrates.json b/data/conf/samples/dispatchers/diamagent/cgrates.json new file mode 100644 index 000000000..d685a7043 --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/cgrates.json @@ -0,0 +1,57 @@ +{ +// CGRateS Configuration file +// +// Used for cgradmin +// Starts rater, scheduler + +"general": { + "node_id": "DispatcherS1", + "log_level": 7, + "reconnects": 1, +}, + +"listen": { + "rpc_json": ":2012", // RPC JSON listening address + "rpc_gob": ":2013", // RPC GOB listening address + "http": ":2080", // HTTP listening address +}, + +"data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "mongo", // stor database type to use: + "db_port": 27017, // the port to reach the stordb + "db_name": "datadb", + "db_password": "", +}, + +"stor_db": { + "db_type": "mongo", // stor database type to use: + "db_port": 27017, // the port to reach the stordb + "db_name": "stordb", + "db_password": "", +}, + +"attributes": { + "enabled": true +}, + +"scheduler": { + "enabled": true, +}, + +"rals": { + "enabled": true, +}, + +"dispatchers":{ + "enabled": true, + "attributes_conns": [ + {"address": "*internal"}, + ], +}, + +"diameter_agent": { + "enabled": true, + "asr_template": "*asr", +}, + +} diff --git a/data/conf/samples/dispatchers/diamagent/data.json b/data/conf/samples/dispatchers/diamagent/data.json new file mode 100644 index 000000000..c10cf5bdf --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/data.json @@ -0,0 +1,129 @@ + +{ + +"diameter_agent": { + "request_processors": [ + + { + "id": "data_init", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:1", "*prefix:~*req.Service-Context-Id:gprs"], + "flags": ["*initiate", "*accounts"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*data"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "generic"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(1)]", "mandatory": true}, + {"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"}, + ], + "reply_fields": [ + {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + ], + }, + + { + "id": "data_update_grp1", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:2", + "*string:*req.Multiple-Services-Credit-Control.Rating-Group:1", "*prefix:*req.Service-Context-Id:gprs"], + "flags": ["*update", "*accounts"], + "continue_on_success": true, + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*data"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "InitialOriginID", "field_id": "InitialOriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "_grp1"}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", "type": "*contant", "value": "generic"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]"}, + {"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"}, + {"tag": "LastUsed", "field_id": "LastUsed", "type": "*sum", + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Input-Octets[~Rating-Group(1)];~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Output-Octets[~Rating-Group(1)]"}, + ], + "reply_fields": [ + {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + ], + }, + + { + "id": "data_update_grp2", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:2", + "*string:~*req.Multiple-Services-Credit-Control.Rating-Group[1]:2", "*prefix:~*req.Service-Context-Id:gprs"], + "flags": ["*update", "*accounts"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*data"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "InitialOriginID", "field_id": "InitialOriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*constant", "value": "_grp2"}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "generic"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", "mandatory": true, + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]"}, + {"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*constant", "value": "2048"}, + {"tag": "LastUsed", "field_id": "LastUsed", "type": "*sum", + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Input-Octets[~Rating-Group(2)];~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Output-Octets[~Rating-Group(2)]"}, + ], + "reply_fields": [ + {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + ], + }, + + { + "id": "data_terminate", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:3", + "*prefix:~*req.Service-Context-Id:gprs"], + "flags": ["*terminate", "*accounts"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*data"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginIDPrefix", "field_id": "OriginIDPrefix", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "generic"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", "mandatory": true, + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]"}, + {"tag": "Destination", "field_id": "Destination", "type": "*constant", "value": "data"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "LastUsed", "field_id": "LastUsed", "type": "*handler", "handler_id": "*sum", + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Input-Octets;~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Output-Octets"}, + ], + }, + ] +} + +} \ No newline at end of file diff --git a/data/conf/samples/dispatchers/diamagent/dryrun.json b/data/conf/samples/dispatchers/diamagent/dryrun.json new file mode 100644 index 000000000..ab3242d3d --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/dryrun.json @@ -0,0 +1,76 @@ +{ + +"diameter_agent": { + "request_processors": [ + { + "id": "dryrun1", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.Service-Context-Id:TestDiamItDryRun"], + "flags": ["*dryrun"], + "continue_on_success": true, + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "Val1", "field_id": "Val1", "type": "*constant", "value": "1"}, + {"tag": "Val2", "field_id": "Val2", "type": "*constant", "value": "2"}, + {"tag": "Val3", "field_id": "Val3", "type": "*constant", "value": "3"}, + {"tag": "OptionalField", "field_id":"OptionalField", "type":"*composed", + "value":"~*req.Inexistent", "mandatory":false}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", + "type": "*constant", "value": "*prepaid"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "UsedUnits1", "field_id": "UsedUnits1", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(1)]"}, + {"tag": "UsedUnits2", "field_id": "UsedUnits2", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(2)]"}, + + ], + "reply_fields":[ + {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, + {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2002"}, + {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", + "type": "*constant", "value": "1"}, + {"tag": "CCTotalOctets1", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits1"}, + {"tag": "GrantedUsage", "field_id": "Granted-Service-Unit.CC-Time", "type": "*sum", + "value": "~*cgreq.Val1;~*cgreq.Val2;~*cgreq.Val3"}, + ], + }, + { + "id": "dryrun2", + "filters": ["*rsr::~*rep.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[0](!^$)"], // make sure the CC-Total-Octets was populated in the previous processor + "flags": ["*dryrun"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "Val1", "field_id": "Val1", "type": "*constant", "value": "1"}, + {"tag": "Val2", "field_id": "Val2", "type": "*constant", "value": "2"}, + {"tag": "Val3", "field_id": "Val3", "type": "*constant", "value": "3"}, + {"tag": "OptionalField", "field_id":"OptionalField", "type":"*composed", + "value":"~*req.Inexistent", "mandatory":false}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", + "type": "*constant", "value": "*prepaid"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "UsedUnits1", "field_id": "UsedUnits1", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(1)]"}, + {"tag": "UsedUnits2", "field_id": "UsedUnits2", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(2)]"}, + + ], + "reply_fields":[ + {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", + "type": "*constant", "value": "2","new_branch": true}, + {"tag": "CCTotalOctets2", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits2"}, + ], + }, + + ], +}, + +} \ No newline at end of file diff --git a/data/conf/samples/dispatchers/diamagent/message.json b/data/conf/samples/dispatchers/diamagent/message.json new file mode 100644 index 000000000..da348b72b --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/message.json @@ -0,0 +1,38 @@ +{ + +"diameter_agent": { + "request_processors": [ + + { + "id": "message", + "filters": ["*string:~*vars.*cmd:CCR", "*prefix:~*req.Service-Context-Id:message", + "*string:~*req.CC-Request-Type:4"], + "flags": ["*event", "*accounts", "*cdrs","*attributes"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "sms"}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", "mandatory": true, + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]"}, + {"tag": "Destination", "field_id": "Destination", "type": "*composed", "mandatory": true, + "value": "~*req.Service-Information.SMS-Information.Recipient-Address.Address-Data"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*composed", + "value": "~*req.Requested-Service-Unit.CC-Time", "mandatory": true}, + ], + "reply_fields":[ + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + ], + }, + + ], +}, + +} \ No newline at end of file diff --git a/data/conf/samples/dispatchers/diamagent/simpa.json b/data/conf/samples/dispatchers/diamagent/simpa.json new file mode 100644 index 000000000..e69f3a811 --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/simpa.json @@ -0,0 +1,29 @@ + +{ + +"diameter_agent": { + "request_processors": [ + { + "id": "simpa_event", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:4", + "*prefix:~*req.Service-Context-Id:simpa"], + "flags": ["*event", "*accounts", "*log"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*generic"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "generic"}, + {"tag": "Account", "field_id": "Account", "type": "*composed", "mandatory": true, + "value": "~*req.Subscription-Id.Subscription-Id-Data[~Subscription-Id-Type(0)]"}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*value_exponent", "mandatory": true, + "value": "~*req.Requested-Service-Unit.CC-Money.Unit-Value.Value-Digits;~*req.Requested-Service-Unit.CC-Money.Unit-Value.Exponent"}, + ], + }, + ], +}, + +} \ No newline at end of file diff --git a/data/conf/samples/dispatchers/diamagent/tests.json b/data/conf/samples/dispatchers/diamagent/tests.json new file mode 100644 index 000000000..1cf9cd445 --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/tests.json @@ -0,0 +1,47 @@ + +{ + +"diameter_agent": { + "request_processors": [ + { + "id": "TestSessionDisconnect", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:1", + "*prefix:~*req.Service-Context-Id:testSessionDisconnect"], + "flags": ["*initiate", "*accounts","*attributes"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*variable", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginHost", "field_id": "OriginHost", "type": "*variable", + "value": "~*req.Origin-Host", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", + "type": "*constant", "value": "*prepaid"}, + {"tag": "Category", "field_id": "Category", + "type": "*constant", "value": "call"}, + {"tag": "Account", "field_id": "Account", "type": "*variable", + "value": "~*req.Subscription-Id.Subscription-Id-Data", "mandatory": true}, + {"tag": "Subject", "field_id": "Subject", "type": "*variable", + "value": "~*req.Service-Information.IN-Information.Calling-Party-Address", "mandatory": true}, + {"tag": "Destination", "field_id": "Destination", "type": "*variable", + "value": "~*req.Service-Information.IN-Information.Real-Called-Number", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*variable", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*variable", + "value": "~*req.Requested-Service-Unit.CC-Time:s/(.*)/${1}s/", "mandatory": true}, + {"tag": "DebitInterval", "field_id": "CGRDebitInterval", + "type": "*constant", "value": "1s"}, + ], + "reply_fields":[ + {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, + {"tag": "ResultCode", "filters": ["*notempty:~*cgrep.Error:"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + {"tag": "GrantedUnits", "field_id": "Granted-Service-Unit.CC-Time", + "filters": ["*gte:~*cgrep.MaxUsage:0s"], + "type": "*variable", "value": "~*cgrep.MaxUsage{*duration_seconds&*round:0}", "mandatory": true}, + ], + }, + ], +}, + +} \ No newline at end of file diff --git a/data/conf/samples/dispatchers/diamagent/voice.json b/data/conf/samples/dispatchers/diamagent/voice.json new file mode 100644 index 000000000..25182a214 --- /dev/null +++ b/data/conf/samples/dispatchers/diamagent/voice.json @@ -0,0 +1,106 @@ + +{ + +"diameter_agent": { + "request_processors": [ + { + "id": "VoiceInit", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:1", + "*prefix:~*req.Service-Context-Id:voice"], + "flags": ["*initiate", "*accounts", "*attributes"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginHost", "field_id": "OriginHost", "type": "*remote_host", + "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*attributes"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "call"}, + {"tag": "Account", "field_id": "Account", "type": "*constant", "value": "*attributes"}, + {"tag": "Destination", "field_id": "Destination", "type": "*composed", + "value": "~*req.Service-Information.IN-Information.Real-Called-Number", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*composed", + "value": "~*req.Requested-Service-Unit.CC-Time:s/(.*)/${1}s/", "mandatory": true}, + {"tag": "SubscriberID", "field_id": "SubscriberId", "type": "*composed", + "value": "~*req.Subscription-Id.Subscription-Id-Data", "mandatory": true}, + ], + "reply_fields":[ + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2001"}, + {"tag": "GrantedUnits", "field_id": "Granted-Service-Unit.CC-Time", "type": "*composed", + "value": "~*cgrep.MaxUsage{*duration_seconds}", "mandatory": true}, + ], + }, + { + "id": "VoiceUpdate", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:2", + "*prefix:~*req.Service-Context-Id:voice"], + "flags": ["*update", "*accounts", "*attributes"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginHost", "field_id": "OriginHost", "type": "*remote_host", + "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*attributes"}, + {"tag": "Category", "field_id": "Category", "type": "*constant", "value": "call"}, + {"tag": "Account", "field_id": "Account", "type": "*constant", "value": "*attributes"}, + {"tag": "Destination", "field_id": "Destination", "type": "*composed", + "value": "~*req.Service-Information.IN-Information.Real-Called-Number", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*composed", + "value": "~*req.Requested-Service-Unit.CC-Time:s/(.*)/${1}s/", "mandatory": true}, + {"tag": "LastUsed", "field_id": "LastUsed", "type": "*composed", + "value": "~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/", "mandatory": true}, + {"tag": "SubscriberID", "field_id": "SubscriberId", "type": "*composed", + "value": "~*req.Subscription-Id.Subscription-Id-Data", "mandatory": true}, + ], + "reply_fields":[ + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2001"}, + {"tag": "GrantedUnits", "field_id": "Granted-Service-Unit.CC-Time", "type": "*composed", + "value": "~*cgrep.MaxUsage{*duration_seconds}", "mandatory": true}, + ], + }, + { + "id": "VoiceTerminate", + "filters": ["*string:~*vars.*cmd:CCR", "*string:~*req.CC-Request-Type:3", + "*prefix:~*req.Service-Context-Id:voice"], + "flags": ["*terminate", "*accounts", "*attributes", "*cdrs"], + "request_fields":[ + {"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*voice"}, + {"tag": "*api_key", "field_id": "*api_key", "type": "*constant", "value": "ses12345"}, + {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", + "value": "~*req.Session-Id", "mandatory": true}, + {"tag": "OriginHost", "field_id": "OriginHost", "type": "*remote_host", + "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*attributes"}, + {"tag": "Account", "field_id": "Account", "type": "*constant", "value": "*attributes"}, + {"tag": "Destination", "field_id": "Destination", "type": "*composed", + "value": "~*req.Service-Information.IN-Information.Real-Called-Number", "mandatory": true}, + {"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "Usage", "field_id": "Usage", "type": "*cc_usage", "mandatory": true, + "value": "~*req.CC-Request-Number;~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/;5m"}, + {"tag": "LastUsed", "field_id": "LastUsed", "type": "*composed", + "value": "~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/", "mandatory": true}, + {"tag": "SubscriberID", "field_id": "SubscriberId", "type": "*composed", + "value": "~*req.Subscription-Id.Subscription-Id-Data", "mandatory": true}, + ], + "reply_fields":[ + {"tag": "ResultCode", "filters": ["*rsr::~*cgrep.Error(!^$)"], + "field_id": "Result-Code", "type": "*constant", "value": "5030", "blocker": true}, + {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2001"}, + ], + }, + ], +}, + +} \ No newline at end of file diff --git a/data/tariffplans/dispatchers/Attributes.csv b/data/tariffplans/dispatchers/Attributes.csv index 9aa0d07c7..d4ac71c62 100644 --- a/data/tariffplans/dispatchers/Attributes.csv +++ b/data/tariffplans/dispatchers/Attributes.csv @@ -8,7 +8,7 @@ cgrates.org,ATTR_API_THR_AUTH,*auth,*string:~APIKey:thr12345,,,APIMethods,*const cgrates.org,ATTR_API_SUP_AUTH,*auth,*string:~APIKey:sup12345,,,APIMethods,*constant,SupplierSv1.Ping&SupplierSv1.GetSuppliers,false,20 cgrates.org,ATTR_API_STAT_AUTH,*auth,*string:~APIKey:stat12345,,,APIMethods,*constant,StatSv1.Ping&StatSv1.GetStatQueuesForEvent&StatSv1.GetQueueStringMetrics&StatSv1.ProcessEvent&StatSv1.GetQueueIDs&StatSv1.GetQueueFloatMetrics,false,20 cgrates.org,ATTR_API_RES_AUTH,*auth,*string:~APIKey:res12345,,,APIMethods,*constant,ResourceSv1.Ping&ResourceSv1.GetResourcesForEvent&ResourceSv1.AuthorizeResources&ResourceSv1.AllocateResources&ResourceSv1.ReleaseResources,false,20 -cgrates.org,ATTR_API_SES_AUTH,*auth,*string:~APIKey:ses12345,,,APIMethods,*constant,SessionSv1.Ping&SessionSv1.AuthorizeEventWithDigest&SessionSv1.InitiateSessionWithDigest&SessionSv1.UpdateSession&SessionSv1.TerminateSession&SessionSv1.ProcessCDR&SessionSv1.ProcessEvent&SessionSv1.GetActiveSessions&SessionSv1.GetActiveSessionsCount&SessionSv1.ForceDisconnect&SessionSv1.GetPassiveSessions&SessionSv1.GetPassiveSessionsCount&SessionSv1.SetPassiveSession&SessionSv1.ReplicateSessions,false,20 +cgrates.org,ATTR_API_SES_AUTH,*auth,*string:~APIKey:ses12345,,,APIMethods,*constant,SessionSv1.Ping&SessionSv1.AuthorizeEvent&SessionSv1.AuthorizeEventWithDigest&SessionSv1.InitiateSession&SessionSv1.InitiateSessionWithDigest&SessionSv1.UpdateSession&SessionSv1.SyncSessions&SessionSv1.TerminateSession&SessionSv1.ProcessCDR&SessionSv1.ProcessEvent&SessionSv1.GetActiveSessions&SessionSv1.GetActiveSessionsCount&SessionSv1.ForceDisconnect&SessionSv1.GetPassiveSessions&SessionSv1.GetPassiveSessionsCount&SessionSv1.ReplicateSessions&SessionSv1.SetPassiveSession,false,20 cgrates.org,ATTR_API_RSP_AUTH,*auth,*string:~APIKey:rsp12345,,,APIMethods,*constant,Responder.Status&Responder.GetTimeout&Responder.Shutdown&Responder.Ping,false,20 cgrates.org,ATTR_API_CHC_AUTH,*auth,*string:~APIKey:chc12345,,,APIMethods,*constant,CacheSv1.Ping&CacheSv1.GetCacheStats&CacheSv1.LoadCache&CacheSv1.PrecacheStatus&CacheSv1.GetItemIDs&CacheSv1.HasItem&CacheSv1.GetItemExpiryTime&CacheSv1.ReloadCache&CacheSv1.RemoveItem&CacheSv1.FlushCache&CacheSv1.Clear,false,20 cgrates.org,ATTR_API_GRD_AUTH,*auth,*string:~APIKey:grd12345,,,APIMethods,*constant,GuardianSv1.Ping&GuardianSv1.RemoteLock&GuardianSv1.RemoteUnlock,false,20 diff --git a/data/tariffplans/tutorial/Attributes.csv b/data/tariffplans/tutorial/Attributes.csv index b564df92c..6244ad032 100644 --- a/data/tariffplans/tutorial/Attributes.csv +++ b/data/tariffplans/tutorial/Attributes.csv @@ -15,6 +15,8 @@ cgrates.org,ATTR_1003_SESSIONAUTH,*sessions,*string:~Account:1003,,,Password,*co cgrates.org,ATTR_1003_SESSIONAUTH,,,,,RequestType,*constant,*prepaid,, cgrates.org,ATTR_1003_SESSIONAUTH,,,,,PaypalAccount,*constant,cgrates@paypal.com,, cgrates.org,ATTR_1003_SESSIONAUTH,,,,,LCRProfile,*constant,premium_cli,, +cgrates.org,ATTR_ACC_ALIAS,*any,*string:~SubscriberId:1006,,,Account,*constant,1001,false,10 +cgrates.org,ATTR_ACC_ALIAS,*any,,,,RequestType,*constant,*prepaid,, cgrates.com,ATTR_TNT_ALIAS,*any,*string:~SubscriberId:1006,,,Account,*constant,1001,false,10 cgrates.com,ATTR_TNT_ALIAS,*any,,,,RequestType,*constant,*prepaid,, cgrates.com,ATTR_TNT_ALIAS,*any,,,,*tenant,*constant,cgrates.org,,