diff --git a/agents/dmtagent.go b/agents/dmtagent.go
new file mode 100644
index 000000000..88379ef54
--- /dev/null
+++ b/agents/dmtagent.go
@@ -0,0 +1,63 @@
+/*
+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
+*/
+
+package agents
+
+import (
+ "fmt"
+
+ "github.com/cgrates/cgrates/config"
+ "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"
+)
+
+func NewDiameterAgent(cgrCfg *config.CGRConfig, smg *rpcclient.RpcClient) *DiameterAgent {
+ return &DiameterAgent{cgrCfg: cgrCfg, smg: smg}
+}
+
+type DiameterAgent struct {
+ cgrCfg *config.CGRConfig
+ smg *rpcclient.RpcClient // Connection towards CGR-SMG component
+}
+
+// Creates the message handlers
+func (self *DiameterAgent) handlers() diam.Handler {
+ settings := &sm.Settings{
+ OriginHost: datatype.DiameterIdentity(self.cgrCfg.DiameterAgentCfg().OriginHost),
+ OriginRealm: datatype.DiameterIdentity(self.cgrCfg.DiameterAgentCfg().OriginRealm),
+ VendorID: datatype.Unsigned32(self.cgrCfg.DiameterAgentCfg().VendorId),
+ ProductName: datatype.UTF8String(self.cgrCfg.DiameterAgentCfg().ProductName),
+ FirmwareRevision: datatype.Unsigned32(utils.DIAMETER_FIRMWARE_REVISION),
+ }
+ dSM := sm.New(settings)
+ dSM.HandleFunc("ALL", self.handleALL)
+ return dSM
+}
+
+func (self *DiameterAgent) handleALL(c diam.Conn, m *diam.Message) {
+ utils.Logger.Warning(fmt.Sprintf(" Received unexpected message from %s:\n%s", c.RemoteAddr(), m))
+}
+
+func (self *DiameterAgent) ListenAndServe() error {
+ return diam.ListenAndServe(self.cgrCfg.DiameterAgentCfg().Listen, self.handlers(), nil)
+}
diff --git a/agents/dmtagent_it_test.go b/agents/dmtagent_it_test.go
new file mode 100644
index 000000000..195651647
--- /dev/null
+++ b/agents/dmtagent_it_test.go
@@ -0,0 +1,89 @@
+/*
+Real-time Charging System for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can Storagetribute 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 WITH*out 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
+*/
+
+package agents
+
+import (
+ "flag"
+ "path"
+ "testing"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+)
+
+var testIntegration = flag.Bool("integration", false, "Perform the tests in integration mode, not by default.") // This flag will be passed here via "go test -local" args
+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 daCfgPath string
+var daCfg *config.CGRConfig
+
+func TestDmtAgentInitCfg(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ daCfgPath = path.Join(*dataDir, "conf", "samples", "dmtagent")
+ // Init config first
+ var err error
+ daCfg, err = config.NewCGRConfigFromFolder(daCfgPath)
+ if err != nil {
+ t.Error(err)
+ }
+ daCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush()
+ config.SetCgrConfig(daCfg)
+}
+
+// Remove data in both rating and accounting db
+func TestDmtAgentResetDataDb(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ if err := engine.InitDataDb(daCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Wipe out the cdr database
+func TestDmtAgentResetStorDb(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ if err := engine.InitStorDb(daCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func TestDmtAgentStartEngine(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ if _, err := engine.StopStartEngine(daCfgPath, *waitRater); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestDmtAgentStopEngine(t *testing.T) {
+ if !*testIntegration {
+ return
+ }
+ if err := engine.KillEngine(*waitRater); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go
index bda3b2047..fcee44ef4 100644
--- a/cmd/cgr-engine/cgr-engine.go
+++ b/cmd/cgr-engine/cgr-engine.go
@@ -29,6 +29,7 @@ import (
"strconv"
"time"
+ "github.com/cgrates/cgrates/agents"
"github.com/cgrates/cgrates/apier/v1"
"github.com/cgrates/cgrates/apier/v2"
"github.com/cgrates/cgrates/balancer2go"
@@ -135,7 +136,7 @@ func startCdrc(internalCdrSChan chan *engine.CdrServer, internalRaterChan chan *
}
}
-func startSmGeneric(internalRaterChan chan *engine.Responder, server *utils.Server, exitChan chan bool) {
+func startSmGeneric(internalSMGChan chan rpcclient.RpcClientConnection, internalRaterChan chan *engine.Responder, server *utils.Server, exitChan chan bool) {
utils.Logger.Info("Starting CGRateS SM-Generic service.")
var raterConn, cdrsConn engine.Connector
var client *rpcclient.RpcClient
@@ -184,6 +185,7 @@ func startSmGeneric(internalRaterChan chan *engine.Responder, server *utils.Serv
// Register RPC handler
smgRpc := v1.NewSMGenericV1(sm)
server.RpcRegister(smgRpc)
+ internalSMGChan <- smgRpc
// Register BiRpc handlers
smgBiRpc := v1.NewSMGenericBiRpcV1(sm)
for method, handler := range smgBiRpc.Handlers() {
@@ -194,6 +196,29 @@ func startSmGeneric(internalRaterChan chan *engine.Responder, server *utils.Serv
server.BijsonRegisterOnDisconnect(smg_econns.OnClientDisconnect)
}
+func startDiameterAgent(internalSMGChan chan rpcclient.RpcClientConnection, exitChan chan bool) {
+ utils.Logger.Info("Starting CGRateS DiameterAgent service.")
+ var smgConn *rpcclient.RpcClient
+ var err error
+ if cfg.DiameterAgentCfg().SMGeneric == utils.INTERNAL {
+ smgRpc := <-internalSMGChan
+ internalSMGChan <- smgRpc
+ smgConn, err = rpcclient.NewRpcClient("", "", 0, 0, rpcclient.INTERNAL_RPC, smgRpc)
+ } else {
+ smgConn, err = rpcclient.NewRpcClient("tcp", cfg.DiameterAgentCfg().SMGeneric, cfg.ConnectAttempts, cfg.Reconnects, utils.GOB, nil)
+ }
+ if err != nil {
+ utils.Logger.Crit(fmt.Sprintf(" Could not connect to SMG: %s", err.Error()))
+ exitChan <- true
+ return
+ }
+ da := agents.NewDiameterAgent(cfg, smgConn)
+ if err = da.ListenAndServe(); err != nil {
+ utils.Logger.Err(fmt.Sprintf(" error: %s!", err))
+ }
+ exitChan <- true
+}
+
func startSmFreeSWITCH(internalRaterChan chan *engine.Responder, cdrDb engine.CdrStorage, exitChan chan bool) {
utils.Logger.Info("Starting CGRateS SM-FreeSWITCH service.")
var raterConn, cdrsConn engine.Connector
@@ -643,7 +668,7 @@ func main() {
internalPubSubSChan := make(chan engine.PublisherSubscriber, 1)
internalUserSChan := make(chan engine.UserService, 1)
internalAliaseSChan := make(chan engine.AliasService, 1)
-
+ internalSMGChan := make(chan rpcclient.RpcClientConnection, 1)
// Start balancer service
if cfg.BalancerEnabled {
go startBalancer(internalBalancerChan, &stopHandled, exitChan) // Not really needed async here but to cope with uniformity
@@ -675,7 +700,7 @@ func main() {
// Start SM-Generic
if cfg.SmGenericConfig.Enabled {
- go startSmGeneric(internalRaterChan, server, exitChan)
+ go startSmGeneric(internalSMGChan, internalRaterChan, server, exitChan)
}
// Start SM-FreeSWITCH
if cfg.SmFsConfig.Enabled {
@@ -700,6 +725,10 @@ func main() {
server.RpcRegister(smRpc)
}
+ if cfg.DiameterAgentCfg().Enabled {
+ go startDiameterAgent(internalSMGChan, exitChan)
+ }
+
// Start HistoryS service
if cfg.HistoryServerEnabled {
go startHistoryServer(internalHistorySChan, server, exitChan)
diff --git a/config/config.go b/config/config.go
index 32c486591..0be3b935d 100644
--- a/config/config.go
+++ b/config/config.go
@@ -65,7 +65,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
cfg.SmFsConfig = new(SmFsConfig)
cfg.SmKamConfig = new(SmKamConfig)
cfg.SmOsipsConfig = new(SmOsipsConfig)
- cfg.DiameterAgentCfg = new(DiameterAgentCfg)
+ 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
@@ -232,7 +232,7 @@ type CGRConfig struct {
SmFsConfig *SmFsConfig // SM-FreeSWITCH configuration
SmKamConfig *SmKamConfig // SM-Kamailio Configuration
SmOsipsConfig *SmOsipsConfig // SM-OpenSIPS Configuration
- DiameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
+ diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
HistoryServer string // Address where to reach the master history server:
HistoryServerEnabled bool // Starts History as server: .
HistoryDir string // Location on disk where to store history files.
@@ -379,8 +379,8 @@ func (self *CGRConfig) checkConfigSanity() error {
}
}
// DAgent checks
- if self.DiameterAgentCfg.Enabled {
- if self.DiameterAgentCfg.SMGeneric == utils.INTERNAL && !self.SmGenericConfig.Enabled {
+ if self.diameterAgentCfg.Enabled {
+ if self.diameterAgentCfg.SMGeneric == utils.INTERNAL && !self.SmGenericConfig.Enabled {
return errors.New("SMGeneric not enabled but referenced by DiameterAgent component")
}
}
@@ -798,7 +798,7 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
}
if jsnDACfg != nil {
- if err := self.DiameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
+ if err := self.diameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
return err
}
}
@@ -868,7 +868,12 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
// Use locking to retrieve the configuration, possibility later for runtime reload
func (self *CGRConfig) SureTaxCfg() *SureTaxCfg {
cfgChan := <-self.ConfigReloads[utils.SURETAX] // Lock config for read or reloads
- stCfg := self.sureTaxCfg
- self.ConfigReloads[utils.SURETAX] <- cfgChan // unlock config for reloads or read
- return stCfg
+ defer func() { self.ConfigReloads[utils.SURETAX] <- cfgChan }()
+ return self.sureTaxCfg
+}
+
+func (self *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg {
+ cfgChan := <-self.ConfigReloads[utils.DIAMETER_AGENT] // Lock config for read or reloads
+ defer func() { self.ConfigReloads[utils.DIAMETER_AGENT] <- cfgChan }()
+ return self.diameterAgentCfg
}
diff --git a/config/config_defaults.go b/config/config_defaults.go
index 77709da09..3b6bba33b 100644
--- a/config/config_defaults.go
+++ b/config/config_defaults.go
@@ -203,8 +203,8 @@ const CGRATES_CFG_JSON = `
"listen_bijson": "127.0.0.1:2014", // address where to listen for bidirectional JSON-RPC requests
"rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
"cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234>
- "debit_interval": "10s", // interval to perform debits on.
- "min_call_duration": "0s", // only authorize calls with allowed duration higher than this
+ "debit_interval": "0", // interval to perform debits on.
+ "min_call_duration": "0", // only authorize calls with allowed duration higher than this
"max_call_duration": "3h", // maximum call duration a prepaid call can last
},
@@ -262,8 +262,12 @@ const CGRATES_CFG_JSON = `
"diameter_agent": {
"enabled": false, // enables the diameter agent:
"listen": "127.0.0.1:3868", // address where to listen for diameter requests
- "sm_generic": "internal", // Connection towards SMG component for session management
+ "sm_generic": "internal", // connection towards SMG component for session management
"timezone": "", // timezone for timestamps where not specified, empty for general defaults <""|UTC|Local|$IANA_TZ_DB>
+ "origin_host": "diameter-agent", // diameter Origin-Host AVP used in replies
+ "origin_realm": "cgrates.org", // diameter Origin-Realm AVP used in replies
+ "vendor_id": 0, // diameter Vendor-Id AVP used in replies
+ "product_name": "CGRateS", // diameter Product-Name AVP used in replies
"request_processors": [
{
"id": "*default", // Identifier of this processor
diff --git a/config/config_json_test.go b/config/config_json_test.go
index 03c7269d0..51b4b8a5f 100644
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -330,8 +330,8 @@ func TestSmGenericJsonCfg(t *testing.T) {
Listen_bijson: utils.StringPointer("127.0.0.1:2014"),
Rater: utils.StringPointer("internal"),
Cdrs: utils.StringPointer("internal"),
- Debit_interval: utils.StringPointer("10s"),
- Min_call_duration: utils.StringPointer("0s"),
+ Debit_interval: utils.StringPointer("0"),
+ Min_call_duration: utils.StringPointer("0"),
Max_call_duration: utils.StringPointer("3h"),
}
if cfg, err := dfCgrJsonCfg.SmGenericJsonCfg(); err != nil {
@@ -416,10 +416,14 @@ func TestSmOsipsJsonCfg(t *testing.T) {
func TestDiameterAgentJsonCfg(t *testing.T) {
eCfg := &DiameterAgentJsonCfg{
- Enabled: utils.BoolPointer(false),
- Listen: utils.StringPointer("127.0.0.1:3868"),
- Sm_generic: utils.StringPointer("internal"),
- Timezone: utils.StringPointer(""),
+ Enabled: utils.BoolPointer(false),
+ Listen: utils.StringPointer("127.0.0.1:3868"),
+ Sm_generic: utils.StringPointer("internal"),
+ Timezone: utils.StringPointer(""),
+ Origin_host: utils.StringPointer("diameter-agent"),
+ Origin_realm: utils.StringPointer("cgrates.org"),
+ Vendor_id: utils.IntPointer(0),
+ Product_name: utils.StringPointer("CGRateS"),
Request_processors: &[]*DARequestProcessorJsnCfg{
&DARequestProcessorJsnCfg{
Id: utils.StringPointer("*default"),
diff --git a/config/daconfig.go b/config/daconfig.go
index 61eb86d8b..5f856c1ab 100644
--- a/config/daconfig.go
+++ b/config/daconfig.go
@@ -29,6 +29,10 @@ type DiameterAgentCfg struct {
Listen string // address where to listen for diameter requests
SMGeneric string // connection towards SMG component
Timezone string // timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
+ OriginHost string
+ OriginRealm string
+ VendorId int
+ ProductName string
RequestProcessors []*DARequestProcessor
}
@@ -48,6 +52,18 @@ func (self *DiameterAgentCfg) loadFromJsonCfg(jsnCfg *DiameterAgentJsonCfg) erro
if jsnCfg.Timezone != nil {
self.Timezone = *jsnCfg.Timezone
}
+ if jsnCfg.Origin_host != nil {
+ self.OriginHost = *jsnCfg.Origin_host
+ }
+ if jsnCfg.Origin_realm != nil {
+ self.OriginRealm = *jsnCfg.Origin_realm
+ }
+ if jsnCfg.Vendor_id != nil {
+ self.VendorId = *jsnCfg.Vendor_id
+ }
+ if jsnCfg.Product_name != nil {
+ self.ProductName = *jsnCfg.Product_name
+ }
if jsnCfg.Request_processors != nil {
for _, reqProcJsn := range *jsnCfg.Request_processors {
rp := new(DARequestProcessor)
diff --git a/config/libconfig_json.go b/config/libconfig_json.go
index aa49d499a..88c29de67 100644
--- a/config/libconfig_json.go
+++ b/config/libconfig_json.go
@@ -241,6 +241,10 @@ type DiameterAgentJsonCfg struct {
Listen *string // address where to listen for diameter requests
Sm_generic *string // Connection towards generic SM
Timezone *string // timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
+ Origin_host *string
+ Origin_realm *string
+ Vendor_id *int
+ Product_name *string
Request_processors *[]*DARequestProcessorJsnCfg
}
diff --git a/data/conf/samples/dmtagent/cgrates.json b/data/conf/samples/dmtagent/cgrates.json
new file mode 100644
index 000000000..b60803e90
--- /dev/null
+++ b/data/conf/samples/dmtagent/cgrates.json
@@ -0,0 +1,82 @@
+{
+// CGRateS Configuration file
+//
+// Used for cgradmin
+// Starts rater, scheduler
+
+"listen": {
+ "rpc_json": ":2012", // RPC JSON listening address
+ "rpc_gob": ":2013", // RPC GOB listening address
+ "http": ":2080", // HTTP listening address
+},
+
+"rater": {
+ "enabled": true, // enable Rater service:
+ "cdrstats": "internal", // address where to reach the cdrstats service, empty to disable stats functionality<""|internal|x.y.z.y:1234>
+ "pubsubs": "internal", // address where to reach the pubusb service, empty to disable pubsub functionality: <""|internal|x.y.z.y:1234>
+ "users": "internal", // address where to reach the user service, empty to disable user profile functionality: <""|internal|x.y.z.y:1234>
+ "aliases": "internal",
+},
+
+"scheduler": {
+ "enabled": true, // start Scheduler service:
+},
+
+"cdrs": {
+ "enabled": true, // start the CDR Server service:
+ "rater": "internal", // address where to reach the Rater for cost calculation, empty to disable functionality: <""|internal|x.y.z.y:1234>
+ "cdrstats": "internal", // address where to reach the cdrstats service, empty to disable stats functionality<""|internal|x.y.z.y:1234>
+},
+
+"cdrstats": {
+ "enabled": true, // starts the cdrstats service:
+},
+
+"pubsubs": {
+ "enabled": true, // starts PubSub service: .
+},
+
+"aliases": {
+ "enabled": true, // starts Aliases service: .
+},
+
+"users": {
+ "enabled": true, // starts User service: .
+ "indexes": ["Uuid"], // user profile field indexes
+},
+
+"sm_generic": {
+ "enabled": true, // starts SessionManager service:
+ "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
+ "cdrs": "internal", // address where to reach CDR Server <""|internal|x.y.z.y:1234>
+},
+
+"diameter_agent": {
+ "enabled": true, // enables the diameter agent:
+ "listen": "127.0.0.1:3868", // address where to listen for diameter requests
+ "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},
+ ],
+ },
+ ],
+},
+
+}
diff --git a/devel.yaml b/devel.yaml
index 1b40bb38a..78b991013 100644
--- a/devel.yaml
+++ b/devel.yaml
@@ -19,3 +19,4 @@ import:
- package: github.com/cgrates/fsock
- package: github.com/cenkalti/rpc2
- package: github.com/cenkalti/hub
+ - package: github.com/fiorix/go-diameter
diff --git a/glide.yaml b/glide.yaml
index b6a8c8ab1..fb58e9937 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -5,7 +5,7 @@ import:
- package: github.com/jinzhu/gorm
ref: 611e613459953787a01c2afc82835aa0ba01a045
- package: golang.org/x/net
- ref: c764672d0ee39ffd83cfcb375804d3181302b62b
+ ref: 1d9fd3b8333e891c0e7353e1adcfe8a612573033
- package: github.com/DisposaBoy/JsonConfigReader
ref: 33a99fdf1d5ee1f79b5077e9c06f955ad356d5f4
- package: github.com/hoisie/redis
@@ -25,7 +25,7 @@ import:
- package: gopkg.in/fsnotify.v1
ref: 7be54206639f256967dd82fa767397ba5f8f48f5
- package: github.com/peterh/liner
- ref: 32e535aff4145c12d1e154754ab144b49ab578e2
+ ref: 506a2f061bd0b362a8a2fa445be80386f39dedd8
- package: github.com/cgrates/rpcclient
ref: 028c43fc34d32dc9095c7605e2e455e0c7a5ea69
- package: github.com/cgrates/osipsdagram
@@ -38,3 +38,5 @@ import:
ref: 2d1be381ce47537e9e076b2b76dc70933162e4e9
- package: github.com/cenkalti/hub
ref: 57d753b5f4856e77b3cf8ecce78c97215a7d324d
+ - package: github.com/fiorix/go-diameter
+ ref: b4c1bac20b8e8e1ac7e17fb54dc83b155aacba21
diff --git a/test.sh b/test.sh
index c50c89413..0c62795fc 100755
--- a/test.sh
+++ b/test.sh
@@ -11,6 +11,7 @@ go test -i github.com/cgrates/cgrates/cdrc
go test -i github.com/cgrates/cgrates/utils
go test -i github.com/cgrates/cgrates/history
go test -i github.com/cgrates/cgrates/cdre
+go test -i github.com/cgrates/cgrates/agents
go test github.com/cgrates/cgrates/apier/v1
v1=$?
@@ -38,5 +39,8 @@ go test github.com/cgrates/cgrates/cache2go
c2g=$?
go test github.com/cgrates/cgrates/cdre
cdre=$?
+go test github.com/cgrates/cgrates/agents
+ag=$?
-exit $v1 && $v2 && $en && $gt && $sm && $cfg && $bl && $cr && $con && $cdrc && $ut && $hs && $c2g && $cdre
+
+exit $v1 && $v2 && $en && $gt && $sm && $cfg && $bl && $cr && $con && $cdrc && $ut && $hs && $c2g && $cdre && $ag
diff --git a/utils/consts.go b/utils/consts.go
index d3e491ce1..204589e43 100644
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -30,6 +30,7 @@ var (
const (
VERSION = "0.9.1~rc8"
+ DIAMETER_FIRMWARE_REVISION = 918
POSTGRES = "postgres"
MYSQL = "mysql"
MONGO = "mongo"