SMAsterisk configuration, initial structures

This commit is contained in:
DanB
2016-09-07 19:26:04 +02:00
parent 8360df984a
commit 75f56f9618
7 changed files with 210 additions and 2 deletions

View File

@@ -45,6 +45,7 @@ var (
dfltFsConnConfig *FsConnConfig // Default FreeSWITCH Connection configuration, built out of json default configuration
dfltKamConnConfig *KamConnConfig // Default Kamailio Connection configuration
dfltHaPoolConfig *HaPoolConfig
dfltAstConnCfg *AsteriskConnCfg
)
// Used to retrieve system configuration from other packages
@@ -66,6 +67,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
cfg.SmFsConfig = new(SmFsConfig)
cfg.SmKamConfig = new(SmKamConfig)
cfg.SmOsipsConfig = new(SmOsipsConfig)
cfg.SMAsteriskCfg = new(SMAsteriskCfg)
cfg.diameterAgentCfg = new(DiameterAgentCfg)
cfg.ConfigReloads = make(map[string]chan struct{})
cfg.ConfigReloads[utils.CDRC] = make(chan struct{}, 1)
@@ -88,6 +90,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
cfg.dfltCdrcProfile = cfg.CdrcProfiles["/var/spool/cgrates/cdrc/in"][0].Clone()
dfltFsConnConfig = cfg.SmFsConfig.EventSocketConns[0] // We leave it crashing here on purpose if no Connection defaults defined
dfltKamConnConfig = cfg.SmKamConfig.EvapiConns[0]
dfltAstConnCfg = cfg.SMAsteriskCfg.AsteriskConns[0]
if err := cfg.checkConfigSanity(); err != nil {
return nil, err
}
@@ -242,6 +245,7 @@ type CGRConfig struct {
SmFsConfig *SmFsConfig // SMFreeSWITCH configuration
SmKamConfig *SmKamConfig // SM-Kamailio Configuration
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
SMAsteriskCfg *SMAsteriskCfg // SMAsterisk 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>.
@@ -421,7 +425,7 @@ func (self *CGRConfig) checkConfigSanity() error {
}
for _, smOsipsRaterConn := range self.SmOsipsConfig.RALsConns {
if smOsipsRaterConn.Address == utils.MetaInternal && !self.RALsEnabled {
return errors.New("<SMOpenSIPS> RALs not enabled but requested by SMOpenSIPS component.")
return errors.New("<SMOpenSIPS> RALs not enabled.")
}
}
if len(self.SmOsipsConfig.CDRsConns) == 0 {
@@ -430,7 +434,18 @@ func (self *CGRConfig) checkConfigSanity() error {
for _, smOsipsCDRSConn := range self.SmOsipsConfig.CDRsConns {
if smOsipsCDRSConn.Address == utils.MetaInternal && !self.CDRSEnabled {
return errors.New("<SMOpenSIPS> CDRS not enabled but referenced by SMOpenSIPS component")
return errors.New("<SMOpenSIPS> CDRS not enabled.")
}
}
}
// SMOpenSIPS checks
if self.SMAsteriskCfg.Enabled {
if len(self.SMAsteriskCfg.SMGConns) == 0 {
return errors.New("<SMAsterisk> SMG definition is mandatory!")
}
for _, smAstSMGConn := range self.SMAsteriskCfg.SMGConns {
if smAstSMGConn.Address == utils.MetaInternal && !self.SmGenericConfig.Enabled {
return errors.New("<SMAsterisk> SMG not enabled.")
}
}
}
@@ -548,6 +563,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
return err
}
jsnSMAstCfg, err := jsnCfg.SmAsteriskJsonCfg()
if err != nil {
return err
}
jsnDACfg, err := jsnCfg.DiameterAgentJsonCfg()
if err != nil {
return err
@@ -975,6 +995,12 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
}
}
if jsnSMAstCfg != nil {
if err := self.SMAsteriskCfg.loadFromJsonCfg(jsnSMAstCfg); err != nil {
return err
}
}
if jsnDACfg != nil {
if err := self.diameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
return err

View File

@@ -331,6 +331,21 @@ const CGRATES_CFG_JSON = `
},
"sm_asterisk": {
"enabled": false, // starts Asterisk SessionManager service: <true|false>
"sm_generic_conns": [
{"address": "*internal"} // connection towards SMG component for session management
],
"session_terminate_subscriber": {"address": "*internal"}, // handler for session_terminate events generated by SMG
"debit_interval": "10s", // interval to perform debits on.
"min_call_duration": "0s", // only authorize calls with allowed duration higher than this
"max_call_duration": "3h", // maximum call duration a prepaid call can last
"asterisk_conns":[ // instantiate connections to multiple Asterisk servers
{"address": "127.0.0.1:8088", "user": "cgrates", "password": "CGRateS.org", "reconnects": 5}
],
},
"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>

View File

@@ -44,6 +44,7 @@ const (
SMFS_JSN = "sm_freeswitch"
SMKAM_JSN = "sm_kamailio"
SMOSIPS_JSN = "sm_opensips"
SMAsteriskJSN = "sm_asterisk"
SM_JSN = "session_manager"
FS_JSN = "freeswitch"
KAMAILIO_JSN = "kamailio"
@@ -261,6 +262,18 @@ func (self CgrJsonCfg) SmOsipsJsonCfg() (*SmOsipsJsonCfg, error) {
return cfg, nil
}
func (self CgrJsonCfg) SmAsteriskJsonCfg() (*SMAsteriskJsonCfg, error) {
rawCfg, hasKey := self[SMAsteriskJSN]
if !hasKey {
return nil, nil
}
cfg := new(SMAsteriskJsonCfg)
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
return nil, err
}
return cfg, nil
}
func (self CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) {
rawCfg, hasKey := self[DA_JSN]
if !hasKey {

View File

@@ -516,6 +516,33 @@ func TestSmOsipsJsonCfg(t *testing.T) {
}
}
func TestSmAsteriskJsonCfg(t *testing.T) {
eCfg := &SMAsteriskJsonCfg{
Enabled: utils.BoolPointer(false),
Sm_generic_conns: &[]*HaPoolJsonCfg{
&HaPoolJsonCfg{
Address: utils.StringPointer(utils.MetaInternal),
}},
Session_terminate_subscriber: &HaPoolJsonCfg{Address: utils.StringPointer(utils.MetaInternal)},
Debit_interval: utils.StringPointer("10s"),
Min_call_duration: utils.StringPointer("0s"),
Max_call_duration: utils.StringPointer("3h"),
Asterisk_conns: &[]*AstConnJsonCfg{
&AstConnJsonCfg{
Address: utils.StringPointer("127.0.0.1:8088"),
User: utils.StringPointer("cgrates"),
Password: utils.StringPointer("CGRateS.org"),
Reconnects: utils.IntPointer(5),
},
},
}
if cfg, err := dfCgrJsonCfg.SmAsteriskJsonCfg(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfg, cfg) {
t.Error("Received: ", cfg)
}
}
func TestDiameterAgentJsonCfg(t *testing.T) {
eCfg := &DiameterAgentJsonCfg{
Enabled: utils.BoolPointer(false),

View File

@@ -214,6 +214,23 @@ type HaPoolJsonCfg struct {
Transport *string
}
type AstConnJsonCfg struct {
Address *string
User *string
Password *string
Reconnects *int
}
type SMAsteriskJsonCfg struct {
Enabled *bool
Sm_generic_conns *[]*HaPoolJsonCfg // Connections towards generic SM
Session_terminate_subscriber *HaPoolJsonCfg
Debit_interval *string
Min_call_duration *string
Max_call_duration *string
Asterisk_conns *[]*AstConnJsonCfg
}
type CacheParamJsonCfg struct {
Limit *int
Ttl *string

View File

@@ -435,3 +435,85 @@ func (self *SmOsipsConfig) loadFromJsonCfg(jsnCfg *SmOsipsJsonCfg) error {
return nil
}
// Uses stored defaults so we can pre-populate by loading from JSON config
func NewDefaultAsteriskConnCfg() *AsteriskConnCfg {
if dfltAstConnCfg == nil {
return new(AsteriskConnCfg) // No defaults, most probably we are building the defaults now
}
dfltVal := *dfltAstConnCfg // Copy the value instead of it's pointer
return &dfltVal
}
type AsteriskConnCfg struct {
Address string
User string
Password string
Reconnects int
}
func (aConnCfg *AsteriskConnCfg) loadFromJsonCfg(jsnCfg *AstConnJsonCfg) error {
if jsnCfg.Address != nil {
aConnCfg.Address = *jsnCfg.Address
}
if jsnCfg.User != nil {
aConnCfg.User = *jsnCfg.User
}
if jsnCfg.Password != nil {
aConnCfg.Password = *jsnCfg.Password
}
if jsnCfg.Reconnects != nil {
aConnCfg.Reconnects = *jsnCfg.Reconnects
}
return nil
}
type SMAsteriskCfg struct {
Enabled bool
SMGConns []*HaPoolConfig
SessionTerminateSubscriber *HaPoolConfig
DebitInterval time.Duration
MinCallDuration time.Duration
MaxCallDuration time.Duration
AsteriskConns []*AsteriskConnCfg
}
func (aCfg *SMAsteriskCfg) loadFromJsonCfg(jsnCfg *SMAsteriskJsonCfg) (err error) {
if jsnCfg.Enabled != nil {
aCfg.Enabled = *jsnCfg.Enabled
}
if jsnCfg.Sm_generic_conns != nil {
aCfg.SMGConns = make([]*HaPoolConfig, len(*jsnCfg.Sm_generic_conns))
for idx, jsnHaCfg := range *jsnCfg.Sm_generic_conns {
aCfg.SMGConns[idx] = NewDfltHaPoolConfig()
aCfg.SMGConns[idx].loadFromJsonCfg(jsnHaCfg)
}
}
if jsnCfg.Session_terminate_subscriber != nil {
aCfg.SessionTerminateSubscriber = NewDfltHaPoolConfig()
aCfg.SessionTerminateSubscriber.loadFromJsonCfg(jsnCfg.Session_terminate_subscriber)
}
if jsnCfg.Debit_interval != nil {
if aCfg.DebitInterval, err = utils.ParseDurationWithSecs(*jsnCfg.Debit_interval); err != nil {
return err
}
}
if jsnCfg.Min_call_duration != nil {
if aCfg.MinCallDuration, err = utils.ParseDurationWithSecs(*jsnCfg.Min_call_duration); err != nil {
return err
}
}
if jsnCfg.Max_call_duration != nil {
if aCfg.MaxCallDuration, err = utils.ParseDurationWithSecs(*jsnCfg.Max_call_duration); err != nil {
return err
}
}
if jsnCfg.Asterisk_conns != nil {
aCfg.AsteriskConns = make([]*AsteriskConnCfg, len(*jsnCfg.Asterisk_conns))
for i, jsnAConn := range *jsnCfg.Asterisk_conns {
aCfg.AsteriskConns[i] = NewDefaultAsteriskConnCfg()
aCfg.AsteriskConns[i].loadFromJsonCfg(jsnAConn)
}
}
return nil
}

View File

@@ -0,0 +1,28 @@
/*
Real-time Online/Offline Charging System (OCS) 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 sessionmanager
import (
"github.com/cgrates/cgrates/config"
"github.com/cgrates/rpcclient"
)
type SMAsterisk struct {
cgrCfg *config.CGRConfig // Separate from smCfg since there can be multiple
smg rpcclient.RpcClientConnection
}