mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
Add tut entry for opensips+diameter
INCOMPLETE - shared cgrates configuration for three different scenarios - every scenario has its own opensips configuration. For more info check README or read comments inside the configuration - added script for converting unix time to suitable Event-Timestamp format - added a dictionary.opensips entry for making Credit-Control diameter requests possible
This commit is contained in:
committed by
Dan Christian Bogos
parent
9af344aac7
commit
40eaa8739c
30
data/tutorials/osips_diam/README.md
Normal file
30
data/tutorials/osips_diam/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Prepaid Scenario
|
||||
|
||||
1. **INVITE**: 1001 calls 1002.
|
||||
2. **Send INITIAL_REQUEST CCR**: Before forwarding INVITE, have OpenSIPS send a Diameter Credit-Control INITIAL_REQUEST to authorize the call.
|
||||
3. **Receive CCA**: Extract CC-Time from the reply's Granted-Service-Unit AVP and (if also authorized) then set the dialog timeout to that value.
|
||||
4. **ACK**: 1002 answers the call, `dlg_on_answer` handler is triggered.
|
||||
5. **Send UPDATE_REQUEST CCR**: Send an async Credit-Control request to CGRateS to initiate the session. (see bottom of cfg file to see why, same for the other async calls). No need for further updates as CGRateS will debit based on the configured `debit_interval`.
|
||||
6. **SEND TERMINATION_REQUEST**: Wait for hangup/timeout. The `handle_hangup/handle_auth` handler will be triggered and send a Diameter Credit-Control TERMINATION_REQUEST. Both of those are almost identical, only differing AVP being Terminate-Cause (6/DIAMETER_AUTH_EXPIRED for timeout AND 1/DIAMETER_LOGOUT for hangup). This will terminate the session as well as process the CDR.
|
||||
|
||||
# Postpaid Scenario
|
||||
|
||||
The Postpaid scenario is the same as the above except:
|
||||
- We only send an **EVENT_REQUEST** on `dlg_on_timeout/dlg_on_hangup` handlers to send a ProcessCDR request to CGRateS.
|
||||
- Inside `dlg_on_answer` the answer time is recorded to calculate usage at the end.
|
||||
|
||||
# Accounting Scenario
|
||||
|
||||
Attempts to use the `do_accounting` method (part of the OpenSIPS accounting module) to send Accounting-Start and Accounting-Stop requests. Currently, it's only sending Accounting-Start on hangup which is not intended.
|
||||
|
||||
# Useful commands
|
||||
|
||||
- sudo -u opensips /usr/sbin/opensips -f /etc/opensips/opensips.cfg -m 64 -M 4 -D
|
||||
- cgr-engine -config_path=/usr/share/cgrates/tutorials/osips_diam/etc/cgrates -logger=*stdout
|
||||
- cgr-loader -path /usr/share/cgrates/tutorials/osips_diam/tp/ -verbose
|
||||
- freeDiameterd -dd -c /etc/freeDiameter/freeDiameter.conf
|
||||
- pjsua_listen --help
|
||||
- pjsua_listen --accounts 1001,1002
|
||||
- pjsua_call --help
|
||||
- pjsua_call --from 1001 --to 1002 --dur 67
|
||||
|
||||
154
data/tutorials/osips_diam/etc/cgrates/accounting.json
Normal file
154
data/tutorials/osips_diam/etc/cgrates/accounting.json
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
|
||||
"diameter_agent": {
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "AccountingStart",
|
||||
"filters": ["*eq:~*req.Accounting-Record-Type:1"],
|
||||
"flags": ["*initiate", "*accounts", "*log"],
|
||||
"request_fields":[
|
||||
{"tag": "Category", "path": "*cgreq.Category", "type": "*constant", "value": "call"},
|
||||
{"tag": "RequestType", "path": "*cgreq.RequestType", "type": "*constant",
|
||||
"value": "*prepaid", "mandatory": true},
|
||||
{"tag": "OriginID", "path": "*cgreq.OriginID", "type": "*composed",
|
||||
"value": "~*req.Session-Id", "mandatory": true},
|
||||
{"tag": "OriginHost", "path": "*cgreq.OriginHost", "type": "*variable",
|
||||
"value": "~*req.Origin-Host", "mandatory": true},
|
||||
{"tag": "Account", "path": "*cgreq.Account", "type": "*variable",
|
||||
"value": "~*req.User-Name", "mandatory": true},
|
||||
{"tag": "Subject", "path": "*cgreq.Subject", "type": "*variable",
|
||||
"value": "~*req.User-Name", "mandatory": true},
|
||||
{"tag": "Destination", "path": "*cgreq.Destination", "type": "*variable",
|
||||
"value": "~*req.SIP-AVP", "mandatory": true},
|
||||
{"tag": "SetupTime", "path": "*cgreq.SetupTime", "type": "*variable",
|
||||
"value": "~*req.Sip-Call-Setuptime", "mandatory": true},
|
||||
{"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*variable",
|
||||
"value": "~*req.Sip-Call-Created", "mandatory": true},
|
||||
{"tag": "RemoteAddr" , "path": "*cgreq.RemoteAddr", "type": "*variable",
|
||||
"value": "~*vars.RemoteHost:s/(.*):\\d+/${1}/"}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Accounting-Record-Type",
|
||||
"path": "*rep.Accounting-Record-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Accounting-Record-Type"
|
||||
},
|
||||
{
|
||||
"tag": "Accounting-Record-Number",
|
||||
"path": "*rep.Accounting-Record-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Accounting-Record-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "AccountingStop",
|
||||
"filters": ["*string:~*eq.Accounting-Record-Type:4"],
|
||||
"flags": ["*terminate", "*accounts", "*cdrs", "*log"],
|
||||
"request_fields":[
|
||||
{"tag": "Category", "path": "*cgreq.Category", "type": "*constant", "value": "call"},
|
||||
{"tag": "RequestType", "path": "*cgreq.RequestType", "type": "*constant",
|
||||
"value": "*prepaid", "mandatory": true},
|
||||
{"tag": "OriginID", "path": "*cgreq.OriginID", "type": "*variable",
|
||||
"value": "~*req.Session-Id", "mandatory": true},
|
||||
{"tag": "OriginHost", "path": "*cgreq.OriginHost", "type": "*variable",
|
||||
"value": "~*req.Origin-Host", "mandatory": true},
|
||||
{"tag": "Account", "path": "*cgreq.Account", "type": "*variable",
|
||||
"value": "~*req.User-Name", "mandatory": true},
|
||||
{"tag": "Subject", "path": "*cgreq.Subject", "type": "*variable",
|
||||
"value": "~*req.User-Name", "mandatory": true},
|
||||
{"tag": "Destination", "path": "*cgreq.Destination", "type": "*variable",
|
||||
"value": "~*req.Sip-To-Tag", "mandatory": true},
|
||||
{"tag": "SetupTime", "path": "*cgreq.SetupTime", "type": "*variable",
|
||||
"value": "~*req.Sip-Call-Setuptime", "mandatory": true},
|
||||
{"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*variable",
|
||||
"value": "~*req.Sip-Call-Created", "mandatory": true},
|
||||
{"tag": "Usage", "path": "*cgreq.Usage", "type": "*variable",
|
||||
"value": "~*req.Sip-Call-Duration", "mandatory": true},
|
||||
{"tag": "RemoteAddr" , "path": "*cgreq.RemoteAddr", "type": "*variable",
|
||||
"value": "~*vars.RemoteHost:s/(.*):\\d+/${1}/"}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Accounting-Record-Type",
|
||||
"path": "*rep.Accounting-Record-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Accounting-Record-Type"
|
||||
},
|
||||
{
|
||||
"tag": "Accounting-Record-Number",
|
||||
"path": "*rep.Accounting-Record-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Accounting-Record-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
139
data/tutorials/osips_diam/etc/cgrates/cc-postpaid.json
Normal file
139
data/tutorials/osips_diam/etc/cgrates/cc-postpaid.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
|
||||
"diameter_agent": {
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "SessionProcessCDR",
|
||||
"filters": [
|
||||
"*string:~*vars.*cmd:CCR",
|
||||
"*string:~*req.CC-Request-Type:4",
|
||||
"*prefix:~*req.Service-Context-Id:voice"
|
||||
],
|
||||
"flags": ["*cdrs", "*log"],
|
||||
"request_fields":[
|
||||
{
|
||||
"tag": "ToR",
|
||||
"path": "*cgreq.ToR",
|
||||
"type": "*constant",
|
||||
"value": "*voice"
|
||||
},
|
||||
{
|
||||
"tag": "OriginID",
|
||||
"path": "*cgreq.OriginID",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "OriginHost",
|
||||
"path": "*cgreq.OriginHost",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "RequestType",
|
||||
"path": "*cgreq.RequestType",
|
||||
"type": "*constant",
|
||||
"value": "*postpaid"
|
||||
},
|
||||
{
|
||||
"tag": "Account",
|
||||
"path": "*cgreq.Account",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Calling-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Destination",
|
||||
"path": "*cgreq.Destination",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Called-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "AnswerTime",
|
||||
"path": "*cgreq.AnswerTime",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Event-Timestamp",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Usage",
|
||||
"path": "*cgreq.Usage",
|
||||
"type": "*cc_usage",
|
||||
"mandatory": true,
|
||||
"value": "~*req.CC-Request-Number;~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/;5m"
|
||||
},
|
||||
{
|
||||
"tag": "LastUsed",
|
||||
"path": "*cgreq.LastUsed",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "SubscriberID",
|
||||
"path": "*cgreq.SubscriberId",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Subscription-Id.Subscription-Id-Data",
|
||||
"mandatory": true
|
||||
}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Auth-Application-Id",
|
||||
"path": "*rep.Auth-Application-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Auth-Application-Id"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Type",
|
||||
"path": "*rep.CC-Request-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Type"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Number",
|
||||
"path": "*rep.CC-Request-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
139
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-auth.json
Normal file
139
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-auth.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
|
||||
"diameter_agent": {
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "SessionAuth",
|
||||
"filters": [
|
||||
"*string:~*vars.*cmd:CCR",
|
||||
"*string:~*req.CC-Request-Type:1",
|
||||
"*prefix:~*req.Service-Context-Id:voice"
|
||||
],
|
||||
"flags": ["*authorize", "*accounts", "*log"],
|
||||
"request_fields":[
|
||||
{
|
||||
"tag": "ToR",
|
||||
"path": "*cgreq.ToR",
|
||||
"type": "*constant",
|
||||
"value": "*voice"
|
||||
},
|
||||
{
|
||||
"tag": "OriginID",
|
||||
"path": "*cgreq.OriginID",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "OriginHost",
|
||||
"path": "*cgreq.OriginHost",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "RequestType",
|
||||
"path": "*cgreq.RequestType",
|
||||
"type": "*constant",
|
||||
"value": "*prepaid",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Account",
|
||||
"path": "*cgreq.Account",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Calling-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Destination",
|
||||
"path": "*cgreq.Destination",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Called-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "SetupTime",
|
||||
"path": "*cgreq.SetupTime",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Event-Timestamp",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Usage",
|
||||
"path": "*cgreq.Usage",
|
||||
"type": "*variable",
|
||||
"mandatory": true,
|
||||
"value": "~*req.Requested-Service-Unit.CC-Time;s"
|
||||
},
|
||||
{
|
||||
"tag": "SubscriberID",
|
||||
"path": "*cgreq.SubscriberId",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Subscription-Id.Subscription-Id-Data",
|
||||
"mandatory": true
|
||||
}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Auth-Application-Id",
|
||||
"path": "*rep.Auth-Application-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Auth-Application-Id"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Type",
|
||||
"path": "*rep.CC-Request-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Type"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Number",
|
||||
"path": "*rep.CC-Request-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
},
|
||||
{
|
||||
"tag": "Granted-Units",
|
||||
"path": "*rep.Granted-Service-Unit.CC-Time",
|
||||
"type": "*variable",
|
||||
"value": "~*cgrep.MaxUsage{*duration_seconds}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
126
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-init.json
Normal file
126
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-init.json
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
|
||||
"diameter_agent": {
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "SessionInit",
|
||||
"filters": [
|
||||
"*string:~*vars.*cmd:CCR",
|
||||
"*string:~*req.CC-Request-Type:2",
|
||||
"*prefix:~*req.Service-Context-Id:voice"
|
||||
],
|
||||
"flags": ["*initiate", "*accounts", "*log"],
|
||||
"request_fields":[
|
||||
{
|
||||
"tag": "ToR",
|
||||
"path": "*cgreq.ToR",
|
||||
"type": "*constant",
|
||||
"value": "*voice"
|
||||
},
|
||||
{
|
||||
"tag": "OriginID",
|
||||
"path": "*cgreq.OriginID",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "OriginHost",
|
||||
"path": "*cgreq.OriginHost",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "RequestType",
|
||||
"path": "*cgreq.RequestType",
|
||||
"type": "*constant",
|
||||
"value": "*prepaid",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Account",
|
||||
"path": "*cgreq.Account",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Calling-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Destination",
|
||||
"path": "*cgreq.Destination",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Called-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "AnswerTime",
|
||||
"path": "*cgreq.AnswerTime",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Event-Timestamp",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "SubscriberID",
|
||||
"path": "*cgreq.SubscriberId",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Subscription-Id.Subscription-Id-Data",
|
||||
"mandatory": true
|
||||
}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Auth-Application-Id",
|
||||
"path": "*rep.Auth-Application-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Auth-Application-Id"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Type",
|
||||
"path": "*rep.CC-Request-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Type"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Number",
|
||||
"path": "*rep.CC-Request-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
145
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-terminate.json
Normal file
145
data/tutorials/osips_diam/etc/cgrates/cc-prepaid-terminate.json
Normal file
@@ -0,0 +1,145 @@
|
||||
{
|
||||
|
||||
"diameter_agent": {
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "SessionTerminate",
|
||||
"filters": [
|
||||
"*string:~*vars.*cmd:CCR",
|
||||
"*string:~*req.CC-Request-Type:3",
|
||||
"*prefix:~*req.Service-Context-Id:voice"
|
||||
],
|
||||
"flags": ["*terminate", "*accounts", "*cdrs", "*log"],
|
||||
"request_fields":[
|
||||
{
|
||||
"tag": "ToR",
|
||||
"path": "*cgreq.ToR",
|
||||
"type": "*constant",
|
||||
"value": "*voice"
|
||||
},
|
||||
{
|
||||
"tag": "OriginID",
|
||||
"path": "*cgreq.OriginID",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "OriginHost",
|
||||
"path": "*cgreq.OriginHost",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "RequestType",
|
||||
"path": "*cgreq.RequestType",
|
||||
"type": "*constant",
|
||||
"value": "*prepaid"
|
||||
},
|
||||
{
|
||||
"tag": "Account",
|
||||
"path": "*cgreq.Account",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Calling-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "Destination",
|
||||
"path": "*cgreq.Destination",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Service-Information.IMS-Information.Called-Party-Address",
|
||||
"mandatory": true
|
||||
},
|
||||
{
|
||||
"tag": "AnswerTime",
|
||||
"path": "*cgreq.AnswerTime",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Event-Timestamp",
|
||||
// "value": "~*req.Service-Information.IMS-Information.Time-Stamps.SIP-Request-Response",
|
||||
"mandatory": true
|
||||
},
|
||||
|
||||
// would using these assume that an update CCR request is sent at every debit interval?
|
||||
//
|
||||
// For now I commented them, and let have this just terminate and debit the cached session.
|
||||
// {
|
||||
// "tag": "Usage",
|
||||
// "path": "*cgreq.Usage",
|
||||
// "type": "*cc_usage",
|
||||
// "mandatory": true,
|
||||
// "value": "~*req.CC-Request-Number;~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/;5s"
|
||||
// },
|
||||
// {
|
||||
// "tag": "LastUsed",
|
||||
// "path": "*cgreq.LastUsed",
|
||||
// "type": "*variable",
|
||||
// "value": "~*req.Used-Service-Unit.CC-Time:s/(.*)/${1}s/",
|
||||
// "mandatory": true
|
||||
// },
|
||||
|
||||
{
|
||||
"tag": "SubscriberID",
|
||||
"path": "*cgreq.SubscriberId",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Subscription-Id.Subscription-Id-Data",
|
||||
"mandatory": true
|
||||
}
|
||||
],
|
||||
"reply_fields":[
|
||||
{
|
||||
"tag": "Session-Id",
|
||||
"path": "*rep.Session-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Session-Id"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Host",
|
||||
"path": "*rep.Origin-Host",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Host"
|
||||
},
|
||||
{
|
||||
"tag": "Origin-Realm",
|
||||
"path": "*rep.Origin-Realm",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Origin-Realm"
|
||||
},
|
||||
{
|
||||
"tag": "Auth-Application-Id",
|
||||
"path": "*rep.Auth-Application-Id",
|
||||
"type": "*variable",
|
||||
"value": "~*req.Auth-Application-Id"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Type",
|
||||
"path": "*rep.CC-Request-Type",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Type"
|
||||
},
|
||||
{
|
||||
"tag": "CC-Request-Number",
|
||||
"path": "*rep.CC-Request-Number",
|
||||
"type": "*variable",
|
||||
"value": "~*req.CC-Request-Number"
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"filters": ["*notempty:~*cgrep.Error:"],
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "5030",
|
||||
"blocker": true
|
||||
},
|
||||
{
|
||||
"tag": "ResultCode",
|
||||
"path": "*rep.Result-Code",
|
||||
"type": "*constant",
|
||||
"value": "2001"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
75
data/tutorials/osips_diam/etc/cgrates/cgrates.json
Normal file
75
data/tutorials/osips_diam/etc/cgrates/cgrates.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
|
||||
"general": {
|
||||
"log_level": 7
|
||||
},
|
||||
|
||||
"listen": {
|
||||
"rpc_json": ":2012",
|
||||
"rpc_gob": ":2013",
|
||||
"http": ":2080"
|
||||
},
|
||||
|
||||
|
||||
"stor_db": {
|
||||
"db_password": "CGRateS.org"
|
||||
},
|
||||
|
||||
"schedulers": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
"rals": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
"cdrs": {
|
||||
"enabled": true,
|
||||
"chargers_conns": ["*localhost"],
|
||||
"rals_conns": ["*localhost"],
|
||||
"sessions_cost_retries": 5
|
||||
},
|
||||
|
||||
"chargers": {
|
||||
"enabled": true,
|
||||
"attributes_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
"sessions": {
|
||||
"enabled": true,
|
||||
"listen_bijson": "127.0.0.1:2014",
|
||||
"chargers_conns": ["*localhost"],
|
||||
"rals_conns": ["*localhost"],
|
||||
"cdrs_conns": ["*localhost"],
|
||||
"attributes_conns": ["*localhost"],
|
||||
"debit_interval": "5s"
|
||||
},
|
||||
|
||||
"attributes": {
|
||||
"enabled": true,
|
||||
"string_indexed_fields": ["*req.Account"]
|
||||
},
|
||||
|
||||
"apiers": {
|
||||
"enabled": true,
|
||||
"scheduler_conns": ["*localhost"]
|
||||
},
|
||||
|
||||
"diameter_agent": {
|
||||
"enabled": true,
|
||||
"listen": "192.168.122.42:3868",
|
||||
"listen_net": "tcp",
|
||||
"dictionaries_path": "/usr/share/cgrates/diameter/dict/",
|
||||
"sessions_conns": ["*bijson_localhost"],
|
||||
"origin_host": "server.diameter.test",
|
||||
"origin_realm": "diameter.test",
|
||||
"vendor_id": 0,
|
||||
"product_name": "CGRateS",
|
||||
"concurrent_requests": -1,
|
||||
"synced_conn_requests": false,
|
||||
"asr_template": "*asr",
|
||||
"rar_template": "*rar",
|
||||
"forced_disconnect": "*asr"
|
||||
}
|
||||
|
||||
}
|
||||
94
data/tutorials/osips_diam/etc/opensips/dictionary.opensips
Normal file
94
data/tutorials/osips_diam/etc/opensips/dictionary.opensips
Normal file
@@ -0,0 +1,94 @@
|
||||
APPLICATION 4 Charging Control
|
||||
|
||||
ATTRIBUTE Result-Code 268 unsigned32
|
||||
ATTRIBUTE Value-Digits 447 integer64
|
||||
ATTRIBUTE Exponent 429 integer32
|
||||
ATTRIBUTE Unit-Value 445 grouped
|
||||
{
|
||||
Value-Digits | REQUIRED | 1
|
||||
Exponent | REQUIRED | 1
|
||||
}
|
||||
ATTRIBUTE Currency-Code 425 unsigned32
|
||||
ATTRIBUTE CC-Money 413 grouped
|
||||
{
|
||||
Unit-Value | REQUIRED | 1
|
||||
Currency-Code | REQUIRED | 1
|
||||
}
|
||||
ATTRIBUTE CC-Request-Number 415 unsigned32
|
||||
ATTRIBUTE CC-Request-Type 416 unsigned32
|
||||
ATTRIBUTE CC-Time 420 unsigned32
|
||||
ATTRIBUTE Granted-Service-Unit 431 grouped
|
||||
{
|
||||
CC-Time | OPTIONAL | 1
|
||||
CC-Money | OPTIONAL | 1
|
||||
}
|
||||
ATTRIBUTE Requested-Service-Unit 437 grouped
|
||||
{
|
||||
CC-Time | OPTIONAL | 1
|
||||
CC-Money | OPTIONAL | 1
|
||||
}
|
||||
ATTRIBUTE Subscription-Id-Type 450 unsigned32
|
||||
ATTRIBUTE Subscription-Id-Data 444 string
|
||||
ATTRIBUTE Subscription-Id 443 grouped
|
||||
{
|
||||
Subscription-Id-Type | REQUIRED | 1
|
||||
Subscription-Id-Data | REQUIRED | 1
|
||||
}
|
||||
ATTRIBUTE Used-Service-Unit 446 grouped
|
||||
{
|
||||
CC-Time | OPTIONAL | 1
|
||||
CC-Money | OPTIONAL | 1
|
||||
}
|
||||
ATTRIBUTE Service-Context-Id 461 string
|
||||
|
||||
VENDOR 10415 TGPP
|
||||
ATTRIBUTE Calling-Party-Address 831 string 10415
|
||||
ATTRIBUTE Called-Party-Address 832 string 10415
|
||||
ATTRIBUTE SIP-Request-Timestamp 2301 unsigned32 10415
|
||||
ATTRIBUTE SIP-Response-Timestamp 834 string 10415
|
||||
ATTRIBUTE Time-Stamps 833 grouped 10415
|
||||
{
|
||||
SIP-Request-Timestamp | OPTIONAL | 1
|
||||
SIP-Response-Timestamp | OPTIONAL | 1
|
||||
}
|
||||
ATTRIBUTE IMS-Information 876 grouped 10415
|
||||
{
|
||||
Calling-Party-Address | OPTIONAL | 1
|
||||
Called-Party-Address | OPTIONAL | 1
|
||||
Time-Stamps | OPTIONAL | 1
|
||||
}
|
||||
ATTRIBUTE Service-Information 873 grouped 10415
|
||||
{
|
||||
IMS-Information | OPTIONAL | 1
|
||||
}
|
||||
|
||||
REQUEST 272 Credit-Control-Request
|
||||
{
|
||||
Session-Id | REQUIRED | 1
|
||||
Origin-Host | REQUIRED | 1
|
||||
Origin-Realm | REQUIRED | 1
|
||||
Destination-Realm | REQUIRED | 1
|
||||
Auth-Application-Id | REQUIRED | 1
|
||||
Service-Context-Id | REQUIRED | 1
|
||||
CC-Request-Type | REQUIRED | 1
|
||||
CC-Request-Number | REQUIRED | 1
|
||||
Event-Timestamp | OPTIONAL | 1
|
||||
User-Name | OPTIONAL | 1
|
||||
Subscription-Id | OPTIONAL | 1
|
||||
Requested-Service-Unit | OPTIONAL | 1
|
||||
Used-Service-Unit | OPTIONAL | 1
|
||||
Service-Information | OPTIONAL | 1
|
||||
Termination-Cause | OPTIONAL | 1
|
||||
}
|
||||
|
||||
ANSWER 272 Credit-Control-Answer
|
||||
{
|
||||
Result-Code | OPTIONAL | 1
|
||||
Session-Id | OPTIONAL | 1
|
||||
Origin-Host | OPTIONAL | 1
|
||||
Origin-Realm | OPTIONAL | 1
|
||||
CC-Request-Type | OPTIONAL | 1
|
||||
CC-Request-Number | OPTIONAL | 1
|
||||
Granted-Service-Unit | OPTIONAL | 1
|
||||
Route-Record | OPTIONAL | 1
|
||||
}
|
||||
278
data/tutorials/osips_diam/etc/opensips/opensips_acc.cfg
Normal file
278
data/tutorials/osips_diam/etc/opensips/opensips_acc.cfg
Normal file
@@ -0,0 +1,278 @@
|
||||
#
|
||||
# OpenSIPS residential configuration script
|
||||
# by OpenSIPS Solutions <team@opensips-solutions.com>
|
||||
#
|
||||
# This script was generated via "make menuconfig", from
|
||||
# the "Residential" scenario.
|
||||
# You can enable / disable more features / functionalities by
|
||||
# re-generating the scenario with different options.#
|
||||
#
|
||||
# Please refer to the Core CookBook at:
|
||||
# https://opensips.org/Resources/DocsCookbooks
|
||||
# for a explanation of possible statements, functions and parameters.
|
||||
#
|
||||
|
||||
|
||||
####### Global Parameters #########
|
||||
|
||||
debug_mode=no
|
||||
log_stdout=yes
|
||||
log_level=3
|
||||
xlog_level=3
|
||||
stderror_enabled=no
|
||||
syslog_enabled=yes
|
||||
syslog_facility=LOG_LOCAL0
|
||||
|
||||
udp_workers=4
|
||||
|
||||
socket=udp:enp0s3:5060
|
||||
socket=udp:127.0.0.1:5060
|
||||
|
||||
####### Modules Section ########
|
||||
|
||||
#set module path
|
||||
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
|
||||
|
||||
#### SIGNALING module
|
||||
loadmodule "signaling.so"
|
||||
|
||||
#### StateLess module
|
||||
loadmodule "sl.so"
|
||||
|
||||
#### Transaction Module
|
||||
loadmodule "tm.so"
|
||||
modparam("tm", "fr_timeout", 5)
|
||||
modparam("tm", "fr_inv_timeout", 30)
|
||||
modparam("tm", "restart_fr_on_each_reply", 0)
|
||||
modparam("tm", "onreply_avp_mode", 1)
|
||||
|
||||
#### Record Route Module
|
||||
loadmodule "rr.so"
|
||||
modparam("rr", "append_fromtag", 0)
|
||||
|
||||
#### MAX ForWarD module
|
||||
loadmodule "maxfwd.so"
|
||||
|
||||
#### SIP MSG OPerationS module
|
||||
loadmodule "sipmsgops.so"
|
||||
|
||||
#### FIFO Management Interface
|
||||
loadmodule "mi_fifo.so"
|
||||
modparam("mi_fifo", "fifo_name", "/run/opensips/opensips_fifo")
|
||||
modparam("mi_fifo", "fifo_mode", 0666)
|
||||
|
||||
#### USeR LOCation module
|
||||
loadmodule "usrloc.so"
|
||||
modparam("usrloc", "nat_bflag", "NAT")
|
||||
modparam("usrloc", "working_mode_preset", "single-instance-no-db")
|
||||
|
||||
#### REGISTRAR module
|
||||
loadmodule "registrar.so"
|
||||
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
|
||||
#modparam("registrar", "max_contacts", 10)
|
||||
|
||||
#### ACCounting module
|
||||
loadmodule "acc.so"
|
||||
modparam("acc", "early_media", 0)
|
||||
modparam("acc", "report_cancels", 0)
|
||||
modparam("acc", "detect_direction", 0)
|
||||
modparam("acc", "aaa_url", "diameter:/etc/freeDiameter/freeDiameter.conf")
|
||||
|
||||
# Adding some AVPs to identify account and destination. No idea what AVP to use
|
||||
# for destination. Went for SIP-AVP.
|
||||
modparam("acc", "extra_fields", "aaa: account -> User-Name ; destination -> SIP-AVP")
|
||||
|
||||
# Sip-Session
|
||||
modparam("acc", "service_type", 15)
|
||||
|
||||
loadmodule "proto_udp.so"
|
||||
|
||||
#### Dialog module
|
||||
loadmodule "dialog.so"
|
||||
|
||||
#### Auth modules (not used in this cfg)
|
||||
loadmodule "auth.so"
|
||||
loadmodule "auth_aaa.so"
|
||||
modparam("auth_aaa", "aaa_url", "diameter:/etc/freeDiameter/freeDiameter.conf")
|
||||
|
||||
#### Diameter module
|
||||
loadmodule "aaa_diameter.so"
|
||||
modparam("aaa_diameter", "fd_log_level", 0)
|
||||
modparam("aaa_diameter", "realm", "diameter.test")
|
||||
modparam("aaa_diameter", "peer_identity", "server")
|
||||
|
||||
####### Routing Logic ########
|
||||
|
||||
# main request routing logic
|
||||
|
||||
route{
|
||||
|
||||
if (!mf_process_maxfwd_header(10)) {
|
||||
send_reply(483,"Too Many Hops");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (has_totag()) {
|
||||
|
||||
# handle hop-by-hop ACK (no routing required)
|
||||
if ( is_method("ACK") && t_check_trans() ) {
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# sequential request within a dialog should
|
||||
# take the path determined by record-routing
|
||||
if ( !loose_route() ) {
|
||||
# we do record-routing for all our traffic, so we should not
|
||||
# receive any sequential requests without Route hdr.
|
||||
send_reply(404,"Not here");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_method("BYE")) {
|
||||
# do accounting even if the transaction fails
|
||||
do_accounting("log","failed");
|
||||
}
|
||||
|
||||
# route it out to whatever destination was set by loose_route()
|
||||
# in $du (destination URI).
|
||||
route(relay);
|
||||
exit;
|
||||
}
|
||||
|
||||
# CANCEL processing
|
||||
if (is_method("CANCEL")) {
|
||||
if (t_check_trans())
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# absorb retransmissions, but do not create transaction
|
||||
t_check_trans();
|
||||
|
||||
if ( !(is_method("REGISTER") ) ) {
|
||||
|
||||
if (is_myself("$fd")) {
|
||||
|
||||
} else {
|
||||
# if caller is not local, then called number must be local
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
send_reply(403,"Relay Forbidden");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# preloaded route checking
|
||||
if (loose_route()) {
|
||||
xlog("L_ERR",
|
||||
"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
|
||||
if (!is_method("ACK"))
|
||||
send_reply(403,"Preload Route denied");
|
||||
exit;
|
||||
}
|
||||
|
||||
# record routing
|
||||
if (!is_method("REGISTER|MESSAGE"))
|
||||
record_route();
|
||||
|
||||
# account only INVITEs
|
||||
if (is_method("INVITE")) {
|
||||
|
||||
# if (!aaa_proxy_authorize("$fd")){
|
||||
# proxy_challenge("$fd");
|
||||
# exit;
|
||||
# }
|
||||
|
||||
$acc_extra(account) = $fU;
|
||||
$acc_extra(destination) = $rU;
|
||||
|
||||
# this sends an accounting start on hangup/timeout. Not
|
||||
# sure how to set up accounting to send Accounting-Start
|
||||
# on answer and Accounting-Stop on hangup.
|
||||
do_accounting("aaa", "cdr");
|
||||
}
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
append_hf("P-hint: outbound\r\n");
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
# requests for my domain
|
||||
|
||||
if (is_method("PUBLISH|SUBSCRIBE")) {
|
||||
send_reply(503, "Service Unavailable");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_method("REGISTER")) {
|
||||
# store the registration and generate a SIP reply
|
||||
if (!save("location"))
|
||||
xlog("failed to register AoR $tu\n");
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($rU==NULL) {
|
||||
# request with no Username in RURI
|
||||
send_reply(484,"Address Incomplete");
|
||||
exit;
|
||||
}
|
||||
|
||||
# do lookup with method filtering
|
||||
if (!lookup("location","method-filtering")) {
|
||||
t_reply(404, "Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
do_accounting("log","missed");
|
||||
route(relay);
|
||||
}
|
||||
|
||||
route[relay] {
|
||||
# for INVITEs enable some additional helper routes
|
||||
if (is_method("INVITE")) {
|
||||
t_on_branch("per_branch_ops");
|
||||
t_on_reply("handle_nat");
|
||||
t_on_failure("missed_call");
|
||||
}
|
||||
|
||||
if (!t_relay()) {
|
||||
send_reply(500,"Internal Error");
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
branch_route[per_branch_ops] {
|
||||
xlog("new branch at $ru\n");
|
||||
}
|
||||
|
||||
|
||||
onreply_route[handle_nat] {
|
||||
xlog("incoming reply\n");
|
||||
}
|
||||
|
||||
|
||||
failure_route[missed_call] {
|
||||
if (t_was_cancelled()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
# uncomment the following lines if you want to block client
|
||||
# redirect based on 3xx replies.
|
||||
##if (t_check_status("3[0-9][0-9]")) {
|
||||
##t_reply(404,"Not found");
|
||||
## exit;
|
||||
##}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
309
data/tutorials/osips_diam/etc/opensips/opensips_ccr_postpaid.cfg
Normal file
309
data/tutorials/osips_diam/etc/opensips/opensips_ccr_postpaid.cfg
Normal file
@@ -0,0 +1,309 @@
|
||||
#
|
||||
# OpenSIPS residential configuration script
|
||||
# by OpenSIPS Solutions <team@opensips-solutions.com>
|
||||
#
|
||||
# This script was generated via "make menuconfig", from
|
||||
# the "Residential" scenario.
|
||||
# You can enable / disable more features / functionalities by
|
||||
# re-generating the scenario with different options.#
|
||||
#
|
||||
# Please refer to the Core CookBook at:
|
||||
# https://opensips.org/Resources/DocsCookbooks
|
||||
# for a explanation of possible statements, functions and parameters.
|
||||
#
|
||||
|
||||
|
||||
####### Global Parameters #########
|
||||
|
||||
debug_mode=no
|
||||
log_stdout=yes
|
||||
log_level=3
|
||||
xlog_level=3
|
||||
stderror_enabled=no
|
||||
syslog_enabled=yes
|
||||
syslog_facility=LOG_LOCAL0
|
||||
|
||||
udp_workers=4
|
||||
|
||||
socket=udp:enp0s3:5060
|
||||
socket=udp:127.0.0.1:5060
|
||||
|
||||
####### Modules Section ########
|
||||
|
||||
#set module path
|
||||
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
|
||||
|
||||
#### SIGNALING module
|
||||
loadmodule "signaling.so"
|
||||
|
||||
#### StateLess module
|
||||
loadmodule "sl.so"
|
||||
|
||||
#### Transaction Module
|
||||
loadmodule "tm.so"
|
||||
modparam("tm", "fr_timeout", 5)
|
||||
modparam("tm", "fr_inv_timeout", 30)
|
||||
modparam("tm", "restart_fr_on_each_reply", 0)
|
||||
modparam("tm", "onreply_avp_mode", 1)
|
||||
|
||||
#### Record Route Module
|
||||
loadmodule "rr.so"
|
||||
modparam("rr", "append_fromtag", 0)
|
||||
|
||||
#### MAX ForWarD module
|
||||
loadmodule "maxfwd.so"
|
||||
|
||||
#### SIP MSG OPerationS module
|
||||
loadmodule "sipmsgops.so"
|
||||
|
||||
#### FIFO Management Interface
|
||||
loadmodule "mi_fifo.so"
|
||||
modparam("mi_fifo", "fifo_name", "/run/opensips/opensips_fifo")
|
||||
modparam("mi_fifo", "fifo_mode", 0666)
|
||||
|
||||
#### USeR LOCation module
|
||||
loadmodule "usrloc.so"
|
||||
modparam("usrloc", "nat_bflag", "NAT")
|
||||
modparam("usrloc", "working_mode_preset", "single-instance-no-db")
|
||||
|
||||
#### REGISTRAR module
|
||||
loadmodule "registrar.so"
|
||||
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
|
||||
|
||||
loadmodule "proto_udp.so"
|
||||
|
||||
#### Dialog module
|
||||
loadmodule "dialog.so"
|
||||
|
||||
#### Exec module
|
||||
loadmodule "exec.so"
|
||||
|
||||
|
||||
#### Diameter module
|
||||
loadmodule "aaa_diameter.so"
|
||||
modparam("aaa_diameter", "fd_log_level", 0)
|
||||
modparam("aaa_diameter", "realm", "diameter.test")
|
||||
modparam("aaa_diameter", "peer_identity", "server")
|
||||
modparam("aaa_diameter", "aaa_url", "diameter:/etc/freeDiameter/freeDiameter.conf;extra-avps-file:/etc/opensips/dictionary.opensips")
|
||||
|
||||
####### Routing Logic ########
|
||||
|
||||
# main request routing logic
|
||||
|
||||
route{
|
||||
|
||||
if (!mf_process_maxfwd_header(10)) {
|
||||
send_reply(483,"Too Many Hops");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (has_totag()) {
|
||||
|
||||
# handle hop-by-hop ACK (no routing required)
|
||||
if ( is_method("ACK") && t_check_trans() ) {
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# sequential request within a dialog should
|
||||
# take the path determined by record-routing
|
||||
if ( !loose_route() ) {
|
||||
# we do record-routing for all our traffic, so we should not
|
||||
# receive any sequential requests without Route hdr.
|
||||
send_reply(404,"Not here");
|
||||
exit;
|
||||
}
|
||||
|
||||
# if (is_method("BYE")) {
|
||||
# # do accounting even if the transaction fails
|
||||
# do_accounting("log","failed");
|
||||
# }
|
||||
|
||||
# route it out to whatever destination was set by loose_route()
|
||||
# in $du (destination URI).
|
||||
route(relay);
|
||||
exit;
|
||||
}
|
||||
|
||||
# CANCEL processing
|
||||
if (is_method("CANCEL")) {
|
||||
if (t_check_trans())
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# absorb retransmissions, but do not create transaction
|
||||
t_check_trans();
|
||||
|
||||
if ( !(is_method("REGISTER") ) ) {
|
||||
|
||||
if (is_myself("$fd")) {
|
||||
|
||||
} else {
|
||||
# if caller is not local, then called number must be local
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
send_reply(403,"Relay Forbidden");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# preloaded route checking
|
||||
if (loose_route()) {
|
||||
xlog("L_ERR",
|
||||
"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
|
||||
if (!is_method("ACK"))
|
||||
send_reply(403,"Preload Route denied");
|
||||
exit;
|
||||
}
|
||||
|
||||
# record routing
|
||||
if (!is_method("REGISTER|MESSAGE"))
|
||||
record_route();
|
||||
|
||||
# account only INVITEs
|
||||
if (is_method("INVITE")) {
|
||||
|
||||
create_dialog();
|
||||
$dlg_val(callid) = $ci;
|
||||
$dlg_val(originhost) = $(ou{uri.host});
|
||||
$dlg_val(originrealm) = $fd;
|
||||
$dlg_val(setuptime) = $Ts;
|
||||
$dlg_val(account) = $fU;
|
||||
$dlg_val(destination) = $rU;
|
||||
|
||||
# we need an answer handler to record answertime for cdr processing
|
||||
dlg_on_answer("handle_answer");
|
||||
|
||||
# would probably be a good idea to have a timeout handler also
|
||||
dlg_on_hangup("handle_hangup");
|
||||
}
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
append_hf("P-hint: outbound\r\n");
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
# requests for my domain
|
||||
|
||||
if (is_method("PUBLISH|SUBSCRIBE")) {
|
||||
send_reply(503, "Service Unavailable");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_method("REGISTER")) {
|
||||
# store the registration and generate a SIP reply
|
||||
if (!save("location"))
|
||||
xlog("failed to register AoR $tu\n");
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($rU==NULL) {
|
||||
# request with no Username in RURI
|
||||
send_reply(484,"Address Incomplete");
|
||||
exit;
|
||||
}
|
||||
|
||||
# do lookup with method filtering
|
||||
if (!lookup("location","method-filtering")) {
|
||||
t_reply(404, "Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
route[handle_answer] {
|
||||
$dlg_val(answertime) = $Ts;
|
||||
xlog("$$dlg_val(answertime) 1 = $dlg_val(answertime)\n");
|
||||
}
|
||||
|
||||
route[handle_hangup] {
|
||||
$var(duration) = $Ts - $dlg_val(answertime);
|
||||
exec("/usr/share/cgrates/tutorials/osips_diam/etc/opensips/unix2ntp", "$dlg_val(answertime)", $var(answertime32bit), , );
|
||||
$var(payload) = "[
|
||||
{ \"Session-Id\": \"" + $dlg_val(callid) + "\" },
|
||||
{ \"Origin-Host\": \"client.diameter.test\" },
|
||||
{ \"Origin-Realm\": \"diameter.test\" },
|
||||
{ \"Destination-Realm\": \"diameter.test\" },
|
||||
{ \"Service-Context-Id\": \"voice@OsipsDiamCCR\" },
|
||||
{ \"CC-Request-Type\": 4 },
|
||||
{ \"CC-Request-Number\": 0 },
|
||||
{ \"Termination-Cause\": 1 },
|
||||
{ \"Event-Timestamp\": \"" + $var(answertime32bit) + "\" },
|
||||
{ \"User-Name\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Subscription-Id\": [
|
||||
{ \"Subscription-Id-Type\": 0 },
|
||||
{ \"Subscription-Id-Data\": \"" + $dlg_val(account) + "\" }
|
||||
]},
|
||||
{ \"Requested-Service-Unit\": [
|
||||
{\"CC-Time\": 0}
|
||||
]},
|
||||
{ \"Used-Service-Unit\": [
|
||||
{\"CC-Time\": " + $var(duration) + " }
|
||||
]},
|
||||
{ \"Service-Information\": [
|
||||
{\"IMS-Information\": [
|
||||
{ \"Calling-Party-Address\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Called-Party-Address\": \"" + $dlg_val(destination) + "\" }
|
||||
]}
|
||||
]}
|
||||
]";
|
||||
|
||||
dm_send_request(4, 272, $var(payload), $var(rpl_avps));
|
||||
if ($rc < 1) {
|
||||
xlog("error processing diameter request (returned $rc), received reply: $var(rpl_avps)");
|
||||
exit;
|
||||
}
|
||||
route(relay);
|
||||
}
|
||||
|
||||
|
||||
route[relay] {
|
||||
# for INVITEs enable some additional helper routes
|
||||
if (is_method("INVITE")) {
|
||||
t_on_branch("per_branch_ops");
|
||||
t_on_reply("handle_nat");
|
||||
t_on_failure("missed_call");
|
||||
}
|
||||
|
||||
if (!t_relay()) {
|
||||
send_reply(500,"Internal Error");
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
branch_route[per_branch_ops] {
|
||||
xlog("new branch at $ru\n");
|
||||
}
|
||||
|
||||
|
||||
onreply_route[handle_nat] {
|
||||
xlog("incoming reply\n");
|
||||
}
|
||||
|
||||
|
||||
failure_route[missed_call] {
|
||||
if (t_was_cancelled()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
# uncomment the following lines if you want to block client
|
||||
# redirect based on 3xx replies.
|
||||
##if (t_check_status("3[0-9][0-9]")) {
|
||||
##t_reply(404,"Not found");
|
||||
## exit;
|
||||
##}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
440
data/tutorials/osips_diam/etc/opensips/opensips_ccr_prepaid.cfg
Normal file
440
data/tutorials/osips_diam/etc/opensips/opensips_ccr_prepaid.cfg
Normal file
@@ -0,0 +1,440 @@
|
||||
#
|
||||
# OpenSIPS residential configuration script
|
||||
# by OpenSIPS Solutions <team@opensips-solutions.com>
|
||||
#
|
||||
# This script was generated via "make menuconfig", from
|
||||
# the "Residential" scenario.
|
||||
# You can enable / disable more features / functionalities by
|
||||
# re-generating the scenario with different options.#
|
||||
#
|
||||
# Please refer to the Core CookBook at:
|
||||
# https://opensips.org/Resources/DocsCookbooks
|
||||
# for a explanation of possible statements, functions and parameters.
|
||||
#
|
||||
|
||||
|
||||
####### Global Parameters #########
|
||||
|
||||
debug_mode=no
|
||||
log_stdout = yes
|
||||
log_level=3
|
||||
xlog_level=3
|
||||
stderror_enabled=no
|
||||
syslog_enabled=yes
|
||||
syslog_facility=LOG_LOCAL0
|
||||
|
||||
udp_workers=4
|
||||
|
||||
socket=udp:enp0s3:5060
|
||||
socket=udp:127.0.0.1:5060
|
||||
|
||||
####### Modules Section ########
|
||||
|
||||
#set module path
|
||||
mpath="/usr/lib/x86_64-linux-gnu/opensips/modules/"
|
||||
|
||||
#### SIGNALING module
|
||||
loadmodule "signaling.so"
|
||||
|
||||
#### StateLess module
|
||||
loadmodule "sl.so"
|
||||
|
||||
#### Transaction Module
|
||||
loadmodule "tm.so"
|
||||
modparam("tm", "fr_timeout", 5)
|
||||
modparam("tm", "fr_inv_timeout", 30)
|
||||
modparam("tm", "restart_fr_on_each_reply", 0)
|
||||
modparam("tm", "onreply_avp_mode", 1)
|
||||
|
||||
#### Record Route Module
|
||||
loadmodule "rr.so"
|
||||
modparam("rr", "append_fromtag", 0)
|
||||
|
||||
#### MAX ForWarD module
|
||||
loadmodule "maxfwd.so"
|
||||
|
||||
#### SIP MSG OPerationS module
|
||||
loadmodule "sipmsgops.so"
|
||||
|
||||
#### FIFO Management Interface
|
||||
loadmodule "mi_fifo.so"
|
||||
modparam("mi_fifo", "fifo_name", "/run/opensips/opensips_fifo")
|
||||
modparam("mi_fifo", "fifo_mode", 0666)
|
||||
|
||||
#### USeR LOCation module
|
||||
loadmodule "usrloc.so"
|
||||
modparam("usrloc", "nat_bflag", "NAT")
|
||||
modparam("usrloc", "working_mode_preset", "single-instance-no-db")
|
||||
|
||||
#### REGISTRAR module
|
||||
loadmodule "registrar.so"
|
||||
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
|
||||
#modparam("registrar", "max_contacts", 10)
|
||||
|
||||
loadmodule "proto_udp.so"
|
||||
|
||||
#### Dialog module
|
||||
loadmodule "dialog.so"
|
||||
|
||||
#### Exec module
|
||||
loadmodule "exec.so"
|
||||
|
||||
#### JSON module
|
||||
loadmodule "json.so"
|
||||
|
||||
#### Diameter module
|
||||
loadmodule "aaa_diameter.so"
|
||||
modparam("aaa_diameter", "fd_log_level", 0)
|
||||
modparam("aaa_diameter", "realm", "diameter.test")
|
||||
modparam("aaa_diameter", "peer_identity", "server")
|
||||
modparam("aaa_diameter", "aaa_url", "diameter:/etc/freeDiameter/freeDiameter.conf;extra-avps-file:/etc/opensips/dictionary.opensips")
|
||||
|
||||
####### Routing Logic ########
|
||||
|
||||
# main request routing logic
|
||||
|
||||
route{
|
||||
|
||||
if (!mf_process_maxfwd_header(10)) {
|
||||
send_reply(483,"Too Many Hops");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (has_totag()) {
|
||||
|
||||
# handle hop-by-hop ACK (no routing required)
|
||||
if ( is_method("ACK") && t_check_trans() ) {
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# sequential request within a dialog should
|
||||
# take the path determined by record-routing
|
||||
if ( !loose_route() ) {
|
||||
# we do record-routing for all our traffic, so we should not
|
||||
# receive any sequential requests without Route hdr.
|
||||
send_reply(404,"Not here");
|
||||
exit;
|
||||
}
|
||||
|
||||
# route it out to whatever destination was set by loose_route()
|
||||
# in $du (destination URI).
|
||||
route(relay);
|
||||
exit;
|
||||
}
|
||||
|
||||
# CANCEL processing
|
||||
if (is_method("CANCEL")) {
|
||||
if (t_check_trans())
|
||||
t_relay();
|
||||
exit;
|
||||
}
|
||||
|
||||
# absorb retransmissions, but do not create transaction
|
||||
t_check_trans();
|
||||
|
||||
if ( !(is_method("REGISTER") ) ) {
|
||||
|
||||
if (is_myself("$fd")) {
|
||||
|
||||
} else {
|
||||
# if caller is not local, then called number must be local
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
send_reply(403,"Relay Forbidden");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# preloaded route checking
|
||||
if (loose_route()) {
|
||||
xlog("L_ERR",
|
||||
"Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
|
||||
if (!is_method("ACK"))
|
||||
send_reply(403,"Preload Route denied");
|
||||
exit;
|
||||
}
|
||||
|
||||
# record routing
|
||||
if (!is_method("REGISTER|MESSAGE"))
|
||||
record_route();
|
||||
|
||||
# account only INVITEs
|
||||
if (is_method("INVITE")) {
|
||||
|
||||
create_dialog();
|
||||
|
||||
# populate dialog variables to use them inside handlers
|
||||
$dlg_val(setuptime) = $Ts;
|
||||
$dlg_val(callid) = $ci;
|
||||
$dlg_val(originhost) = $(ou{uri.host});
|
||||
$dlg_val(originrealm) = $fd;
|
||||
$dlg_val(account) = $fU;
|
||||
$dlg_val(destination) = $rU;
|
||||
|
||||
# use the unix2ntp helper script to convert unix time to 32bit format
|
||||
# for the Event-Timestamp AVP
|
||||
# can this be done directly inside the cfg file?
|
||||
exec("/usr/share/cgrates/tutorials/osips_diam/etc/opensips/unix2ntp", "$dlg_val(setuptime)", $var(setuptime32bit), , );
|
||||
|
||||
# Send blocking CCR INITIAL_REQUEST and retrieve MaxUsage
|
||||
$var(payload) = "[
|
||||
{ \"Session-Id\": \"" + $dlg_val(callid) + "\" },
|
||||
{ \"Origin-Host\": \"client.diameter.test\" },
|
||||
{ \"Origin-Realm\": \"diameter.test\" },
|
||||
{ \"Destination-Realm\": \"diameter.test\" },
|
||||
{ \"Service-Context-Id\": \"voice@OsipsDiamCCR\" },
|
||||
{ \"CC-Request-Type\": 1 },
|
||||
{ \"CC-Request-Number\": 0 },
|
||||
{ \"Event-Timestamp\": \"" + $var(setuptime32bit) + "\" },
|
||||
{ \"User-Name\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Subscription-Id\": [
|
||||
{ \"Subscription-Id-Type\": 0 },
|
||||
{ \"Subscription-Id-Data\": \"" + $dlg_val(account) + "\" }
|
||||
]},
|
||||
{ \"Requested-Service-Unit\": [
|
||||
{\"CC-Time\": 10800}
|
||||
]},
|
||||
{ \"Service-Information\": [
|
||||
{\"IMS-Information\": [
|
||||
{ \"Calling-Party-Address\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Called-Party-Address\": \"" + $dlg_val(destination) + "\" }
|
||||
]}
|
||||
]}
|
||||
]";
|
||||
|
||||
# send the diameter request
|
||||
dm_send_request(4, 272, $var(payload), $var(rpl_avps));
|
||||
|
||||
# handle the diameter reply
|
||||
$json(rpl) := $var(rpl_avps);
|
||||
if ($rc != 1) {
|
||||
xlog("L_NOTICE", "failed to send diameter request: rc=$rc\n");
|
||||
send_reply(403, "Forbidden");
|
||||
exit;
|
||||
}
|
||||
|
||||
# check Result-Code coming from diameter server
|
||||
# is there a way to index directly by the name of the key without knowing the index first?
|
||||
if ($json(rpl[5]/Result-Code) != 2001) {
|
||||
xlog("L_NOTICE", "failed to authorize session (Result-Code=$json(rpl[5]/Result-Code))\n");
|
||||
send_reply(403, "Forbidden");
|
||||
exit;
|
||||
}
|
||||
|
||||
# set dialog timeout based on the received Granted-Service-Unit AVP
|
||||
$DLG_timeout = $json(rpl[6]/Granted-Service-Unit[0]/CC-Time);
|
||||
|
||||
# dialog handlers
|
||||
# only send async requests due to issue detailed at the bottom of the cfg file
|
||||
dlg_on_answer("handle_answer");
|
||||
dlg_on_hangup("handle_hangup");
|
||||
dlg_on_timeout("handle_timeout");
|
||||
}
|
||||
|
||||
if (!is_myself("$rd")) {
|
||||
append_hf("P-hint: outbound\r\n");
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
# requests for my domain
|
||||
|
||||
if (is_method("PUBLISH|SUBSCRIBE")) {
|
||||
send_reply(503, "Service Unavailable");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (is_method("REGISTER")) {
|
||||
# store the registration and generate a SIP reply
|
||||
if (!save("location"))
|
||||
xlog("failed to register AoR $tu\n");
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($rU==NULL) {
|
||||
# request with no Username in RURI
|
||||
send_reply(484,"Address Incomplete");
|
||||
exit;
|
||||
}
|
||||
|
||||
# do lookup with method filtering
|
||||
if (!lookup("location","method-filtering")) {
|
||||
t_reply(404, "Not Found");
|
||||
exit;
|
||||
}
|
||||
|
||||
route(relay);
|
||||
}
|
||||
|
||||
route[handle_answer] {
|
||||
$dlg_val(answertime) = $Ts;
|
||||
exec("/usr/share/cgrates/tutorials/osips_diam/etc/opensips/unix2ntp", "$dlg_val(answertime)", $dlg_val(answertime32bit), , );
|
||||
$var(payload) = "[
|
||||
{ \"Session-Id\": \"" + $dlg_val(callid) + "\" },
|
||||
{ \"Origin-Host\": \"client.diameter.test\" },
|
||||
{ \"Origin-Realm\": \"diameter.test\" },
|
||||
{ \"Destination-Realm\": \"diameter.test\" },
|
||||
{ \"Service-Context-Id\": \"voice@OsipsDiamCCR\" },
|
||||
{ \"CC-Request-Type\": 2 },
|
||||
{ \"CC-Request-Number\": 1 },
|
||||
{ \"Event-Timestamp\": \"" + $dlg_val(answertime32bit) + "\" },
|
||||
{ \"User-Name\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Subscription-Id\": [
|
||||
{ \"Subscription-Id-Type\": 0 },
|
||||
{ \"Subscription-Id-Data\": \"" + $dlg_val(account) + "\" }
|
||||
]},
|
||||
{ \"Requested-Service-Unit\": [
|
||||
{\"CC-Time\": 0}
|
||||
]},
|
||||
{ \"Service-Information\": [
|
||||
{\"IMS-Information\": [
|
||||
{ \"Calling-Party-Address\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Called-Party-Address\": \"" + $dlg_val(destination) + "\" }
|
||||
]}
|
||||
]}
|
||||
]";
|
||||
|
||||
async(dm_send_request(4, 272, $var(payload), $var(rpl_avps)), dm_reply);
|
||||
|
||||
}
|
||||
|
||||
route[handle_hangup] {
|
||||
$var(duration1) = $Ts - $dlg_val(answertime);
|
||||
$var(payload) = "[
|
||||
{ \"Session-Id\": \"" + $dlg_val(callid) + "\" },
|
||||
{ \"Origin-Host\": \"client.diameter.test\" },
|
||||
{ \"Origin-Realm\": \"diameter.test\" },
|
||||
{ \"Destination-Realm\": \"diameter.test\" },
|
||||
{ \"Service-Context-Id\": \"voice@OsipsDiamCCR\" },
|
||||
{ \"CC-Request-Type\": 3 },
|
||||
{ \"CC-Request-Number\": 2 },
|
||||
{ \"Termination-Cause\": 1 },
|
||||
{ \"Event-Timestamp\": \"" + $dlg_val(answertime32bit) + "\" },
|
||||
{ \"User-Name\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Subscription-Id\": [
|
||||
{ \"Subscription-Id-Type\": 0 },
|
||||
{ \"Subscription-Id-Data\": \"" + $dlg_val(account) + "\" }
|
||||
]},
|
||||
{ \"Used-Service-Unit\": [
|
||||
{\"CC-Time\": " + $var(duration1) + " }
|
||||
]},
|
||||
{ \"Service-Information\": [
|
||||
{\"IMS-Information\": [
|
||||
{ \"Calling-Party-Address\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Called-Party-Address\": \"" + $dlg_val(destination) + "\" }
|
||||
]}
|
||||
]}
|
||||
]";
|
||||
|
||||
async(dm_send_request(4, 272, $var(payload), $var(rpl_avps)), dm_reply);
|
||||
}
|
||||
|
||||
# should be almost identical to handle_hangup. Sends Termination-Cause 6 (DIAMETER_AUTH_EXPIRED) instead of 1 (DIAMETER_LOGOUT)
|
||||
route[handle_timeout] {
|
||||
$var(duration2) = $Ts - $dlg_val(answertime);
|
||||
$var(payload) = "[
|
||||
{ \"Session-Id\": \"" + $dlg_val(callid) + "\" },
|
||||
{ \"Origin-Host\": \"client.diameter.test\" },
|
||||
{ \"Origin-Realm\": \"diameter.test\" },
|
||||
{ \"Destination-Realm\": \"diameter.test\" },
|
||||
{ \"Service-Context-Id\": \"voice@OsipsDiamCCR\" },
|
||||
{ \"CC-Request-Type\": 3 },
|
||||
{ \"CC-Request-Number\": 2 },
|
||||
{ \"Termination-Cause\": 6 },
|
||||
{ \"Event-Timestamp\": \"" + $dlg_val(answertime32bit) + "\" },
|
||||
{ \"User-Name\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Subscription-Id\": [
|
||||
{ \"Subscription-Id-Type\": 0 },
|
||||
{ \"Subscription-Id-Data\": \"" + $dlg_val(account) + "\" }
|
||||
]},
|
||||
{ \"Used-Service-Unit\": [
|
||||
{\"CC-Time\": " + $var(duration2) + " }
|
||||
]},
|
||||
{ \"Service-Information\": [
|
||||
{\"IMS-Information\": [
|
||||
{ \"Calling-Party-Address\": \"" + $dlg_val(account) + "\" },
|
||||
{ \"Called-Party-Address\": \"" + $dlg_val(destination) + "\" }
|
||||
]}
|
||||
]}
|
||||
]";
|
||||
|
||||
async(dm_send_request(4, 272, $var(payload), $var(rpl_avps)), dm_reply);
|
||||
}
|
||||
|
||||
# async dm reply handler
|
||||
route[dm_reply] {
|
||||
$json(rpl) := $var(rpl_avps);
|
||||
if ($rc != 1 || $json(rpl[5]/Result-Code) != 2001) {
|
||||
xlog("L_NOTICE", "rc=$rc\nResult-Code=$json(rpl[5]/Result-Code)\nCC-Request-Type=$json(rpl[3]/CC-Request-Type)\n");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
route[relay] {
|
||||
# for INVITEs enable some additional helper routes
|
||||
if (is_method("INVITE")) {
|
||||
t_on_branch("per_branch_ops");
|
||||
t_on_reply("handle_nat");
|
||||
t_on_failure("missed_call");
|
||||
}
|
||||
|
||||
if (!t_relay()) {
|
||||
send_reply(500,"Internal Error");
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
branch_route[per_branch_ops] {
|
||||
xlog("new branch at $ru\n");
|
||||
}
|
||||
|
||||
onreply_route[handle_nat] {
|
||||
xlog("incoming reply\n");
|
||||
}
|
||||
|
||||
failure_route[missed_call] {
|
||||
if (t_was_cancelled()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
# uncomment the following lines if you want to block client
|
||||
# redirect based on 3xx replies.
|
||||
##if (t_check_status("3[0-9][0-9]")) {
|
||||
##t_reply(404,"Not found");
|
||||
## exit;
|
||||
##}
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Tried to add Time-Stamps as an extra field to keep track of SetupTime/AnswerTime and set Event-Timestamp to the time of the event itself. Then the route started to behave weirdly. It was sending only the authorize diameter request and then, when the call was supposed to hangup, it sent the authorize request again.
|
||||
#
|
||||
# { \"Time-Stamps\": [
|
||||
# {\"SIP-Request-Timestamp\": " + $dlg_val(setuptime) + " },
|
||||
# {\"SIP-Response-Timestamp\": \"" + $dlg_val(answertime32bit) + "\" }
|
||||
# ]}
|
||||
|
||||
# Had to use async diameter requests, because otherwise it would not do anything on hangup/timeout. It would be stuck in an infinite loop with these (still has them, but it works because it's async):
|
||||
#
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:timer_routine: timer routine:3,tl=0x7fd0bb345400 next=(nil), timeout=125
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:delete_handler: removing 0x7fd0bb345350
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:delete_cell: delete_cell 0x7fd0bb345350: can't delete -- still reffed (-1)
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:set_timer: relative timeout is 2
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:insert_timer_unsafe: [3]: 0x7fd0bb345400 (127)
|
||||
# Apr 30 21:37:15 [26704] DBG:tm:delete_handler: done
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:timer_routine: timer routine:3,tl=0x7fd0bb345400 next=(nil), timeout=127
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:delete_handler: removing 0x7fd0bb345350
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:delete_cell: delete_cell 0x7fd0bb345350: can't delete -- still reffed (-1)
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:set_timer: relative timeout is 2
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:insert_timer_unsafe: [3]: 0x7fd0bb345400 (129)
|
||||
# Apr 30 21:37:18 [26704] DBG:tm:delete_handler: done
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:timer_routine: timer routine:3,tl=0x7fd0bb345400 next=(nil), timeout=129
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:delete_handler: removing 0x7fd0bb345350
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:delete_cell: delete_cell 0x7fd0bb345350: can't delete -- still reffed (-1)
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:set_timer: relative timeout is 2
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:insert_timer_unsafe: [3]: 0x7fd0bb345400 (131)
|
||||
# Apr 30 21:37:20 [26704] DBG:tm:delete_handler: done
|
||||
10
data/tutorials/osips_diam/etc/opensips/unix2ntp
Executable file
10
data/tutorials/osips_diam/etc/opensips/unix2ntp
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# To be used inside opensips.cfg to convert unix time
|
||||
# to 32bit before sending it inside a diameter request
|
||||
# payload as Event-Timestamp.
|
||||
|
||||
read unix_time
|
||||
ntp_offset=2208988800
|
||||
ntp_time=$((unix_time + ntp_offset))
|
||||
printf "%08x" "$ntp_time" | xxd -r -p
|
||||
2
data/tutorials/osips_diam/tp/AccountActions.csv
Normal file
2
data/tutorials/osips_diam/tp/AccountActions.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled
|
||||
cgrates.org,1001,AP_PACKAGE_1001,,,
|
||||
|
2
data/tutorials/osips_diam/tp/ActionPlans.csv
Normal file
2
data/tutorials/osips_diam/tp/ActionPlans.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Id,ActionsId,TimingId,Weight
|
||||
AP_PACKAGE_1001,ACT_TOPUP_RST_10,*asap,10
|
||||
|
2
data/tutorials/osips_diam/tp/Actions.csv
Normal file
2
data/tutorials/osips_diam/tp/Actions.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#ActionsId[0],Action[1],ExtraParameters[2],Filter[3],BalanceId[4],BalanceType[5],Categories[6],DestinationIds[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingIds[11],Units[12],BalanceWeight[13],BalanceBlocker[14],BalanceDisabled[15],Weight[16]
|
||||
ACT_TOPUP_RST_10,*topup_reset,,,balance_test,*monetary,,*any,,,*unlimited,,10,10,false,false,10
|
||||
|
2
data/tutorials/osips_diam/tp/Chargers.csv
Normal file
2
data/tutorials/osips_diam/tp/Chargers.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
|
||||
cgrates.org,DEFAULT,,,*default,*none,0
|
||||
|
2
data/tutorials/osips_diam/tp/DestinationRates.csv
Normal file
2
data/tutorials/osips_diam/tp/DestinationRates.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Id,DestinationId,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy
|
||||
DR_1002,DST_1002,RT_20CNT,*up,4,0,
|
||||
|
2
data/tutorials/osips_diam/tp/Destinations.csv
Normal file
2
data/tutorials/osips_diam/tp/Destinations.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Id,Prefix
|
||||
DST_1002,1002
|
||||
|
3
data/tutorials/osips_diam/tp/Rates.csv
Normal file
3
data/tutorials/osips_diam/tp/Rates.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
#Id,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart
|
||||
RT_20CNT,0.4,0.2,60s,60s,0s
|
||||
RT_20CNT,0,0.1,60s,1s,60s
|
||||
|
2
data/tutorials/osips_diam/tp/RatingPlans.csv
Normal file
2
data/tutorials/osips_diam/tp/RatingPlans.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Id,DestinationRatesId,TimingTag,Weight
|
||||
RP_1001,DR_1002,*any,10
|
||||
|
2
data/tutorials/osips_diam/tp/RatingProfiles.csv
Normal file
2
data/tutorials/osips_diam/tp/RatingProfiles.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
#Tenant,Category,Subject,ActivationTime,RatingPlanId,RatesFallbackSubject
|
||||
cgrates.org,call,1001,2014-01-14T00:00:00Z,RP_1001,
|
||||
|
Reference in New Issue
Block a user