FS Event parsing cgr_category instead of cgr_tor, zero FS configuration support for passive billing scenarios

This commit is contained in:
DanB
2014-08-05 16:03:02 +02:00
parent 33e3f3fd66
commit 71a932e343
9 changed files with 112 additions and 47 deletions

View File

@@ -43,4 +43,5 @@ type Event interface {
MissingParameter() bool
ParseEventValue(*utils.RSRField) string
PassesFieldFilter(*utils.RSRField) (bool, string)
AsStoredCdr() *utils.StoredCdr
}

View File

@@ -41,7 +41,7 @@ const (
ACCOUNT = "variable_cgr_account"
DESTINATION = "variable_cgr_destination"
REQTYPE = "variable_cgr_reqtype" //prepaid or postpaid
Category = "variable_cgr_tor"
Category = "variable_cgr_category"
UUID = "Unique-ID" // -Unique ID for this call leg
CSTMID = "variable_cgr_tenant"
CALL_DEST_NR = "Caller-Destination-Number"
@@ -62,6 +62,7 @@ const (
SYSTEM_ERROR = "-SYSTEM_ERROR"
MANAGER_REQUEST = "+MANAGER_REQUEST"
USERNAME = "Caller-Username"
FS_IPv4 = "FreeSWITCH-IPv4"
)
// Nice printing for the event object.
@@ -205,6 +206,23 @@ func (fsev FSEvent) GetDuration(fieldName string) (dur time.Duration, err error)
return utils.ParseDurationWithSecs(durStr)
}
func (fsev FSEvent) GetOriginatorIP(fieldName string) string {
if strings.HasPrefix(fieldName, utils.STATIC_VALUE_PREFIX) { // Static value
return fieldName[len(utils.STATIC_VALUE_PREFIX):]
} else if fieldName == utils.META_DEFAULT {
return fsev[FS_IPv4]
}
return utils.FirstNonEmpty(fsev[fieldName], fsev[FS_IPv4])
}
func (fsev FSEvent) GetExtraFields() map[string]string {
var extraFields map[string]string
for _, fldRule := range config.CgrConfig().CDRSExtraFields {
extraFields[fldRule.Id] = fsev.ParseEventValue(fldRule)
}
return extraFields
}
// Used in derived charging and sittuations when we need to run regexp on fields
func (fsev FSEvent) ParseEventValue(rsrFld *utils.RSRField) string {
switch rsrFld.Id {
@@ -270,3 +288,25 @@ func (fsev FSEvent) PassesFieldFilter(fieldFilter *utils.RSRField) (bool, string
}
return false, ""
}
func (fsev FSEvent) AsStoredCdr() *utils.StoredCdr {
storCdr := new(utils.StoredCdr)
storCdr.CgrId = fsev.GetCgrId()
storCdr.TOR = utils.VOICE
storCdr.AccId = fsev.GetUUID()
storCdr.CdrHost = fsev.GetOriginatorIP(utils.META_DEFAULT)
storCdr.CdrSource = "FS_" + fsev.GetName()
storCdr.ReqType = fsev.GetReqType(utils.META_DEFAULT)
storCdr.Direction = fsev.GetDirection(utils.META_DEFAULT)
storCdr.Tenant = fsev.GetTenant(utils.META_DEFAULT)
storCdr.Category = fsev.GetCategory(utils.META_DEFAULT)
storCdr.Account = fsev.GetAccount(utils.META_DEFAULT)
storCdr.Subject = fsev.GetSubject(utils.META_DEFAULT)
storCdr.Destination = fsev.GetDestination(utils.META_DEFAULT)
storCdr.SetupTime, _ = fsev.GetSetupTime(utils.META_DEFAULT)
storCdr.AnswerTime, _ = fsev.GetAnswerTime(utils.META_DEFAULT)
storCdr.Usage, _ = fsev.GetDuration(utils.META_DEFAULT)
storCdr.ExtraFields = fsev.GetExtraFields()
storCdr.Cost = -1
return storCdr
}

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package sessionmanager
import (
"reflect"
"testing"
"time"
@@ -610,3 +611,19 @@ Caller-Username: 04021292812`
t.Error("Should not pass filter")
}
}
func TestFsEvAsStoredCdr(t *testing.T) {
cfg, _ = config.NewDefaultCGRConfig()
config.SetCgrConfig(cfg)
ev := new(FSEvent).New(hangupEv)
setupTime, _ := utils.ParseTimeDetectLayout("1398442107")
aTime, _ := utils.ParseTimeDetectLayout("1398442120")
eStoredCdr := &utils.StoredCdr{CgrId: utils.Sha1("37e9b766-5256-4e4b-b1ed-3767b930fec8", setupTime.UTC().String()),
TOR: utils.VOICE, AccId: "37e9b766-5256-4e4b-b1ed-3767b930fec8", CdrHost: "10.0.2.15", CdrSource: "FS_CHANNEL_HANGUP_COMPLETE", ReqType: utils.PSEUDOPREPAID,
Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003",
Destination: "1002", SetupTime: setupTime, AnswerTime: aTime,
Usage: time.Duration(5) * time.Second, Cost: -1}
if storedCdr := ev.AsStoredCdr(); !reflect.DeepEqual(eStoredCdr, storedCdr) {
t.Errorf("Expecting: %+v, received: %+v", eStoredCdr, storedCdr)
}
}

View File

@@ -40,14 +40,16 @@ type FSSessionManager struct {
conn net.Conn
buf *bufio.Reader
sessions []*Session
connector engine.Connector
rater engine.Connector
cdrs engine.Connector
debitPeriod time.Duration
loggerDB engine.LogStorage
}
func NewFSSessionManager(cgrCfg *config.CGRConfig, storage engine.LogStorage, connector engine.Connector, debitPeriod time.Duration) *FSSessionManager {
func NewFSSessionManager(cgrCfg *config.CGRConfig, storage engine.LogStorage, rater, cdrs engine.Connector, debitPeriod time.Duration) *FSSessionManager {
cfg = cgrCfg // make config global
return &FSSessionManager{loggerDB: storage, connector: connector, debitPeriod: debitPeriod}
return &FSSessionManager{loggerDB: storage, rater: rater, cdrs: cdrs, debitPeriod: debitPeriod}
}
// Connects to the freeswitch mod_event_socket server and starts
@@ -164,7 +166,7 @@ func (sm *FSSessionManager) OnChannelPark(ev Event) {
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.connector.GetDerivedChargers(attrsDC, &dcs); err != nil {
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
@@ -203,7 +205,7 @@ func (sm *FSSessionManager) OnChannelPark(ev Event) {
TimeEnd: startTime.Add(cfg.SMMaxCallDuration),
}
var remainingDurationFloat float64
err = sm.connector.GetMaxSessionTime(cd, &remainingDurationFloat)
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
@@ -237,7 +239,7 @@ func (sm *FSSessionManager) OnChannelAnswer(ev Event) {
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.connector.GetDerivedChargers(attrsDC, &dcs); err != nil {
if err := sm.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
engine.Logger.Err(fmt.Sprintf("<SessionManager> OnAnswer: could not get derived charging for event %s: %s", ev.GetUUID(), err.Error()))
sm.DisconnectSession(ev.GetUUID(), SYSTEM_ERROR, "") // Disconnect the session since we are not able to process sessions
return
@@ -260,7 +262,7 @@ func (sm *FSSessionManager) OnChannelHangupComplete(ev Event) {
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.connector.GetDerivedChargers(attrsDC, &dcs); err != nil {
if err := sm.rater.GetDerivedChargers(attrsDC, &dcs); err != nil {
engine.Logger.Err(fmt.Sprintf("<SessionManager> OnHangup: could not get derived charging for event %s: %s", ev.GetUUID(), err.Error()))
return
}
@@ -330,7 +332,7 @@ func (sm *FSSessionManager) OnChannelHangupComplete(ev Event) {
Increments: refundIncrements,
}
var response float64
err := sm.connector.RefundIncrements(*cd, &response)
err := sm.rater.RefundIncrements(*cd, &response)
if err != nil {
engine.Logger.Err(fmt.Sprintf("Debit cents failed: %v", err))
}
@@ -338,7 +340,13 @@ func (sm *FSSessionManager) OnChannelHangupComplete(ev Event) {
cost := refundIncrements.GetTotalCost()
lastCC.Cost -= cost
lastCC.Timespans.Compress()
// engine.Logger.Info(fmt.Sprintf("Rambursed %v cents", cost))
}
if sm.cdrs != nil {
var reply string
storedCdr := ev.AsStoredCdr()
if err := sm.cdrs.ProcessCdr(storedCdr, &reply); err != nil {
engine.Logger.Err(fmt.Sprintf("<SM-FreeSWITCH> Failed processing CDR, cgrid: %s, accid: %s, error: <%s>", storedCdr.CgrId, storedCdr.AccId, err.Error()))
}
}
}
@@ -347,7 +355,7 @@ func (sm *FSSessionManager) GetDebitPeriod() time.Duration {
}
func (sm *FSSessionManager) MaxDebit(cd *engine.CallDescriptor, cc *engine.CallCost) error {
return sm.connector.MaxDebit(*cd, cc)
return sm.rater.MaxDebit(*cd, cc)
}
func (sm *FSSessionManager) GetDbLogger() engine.LogStorage {