diff --git a/cdrs/cdrs.go b/cdrs/cdrs.go
index 7cb0688a1..550174c24 100644
--- a/cdrs/cdrs.go
+++ b/cdrs/cdrs.go
@@ -45,16 +45,15 @@ func fsCdrHandler(w http.ResponseWriter, r *http.Request) {
}
}()
} else {
- engine.Logger.Err(fmt.Sprintf("Could not create CDR entry: %v", err))
+ engine.Logger.Err(fmt.Sprintf("Could not create CDR entry: %s", err.Error()))
}
}
func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
- body, _ := ioutil.ReadAll(r.Body)
- if genCdr, err := new(GenCdr).New(body); err == nil {
- storage.SetCdr(genCdr)
+ if cgrCdr, err := NewCgrCdrFromHttpReq(r); err == nil {
+ storage.SetCdr(cgrCdr)
if cfg.CDRSMediator == "internal" {
- errMedi := medi.MediateDBCDR(genCdr, storage)
+ errMedi := medi.MediateDBCDR(cgrCdr, storage)
if errMedi != nil {
engine.Logger.Err(fmt.Sprintf("Could not run mediation on CDR: %s", errMedi.Error()))
}
@@ -62,7 +61,7 @@ func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
//TODO: use the connection to mediator
}
} else {
- engine.Logger.Err(fmt.Sprintf("Could not create CDR entry: %v", err))
+ engine.Logger.Err(fmt.Sprintf("Could not create CDR entry: %s", err.Error()))
}
}
@@ -76,7 +75,7 @@ func New(s engine.CdrStorage, m *mediator.Mediator, c *config.CGRConfig) *CDRS {
}
func (cdrs *CDRS) StartCapturingCDRs() {
- http.HandleFunc("/cgr_json", cgrCdrHandler) // Attach CGR CDR Handler
+ http.HandleFunc("/cgr", cgrCdrHandler) // Attach CGR CDR Handler
http.HandleFunc("/freeswitch_json", fsCdrHandler) // Attach FreeSWITCH JSON CDR Handler
http.ListenAndServe(cfg.CDRSListen, nil)
}
diff --git a/cdrs/cgrcdr.go b/cdrs/cgrcdr.go
new file mode 100644
index 000000000..f1042b002
--- /dev/null
+++ b/cdrs/cgrcdr.go
@@ -0,0 +1,121 @@
+/*
+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
+*/
+
+package cdrs
+
+import (
+ "github.com/cgrates/cgrates/utils"
+ "strconv"
+ "time"
+ "net/http"
+)
+
+const (
+ ACCID = "accid"
+ CDRHOST = "cdrhost"
+ REQTYPE = "reqtype"
+ DIRECTION = "direction"
+ TENANT = "tenant"
+ TOR = "tor"
+ ACCOUNT = "account"
+ SUBJECT = "subject"
+ DESTINATION = "destination"
+ TIME_ANSWER = "time_answer"
+ DURATION = "duration"
+)
+
+var primaryFields []string = []string{ACCID, CDRHOST, REQTYPE, DIRECTION, TENANT, TOR, ACCOUNT, SUBJECT, DESTINATION, TIME_ANSWER, DURATION}
+
+func NewCgrCdrFromHttpReq(req *http.Request) (CgrCdr, error) {
+ if req.Form == nil {
+ if err := req.ParseForm(); err != nil {
+ return nil, err
+ }
+ }
+ cgrCdr := make(CgrCdr)
+ for k, vals := range req.Form {
+ cgrCdr[k] = vals[0] // We only support the first value for now, if more are provided it is considered remote's fault
+ }
+ return cgrCdr, nil
+}
+
+
+type CgrCdr map[string]string
+
+func (cgrCdr CgrCdr) GetCgrId() string {
+ return utils.FSCgrId(cgrCdr[ACCID])
+}
+
+func (cgrCdr CgrCdr) GetAccId() string {
+ return cgrCdr[ACCID]
+}
+
+func (cgrCdr CgrCdr) GetCdrHost() string {
+ return cgrCdr[CDRHOST]
+}
+func (cgrCdr CgrCdr) GetDirection() string {
+ //TODO: implement direction
+ return "*out"
+}
+func (cgrCdr CgrCdr) GetOrigId() string {
+ return cgrCdr[CDRHOST]
+}
+func (cgrCdr CgrCdr) GetSubject() string {
+ return cgrCdr[SUBJECT]
+}
+func (cgrCdr CgrCdr) GetAccount() string {
+ return cgrCdr[ACCOUNT]
+}
+
+// Charging destination number
+func (cgrCdr CgrCdr) GetDestination() string {
+ return cgrCdr[DESTINATION]
+}
+
+func (cgrCdr CgrCdr) GetTOR() string {
+ return cgrCdr[TOR]
+}
+
+func (cgrCdr CgrCdr) GetTenant() string {
+ return cgrCdr[TENANT]
+}
+func (cgrCdr CgrCdr) GetReqType() string {
+ return cgrCdr[REQTYPE]
+}
+func (cgrCdr CgrCdr) GetExtraFields() map[string]string {
+ extraFields := make(map[string]string)
+ for k, v := range cgrCdr {
+ if !utils.IsSliceMember(primaryFields, k) {
+ extraFields[k] = v
+ }
+ }
+ return extraFields
+}
+func (cgrCdr CgrCdr) GetFallbackSubj() string {
+ return cfg.DefaultSubject
+}
+func (cgrCdr CgrCdr) GetAnswerTime() (t time.Time, err error) {
+ st, err := strconv.ParseInt(cgrCdr[TIME_ANSWER], 0, 64)
+ t = time.Unix(st, 0)
+ return
+}
+// Extracts duration as considered by the telecom switch
+func (cgrCdr CgrCdr) GetDuration() int64 {
+ dur, _ := strconv.ParseInt(cgrCdr[DURATION], 0, 64)
+ return dur
+}
diff --git a/cdrs/cgrcdr_test.go b/cdrs/cgrcdr_test.go
new file mode 100644
index 000000000..5b25cee08
--- /dev/null
+++ b/cdrs/cgrcdr_test.go
@@ -0,0 +1,85 @@
+/*
+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
+*/
+
+package cdrs
+
+import (
+ "github.com/cgrates/cgrates/utils"
+ "github.com/cgrates/cgrates/config"
+ "testing"
+ "time"
+)
+
+/*
+curl --data "accid=asbfdsaf&cdrhost=192.168.1.1&reqtype=rated&direction=*out&tenant=cgrates.org&tor=call&account=1001&subject=1001&destination=1002&time_answer=1383813746&duration=10&field_extr1=val_extr1&fieldextr2=valextr2" http://ipbxdev:2022/cgr
+*/
+
+func TestCgrCdrFields(t *testing.T) {
+ cfg, _ = config.NewDefaultCGRConfig()
+ cgrCdr := CgrCdr{ "accid":"dsafdsaf", "cdrhost":"192.168.1.1", "reqtype":"rated", "direction":"*out", "tenant":"cgrates.org", "tor":"call",
+ "account":"1001", "subject":"1001", "destination":"1002", "time_answer":"1383813746", "duration":"10", "field_extr1":"val_extr1", "fieldextr2":"valextr2"}
+ if cgrCdr.GetCgrId() != utils.FSCgrId("dsafdsaf") {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetAccId() != "dsafdsaf" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetCdrHost() != "192.168.1.1" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetDirection() != "*out" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetSubject() != "1001" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetAccount() != "1001" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetDestination() != "1002" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetTOR() != "call" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetTenant() != "cgrates.org" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetReqType() != utils.RATED {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetFallbackSubj() != "0" {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ answerTime, _ := cgrCdr.GetAnswerTime()
+ expectedATime, _ := time.Parse(time.RFC3339, "2013-11-07T08:42:26Z")
+ if answerTime.UTC() != expectedATime {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ if cgrCdr.GetDuration() != 10 {
+ t.Error("Error parsing cdr: ", cgrCdr)
+ }
+ extraFields := cgrCdr.GetExtraFields()
+ if len(extraFields) != 2 {
+ t.Error("Error parsing extra fields: ", extraFields)
+ }
+ if extraFields["field_extr1"] != "val_extr1" {
+ t.Error("Error parsing extra fields: ", extraFields)
+ }
+
+}
diff --git a/cdrs/gencdr.go b/cdrs/gencdr.go
deleted file mode 100644
index 8eb7ec0ae..000000000
--- a/cdrs/gencdr.go
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-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
-*/
-
-package cdrs
-
-import (
- "encoding/json"
- "errors"
- "github.com/cgrates/cgrates/utils"
- "strconv"
- "time"
-)
-
-const (
- CDR_MAP = "variables"
- DIRECTION = "direction"
- ORIG_ID = "id"
- SUBJECT = "subject"
- ACCOUNT = "account"
- DESTINATION = "destination"
- REQTYPE = "reqtype" //prepaid or postpaid
- TOR = "tor"
- UUID = "uuid" // -Unique ID for this call leg
- CSTMID = "tenant"
- CALL_DEST_NR = "dialed_extension"
- PARK_TIME = "start_epoch"
- ANSWER_TIME = "time_answer"
- HANGUP_TIME = "time_hangup"
- DURATION = "duration"
- USERNAME = "user_name"
- IP = "sip_local_network_addr"
-)
-
-type GenCdr map[string]string
-
-func (genCdr GenCdr) New(body []byte) (utils.CDR, error) {
- genCdr = make(map[string]string)
- var tmp map[string]interface{}
- var err error
- if err = json.Unmarshal(body, &tmp); err == nil {
- if variables, ok := tmp[CDR_MAP]; ok {
- if variables, ok := variables.(map[string]interface{}); ok {
- for k, v := range variables {
- genCdr[k] = v.(string)
- }
- }
- return genCdr, nil
- }
- }
- return nil, err
-}
-
-func (genCdr GenCdr) GetCgrId() string {
- return utils.FSCgrId(genCdr[UUID])
-}
-func (genCdr GenCdr) GetAccId() string {
- return genCdr[UUID]
-}
-func (genCdr GenCdr) GetCdrHost() string {
- return genCdr[FS_IP]
-}
-func (genCdr GenCdr) GetDirection() string {
- //TODO: implement direction
- return "*out"
-}
-func (genCdr GenCdr) GetOrigId() string {
- return genCdr[ORIG_ID]
-}
-func (genCdr GenCdr) GetSubject() string {
- return utils.FirstNonEmpty(genCdr[SUBJECT], genCdr[USERNAME])
-}
-func (genCdr GenCdr) GetAccount() string {
- return utils.FirstNonEmpty(genCdr[ACCOUNT], genCdr[USERNAME])
-}
-
-// Charging destination number
-func (genCdr GenCdr) GetDestination() string {
- return utils.FirstNonEmpty(genCdr[DESTINATION], genCdr[CALL_DEST_NR])
-}
-
-func (genCdr GenCdr) GetTOR() string {
- return utils.FirstNonEmpty(genCdr[TOR], cfg.DefaultTOR)
-}
-
-func (genCdr GenCdr) GetTenant() string {
- return utils.FirstNonEmpty(genCdr[CSTMID], cfg.DefaultTenant)
-}
-func (genCdr GenCdr) GetReqType() string {
- return utils.FirstNonEmpty(genCdr[REQTYPE], cfg.DefaultReqType)
-}
-func (genCdr GenCdr) GetExtraFields() map[string]string {
- extraFields := make(map[string]string, len(cfg.CDRSExtraFields))
- for _, field := range cfg.CDRSExtraFields {
- extraFields[field] = genCdr[field]
- }
- return extraFields
-}
-func (genCdr GenCdr) GetFallbackSubj() string {
- return cfg.DefaultSubject
-}
-func (genCdr GenCdr) GetAnswerTime() (t time.Time, err error) {
- st, err := strconv.ParseInt(genCdr[ANSWER_TIME], 0, 64)
- t = time.Unix(0, st*1000)
- return
-}
-func (genCdr GenCdr) GetHangupTime() (t time.Time, err error) {
- st, err := strconv.ParseInt(genCdr[HANGUP_TIME], 0, 64)
- t = time.Unix(0, st*1000)
- return
-}
-
-// Extracts duration as considered by the telecom switch
-func (genCdr GenCdr) GetDuration() int64 {
- dur, _ := strconv.ParseInt(genCdr[DURATION], 0, 64)
- return dur
-}
-
-func (genCdr GenCdr) Store() (result string, err error) {
- result += genCdr.GetCgrId() + "|"
- result += genCdr.GetAccId() + "|"
- result += genCdr.GetCdrHost() + "|"
- result += genCdr.GetDirection() + "|"
- result += genCdr.GetOrigId() + "|"
- result += genCdr.GetSubject() + "|"
- result += genCdr.GetAccount() + "|"
- result += genCdr.GetDestination() + "|"
- result += genCdr.GetTOR() + "|"
- result += genCdr.GetAccId() + "|"
- result += genCdr.GetTenant() + "|"
- result += genCdr.GetReqType() + "|"
- st, err := genCdr.GetAnswerTime()
- if err != nil {
- return "", err
- }
- result += strconv.FormatInt(st.UnixNano(), 10) + "|"
- et, err := genCdr.GetHangupTime()
- if err != nil {
- return "", err
- }
- result += strconv.FormatInt(et.UnixNano(), 10) + "|"
- result += strconv.FormatInt(genCdr.GetDuration(), 10) + "|"
- result += genCdr.GetFallbackSubj() + "|"
- return
-}
-
-func (genCdr GenCdr) Restore(input string) error {
- return errors.New("Not implemented")
-}
diff --git a/utils/cdr.go b/utils/cdr.go
index fe75b53d0..b8dbff990 100644
--- a/utils/cdr.go
+++ b/utils/cdr.go
@@ -39,51 +39,3 @@ type CDR interface {
GetFallbackSubj() string
GetExtraFields() map[string]string //Stores extra CDR Fields
}
-
-type GenericCdr map[string]string
-
-func (gcdr GenericCdr) GetCgrId() string {
- return ""
-}
-func (gcdr GenericCdr) GetAccId() string {
- return ""
-}
-func (gcdr GenericCdr) GetCdrHost() string {
- return ""
-}
-func (gcdr GenericCdr) GetDirection() string {
- return ""
-}
-func (gcdr GenericCdr) GetOrigId() string {
- return ""
-}
-func (gcdr GenericCdr) GetSubject() string {
- return ""
-}
-func (gcdr GenericCdr) GetAccount() string {
- return ""
-}
-func (gcdr GenericCdr) GetDestination() string {
- return ""
-}
-func (gcdr GenericCdr) GetTOR() string {
- return ""
-}
-func (gcdr GenericCdr) GetTenant() string {
- return ""
-}
-func (gcdr GenericCdr) GetReqType() string {
- return ""
-}
-func (gcdr GenericCdr) GetAnswerTime() (time.Time, error) {
- return time.Now(), nil
-}
-func (gcdr GenericCdr) GetDuration() int64 {
- return 0.0
-}
-func (gcdr GenericCdr) GetFallbackSubj() string {
- return ""
-}
-func (gcdr GenericCdr) GetExtraFields() map[string]string {
- return nil
-}