mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
DiameterAgent config skel
This commit is contained in:
@@ -65,6 +65,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
|
||||
cfg.SmFsConfig = new(SmFsConfig)
|
||||
cfg.SmKamConfig = new(SmKamConfig)
|
||||
cfg.SmOsipsConfig = new(SmOsipsConfig)
|
||||
cfg.DiameterAgentCfg = new(DiameterAgentCfg)
|
||||
cfg.ConfigReloads = make(map[string]chan struct{})
|
||||
cfg.ConfigReloads[utils.CDRC] = make(chan struct{}, 1)
|
||||
cfg.ConfigReloads[utils.CDRC] <- struct{}{} // Unlock the channel
|
||||
@@ -72,6 +73,8 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
|
||||
cfg.ConfigReloads[utils.CDRE] <- struct{}{} // Unlock the channel
|
||||
cfg.ConfigReloads[utils.SURETAX] = make(chan struct{}, 1)
|
||||
cfg.ConfigReloads[utils.SURETAX] <- struct{}{} // Unlock the channel
|
||||
cfg.ConfigReloads[utils.DIAMETER_AGENT] = make(chan struct{}, 1)
|
||||
cfg.ConfigReloads[utils.DIAMETER_AGENT] <- struct{}{} // Unlock the channel
|
||||
cgrJsonCfg, err := NewCgrJsonCfgFromReader(strings.NewReader(CGRATES_CFG_JSON))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -229,6 +232,7 @@ type CGRConfig struct {
|
||||
SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration
|
||||
SmKamConfig *SmKamConfig // SM-Kamailio Configuration
|
||||
SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration
|
||||
DiameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
|
||||
HistoryServer string // Address where to reach the master history server: <internal|x.y.z.y:1234>
|
||||
HistoryServerEnabled bool // Starts History as server: <true|false>.
|
||||
HistoryDir string // Location on disk where to store history files.
|
||||
@@ -461,6 +465,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnDACfg, err := jsnCfg.DiameterAgentJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnHistServCfg, err := jsnCfg.HistServJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -782,6 +791,12 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
|
||||
}
|
||||
}
|
||||
|
||||
if jsnDACfg != nil {
|
||||
if err := self.DiameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if jsnHistServCfg != nil {
|
||||
if jsnHistServCfg.Enabled != nil {
|
||||
self.HistoryServerEnabled = *jsnHistServCfg.Enabled
|
||||
|
||||
@@ -259,6 +259,36 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
|
||||
|
||||
"diameter_agent": {
|
||||
"enabled": false, // enables the diameter agent: <true|false>
|
||||
"listen": "127.0.0.1:3868", // address where to listen for diameter requests <x.y.z.y:1234>
|
||||
"timezone": "", // timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "*default", // Identifier of this processor
|
||||
"dry_run": false, // do not send the CDRs to CDRS, just parse them
|
||||
"request_filter": "Subscription-Id>Subscription-Type(0)", // filter requests processed by this processor
|
||||
"continue_on_success": false, // continue to the next template if executed
|
||||
"content_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
|
||||
{"tag": "tor", "cdr_field_id": "TOR", "type": "cdrfield", "value": "^*voice", "mandatory": true},
|
||||
{"tag": "accid", "cdr_field_id": "AccId", "type": "cdrfield", "value": "Session-Id", "mandatory": true},
|
||||
{"tag": "reqtype", "cdr_field_id": "ReqType", "type": "cdrfield", "value": "^*users", "mandatory": true},
|
||||
{"tag": "direction", "cdr_field_id": "Direction", "type": "cdrfield", "value": "^*out", "mandatory": true},
|
||||
{"tag": "tenant", "cdr_field_id": "Tenant", "type": "cdrfield", "value": "^*users", "mandatory": true},
|
||||
{"tag": "category", "cdr_field_id": "Category", "type": "cdrfield", "value": "^call_;~Calling-Vlr-Number:s/^$/33000/;~Calling-Vlr-Number:s/^(\\d{5})/${1}/", "mandatory": true},
|
||||
{"tag": "account", "cdr_field_id": "Account", "type": "cdrfield", "value": "^*users", "mandatory": true},
|
||||
{"tag": "subject", "cdr_field_id": "Subject", "type": "cdrfield", "value": "^*users", "mandatory": true},
|
||||
{"tag": "destination", "cdr_field_id": "Destination", "type": "cdrfield", "value": "Real-Called-Number", "mandatory": true},
|
||||
{"tag": "setup_time", "cdr_field_id": "SetupTime", "type": "cdrfield", "value": "Event-Time", "mandatory": true},
|
||||
{"tag": "answer_time", "cdr_field_id": "AnswerTime", "type": "cdrfield", "value": "Event-Time", "mandatory": true},
|
||||
{"tag": "usage", "cdr_field_id": "Usage", "type": "cdrfield", "value": "CC-Time", "mandatory": true},
|
||||
{"tag": "subscriber_id", "cdr_field_id": "SubscriberId", "type": "cdrfield", "value": "Subscription-Id>Subscription-Id-Data", "mandatory": true},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
"historys": {
|
||||
"enabled": false, // starts History service: <true|false>.
|
||||
"history_dir": "/var/log/cgrates/history", // location on disk where to store history files.
|
||||
|
||||
@@ -48,6 +48,7 @@ const (
|
||||
FS_JSN = "freeswitch"
|
||||
KAMAILIO_JSN = "kamailio"
|
||||
OSIPS_JSN = "opensips"
|
||||
DA_JSN = "diameter_agent"
|
||||
HISTSERV_JSN = "historys"
|
||||
PUBSUBSERV_JSN = "pubsubs"
|
||||
ALIASESSERV_JSN = "aliases"
|
||||
@@ -247,6 +248,18 @@ func (self CgrJsonCfg) SmOsipsJsonCfg() (*SmOsipsJsonCfg, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) {
|
||||
rawCfg, hasKey := self[DA_JSN]
|
||||
if !hasKey {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := new(DiameterAgentJsonCfg)
|
||||
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) HistServJsonCfg() (*HistServJsonCfg, error) {
|
||||
rawCfg, hasKey := self[HISTSERV_JSN]
|
||||
if !hasKey {
|
||||
|
||||
@@ -414,6 +414,55 @@ func TestSmOsipsJsonCfg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiameterAgentJsonCfg(t *testing.T) {
|
||||
eCfg := &DiameterAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
Listen: utils.StringPointer("127.0.0.1:3868"),
|
||||
Timezone: utils.StringPointer(""),
|
||||
Request_processors: &[]*DARequestProcessorJsnCfg{
|
||||
&DARequestProcessorJsnCfg{
|
||||
Id: utils.StringPointer("*default"),
|
||||
Dry_run: utils.BoolPointer(false),
|
||||
Request_filter: utils.StringPointer("Subscription-Id>Subscription-Type(0)"),
|
||||
Continue_on_success: utils.BoolPointer(false),
|
||||
Content_fields: &[]*CdrFieldJsonCfg{
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("tor"), Cdr_field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*voice"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("accid"), Cdr_field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("Session-Id"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("reqtype"), Cdr_field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*users"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("direction"), Cdr_field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*out"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("tenant"), Cdr_field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*users"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("category"), Cdr_field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^call_;~Calling-Vlr-Number:s/^$/33000/;~Calling-Vlr-Number:s/^(\\d{5})/${1}/"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("account"), Cdr_field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*users"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("subject"), Cdr_field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("^*users"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("destination"), Cdr_field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("Real-Called-Number"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("setup_time"), Cdr_field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("Event-Time"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("answer_time"), Cdr_field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("Event-Time"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("usage"), Cdr_field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("CC-Time"), Mandatory: utils.BoolPointer(true)},
|
||||
&CdrFieldJsonCfg{Tag: utils.StringPointer("subscriber_id"), Cdr_field_id: utils.StringPointer("SubscriberId"), Type: utils.StringPointer(utils.CDRFIELD),
|
||||
Value: utils.StringPointer("Subscription-Id>Subscription-Id-Data"), Mandatory: utils.BoolPointer(true)},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if cfg, err := dfCgrJsonCfg.DiameterAgentJsonCfg(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCfg, cfg) {
|
||||
t.Error("Received: ", cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDfHistServJsonCfg(t *testing.T) {
|
||||
eCfg := &HistServJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
|
||||
95
config/daconfig.go
Normal file
95
config/daconfig.go
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Real-time Charging System for Telecom & ISP environments
|
||||
Copyright (C) 2012-2015 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 config
|
||||
|
||||
import (
|
||||
//"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type DiameterAgentCfg struct {
|
||||
Enabled bool // enables the diameter agent: <true|false>
|
||||
Listen string // address where to listen for diameter requests <x.y.z.y:1234>
|
||||
Timezone string // timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
|
||||
RequestProcessors []*DARequestProcessor
|
||||
}
|
||||
|
||||
func (self *DiameterAgentCfg) loadFromJsonCfg(jsnCfg *DiameterAgentJsonCfg) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
self.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Listen != nil {
|
||||
self.Listen = *jsnCfg.Listen
|
||||
}
|
||||
if jsnCfg.Timezone != nil {
|
||||
self.Timezone = *jsnCfg.Timezone
|
||||
}
|
||||
if jsnCfg.Request_processors != nil {
|
||||
for _, reqProcJsn := range *jsnCfg.Request_processors {
|
||||
rp := new(DARequestProcessor)
|
||||
for _, rpSet := range self.RequestProcessors {
|
||||
if reqProcJsn.Id != nil && rpSet.Id == *reqProcJsn.Id {
|
||||
rp = rpSet // Will load data into the one set
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := rp.loadFromJsonCfg(reqProcJsn); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// One Diameter request processor configuration
|
||||
type DARequestProcessor struct {
|
||||
Id string
|
||||
DryRun bool
|
||||
RequestFilter utils.RSRFields
|
||||
ContinueOnSuccess bool
|
||||
ContentFields []*CfgCdrField
|
||||
}
|
||||
|
||||
func (self *DARequestProcessor) loadFromJsonCfg(jsnCfg *DARequestProcessorJsnCfg) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Id != nil {
|
||||
self.Id = *jsnCfg.Id
|
||||
}
|
||||
if jsnCfg.Dry_run != nil {
|
||||
self.DryRun = *jsnCfg.Dry_run
|
||||
}
|
||||
var err error
|
||||
if jsnCfg.Request_filter != nil {
|
||||
if self.RequestFilter, err = utils.ParseRSRFields(*jsnCfg.Request_filter, utils.INFIELD_SEP); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if jsnCfg.Content_fields != nil {
|
||||
if self.ContentFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Content_fields); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -235,6 +235,23 @@ type OsipsConnJsonCfg struct {
|
||||
Reconnects *int
|
||||
}
|
||||
|
||||
// DiameterAgent configuration
|
||||
type DiameterAgentJsonCfg struct {
|
||||
Enabled *bool // enables the diameter agent: <true|false>
|
||||
Listen *string // address where to listen for diameter requests <x.y.z.y:1234>
|
||||
Timezone *string // timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
|
||||
Request_processors *[]*DARequestProcessorJsnCfg
|
||||
}
|
||||
|
||||
// One Diameter request processor configuration
|
||||
type DARequestProcessorJsnCfg struct {
|
||||
Id *string
|
||||
Dry_run *bool
|
||||
Request_filter *string
|
||||
Continue_on_success *bool
|
||||
Content_fields *[]*CdrFieldJsonCfg
|
||||
}
|
||||
|
||||
// History server config section
|
||||
type HistServJsonCfg struct {
|
||||
Enabled *bool
|
||||
|
||||
@@ -239,6 +239,7 @@ const (
|
||||
EXTRA_FIELDS = "ExtraFields"
|
||||
META_SURETAX = "*sure_tax"
|
||||
SURETAX = "suretax"
|
||||
DIAMETER_AGENT = "diameter_agent"
|
||||
COUNTER_EVENT = "*event"
|
||||
COUNTER_BALANCE = "*balance"
|
||||
EVENT_NAME = "EventName"
|
||||
|
||||
@@ -20,9 +20,10 @@ package utils
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -406,3 +407,17 @@ func ConvertIfaceToString(fld interface{}) (string, bool) {
|
||||
}
|
||||
return strVal, converted
|
||||
}
|
||||
|
||||
// Simple object cloner, b should be a pointer towards a value into which we want to decode
|
||||
func Clone(a, b interface{}) error {
|
||||
buff := new(bytes.Buffer)
|
||||
enc := gob.NewEncoder(buff)
|
||||
dec := gob.NewDecoder(buff)
|
||||
if err := enc.Encode(a); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dec.Decode(b); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user