mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
FreeSWITCH cgr_computelcr channel variable processing, fix logging of callcosts from session manager, improved tutorial_fs testing
This commit is contained in:
@@ -7,65 +7,9 @@
|
||||
// This is what you get when you load CGRateS with an empty configuration file.
|
||||
|
||||
|
||||
//"general": {
|
||||
// "http_skip_tls_veify": false, // if enabled Http Client will accept any TLS certificate
|
||||
// "rounding_decimals": 10, // system level precision for floats
|
||||
// "dbdata_encoding": "msgpack", // encoding used to store object data in strings: <msgpack|json>
|
||||
// "tpexport_dir": "/var/log/cgrates/tpe", // path towards export folder for offline Tariff Plans
|
||||
// "default_reqtype": "*rated", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated>
|
||||
// "default_category": "call", // default Type of Record to consider when missing from requests
|
||||
// "default_tenant": "cgrates.org", // default Tenant to consider when missing from requests
|
||||
// "default_subject": "cgrates", // default rating Subject to consider when missing from requests
|
||||
//},
|
||||
|
||||
|
||||
//"listen": {
|
||||
// "rpc_json": "127.0.0.1:2012", // RPC JSON listening address
|
||||
// "rpc_gob": "127.0.0.1:2013", // RPC GOB listening address
|
||||
// "http": "127.0.0.1:2080", // HTTP listening address
|
||||
//},
|
||||
|
||||
|
||||
//"rating_db": {
|
||||
// "db_type": "redis", // rating subsystem database type: <redis>
|
||||
// "db_host": "127.0.0.1", // rating subsystem database host address
|
||||
// "db_port": 6379, // rating subsystem port to reach the database
|
||||
// "db_name": "10", // rating subsystem database name to connect to
|
||||
// "db_user": "", // rating subsystem username to use when connecting to database
|
||||
// "db_passwd": "", // rating subsystem password to use when connecting to database
|
||||
//},
|
||||
|
||||
|
||||
//"accounting_db": {
|
||||
// "db_type": "redis", // accounting subsystem database: <redis>
|
||||
// "db_host": "127.0.0.1", // accounting subsystem database host address
|
||||
// "db_port": 6379, // accounting subsystem port to reach the database
|
||||
// "db_name": "11", // accounting subsystem database name to connect to
|
||||
// "db_user": "", // accounting subsystem username to use when connecting to database
|
||||
// "db_passwd": "", // accounting subsystem password to use when connecting to database
|
||||
//},
|
||||
|
||||
|
||||
//"stor_db": {
|
||||
// "db_type": "mysql", // stor database type to use: <mysql|postgres>
|
||||
// "db_host": "127.0.0.1", // the host to connect to
|
||||
// "db_port": 3306, // the port to reach the stordb
|
||||
// "db_name": "cgrates", // stor database name
|
||||
// "db_user": "cgrates", // username to use when connecting to stordb
|
||||
// "db_passwd": "CGRateS.org", // password to use when connecting to stordb
|
||||
// "max_open_conns": 0, // maximum database connections opened
|
||||
// "max_idle_conns": -1, // maximum database connections idle
|
||||
//},
|
||||
|
||||
|
||||
//"balancer": {
|
||||
// "enabled": false, // start Balancer service: <true|false>
|
||||
//},
|
||||
|
||||
|
||||
"rater": {
|
||||
"enabled": true, // enable Rater service: <true|false>
|
||||
// "balancer": "", // register to Balancer as worker: <""|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>
|
||||
},
|
||||
|
||||
|
||||
@@ -76,36 +20,12 @@
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true, // start the CDR Server service: <true|false>
|
||||
// "extra_fields": [], // extra fields to store in CDRs for non-generic CDRs
|
||||
// "rate_cdrs": true, // enable CDR rating calculation
|
||||
// "store_cdrs": true, // store cdrs in storDb
|
||||
"rater": "internal", // address where to reach the Rater for cost calculation: <""|internal|x.y.z.y:1234>
|
||||
"cdrstats": "internal", // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234>
|
||||
// "reconnects": 5, // number of reconnect attempts to rater or cdrs
|
||||
// "cdr_replication":[], // replicate the raw CDR to a number of servers
|
||||
},
|
||||
|
||||
"cdrstats": {
|
||||
"enabled": true, // starts the cdrstats service: <true|false>
|
||||
// "queue_length": 50, // number of items in the stats buffer
|
||||
// "time_window": "1h", // will only keep the CDRs who's call setup time is not older than time.Now()-TimeWindow
|
||||
// "metrics": ["ASR", "ACD", "ACC"], // stat metric ids to build
|
||||
// "setup_interval": [], // filter on CDR SetupTime
|
||||
// "tors": [], // filter on CDR TOR fields
|
||||
// "cdr_hosts": [], // filter on CDR CdrHost fields
|
||||
// "cdr_sources": [], // filter on CDR CdrSource fields
|
||||
// "req_types": [], // filter on CDR ReqType fields
|
||||
// "directions": [], // filter on CDR Direction fields
|
||||
// "tenants": [], // filter on CDR Tenant fields
|
||||
// "categories": [], // filter on CDR Category fields
|
||||
// "accounts": [], // filter on CDR Account fields
|
||||
// "subjects": [], // filter on CDR Subject fields
|
||||
// "destination_prefixes": [], // filter on CDR Destination prefixes
|
||||
// "usage_interval": [], // filter on CDR Usage
|
||||
// "mediation_run_ids": [], // filter on CDR MediationRunId fields
|
||||
// "rated_accounts": [], // filter on CDR RatedAccount fields
|
||||
// "rated_subjects": [], // filter on CDR RatedSubject fields
|
||||
// "cost_interval": [], // filter on CDR Cost
|
||||
},
|
||||
|
||||
|
||||
@@ -145,103 +65,27 @@
|
||||
},
|
||||
|
||||
|
||||
//"cdrc": {
|
||||
// "*default": {
|
||||
// "enabled": false, // enable CDR client functionality
|
||||
// "cdrs_address": "internal", // address where to reach CDR server. <internal|x.y.z.y:1234>
|
||||
// "cdr_format": "csv", // CDR file format <csv|freeswitch_csv|fwv>
|
||||
// "field_separator": ",", // separator used in case of csv files
|
||||
// "run_delay": 0, // sleep interval in seconds between consecutive runs, 0 to use automation via inotify
|
||||
// "data_usage_multiply_factor": 1024, // conversion factor for data usage
|
||||
// "cdr_in_dir": "/var/log/cgrates/cdrc/in", // absolute path towards the directory where the CDRs are stored
|
||||
// "cdr_out_dir": "/var/log/cgrates/cdrc/out", // absolute path towards the directory where processed CDRs will be moved
|
||||
// "cdr_source_id": "freeswitch_csv", // free form field, tag identifying the source of the CDRs within CDRS database
|
||||
// "cdr_filter": "", // Filter CDR records to import
|
||||
// "cdr_fields":[ // import 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": "2", "mandatory": true},
|
||||
// {"tag": "accid", "cdr_field_id": "accid", "type": "cdrfield", "value": "3", "mandatory": true},
|
||||
// {"tag": "reqtype", "cdr_field_id": "reqtype", "type": "cdrfield", "value": "4", "mandatory": true},
|
||||
// {"tag": "direction", "cdr_field_id": "direction", "type": "cdrfield", "value": "5", "mandatory": true},
|
||||
// {"tag": "tenant", "cdr_field_id": "tenant", "type": "cdrfield", "value": "6", "mandatory": true},
|
||||
// {"tag": "category", "cdr_field_id": "category", "type": "cdrfield", "value": "7", "mandatory": true},
|
||||
// {"tag": "account", "cdr_field_id": "account", "type": "cdrfield", "value": "8", "mandatory": true},
|
||||
// {"tag": "subject", "cdr_field_id": "subject", "type": "cdrfield", "value": "9", "mandatory": true},
|
||||
// {"tag": "destination", "cdr_field_id": "destination", "type": "cdrfield", "value": "10", "mandatory": true},
|
||||
// {"tag": "setup_time", "cdr_field_id": "setup_time", "type": "cdrfield", "value": "11", "mandatory": true},
|
||||
// {"tag": "answer_time", "cdr_field_id": "answer_time", "type": "cdrfield", "value": "12", "mandatory": true},
|
||||
// {"tag": "usage", "cdr_field_id": "usage", "type": "cdrfield", "value": "13", "mandatory": true},
|
||||
// ],
|
||||
// }
|
||||
//},
|
||||
|
||||
|
||||
"sm_freeswitch": {
|
||||
"enabled": true, // starts SessionManager service: <true|false>
|
||||
"rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
"cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234>
|
||||
// "reconnects": 5, // number of reconnect attempts to rater or cdrs
|
||||
"create_cdr": true, // create CDR out of events and sends them to CDRS component
|
||||
// "cdr_extra_fields": [], // extra fields to store in CDRs in case of processing them
|
||||
"debit_interval": "5s", // 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
|
||||
// "min_dur_low_balance": "5s", // threshold which will trigger low balance warnings for prepaid calls (needs to be lower than debit_interval)
|
||||
// "low_balance_ann_file": "", // file to be played when low balance is reached for prepaid calls
|
||||
// "empty_balance_context": "", // if defined, prepaid calls will be transfered to this context on empty balance
|
||||
// "empty_balance_ann_file": "", // file to be played before disconnecting prepaid calls on empty balance (applies only if no context defined)
|
||||
"connections":[ // instantiate connections to multiple FreeSWITCH servers
|
||||
{"server": "127.0.0.1:8021", "password": "ClueCon", "reconnects": 15}
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
//"sm_kamailio": {
|
||||
// "enabled": false, // starts SessionManager service: <true|false>
|
||||
// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|internal|x.y.z.y:1234>
|
||||
// "reconnects": 5, // number of reconnect attempts to rater or cdrs
|
||||
// "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
|
||||
// "connections":[ // instantiate connections to multiple Kamailio servers
|
||||
// {"evapi_addr": "127.0.0.1:8448", "reconnects": -1} // reconnects -1 to indefinitely connect
|
||||
// ],
|
||||
//},
|
||||
|
||||
|
||||
//"sm_opensips": {
|
||||
// "enabled": false, // starts SessionManager service: <true|false>
|
||||
// "listen_udp": "127.0.0.1:2020", // address where to listen for datagram events coming from OpenSIPS
|
||||
// "rater": "internal", // address where to reach the Rater <""|internal|127.0.0.1:2013>
|
||||
// "cdrs": "internal", // address where to reach CDR Server, empty to disable CDR capturing <""|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
|
||||
// "max_call_duration": "3h", // maximum call duration a prepaid call can last
|
||||
// "events_subscribe_interval": "60s", // automatic events subscription to OpenSIPS, 0 to disable it
|
||||
// "mi_addr": "127.0.0.1:8020", // address where to reach OpenSIPS MI to send session disconnects
|
||||
// "reconnects": -1, // reconnects -1 to indefinitely connect
|
||||
//},
|
||||
|
||||
|
||||
|
||||
"history_server": {
|
||||
"enabled": true, // starts History service: <true|false>.
|
||||
"history_dir": "/tmp/cgr_fsevsock/cgrates/history", // location on disk where to store history files.
|
||||
// "save_interval": "1s", // interval to save changed cache into .git archive
|
||||
},
|
||||
|
||||
|
||||
"history_agent": {
|
||||
"enabled": true, // starts History as a client: <true|false>.
|
||||
// "server": "internal", // address where to reach the master history server: <internal|x.y.z.y:1234>
|
||||
},
|
||||
|
||||
|
||||
//"mailer": {
|
||||
// "server": "localhost", // the server to use when sending emails out
|
||||
// "auth_user": "cgrates", // authenticate to email server using this user
|
||||
// "auth_passwd": "CGRateS.org", // authenticate to email server with this password
|
||||
// "from_address": "cgr-mailer@localhost.localdomain" // from address used when sending emails out
|
||||
//},
|
||||
|
||||
}
|
||||
|
||||
@@ -108,9 +108,10 @@ type CallCostLog struct {
|
||||
|
||||
// RPC method, used to log callcosts to db
|
||||
func (self *CdrServer) LogCallCost(ccl *CallCostLog) error {
|
||||
Logger.Debug(fmt.Sprintf("LogCallCost, callCostLog: %+v, cost: %+v", ccl, ccl.CallCost))
|
||||
if ccl.CheckDuplicate {
|
||||
cc, err := self.cdrDb.GetCallCostLog(ccl.CgrId, ccl.Source, ccl.RunId)
|
||||
if err != nil {
|
||||
if err != nil && err.Error() != "record not found" {
|
||||
return err
|
||||
}
|
||||
if cc != nil {
|
||||
@@ -245,7 +246,7 @@ func (self *CdrServer) getCostFromRater(storedCdr *StoredCdr) (*CallCost, error)
|
||||
}
|
||||
if utils.IsSliceMember([]string{utils.META_PSEUDOPREPAID, utils.META_POSTPAID, utils.PSEUDOPREPAID, utils.POSTPAID}, storedCdr.ReqType) {
|
||||
if err = self.rater.Debit(cd, cc); err == nil { // Debit has occured, we are forced to write the log, even if CDR store is disabled
|
||||
self.cdrDb.LogCallCost(storedCdr.CgrId, MEDIATOR_SOURCE, storedCdr.MediationRunId, cc)
|
||||
self.cdrDb.LogCallCost(storedCdr.CgrId, utils.CDRS_SOURCE, storedCdr.MediationRunId, cc)
|
||||
}
|
||||
} else {
|
||||
err = self.rater.GetCost(cd, cc)
|
||||
|
||||
@@ -51,4 +51,5 @@ type Event interface {
|
||||
AsStoredCdr() *StoredCdr
|
||||
String() string
|
||||
AsEvent(string) Event
|
||||
ComputeLcr() bool
|
||||
}
|
||||
|
||||
@@ -305,21 +305,36 @@ func (lc *LCRCost) LogErrors() {
|
||||
}
|
||||
}
|
||||
|
||||
func (lc *LCRCost) SuppliersSlice() ([]string, error) {
|
||||
if lc.Entry == nil {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
supps := []string{}
|
||||
for _, supplCost := range lc.SupplierCosts {
|
||||
if dtcs, err := utils.NewDTCSFromRPKey(supplCost.Supplier); err != nil {
|
||||
return nil, err
|
||||
} else if len(dtcs.Subject) != 0 {
|
||||
supps = append(supps, dtcs.Subject)
|
||||
}
|
||||
}
|
||||
if len(supps) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
return supps, nil
|
||||
}
|
||||
|
||||
// Returns a list of suppliers separated via
|
||||
func (lc *LCRCost) SuppliersString() (string, error) {
|
||||
supplStr := ""
|
||||
if lc.Entry == nil {
|
||||
return "", utils.ErrNotFound
|
||||
supps, err := lc.SuppliersSlice()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for idx, supplCost := range lc.SupplierCosts {
|
||||
if dtcs, err := utils.NewDTCSFromRPKey(supplCost.Supplier); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
if idx != 0 {
|
||||
supplStr += utils.FIELDS_SEP
|
||||
}
|
||||
supplStr += dtcs.Subject
|
||||
supplStr := ""
|
||||
for idx, suppl := range supps {
|
||||
if idx != 0 {
|
||||
supplStr += utils.FIELDS_SEP
|
||||
}
|
||||
supplStr += suppl
|
||||
}
|
||||
return supplStr, nil
|
||||
}
|
||||
|
||||
@@ -234,6 +234,27 @@ func TestLcrRequestAsCallDescriptor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLCRCostSuppliersSlice(t *testing.T) {
|
||||
lcrCost := new(LCRCost)
|
||||
if _, err := lcrCost.SuppliersString(); err == nil || err != utils.ErrNotFound {
|
||||
t.Errorf("Unexpected error received: %v", err)
|
||||
}
|
||||
lcrCost = &LCRCost{
|
||||
Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_STATIC, StrategyParams: "ivo12;dan12;rif12", Weight: 10.0},
|
||||
SupplierCosts: []*LCRSupplierCost{
|
||||
&LCRSupplierCost{Supplier: "*out:tenant12:call:ivo12", Cost: 1.8, Duration: 60 * time.Second},
|
||||
&LCRSupplierCost{Supplier: "*out:tenant12:call:dan12", Cost: 0.6, Duration: 60 * time.Second},
|
||||
&LCRSupplierCost{Supplier: "*out:tenant12:call:rif12", Cost: 1.2, Duration: 60 * time.Second},
|
||||
},
|
||||
}
|
||||
eSuppls := []string{"ivo12", "dan12", "rif12"}
|
||||
if suppls, err := lcrCost.SuppliersSlice(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eSuppls, suppls) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eSuppls, suppls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLCRCostSuppliersString(t *testing.T) {
|
||||
lcrCost := new(LCRCost)
|
||||
if _, err := lcrCost.SuppliersString(); err == nil || err != utils.ErrNotFound {
|
||||
|
||||
@@ -418,6 +418,9 @@ func (storedCdr *StoredCdr) AsExternalCdr() *ExternalCdr {
|
||||
func (storedCdr *StoredCdr) AsEvent(ignored string) Event {
|
||||
return Event(storedCdr)
|
||||
}
|
||||
func (storedCdr *StoredCdr) ComputeLcr() bool {
|
||||
return false
|
||||
}
|
||||
func (storedCdr *StoredCdr) GetName() string {
|
||||
return storedCdr.CdrSource
|
||||
}
|
||||
|
||||
@@ -291,6 +291,9 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
@@ -380,6 +383,9 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Usage != "64" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
@@ -399,6 +405,9 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Usage != "66" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ const (
|
||||
IGNOREPARK = "variable_cgr_ignorepark"
|
||||
|
||||
VAR_CGR_DISCONNECT_CAUSE = "variable_" + utils.CGR_DISCONNECT_CAUSE
|
||||
VAR_CGR_CMPUTELCR = "variable_" + utils.CGR_COMPUTELCR
|
||||
)
|
||||
|
||||
// Nice printing for the event object.
|
||||
@@ -362,7 +363,30 @@ func (fsev FSEvent) AsStoredCdr() *engine.StoredCdr {
|
||||
return storCdr
|
||||
}
|
||||
|
||||
// Converts a slice of strings into a FS array string
|
||||
func (fsev FSEvent) ComputeLcr() bool {
|
||||
if computeLcr, err := strconv.ParseBool(fsev[VAR_CGR_CMPUTELCR]); err != nil {
|
||||
return false
|
||||
} else {
|
||||
return computeLcr
|
||||
}
|
||||
}
|
||||
|
||||
// Converts into CallDescriptor due to responder interface needs
|
||||
func (fsev FSEvent) AsCallDescriptor() (*engine.CallDescriptor, error) {
|
||||
lcrReq := &engine.LcrRequest{
|
||||
Direction: fsev.GetDirection(utils.META_DEFAULT),
|
||||
Tenant: fsev.GetTenant(utils.META_DEFAULT),
|
||||
Category: fsev.GetCategory(utils.META_DEFAULT),
|
||||
Account: fsev.GetAccount(utils.META_DEFAULT),
|
||||
Subject: fsev.GetSubject(utils.META_DEFAULT),
|
||||
Destination: fsev.GetDestination(utils.META_DEFAULT),
|
||||
StartTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]),
|
||||
Duration: fsev[DURATION],
|
||||
}
|
||||
return lcrReq.AsCallDescriptor()
|
||||
}
|
||||
|
||||
// Converts a slice of strings into a FS array string, contains len(array) at first index since FS does not support len(ARRAY::) for now
|
||||
func SliceAsFsArray(slc []string) string {
|
||||
arry := ""
|
||||
if len(slc) == 0 {
|
||||
@@ -370,7 +394,7 @@ func SliceAsFsArray(slc []string) string {
|
||||
}
|
||||
for idx, itm := range slc {
|
||||
if idx == 0 {
|
||||
arry += "ARRAY::" + itm
|
||||
arry = fmt.Sprintf("ARRAY::%d|:%s", len(slc), itm)
|
||||
} else {
|
||||
arry += "|:" + itm
|
||||
}
|
||||
|
||||
@@ -665,7 +665,7 @@ func TestSliceAsFsArray(t *testing.T) {
|
||||
t.Error(fsArray)
|
||||
}
|
||||
items = []string{"item1", "item2", "item3"}
|
||||
if fsArray := SliceAsFsArray(items); fsArray != "ARRAY::item1|:item2|:item3" {
|
||||
if fsArray := SliceAsFsArray(items); fsArray != "ARRAY::3|:item1|:item2|:item3" {
|
||||
t.Error(fsArray)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,15 +207,36 @@ func (sm *FSSessionManager) onChannelPark(ev engine.Event, connId string) {
|
||||
return
|
||||
}
|
||||
sm.setMaxCallDuration(ev.GetUUID(), connId, maxCallDur)
|
||||
|
||||
/*if sm.cfg.ComputeLcr { // Fix here out of channel variable
|
||||
if err := sm.setCgrLcr(ev, connId); err != nil {
|
||||
engine.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Could not set LCR for %s, error: %s", ev.GetUUID(), err.Error()))
|
||||
// ComputeLcr
|
||||
if ev.ComputeLcr() {
|
||||
cd, err := fsev.AsCallDescriptor()
|
||||
if err != nil {
|
||||
engine.Logger.Info(fmt.Sprintf("<SM-FreeSWITCH> LCR_PREPROCESS_ERROR: %s", err.Error()))
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR)
|
||||
return
|
||||
}
|
||||
var lcr engine.LCRCost
|
||||
if err = sm.Rater().GetLCR(cd, &lcr); err != nil {
|
||||
engine.Logger.Info(fmt.Sprintf("<SM-FreeSWITCH> LCR_API_ERROR: %s", err.Error()))
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR)
|
||||
}
|
||||
if lcr.HasErrors() {
|
||||
lcr.LogErrors()
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR)
|
||||
return
|
||||
}
|
||||
if supps, err := lcr.SuppliersSlice(); err != nil {
|
||||
engine.Logger.Info(fmt.Sprintf("<SM-FreeSWITCH> LCR_ERROR: %s", err.Error()))
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR)
|
||||
return
|
||||
} else {
|
||||
fsArray := SliceAsFsArray(supps)
|
||||
if _, err = sm.conns[connId].SendApiCmd(fmt.Sprintf("uuid_setvar %s %s %s\n\n", ev.GetUUID(), utils.CGR_SUPPLIERS, fsArray)); err != nil {
|
||||
engine.Logger.Info(fmt.Sprintf("<SM-FreeSWITCH> LCR_ERROR: %s", err.Error()))
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), AUTH_OK)
|
||||
}
|
||||
|
||||
|
||||
@@ -228,11 +228,6 @@ func (kev KamEvent) GetCdrSource() string {
|
||||
return "KAMAILIO_" + kev.GetName()
|
||||
}
|
||||
|
||||
func (kev KamEvent) ComputeLcr() bool {
|
||||
compute, _ := strconv.ParseBool(kev[utils.CGR_COMPUTELCR])
|
||||
return compute
|
||||
}
|
||||
|
||||
func (kev KamEvent) MissingParameter() bool {
|
||||
var nullTime time.Time
|
||||
switch kev.GetName() {
|
||||
@@ -391,3 +386,11 @@ func (kev KamEvent) AsCallDescriptor() (*engine.CallDescriptor, error) {
|
||||
}
|
||||
return lcrReq.AsCallDescriptor()
|
||||
}
|
||||
|
||||
func (kev KamEvent) ComputeLcr() bool {
|
||||
if computeLcr, err := strconv.ParseBool(kev[utils.CGR_COMPUTELCR]); err != nil {
|
||||
return false
|
||||
} else {
|
||||
return computeLcr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package sessionmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -298,3 +299,11 @@ func (osipsEv *OsipsEvent) updateDurationFromEvent(updatedOsipsEv *OsipsEvent) e
|
||||
osipsEv.osipsEvent.AttrValues[OSIPS_SIPCODE] = updatedOsipsEv.osipsEvent.AttrValues[OSIPS_SIPCODE]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (osipsEv *OsipsEvent) ComputeLcr() bool {
|
||||
if computeLcr, err := strconv.ParseBool(osipsEv.osipsEvent.AttrValues[utils.CGR_COMPUTELCR]); err != nil {
|
||||
return false
|
||||
} else {
|
||||
return computeLcr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,6 @@ const (
|
||||
LOG_CDR = "cdr_"
|
||||
LOG_MEDIATED_CDR = "mcd_"
|
||||
SESSION_MANAGER_SOURCE = "SMR"
|
||||
MEDIATOR_SOURCE = "MED"
|
||||
CDRS_SOURCE = "CDRS"
|
||||
SCHED_SOURCE = "SCH"
|
||||
RATER_SOURCE = "RAT"
|
||||
@@ -189,6 +188,7 @@ const (
|
||||
CGR_AUTHORIZE = "CGR_AUTHORIZE"
|
||||
CONFIG_DIR = "/etc/cgrates/"
|
||||
CGR_SUPPLIER = "cgr_supplier"
|
||||
CGR_SUPPLIERS = "cgr_suppliers"
|
||||
DISCONNECT_CAUSE = "disconnect_cause"
|
||||
CGR_DISCONNECT_CAUSE = "cgr_disconnectcause"
|
||||
CGR_COMPUTELCR = "cgr_computelcr"
|
||||
|
||||
Reference in New Issue
Block a user