/* 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/birpc/context" "github.com/cgrates/cgrates/utils" ) // SessionSCfg is the config section for SessionS type SessionSCfg struct { Enabled bool ListenBijson string ListenBigob string ChargerSConns []string ResourceSConns []string ThresholdSConns []string StatSConns []string RouteSConns []string AttributeSConns []string CDRsConns []string ReplicationConns []string RateSConns []string AccountSConns []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 TerminateAttempts int AlterableFields utils.StringSet MinDurLowBalance time.Duration ActionSConns []string STIRCfg *STIRcfg DefaultUsage map[string]time.Duration } // loadSessionSCfg loads the SessionS section of the configuration func (scfg *SessionSCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) { jsnSessionSCfg := new(SessionSJsonCfg) if err = jsnCfg.GetSection(ctx, SessionSJSON, jsnSessionSCfg); err != nil { return } return scfg.loadFromJSONCfg(jsnSessionSCfg) } 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 = updateInternalConns(*jsnCfg.Chargers_conns, utils.MetaChargers) } if jsnCfg.Resources_conns != nil { scfg.ResourceSConns = updateInternalConns(*jsnCfg.Resources_conns, utils.MetaResources) } if jsnCfg.Thresholds_conns != nil { scfg.ThresholdSConns = updateInternalConns(*jsnCfg.Thresholds_conns, utils.MetaThresholds) } if jsnCfg.Stats_conns != nil { scfg.StatSConns = updateInternalConns(*jsnCfg.Stats_conns, utils.MetaStats) } if jsnCfg.Routes_conns != nil { scfg.RouteSConns = updateInternalConns(*jsnCfg.Routes_conns, utils.MetaRoutes) } if jsnCfg.Attributes_conns != nil { scfg.AttributeSConns = updateInternalConns(*jsnCfg.Attributes_conns, utils.MetaAttributes) } if jsnCfg.Cdrs_conns != nil { scfg.CDRsConns = updateInternalConns(*jsnCfg.Cdrs_conns, utils.MetaCDRs) } if jsnCfg.Actions_conns != nil { scfg.ActionSConns = updateInternalConns(*jsnCfg.Actions_conns, utils.MetaActions) } 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.Rates_conns != nil { scfg.RateSConns = updateInternalConns(*jsnCfg.Rates_conns, utils.MetaRateS) } if jsnCfg.Accounts_conns != nil { scfg.AccountSConns = updateInternalConns(*jsnCfg.Accounts_conns, utils.MetaAccounts) } 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.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 } } } 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]interface{} func (scfg SessionSCfg) AsMapInterface(string) interface{} { 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)) } } mp := map[string]interface{}{ 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.DebitIntervalCfg: "0", utils.SessionTTLCfg: "0", utils.DefaultUsageCfg: maxComputed, } if scfg.DebitInterval != 0 { mp[utils.DebitIntervalCfg] = scfg.DebitInterval.String() } if scfg.SessionTTL != 0 { mp[utils.SessionTTLCfg] = scfg.SessionTTL.String() } if scfg.SessionTTLMaxDelay != nil { mp[utils.SessionTTLMaxDelayCfg] = scfg.SessionTTLMaxDelay.String() } if scfg.SessionTTLLastUsed != nil { mp[utils.SessionTTLLastUsedCfg] = scfg.SessionTTLLastUsed.String() } if scfg.SessionTTLUsage != nil { mp[utils.SessionTTLUsageCfg] = scfg.SessionTTLUsage.String() } if scfg.SessionTTLLastUsage != nil { mp[utils.SessionTTLLastUsageCfg] = scfg.SessionTTLLastUsage.String() } if scfg.ChannelSyncInterval != 0 { mp[utils.ChannelSyncIntervalCfg] = scfg.ChannelSyncInterval.String() } if scfg.MinDurLowBalance != 0 { mp[utils.MinDurLowBalanceCfg] = scfg.MinDurLowBalance.String() } if scfg.ChargerSConns != nil { mp[utils.ChargerSConnsCfg] = getInternalJSONConns(scfg.ChargerSConns) } if scfg.ResourceSConns != nil { mp[utils.ResourceSConnsCfg] = getInternalJSONConns(scfg.ResourceSConns) } if scfg.ThresholdSConns != nil { mp[utils.ThresholdSConnsCfg] = getInternalJSONConns(scfg.ThresholdSConns) } if scfg.StatSConns != nil { mp[utils.StatSConnsCfg] = getInternalJSONConns(scfg.StatSConns) } if scfg.RouteSConns != nil { mp[utils.RouteSConnsCfg] = getInternalJSONConns(scfg.RouteSConns) } if scfg.AttributeSConns != nil { mp[utils.AttributeSConnsCfg] = getInternalJSONConns(scfg.AttributeSConns) } if scfg.CDRsConns != nil { mp[utils.CDRsConnsCfg] = getInternalJSONConns(scfg.CDRsConns) } if scfg.ActionSConns != nil { mp[utils.ActionSConnsCfg] = getInternalJSONConns(scfg.ActionSConns) } if scfg.RateSConns != nil { mp[utils.RateSConnsCfg] = getInternalJSONConns(scfg.RateSConns) } if scfg.AccountSConns != nil { mp[utils.AccountSConnsCfg] = getInternalJSONConns(scfg.AccountSConns) } return mp } func (SessionSCfg) SName() string { return SessionSJSON } func (scfg SessionSCfg) CloneSection() Section { return scfg.Clone() } // 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, ClientProtocol: scfg.ClientProtocol, ChannelSyncInterval: scfg.ChannelSyncInterval, 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 = utils.DurationPointer(*scfg.SessionTTLMaxDelay) } if scfg.SessionTTLLastUsed != nil { cln.SessionTTLLastUsed = utils.DurationPointer(*scfg.SessionTTLLastUsed) } if scfg.SessionTTLUsage != nil { cln.SessionTTLUsage = utils.DurationPointer(*scfg.SessionTTLUsage) } if scfg.SessionTTLLastUsage != nil { cln.SessionTTLLastUsage = utils.DurationPointer(*scfg.SessionTTLLastUsage) } if scfg.ChargerSConns != nil { cln.ChargerSConns = utils.CloneStringSlice(scfg.ChargerSConns) } if scfg.ResourceSConns != nil { cln.ResourceSConns = utils.CloneStringSlice(scfg.ResourceSConns) } if scfg.ThresholdSConns != nil { cln.ThresholdSConns = utils.CloneStringSlice(scfg.ThresholdSConns) } if scfg.StatSConns != nil { cln.StatSConns = utils.CloneStringSlice(scfg.StatSConns) } if scfg.RouteSConns != nil { cln.RouteSConns = utils.CloneStringSlice(scfg.RouteSConns) } if scfg.AttributeSConns != nil { cln.AttributeSConns = utils.CloneStringSlice(scfg.AttributeSConns) } if scfg.CDRsConns != nil { cln.CDRsConns = utils.CloneStringSlice(scfg.CDRsConns) } if scfg.ReplicationConns != nil { cln.ReplicationConns = utils.CloneStringSlice(scfg.ReplicationConns) } if scfg.ActionSConns != nil { cln.ActionSConns = utils.CloneStringSlice(scfg.ActionSConns) } if scfg.RateSConns != nil { cln.RateSConns = utils.CloneStringSlice(scfg.RateSConns) } if scfg.AccountSConns != nil { cln.AccountSConns = utils.CloneStringSlice(scfg.AccountSConns) } 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]interface{} func (stirCfg *STIRcfg) AsMapInterface() (initialMP map[string]interface{}) { initialMP = map[string]interface{}{ 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, } } type STIRJsonCfg struct { Allowed_attest *[]string Payload_maxduration *string Default_attest *string Publickey_path *string Privatekey_path *string } func diffSTIRJsonCfg(d *STIRJsonCfg, v1, v2 *STIRcfg) *STIRJsonCfg { if d == nil { d = new(STIRJsonCfg) } if v1.AllowedAttest.Equals(v2.AllowedAttest) { d.Allowed_attest = nil if v2.AllowedAttest != nil { d.Allowed_attest = utils.SliceStringPointer(v2.AllowedAttest.AsSlice()) } } if v1.PayloadMaxduration != v2.PayloadMaxduration { d.Payload_maxduration = utils.StringPointer(v2.PayloadMaxduration.String()) } if v1.DefaultAttest != v2.DefaultAttest { d.Default_attest = utils.StringPointer(v2.DefaultAttest) } if v1.PublicKeyPath != v2.PublicKeyPath { d.Publickey_path = utils.StringPointer(v2.PublicKeyPath) } if v1.PrivateKeyPath != v2.PrivateKeyPath { d.Privatekey_path = utils.StringPointer(v2.PrivateKeyPath) } return d } // SessionSJsonCfg config section type SessionSJsonCfg struct { Enabled *bool Listen_bijson *string Listen_bigob *string Chargers_conns *[]string Resources_conns *[]string Thresholds_conns *[]string Stats_conns *[]string Routes_conns *[]string Cdrs_conns *[]string Replication_conns *[]string Attributes_conns *[]string Actions_conns *[]string Rates_conns *[]string Accounts_conns *[]string Debit_interval *string Store_session_costs *bool Session_ttl *string Session_ttl_max_delay *string Session_ttl_last_used *string Session_ttl_usage *string Session_ttl_last_usage *string Session_indexes *[]string Client_protocol *float64 Channel_sync_interval *string Terminate_attempts *int Alterable_fields *[]string Min_dur_low_balance *string Stir *STIRJsonCfg Default_usage map[string]string } func diffSessionSJsonCfg(d *SessionSJsonCfg, v1, v2 *SessionSCfg) *SessionSJsonCfg { if d == nil { d = new(SessionSJsonCfg) } if v1.Enabled != v2.Enabled { d.Enabled = utils.BoolPointer(v2.Enabled) } if v1.ListenBijson != v2.ListenBijson { d.Listen_bijson = utils.StringPointer(v2.ListenBijson) } if v1.ListenBigob != v2.ListenBigob { d.Listen_bigob = utils.StringPointer(v2.ListenBigob) } if !utils.SliceStringEqual(v1.ChargerSConns, v2.ChargerSConns) { d.Chargers_conns = utils.SliceStringPointer(getInternalJSONConns(v2.ChargerSConns)) } if !utils.SliceStringEqual(v1.ResourceSConns, v2.ResourceSConns) { d.Resources_conns = utils.SliceStringPointer(getInternalJSONConns(v2.ResourceSConns)) } if !utils.SliceStringEqual(v1.ThresholdSConns, v2.ThresholdSConns) { d.Thresholds_conns = utils.SliceStringPointer(getInternalJSONConns(v2.ThresholdSConns)) } if !utils.SliceStringEqual(v1.StatSConns, v2.StatSConns) { d.Stats_conns = utils.SliceStringPointer(getInternalJSONConns(v2.StatSConns)) } if !utils.SliceStringEqual(v1.RouteSConns, v2.RouteSConns) { d.Routes_conns = utils.SliceStringPointer(getInternalJSONConns(v2.RouteSConns)) } if !utils.SliceStringEqual(v1.AttributeSConns, v2.AttributeSConns) { d.Cdrs_conns = utils.SliceStringPointer(getInternalJSONConns(v2.AttributeSConns)) } if !utils.SliceStringEqual(v1.CDRsConns, v2.CDRsConns) { d.Replication_conns = utils.SliceStringPointer(getInternalJSONConns(v2.CDRsConns)) } if !utils.SliceStringEqual(v1.ReplicationConns, v2.ReplicationConns) { d.Attributes_conns = utils.SliceStringPointer(v2.ReplicationConns) } if !utils.SliceStringEqual(v1.RateSConns, v2.RateSConns) { d.Rates_conns = utils.SliceStringPointer(getInternalJSONConns(v2.RateSConns)) } if !utils.SliceStringEqual(v1.AccountSConns, v2.AccountSConns) { d.Accounts_conns = utils.SliceStringPointer(getInternalJSONConns(v2.AccountSConns)) } if v1.DebitInterval != v2.DebitInterval { d.Debit_interval = utils.StringPointer(v2.DebitInterval.String()) } if v1.StoreSCosts != v2.StoreSCosts { d.Store_session_costs = utils.BoolPointer(v2.StoreSCosts) } if v1.SessionTTL != v2.SessionTTL { d.Session_ttl = utils.StringPointer(v2.SessionTTL.String()) } if v2.SessionTTLMaxDelay != nil { if v1.SessionTTLMaxDelay == nil || *v1.SessionTTLMaxDelay != *v2.SessionTTLMaxDelay { d.Session_ttl_max_delay = utils.StringPointer(v2.SessionTTLMaxDelay.String()) } } else { d.Session_ttl_max_delay = nil } if v2.SessionTTLLastUsed != nil { if v1.SessionTTLLastUsed == nil || *v1.SessionTTLLastUsed != *v2.SessionTTLLastUsed { d.Session_ttl_last_used = utils.StringPointer(v2.SessionTTLLastUsed.String()) } } else { d.Session_ttl_last_used = nil } if v2.SessionTTLUsage != nil { if v1.SessionTTLUsage == nil || *v1.SessionTTLUsage != *v2.SessionTTLUsage { d.Session_ttl_usage = utils.StringPointer(v2.SessionTTLUsage.String()) } } else { d.Session_ttl_usage = nil } if v2.SessionTTLLastUsage != nil { if v1.SessionTTLLastUsage == nil || *v1.SessionTTLLastUsage != *v2.SessionTTLLastUsage { d.Session_ttl_last_usage = utils.StringPointer(v2.SessionTTLLastUsage.String()) } } else { d.Session_ttl_last_usage = nil } if !v1.SessionIndexes.Equals(v2.SessionIndexes) { d.Session_indexes = utils.SliceStringPointer(v2.SessionIndexes.AsSlice()) } if v1.ClientProtocol != v2.ClientProtocol { d.Client_protocol = utils.Float64Pointer(v2.ClientProtocol) } if v1.ChannelSyncInterval != v2.ChannelSyncInterval { d.Channel_sync_interval = utils.StringPointer(v2.ChannelSyncInterval.String()) } if v1.TerminateAttempts != v2.TerminateAttempts { d.Terminate_attempts = utils.IntPointer(v2.TerminateAttempts) } if !v1.AlterableFields.Equals(v2.AlterableFields) { d.Alterable_fields = utils.SliceStringPointer(v2.AlterableFields.AsSlice()) } if v1.MinDurLowBalance != v2.MinDurLowBalance { d.Min_dur_low_balance = utils.StringPointer(v2.MinDurLowBalance.String()) } if !utils.SliceStringEqual(v1.ActionSConns, v2.ActionSConns) { d.Actions_conns = utils.SliceStringPointer(getInternalJSONConns(v2.ActionSConns)) } d.Stir = diffSTIRJsonCfg(d.Stir, v1.STIRCfg, v2.STIRCfg) if d.Default_usage == nil { d.Default_usage = make(map[string]string) } for tor, usage2 := range v2.DefaultUsage { if usage1, has := v1.DefaultUsage[tor]; !has || usage1 != usage2 { d.Default_usage[tor] = usage2.String() } } return d }