func (fsev FSEvent) GetSubject(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[SUBJECT], fsev[USERNAME]) } return utils.FirstNonEmpty(fsev[fieldName], fsev[SUBJECT], fsev[USERNAME]) }
// Charging destination number func (fsev FSEvent) GetDestination(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[DESTINATION], fsev[CALL_DEST_NR]) } return utils.FirstNonEmpty(fsev[fieldName], fsev[DESTINATION], fsev[CALL_DEST_NR]) }
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 (fsCdr FSCdr) AsStoredCdr(timezone string) *CDR { storCdr := new(CDR) storCdr.CGRID = fsCdr.getCGRID(timezone) storCdr.ToR = utils.VOICE storCdr.OriginID = fsCdr.vars[FS_UUID] storCdr.OriginHost = fsCdr.vars[FS_IP] storCdr.Source = FS_CDR_SOURCE storCdr.RequestType = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE], fsCdr.cgrCfg.DefaultReqType) storCdr.Direction = utils.OUT storCdr.Tenant = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_TENANT], fsCdr.cgrCfg.DefaultTenant) storCdr.Category = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_CATEGORY], fsCdr.cgrCfg.DefaultCategory) storCdr.Account = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_ACCOUNT], fsCdr.vars[FS_USERNAME]) storCdr.Subject = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_SUBJECT], fsCdr.vars[utils.CGR_ACCOUNT], fsCdr.vars[FS_USERNAME]) storCdr.Destination = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DESTINATION], fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER]) storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME], timezone) // Not interested to process errors, should do them if necessary in a previous step pddStr := utils.FirstNonEmpty(fsCdr.vars[FS_PROGRESS_MEDIAMSEC], fsCdr.vars[FS_PROGRESSMS]) pddStr += "ms" storCdr.PDD, _ = time.ParseDuration(pddStr) storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME], timezone) storCdr.Usage, _ = utils.ParseDurationWithSecs(fsCdr.vars[FS_DURATION]) storCdr.Supplier = fsCdr.vars[utils.CGR_SUPPLIER] storCdr.DisconnectCause = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DISCONNECT_CAUSE], fsCdr.vars["hangup_cause"]) storCdr.ExtraFields = fsCdr.getExtraFields() storCdr.Cost = -1 return storCdr }
func (kev KamEvent) GetSetupTime(fieldName, timezone string) (time.Time, error) { sTimeStr := utils.FirstNonEmpty(kev[fieldName], kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value sTimeStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.ParseTimeDetectLayout(sTimeStr, timezone) }
func (osipsev *OsipsEvent) GetSetupTime(fieldName, timezone string) (time.Time, error) { sTimeStr := utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[OSIPS_SETUP_TIME], osipsev.osipsEvent.AttrValues[OSIPS_EVENT_TIME]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value sTimeStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.ParseTimeDetectLayout(sTimeStr, timezone) }
func (kev KamEvent) GetDuration(fieldName string) (time.Duration, error) { durStr := utils.FirstNonEmpty(kev[fieldName], kev[CGR_DURATION]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value durStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.ParseDurationWithSecs(durStr) }
func (osipsev *OsipsEvent) GetDuration(fieldName string) (time.Duration, error) { durStr := utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[OSIPS_DURATION]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value durStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.ParseDurationWithSecs(durStr) }
func (fsev FSEvent) GetOriginatorIP(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 fsev[FS_IPv4] } return utils.FirstNonEmpty(fsev[fieldName], fsev[FS_IPv4]) }
func (osipsev *OsipsEvent) GetAnswerTime(fieldName, timezone string) (time.Time, error) { aTimeStr := utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[CGR_ANSWERTIME]) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value aTimeStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } else if fieldName == utils.META_DEFAULT { aTimeStr = osipsev.osipsEvent.AttrValues[CGR_ANSWERTIME] } return utils.ParseTimeDetectLayout(aTimeStr, timezone) }
func (fsev FSEvent) GetAnswerTime(fieldName, timezone string) (t time.Time, err error) { fsATimeStr, hasKey := fsev[ANSWER_TIME] if hasKey && fsATimeStr != "0" { // Discard the nanoseconds information since MySQL cannot store them in early versions and csv uses default seconds so cgrid will not corelate fsATimeStr = fsATimeStr[:len(fsATimeStr)-6] } aTimeStr := utils.FirstNonEmpty(fsev[fieldName], fsATimeStr) if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value aTimeStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.ParseTimeDetectLayout(aTimeStr, timezone) }
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) }
func (fsev FSEvent) GetPdd(fieldName string) (time.Duration, error) { var pddStr string if utils.IsSliceMember([]string{utils.PDD, utils.META_DEFAULT}, fieldName) { pddStr = utils.FirstNonEmpty(fsev[PDD_MEDIA_MS], fsev[PDD_NOMEDIA_MS]) if len(pddStr) != 0 { pddStr = pddStr + "ms" // PDD is in milliseconds and CGR expects it in seconds } } else if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value pddStr = fieldName[len(utils.STATIC_VALUE_PREFIX):] } else { pddStr = fsev[fieldName] } return utils.ParseDurationWithSecs(pddStr) }
// 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) }
func (self SMGenericEvent) AsLcrRequest() *engine.LcrRequest { setupTimeStr, _ := utils.ConvertIfaceToString(self[utils.SETUP_TIME]) usageStr, _ := utils.ConvertIfaceToString(self[utils.USAGE]) return &engine.LcrRequest{ Direction: self.GetDirection(utils.META_DEFAULT), Tenant: self.GetTenant(utils.META_DEFAULT), Category: self.GetCategory(utils.META_DEFAULT), Account: self.GetAccount(utils.META_DEFAULT), Subject: self.GetSubject(utils.META_DEFAULT), Destination: self.GetDestination(utils.META_DEFAULT), SetupTime: utils.FirstNonEmpty(setupTimeStr), Duration: usageStr, } }
func (self SMGenericEvent) AsStoredCdr(cfg *config.CGRConfig, timezone string) *engine.CDR { storCdr := engine.NewCDRWithDefaults(cfg) storCdr.CGRID = self.GetCgrId(timezone) storCdr.ToR = utils.FirstNonEmpty(self.GetTOR(utils.META_DEFAULT), storCdr.ToR) // Keep default if none in the event storCdr.OriginID = self.GetUUID() storCdr.OriginHost = self.GetOriginatorIP(utils.META_DEFAULT) storCdr.Source = self.GetCdrSource() storCdr.RequestType = utils.FirstNonEmpty(self.GetReqType(utils.META_DEFAULT), storCdr.RequestType) storCdr.Direction = utils.FirstNonEmpty(self.GetDirection(utils.META_DEFAULT), storCdr.Direction) storCdr.Tenant = utils.FirstNonEmpty(self.GetTenant(utils.META_DEFAULT), storCdr.Tenant) storCdr.Category = utils.FirstNonEmpty(self.GetCategory(utils.META_DEFAULT), storCdr.Category) storCdr.Account = self.GetAccount(utils.META_DEFAULT) storCdr.Subject = self.GetSubject(utils.META_DEFAULT) storCdr.Destination = self.GetDestination(utils.META_DEFAULT) storCdr.SetupTime, _ = self.GetSetupTime(utils.META_DEFAULT, timezone) storCdr.AnswerTime, _ = self.GetAnswerTime(utils.META_DEFAULT, timezone) storCdr.Usage, _ = self.GetUsage(utils.META_DEFAULT) storCdr.PDD, _ = self.GetPdd(utils.META_DEFAULT) storCdr.Supplier = self.GetSupplier(utils.META_DEFAULT) storCdr.DisconnectCause = self.GetDisconnectCause(utils.META_DEFAULT) storCdr.ExtraFields = self.GetExtraFields() storCdr.Cost = -1 return storCdr }
func (fsCdr FSCdr) AsStoredCdr() *utils.StoredCdr { storCdr := new(utils.StoredCdr) storCdr.CgrId = fsCdr.getCgrId() storCdr.TOR = utils.VOICE storCdr.AccId = fsCdr.vars[FS_UUID] storCdr.CdrHost = fsCdr.vars[FS_IP] storCdr.CdrSource = FS_CDR_SOURCE storCdr.ReqType = utils.FirstNonEmpty(fsCdr.vars[FS_REQTYPE], cfg.DefaultReqType) storCdr.Direction = "*out" storCdr.Tenant = utils.FirstNonEmpty(fsCdr.vars[FS_CSTMID], cfg.DefaultTenant) storCdr.Category = utils.FirstNonEmpty(fsCdr.vars[FS_CATEGORY], cfg.DefaultCategory) storCdr.Account = utils.FirstNonEmpty(fsCdr.vars[FS_ACCOUNT], fsCdr.vars[FS_USERNAME]) storCdr.Subject = utils.FirstNonEmpty(fsCdr.vars[FS_SUBJECT], fsCdr.vars[FS_USERNAME]) storCdr.Destination = utils.FirstNonEmpty(fsCdr.vars[FS_DESTINATION], fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER]) storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME]) // Not interested to process errors, should do them if necessary in a previous step storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME]) storCdr.Usage, _ = utils.ParseDurationWithSecs(fsCdr.vars[FS_DURATION]) storCdr.ExtraFields = fsCdr.getExtraFields() storCdr.Cost = -1 return storCdr }
/* One instance of CDRC will act on one folder. Common parameters within configs processed: * cdrS, cdrFormat, cdrInDir, cdrOutDir, runDelay Parameters specific per config instance: * duMultiplyFactor, cdrSourceId, cdrFilter, cdrFields */ func NewCdrc(cdrcCfgs map[string]*config.CdrcConfig, httpSkipTlsCheck bool, cdrs engine.Connector, closeChan chan struct{}, dfltTimezone string) (*Cdrc, error) { var cdrcCfg *config.CdrcConfig for _, cdrcCfg = range cdrcCfgs { // Take the first config out, does not matter which one break } cdrc := &Cdrc{httpSkipTlsCheck: httpSkipTlsCheck, cdrcCfgs: cdrcCfgs, dfltCdrcCfg: cdrcCfg, timezone: utils.FirstNonEmpty(cdrcCfg.Timezone, dfltTimezone), cdrs: cdrs, closeChan: closeChan, maxOpenFiles: make(chan struct{}, cdrcCfg.MaxOpenFiles), } var processFile struct{} for i := 0; i < cdrcCfg.MaxOpenFiles; i++ { cdrc.maxOpenFiles <- processFile // Empty initiate so we do not need to wait later when we pop } var err error if cdrc.partialRecordsCache, err = NewPartialRecordsCache(cdrcCfg.PartialRecordCache, cdrcCfg.CdrOutDir, cdrcCfg.FieldSeparator); err != nil { return nil, err } // Before processing, make sure in and out folders exist for _, dir := range []string{cdrcCfg.CdrInDir, cdrcCfg.CdrOutDir} { if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { return nil, fmt.Errorf("Nonexistent folder: %s", dir) } } cdrc.httpClient = new(http.Client) return cdrc, nil }
func (osipsev *OsipsEvent) GetDisconnectCause(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[OSIPS_SIPCODE], osipsev.osipsEvent.AttrValues[utils.DISCONNECT_CAUSE]) }
func (osipsev *OsipsEvent) GetSupplier(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(osipsev.osipsEvent.AttrValues[fieldName], osipsev.osipsEvent.AttrValues[utils.CGR_SUPPLIER]) }
func (kev KamEvent) GetDisconnectCause(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[utils.CGR_DISCONNECT_CAUSE]) }
// Account calling func (fsev FSEvent) GetAccount(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(fsev[fieldName], fsev[ACCOUNT], fsev[USERNAME]) }
// Original dialed destination number, useful in case of unpark func (fsev FSEvent) GetCallDestNr(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(fsev[fieldName], fsev[CALL_DEST_NR], fsev[SIP_REQ_USER]) }
func (kev KamEvent) GetSupplier(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[utils.CGR_SUPPLIER]) }
func (fsev FSEvent) GetTenant(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(fsev[fieldName], fsev[CSTMID], config.CgrConfig().DefaultTenant) }
func (kev KamEvent) GetReqType(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[CGR_REQTYPE], config.CgrConfig().DefaultReqType) }
func (kev KamEvent) GetCategory(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[CGR_CATEGORY], config.CgrConfig().DefaultCategory) }
func (kev KamEvent) GetDestination(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[CGR_DESTINATION]) }
func (kev KamEvent) GetSubject(fieldName string) string { if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value return fieldName[len(utils.STATIC_VALUE_PREFIX):] } return utils.FirstNonEmpty(kev[fieldName], kev[CGR_SUBJECT], kev.GetAccount(fieldName)) }