code reorganization and added cdr interface

This commit is contained in:
Radu Ioan Fericean
2013-05-19 15:57:09 +03:00
parent faaca5ae57
commit cdfea5aba4
14 changed files with 280 additions and 126 deletions

42
cdrs/cdr.go Normal file
View File

@@ -0,0 +1,42 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2013 ITsysCOM
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package cdrs
import (
"time"
)
type CDR interface {
New([]byte) CDR
GetName() string
GetDirection() string
GetOrigId() string
GetSubject() string
GetAccount() string
GetDestination() string
GetCallDestNr() string
GetTOR() string
GetUUID() string
GetTenant() string
GetReqType() string
GetStartTime(string) (time.Time, error)
GetEndTime() (time.Time, error)
GetFallbackSubj() string
GetExtraParameters() string
}

View File

@@ -21,122 +21,35 @@ package cdrs
import (
"encoding/json"
"fmt"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/rater"
utils "github.com/cgrates/cgrates/cgrcoreutils"
"io/ioutil"
"log/syslog"
"net/http"
"strconv"
"time"
)
const (
// Freswitch event proprities names
DIRECTION = "Call-Direction"
ORIG_ID = "variable_sip_call_id" //- originator_id - match cdrs
SUBJECT = "variable_cgr_subject"
ACCOUNT = "variable_cgr_account"
DESTINATION = "variable_cgr_destination"
REQTYPE = "variable_cgr_reqtype" //prepaid or postpaid
TOR = "variable_cgr_tor"
UUID = "Unique-ID" // -Unique ID for this call leg
CSTMID = "variable_cgr_cstmid"
CALL_DEST_NR = "Caller-Destination-Number"
PARK_TIME = "Caller-Profile-Created-Time"
START_TIME = "Caller-Channel-Answered-Time"
END_TIME = "Caller-Channel-Hangup-Time"
NAME = "Event-Name"
HEARTBEAT = "HEARTBEAT"
ANSWER = "CHANNEL_ANSWER"
HANGUP = "CHANNEL_HANGUP_COMPLETE"
PARK = "CHANNEL_PARK"
REQTYPE_PREPAID = "prepaid"
REQTYPE_POSTPAID = "postpaid"
AUTH_OK = "+AUTH_OK"
DISCONNECT = "+SWITCH DISCONNECT"
INSUFFICIENT_FUNDS = "-INSUFFICIENT_FUNDS"
MISSING_PARAMETER = "-MISSING_PARAMETER"
SYSTEM_ERROR = "-SYSTEM_ERROR"
MANAGER_REQUEST = "+MANAGER_REQUEST"
USERNAME = "Caller-Username"
var (
Logger utils.LoggerInterface
)
var cfg *config.CGRConfig
// Returns first non empty string out of vals. Useful to extract defaults
func firstNonEmpty(vals ...string) string {
for _, val := range vals {
if len(val) != 0 {
return val
}
func init() {
var err error
Logger, err = syslog.New(syslog.LOG_INFO, "CGRateS")
if err != nil {
Logger = new(utils.StdLogger)
}
return ""
}
func GetName(vars map[string]string) string {
return vars[NAME]
}
func GetDirection(vars map[string]string) string {
//TODO: implement direction
return "OUT"
//return vars[DIRECTION]
}
func GetOrigId(vars map[string]string) string {
return vars[ORIG_ID]
}
func GetSubject(vars map[string]string) string {
return firstNonEmpty(vars[SUBJECT], vars[USERNAME])
}
func GetAccount(vars map[string]string) string {
return firstNonEmpty(vars[ACCOUNT], vars[USERNAME])
}
// Charging destination number
func GetDestination(vars map[string]string) string {
return firstNonEmpty(vars[DESTINATION], vars[CALL_DEST_NR])
}
// Original dialed destination number, useful in case of unpark
func GetCallDestNr(vars map[string]string) string {
return vars[CALL_DEST_NR]
}
func GetTOR(vars map[string]string) string {
return firstNonEmpty(vars[TOR], cfg.SMDefaultTOR)
}
func GetUUID(vars map[string]string) string {
return vars[UUID]
}
func GetTenant(vars map[string]string) string {
return firstNonEmpty(vars[CSTMID], cfg.SMDefaultTenant)
}
func GetReqType(vars map[string]string) string {
return firstNonEmpty(vars[REQTYPE], cfg.SMDefaultReqType)
}
func GetFallbackSubj(vars map[string]string) string {
return cfg.SMDefaultSubject
}
func GetStartTime(vars map[string]string, field string) (t time.Time, err error) {
st, err := strconv.ParseInt(vars[field], 0, 64)
t = time.Unix(0, st*1000)
return
}
func GetEndTime() (vars map[string]string, t time.Time, err error) {
st, err := strconv.ParseInt(vars[END_TIME], 0, 64)
t = time.Unix(0, st*1000)
return
}
type CDR struct {
Variables map[string]string
type CDRVars struct {
FSCdr map[string]string
}
func cdrHandler(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
cdr := CDR{}
cdr := CDRVars{}
if err := json.Unmarshal(body, &cdr); err == nil {
new(FSCdr).New(body)
} else {
rater.Logger.Err(fmt.Sprintf("CDRCAPTOR: Could not unmarshal cdr: %v", err))
Logger.Err(fmt.Sprintf("CDRCAPTOR: Could not unmarshal cdr: %v", err))
}
}

111
cdrs/fscdr.go Normal file
View File

@@ -0,0 +1,111 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2013 ITsysCOM
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package cdrs
import (
utils "github.com/cgrates/cgrates/cgrcoreutils"
"github.com/cgrates/cgrates/config"
"strconv"
"time"
)
var cfg *config.CGRConfig // Share the configuration with the rest of the package
const (
// Freswitch event proprities names
DIRECTION = "Call-Direction"
ORIG_ID = "variable_sip_call_id" //- originator_id - match cdrs
SUBJECT = "variable_cgr_subject"
ACCOUNT = "variable_cgr_account"
DESTINATION = "variable_cgr_destination"
REQTYPE = "variable_cgr_reqtype" //prepaid or postpaid
TOR = "variable_cgr_tor"
UUID = "Unique-ID" // -Unique ID for this call leg
CSTMID = "variable_cgr_cstmid"
CALL_DEST_NR = "Caller-Destination-Number"
PARK_TIME = "Caller-Profile-Created-Time"
START_TIME = "Caller-Channel-Answered-Time"
END_TIME = "Caller-Channel-Hangup-Time"
NAME = "Event-Name"
USERNAME = "Caller-Username"
)
type FSCdr map[string]string
func (fsev FSCdr) New(body []byte) CDR {
//fsev = fsock.FSCdrStrToMap(body, nil)
return fsev
}
func (fsev FSCdr) GetName() string {
return fsev[NAME]
}
func (fsev FSCdr) GetDirection() string {
//TODO: implement direction
return "OUT"
//return fsev[DIRECTION]
}
func (fsev FSCdr) GetOrigId() string {
return fsev[ORIG_ID]
}
func (fsev FSCdr) GetSubject() string {
return utils.FirstNonEmpty(fsev[SUBJECT], fsev[USERNAME])
}
func (fsev FSCdr) GetAccount() string {
return utils.FirstNonEmpty(fsev[ACCOUNT], fsev[USERNAME])
}
// Charging destination number
func (fsev FSCdr) GetDestination() string {
return utils.FirstNonEmpty(fsev[DESTINATION], fsev[CALL_DEST_NR])
}
// Original dialed destination number, useful in case of unpark
func (fsev FSCdr) GetCallDestNr() string {
return fsev[CALL_DEST_NR]
}
func (fsev FSCdr) GetTOR() string {
return utils.FirstNonEmpty(fsev[TOR], cfg.SMDefaultTOR)
}
func (fsev FSCdr) GetUUID() string {
return fsev[UUID]
}
func (fsev FSCdr) GetTenant() string {
return utils.FirstNonEmpty(fsev[CSTMID], cfg.SMDefaultTenant)
}
func (fsev FSCdr) GetReqType() string {
return utils.FirstNonEmpty(fsev[REQTYPE], cfg.SMDefaultReqType)
}
func (fsev FSCdr) GetExtraParameters() string {
return ""
}
func (fsev FSCdr) GetFallbackSubj() string {
return cfg.SMDefaultSubject
}
func (fsev FSCdr) GetStartTime(field string) (t time.Time, err error) {
st, err := strconv.ParseInt(fsev[field], 0, 64)
t = time.Unix(0, st*1000)
return
}
func (fsev FSCdr) GetEndTime() (t time.Time, err error) {
st, err := strconv.ParseInt(fsev[END_TIME], 0, 64)
t = time.Unix(0, st*1000)
return
}

View File

@@ -0,0 +1,29 @@
/*
Rating system designed to be used in VoIP Carriers World
Copyright (C) 2013 ITsysCOM
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package cgrcoreutils
// Returns first non empty string out of vals. Useful to extract defaults
func FirstNonEmpty(vals ...string) string {
for _, val := range vals {
if len(val) != 0 {
return val
}
}
return ""
}

View File

@@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package rater
package cgrcoreutils
import (
"log"

View File

@@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"github.com/cgrates/cgrates/cache2go"
utils "github.com/cgrates/cgrates/cgrcoreutils"
"log/syslog"
"math"
"time"
@@ -31,7 +32,7 @@ func init() {
var err error
Logger, err = syslog.New(syslog.LOG_INFO, "CGRateS")
if err != nil {
Logger = new(StdLogger)
Logger = new(utils.StdLogger)
}
}
@@ -42,7 +43,7 @@ const (
)
var (
Logger LoggerInterface
Logger utils.LoggerInterface
db_server = "127.0.0.1"
//db_server = "192.168.0.17"
storageGetter, _ = NewMapStorage()

View File

@@ -20,6 +20,7 @@ package rater
import (
"fmt"
"github.com/cgrates/cgrates/cdrs"
"menteslibres.net/gosexy/redis"
//"log"
"strconv"
@@ -217,3 +218,10 @@ func (rs *GosexyStorage) LogError(uuid, source, errstr string) (err error) {
_, err = rs.db.Set(LOG_ERR+source+"_"+uuid, errstr)
return
}
func (rs *GosexyStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (rs *GosexyStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -22,6 +22,7 @@ import (
"bytes"
"encoding/gob"
"encoding/json"
"github.com/cgrates/cgrates/cdrs"
gmsgpack "github.com/ugorji/go-msgpack"
"github.com/vmihailenco/msgpack"
"strings"
@@ -61,6 +62,8 @@ type DataStorage interface {
GetActionTimings(string) ([]*ActionTiming, error)
SetActionTimings(string, []*ActionTiming) error
GetAllActionTimings() (map[string][]*ActionTiming, error)
GetCdr(string) (cdrs.CDR, error)
SetCdr(string, cdrs.CDR) error
//GetAllActionTimingsLogs() (map[string][]*ActionTiming, error)
LogCallCost(uuid, source string, cc *CallCost) error
LogError(uuid, source, errstr string) error

View File

@@ -21,6 +21,7 @@ package rater
import (
"errors"
"fmt"
"github.com/cgrates/cgrates/cdrs"
"strings"
"time"
)
@@ -182,3 +183,10 @@ func (ms *MapStorage) LogError(uuid, source, errstr string) (err error) {
ms.dict[LOG_ERR+source+"_"+uuid] = []byte(errstr)
return nil
}
func (ms *MapStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (ms *MapStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -20,6 +20,7 @@ package rater
import (
"fmt"
"github.com/cgrates/cgrates/cdrs"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"log"
@@ -207,3 +208,10 @@ func (ms *MongoStorage) LogActionTiming(source string, at *ActionTiming, as []*A
func (ms *MongoStorage) LogError(uuid, source, errstr string) (err error) {
return ms.db.C("errlog").Insert(&LogErrEntry{uuid, errstr, source})
}
func (ms *MongoStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (ms *MongoStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -22,6 +22,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/cgrates/cgrates/cdrs"
_ "github.com/go-sql-driver/mysql"
)
@@ -136,49 +137,49 @@ func NewMySQLStorage(host, port, name, user, password string) (DataStorage, erro
return &MySQLStorage{db}, nil
}
func (psl *MySQLStorage) Close() {}
func (mys *MySQLStorage) Close() {}
func (psl *MySQLStorage) Flush() (err error) {
func (mys *MySQLStorage) Flush() (err error) {
return
}
func (psl *MySQLStorage) GetRatingProfile(string) (rp *RatingProfile, err error) {
/*row := psl.Db.QueryRow(fmt.Sprintf("SELECT * FROM ratingprofiles WHERE id='%s'", id))
func (mys *MySQLStorage) GetRatingProfile(string) (rp *RatingProfile, err error) {
/*row := mys.Db.QueryRow(fmt.Sprintf("SELECT * FROM ratingprofiles WHERE id='%s'", id))
err = row.Scan(&rp, &cc.Direction, &cc.Tenant, &cc.TOR, &cc.Subject, &cc.Destination, &cc.Cost, &cc.ConnectFee, &timespansJson)
err = json.Unmarshal([]byte(timespansJson), cc.Timespans)*/
return
}
func (psl *MySQLStorage) SetRatingProfile(rp *RatingProfile) (err error) {
func (mys *MySQLStorage) SetRatingProfile(rp *RatingProfile) (err error) {
return
}
func (psl *MySQLStorage) GetDestination(string) (d *Destination, err error) {
func (mys *MySQLStorage) GetDestination(string) (d *Destination, err error) {
return
}
func (psl *MySQLStorage) SetDestination(d *Destination) (err error) {
func (mys *MySQLStorage) SetDestination(d *Destination) (err error) {
return
}
func (psl *MySQLStorage) GetActions(string) (as []*Action, err error) {
func (mys *MySQLStorage) GetActions(string) (as []*Action, err error) {
return
}
func (psl *MySQLStorage) SetActions(key string, as []*Action) (err error) { return }
func (mys *MySQLStorage) SetActions(key string, as []*Action) (err error) { return }
func (psl *MySQLStorage) GetUserBalance(string) (ub *UserBalance, err error) { return }
func (mys *MySQLStorage) GetUserBalance(string) (ub *UserBalance, err error) { return }
func (psl *MySQLStorage) SetUserBalance(ub *UserBalance) (err error) { return }
func (mys *MySQLStorage) SetUserBalance(ub *UserBalance) (err error) { return }
func (psl *MySQLStorage) GetActionTimings(key string) (ats []*ActionTiming, err error) { return }
func (mys *MySQLStorage) GetActionTimings(key string) (ats []*ActionTiming, err error) { return }
func (psl *MySQLStorage) SetActionTimings(key string, ats []*ActionTiming) (err error) { return }
func (mys *MySQLStorage) SetActionTimings(key string, ats []*ActionTiming) (err error) { return }
func (psl *MySQLStorage) GetAllActionTimings() (ats map[string][]*ActionTiming, err error) { return }
func (mys *MySQLStorage) GetAllActionTimings() (ats map[string][]*ActionTiming, err error) { return }
func (psl *MySQLStorage) LogCallCost(uuid, source string, cc *CallCost) (err error) {
if psl.Db == nil {
func (mys *MySQLStorage) LogCallCost(uuid, source string, cc *CallCost) (err error) {
if mys.Db == nil {
//timespans.Logger.Warning("Cannot write log to database.")
return
}
@@ -186,7 +187,7 @@ func (psl *MySQLStorage) LogCallCost(uuid, source string, cc *CallCost) (err err
if err != nil {
Logger.Err(fmt.Sprintf("Error marshalling timespans to json: %v", err))
}
_, err = psl.Db.Exec(fmt.Sprintf("INSERT INTO cdr VALUES ('%s', '%s','%s', '%s', '%s', '%s', '%s', '%s', %v, %v, '%s')",
_, err = mys.Db.Exec(fmt.Sprintf("INSERT INTO cdr VALUES ('%s', '%s','%s', '%s', '%s', '%s', '%s', '%s', %v, %v, '%s')",
uuid,
source,
cc.Direction,
@@ -204,8 +205,8 @@ func (psl *MySQLStorage) LogCallCost(uuid, source string, cc *CallCost) (err err
return
}
func (psl *MySQLStorage) GetCallCostLog(uuid, source string) (cc *CallCost, err error) {
row := psl.Db.QueryRow(fmt.Sprintf("SELECT * FROM cdr WHERE uuid='%s' AND source='%s'", uuid, source))
func (mys *MySQLStorage) GetCallCostLog(uuid, source string) (cc *CallCost, err error) {
row := mys.Db.QueryRow(fmt.Sprintf("SELECT * FROM cdr WHERE uuid='%s' AND source='%s'", uuid, source))
var uuid_found string
var timespansJson string
err = row.Scan(&uuid_found, &cc.Direction, &cc.Tenant, &cc.TOR, &cc.Subject, &cc.Destination, &cc.Cost, &cc.ConnectFee, &timespansJson)
@@ -213,10 +214,17 @@ func (psl *MySQLStorage) GetCallCostLog(uuid, source string) (cc *CallCost, err
return
}
func (psl *MySQLStorage) LogActionTrigger(ubId, source string, at *ActionTrigger, as []*Action) (err error) {
func (mys *MySQLStorage) LogActionTrigger(ubId, source string, at *ActionTrigger, as []*Action) (err error) {
return
}
func (psl *MySQLStorage) LogActionTiming(source string, at *ActionTiming, as []*Action) (err error) {
func (mys *MySQLStorage) LogActionTiming(source string, at *ActionTiming, as []*Action) (err error) {
return
}
func (psl *MySQLStorage) LogError(uuid, source, errstr string) (err error) { return }
func (mys *MySQLStorage) LogError(uuid, source, errstr string) (err error) { return }
func (mys *MySQLStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (mys *MySQLStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -23,6 +23,7 @@ import (
"encoding/json"
"fmt"
_ "github.com/bmizerany/pq"
"github.com/cgrates/cgrates/cdrs"
)
type PostgresStorage struct {
@@ -220,3 +221,10 @@ func (psl *PostgresStorage) LogActionTiming(source string, at *ActionTiming, as
return
}
func (psl *PostgresStorage) LogError(uuid, source, errstr string) (err error) { return }
func (psl *PostgresStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (psl *PostgresStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -20,6 +20,7 @@ package rater
import (
"fmt"
"github.com/cgrates/cgrates/cdrs"
"github.com/garyburd/redigo/redis"
//"log"
"time"
@@ -214,3 +215,10 @@ func (rs *RedigoStorage) LogError(uuid, source, errstr string) (err error) {
_, err = rs.db.Do("set", LOG_ERR+source+"_"+uuid, errstr)
return
}
func (rs *RedigoStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (rs *RedigoStorage) SetCdr(string, cdrs.CDR) error {
return nil
}

View File

@@ -20,6 +20,7 @@ package rater
import (
"fmt"
"github.com/cgrates/cgrates/cdrs"
"github.com/fzzy/radix/redis"
//"log"
"time"
@@ -241,3 +242,9 @@ func (rs *RedisStorage) LogError(uuid, source, errstr string) (err error) {
}
return
}
func (rs *RedisStorage) GetCdr(string) (cdrs.CDR, error) {
return nil, nil
}
func (rs *RedisStorage) SetCdr(string, cdrs.CDR) error {
return nil
}