/* 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 */ package config import ( "fmt" "strconv" "time" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) // NewDfltFsConnConfig returns the first cached default value for a FreeSWITCHAgent connection func NewDfltFsConnConfig() *FsConnCfg { if dfltFsConnConfig == nil { return new(FsConnCfg) // No defaults, most probably we are building the defaults now } dfltVal := *dfltFsConnConfig // Copy the value instead of it's pointer return &dfltVal } // FsConnCfg one connection to FreeSWITCH server type FsConnCfg struct { Address string Password string Reconnects int MaxReconnectInterval time.Duration ReplyTimeout time.Duration Alias string } func (fs *FsConnCfg) loadFromJSONCfg(jsnCfg *FsConnJsonCfg) (err error) { if jsnCfg == nil { return } if jsnCfg.Address != nil { fs.Address = *jsnCfg.Address } if jsnCfg.Password != nil { fs.Password = *jsnCfg.Password } if jsnCfg.Reconnects != nil { fs.Reconnects = *jsnCfg.Reconnects } if jsnCfg.MaxReconnectInterval != nil { if fs.MaxReconnectInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.MaxReconnectInterval); err != nil { return } } if jsnCfg.ReplyTimeout != nil { if fs.ReplyTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.ReplyTimeout); err != nil { return } } fs.Alias = fs.Address if jsnCfg.Alias != nil && *jsnCfg.Alias != "" { fs.Alias = *jsnCfg.Alias } return } // AsMapInterface returns the config as a map[string]any func (fs *FsConnCfg) AsMapInterface() map[string]any { return map[string]any{ utils.AddressCfg: fs.Address, utils.Password: fs.Password, utils.ReconnectsCfg: fs.Reconnects, utils.MaxReconnectIntervalCfg: fs.MaxReconnectInterval.String(), utils.ReplyTimeoutCfg: fs.ReplyTimeout.String(), utils.AliasCfg: fs.Alias, } } // Clone returns a deep copy of FsConnCfg func (fs FsConnCfg) Clone() *FsConnCfg { return &FsConnCfg{ Address: fs.Address, Password: fs.Password, Reconnects: fs.Reconnects, MaxReconnectInterval: fs.MaxReconnectInterval, ReplyTimeout: fs.ReplyTimeout, Alias: fs.Alias, } } // SessionSCfg is the config section for SessionS type SessionSCfg struct { Enabled bool ListenBijson string ListenBigob string ChargerSConns []string RALsConns []string ResSConns []string ThreshSConns []string StatSConns []string RouteSConns []string AttrSConns []string CDRsConns []string ReplicationConns []string DebitInterval time.Duration StoreSCosts bool SessionTTL time.Duration SessionTTLMaxDelay *time.Duration SessionTTLLastUsed *time.Duration SessionTTLUsage *time.Duration SessionTTLLastUsage *time.Duration SessionIndexes utils.StringSet ClientProtocol float64 ChannelSyncInterval time.Duration StaleChanMaxExtraUsage time.Duration TerminateAttempts int AlterableFields utils.StringSet MinDurLowBalance time.Duration SchedulerConns []string STIRCfg *STIRcfg DefaultUsage map[string]time.Duration BackupInterval time.Duration } func (scfg *SessionSCfg) loadFromJSONCfg(jsnCfg *SessionSJsonCfg) (err error) { if jsnCfg == nil { return nil } if jsnCfg.Enabled != nil { scfg.Enabled = *jsnCfg.Enabled } if jsnCfg.Listen_bijson != nil { scfg.ListenBijson = *jsnCfg.Listen_bijson } if jsnCfg.Listen_bigob != nil { scfg.ListenBigob = *jsnCfg.Listen_bigob } if jsnCfg.Chargers_conns != nil { scfg.ChargerSConns = make([]string, len(*jsnCfg.Chargers_conns)) for idx, connID := range *jsnCfg.Chargers_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.ChargerSConns[idx] = connID if connID == utils.MetaInternal { scfg.ChargerSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaChargers) } } } if jsnCfg.Rals_conns != nil { scfg.RALsConns = make([]string, len(*jsnCfg.Rals_conns)) for idx, connID := range *jsnCfg.Rals_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.RALsConns[idx] = connID if connID == utils.MetaInternal { scfg.RALsConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResponder) } } } if jsnCfg.Resources_conns != nil { scfg.ResSConns = make([]string, len(*jsnCfg.Resources_conns)) for idx, connID := range *jsnCfg.Resources_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.ResSConns[idx] = connID if connID == utils.MetaInternal { scfg.ResSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResources) } } } if jsnCfg.Thresholds_conns != nil { scfg.ThreshSConns = make([]string, len(*jsnCfg.Thresholds_conns)) for idx, connID := range *jsnCfg.Thresholds_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.ThreshSConns[idx] = connID if connID == utils.MetaInternal { scfg.ThreshSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds) } } } if jsnCfg.Stats_conns != nil { scfg.StatSConns = make([]string, len(*jsnCfg.Stats_conns)) for idx, connID := range *jsnCfg.Stats_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.StatSConns[idx] = connID if connID == utils.MetaInternal { scfg.StatSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats) } } } if jsnCfg.Routes_conns != nil { scfg.RouteSConns = make([]string, len(*jsnCfg.Routes_conns)) for idx, connID := range *jsnCfg.Routes_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.RouteSConns[idx] = connID if connID == utils.MetaInternal { scfg.RouteSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRoutes) } } } if jsnCfg.Attributes_conns != nil { scfg.AttrSConns = make([]string, len(*jsnCfg.Attributes_conns)) for idx, connID := range *jsnCfg.Attributes_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.AttrSConns[idx] = connID if connID == utils.MetaInternal { scfg.AttrSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAttributes) } } } if jsnCfg.Cdrs_conns != nil { scfg.CDRsConns = make([]string, len(*jsnCfg.Cdrs_conns)) for idx, connID := range *jsnCfg.Cdrs_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.CDRsConns[idx] = connID if connID == utils.MetaInternal { scfg.CDRsConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs) } } } if jsnCfg.Replication_conns != nil { scfg.ReplicationConns = make([]string, len(*jsnCfg.Replication_conns)) for idx, connID := range *jsnCfg.Replication_conns { if connID == utils.MetaInternal { return fmt.Errorf("Replication connection ID needs to be different than *internal") } scfg.ReplicationConns[idx] = connID } } if jsnCfg.Debit_interval != nil { if scfg.DebitInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.Debit_interval); err != nil { return err } } if jsnCfg.Store_session_costs != nil { scfg.StoreSCosts = *jsnCfg.Store_session_costs } if jsnCfg.Session_ttl != nil { if scfg.SessionTTL, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl); err != nil { return err } } if jsnCfg.Session_ttl_max_delay != nil { var maxTTLDelay time.Duration if maxTTLDelay, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl_max_delay); err != nil { return err } scfg.SessionTTLMaxDelay = &maxTTLDelay } if jsnCfg.Session_ttl_last_used != nil { var sessionTTLLastUsed time.Duration if sessionTTLLastUsed, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl_last_used); err != nil { return err } scfg.SessionTTLLastUsed = &sessionTTLLastUsed } if jsnCfg.Session_ttl_usage != nil { var sessionTTLUsage time.Duration if sessionTTLUsage, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl_usage); err != nil { return err } scfg.SessionTTLUsage = &sessionTTLUsage } if jsnCfg.Session_ttl_last_usage != nil { var sessionTTLLastUsage time.Duration if sessionTTLLastUsage, err = utils.ParseDurationWithNanosecs(*jsnCfg.Session_ttl_last_usage); err != nil { return err } scfg.SessionTTLLastUsage = &sessionTTLLastUsage } if jsnCfg.Session_indexes != nil { scfg.SessionIndexes = utils.NewStringSet(*jsnCfg.Session_indexes) } if jsnCfg.Client_protocol != nil { scfg.ClientProtocol = *jsnCfg.Client_protocol } if jsnCfg.Channel_sync_interval != nil { if scfg.ChannelSyncInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.Channel_sync_interval); err != nil { return err } } if jsnCfg.Stale_chan_max_extra_usage != nil { if scfg.StaleChanMaxExtraUsage, err = utils.ParseDurationWithNanosecs(*jsnCfg.Stale_chan_max_extra_usage); err != nil { return err } } if jsnCfg.Terminate_attempts != nil { scfg.TerminateAttempts = *jsnCfg.Terminate_attempts } if jsnCfg.Alterable_fields != nil { scfg.AlterableFields = utils.NewStringSet(*jsnCfg.Alterable_fields) } if jsnCfg.Min_dur_low_balance != nil { if scfg.MinDurLowBalance, err = utils.ParseDurationWithNanosecs(*jsnCfg.Min_dur_low_balance); err != nil { return err } } if jsnCfg.Default_usage != nil { for k, v := range *jsnCfg.Default_usage { if scfg.DefaultUsage[k], err = utils.ParseDurationWithNanosecs(v); err != nil { return } } } if jsnCfg.Scheduler_conns != nil { scfg.SchedulerConns = make([]string, len(*jsnCfg.Scheduler_conns)) for idx, connID := range *jsnCfg.Scheduler_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem scfg.SchedulerConns[idx] = connID if connID == utils.MetaInternal { scfg.SchedulerConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaScheduler) } } } if jsnCfg.Backup_interval != nil { if scfg.BackupInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.Backup_interval); err != nil { return err } } return scfg.STIRCfg.loadFromJSONCfg(jsnCfg.Stir) } func (scfg *SessionSCfg) GetDefaultUsage(tor string) time.Duration { if tor == utils.EmptyString { tor = utils.MetaAny } return scfg.DefaultUsage[tor] } // AsMapInterface returns the config as a map[string]any func (scfg *SessionSCfg) AsMapInterface() (initialMP map[string]any) { maxComputed := make(map[string]string) for key, item := range scfg.DefaultUsage { if key == utils.MetaAny || key == utils.MetaVoice { maxComputed[key] = item.String() } else { maxComputed[key] = strconv.Itoa(int(item)) } } initialMP = map[string]any{ utils.EnabledCfg: scfg.Enabled, utils.ListenBijsonCfg: scfg.ListenBijson, utils.ListenBigobCfg: scfg.ListenBigob, utils.ReplicationConnsCfg: scfg.ReplicationConns, utils.StoreSCostsCfg: scfg.StoreSCosts, utils.SessionIndexesCfg: scfg.SessionIndexes.AsSlice(), utils.ClientProtocolCfg: scfg.ClientProtocol, utils.TerminateAttemptsCfg: scfg.TerminateAttempts, utils.AlterableFieldsCfg: scfg.AlterableFields.AsSlice(), utils.STIRCfg: scfg.STIRCfg.AsMapInterface(), utils.MinDurLowBalanceCfg: "0", utils.ChannelSyncIntervalCfg: "0", utils.StaleChanMaxExtraUsageCfg: "0", utils.DebitIntervalCfg: "0", utils.SessionTTLCfg: "0", utils.BackupIntervalCfg: "0", utils.DefaultUsageCfg: maxComputed, } if scfg.DebitInterval != 0 { initialMP[utils.DebitIntervalCfg] = scfg.DebitInterval.String() } if scfg.SessionTTL != 0 { initialMP[utils.SessionTTLCfg] = scfg.SessionTTL.String() } if scfg.SessionTTLMaxDelay != nil { initialMP[utils.SessionTTLMaxDelayCfg] = scfg.SessionTTLMaxDelay.String() } if scfg.SessionTTLLastUsed != nil { initialMP[utils.SessionTTLLastUsedCfg] = scfg.SessionTTLLastUsed.String() } if scfg.SessionTTLUsage != nil { initialMP[utils.SessionTTLUsageCfg] = scfg.SessionTTLUsage.String() } if scfg.SessionTTLLastUsage != nil { initialMP[utils.SessionTTLLastUsageCfg] = scfg.SessionTTLLastUsage.String() } if scfg.ChannelSyncInterval != 0 { initialMP[utils.ChannelSyncIntervalCfg] = scfg.ChannelSyncInterval.String() } if scfg.StaleChanMaxExtraUsage != 0 { initialMP[utils.StaleChanMaxExtraUsageCfg] = scfg.StaleChanMaxExtraUsage.String() } if scfg.MinDurLowBalance != 0 { initialMP[utils.MinDurLowBalanceCfg] = scfg.MinDurLowBalance.String() } if scfg.ChargerSConns != nil { chargerSConns := make([]string, len(scfg.ChargerSConns)) for i, item := range scfg.ChargerSConns { chargerSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaChargers) { chargerSConns[i] = utils.MetaInternal } } initialMP[utils.ChargerSConnsCfg] = chargerSConns } if scfg.RALsConns != nil { RALsConns := make([]string, len(scfg.RALsConns)) for i, item := range scfg.RALsConns { RALsConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResponder) { RALsConns[i] = utils.MetaInternal } } initialMP[utils.RALsConnsCfg] = RALsConns } if scfg.ResSConns != nil { resSConns := make([]string, len(scfg.ResSConns)) for i, item := range scfg.ResSConns { resSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResources) { resSConns[i] = utils.MetaInternal } } initialMP[utils.ResourceSConnsCfg] = resSConns } if scfg.ThreshSConns != nil { threshSConns := make([]string, len(scfg.ThreshSConns)) for i, item := range scfg.ThreshSConns { threshSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds) { threshSConns[i] = utils.MetaInternal } } initialMP[utils.ThresholdSConnsCfg] = threshSConns } if scfg.StatSConns != nil { statSConns := make([]string, len(scfg.StatSConns)) for i, item := range scfg.StatSConns { statSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats) { statSConns[i] = utils.MetaInternal } } initialMP[utils.StatSConnsCfg] = statSConns } if scfg.RouteSConns != nil { routesConns := make([]string, len(scfg.RouteSConns)) for i, item := range scfg.RouteSConns { routesConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRoutes) { routesConns[i] = utils.MetaInternal } } initialMP[utils.RouteSConnsCfg] = routesConns } if scfg.AttrSConns != nil { attrSConns := make([]string, len(scfg.AttrSConns)) for i, item := range scfg.AttrSConns { attrSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAttributes) { attrSConns[i] = utils.MetaInternal } } initialMP[utils.AttributeSConnsCfg] = attrSConns } if scfg.CDRsConns != nil { CDRsConns := make([]string, len(scfg.CDRsConns)) for i, item := range scfg.CDRsConns { CDRsConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs) { CDRsConns[i] = utils.MetaInternal } } initialMP[utils.CDRsConnsCfg] = CDRsConns } if scfg.SchedulerConns != nil { schedulerConns := make([]string, len(scfg.SchedulerConns)) for i, item := range scfg.SchedulerConns { schedulerConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaScheduler) { schedulerConns[i] = utils.MetaInternal } } initialMP[utils.SchedulerConnsCfg] = schedulerConns } if scfg.BackupInterval != 0 { initialMP[utils.BackupIntervalCfg] = scfg.BackupInterval.String() } return } // Clone returns a deep copy of SessionSCfg func (scfg SessionSCfg) Clone() (cln *SessionSCfg) { cln = &SessionSCfg{ Enabled: scfg.Enabled, ListenBijson: scfg.ListenBijson, DebitInterval: scfg.DebitInterval, StoreSCosts: scfg.StoreSCosts, SessionTTL: scfg.SessionTTL, BackupInterval: scfg.BackupInterval, ClientProtocol: scfg.ClientProtocol, ChannelSyncInterval: scfg.ChannelSyncInterval, StaleChanMaxExtraUsage: scfg.StaleChanMaxExtraUsage, TerminateAttempts: scfg.TerminateAttempts, MinDurLowBalance: scfg.MinDurLowBalance, SessionIndexes: scfg.SessionIndexes.Clone(), AlterableFields: scfg.AlterableFields.Clone(), STIRCfg: scfg.STIRCfg.Clone(), DefaultUsage: make(map[string]time.Duration), } for k, v := range scfg.DefaultUsage { cln.DefaultUsage[k] = v } if scfg.SessionTTLMaxDelay != nil { cln.SessionTTLMaxDelay = new(time.Duration) *cln.SessionTTLMaxDelay = *scfg.SessionTTLMaxDelay } if scfg.SessionTTLLastUsed != nil { cln.SessionTTLLastUsed = new(time.Duration) *cln.SessionTTLLastUsed = *scfg.SessionTTLLastUsed } if scfg.SessionTTLUsage != nil { cln.SessionTTLUsage = new(time.Duration) *cln.SessionTTLUsage = *scfg.SessionTTLUsage } if scfg.SessionTTLLastUsage != nil { cln.SessionTTLLastUsage = new(time.Duration) *cln.SessionTTLLastUsage = *scfg.SessionTTLLastUsage } if scfg.ChargerSConns != nil { cln.ChargerSConns = make([]string, len(scfg.ChargerSConns)) copy(cln.ChargerSConns, scfg.ChargerSConns) } if scfg.RALsConns != nil { cln.RALsConns = make([]string, len(scfg.RALsConns)) copy(cln.RALsConns, scfg.RALsConns) } if scfg.ResSConns != nil { cln.ResSConns = make([]string, len(scfg.ResSConns)) copy(cln.ResSConns, scfg.ResSConns) } if scfg.ThreshSConns != nil { cln.ThreshSConns = make([]string, len(scfg.ThreshSConns)) copy(cln.ThreshSConns, scfg.ThreshSConns) } if scfg.StatSConns != nil { cln.StatSConns = make([]string, len(scfg.StatSConns)) copy(cln.StatSConns, scfg.StatSConns) } if scfg.RouteSConns != nil { cln.RouteSConns = make([]string, len(scfg.RouteSConns)) copy(cln.RouteSConns, scfg.RouteSConns) } if scfg.AttrSConns != nil { cln.AttrSConns = make([]string, len(scfg.AttrSConns)) copy(cln.AttrSConns, scfg.AttrSConns) } if scfg.CDRsConns != nil { cln.CDRsConns = make([]string, len(scfg.CDRsConns)) copy(cln.CDRsConns, scfg.CDRsConns) } if scfg.ReplicationConns != nil { cln.ReplicationConns = make([]string, len(scfg.ReplicationConns)) copy(cln.ReplicationConns, scfg.ReplicationConns) } if scfg.SchedulerConns != nil { cln.SchedulerConns = make([]string, len(scfg.SchedulerConns)) copy(cln.SchedulerConns, scfg.SchedulerConns) } return } // FsAgentCfg the config section that describes the FreeSWITCH Agent type FsAgentCfg struct { Enabled bool SessionSConns []string SubscribePark bool CreateCDR bool ExtraFields RSRParsers LowBalanceAnnFile string EmptyBalanceContext string EmptyBalanceAnnFile string ActiveSessionDelimiter string MaxWaitConnection time.Duration EventSocketConns []*FsConnCfg } func (fscfg *FsAgentCfg) loadFromJSONCfg(jsnCfg *FreeswitchAgentJsonCfg) error { if jsnCfg == nil { return nil } var err error if jsnCfg.Enabled != nil { fscfg.Enabled = *jsnCfg.Enabled } if jsnCfg.SessionSConns != nil { fscfg.SessionSConns = make([]string, len(*jsnCfg.SessionSConns)) for idx, connID := range *jsnCfg.SessionSConns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem fscfg.SessionSConns[idx] = connID if connID == utils.MetaInternal || connID == rpcclient.BiRPCInternal { fscfg.SessionSConns[idx] = utils.ConcatenatedKey(connID, utils.MetaSessionS) } } } if jsnCfg.SubscribePark != nil { fscfg.SubscribePark = *jsnCfg.SubscribePark } if jsnCfg.CreateCDR != nil { fscfg.CreateCDR = *jsnCfg.CreateCDR } if jsnCfg.ExtraFields != nil { if fscfg.ExtraFields, err = NewRSRParsersFromSlice(*jsnCfg.ExtraFields); err != nil { return err } } if jsnCfg.LowBalanceAnnFile != nil { fscfg.LowBalanceAnnFile = *jsnCfg.LowBalanceAnnFile } if jsnCfg.EmptyBalanceContext != nil { fscfg.EmptyBalanceContext = *jsnCfg.EmptyBalanceContext } if jsnCfg.EmptyBalanceAnnFile != nil { fscfg.EmptyBalanceAnnFile = *jsnCfg.EmptyBalanceAnnFile } if jsnCfg.ActiveSessionDelimiter != nil { fscfg.ActiveSessionDelimiter = *jsnCfg.ActiveSessionDelimiter } if jsnCfg.MaxWaitConnection != nil { if fscfg.MaxWaitConnection, err = utils.ParseDurationWithNanosecs(*jsnCfg.MaxWaitConnection); err != nil { return err } } if jsnCfg.EventSocketConns != nil { fscfg.EventSocketConns = make([]*FsConnCfg, len(*jsnCfg.EventSocketConns)) for idx, jsnConnCfg := range *jsnCfg.EventSocketConns { fscfg.EventSocketConns[idx] = NewDfltFsConnConfig() fscfg.EventSocketConns[idx].loadFromJSONCfg(jsnConnCfg) } } return nil } // AsMapInterface returns the config as a map[string]any func (fscfg *FsAgentCfg) AsMapInterface(separator string) (initialMP map[string]any) { initialMP = map[string]any{ utils.EnabledCfg: fscfg.Enabled, utils.SubscribeParkCfg: fscfg.SubscribePark, utils.CreateCdrCfg: fscfg.CreateCDR, utils.LowBalanceAnnFileCfg: fscfg.LowBalanceAnnFile, utils.EmptyBalanceContextCfg: fscfg.EmptyBalanceContext, utils.EmptyBalanceAnnFileCfg: fscfg.EmptyBalanceAnnFile, utils.ActiveSessionDelimiterCfg: fscfg.ActiveSessionDelimiter, } if fscfg.SessionSConns != nil { sessionSConns := make([]string, len(fscfg.SessionSConns)) for i, item := range fscfg.SessionSConns { sessionSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS) { sessionSConns[i] = utils.MetaInternal } else if item == utils.ConcatenatedKey(rpcclient.BiRPCInternal, utils.MetaSessionS) { sessionSConns[i] = rpcclient.BiRPCInternal } } initialMP[utils.SessionSConnsCfg] = sessionSConns } if fscfg.ExtraFields != nil { initialMP[utils.ExtraFieldsCfg] = fscfg.ExtraFields.GetRule(separator) } if fscfg.MaxWaitConnection != 0 { initialMP[utils.MaxWaitConnectionCfg] = fscfg.MaxWaitConnection.String() } else { initialMP[utils.MaxWaitConnectionCfg] = utils.EmptyString } if fscfg.EventSocketConns != nil { eventSocketConns := make([]map[string]any, len(fscfg.EventSocketConns)) for key, item := range fscfg.EventSocketConns { eventSocketConns[key] = item.AsMapInterface() } initialMP[utils.EventSocketConnsCfg] = eventSocketConns } return } // Clone returns a deep copy of FsAgentCfg func (fscfg FsAgentCfg) Clone() (cln *FsAgentCfg) { cln = &FsAgentCfg{ Enabled: fscfg.Enabled, SubscribePark: fscfg.SubscribePark, CreateCDR: fscfg.CreateCDR, ExtraFields: fscfg.ExtraFields.Clone(), LowBalanceAnnFile: fscfg.LowBalanceAnnFile, EmptyBalanceContext: fscfg.EmptyBalanceContext, EmptyBalanceAnnFile: fscfg.EmptyBalanceAnnFile, ActiveSessionDelimiter: fscfg.ActiveSessionDelimiter, MaxWaitConnection: fscfg.MaxWaitConnection, } if fscfg.SessionSConns != nil { cln.SessionSConns = make([]string, len(fscfg.SessionSConns)) copy(cln.SessionSConns, fscfg.SessionSConns) } if fscfg.EventSocketConns != nil { cln.EventSocketConns = make([]*FsConnCfg, len(fscfg.EventSocketConns)) for i, req := range fscfg.EventSocketConns { cln.EventSocketConns[i] = req.Clone() } } return } // NewDefaultAsteriskConnCfg is 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 } // AsteriskConnCfg the config for a Asterisk connection type AsteriskConnCfg struct { Alias string Address string User string Password string ConnectAttempts int Reconnects int MaxReconnectInterval time.Duration } func (aConnCfg *AsteriskConnCfg) loadFromJSONCfg(jsnCfg *AstConnJsonCfg) (err error) { if jsnCfg == nil { return } if jsnCfg.Address != nil { aConnCfg.Address = *jsnCfg.Address } if jsnCfg.Alias != nil { aConnCfg.Alias = *jsnCfg.Alias } if jsnCfg.User != nil { aConnCfg.User = *jsnCfg.User } if jsnCfg.Password != nil { aConnCfg.Password = *jsnCfg.Password } if jsnCfg.Connect_attempts != nil { aConnCfg.ConnectAttempts = *jsnCfg.Connect_attempts } if jsnCfg.Reconnects != nil { aConnCfg.Reconnects = *jsnCfg.Reconnects } if jsnCfg.Max_reconnect_interval != nil { if aConnCfg.MaxReconnectInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.Max_reconnect_interval); err != nil { return } } return } // AsMapInterface returns the config as a map[string]any func (aConnCfg *AsteriskConnCfg) AsMapInterface() map[string]any { return map[string]any{ utils.AliasCfg: aConnCfg.Alias, utils.AddressCfg: aConnCfg.Address, utils.UserCf: aConnCfg.User, utils.Password: aConnCfg.Password, utils.ConnectAttemptsCfg: aConnCfg.ConnectAttempts, utils.ReconnectsCfg: aConnCfg.Reconnects, utils.MaxReconnectIntervalCfg: aConnCfg.MaxReconnectInterval.String(), } } // Clone returns a deep copy of AsteriskConnCfg func (aConnCfg AsteriskConnCfg) Clone() *AsteriskConnCfg { return &AsteriskConnCfg{ Alias: aConnCfg.Alias, Address: aConnCfg.Address, User: aConnCfg.User, Password: aConnCfg.Password, ConnectAttempts: aConnCfg.ConnectAttempts, Reconnects: aConnCfg.Reconnects, MaxReconnectInterval: aConnCfg.MaxReconnectInterval, } } // AsteriskAgentCfg the config section that describes the Asterisk Agent type AsteriskAgentCfg struct { Enabled bool SessionSConns []string CreateCDR bool AsteriskConns []*AsteriskConnCfg } func (aCfg *AsteriskAgentCfg) loadFromJSONCfg(jsnCfg *AsteriskAgentJsonCfg) (err error) { if jsnCfg == nil { return nil } if jsnCfg.Enabled != nil { aCfg.Enabled = *jsnCfg.Enabled } if jsnCfg.Sessions_conns != nil { aCfg.SessionSConns = make([]string, len(*jsnCfg.Sessions_conns)) for idx, attrConn := range *jsnCfg.Sessions_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem aCfg.SessionSConns[idx] = attrConn if attrConn == utils.MetaInternal || attrConn == rpcclient.BiRPCInternal { aCfg.SessionSConns[idx] = utils.ConcatenatedKey(attrConn, utils.MetaSessionS) } } } if jsnCfg.Create_cdr != nil { aCfg.CreateCDR = *jsnCfg.Create_cdr } 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 } // AsMapInterface returns the config as a map[string]any func (aCfg *AsteriskAgentCfg) AsMapInterface() (initialMP map[string]any) { initialMP = map[string]any{ utils.EnabledCfg: aCfg.Enabled, utils.CreateCDRCfg: aCfg.CreateCDR, } if aCfg.AsteriskConns != nil { conns := make([]map[string]any, len(aCfg.AsteriskConns)) for i, item := range aCfg.AsteriskConns { conns[i] = item.AsMapInterface() } initialMP[utils.AsteriskConnsCfg] = conns } if aCfg.SessionSConns != nil { sessionSConns := make([]string, len(aCfg.SessionSConns)) for i, item := range aCfg.SessionSConns { sessionSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS) { sessionSConns[i] = utils.MetaInternal } else if item == utils.ConcatenatedKey(rpcclient.BiRPCInternal, utils.MetaSessionS) { sessionSConns[i] = rpcclient.BiRPCInternal } } initialMP[utils.SessionSConnsCfg] = sessionSConns } return } // Clone returns a deep copy of AsteriskAgentCfg func (aCfg AsteriskAgentCfg) Clone() (cln *AsteriskAgentCfg) { cln = &AsteriskAgentCfg{ Enabled: aCfg.Enabled, CreateCDR: aCfg.CreateCDR, } if aCfg.SessionSConns != nil { cln.SessionSConns = make([]string, len(aCfg.SessionSConns)) copy(cln.SessionSConns, aCfg.SessionSConns) } if aCfg.AsteriskConns != nil { cln.AsteriskConns = make([]*AsteriskConnCfg, len(aCfg.AsteriskConns)) for i, req := range aCfg.AsteriskConns { cln.AsteriskConns[i] = req.Clone() } } return } // STIRcfg the confuguration structure for STIR type STIRcfg struct { AllowedAttest utils.StringSet PayloadMaxduration time.Duration DefaultAttest string PublicKeyPath string PrivateKeyPath string } func (stirCfg *STIRcfg) loadFromJSONCfg(jsnCfg *STIRJsonCfg) (err error) { if jsnCfg == nil { return nil } if jsnCfg.Allowed_attest != nil { stirCfg.AllowedAttest = utils.NewStringSet(*jsnCfg.Allowed_attest) } if jsnCfg.Payload_maxduration != nil { if stirCfg.PayloadMaxduration, err = utils.ParseDurationWithNanosecs(*jsnCfg.Payload_maxduration); err != nil { return err } } if jsnCfg.Default_attest != nil { stirCfg.DefaultAttest = *jsnCfg.Default_attest } if jsnCfg.Publickey_path != nil { stirCfg.PublicKeyPath = *jsnCfg.Publickey_path } if jsnCfg.Privatekey_path != nil { stirCfg.PrivateKeyPath = *jsnCfg.Privatekey_path } return nil } // AsMapInterface returns the config as a map[string]any func (stirCfg *STIRcfg) AsMapInterface() (initialMP map[string]any) { initialMP = map[string]any{ utils.DefaultAttestCfg: stirCfg.DefaultAttest, utils.PublicKeyPathCfg: stirCfg.PublicKeyPath, utils.PrivateKeyPathCfg: stirCfg.PrivateKeyPath, utils.AllowedAtestCfg: stirCfg.AllowedAttest.AsSlice(), utils.PayloadMaxdurationCfg: "0", } if stirCfg.PayloadMaxduration > 0 { initialMP[utils.PayloadMaxdurationCfg] = stirCfg.PayloadMaxduration.String() } else if stirCfg.PayloadMaxduration < 0 { initialMP[utils.PayloadMaxdurationCfg] = "-1" } return } // Clone returns a deep copy of STIRcfg func (stirCfg STIRcfg) Clone() *STIRcfg { return &STIRcfg{ AllowedAttest: stirCfg.AllowedAttest.Clone(), PayloadMaxduration: stirCfg.PayloadMaxduration, DefaultAttest: stirCfg.DefaultAttest, PublicKeyPath: stirCfg.PublicKeyPath, PrivateKeyPath: stirCfg.PrivateKeyPath, } }