예제 #1
0
func TestCdreCfgClone(t *testing.T) {
	cgrIdRsrs, _ := utils.ParseRSRFields("cgrid", utils.INFIELD_SEP)
	runIdRsrs, _ := utils.ParseRSRFields("mediation_runid", utils.INFIELD_SEP)
	emptyFields := []*CfgCdrField{}
	initContentFlds := []*CfgCdrField{
		&CfgCdrField{Tag: "CgrId",
			Type:    "*composed",
			FieldId: "cgrid",
			Value:   cgrIdRsrs},
		&CfgCdrField{Tag: "RunId",
			Type:    "*composed",
			FieldId: "mediation_runid",
			Value:   runIdRsrs},
	}
	initCdreCfg := &CdreConfig{
		CdrFormat:               "csv",
		FieldSeparator:          rune(','),
		DataUsageMultiplyFactor: 1.0,
		CostMultiplyFactor:      1.0,
		ExportDirectory:         "/var/spool/cgrates/cdre",
		ContentFields:           initContentFlds,
	}
	eClnContentFlds := []*CfgCdrField{
		&CfgCdrField{Tag: "CgrId",
			Type:    "*composed",
			FieldId: "cgrid",
			Value:   cgrIdRsrs},
		&CfgCdrField{Tag: "RunId",
			Type:    "*composed",
			FieldId: "mediation_runid",
			Value:   runIdRsrs},
	}
	eClnCdreCfg := &CdreConfig{
		CdrFormat:               "csv",
		FieldSeparator:          rune(','),
		DataUsageMultiplyFactor: 1.0,
		CostMultiplyFactor:      1.0,
		ExportDirectory:         "/var/spool/cgrates/cdre",
		HeaderFields:            emptyFields,
		ContentFields:           eClnContentFlds,
		TrailerFields:           emptyFields,
	}
	clnCdreCfg := initCdreCfg.Clone()
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) {
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	initCdreCfg.DataUsageMultiplyFactor = 1024.0
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	initContentFlds[0].Tag = "Destination"
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	clnCdreCfg.ContentFields[0].FieldId = "destination"
	if initCdreCfg.ContentFields[0].FieldId != "cgrid" {
		t.Error("Unexpected change of FieldId: ", initCdreCfg.ContentFields[0].FieldId)
	}

}
예제 #2
0
func ParseCdrcCdrFields(torFld, accIdFld, reqtypeFld, directionFld, tenantFld, categoryFld, acntFld, subjectFld, destFld,
	setupTimeFld, answerTimeFld, durFld, extraFlds string) (map[string][]*utils.RSRField, error) {
	cdrcCdrFlds := make(map[string][]*utils.RSRField)
	if len(extraFlds) != 0 {
		if sepExtraFlds, err := ConfigSlice(extraFlds); err != nil {
			return nil, err
		} else {
			for _, fldStr := range sepExtraFlds {
				// extra fields defined as: <label_extrafield_1>:<index_extrafield_1>
				if spltLbl := strings.Split(fldStr, utils.CONCATENATED_KEY_SEP); len(spltLbl) != 2 {
					return nil, fmt.Errorf("Wrong format for cdrc.extra_fields: %s", fldStr)
				} else {
					if rsrFlds, err := utils.ParseRSRFields(spltLbl[1], utils.INFIELD_SEP); err != nil {
						return nil, err
					} else {
						cdrcCdrFlds[spltLbl[0]] = rsrFlds
					}
				}
			}
		}
	}
	for fldTag, fldVal := range map[string]string{utils.TOR: torFld, utils.ACCID: accIdFld, utils.REQTYPE: reqtypeFld, utils.DIRECTION: directionFld, utils.TENANT: tenantFld,
		utils.CATEGORY: categoryFld, utils.ACCOUNT: acntFld, utils.SUBJECT: subjectFld, utils.DESTINATION: destFld, utils.SETUP_TIME: setupTimeFld,
		utils.ANSWER_TIME: answerTimeFld, utils.USAGE: durFld} {
		if len(fldVal) != 0 {
			if rsrFlds, err := utils.ParseRSRFields(fldVal, utils.INFIELD_SEP); err != nil {
				return nil, err
			} else {
				cdrcCdrFlds[fldTag] = rsrFlds
			}
		}
	}
	return cdrcCdrFlds, nil
}
예제 #3
0
func TestGetDateTimeFieldVal(t *testing.T) {
	cdreTst := new(CdrExporter)
	cdrTst := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
		RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
		Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01,
		ExtraFields: map[string]string{"stop_time": "2014-06-11 19:19:00 +0000 UTC", "fieldextr2": "valextr2"}}
	val, _ := utils.ParseRSRFields("stop_time", utils.INFIELD_SEP)
	layout := "2006-01-02 15:04:05"
	cfgCdrFld := &config.CfgCdrField{Tag: "stop_time", Type: "cdrfield", FieldId: "stop_time", Value: val, Layout: layout}
	if cdrVal, err := cdreTst.getDateTimeFieldVal(cdrTst, cfgCdrFld); err != nil {
		t.Error(err)
	} else if cdrVal != "2014-06-11 19:19:00" {
		t.Error("Expecting: 2014-06-11 19:19:00, got: ", cdrVal)
	}
	// Test filter
	fltr, _ := utils.ParseRSRFields("~tenant:s/(.+)/itsyscom.com/", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "stop_time", Type: "cdrfield", FieldId: "stop_time", Value: val, FieldFilter: fltr, Layout: layout}
	if _, err := cdreTst.getDateTimeFieldVal(cdrTst, cfgCdrFld); err == nil {
		t.Error(err)
	}
	val, _ = utils.ParseRSRFields("fieldextr2", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "stop_time", Type: "cdrfield", FieldId: "stop_time", Value: val, Layout: layout}
	// Test time parse error
	if _, err := cdreTst.getDateTimeFieldVal(cdrTst, cfgCdrFld); err == nil {
		t.Error("Should give error here, got none.")
	}
}
예제 #4
0
func NewCfgCdrFieldFromCdrFieldJsonCfg(jsnCfgFld *CdrFieldJsonCfg) (*CfgCdrField, error) {
	var err error
	cfgFld := new(CfgCdrField)
	if jsnCfgFld.Tag != nil {
		cfgFld.Tag = *jsnCfgFld.Tag
	}
	if jsnCfgFld.Type != nil {
		cfgFld.Type = *jsnCfgFld.Type
	}
	if jsnCfgFld.Field_id != nil {
		cfgFld.FieldId = *jsnCfgFld.Field_id
	}
	if jsnCfgFld.Handler_id != nil {
		cfgFld.HandlerId = *jsnCfgFld.Handler_id
	}
	if jsnCfgFld.Value != nil {
		if cfgFld.Value, err = utils.ParseRSRFields(*jsnCfgFld.Value, utils.INFIELD_SEP); err != nil {
			return nil, err
		}
	}
	if jsnCfgFld.Append != nil {
		cfgFld.Append = *jsnCfgFld.Append
	}
	if jsnCfgFld.Field_filter != nil {
		if cfgFld.FieldFilter, err = utils.ParseRSRFields(*jsnCfgFld.Field_filter, utils.INFIELD_SEP); err != nil {
			return nil, err
		}
	}
	if jsnCfgFld.Width != nil {
		cfgFld.Width = *jsnCfgFld.Width
	}
	if jsnCfgFld.Strip != nil {
		cfgFld.Strip = *jsnCfgFld.Strip
	}
	if jsnCfgFld.Padding != nil {
		cfgFld.Padding = *jsnCfgFld.Padding
	}
	if jsnCfgFld.Layout != nil {
		cfgFld.Layout = *jsnCfgFld.Layout
	}
	if jsnCfgFld.Mandatory != nil {
		cfgFld.Mandatory = *jsnCfgFld.Mandatory
	}
	if jsnCfgFld.Cost_shift_digits != nil {
		cfgFld.CostShiftDigits = *jsnCfgFld.Cost_shift_digits
	}
	if jsnCfgFld.Rounding_decimals != nil {
		cfgFld.RoundingDecimals = *jsnCfgFld.Rounding_decimals
	}
	if jsnCfgFld.Timezone != nil {
		cfgFld.Timezone = *jsnCfgFld.Timezone
	}
	if jsnCfgFld.Mask_length != nil {
		cfgFld.MaskLen = *jsnCfgFld.Mask_length
	}
	if jsnCfgFld.Mask_destinationd_id != nil {
		cfgFld.MaskDestID = *jsnCfgFld.Mask_destinationd_id
	}
	return cfgFld, nil
}
예제 #5
0
파일: daconfig.go 프로젝트: bhepp/cgrates
func (self *DARequestProcessor) loadFromJsonCfg(jsnCfg *DARequestProcessorJsnCfg) error {
	if jsnCfg == nil {
		return nil
	}
	if jsnCfg.Id != nil {
		self.Id = *jsnCfg.Id
	}
	if jsnCfg.Dry_run != nil {
		self.DryRun = *jsnCfg.Dry_run
	}
	if jsnCfg.Publish_event != nil {
		self.PublishEvent = *jsnCfg.Publish_event
	}
	var err error
	if jsnCfg.Request_filter != nil {
		if self.RequestFilter, err = utils.ParseRSRFields(*jsnCfg.Request_filter, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.CCR_fields != nil {
		if self.CCRFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.CCR_fields); err != nil {
			return err
		}
	}
	if jsnCfg.CCA_fields != nil {
		if self.CCAFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.CCA_fields); err != nil {
			return err
		}
	}
	return nil
}
예제 #6
0
파일: pubsub.go 프로젝트: nikbyte/cgrates
func (ps *PubSub) Subscribe(si SubscribeInfo, reply *string) error {
	ps.mux.Lock()
	defer ps.mux.Unlock()
	if si.Transport != utils.META_HTTP_POST {
		*reply = "Unsupported transport type"
		return errors.New(*reply)
	}
	var expTime time.Time
	if si.LifeSpan > 0 {
		expTime = time.Now().Add(si.LifeSpan)
	}
	rsr, err := utils.ParseRSRFields(si.EventFilter, utils.INFIELD_SEP)
	if err != nil {
		*reply = err.Error()
		return err
	}
	key := utils.InfieldJoin(si.Transport, si.Address)
	ps.subscribers[key] = &SubscriberData{
		ExpTime: expTime,
		Filters: rsr,
	}
	ps.saveSubscriber(key)
	*reply = utils.OK
	return nil
}
예제 #7
0
func TestCdreGetCombimedCdrFieldVal(t *testing.T) {
	cfg, _ := config.NewDefaultCGRConfig()
	cdrs := []*engine.CDR{
		&engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
			RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, RunID: "RUN_RTL", Cost: 1.01},
		&engine.CDR{CGRID: utils.Sha1("dsafdsaf2", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
			RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, RunID: "CUSTOMER1", Cost: 2.01},
		&engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
			RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, RunID: "CUSTOMER1", Cost: 3.01},
		&engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
			RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 4.01},
		&engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
			RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
			Category: "call", Account: "1000", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
			Usage: time.Duration(10) * time.Second, RunID: "RETAIL1", Cost: 5.01},
	}
	cdre, err := NewCdrExporter(cdrs, nil, cfg.CdreProfiles["*default"], cfg.CdreProfiles["*default"].CdrFormat, cfg.CdreProfiles["*default"].FieldSeparator,
		"firstexport", 0.0, 0.0, 0.0, 0.0, 0.0, 0, 4, cfg.RoundingDecimals, "", 0, cfg.HttpSkipTlsVerify, "")
	if err != nil {
		t.Error("Unexpected error received: ", err)
	}
	fltrRule, _ := utils.ParseRSRFields("~RunID:s/default/RUN_RTL/", utils.INFIELD_SEP)
	val, _ := utils.ParseRSRFields(utils.COST, utils.INFIELD_SEP)
	cfgCdrFld := &config.CfgCdrField{Tag: "cost", Type: "cdrfield", FieldId: utils.COST, Value: val, FieldFilter: fltrRule}
	if costVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], cfgCdrFld); err != nil {
		t.Error(err)
	} else if costVal != "1.01" {
		t.Error("Expecting: 1.01, received: ", costVal)
	}
	fltrRule, _ = utils.ParseRSRFields("~RunID:s/default/RETAIL1/", utils.INFIELD_SEP)
	val, _ = utils.ParseRSRFields(utils.ACCOUNT, utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: utils.ACCOUNT, Type: "cdrfield", FieldId: utils.ACCOUNT, Value: val, FieldFilter: fltrRule}
	if acntVal, err := cdre.getCombimedCdrFieldVal(cdrs[3], cfgCdrFld); err != nil {
		t.Error(err)
	} else if acntVal != "1000" {
		t.Error("Expecting: 1000, received: ", acntVal)
	}
}
예제 #8
0
func NewCfgCdrFieldFromCdrFieldJsonCfg(jsnCfgFld *CdrFieldJsonCfg) (*CfgCdrField, error) {
	var err error
	cfgFld := new(CfgCdrField)
	if jsnCfgFld.Tag != nil {
		cfgFld.Tag = *jsnCfgFld.Tag
	}
	if jsnCfgFld.Type != nil {
		cfgFld.Type = *jsnCfgFld.Type
	}
	if jsnCfgFld.Field_id != nil {
		cfgFld.FieldId = *jsnCfgFld.Field_id
	}
	if jsnCfgFld.Handler_id != nil {
		cfgFld.HandlerId = *jsnCfgFld.Handler_id
	}
	if jsnCfgFld.Value != nil {
		if cfgFld.Value, err = utils.ParseRSRFields(*jsnCfgFld.Value, utils.INFIELD_SEP); err != nil {
			return nil, err
		}
	}
	if jsnCfgFld.Append != nil {
		cfgFld.Append = *jsnCfgFld.Append
	}
	if jsnCfgFld.Field_filter != nil {
		if cfgFld.FieldFilter, err = utils.ParseRSRFields(*jsnCfgFld.Field_filter, utils.INFIELD_SEP); err != nil {
			return nil, err
		}
	}
	if jsnCfgFld.Width != nil {
		cfgFld.Width = *jsnCfgFld.Width
	}
	if jsnCfgFld.Strip != nil {
		cfgFld.Strip = *jsnCfgFld.Strip
	}
	if jsnCfgFld.Padding != nil {
		cfgFld.Padding = *jsnCfgFld.Padding
	}
	if jsnCfgFld.Layout != nil {
		cfgFld.Layout = *jsnCfgFld.Layout
	}
	if jsnCfgFld.Mandatory != nil {
		cfgFld.Mandatory = *jsnCfgFld.Mandatory
	}
	return cfgFld, nil
}
예제 #9
0
파일: cdrs.go 프로젝트: perrault/cgrates
func (self *CdrServer) deriveCdrs(storedCdr *StoredCdr) ([]*StoredCdr, error) {
	if len(storedCdr.MediationRunId) == 0 {
		storedCdr.MediationRunId = utils.META_DEFAULT
	}
	cdrRuns := []*StoredCdr{storedCdr}
	if storedCdr.Rated { // Do not derive already rated CDRs since they should be already derived
		return cdrRuns, nil
	}
	attrsDC := &utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction,
		Account: storedCdr.Account, Subject: storedCdr.Subject, Destination: storedCdr.Destination}
	var dcs utils.DerivedChargers
	if err := self.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
		utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error()))
		return nil, err
	}
	for _, dc := range dcs.Chargers {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := storedCdr.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched

			continue
		}
		dcReqTypeFld, _ := utils.NewRSRField(dc.ReqTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcPddFld, _ := utils.NewRSRField(dc.PddField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
		dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField)
		dcRatedFld, _ := utils.NewRSRField(dc.RatedField)
		dcCostFld, _ := utils.NewRSRField(dc.CostField)
		forkedCdr, err := storedCdr.ForkCdr(dc.RunId, dcReqTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
			dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", storedCdr.CgrId, dc.RunId, err.Error()))
			continue // do not add it to the forked CDR list
		}
		if !forkedCdr.Rated {
			forkedCdr.Cost = -1.0 // Make sure that un-rated CDRs start with Cost -1
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	return cdrRuns, nil
}
예제 #10
0
func TestCdreCdrFieldValue(t *testing.T) {
	cdre := new(CdrExporter)
	cdr := &engine.CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
		RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
		Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01}
	val, _ := utils.ParseRSRFields(utils.DESTINATION, utils.INFIELD_SEP)
	cfgCdrFld := &config.CfgCdrField{Tag: "destination", Type: "cdrfield", FieldId: utils.DESTINATION, Value: val}
	if val, err := cdre.cdrFieldValue(cdr, cfgCdrFld); err != nil {
		t.Error(err)
	} else if val != cdr.Destination {
		t.Errorf("Expecting: %s, received: %s", cdr.Destination, val)
	}
	fltr, _ := utils.ParseRSRFields("~tenant:s/(.+)/itsyscom.com/", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "destination", Type: "cdrfield", FieldId: utils.DESTINATION, Value: val, FieldFilter: fltr}
	if _, err := cdre.cdrFieldValue(cdr, cfgCdrFld); err == nil {
		t.Error("Failed to use filter")
	}
}
예제 #11
0
func (csvr *CSVReader) LoadDerivedChargers() (err error) {
	csvReader, fp, err := csvr.readerFunc(csvr.derivedChargersFn, csvr.sep, utils.DERIVED_CHARGERS_NRCOLS)
	if err != nil {
		log.Print("Could not load derivedChargers file: ", err)
		// allow writing of the other values
		return nil
	}
	if fp != nil {
		defer fp.Close()
	}
	for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
		if _, err = utils.ParseRSRFields(record[6], utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db
			return err
		}
		tag := utils.DerivedChargersKey(record[0], record[1], record[2], record[3], record[4])
		if _, found := csvr.derivedChargers[tag]; found {
			if csvr.derivedChargers[tag], err = csvr.derivedChargers[tag].Append(&utils.DerivedCharger{
				RunId:            ValueOrDefault(record[5], "*default"),
				RunFilters:       record[6],
				ReqTypeField:     ValueOrDefault(record[7], "*default"),
				DirectionField:   ValueOrDefault(record[8], "*default"),
				TenantField:      ValueOrDefault(record[9], "*default"),
				CategoryField:    ValueOrDefault(record[10], "*default"),
				AccountField:     ValueOrDefault(record[11], "*default"),
				SubjectField:     ValueOrDefault(record[12], "*default"),
				DestinationField: ValueOrDefault(record[13], "*default"),
				SetupTimeField:   ValueOrDefault(record[14], "*default"),
				AnswerTimeField:  ValueOrDefault(record[15], "*default"),
				UsageField:       ValueOrDefault(record[16], "*default"),
			}); err != nil {
				return err
			}
		} else {
			if record[5] == utils.DEFAULT_RUNID {
				return errors.New("Reserved RunId")
			}
			csvr.derivedChargers[tag] = utils.DerivedChargers{&utils.DerivedCharger{
				RunId:            ValueOrDefault(record[5], "*default"),
				RunFilters:       record[6],
				ReqTypeField:     ValueOrDefault(record[7], "*default"),
				DirectionField:   ValueOrDefault(record[8], "*default"),
				TenantField:      ValueOrDefault(record[9], "*default"),
				CategoryField:    ValueOrDefault(record[10], "*default"),
				AccountField:     ValueOrDefault(record[11], "*default"),
				SubjectField:     ValueOrDefault(record[12], "*default"),
				DestinationField: ValueOrDefault(record[13], "*default"),
				SetupTimeField:   ValueOrDefault(record[14], "*default"),
				AnswerTimeField:  ValueOrDefault(record[15], "*default"),
				UsageField:       ValueOrDefault(record[16], "*default"),
			}}
		}
	}
	return
}
예제 #12
0
func TestCDRAsExportRecord(t *testing.T) {
	cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Unix(1383813745, 0).UTC().String()), ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1",
		RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org",
		Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813745, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
		Usage: time.Duration(10) * time.Second, RunID: utils.DEFAULT_RUNID, Cost: 1.01,
		ExtraFields: map[string]string{"stop_time": "2014-06-11 19:19:00 +0000 UTC", "fieldextr2": "valextr2"}}

	val, _ := utils.ParseRSRFields(utils.DESTINATION, utils.INFIELD_SEP)
	cfgCdrFld := &config.CfgCdrField{Tag: "destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: val}
	if expRecord, err := cdr.AsExportRecord([]*config.CfgCdrField{cfgCdrFld}, 0, 0, "UTC", false, 0, "", nil); err != nil {
		t.Error(err)
	} else if expRecord[0] != cdr.Destination {
		t.Errorf("Expecting: %s, received: %s", cdr.Destination, expRecord[0])
	}
	fltr, _ := utils.ParseRSRFields("Tenant(itsyscom.com)", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "destination", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: val, FieldFilter: fltr}
	if _, err := cdr.AsExportRecord([]*config.CfgCdrField{cfgCdrFld}, 0, 0, "UTC", false, 0, "", nil); err == nil {
		t.Error("Failed to use filter")
	}
	// Test MetaDateTime
	val, _ = utils.ParseRSRFields("stop_time", utils.INFIELD_SEP)
	layout := "2006-01-02 15:04:05"
	cfgCdrFld = &config.CfgCdrField{Tag: "stop_time", Type: utils.MetaDateTime, FieldId: "stop_time", Value: val, Layout: layout}
	if expRecord, err := cdr.AsExportRecord([]*config.CfgCdrField{cfgCdrFld}, 0, 0, "UTC", false, 0, "", nil); err != nil {
		t.Error(err)
	} else if expRecord[0] != "2014-06-11 19:19:00" {
		t.Error("Expecting: 2014-06-11 19:19:00, got: ", expRecord[0])
	}
	// Test filter
	fltr, _ = utils.ParseRSRFields("Tenant(itsyscom.com)", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "stop_time", Type: utils.MetaDateTime, FieldId: "stop_time", Value: val, FieldFilter: fltr, Layout: layout}
	if _, err := cdr.AsExportRecord([]*config.CfgCdrField{cfgCdrFld}, 0, 0, "UTC", false, 0, "", nil); err == nil {
		t.Error("Received empty error", err)
	}
	val, _ = utils.ParseRSRFields("fieldextr2", utils.INFIELD_SEP)
	cfgCdrFld = &config.CfgCdrField{Tag: "stop_time", Type: utils.MetaDateTime, FieldId: "stop_time", Value: val, Layout: layout}
	// Test time parse error
	if _, err := cdr.AsExportRecord([]*config.CfgCdrField{cfgCdrFld}, 0, 0, "UTC", false, 0, "", nil); err == nil {
		t.Error("Should give error here, got none.")
	}
}
예제 #13
0
func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *string) (err error) {
	if len(attrs.DerivedChargers) == 0 {
		return utils.NewErrMandatoryIeMissing("DerivedChargers")
	}
	if len(attrs.Direction) == 0 {
		attrs.Direction = utils.OUT
	}
	if len(attrs.Tenant) == 0 {
		attrs.Tenant = utils.ANY
	}
	if len(attrs.Category) == 0 {
		attrs.Category = utils.ANY
	}
	if len(attrs.Account) == 0 {
		attrs.Account = utils.ANY
	}
	if len(attrs.Subject) == 0 {
		attrs.Subject = utils.ANY
	}
	for _, dc := range attrs.DerivedChargers {
		if _, err = utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db
			return fmt.Errorf("%s:%s", utils.ErrParserError.Error(), err.Error())
		}
	}
	dcKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject)
	if !attrs.Overwrite {
		if exists, err := self.RatingDb.HasData(utils.DERIVEDCHARGERS_PREFIX, dcKey); err != nil {
			return utils.NewErrServerError(err)
		} else if exists {
			return utils.ErrExists
		}
	}
	dstIds := strings.Split(attrs.DestinationIds, utils.INFIELD_SEP)
	dcs := &utils.DerivedChargers{DestinationIDs: utils.NewStringMap(dstIds...), Chargers: attrs.DerivedChargers}
	if err := self.RatingDb.SetDerivedChargers(dcKey, dcs); err != nil {
		return utils.NewErrServerError(err)
	}
	if err := self.RatingDb.CacheRatingPrefixValues(map[string][]string{
		utils.DERIVEDCHARGERS_PREFIX: []string{utils.DERIVEDCHARGERS_PREFIX + dcKey},
	}); err != nil {
		return utils.NewErrServerError(err)
	}
	*reply = utils.OK
	return nil
}
예제 #14
0
func (self *ApierV1) SetDerivedChargers(attrs AttrSetDerivedChargers, reply *string) (err error) {
	if missing := utils.MissingStructFields(&attrs, []string{"Tenant", "Category", "Direction", "Account", "Subject", "DerivedChargers"}); len(missing) != 0 {
		return fmt.Errorf("%s:%v", utils.ERR_MANDATORY_IE_MISSING, missing)
	}
	for _, dc := range attrs.DerivedChargers {
		if _, err = utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP); err != nil { // Make sure rules are OK before loading in db
			return fmt.Errorf("%s:%s", utils.ERR_PARSER_ERROR, err.Error())
		}
	}
	dcKey := utils.DerivedChargersKey(attrs.Direction, attrs.Tenant, attrs.Category, attrs.Account, attrs.Subject)
	if err := self.AccountDb.SetDerivedChargers(dcKey, attrs.DerivedChargers); err != nil {
		return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
	}
	if err := self.AccountDb.CacheAccounting([]string{}, []string{}, []string{}, []string{engine.DERIVEDCHARGERS_PREFIX + dcKey}); err != nil {
		return fmt.Errorf("%s:%s", utils.ERR_SERVER_ERROR, err.Error())
	}
	*reply = utils.OK
	return nil
}
예제 #15
0
파일: daconfig.go 프로젝트: cgrates/cgrates
func (self *DARequestProcessor) loadFromJsonCfg(jsnCfg *DARequestProcessorJsnCfg) error {
	if jsnCfg == nil {
		return nil
	}
	if jsnCfg.Id != nil {
		self.Id = *jsnCfg.Id
	}
	if jsnCfg.Dry_run != nil {
		self.DryRun = *jsnCfg.Dry_run
	}
	if jsnCfg.Publish_event != nil {
		self.PublishEvent = *jsnCfg.Publish_event
	}
	var err error
	if jsnCfg.Request_filter != nil {
		if self.RequestFilter, err = utils.ParseRSRFields(*jsnCfg.Request_filter, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Flags != nil {
		self.Flags = utils.StringMapFromSlice(*jsnCfg.Flags)
	}
	if jsnCfg.Continue_on_success != nil {
		self.ContinueOnSuccess = *jsnCfg.Continue_on_success
	}
	if jsnCfg.Append_cca != nil {
		self.AppendCCA = *jsnCfg.Append_cca
	}
	if jsnCfg.CCR_fields != nil {
		if self.CCRFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.CCR_fields); err != nil {
			return err
		}
	}
	if jsnCfg.CCA_fields != nil {
		if self.CCAFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.CCA_fields); err != nil {
			return err
		}
	}
	return nil
}
예제 #16
0
func (cdrcFld *CdrcField) PopulateRSRFields() (err error) {
	if cdrcFld.rsrFields, err = utils.ParseRSRFields(cdrcFld.Value, utils.INFIELD_SEP); err != nil {
		return err
	}
	return nil
}
예제 #17
0
파일: config.go 프로젝트: nikbyte/cgrates
// Loads from json configuration object, will be used for defaults, config from file and reload, might need lock
func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {

	// Load sections out of JSON config, stop on error
	jsnGeneralCfg, err := jsnCfg.GeneralJsonCfg()
	if err != nil {
		return err
	}

	jsnListenCfg, err := jsnCfg.ListenJsonCfg()
	if err != nil {
		return err
	}

	jsnTpDbCfg, err := jsnCfg.DbJsonCfg(TPDB_JSN)
	if err != nil {
		return err
	}

	jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN)
	if err != nil {
		return err
	}

	jsnStorDbCfg, err := jsnCfg.DbJsonCfg(STORDB_JSN)
	if err != nil {
		return err
	}

	jsnBalancerCfg, err := jsnCfg.BalancerJsonCfg()
	if err != nil {
		return err
	}

	jsnRaterCfg, err := jsnCfg.RaterJsonCfg()
	if err != nil {
		return err
	}

	jsnSchedCfg, err := jsnCfg.SchedulerJsonCfg()
	if err != nil {
		return err
	}

	jsnCdrsCfg, err := jsnCfg.CdrsJsonCfg()
	if err != nil {
		return err
	}

	jsnCdrstatsCfg, err := jsnCfg.CdrStatsJsonCfg()
	if err != nil {
		return err
	}

	jsnCdreCfg, err := jsnCfg.CdreJsonCfgs()
	if err != nil {
		return err
	}

	jsnCdrcCfg, err := jsnCfg.CdrcJsonCfg()
	if err != nil {
		return err
	}

	jsnSmFsCfg, err := jsnCfg.SmFsJsonCfg()
	if err != nil {
		return err
	}

	jsnSmKamCfg, err := jsnCfg.SmKamJsonCfg()
	if err != nil {
		return err
	}

	jsnSmOsipsCfg, err := jsnCfg.SmOsipsJsonCfg()
	if err != nil {
		return err
	}

	jsnHistServCfg, err := jsnCfg.HistServJsonCfg()
	if err != nil {
		return err
	}

	jsnPubSubServCfg, err := jsnCfg.PubSubServJsonCfg()
	if err != nil {
		return err
	}

	jsnAliasesServCfg, err := jsnCfg.AliasesServJsonCfg()
	if err != nil {
		return err
	}

	jsnUserServCfg, err := jsnCfg.UserServJsonCfg()
	if err != nil {
		return err
	}

	jsnMailerCfg, err := jsnCfg.MailerJsonCfg()
	if err != nil {
		return err
	}

	// All good, start populating config variables
	if jsnTpDbCfg != nil {
		if jsnTpDbCfg.Db_type != nil {
			self.TpDbType = *jsnTpDbCfg.Db_type
		}
		if jsnTpDbCfg.Db_host != nil {
			self.TpDbHost = *jsnTpDbCfg.Db_host
		}
		if jsnTpDbCfg.Db_port != nil {
			self.TpDbPort = strconv.Itoa(*jsnTpDbCfg.Db_port)
		}
		if jsnTpDbCfg.Db_name != nil {
			self.TpDbName = *jsnTpDbCfg.Db_name
		}
		if jsnTpDbCfg.Db_user != nil {
			self.TpDbUser = *jsnTpDbCfg.Db_user
		}
		if jsnTpDbCfg.Db_passwd != nil {
			self.TpDbPass = *jsnTpDbCfg.Db_passwd
		}
	}

	if jsnDataDbCfg != nil {
		if jsnDataDbCfg.Db_type != nil {
			self.DataDbType = *jsnDataDbCfg.Db_type
		}
		if jsnDataDbCfg.Db_host != nil {
			self.DataDbHost = *jsnDataDbCfg.Db_host
		}
		if jsnDataDbCfg.Db_port != nil {
			self.DataDbPort = strconv.Itoa(*jsnDataDbCfg.Db_port)
		}
		if jsnDataDbCfg.Db_name != nil {
			self.DataDbName = *jsnDataDbCfg.Db_name
		}
		if jsnDataDbCfg.Db_user != nil {
			self.DataDbUser = *jsnDataDbCfg.Db_user
		}
		if jsnDataDbCfg.Db_passwd != nil {
			self.DataDbPass = *jsnDataDbCfg.Db_passwd
		}
		if jsnDataDbCfg.Load_history_size != nil {
			self.LoadHistorySize = *jsnDataDbCfg.Load_history_size
		}
	}

	if jsnStorDbCfg != nil {
		if jsnStorDbCfg.Db_type != nil {
			self.StorDBType = *jsnStorDbCfg.Db_type
		}
		if jsnStorDbCfg.Db_host != nil {
			self.StorDBHost = *jsnStorDbCfg.Db_host
		}
		if jsnStorDbCfg.Db_port != nil {
			self.StorDBPort = strconv.Itoa(*jsnStorDbCfg.Db_port)
		}
		if jsnStorDbCfg.Db_name != nil {
			self.StorDBName = *jsnStorDbCfg.Db_name
		}
		if jsnStorDbCfg.Db_user != nil {
			self.StorDBUser = *jsnStorDbCfg.Db_user
		}
		if jsnStorDbCfg.Db_passwd != nil {
			self.StorDBPass = *jsnStorDbCfg.Db_passwd
		}
		if jsnStorDbCfg.Max_open_conns != nil {
			self.StorDBMaxOpenConns = *jsnStorDbCfg.Max_open_conns
		}
		if jsnStorDbCfg.Max_idle_conns != nil {
			self.StorDBMaxIdleConns = *jsnStorDbCfg.Max_idle_conns
		}
	}

	if jsnGeneralCfg != nil {
		if jsnGeneralCfg.Dbdata_encoding != nil {
			self.DBDataEncoding = *jsnGeneralCfg.Dbdata_encoding
		}
		if jsnGeneralCfg.Default_reqtype != nil {
			self.DefaultReqType = *jsnGeneralCfg.Default_reqtype
		}
		if jsnGeneralCfg.Default_category != nil {
			self.DefaultCategory = *jsnGeneralCfg.Default_category
		}
		if jsnGeneralCfg.Default_tenant != nil {
			self.DefaultTenant = *jsnGeneralCfg.Default_tenant
		}
		if jsnGeneralCfg.Default_subject != nil {
			self.DefaultSubject = *jsnGeneralCfg.Default_subject
		}
		if jsnGeneralCfg.Connect_attempts != nil {
			self.ConnectAttempts = *jsnGeneralCfg.Connect_attempts
		}
		if jsnGeneralCfg.Response_cache_ttl != nil {
			if self.ResponseCacheTTL, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Response_cache_ttl); err != nil {
				return err
			}
		}
		if jsnGeneralCfg.Reconnects != nil {
			self.Reconnects = *jsnGeneralCfg.Reconnects
		}
		if jsnGeneralCfg.Rounding_decimals != nil {
			self.RoundingDecimals = *jsnGeneralCfg.Rounding_decimals
		}
		if jsnGeneralCfg.Http_skip_tls_verify != nil {
			self.HttpSkipTlsVerify = *jsnGeneralCfg.Http_skip_tls_verify
		}
		if jsnGeneralCfg.Tpexport_dir != nil {
			self.TpExportPath = *jsnGeneralCfg.Tpexport_dir
		}
		if jsnGeneralCfg.Default_timezone != nil {
			self.DefaultTimezone = *jsnGeneralCfg.Default_timezone
		}
		if jsnGeneralCfg.Internal_ttl != nil {
			if self.InternalTtl, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Internal_ttl); err != nil {
				return err
			}
		}
	}

	if jsnListenCfg != nil {
		if jsnListenCfg.Rpc_json != nil {
			self.RPCJSONListen = *jsnListenCfg.Rpc_json
		}
		if jsnListenCfg.Rpc_gob != nil {
			self.RPCGOBListen = *jsnListenCfg.Rpc_gob
		}
		if jsnListenCfg.Http != nil {
			self.HTTPListen = *jsnListenCfg.Http
		}
	}

	if jsnRaterCfg != nil {
		if jsnRaterCfg.Enabled != nil {
			self.RaterEnabled = *jsnRaterCfg.Enabled
		}
		if jsnRaterCfg.Balancer != nil {
			self.RaterBalancer = *jsnRaterCfg.Balancer
		}
		if jsnRaterCfg.Cdrstats != nil {
			self.RaterCdrStats = *jsnRaterCfg.Cdrstats
		}
		if jsnRaterCfg.Historys != nil {
			self.RaterHistoryServer = *jsnRaterCfg.Historys
		}
		if jsnRaterCfg.Pubsubs != nil {
			self.RaterPubSubServer = *jsnRaterCfg.Pubsubs
		}
		if jsnRaterCfg.Aliases != nil {
			self.RaterAliasesServer = *jsnRaterCfg.Aliases
		}
		if jsnRaterCfg.Users != nil {
			self.RaterUserServer = *jsnRaterCfg.Users
		}
	}

	if jsnBalancerCfg != nil && jsnBalancerCfg.Enabled != nil {
		self.BalancerEnabled = *jsnBalancerCfg.Enabled
	}

	if jsnSchedCfg != nil && jsnSchedCfg.Enabled != nil {
		self.SchedulerEnabled = *jsnSchedCfg.Enabled
	}

	if jsnCdrsCfg != nil {
		if jsnCdrsCfg.Enabled != nil {
			self.CDRSEnabled = *jsnCdrsCfg.Enabled
		}
		if jsnCdrsCfg.Extra_fields != nil {
			if self.CDRSExtraFields, err = utils.ParseRSRFieldsFromSlice(*jsnCdrsCfg.Extra_fields); err != nil {
				return err
			}
		}
		if jsnCdrsCfg.Store_cdrs != nil {
			self.CDRSStoreCdrs = *jsnCdrsCfg.Store_cdrs
		}
		if jsnCdrsCfg.Rater != nil {
			self.CDRSRater = *jsnCdrsCfg.Rater
		}
		if jsnCdrsCfg.Pubsubs != nil {
			self.CDRSPubSub = *jsnCdrsCfg.Pubsubs
		}
		if jsnCdrsCfg.Users != nil {
			self.CDRSUsers = *jsnCdrsCfg.Users
		}
		if jsnCdrsCfg.Aliases != nil {
			self.CDRSAliases = *jsnCdrsCfg.Aliases
		}
		if jsnCdrsCfg.Cdrstats != nil {
			self.CDRSStats = *jsnCdrsCfg.Cdrstats
		}
		if jsnCdrsCfg.Cdr_replication != nil {
			self.CDRSCdrReplication = make([]*CdrReplicationCfg, len(*jsnCdrsCfg.Cdr_replication))
			for idx, rplJsonCfg := range *jsnCdrsCfg.Cdr_replication {
				self.CDRSCdrReplication[idx] = new(CdrReplicationCfg)
				if rplJsonCfg.Transport != nil {
					self.CDRSCdrReplication[idx].Transport = *rplJsonCfg.Transport
				}
				if rplJsonCfg.Server != nil {
					self.CDRSCdrReplication[idx].Server = *rplJsonCfg.Server
				}
				if rplJsonCfg.Synchronous != nil {
					self.CDRSCdrReplication[idx].Synchronous = *rplJsonCfg.Synchronous
				}
				if rplJsonCfg.Cdr_filter != nil {
					if self.CDRSCdrReplication[idx].CdrFilter, err = utils.ParseRSRFields(*rplJsonCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
						return err
					}
				}
			}
		}
	}

	if jsnCdrstatsCfg != nil {
		if jsnCdrstatsCfg.Enabled != nil {
			self.CDRStatsEnabled = *jsnCdrstatsCfg.Enabled
			if jsnCdrstatsCfg.Save_Interval != nil {
				if self.CDRStatsSaveInterval, err = utils.ParseDurationWithSecs(*jsnCdrstatsCfg.Save_Interval); err != nil {
					return err
				}
			}
		}
	}

	if jsnCdreCfg != nil {
		if self.CdreProfiles == nil {
			self.CdreProfiles = make(map[string]*CdreConfig)
		}
		for profileName, jsnCdre1Cfg := range jsnCdreCfg {
			if _, hasProfile := self.CdreProfiles[profileName]; !hasProfile { // New profile, create before loading from json
				self.CdreProfiles[profileName] = new(CdreConfig)
				if profileName != utils.META_DEFAULT {
					self.CdreProfiles[profileName] = self.dfltCdreProfile.Clone() // Clone default so we do not inherit pointers
				}
			}
			if err = self.CdreProfiles[profileName].loadFromJsonCfg(jsnCdre1Cfg); err != nil { // Update the existing profile with content from json config
				return err
			}
		}
	}

	if jsnCdrcCfg != nil {
		if self.CdrcProfiles == nil {
			self.CdrcProfiles = make(map[string]map[string]*CdrcConfig)
		}
		for profileName, jsnCrc1Cfg := range jsnCdrcCfg {
			if _, hasDir := self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir]; !hasDir {
				self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir] = make(map[string]*CdrcConfig)
			}
			if _, hasProfile := self.CdrcProfiles[profileName]; !hasProfile {
				if profileName == utils.META_DEFAULT {
					self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName] = new(CdrcConfig)
				} else {
					self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName] = self.dfltCdrcProfile.Clone() // Clone default so we do not inherit pointers
				}
			}
			if err = self.CdrcProfiles[*jsnCrc1Cfg.Cdr_in_dir][profileName].loadFromJsonCfg(jsnCrc1Cfg); err != nil {
				return err
			}
		}
	}

	if jsnSmFsCfg != nil {
		if err := self.SmFsConfig.loadFromJsonCfg(jsnSmFsCfg); err != nil {
			return err
		}
	}

	if jsnSmKamCfg != nil {
		if err := self.SmKamConfig.loadFromJsonCfg(jsnSmKamCfg); err != nil {
			return err
		}
	}

	if jsnSmOsipsCfg != nil {
		if err := self.SmOsipsConfig.loadFromJsonCfg(jsnSmOsipsCfg); err != nil {
			return err
		}
	}

	if jsnHistServCfg != nil {
		if jsnHistServCfg.Enabled != nil {
			self.HistoryServerEnabled = *jsnHistServCfg.Enabled
		}
		if jsnHistServCfg.History_dir != nil {
			self.HistoryDir = *jsnHistServCfg.History_dir
		}
		if jsnHistServCfg.Save_interval != nil {
			if self.HistorySaveInterval, err = utils.ParseDurationWithSecs(*jsnHistServCfg.Save_interval); err != nil {
				return err
			}
		}
	}

	if jsnPubSubServCfg != nil {
		if jsnPubSubServCfg.Enabled != nil {
			self.PubSubServerEnabled = *jsnPubSubServCfg.Enabled
		}
	}

	if jsnAliasesServCfg != nil {
		if jsnAliasesServCfg.Enabled != nil {
			self.AliasesServerEnabled = *jsnAliasesServCfg.Enabled
		}
	}

	if jsnUserServCfg != nil {
		if jsnUserServCfg.Enabled != nil {
			self.UserServerEnabled = *jsnUserServCfg.Enabled
		}
		if jsnUserServCfg.Indexes != nil {
			self.UserServerIndexes = *jsnUserServCfg.Indexes
		}
	}

	if jsnMailerCfg != nil {
		if jsnMailerCfg.Server != nil {
			self.MailerServer = *jsnMailerCfg.Server
		}
		if jsnMailerCfg.Auth_user != nil {
			self.MailerAuthUser = *jsnMailerCfg.Auth_user
		}
		if jsnMailerCfg.Auth_passwd != nil {
			self.MailerAuthPass = *jsnMailerCfg.Auth_passwd
		}
		if jsnMailerCfg.From_address != nil {
			self.MailerFromAddr = *jsnMailerCfg.From_address
		}
	}
	return nil
}
예제 #18
0
func (sm *FSSessionManager) OnChannelPark(ev Event) {
	var maxCallDuration time.Duration // This will be the maximum duration this channel will be allowed to last
	var durInitialized bool
	attrsDC := utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
		Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
	var dcs utils.DerivedChargers
	if err := sm.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
		engine.Logger.Err(fmt.Sprintf("<SessionManager> OnPark: could not get derived charging for event %s: %s", ev.GetUUID(), err.Error()))
		sm.unparkCall(ev.GetUUID(), ev.GetCallDestNr(utils.META_DEFAULT), SYSTEM_ERROR) // We unpark on original destination
		return
	}
	dcs, _ = dcs.AppendDefaultRun()
	for _, dc := range dcs {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := ev.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		startTime, err := ev.GetAnswerTime(PARK_TIME)
		if err != nil {
			engine.Logger.Err("Error parsing answer event start time, using time.Now!")
			startTime = time.Now()
		}
		if ev.MissingParameter() {
			sm.unparkCall(ev.GetUUID(), ev.GetCallDestNr(dc.DestinationField), MISSING_PARAMETER)
			engine.Logger.Err(fmt.Sprintf("Missing parameter for %s", ev.GetUUID()))
			return
		}
		cd := engine.CallDescriptor{
			Direction:   ev.GetDirection(dc.DirectionField),
			Tenant:      ev.GetTenant(dc.TenantField),
			Category:    ev.GetCategory(dc.CategoryField),
			Subject:     ev.GetSubject(dc.SubjectField),
			Account:     ev.GetAccount(dc.AccountField),
			Destination: ev.GetDestination(dc.DestinationField),
			TimeStart:   startTime,
			TimeEnd:     startTime.Add(cfg.SMMaxCallDuration),
		}
		var remainingDurationFloat float64
		err = sm.rater.GetMaxSessionTime(cd, &remainingDurationFloat)
		if err != nil {
			engine.Logger.Err(fmt.Sprintf("Could not get max session time for %s: %v", ev.GetUUID(), err))
			sm.unparkCall(ev.GetUUID(), ev.GetCallDestNr(""), SYSTEM_ERROR) // We unpark on original destination
			return
		}
		remainingDuration := time.Duration(remainingDurationFloat)
		// Set maxCallDuration, smallest out of all forked sessions
		if !durInitialized { // first time we set it /not initialized yet
			maxCallDuration = remainingDuration
			durInitialized = true
		} else if maxCallDuration > remainingDuration {
			maxCallDuration = remainingDuration
		}
	}
	if maxCallDuration <= cfg.SMMinCallDuration {
		//engine.Logger.Info(fmt.Sprintf("Not enough credit for trasferring the call %s for %s.", ev.GetUUID(), cd.GetKey(cd.Subject)))
		sm.unparkCall(ev.GetUUID(), ev.GetCallDestNr(utils.META_DEFAULT), INSUFFICIENT_FUNDS)
		return
	}
	sm.setMaxCallDuration(ev.GetUUID(), maxCallDuration)
	sm.unparkCall(ev.GetUUID(), ev.GetCallDestNr(utils.META_DEFAULT), AUTH_OK)
}
예제 #19
0
func (self *CdrcConfig) loadFromJsonCfg(jsnCfg *CdrcJsonCfg) error {
	if jsnCfg == nil {
		return nil
	}
	var err error
	if jsnCfg.Id != nil {
		self.ID = *jsnCfg.Id
	}
	if jsnCfg.Enabled != nil {
		self.Enabled = *jsnCfg.Enabled
	}
	if jsnCfg.Dry_run != nil {
		self.DryRun = *jsnCfg.Dry_run
	}
	if jsnCfg.Cdrs_conns != nil {
		self.CdrsConns = make([]*HaPoolConfig, len(*jsnCfg.Cdrs_conns))
		for idx, jsnHaCfg := range *jsnCfg.Cdrs_conns {
			self.CdrsConns[idx] = NewDfltHaPoolConfig()
			self.CdrsConns[idx].loadFromJsonCfg(jsnHaCfg)
		}
	}
	if jsnCfg.Cdr_format != nil {
		self.CdrFormat = *jsnCfg.Cdr_format
	}
	if jsnCfg.Field_separator != nil && len(*jsnCfg.Field_separator) > 0 {
		sepStr := *jsnCfg.Field_separator
		self.FieldSeparator = rune(sepStr[0])
	}
	if jsnCfg.Data_usage_multiply_factor != nil {
		self.DataUsageMultiplyFactor = *jsnCfg.Data_usage_multiply_factor
	}
	if jsnCfg.Timezone != nil {
		self.Timezone = *jsnCfg.Timezone
	}
	if jsnCfg.Run_delay != nil {
		self.RunDelay = time.Duration(*jsnCfg.Run_delay) * time.Second
	}
	if jsnCfg.Max_open_files != nil {
		self.MaxOpenFiles = *jsnCfg.Max_open_files
	}
	if jsnCfg.Cdr_in_dir != nil {
		self.CdrInDir = *jsnCfg.Cdr_in_dir
	}
	if jsnCfg.Cdr_out_dir != nil {
		self.CdrOutDir = *jsnCfg.Cdr_out_dir
	}
	if jsnCfg.Failed_calls_prefix != nil {
		self.FailedCallsPrefix = *jsnCfg.Failed_calls_prefix
	}
	if jsnCfg.Cdr_path != nil {
		self.CDRPath = utils.ParseHierarchyPath(*jsnCfg.Cdr_path, "")
	}
	if jsnCfg.Cdr_source_id != nil {
		self.CdrSourceId = *jsnCfg.Cdr_source_id
	}
	if jsnCfg.Cdr_filter != nil {
		if self.CdrFilter, err = utils.ParseRSRFields(*jsnCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Continue_on_success != nil {
		self.ContinueOnSuccess = *jsnCfg.Continue_on_success
	}
	if jsnCfg.Partial_record_cache != nil {
		if self.PartialRecordCache, err = utils.ParseDurationWithSecs(*jsnCfg.Partial_record_cache); err != nil {
			return err
		}
	}
	if jsnCfg.Partial_cache_expiry_action != nil {
		self.PartialCacheExpiryAction = *jsnCfg.Partial_cache_expiry_action
	}
	if jsnCfg.Header_fields != nil {
		if self.HeaderFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Header_fields); err != nil {
			return err
		}
	}
	if jsnCfg.Content_fields != nil {
		if self.ContentFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Content_fields); err != nil {
			return err
		}
	}
	if jsnCfg.Trailer_fields != nil {
		if self.TrailerFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Trailer_fields); err != nil {
			return err
		}
	}
	if jsnCfg.Cache_dump_fields != nil {
		if self.CacheDumpFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Cache_dump_fields); err != nil {
			return err
		}
	}
	return nil
}
예제 #20
0
파일: config.go 프로젝트: eloycoto/cgrates
// Loads from json configuration object, will be used for defaults, config from file and reload, might need lock
func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {

	// Load sections out of JSON config, stop on error
	jsnGeneralCfg, err := jsnCfg.GeneralJsonCfg()
	if err != nil {
		return err
	}

	// Load sections out of JSON config, stop on error
	jsnCacheCfg, err := jsnCfg.CacheJsonCfg()
	if err != nil {
		return err
	}

	jsnListenCfg, err := jsnCfg.ListenJsonCfg()
	if err != nil {
		return err
	}

	jsnTpDbCfg, err := jsnCfg.DbJsonCfg(TPDB_JSN)
	if err != nil {
		return err
	}

	jsnDataDbCfg, err := jsnCfg.DbJsonCfg(DATADB_JSN)
	if err != nil {
		return err
	}

	jsnStorDbCfg, err := jsnCfg.DbJsonCfg(STORDB_JSN)
	if err != nil {
		return err
	}

	jsnBalancerCfg, err := jsnCfg.BalancerJsonCfg()
	if err != nil {
		return err
	}

	jsnRALsCfg, err := jsnCfg.RalsJsonCfg()
	if err != nil {
		return err
	}

	jsnSchedCfg, err := jsnCfg.SchedulerJsonCfg()
	if err != nil {
		return err
	}

	jsnCdrsCfg, err := jsnCfg.CdrsJsonCfg()
	if err != nil {
		return err
	}

	jsnCdrstatsCfg, err := jsnCfg.CdrStatsJsonCfg()
	if err != nil {
		return err
	}

	jsnCdreCfg, err := jsnCfg.CdreJsonCfgs()
	if err != nil {
		return err
	}

	jsnCdrcCfg, err := jsnCfg.CdrcJsonCfg()
	if err != nil {
		return err
	}

	jsnSmGenericCfg, err := jsnCfg.SmGenericJsonCfg()
	if err != nil {
		return err
	}

	jsnSmFsCfg, err := jsnCfg.SmFsJsonCfg()
	if err != nil {
		return err
	}

	jsnSmKamCfg, err := jsnCfg.SmKamJsonCfg()
	if err != nil {
		return err
	}

	jsnSmOsipsCfg, err := jsnCfg.SmOsipsJsonCfg()
	if err != nil {
		return err
	}

	jsnSMAstCfg, err := jsnCfg.SmAsteriskJsonCfg()
	if err != nil {
		return err
	}

	jsnDACfg, err := jsnCfg.DiameterAgentJsonCfg()
	if err != nil {
		return err
	}

	jsnHistServCfg, err := jsnCfg.HistServJsonCfg()
	if err != nil {
		return err
	}

	jsnPubSubServCfg, err := jsnCfg.PubSubServJsonCfg()
	if err != nil {
		return err
	}

	jsnAliasesServCfg, err := jsnCfg.AliasesServJsonCfg()
	if err != nil {
		return err
	}

	jsnUserServCfg, err := jsnCfg.UserServJsonCfg()
	if err != nil {
		return err
	}

	jsnRLSCfg, err := jsnCfg.ResourceLimiterJsonCfg()
	if err != nil {
		return err
	}

	jsnMailerCfg, err := jsnCfg.MailerJsonCfg()
	if err != nil {
		return err
	}

	jsnSureTaxCfg, err := jsnCfg.SureTaxJsonCfg()
	if err != nil {
		return err
	}

	// All good, start populating config variables
	if jsnTpDbCfg != nil {
		if jsnTpDbCfg.Db_type != nil {
			self.TpDbType = *jsnTpDbCfg.Db_type
		}
		if jsnTpDbCfg.Db_host != nil {
			self.TpDbHost = *jsnTpDbCfg.Db_host
		}
		if jsnTpDbCfg.Db_port != nil {
			self.TpDbPort = strconv.Itoa(*jsnTpDbCfg.Db_port)
		}
		if jsnTpDbCfg.Db_name != nil {
			self.TpDbName = *jsnTpDbCfg.Db_name
		}
		if jsnTpDbCfg.Db_user != nil {
			self.TpDbUser = *jsnTpDbCfg.Db_user
		}
		if jsnTpDbCfg.Db_password != nil {
			self.TpDbPass = *jsnTpDbCfg.Db_password
		}
	}

	if jsnDataDbCfg != nil {
		if jsnDataDbCfg.Db_type != nil {
			self.DataDbType = *jsnDataDbCfg.Db_type
		}
		if jsnDataDbCfg.Db_host != nil {
			self.DataDbHost = *jsnDataDbCfg.Db_host
		}
		if jsnDataDbCfg.Db_port != nil {
			self.DataDbPort = strconv.Itoa(*jsnDataDbCfg.Db_port)
		}
		if jsnDataDbCfg.Db_name != nil {
			self.DataDbName = *jsnDataDbCfg.Db_name
		}
		if jsnDataDbCfg.Db_user != nil {
			self.DataDbUser = *jsnDataDbCfg.Db_user
		}
		if jsnDataDbCfg.Db_password != nil {
			self.DataDbPass = *jsnDataDbCfg.Db_password
		}
		if jsnDataDbCfg.Load_history_size != nil {
			self.LoadHistorySize = *jsnDataDbCfg.Load_history_size
		}
	}

	if jsnStorDbCfg != nil {
		if jsnStorDbCfg.Db_type != nil {
			self.StorDBType = *jsnStorDbCfg.Db_type
		}
		if jsnStorDbCfg.Db_host != nil {
			self.StorDBHost = *jsnStorDbCfg.Db_host
		}
		if jsnStorDbCfg.Db_port != nil {
			self.StorDBPort = strconv.Itoa(*jsnStorDbCfg.Db_port)
		}
		if jsnStorDbCfg.Db_name != nil {
			self.StorDBName = *jsnStorDbCfg.Db_name
		}
		if jsnStorDbCfg.Db_user != nil {
			self.StorDBUser = *jsnStorDbCfg.Db_user
		}
		if jsnStorDbCfg.Db_password != nil {
			self.StorDBPass = *jsnStorDbCfg.Db_password
		}
		if jsnStorDbCfg.Max_open_conns != nil {
			self.StorDBMaxOpenConns = *jsnStorDbCfg.Max_open_conns
		}
		if jsnStorDbCfg.Max_idle_conns != nil {
			self.StorDBMaxIdleConns = *jsnStorDbCfg.Max_idle_conns
		}
		if jsnStorDbCfg.Cdrs_indexes != nil {
			self.StorDBCDRSIndexes = *jsnStorDbCfg.Cdrs_indexes
		}
	}

	if jsnGeneralCfg != nil {
		if jsnGeneralCfg.Dbdata_encoding != nil {
			self.DBDataEncoding = *jsnGeneralCfg.Dbdata_encoding
		}
		if jsnGeneralCfg.Default_request_type != nil {
			self.DefaultReqType = *jsnGeneralCfg.Default_request_type
		}
		if jsnGeneralCfg.Default_category != nil {
			self.DefaultCategory = *jsnGeneralCfg.Default_category
		}
		if jsnGeneralCfg.Default_tenant != nil {
			self.DefaultTenant = *jsnGeneralCfg.Default_tenant
		}
		if jsnGeneralCfg.Connect_attempts != nil {
			self.ConnectAttempts = *jsnGeneralCfg.Connect_attempts
		}
		if jsnGeneralCfg.Response_cache_ttl != nil {
			if self.ResponseCacheTTL, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Response_cache_ttl); err != nil {
				return err
			}
		}
		if jsnGeneralCfg.Reconnects != nil {
			self.Reconnects = *jsnGeneralCfg.Reconnects
		}
		if jsnGeneralCfg.Connect_timeout != nil {
			if self.ConnectTimeout, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Connect_timeout); err != nil {
				return err
			}
		}
		if jsnGeneralCfg.Reply_timeout != nil {
			if self.ReplyTimeout, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Reply_timeout); err != nil {
				return err
			}
		}
		if jsnGeneralCfg.Rounding_decimals != nil {
			self.RoundingDecimals = *jsnGeneralCfg.Rounding_decimals
		}
		if jsnGeneralCfg.Http_skip_tls_verify != nil {
			self.HttpSkipTlsVerify = *jsnGeneralCfg.Http_skip_tls_verify
		}
		if jsnGeneralCfg.Tpexport_dir != nil {
			self.TpExportPath = *jsnGeneralCfg.Tpexport_dir
		}
		if jsnGeneralCfg.Httpposter_attempts != nil {
			self.HttpPosterAttempts = *jsnGeneralCfg.Httpposter_attempts
		}
		if jsnGeneralCfg.Http_failed_dir != nil {
			self.HttpFailedDir = *jsnGeneralCfg.Http_failed_dir
		}
		if jsnGeneralCfg.Default_timezone != nil {
			self.DefaultTimezone = *jsnGeneralCfg.Default_timezone
		}
		if jsnGeneralCfg.Internal_ttl != nil {
			if self.InternalTtl, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Internal_ttl); err != nil {
				return err
			}
		}
		if jsnGeneralCfg.Locking_timeout != nil {
			if self.LockingTimeout, err = utils.ParseDurationWithSecs(*jsnGeneralCfg.Locking_timeout); err != nil {
				return err
			}
		}
	}

	if jsnCacheCfg != nil {
		if err := self.CacheConfig.loadFromJsonCfg(jsnCacheCfg); err != nil {
			return err
		}
	}

	if jsnListenCfg != nil {
		if jsnListenCfg.Rpc_json != nil {
			self.RPCJSONListen = *jsnListenCfg.Rpc_json
		}
		if jsnListenCfg.Rpc_gob != nil {
			self.RPCGOBListen = *jsnListenCfg.Rpc_gob
		}
		if jsnListenCfg.Http != nil {
			self.HTTPListen = *jsnListenCfg.Http
		}
	}

	if jsnRALsCfg != nil {
		if jsnRALsCfg.Enabled != nil {
			self.RALsEnabled = *jsnRALsCfg.Enabled
		}
		if jsnRALsCfg.Balancer != nil {
			self.RALsBalancer = *jsnRALsCfg.Balancer
		}
		if jsnRALsCfg.Cdrstats_conns != nil {
			self.RALsCDRStatSConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Cdrstats_conns))
			for idx, jsnHaCfg := range *jsnRALsCfg.Cdrstats_conns {
				self.RALsCDRStatSConns[idx] = NewDfltHaPoolConfig()
				self.RALsCDRStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnRALsCfg.Historys_conns != nil {
			self.RALsHistorySConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Historys_conns))
			for idx, jsnHaCfg := range *jsnRALsCfg.Historys_conns {
				self.RALsHistorySConns[idx] = NewDfltHaPoolConfig()
				self.RALsHistorySConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnRALsCfg.Pubsubs_conns != nil {
			self.RALsPubSubSConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Pubsubs_conns))
			for idx, jsnHaCfg := range *jsnRALsCfg.Pubsubs_conns {
				self.RALsPubSubSConns[idx] = NewDfltHaPoolConfig()
				self.RALsPubSubSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnRALsCfg.Aliases_conns != nil {
			self.RALsAliasSConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Aliases_conns))
			for idx, jsnHaCfg := range *jsnRALsCfg.Aliases_conns {
				self.RALsAliasSConns[idx] = NewDfltHaPoolConfig()
				self.RALsAliasSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnRALsCfg.Users_conns != nil {
			self.RALsUserSConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Users_conns))
			for idx, jsnHaCfg := range *jsnRALsCfg.Users_conns {
				self.RALsUserSConns[idx] = NewDfltHaPoolConfig()
				self.RALsUserSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnRALsCfg.Rp_subject_prefix_matching != nil {
			self.RpSubjectPrefixMatching = *jsnRALsCfg.Rp_subject_prefix_matching
		}
		if jsnRALsCfg.Lcr_subject_prefix_matching != nil {
			self.LcrSubjectPrefixMatching = *jsnRALsCfg.Lcr_subject_prefix_matching
		}
	}

	if jsnBalancerCfg != nil && jsnBalancerCfg.Enabled != nil {
		self.BalancerEnabled = *jsnBalancerCfg.Enabled
	}

	if jsnSchedCfg != nil && jsnSchedCfg.Enabled != nil {
		self.SchedulerEnabled = *jsnSchedCfg.Enabled
	}

	if jsnCdrsCfg != nil {
		if jsnCdrsCfg.Enabled != nil {
			self.CDRSEnabled = *jsnCdrsCfg.Enabled
		}
		if jsnCdrsCfg.Extra_fields != nil {
			if self.CDRSExtraFields, err = utils.ParseRSRFieldsFromSlice(*jsnCdrsCfg.Extra_fields); err != nil {
				return err
			}
		}
		if jsnCdrsCfg.Store_cdrs != nil {
			self.CDRSStoreCdrs = *jsnCdrsCfg.Store_cdrs
		}
		if jsnCdrsCfg.Cdr_account_summary != nil {
			self.CDRScdrAccountSummary = *jsnCdrsCfg.Cdr_account_summary
		}
		if jsnCdrsCfg.Rals_conns != nil {
			self.CDRSRaterConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Rals_conns))
			for idx, jsnHaCfg := range *jsnCdrsCfg.Rals_conns {
				self.CDRSRaterConns[idx] = NewDfltHaPoolConfig()
				self.CDRSRaterConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnCdrsCfg.Pubsubs_conns != nil {
			self.CDRSPubSubSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Pubsubs_conns))
			for idx, jsnHaCfg := range *jsnCdrsCfg.Pubsubs_conns {
				self.CDRSPubSubSConns[idx] = NewDfltHaPoolConfig()
				self.CDRSPubSubSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnCdrsCfg.Users_conns != nil {
			self.CDRSUserSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Users_conns))
			for idx, jsnHaCfg := range *jsnCdrsCfg.Users_conns {
				self.CDRSUserSConns[idx] = NewDfltHaPoolConfig()
				self.CDRSUserSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnCdrsCfg.Aliases_conns != nil {
			self.CDRSAliaseSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Aliases_conns))
			for idx, jsnHaCfg := range *jsnCdrsCfg.Aliases_conns {
				self.CDRSAliaseSConns[idx] = NewDfltHaPoolConfig()
				self.CDRSAliaseSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnCdrsCfg.Cdrstats_conns != nil {
			self.CDRSStatSConns = make([]*HaPoolConfig, len(*jsnCdrsCfg.Cdrstats_conns))
			for idx, jsnHaCfg := range *jsnCdrsCfg.Cdrstats_conns {
				self.CDRSStatSConns[idx] = NewDfltHaPoolConfig()
				self.CDRSStatSConns[idx].loadFromJsonCfg(jsnHaCfg)
			}
		}
		if jsnCdrsCfg.Cdr_replication != nil {
			self.CDRSCdrReplication = make([]*CdrReplicationCfg, len(*jsnCdrsCfg.Cdr_replication))
			for idx, rplJsonCfg := range *jsnCdrsCfg.Cdr_replication {
				self.CDRSCdrReplication[idx] = new(CdrReplicationCfg)
				if rplJsonCfg.Transport != nil {
					self.CDRSCdrReplication[idx].Transport = *rplJsonCfg.Transport
				}
				if rplJsonCfg.Address != nil {
					self.CDRSCdrReplication[idx].Address = *rplJsonCfg.Address
				}
				if rplJsonCfg.Synchronous != nil {
					self.CDRSCdrReplication[idx].Synchronous = *rplJsonCfg.Synchronous
				}
				self.CDRSCdrReplication[idx].Attempts = 1
				if rplJsonCfg.Attempts != nil {
					self.CDRSCdrReplication[idx].Attempts = *rplJsonCfg.Attempts
				}
				if rplJsonCfg.Cdr_filter != nil {
					if self.CDRSCdrReplication[idx].CdrFilter, err = utils.ParseRSRFields(*rplJsonCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
						return err
					}
				}
			}
		}
	}

	if jsnCdrstatsCfg != nil {
		if jsnCdrstatsCfg.Enabled != nil {
			self.CDRStatsEnabled = *jsnCdrstatsCfg.Enabled
			if jsnCdrstatsCfg.Save_Interval != nil {
				if self.CDRStatsSaveInterval, err = utils.ParseDurationWithSecs(*jsnCdrstatsCfg.Save_Interval); err != nil {
					return err
				}
			}
		}
	}

	if jsnCdreCfg != nil {
		if self.CdreProfiles == nil {
			self.CdreProfiles = make(map[string]*CdreConfig)
		}
		for profileName, jsnCdre1Cfg := range jsnCdreCfg {
			if _, hasProfile := self.CdreProfiles[profileName]; !hasProfile { // New profile, create before loading from json
				self.CdreProfiles[profileName] = new(CdreConfig)
				if profileName != utils.META_DEFAULT {
					self.CdreProfiles[profileName] = self.dfltCdreProfile.Clone() // Clone default so we do not inherit pointers
				}
			}
			if err = self.CdreProfiles[profileName].loadFromJsonCfg(jsnCdre1Cfg); err != nil { // Update the existing profile with content from json config
				return err
			}
		}
	}
	if jsnCdrcCfg != nil {
		if self.CdrcProfiles == nil {
			self.CdrcProfiles = make(map[string][]*CdrcConfig)
		}
		for _, jsnCrc1Cfg := range jsnCdrcCfg {
			if jsnCrc1Cfg.Id == nil || *jsnCrc1Cfg.Id == "" {
				return errors.New("CDRC profile without an id")
			}
			if *jsnCrc1Cfg.Id == utils.META_DEFAULT {
				if self.dfltCdrcProfile == nil {
					self.dfltCdrcProfile = new(CdrcConfig)
				}
			}
			indxFound := -1 // Will be different than -1 if an instance with same id will be found
			pathFound := "" // Will be populated with the path where slice of cfgs was found
			var cdrcInstCfg *CdrcConfig
			for path := range self.CdrcProfiles {
				for i := range self.CdrcProfiles[path] {
					if self.CdrcProfiles[path][i].ID == *jsnCrc1Cfg.Id {
						indxFound = i
						pathFound = path
						cdrcInstCfg = self.CdrcProfiles[path][i]
						break
					}
				}
			}
			if cdrcInstCfg == nil {
				cdrcInstCfg = self.dfltCdrcProfile.Clone()
			}
			if err := cdrcInstCfg.loadFromJsonCfg(jsnCrc1Cfg); err != nil {
				return err
			}
			if cdrcInstCfg.CdrInDir == "" {
				return errors.New("CDRC profile without cdr_in_dir")
			}
			if _, hasDir := self.CdrcProfiles[cdrcInstCfg.CdrInDir]; !hasDir {
				self.CdrcProfiles[cdrcInstCfg.CdrInDir] = make([]*CdrcConfig, 0)
			}
			if indxFound != -1 { // Replace previous config so we have inheritance
				self.CdrcProfiles[pathFound][indxFound] = cdrcInstCfg
			} else {
				self.CdrcProfiles[cdrcInstCfg.CdrInDir] = append(self.CdrcProfiles[cdrcInstCfg.CdrInDir], cdrcInstCfg)
			}
		}
	}
	if jsnSmGenericCfg != nil {
		if err := self.SmGenericConfig.loadFromJsonCfg(jsnSmGenericCfg); err != nil {
			return err
		}
	}
	if jsnSmFsCfg != nil {
		if err := self.SmFsConfig.loadFromJsonCfg(jsnSmFsCfg); err != nil {
			return err
		}
	}

	if jsnSmKamCfg != nil {
		if err := self.SmKamConfig.loadFromJsonCfg(jsnSmKamCfg); err != nil {
			return err
		}
	}

	if jsnSmOsipsCfg != nil {
		if err := self.SmOsipsConfig.loadFromJsonCfg(jsnSmOsipsCfg); err != nil {
			return err
		}
	}

	if jsnSMAstCfg != nil {
		if err := self.smAsteriskCfg.loadFromJsonCfg(jsnSMAstCfg); err != nil {
			return err
		}
	}

	if jsnDACfg != nil {
		if err := self.diameterAgentCfg.loadFromJsonCfg(jsnDACfg); err != nil {
			return err
		}
	}

	if jsnHistServCfg != nil {
		if jsnHistServCfg.Enabled != nil {
			self.HistoryServerEnabled = *jsnHistServCfg.Enabled
		}
		if jsnHistServCfg.History_dir != nil {
			self.HistoryDir = *jsnHistServCfg.History_dir
		}
		if jsnHistServCfg.Save_interval != nil {
			if self.HistorySaveInterval, err = utils.ParseDurationWithSecs(*jsnHistServCfg.Save_interval); err != nil {
				return err
			}
		}
	}

	if jsnPubSubServCfg != nil {
		if jsnPubSubServCfg.Enabled != nil {
			self.PubSubServerEnabled = *jsnPubSubServCfg.Enabled
		}
	}

	if jsnAliasesServCfg != nil {
		if jsnAliasesServCfg.Enabled != nil {
			self.AliasesServerEnabled = *jsnAliasesServCfg.Enabled
		}
	}

	if jsnRLSCfg != nil {
		if self.resourceLimiterCfg == nil {
			self.resourceLimiterCfg = new(ResourceLimiterConfig)
		}
		if self.resourceLimiterCfg.loadFromJsonCfg(jsnRLSCfg); err != nil {
			return err
		}
	}

	if jsnUserServCfg != nil {
		if jsnUserServCfg.Enabled != nil {
			self.UserServerEnabled = *jsnUserServCfg.Enabled
		}
		if jsnUserServCfg.Indexes != nil {
			self.UserServerIndexes = *jsnUserServCfg.Indexes
		}
	}

	if jsnMailerCfg != nil {
		if jsnMailerCfg.Server != nil {
			self.MailerServer = *jsnMailerCfg.Server
		}
		if jsnMailerCfg.Auth_user != nil {
			self.MailerAuthUser = *jsnMailerCfg.Auth_user
		}
		if jsnMailerCfg.Auth_password != nil {
			self.MailerAuthPass = *jsnMailerCfg.Auth_password
		}
		if jsnMailerCfg.From_address != nil {
			self.MailerFromAddr = *jsnMailerCfg.From_address
		}
	}

	if jsnSureTaxCfg != nil { // New config for SureTax
		if self.sureTaxCfg, err = NewSureTaxCfgWithDefaults(); err != nil {
			return err
		}
		if err := self.sureTaxCfg.loadFromJsonCfg(jsnSureTaxCfg); err != nil {
			return err
		}
	}

	return nil
}
예제 #21
0
func (self *Mediator) RateCdr(storedCdr *utils.StoredCdr, sendToStats bool) error {
	storedCdr.MediationRunId = utils.DEFAULT_RUNID
	cdrRuns := []*utils.StoredCdr{storedCdr} // Start with initial storCdr, will add here all to be mediated
	attrsDC := utils.AttrDerivedChargers{Tenant: storedCdr.Tenant, Category: storedCdr.Category, Direction: storedCdr.Direction,
		Account: storedCdr.Account, Subject: storedCdr.Subject}
	var dcs utils.DerivedChargers
	if err := self.connector.GetDerivedChargers(attrsDC, &dcs); err != nil {
		errText := fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", storedCdr.CgrId, err.Error())
		Logger.Err(errText)
		return errors.New(errText)
	}
	for _, dc := range dcs {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := storedCdr.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		dcReqTypeFld, _ := utils.NewRSRField(dc.ReqTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		forkedCdr, err := storedCdr.ForkCdr(dc.RunId, dcReqTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld, dcSTimeFld, dcATimeFld, dcDurFld,
			[]*utils.RSRField{}, true)
		if err != nil { // Errors on fork, cannot calculate further, write that into db for later analysis
			self.cdrDb.SetRatedCdr(&utils.StoredCdr{CgrId: storedCdr.CgrId, CdrSource: utils.FORKED_CDR, MediationRunId: dc.RunId, Cost: -1},
				err.Error()) // Cannot fork CDR, important just runid and error
			continue
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	for _, cdr := range cdrRuns {
		extraInfo := ""
		if err := self.rateCDR(cdr); err != nil {
			extraInfo = err.Error()
		}
		if !self.cgrCfg.MediatorStoreDisable {
			if err := self.cdrDb.SetRatedCdr(cdr, extraInfo); err != nil {
				Logger.Err(fmt.Sprintf("<Mediator> Could not record cost for cgrid: <%s>, ERROR: <%s>, cost: %f, extraInfo: %s",
					cdr.CgrId, err.Error(), cdr.Cost, extraInfo))
			}
		}
		if sendToStats && self.stats != nil { // We send to stats only after saving to db since there are chances we cannot store and then no way to reproduce stats offline
			go func(cdr *utils.StoredCdr) { // Pass it by value since the variable will be overwritten by for
				if err := self.stats.AppendCDR(cdr, nil); err != nil {
					Logger.Err(fmt.Sprintf("Could not append cdr to stats (mediator): %s", err.Error()))
				}
			}(cdr)
		}
	}
	return nil
}
예제 #22
0
func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
	defaultTemplate := map[string]utils.RSRFields{
		"TOR":            utils.ParseRSRFieldsMustCompile("balance_type", utils.INFIELD_SEP),
		"CdrHost":        utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP),
		"Direction":      utils.ParseRSRFieldsMustCompile("direction", utils.INFIELD_SEP),
		"ReqType":        utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP),
		"Tenant":         utils.ParseRSRFieldsMustCompile("tenant", utils.INFIELD_SEP),
		"Account":        utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
		"Subject":        utils.ParseRSRFieldsMustCompile("account", utils.INFIELD_SEP),
		"Cost":           utils.ParseRSRFieldsMustCompile("balance_value", utils.INFIELD_SEP),
		"MediationRunId": utils.ParseRSRFieldsMustCompile("^"+utils.META_DEFAULT, utils.INFIELD_SEP),
	}
	template := make(map[string]string)

	// overwrite default template
	if a.ExtraParameters != "" {
		if err = json.Unmarshal([]byte(a.ExtraParameters), &template); err != nil {
			return
		}
		for field, rsr := range template {
			defaultTemplate[field], err = utils.ParseRSRFields(rsr, utils.INFIELD_SEP)
			if err != nil {
				return err
			}
		}
	}

	// set stored cdr values
	var cdrs []*StoredCdr
	for _, action := range acs {
		if !utils.IsSliceMember([]string{DEBIT, DEBIT_RESET}, action.ActionType) || action.Balance == nil {
			continue // Only log specific actions
		}
		cdr := &StoredCdr{CdrSource: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), AccId: utils.GenUUID(), ExtraFields: make(map[string]string)}
		cdr.CgrId = utils.Sha1(cdr.AccId, cdr.SetupTime.String())
		cdr.Usage = time.Duration(1) * time.Second
		elem := reflect.ValueOf(cdr).Elem()
		for key, rsrFlds := range defaultTemplate {
			parsedValue := parseTemplateValue(rsrFlds, acc, action)
			field := elem.FieldByName(key)
			if field.IsValid() && field.CanSet() {
				switch field.Kind() {
				case reflect.Float64:
					value, err := strconv.ParseFloat(parsedValue, 64)
					if err != nil {
						continue
					}
					field.SetFloat(value)
				case reflect.String:
					field.SetString(parsedValue)
				}
			} else { // invalid fields go in extraFields of CDR
				cdr.ExtraFields[key] = parsedValue
			}
		}
		//utils.Logger.Debug(fmt.Sprintf("account: %+v, action: %+v, balance: %+v", acc, action, action.Balance))
		cdrs = append(cdrs, cdr)
		if cdrStorage == nil { // Only save if the cdrStorage is defined
			continue
		}
		if err := cdrStorage.SetCdr(cdr); err != nil {
			return err
		}
		if err := cdrStorage.SetRatedCdr(cdr); err != nil {
			return err
		}
		// FixMe
		//if err := cdrStorage.LogCallCost(); err != nil {
		//	return err
		//}

	}

	b, _ := json.Marshal(cdrs)
	a.ExpirationString = string(b) // testing purpose only
	return
}
예제 #23
0
func TestCdreCfgClone(t *testing.T) {
	cgrIdRsrs, _ := utils.ParseRSRFields("cgrid", utils.INFIELD_SEP)
	runIdRsrs, _ := utils.ParseRSRFields("mediation_runid", utils.INFIELD_SEP)
	emptyFields := []*CfgCdrField{}
	initContentFlds := []*CfgCdrField{
		&CfgCdrField{Tag: "CgrId",
			Type:       "cdrfield",
			CdrFieldId: "cgrid",
			Value:      cgrIdRsrs},
		&CfgCdrField{Tag: "RunId",
			Type:       "cdrfield",
			CdrFieldId: "mediation_runid",
			Value:      runIdRsrs},
	}
	initCdreCfg := &CdreConfig{
		CdrFormat:               "csv",
		FieldSeparator:          rune(','),
		DataUsageMultiplyFactor: 1.0,
		CostMultiplyFactor:      1.0,
		CostRoundingDecimals:    -1,
		CostShiftDigits:         0,
		MaskDestId:              "MASKED_DESTINATIONS",
		MaskLength:              0,
		ExportDir:               "/var/log/cgrates/cdre",
		ContentFields:           initContentFlds,
	}
	eClnContentFlds := []*CfgCdrField{
		&CfgCdrField{Tag: "CgrId",
			Type:       "cdrfield",
			CdrFieldId: "cgrid",
			Value:      cgrIdRsrs},
		&CfgCdrField{Tag: "RunId",
			Type:       "cdrfield",
			CdrFieldId: "mediation_runid",
			Value:      runIdRsrs},
	}
	eClnCdreCfg := &CdreConfig{
		CdrFormat:               "csv",
		FieldSeparator:          rune(','),
		DataUsageMultiplyFactor: 1.0,
		CostMultiplyFactor:      1.0,
		CostRoundingDecimals:    -1,
		CostShiftDigits:         0,
		MaskDestId:              "MASKED_DESTINATIONS",
		MaskLength:              0,
		ExportDir:               "/var/log/cgrates/cdre",
		HeaderFields:            emptyFields,
		ContentFields:           eClnContentFlds,
		TrailerFields:           emptyFields,
	}
	clnCdreCfg := initCdreCfg.Clone()
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) {
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	initCdreCfg.DataUsageMultiplyFactor = 1024.0
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	initContentFlds[0].Tag = "Destination"
	if !reflect.DeepEqual(eClnCdreCfg, clnCdreCfg) { // MOdifying a field after clone should not affect cloned instance
		t.Errorf("Cloned result: %+v", clnCdreCfg)
	}
	clnCdreCfg.CostShiftDigits = 2
	if initCdreCfg.CostShiftDigits != 0 {
		t.Error("Unexpected CostShiftDigits: ", initCdreCfg.CostShiftDigits)
	}
	clnCdreCfg.ContentFields[0].CdrFieldId = "destination"
	if initCdreCfg.ContentFields[0].CdrFieldId != "cgrid" {
		t.Error("Unexpected change of CdrFieldId: ", initCdreCfg.ContentFields[0].CdrFieldId)
	}

}
예제 #24
0
파일: responder.go 프로젝트: iwada/cgrates
// Returns MaxSessionTime for an event received in SessionManager, considering DerivedCharging for it
func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error {
	if rs.Bal != nil {
		return errors.New("unsupported method on the balancer")
	}
	cacheKey := utils.GET_DERIV_MAX_SESS_TIME + ev.CGRID + ev.RunID
	if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil {
		if item.Value != nil {
			*reply = *(item.Value.(*float64))
		}
		return item.Err
	}
	if ev.Subject == "" {
		ev.Subject = ev.Account
	}
	// replace user profile fields
	if err := LoadUserProfile(ev, utils.EXTRA_FIELDS); err != nil {
		rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
		return err
	}
	// replace aliases
	if err := LoadAlias(
		&AttrMatchingAlias{
			Destination: ev.Destination,
			Direction:   ev.Direction,
			Tenant:      ev.Tenant,
			Category:    ev.Category,
			Account:     ev.Account,
			Subject:     ev.Subject,
			Context:     utils.ALIAS_CONTEXT_RATING,
		}, ev, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
		rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
		return err
	}

	maxCallDuration := -1.0
	attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
		Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
	dcs := &utils.DerivedChargers{}
	if err := rs.GetDerivedChargers(attrsDC, dcs); err != nil {
		rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
		return err
	}
	dcs, _ = dcs.AppendDefaultRun()
	for _, dc := range dcs.Chargers {
		if utils.IsSliceMember([]string{utils.META_RATED, utils.RATED}, ev.GetReqType(dc.RequestTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
			continue
		}
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if !dcRunFilter.FilterPasses(ev.FieldAsString(dcRunFilter)) {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		startTime, err := ev.GetSetupTime(utils.META_DEFAULT, rs.Timezone)
		if err != nil {
			rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
			return err
		}
		usage, err := ev.GetDuration(utils.META_DEFAULT)
		if err != nil {
			rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
			return err
		}
		if usage == 0 {
			usage = config.CgrConfig().MaxCallDuration
		}
		cd := &CallDescriptor{
			CgrID:       ev.GetCgrId(rs.Timezone),
			RunID:       dc.RunID,
			TOR:         ev.ToR,
			Direction:   ev.GetDirection(dc.DirectionField),
			Tenant:      ev.GetTenant(dc.TenantField),
			Category:    ev.GetCategory(dc.CategoryField),
			Subject:     ev.GetSubject(dc.SubjectField),
			Account:     ev.GetAccount(dc.AccountField),
			Destination: ev.GetDestination(dc.DestinationField),
			TimeStart:   startTime,
			TimeEnd:     startTime.Add(usage),
		}
		var remainingDuration float64
		err = rs.GetMaxSessionTime(cd, &remainingDuration)
		if err != nil {
			*reply = 0
			rs.getCache().Cache(cacheKey, &CacheItem{Err: err})
			return err
		}
		if utils.IsSliceMember([]string{utils.META_POSTPAID, utils.POSTPAID}, ev.GetReqType(dc.RequestTypeField)) {
			// Only consider prepaid and pseudoprepaid for MaxSessionTime, do it here for unauthorized destination error check
			continue
		}
		// Set maxCallDuration, smallest out of all forked sessions
		if maxCallDuration == -1.0 { // first time we set it /not initialized yet
			maxCallDuration = remainingDuration
		} else if maxCallDuration > remainingDuration {
			maxCallDuration = remainingDuration
		}
	}
	rs.getCache().Cache(cacheKey, &CacheItem{Value: maxCallDuration})
	*reply = maxCallDuration
	return nil
}
예제 #25
0
// Process Authorize request from OpenSIPS and communicate back maxdur
func (osm *OsipsSessionManager) OnAuthorize(osipsDagram *osipsdagram.OsipsEvent) {
	ev, _ := NewOsipsEvent(osipsDagram)
	if ev.MissingParameter() {
		cmdNotify := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_notify\n%s\n2\n\n", ev.GetUUID(), utils.ERR_MANDATORY_IE_MISSING)
		if reply, err := osm.miConn.SendCommand([]byte(cmdNotify)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
			engine.Logger.Err(fmt.Sprintf("Failed setting cgr_notify variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
		}
		return
	}
	var maxCallDuration time.Duration // This will be the maximum duration this channel will be allowed to last
	var durInitialized bool
	attrsDC := utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
		Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
	var dcs utils.DerivedChargers
	if err := osm.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
		engine.Logger.Err(fmt.Sprintf("<SM-OpenSIPS> OnAuthorize: could not get derived charging for event %s: %s", ev.GetUUID(), err.Error()))
		cmdNotify := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_notify\n%s\n2\n\n", ev.GetUUID(), utils.ERR_SERVER_ERROR)
		if reply, err := osm.miConn.SendCommand([]byte(cmdNotify)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
			engine.Logger.Err(fmt.Sprintf("Failed setting cgr_notify variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
		}
		return
	}
	dcs, _ = dcs.AppendDefaultRun()
	for _, dc := range dcs {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := ev.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		startTime, err := ev.GetSetupTime(utils.META_DEFAULT)
		if err != nil {
			engine.Logger.Err("Error parsing answer event start time, using time.Now!")
			startTime = time.Now()
		}
		cd := engine.CallDescriptor{
			Direction:   ev.GetDirection(dc.DirectionField),
			Tenant:      ev.GetTenant(dc.TenantField),
			Category:    ev.GetCategory(dc.CategoryField),
			Subject:     ev.GetSubject(dc.SubjectField),
			Account:     ev.GetAccount(dc.AccountField),
			Destination: ev.GetDestination(dc.DestinationField),
			TimeStart:   startTime,
			TimeEnd:     startTime.Add(osm.cgrCfg.SMMaxCallDuration),
		}
		var remainingDurationFloat float64
		err = osm.rater.GetMaxSessionTime(cd, &remainingDurationFloat)
		if err != nil {
			engine.Logger.Err(fmt.Sprintf("Could not get max session time for %s: %v", ev.GetUUID(), err))
			cmdNotify := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_notify\n%s\n2\n\n", ev.GetUUID(), utils.ERR_SERVER_ERROR)
			if reply, err := osm.miConn.SendCommand([]byte(cmdNotify)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
				engine.Logger.Err(fmt.Sprintf("Failed setting cgr_notify variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
			}
			return
		}
		remainingDuration := time.Duration(remainingDurationFloat)
		// Set maxCallDuration, smallest out of all forked sessions
		if !durInitialized { // first time we set it /not initialized yet
			maxCallDuration = remainingDuration
			durInitialized = true
		} else if maxCallDuration > remainingDuration {
			maxCallDuration = remainingDuration
		}
	}
	if maxCallDuration <= osm.cgrCfg.SMMinCallDuration {
		cmdNotify := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_notify\n%s\n2\n\n", ev.GetUUID(), OSIPS_INSUFFICIENT_FUNDS)
		if reply, err := osm.miConn.SendCommand([]byte(cmdNotify)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
			engine.Logger.Err(fmt.Sprintf("Failed setting cgr_notify variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
		}
		return
	}
	cmdMaxDur := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_maxdur\n%d\n\n", ev.GetUUID(), int(maxCallDuration.Seconds()))
	if reply, err := osm.miConn.SendCommand([]byte(cmdMaxDur)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
		engine.Logger.Err(fmt.Sprintf("Failed setting cgr_maxdur variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
	}
	cmdNotify := fmt.Sprintf(":cache_store:\nlocal\n%s/cgr_notify\n%s\n", ev.GetUUID(), OSIPS_AUTH_OK)
	if reply, err := osm.miConn.SendCommand([]byte(cmdNotify)); err != nil || !bytes.HasPrefix(reply, []byte("200 OK")) {
		engine.Logger.Err(fmt.Sprintf("Failed setting cgr_notify variable for accid: %s, err: %v, reply: %s", ev.GetUUID(), err, string(reply)))
	}
}
예제 #26
0
// Loads/re-loads data from json config object
func (self *SureTaxCfg) loadFromJsonCfg(jsnCfg *SureTaxJsonCfg) error {
	var err error
	if jsnCfg.Url != nil {
		self.Url = *jsnCfg.Url
	}
	if jsnCfg.Client_number != nil {
		self.ClientNumber = *jsnCfg.Client_number
	}
	if jsnCfg.Validation_key != nil {
		self.ValidationKey = *jsnCfg.Validation_key
	}
	if jsnCfg.Business_unit != nil {
		self.BusinessUnit = *jsnCfg.Business_unit
	}
	if jsnCfg.Timezone != nil {
		if self.Timezone, err = time.LoadLocation(*jsnCfg.Timezone); err != nil {
			return err
		}
	}
	if jsnCfg.Include_local_cost != nil {
		self.IncludeLocalCost = *jsnCfg.Include_local_cost
	}
	if jsnCfg.Return_file_code != nil {
		self.ReturnFileCode = *jsnCfg.Return_file_code
	}
	if jsnCfg.Response_group != nil {
		self.ResponseGroup = *jsnCfg.Response_group
	}
	if jsnCfg.Response_type != nil {
		self.ResponseType = *jsnCfg.Response_type
	}
	if jsnCfg.Regulatory_code != nil {
		self.RegulatoryCode = *jsnCfg.Regulatory_code
	}
	if jsnCfg.Client_tracking != nil {
		if self.ClientTracking, err = utils.ParseRSRFields(*jsnCfg.Client_tracking, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Customer_number != nil {
		if self.CustomerNumber, err = utils.ParseRSRFields(*jsnCfg.Customer_number, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Orig_number != nil {
		if self.OrigNumber, err = utils.ParseRSRFields(*jsnCfg.Orig_number, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Term_number != nil {
		if self.TermNumber, err = utils.ParseRSRFields(*jsnCfg.Term_number, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Bill_to_number != nil {
		if self.BillToNumber, err = utils.ParseRSRFields(*jsnCfg.Bill_to_number, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Zipcode != nil {
		if self.Zipcode, err = utils.ParseRSRFields(*jsnCfg.Zipcode, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Plus4 != nil {
		if self.Plus4, err = utils.ParseRSRFields(*jsnCfg.Plus4, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.P2PZipcode != nil {
		if self.P2PZipcode, err = utils.ParseRSRFields(*jsnCfg.P2PZipcode, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.P2PPlus4 != nil {
		if self.P2PPlus4, err = utils.ParseRSRFields(*jsnCfg.P2PPlus4, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Units != nil {
		if self.Units, err = utils.ParseRSRFields(*jsnCfg.Units, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Unit_type != nil {
		if self.UnitType, err = utils.ParseRSRFields(*jsnCfg.Unit_type, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Tax_included != nil {
		if self.TaxIncluded, err = utils.ParseRSRFields(*jsnCfg.Tax_included, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Tax_situs_rule != nil {
		if self.TaxSitusRule, err = utils.ParseRSRFields(*jsnCfg.Tax_situs_rule, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Trans_type_code != nil {
		if self.TransTypeCode, err = utils.ParseRSRFields(*jsnCfg.Trans_type_code, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Sales_type_code != nil {
		if self.SalesTypeCode, err = utils.ParseRSRFields(*jsnCfg.Sales_type_code, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Tax_exemption_code_list != nil {
		if self.TaxExemptionCodeList, err = utils.ParseRSRFields(*jsnCfg.Tax_exemption_code_list, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	return nil
}
예제 #27
0
파일: cdrs.go 프로젝트: eloycoto/cgrates
func (self *CdrServer) deriveCdrs(cdr *CDR) ([]*CDR, error) {
	dfltCDRRun := cdr.Clone()
	cdrRuns := []*CDR{dfltCDRRun}
	if cdr.RunID != utils.MetaRaw { // Only derive *raw CDRs
		return cdrRuns, nil
	}
	dfltCDRRun.RunID = utils.META_DEFAULT // Rewrite *raw with *default since we have it as first run
	if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil {
		return nil, err
	}
	if err := LoadAlias(&AttrMatchingAlias{
		Destination: cdr.Destination,
		Direction:   cdr.Direction,
		Tenant:      cdr.Tenant,
		Category:    cdr.Category,
		Account:     cdr.Account,
		Subject:     cdr.Subject,
		Context:     utils.ALIAS_CONTEXT_RATING,
	}, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound {
		return nil, err
	}
	attrsDC := &utils.AttrDerivedChargers{Tenant: cdr.Tenant, Category: cdr.Category, Direction: cdr.Direction,
		Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination}
	var dcs utils.DerivedChargers
	if err := self.rals.Call("Responder.GetDerivedChargers", attrsDC, &dcs); err != nil {
		utils.Logger.Err(fmt.Sprintf("Could not get derived charging for cgrid %s, error: %s", cdr.CGRID, err.Error()))
		return nil, err
	}
	for _, dc := range dcs.Chargers {
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if !dcRunFilter.FilterPasses(cdr.FieldAsString(dcRunFilter)) {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		dcRequestTypeFld, _ := utils.NewRSRField(dc.RequestTypeField)
		dcDirFld, _ := utils.NewRSRField(dc.DirectionField)
		dcTenantFld, _ := utils.NewRSRField(dc.TenantField)
		dcCategoryFld, _ := utils.NewRSRField(dc.CategoryField)
		dcAcntFld, _ := utils.NewRSRField(dc.AccountField)
		dcSubjFld, _ := utils.NewRSRField(dc.SubjectField)
		dcDstFld, _ := utils.NewRSRField(dc.DestinationField)
		dcSTimeFld, _ := utils.NewRSRField(dc.SetupTimeField)
		dcPddFld, _ := utils.NewRSRField(dc.PDDField)
		dcATimeFld, _ := utils.NewRSRField(dc.AnswerTimeField)
		dcDurFld, _ := utils.NewRSRField(dc.UsageField)
		dcSupplFld, _ := utils.NewRSRField(dc.SupplierField)
		dcDCauseFld, _ := utils.NewRSRField(dc.DisconnectCauseField)
		dcRatedFld, _ := utils.NewRSRField(dc.RatedField)
		dcCostFld, _ := utils.NewRSRField(dc.CostField)
		forkedCdr, err := cdr.ForkCdr(dc.RunID, dcRequestTypeFld, dcDirFld, dcTenantFld, dcCategoryFld, dcAcntFld, dcSubjFld, dcDstFld,
			dcSTimeFld, dcPddFld, dcATimeFld, dcDurFld, dcSupplFld, dcDCauseFld, dcRatedFld, dcCostFld, []*utils.RSRField{}, true, self.cgrCfg.DefaultTimezone)
		if err != nil {
			utils.Logger.Err(fmt.Sprintf("Could not fork CGR with cgrid %s, run: %s, error: %s", cdr.CGRID, dc.RunID, err.Error()))
			continue // do not add it to the forked CDR list
		}
		if !forkedCdr.Rated {
			forkedCdr.Cost = -1.0 // Make sure that un-rated CDRs start with Cost -1
		}
		cdrRuns = append(cdrRuns, forkedCdr)
	}
	return cdrRuns, nil
}
예제 #28
0
func (self *CdrcConfig) loadFromJsonCfg(jsnCfg *CdrcJsonCfg) error {
	if jsnCfg == nil {
		return nil
	}
	var err error
	if jsnCfg.Enabled != nil {
		self.Enabled = *jsnCfg.Enabled
	}
	if jsnCfg.Dry_run != nil {
		self.DryRun = *jsnCfg.Dry_run
	}
	if jsnCfg.Cdrs != nil {
		self.Cdrs = *jsnCfg.Cdrs
	}
	if jsnCfg.Cdr_format != nil {
		self.CdrFormat = *jsnCfg.Cdr_format
	}
	if jsnCfg.Field_separator != nil && len(*jsnCfg.Field_separator) > 0 {
		sepStr := *jsnCfg.Field_separator
		self.FieldSeparator = rune(sepStr[0])
	}
	if jsnCfg.Data_usage_multiply_factor != nil {
		self.DataUsageMultiplyFactor = *jsnCfg.Data_usage_multiply_factor
	}
	if jsnCfg.Timezone != nil {
		self.Timezone = *jsnCfg.Timezone
	}
	if jsnCfg.Run_delay != nil {
		self.RunDelay = time.Duration(*jsnCfg.Run_delay) * time.Second
	}
	if jsnCfg.Max_open_files != nil {
		self.MaxOpenFiles = *jsnCfg.Max_open_files
	}
	if jsnCfg.Cdr_in_dir != nil {
		self.CdrInDir = *jsnCfg.Cdr_in_dir
	}
	if jsnCfg.Cdr_out_dir != nil {
		self.CdrOutDir = *jsnCfg.Cdr_out_dir
	}
	if jsnCfg.Failed_calls_prefix != nil {
		self.FailedCallsPrefix = *jsnCfg.Failed_calls_prefix
	}
	if jsnCfg.Cdr_source_id != nil {
		self.CdrSourceId = *jsnCfg.Cdr_source_id
	}
	if jsnCfg.Cdr_filter != nil {
		if self.CdrFilter, err = utils.ParseRSRFields(*jsnCfg.Cdr_filter, utils.INFIELD_SEP); err != nil {
			return err
		}
	}
	if jsnCfg.Continue_on_success != nil {
		self.ContinueOnSuccess = *jsnCfg.Continue_on_success
	}
	if jsnCfg.Partial_record_cache != nil {
		if self.PartialRecordCache, err = utils.ParseDurationWithSecs(*jsnCfg.Partial_record_cache); err != nil {
			return err
		}
	}
	if jsnCfg.Header_fields != nil {
		if self.HeaderFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Header_fields); err != nil {
			return err
		}
	}
	if jsnCfg.Content_fields != nil {
		if self.ContentFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Content_fields); err != nil {
			return err
		}
	}
	if jsnCfg.Trailer_fields != nil {
		if self.TrailerFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Trailer_fields); err != nil {
			return err
		}
	}
	return nil
}
예제 #29
0
// Returns MaxSessionTime for an event received in SessionManager, considering DerivedCharging for it
func (rs *Responder) GetDerivedMaxSessionTime(ev *StoredCdr, reply *float64) error {
	if rs.Bal != nil {
		return errors.New("unsupported method on the balancer")
	}
	if ev.Subject == "" {
		ev.Subject = ev.Account
	}
	if upData, err := LoadUserProfile(ev, "ExtraFields"); err != nil {
		return err
	} else {
		udRcv := upData.(*StoredCdr)
		*ev = *udRcv
	}
	maxCallDuration := -1.0
	attrsDC := &utils.AttrDerivedChargers{Tenant: ev.GetTenant(utils.META_DEFAULT), Category: ev.GetCategory(utils.META_DEFAULT), Direction: ev.GetDirection(utils.META_DEFAULT),
		Account: ev.GetAccount(utils.META_DEFAULT), Subject: ev.GetSubject(utils.META_DEFAULT)}
	var dcs utils.DerivedChargers
	if err := rs.GetDerivedChargers(attrsDC, &dcs); err != nil {
		return err
	}
	dcs, _ = dcs.AppendDefaultRun()
	for _, dc := range dcs {
		if utils.IsSliceMember([]string{utils.META_RATED, utils.RATED}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
			continue
		}
		runFilters, _ := utils.ParseRSRFields(dc.RunFilters, utils.INFIELD_SEP)
		matchingAllFilters := true
		for _, dcRunFilter := range runFilters {
			if fltrPass, _ := ev.PassesFieldFilter(dcRunFilter); !fltrPass {
				matchingAllFilters = false
				break
			}
		}
		if !matchingAllFilters { // Do not process the derived charger further if not all filters were matched
			continue
		}
		startTime, err := ev.GetSetupTime(utils.META_DEFAULT, rs.Timezone)
		if err != nil {
			return err
		}
		usage, err := ev.GetDuration(utils.META_DEFAULT)
		if err != nil {
			return err
		}
		if usage == 0 {
			usage = config.CgrConfig().MaxCallDuration
		}
		cd := &CallDescriptor{
			Direction:   ev.GetDirection(dc.DirectionField),
			Tenant:      ev.GetTenant(dc.TenantField),
			Category:    ev.GetCategory(dc.CategoryField),
			Subject:     ev.GetSubject(dc.SubjectField),
			Account:     ev.GetAccount(dc.AccountField),
			Destination: ev.GetDestination(dc.DestinationField),
			TimeStart:   startTime,
			TimeEnd:     startTime.Add(usage),
		}
		var remainingDuration float64
		err = rs.GetMaxSessionTime(cd, &remainingDuration)
		if err != nil {
			*reply = 0
			return err
		}
		if utils.IsSliceMember([]string{utils.META_POSTPAID, utils.POSTPAID}, ev.GetReqType(dc.ReqTypeField)) { // Only consider prepaid and pseudoprepaid for MaxSessionTime
			continue
		}
		// Set maxCallDuration, smallest out of all forked sessions
		if maxCallDuration == -1.0 { // first time we set it /not initialized yet
			maxCallDuration = remainingDuration
		} else if maxCallDuration > remainingDuration {
			maxCallDuration = remainingDuration
		}
	}
	*reply = maxCallDuration
	return nil
}
예제 #30
0
파일: action.go 프로젝트: cgrates/cgrates
func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) (err error) {
	defaultTemplate := map[string]utils.RSRFields{
		utils.TOR:       utils.ParseRSRFieldsMustCompile("BalanceType", utils.INFIELD_SEP),
		utils.CDRHOST:   utils.ParseRSRFieldsMustCompile("^127.0.0.1", utils.INFIELD_SEP),
		utils.DIRECTION: utils.ParseRSRFieldsMustCompile("Directions", utils.INFIELD_SEP),
		utils.REQTYPE:   utils.ParseRSRFieldsMustCompile("^"+utils.META_PREPAID, utils.INFIELD_SEP),
		utils.TENANT:    utils.ParseRSRFieldsMustCompile(utils.TENANT, utils.INFIELD_SEP),
		utils.ACCOUNT:   utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP),
		utils.SUBJECT:   utils.ParseRSRFieldsMustCompile(utils.ACCOUNT, utils.INFIELD_SEP),
		utils.COST:      utils.ParseRSRFieldsMustCompile("ActionValue", utils.INFIELD_SEP),
	}
	template := make(map[string]string)

	// overwrite default template
	if a.ExtraParameters != "" {
		if err = json.Unmarshal([]byte(a.ExtraParameters), &template); err != nil {
			return
		}
		for field, rsr := range template {
			defaultTemplate[field], err = utils.ParseRSRFields(rsr, utils.INFIELD_SEP)
			if err != nil {
				return err
			}
		}
	}

	// set stored cdr values
	var cdrs []*CDR
	for _, action := range acs {
		if !utils.IsSliceMember([]string{DEBIT, DEBIT_RESET, TOPUP, TOPUP_RESET}, action.ActionType) || action.Balance == nil {
			continue // Only log specific actions
		}
		cdr := &CDR{RunID: action.ActionType, Source: CDRLOG, SetupTime: time.Now(), AnswerTime: time.Now(), OriginID: utils.GenUUID(), ExtraFields: make(map[string]string)}
		cdr.CGRID = utils.Sha1(cdr.OriginID, cdr.SetupTime.String())
		cdr.Usage = time.Duration(1) * time.Second
		elem := reflect.ValueOf(cdr).Elem()
		for key, rsrFlds := range defaultTemplate {
			parsedValue := parseTemplateValue(rsrFlds, acc, action)
			field := elem.FieldByName(key)
			if field.IsValid() && field.CanSet() {
				switch field.Kind() {
				case reflect.Float64:
					value, err := strconv.ParseFloat(parsedValue, 64)
					if err != nil {
						continue
					}
					field.SetFloat(value)
				case reflect.String:
					field.SetString(parsedValue)
				}
			} else { // invalid fields go in extraFields of CDR
				cdr.ExtraFields[key] = parsedValue
			}
		}
		cdrs = append(cdrs, cdr)
		if cdrStorage == nil { // Only save if the cdrStorage is defined
			continue
		}
		if err := cdrStorage.SetCDR(cdr, true); err != nil {
			return err
		}
	}
	b, _ := json.Marshal(cdrs)
	a.ExpirationString = string(b) // testing purpose only
	return
}