func (fsev FSEvent) GetExtraFields() map[string]string { extraFields := make(map[string]string) for _, fldRule := range config.CgrConfig().SmFsConfig.ExtraFields { extraFields[fldRule.Id] = fsev.ParseEventValue(fldRule, config.CgrConfig().DefaultTimezone) } return extraFields }
func (kev KamEvent) MissingParameter() bool { var nullTime time.Time switch kev.GetName() { case CGR_AUTH_REQUEST: if setupTime, err := kev.GetSetupTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone); err != nil || setupTime == nullTime { return true } return len(kev.GetAccount(utils.META_DEFAULT)) == 0 || len(kev.GetDestination(utils.META_DEFAULT)) == 0 || len(kev[KAM_TR_INDEX]) == 0 || len(kev[KAM_TR_LABEL]) == 0 case CGR_LCR_REQUEST: return len(kev.GetAccount(utils.META_DEFAULT)) == 0 || len(kev.GetDestination(utils.META_DEFAULT)) == 0 || len(kev[KAM_TR_INDEX]) == 0 || len(kev[KAM_TR_LABEL]) == 0 case CGR_CALL_START: if aTime, err := kev.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone); err != nil || aTime == nullTime { return true } return len(kev.GetUUID()) == 0 || len(kev.GetAccount(utils.META_DEFAULT)) == 0 || len(kev.GetDestination(utils.META_DEFAULT)) == 0 || len(kev[HASH_ENTRY]) == 0 || len(kev[HASH_ID]) == 0 case CGR_CALL_END: return len(kev.GetUUID()) == 0 || len(kev.GetAccount(utils.META_DEFAULT)) == 0 || len(kev.GetDestination(utils.META_DEFAULT)) == 0 || len(kev[CGR_DURATION]) == 0 default: return true } }
func (osipsev *OsipsEvent) MissingParameter() bool { var nilTime time.Time if osipsev.GetName() == "E_ACC_EVENT" && osipsev.osipsEvent.AttrValues["method"] == "INVITE" { return len(osipsev.GetUUID()) == 0 || len(osipsev.GetAccount(utils.META_DEFAULT)) == 0 || len(osipsev.GetDestination(utils.META_DEFAULT)) == 0 || len(osipsev.osipsEvent.AttrValues[OSIPS_DIALOG_ID]) == 0 } else if osipsev.GetName() == "E_ACC_EVENT" && osipsev.osipsEvent.AttrValues["method"] == "BYE" { return len(osipsev.osipsEvent.AttrValues[OSIPS_DIALOG_ID]) == 0 || len(osipsev.osipsEvent.AttrValues[TIME]) == 0 } else if osipsev.GetName() == "E_ACC_EVENT" && osipsev.osipsEvent.AttrValues["method"] == "UPDATE" { // Updated event out of start/stop // Data needed when stopping a prepaid loop or building a CDR with start/stop event setupTime, err := osipsev.GetSetupTime(TIME, config.CgrConfig().DefaultTimezone) if err != nil || setupTime.Equal(nilTime) { return true } aTime, err := osipsev.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) if err != nil || aTime.Equal(nilTime) { return true } endTime, err := osipsev.GetEndTime() if err != nil || endTime.Equal(nilTime) { return true } _, err = osipsev.GetDuration(utils.META_DEFAULT) if err != nil { return true } if osipsev.osipsEvent.AttrValues[OSIPS_DIALOG_ID] == "" { return true } return false } return true }
func (fsev FSEvent) GetReqType(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } else if fieldName == utils.META_DEFAULT { return utils.FirstNonEmpty(fsev[REQTYPE], config.CgrConfig().DefaultReqType) } return utils.FirstNonEmpty(fsev[fieldName], fsev[REQTYPE], config.CgrConfig().DefaultReqType) }
func SureTaxProcessCdr(cdr *CDR) error { stCfg := config.CgrConfig().SureTaxCfg() if stCfg == nil { return errors.New("Invalid SureTax configuration") } if sureTaxClient == nil { // First time used, init the client here tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: config.CgrConfig().HttpSkipTlsVerify}, } sureTaxClient = &http.Client{Transport: tr} } req, err := NewSureTaxRequest(cdr, stCfg) if err != nil { return err } jsnContent, err := json.Marshal(req) if err != nil { return err } resp, err := sureTaxClient.Post(stCfg.Url, "application/json", bytes.NewBuffer(jsnContent)) if err != nil { return err } defer resp.Body.Close() respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode > 299 { return fmt.Errorf("Unexpected status code received: %d", resp.StatusCode) } var respFull SureTaxResponse if err := json.Unmarshal(respBody, &respFull); err != nil { return err } var stResp STResponse if err := json.Unmarshal([]byte(respFull.D), &stResp); err != nil { return err } if stResp.ResponseCode != "9999" { cdr.ExtraInfo = stResp.HeaderMessage return nil // No error because the request was processed by SureTax, error will be in the ExtraInfo } // Write cost to CDR totalTax, err := strconv.ParseFloat(stResp.TotalTax, 64) if err != nil { cdr.ExtraInfo = err.Error() } if !stCfg.IncludeLocalCost { cdr.Cost = utils.Round(totalTax, config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE) } else { cdr.Cost = utils.Round(cdr.Cost+totalTax, config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE) } // Add response into extra fields to be available for later review cdr.ExtraFields[utils.META_SURETAX] = respFull.D return nil }
// Computes duration out of setup time of the callEnd func (osipsEv *OsipsEvent) updateDurationFromEvent(updatedOsipsEv *OsipsEvent) error { endTime, err := updatedOsipsEv.GetSetupTime(TIME, config.CgrConfig().DefaultTimezone) if err != nil { return err } answerTime, err := osipsEv.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) osipsEv.osipsEvent.AttrValues[OSIPS_DURATION] = endTime.Sub(answerTime).String() osipsEv.osipsEvent.AttrValues["method"] = "UPDATE" // So we can know it is an end event osipsEv.osipsEvent.AttrValues[OSIPS_SIPCODE] = updatedOsipsEv.osipsEvent.AttrValues[OSIPS_SIPCODE] return nil }
func SureTaxProcessCdr(cdr *StoredCdr) error { stCfg := config.CgrConfig().SureTaxCfg() if stCfg == nil { return errors.New("Invalid SureTax configuration") } if sureTaxClient == nil { // First time used, init the client here tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: config.CgrConfig().HttpSkipTlsVerify}, } sureTaxClient = &http.Client{Transport: tr} } req, err := NewSureTaxRequest(cdr, stCfg) if err != nil { return err } body, err := json.Marshal(req) if err != nil { return err } utils.Logger.Debug(fmt.Sprintf("###SureTax NewSureTaxRequest: %+v, ItemList: %+v\n", req, req.ItemList[0])) resp, err := sureTaxClient.Post(stCfg.Url, "application/json", bytes.NewBuffer(body)) if err != nil { return err } defer resp.Body.Close() respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode > 299 { return fmt.Errorf("Unexpected status code received: %d", resp.StatusCode) } var stResp SureTaxResponse if err := json.Unmarshal(respBody, &stResp); err != nil { return err } utils.Logger.Debug(fmt.Sprintf("###SureTax received response: %+v\n", stResp)) if stResp.ResponseCode != 9999 { cdr.ExtraInfo = stResp.HeaderMessage return nil // No error because the request was processed by SureTax, error will be in the ExtraInfo } // Write cost to CDR if !stCfg.IncludeLocalCost { cdr.Cost = utils.Round(stResp.TotalTax, config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE) } else { cdr.Cost = utils.Round(cdr.Cost+stResp.TotalTax, config.CgrConfig().RoundingDecimals, utils.ROUNDING_MIDDLE) } // Add response into extra fields to be available for later review cdr.ExtraFields[utils.META_SURETAX] = string(respBody) return nil }
// Useful for CDR generation func (kev KamEvent) ParseEventValue(rsrFld *utils.RSRField, timezone string) string { sTime, _ := kev.GetSetupTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) aTime, _ := kev.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) duration, _ := kev.GetDuration(utils.META_DEFAULT) switch rsrFld.Id { case utils.CGRID: return rsrFld.ParseValue(kev.GetCgrId(timezone)) case utils.TOR: return rsrFld.ParseValue(utils.VOICE) case utils.ACCID: return rsrFld.ParseValue(kev.GetUUID()) case utils.CDRHOST: return rsrFld.ParseValue(kev.GetOriginatorIP(utils.META_DEFAULT)) case utils.CDRSOURCE: return rsrFld.ParseValue(kev.GetCdrSource()) case utils.REQTYPE: return rsrFld.ParseValue(kev.GetReqType(utils.META_DEFAULT)) case utils.DIRECTION: return rsrFld.ParseValue(kev.GetDirection(utils.META_DEFAULT)) case utils.TENANT: return rsrFld.ParseValue(kev.GetTenant(utils.META_DEFAULT)) case utils.CATEGORY: return rsrFld.ParseValue(kev.GetCategory(utils.META_DEFAULT)) case utils.ACCOUNT: return rsrFld.ParseValue(kev.GetAccount(utils.META_DEFAULT)) case utils.SUBJECT: return rsrFld.ParseValue(kev.GetSubject(utils.META_DEFAULT)) case utils.DESTINATION: return rsrFld.ParseValue(kev.GetDestination(utils.META_DEFAULT)) case utils.SETUP_TIME: return rsrFld.ParseValue(sTime.String()) case utils.ANSWER_TIME: return rsrFld.ParseValue(aTime.String()) case utils.USAGE: return rsrFld.ParseValue(strconv.FormatFloat(utils.Round(duration.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)) case utils.PDD: return rsrFld.ParseValue(strconv.FormatFloat(utils.Round(duration.Seconds(), 0, utils.ROUNDING_MIDDLE), 'f', -1, 64)) case utils.SUPPLIER: return rsrFld.ParseValue(kev.GetSupplier(utils.META_DEFAULT)) case utils.DISCONNECT_CAUSE: return rsrFld.ParseValue(kev.GetDisconnectCause(utils.META_DEFAULT)) case utils.MEDI_RUNID: return rsrFld.ParseValue(utils.META_DEFAULT) case utils.COST: return rsrFld.ParseValue("-1.0") default: return rsrFld.ParseValue(kev.GetExtraFields()[rsrFld.Id]) } }
func (self *LcrRequest) AsCallDescriptor(timezone string) (*CallDescriptor, error) { if len(self.Account) == 0 || len(self.Destination) == 0 { return nil, utils.ErrMandatoryIeMissing } // Set defaults if len(self.Direction) == 0 { self.Direction = utils.OUT } if len(self.Tenant) == 0 { self.Tenant = config.CgrConfig().DefaultTenant } if len(self.Category) == 0 { self.Category = config.CgrConfig().DefaultCategory } if len(self.Subject) == 0 { self.Subject = self.Account } var timeStart time.Time var err error if len(self.SetupTime) == 0 { timeStart = time.Now() } else if timeStart, err = utils.ParseTimeDetectLayout(self.SetupTime, timezone); err != nil { return nil, err } var callDur time.Duration if len(self.Duration) == 0 { callDur = time.Duration(1) * time.Minute } else if callDur, err = utils.ParseDurationWithSecs(self.Duration); err != nil { return nil, err } cd := &CallDescriptor{ Direction: self.Direction, Tenant: self.Tenant, Category: self.Category, Account: self.Account, Subject: self.Subject, Destination: self.Destination, TimeStart: timeStart, TimeEnd: timeStart.Add(callDur), } if self.ExtraFields != nil { cd.ExtraFields = make(map[string]string) } for key, val := range self.ExtraFields { cd.ExtraFields[key] = val } return cd, nil }
func (sm *FSSessionManager) onChannelHangupComplete(ev engine.Event) { if ev.GetReqType(utils.META_DEFAULT) == utils.META_NONE { // Do not process this request return } var s *Session for i := 0; i < 2; i++ { // Protect us against concurrency, wait a couple of seconds for the answer to be populated before we process hangup s = sm.sessions.getSession(ev.GetUUID()) if s != nil { break } time.Sleep(time.Duration(i+1) * time.Second) } if s != nil { // Handled by us, cleanup here if err := sm.sessions.removeSession(s, ev); err != nil { utils.Logger.Err(err.Error()) } } if sm.cfg.CreateCdr { sm.ProcessCdr(ev.AsStoredCdr(config.CgrConfig().DefaultTimezone)) } var reply string attrRU := utils.AttrRLsResourceUsage{ ResourceUsageID: ev.GetUUID(), Event: ev.(FSEvent).AsMapStringInterface(sm.timezone), RequestedUnits: 1, } if sm.rls != nil { if err := sm.rls.Call("RLsV1.TerminateResourceUsage", attrRU, &reply); err != nil { utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> RLs API error: %s", err.Error())) } } }
func (fsev FSEvent) GetExtraFields() map[string]string { extraFields := make(map[string]string) for _, fldRule := range config.CgrConfig().FSCdrExtraFields { extraFields[fldRule.Id] = fsev.ParseEventValue(fldRule) } return extraFields }
// Does not block for posts, no error reports func callUrlAsync(ub *Account, sq *StatsQueueTriggered, a *Action) error { var o interface{} if ub != nil { o = ub } if sq != nil { o = sq } jsn, err := json.Marshal(o) if err != nil { return err } cfg := config.CgrConfig() go func() { for i := 0; i < 5; i++ { // Loop so we can increase the success rate on best effort if _, err = utils.HttpJsonPost(a.ExtraParameters, cfg.HttpSkipTlsVerify, o); err == nil { break // Success, no need to reinterate } else if i == 4 { // Last iteration, syslog the warning Logger.Warning(fmt.Sprintf("<Triggers> WARNING: Failed calling url: [%s], error: [%s], triggered: %s", a.ExtraParameters, err.Error(), jsn)) break } time.Sleep(time.Duration(i) * time.Minute) } }() return nil }
// Queries LCR and sets the cgr_lcr channel variable func (sm *FSSessionManager) setCgrLcr(ev engine.Event, connId string) error { var lcrCost engine.LCRCost startTime, err := ev.GetSetupTime(utils.META_DEFAULT, sm.timezone) if err != nil { return err } cd := &engine.CallDescriptor{ Direction: ev.GetDirection(utils.META_DEFAULT), Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT), Account: ev.GetAccount(utils.META_DEFAULT), Destination: ev.GetDestination(utils.META_DEFAULT), TimeStart: startTime, TimeEnd: startTime.Add(config.CgrConfig().MaxCallDuration), } if err := sm.rater.GetLCR(&engine.AttrGetLcr{CallDescriptor: cd}, &lcrCost); err != nil { return err } supps := []string{} for _, supplCost := range lcrCost.SupplierCosts { if dtcs, err := utils.NewDTCSFromRPKey(supplCost.Supplier); err != nil { return err } else if len(dtcs.Subject) != 0 { supps = append(supps, dtcs.Subject) } } fsArray := SliceAsFsArray(supps) if _, err = sm.conns[connId].SendApiCmd(fmt.Sprintf("uuid_setvar %s cgr_notify %s\n\n", ev.GetUUID(), fsArray)); err != nil { return err } return nil }
// Does not block for posts, no error reports func callUrlAsync(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error { var o interface{} if ub != nil { o = ub } if sq != nil { o = sq } jsn, err := json.Marshal(o) if err != nil { return err } cfg := config.CgrConfig() fallbackPath := path.Join(cfg.HttpFailedDir, fmt.Sprintf("act_%s_%s_%s.json", a.ActionType, a.ExtraParameters, utils.GenUUID())) go utils.NewHTTPPoster(config.CgrConfig().HttpSkipTlsVerify, config.CgrConfig().ReplyTimeout).Post(a.ExtraParameters, utils.CONTENT_JSON, jsn, config.CgrConfig().HttpPosterAttempts, fallbackPath) return nil }
/* << .Object.Property >> Property can be a attribute or a method both used without () Please also note the initial dot . Currently there are following objects that can be used: Account - the account that this action is called on Action - the action with all it's attributs Actions - the list of actions in the current action set Sq - StatsQueueTriggered object We can actually use everythiong that go templates offer. You can read more here: https://golang.org/pkg/text/template/ */ func cgrRPCAction(account *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error { // parse template tmpl := template.New("extra_params") tmpl.Delims("<<", ">>") t, err := tmpl.Parse(a.ExtraParameters) if err != nil { utils.Logger.Err(fmt.Sprintf("error parsing *cgr_rpc template: %s", err.Error())) return err } var buf bytes.Buffer if err = t.Execute(&buf, struct { Account *Account Sq *StatsQueueTriggered Action *Action Actions Actions }{account, sq, a, acs}); err != nil { utils.Logger.Err(fmt.Sprintf("error executing *cgr_rpc template %s:", err.Error())) return err } processedExtraParam := buf.String() //utils.Logger.Info("ExtraParameters: " + parsedExtraParameters) req := RPCRequest{} if err := json.Unmarshal([]byte(processedExtraParam), &req); err != nil { return err } params, err := utils.GetRpcParams(req.Method) if err != nil { return err } var client rpcclient.RpcClientConnection if req.Address != utils.MetaInternal { if client, err = rpcclient.NewRpcClient("tcp", req.Address, req.Attempts, 0, config.CgrConfig().ConnectTimeout, config.CgrConfig().ReplyTimeout, req.Transport, nil); err != nil { return err } } else { client = params.Object.(rpcclient.RpcClientConnection) } in, out := params.InParam, params.OutParam //utils.Logger.Info("Params: " + utils.ToJSON(req.Params)) //p, err := utils.FromMapStringInterfaceValue(req.Params, in) mapstructure.Decode(req.Params, in) if err != nil { utils.Logger.Info("<*cgr_rpc> err: " + err.Error()) return err } utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> calling: %s with: %s", req.Method, utils.ToJSON(in))) if !req.Async { err = client.Call(req.Method, in, out) utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err)) return err } go func() { err := client.Call(req.Method, in, out) utils.Logger.Info(fmt.Sprintf("<*cgr_rpc> result: %s err: %v", utils.ToJSON(out), err)) }() return nil }
// Methods to apply on sessions, mostly exported through RPC/Bi-RPC //Calculates maximum usage allowed for gevent func (smg *SMGeneric) MaxUsage(gev SMGenericEvent) (time.Duration, error) { gev[utils.EVENT_NAME] = utils.CGR_AUTHORIZATION storedCdr := gev.AsStoredCdr(config.CgrConfig(), smg.timezone) var maxDur float64 if err := smg.rater.Call("Responder.GetDerivedMaxSessionTime", storedCdr, &maxDur); err != nil { return time.Duration(0), err } return time.Duration(maxDur), nil }
// Methods to apply on sessions, mostly exported through RPC/Bi-RPC //Calculates maximum usage allowed for gevent func (self *SMGeneric) GetMaxUsage(gev SMGenericEvent, clnt *rpc2.Client) (time.Duration, error) { gev[utils.EVENT_NAME] = utils.CGR_AUTHORIZATION storedCdr := gev.AsStoredCdr(config.CgrConfig(), self.timezone) var maxDur float64 if err := self.rater.GetDerivedMaxSessionTime(storedCdr, &maxDur); err != nil { return time.Duration(0), err } return time.Duration(maxDur), nil }
func (rs *Responder) GetDerivedChargers(attrs utils.AttrDerivedChargers, dcs *utils.DerivedChargers) error { // ToDo: Make it work with balancer if needed if dcsH, err := HandleGetDerivedChargers(accountingStorage, config.CgrConfig(), attrs); err != nil { return err } else if dcsH != nil { *dcs = dcsH } return nil }
func (fsev FSEvent) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string) { // Keep in sync (or merge) with StoredCdr.PassesFieldFielter() if fieldFilter == nil { return true, "" } if fieldFilter.IsStatic() && fsev.ParseEventValue(&utils.RSRField{Id: fieldFilter.Id}, config.CgrConfig().DefaultTimezone) == fsev.ParseEventValue(fieldFilter, config.CgrConfig().DefaultTimezone) { return true, fsev.ParseEventValue(&utils.RSRField{Id: fieldFilter.Id}, config.CgrConfig().DefaultTimezone) } preparedFilter := &utils.RSRField{Id: fieldFilter.Id, RSRules: make([]*utils.ReSearchReplace, len(fieldFilter.RSRules))} // Reset rules so they do not point towards same structures as original fieldFilter for idx := range fieldFilter.RSRules { // Hardcode the template with maximum of 5 groups ordered preparedFilter.RSRules[idx] = &utils.ReSearchReplace{SearchRegexp: fieldFilter.RSRules[idx].SearchRegexp, ReplaceTemplate: utils.FILTER_REGEXP_TPL} } preparedVal := fsev.ParseEventValue(preparedFilter, config.CgrConfig().DefaultTimezone) filteredValue := fsev.ParseEventValue(fieldFilter, config.CgrConfig().DefaultTimezone) if preparedFilter.RegexpMatched() && (len(preparedVal) == 0 || preparedVal == filteredValue) { return true, filteredValue } return false, "" }
func TestKevAsCallDescriptor(t *testing.T) { sTime := time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC) kamEv := KamEvent{"event": CGR_LCR_REQUEST, CGR_ACCOUNT: "1001", CGR_DESTINATION: "1002", CGR_SETUPTIME: sTime.String()} eCd := &engine.CallDescriptor{ Direction: utils.OUT, Tenant: config.CgrConfig().DefaultTenant, Category: config.CgrConfig().DefaultCategory, Account: kamEv[CGR_ACCOUNT], Subject: kamEv[CGR_ACCOUNT], Destination: kamEv[CGR_DESTINATION], TimeStart: sTime, TimeEnd: sTime.Add(time.Duration(1) * time.Minute), } if cd, err := kamEv.AsCallDescriptor(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCd, cd) { t.Errorf("Expecting: %+v, received: %+v", eCd, cd) } }
func (osipsev *OsipsEvent) GetEndTime() (time.Time, error) { var nilTime time.Time aTime, err := osipsev.GetAnswerTime(utils.META_DEFAULT, config.CgrConfig().DefaultTimezone) if err != nil { return nilTime, err } dur, err := osipsev.GetDuration(utils.META_DEFAULT) if err != nil { return nilTime, err } return aTime.Add(dur), nil }
func (fsev FSEvent) GetReqType(fieldName string) string { var reqTypeDetected = "" // Used to automatically disable processing of the request if fsev["variable_process_cdr"] == "false" { // FS will not generated CDR here reqTypeDetected = utils.META_NONE } else if fsev["Caller-Dialplan"] == "inline" { // Used for internally generated dialplan, eg refer coming from another box, not in our control reqTypeDetected = utils.META_NONE } if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(fsev[fieldName], fsev[REQTYPE], reqTypeDetected, config.CgrConfig().DefaultReqType) }
// Converts into CallDescriptor due to responder interface needs func (kev KamEvent) AsCallDescriptor() (*engine.CallDescriptor, error) { lcrReq := &engine.LcrRequest{ Direction: kev.GetDirection(utils.META_DEFAULT), Tenant: kev.GetTenant(utils.META_DEFAULT), Category: kev.GetCategory(utils.META_DEFAULT), Account: kev.GetAccount(utils.META_DEFAULT), Subject: kev.GetSubject(utils.META_DEFAULT), Destination: kev.GetDestination(utils.META_DEFAULT), SetupTime: utils.FirstNonEmpty(kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]), Duration: kev[CGR_DURATION], } return lcrReq.AsCallDescriptor(config.CgrConfig().DefaultTimezone) }
// Does not block for posts, no error reports func callUrlAsync(ub *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error { var o interface{} if ub != nil { o = ub } if sq != nil { o = sq } cfg := config.CgrConfig() fallbackPath := path.Join(cfg.HttpFailedDir, fmt.Sprintf("act_%s_%s_%s.json", a.ActionType, a.ExtraParameters, utils.GenUUID())) go utils.HttpPoster(a.ExtraParameters, cfg.HttpSkipTlsVerify, o, utils.CONTENT_JSON, 3, fallbackPath) return nil }
func (rs *Responder) Status(arg string, reply *map[string]interface{}) (err error) { memstats := new(runtime.MemStats) runtime.ReadMemStats(memstats) response := make(map[string]interface{}) response[utils.InstanceID] = config.CgrConfig().InstanceID if rs.Bal != nil { response["Raters"] = rs.Bal.GetClientAddresses() } response["memstat"] = utils.SizeFmt(float64(memstats.HeapAlloc), "") response["footprint"] = utils.SizeFmt(float64(memstats.Sys), "") *reply = response return }
func (sm *FSSessionManager) onChannelPark(ev engine.Event, connId string) { fsev := ev.(FSEvent) if ev.GetReqType(utils.META_DEFAULT) == utils.META_NONE || fsev[IGNOREPARK] == "true" { // Do not process this request return } var maxCallDuration float64 // This will be the maximum duration this channel will be allowed to last if err := sm.rater.Call("Responder.GetDerivedMaxSessionTime", ev.AsStoredCdr(config.CgrConfig().DefaultTimezone), &maxCallDuration); err != nil { utils.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Could not get max session time for %s, error: %s", ev.GetUUID(), err.Error())) } if maxCallDuration != -1 { // For calls different than unlimited, set limits maxCallDur := time.Duration(maxCallDuration) if maxCallDur <= sm.cfg.MinCallDuration { //utils.Logger.Info(fmt.Sprintf("Not enough credit for trasferring the call %s for %s.", ev.GetUUID(), cd.GetKey(cd.Subject))) sm.unparkCall(ev.GetUUID(), connId, ev.GetCallDestNr(utils.META_DEFAULT), INSUFFICIENT_FUNDS) return } sm.setMaxCallDuration(ev.GetUUID(), connId, maxCallDur) } // ComputeLcr if ev.ComputeLcr() { cd, err := fsev.AsCallDescriptor() cd.CgrID = fsev.GetCgrId(sm.Timezone()) if err != nil { utils.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().Call("Responder.GetLCR", &engine.AttrGetLcr{CallDescriptor: cd}, &lcr); err != nil { utils.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 { utils.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 { utils.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) }
func (self *SQLStorage) Flush() (err error) { cfg := config.CgrConfig() for _, scriptName := range []string{CREATE_CDRS_TABLES_SQL, CREATE_TARIFFPLAN_TABLES_SQL} { if err := self.CreateTablesFromScript(path.Join(cfg.DataFolderPath, "storage", "mysql", scriptName)); err != nil { return err } } for _, tbl := range []string{utils.TBL_CDRS_PRIMARY, utils.TBL_CDRS_EXTRA} { if _, err := self.Db.Query(fmt.Sprintf("SELECT 1 from %s", tbl)); err != nil { return err } } return nil }
// 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), SetupTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]), Duration: fsev[DURATION], ExtraFields: fsev.GetExtraFields(), } return lcrReq.AsCallDescriptor(config.CgrConfig().DefaultTimezone) }
// MaxUsage calculates maximum usage allowed for given gevent func (smg *SMGeneric) MaxUsage(gev SMGenericEvent) (maxUsage time.Duration, err error) { cacheKey := "MaxUsage" + gev.GetCgrId(smg.timezone) if item, err := smg.responseCache.Get(cacheKey); err == nil && item != nil { return (item.Value.(time.Duration)), item.Err } defer smg.responseCache.Cache(cacheKey, &cache.CacheItem{Value: maxUsage, Err: err}) gev[utils.EVENT_NAME] = utils.CGR_AUTHORIZATION storedCdr := gev.AsStoredCdr(config.CgrConfig(), smg.timezone) var maxDur float64 if err = smg.rater.Call("Responder.GetDerivedMaxSessionTime", storedCdr, &maxDur); err != nil { return } maxUsage = time.Duration(maxDur) return }
func TestLcrRequestAsCallDescriptor(t *testing.T) { sTime := time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC) callDur := time.Duration(1) * time.Minute lcrReq := &LcrRequest{Account: "2001", SetupTime: sTime.String()} if _, err := lcrReq.AsCallDescriptor(""); err == nil || err != utils.ErrMandatoryIeMissing { t.Error("Unexpected error received: %v", err) } lcrReq = &LcrRequest{Account: "2001", Destination: "2002", SetupTime: sTime.String()} eCd := &CallDescriptor{ Direction: utils.OUT, Tenant: config.CgrConfig().DefaultTenant, Category: config.CgrConfig().DefaultCategory, Account: lcrReq.Account, Subject: lcrReq.Account, Destination: lcrReq.Destination, TimeStart: sTime, TimeEnd: sTime.Add(callDur), } if cd, err := lcrReq.AsCallDescriptor(""); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCd, cd) { t.Errorf("Expected: %+v, received: %+v", eCd, cd) } }