mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
RADIUS integration tests for accounting start and stop with CDR generation
This commit is contained in:
@@ -45,8 +45,14 @@ ATTRIBUTE Password 2 string
|
||||
|
||||
# Alias values
|
||||
VALUE Framed-Protocol PPP 1
|
||||
VALUE Service-Type Sip-Session 15 # Schulzrinne, acc, auth_radius
|
||||
VALUE Service-Type SIP-Caller-AVPs 30 # Proprietary, avp_radius
|
||||
|
||||
VALUE Sip-Method Invite 1
|
||||
VALUE Sip-Method Bye 8
|
||||
VALUE Acct-Status-Type Start 1
|
||||
VALUE Acct-Status-Type Stop 2
|
||||
|
||||
# Vendors
|
||||
VENDOR Cisco 9
|
||||
VENDOR Microsoft 311
|
||||
|
||||
@@ -89,10 +89,12 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> request: %s, error: %s", utils.ToJSON(req), err.Error()))
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> error: <%s> ignoring request: %s, process vars: %+v",
|
||||
err.Error(), utils.ToJSON(req), procVars))
|
||||
return nil, nil
|
||||
} else if !processed {
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> No request processor enabled for request: %s, ignoring request", utils.ToJSON(req)))
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> No request processor enabled, ignoring request %s, process vars: %+v",
|
||||
utils.ToJSON(req), procVars))
|
||||
return nil, nil
|
||||
}
|
||||
return
|
||||
@@ -126,10 +128,12 @@ func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err e
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> request: %s, error: %s", utils.ToJSON(req), err.Error()))
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> error: <%s> ignoring request: %s, process vars: %+v",
|
||||
err.Error(), utils.ToJSON(req), procVars))
|
||||
return nil, nil
|
||||
} else if !processed {
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> No request processor enabled for request: %s, ignoring request", utils.ToJSON(req)))
|
||||
utils.Logger.Err(fmt.Sprintf("<RadiusAgent> No request processor enabled, ignoring request %s, process vars: %+v",
|
||||
utils.ToJSON(req), procVars))
|
||||
return nil, nil
|
||||
}
|
||||
return
|
||||
|
||||
@@ -29,14 +29,15 @@ import (
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/sessionmanager"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/radigo"
|
||||
)
|
||||
|
||||
var raCfgPath string
|
||||
var raCfg *config.CGRConfig
|
||||
var raSMGrpc *rpc.Client
|
||||
var raAuthClnt, raAcctClnt *radigo.Client
|
||||
var raRPC *rpc.Client
|
||||
|
||||
func TestRAitInitCfg(t *testing.T) {
|
||||
raCfgPath = path.Join(*dataDir, "conf", "samples", "radagent")
|
||||
@@ -74,7 +75,7 @@ func TestRAitStartEngine(t *testing.T) {
|
||||
// Connect rpc client to rater
|
||||
func TestRAitApierRpcConn(t *testing.T) {
|
||||
var err error
|
||||
raSMGrpc, err = jsonrpc.Dial("tcp", raCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
|
||||
raRPC, err = jsonrpc.Dial("tcp", raCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -84,7 +85,7 @@ func TestRAitApierRpcConn(t *testing.T) {
|
||||
func TestRAitTPFromFolder(t *testing.T) {
|
||||
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")}
|
||||
var loadInst utils.LoadInstance
|
||||
if err := raSMGrpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil {
|
||||
if err := raRPC.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
||||
@@ -104,10 +105,10 @@ func TestRAitAuth(t *testing.T) {
|
||||
if err := authReq.AddAVPWithName("Called-Station-Id", "1002", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := authReq.AddAVPWithName("Acct-Session-Id", "2ca13afce9b2d76e15de7e1ec6568fc8@0:0:0:0:0:0:0:0", ""); err != nil {
|
||||
if err := authReq.AddAVPWithName("Acct-Session-Id", "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := authReq.AddAVPWithName("Sip-From-Tag", "7f30055f", ""); err != nil {
|
||||
if err := authReq.AddAVPWithName("Sip-From-Tag", "51585361", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := authReq.AddAVPWithName("NAS-IP-Address", "127.0.0.1", ""); err != nil {
|
||||
@@ -131,6 +132,157 @@ func TestRAitAuth(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRAitAcctStart(t *testing.T) {
|
||||
if raAcctClnt, err = radigo.NewClient("udp", "127.0.0.1:1813", "CGRateS.org", dictRad, 1, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
req := raAcctClnt.NewRequest(radigo.AccountingRequest, 2) // emulates Kamailio packet for accounting start
|
||||
if err := req.AddAVPWithName("Acct-Status-Type", "Start", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Service-Type", "Sip-Session", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-Response-Code", "200", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-Method", "Invite", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Event-Timestamp", "1497106115", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-From-Tag", "51585361", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-To-Tag", "75c2f57b", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Acct-Session-Id", "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("User-Name", "1001", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Called-Station-Id", "1002", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Ascend-User-Acct-Time", "1497106115", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("NAS-Port-Id", "5060", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Acct-Delay-Time", "0", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("NAS-IP-Address", "127.0.0.1", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
reply, err := raAcctClnt.SendRequest(req)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if reply.Code != radigo.AccountingResponse {
|
||||
t.Errorf("Received reply: %+v", reply)
|
||||
}
|
||||
if len(reply.AVPs) != 0 { // we don't expect AVPs to be populated
|
||||
t.Errorf("Received AVPs: %+v", reply.AVPs)
|
||||
}
|
||||
// Make sure the sessin is managed by SMG
|
||||
var aSessions []*sessionmanager.ActiveSession
|
||||
if err := raRPC.Call("SMGenericV1.GetActiveSessions",
|
||||
map[string]string{utils.MEDI_RUNID: utils.META_DEFAULT, utils.ACCID: "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0-51585361-75c2f57b"},
|
||||
&aSessions); err != nil {
|
||||
t.Error(err)
|
||||
} else if len(aSessions) != 1 {
|
||||
t.Errorf("Unexpected number of sessions received: %+v", aSessions)
|
||||
} else if aSessions[0].Usage != time.Duration(10)*time.Second {
|
||||
t.Errorf("Expecting 10s, received usage: %v", aSessions[0].Usage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRAitAcctStop(t *testing.T) {
|
||||
req := raAcctClnt.NewRequest(radigo.AccountingRequest, 3) // emulates Kamailio packet for accounting start
|
||||
if err := req.AddAVPWithName("Acct-Status-Type", "Stop", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Service-Type", "Sip-Session", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-Response-Code", "200", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-Method", "Bye", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Event-Timestamp", "1497106119", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-From-Tag", "51585361", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Sip-To-Tag", "75c2f57b", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Acct-Session-Id", "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("User-Name", "1001", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Called-Station-Id", "1002", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Ascend-User-Acct-Time", "1497106115", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("NAS-Port-Id", "5060", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("Acct-Delay-Time", "0", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := req.AddAVPWithName("NAS-IP-Address", "127.0.0.1", ""); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
reply, err := raAcctClnt.SendRequest(req)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if reply.Code != radigo.AccountingResponse {
|
||||
t.Errorf("Received reply: %+v", reply)
|
||||
}
|
||||
if len(reply.AVPs) != 0 { // we don't expect AVPs to be populated
|
||||
t.Errorf("Received AVPs: %+v", reply.AVPs)
|
||||
}
|
||||
// Make sure the sessin was disconnected from SMG
|
||||
var aSessions []*sessionmanager.ActiveSession
|
||||
if err := raRPC.Call("SMGenericV1.GetActiveSessions",
|
||||
map[string]string{utils.MEDI_RUNID: utils.META_DEFAULT, utils.ACCID: "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0-51585361-75c2f57b"},
|
||||
&aSessions); err == nil || err.Error() != utils.ErrNotFound.Error() {
|
||||
t.Error(err)
|
||||
}
|
||||
time.Sleep(time.Duration(10 * time.Millisecond))
|
||||
var cdrs []*engine.ExternalCDR
|
||||
args := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, DestinationPrefixes: []string{"1002"}}
|
||||
if err := raRPC.Call("ApierV2.GetCdrs", args, &cdrs); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(cdrs) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
||||
} else {
|
||||
if cdrs[0].Usage != "4" {
|
||||
t.Errorf("Unexpected CDR Usage received, cdr: %v %+v ", cdrs[0].Usage, cdrs[0])
|
||||
}
|
||||
if cdrs[0].CostSource != utils.SESSION_MANAGER_SOURCE {
|
||||
t.Errorf("Unexpected CDR CostSource received for CDR: %v", cdrs[0])
|
||||
}
|
||||
if cdrs[0].Cost != 0.01 {
|
||||
t.Errorf("Unexpected CDR Cost received for CDR: %v", cdrs[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRAitStopCgrEngine(t *testing.T) {
|
||||
if err := engine.KillEngine(100); err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true,
|
||||
"rals_conns": [
|
||||
{"address": "*internal"}
|
||||
],
|
||||
"cdrstats_conns": [
|
||||
{"address": "*internal"}
|
||||
],
|
||||
@@ -112,14 +115,16 @@
|
||||
"value": "*prepaid", "mandatory": true},
|
||||
{"tag": "OriginID", "field_id": "OriginID", "type": "*composed",
|
||||
"value": "Acct-Session-Id;^-;Sip-From-Tag;^-;Sip-To-Tag", "mandatory": true},
|
||||
{"tag": "OriginHost", "field_id": "OriginHost", "type": "*composed",
|
||||
"value": "NAS-IP-Address", "mandatory": true},
|
||||
{"tag": "Account", "field_id": "Account", "type": "*composed",
|
||||
"value": "User-Name", "mandatory": true},
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*composed",
|
||||
"value": "Called-Station-Id", "mandatory": true},
|
||||
{"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed",
|
||||
"value": "Event-Timestamp", "mandatory": true},
|
||||
"value": "Ascend-User-Acct-Time", "mandatory": true},
|
||||
{"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed",
|
||||
"value": "Event-Timestamp", "mandatory": true},
|
||||
"value": "Ascend-User-Acct-Time", "mandatory": true},
|
||||
],
|
||||
"reply_fields":[],
|
||||
},
|
||||
@@ -138,10 +143,10 @@
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*composed",
|
||||
"value": "Called-Station-Id", "mandatory": true},
|
||||
{"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed",
|
||||
"value": "Event-Timestamp", "mandatory": true},
|
||||
"value": "Ascend-User-Acct-Time", "mandatory": true},
|
||||
{"tag": "AnswerTime", "field_id": "AnswerTime", "type": "*composed",
|
||||
"value": "Event-Timestamp", "mandatory": true},
|
||||
{"tag": "Usage", "field_id": "AnswerTime", "type": "*handler", "handler_id": "*usage_difference",
|
||||
"value": "Ascend-User-Acct-Time", "mandatory": true},
|
||||
{"tag": "Usage", "field_id": "Usage", "type": "*handler", "handler_id": "*usage_difference",
|
||||
"value": "Event-Timestamp;^|;Ascend-User-Acct-Time", "mandatory": true},
|
||||
],
|
||||
"reply_fields":[],
|
||||
|
||||
@@ -58,6 +58,11 @@ ATTRIBUTE Sip-Rpid 213 string # Proprietary, auth_radius
|
||||
ATTRIBUTE SIP-AVP 225 string # Proprietary, avp_radius
|
||||
|
||||
### Acct-Status-Type Values ###
|
||||
VALUE Acct-Status-Type Start 1
|
||||
VALUE Acct-Status-Type Stop 2
|
||||
VALUE Acct-Status-Type Alive 3
|
||||
VALUE Acct-Status-Type Accounting-On 7
|
||||
VALUE Acct-Status-Type Accounting-Off 8
|
||||
VALUE Acct-Status-Type Failed 15 # RFC2866, acc
|
||||
|
||||
### Service-Type Values ###
|
||||
@@ -67,6 +72,8 @@ VALUE Service-Type Sip-Session 15 # Schulzrinne, acc, auth_radius
|
||||
VALUE Service-Type SIP-Caller-AVPs 30 # Proprietary, avp_radius
|
||||
VALUE Service-Type SIP-Callee-AVPs 31 # Proprietary, avp_radius
|
||||
|
||||
|
||||
|
||||
### Sip-Method Values ###
|
||||
VALUE Sip-Method Undefined 0
|
||||
VALUE Sip-Method Invite 1
|
||||
|
||||
Reference in New Issue
Block a user