feat: add number library routing and cdr location support

This commit is contained in:
hectorzhao
2026-06-24 11:39:32 +08:00
parent 5fa1bd35e9
commit 7057fd3c42
63 changed files with 6361 additions and 566 deletions
+58 -8
View File
@@ -18,11 +18,16 @@ loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
modparam("tm", "fr_inv_timeout", 95)
loadmodule "rr.so"
modparam("rr", "append_fromtag", 1)
loadmodule "dialog.so"
modparam("dialog", "dlg_match_mode", 1)
modparam("dialog", "default_timeout", 7200)
modparam("dialog", "delete_delay", 10)
loadmodule "maxfwd.so"
loadmodule "sipmsgops.so"
loadmodule "textops.so"
@@ -167,10 +172,21 @@ route[S28_INVITE] {
$var(s28_line_group_id) = "none";
$var(s28_policy_id) = "none";
$var(s28_customer_id) = "none";
$var(s28_vendor_id) = "none";
$var(s28_vendor_gateway_id) = "none";
$var(s28_vendor_host) = "none";
$var(s28_vendor_port) = "5060";
$var(s28_callee_city_code) = "UNKNOWN";
$var(s28_callee_city_name) = "UNKNOWN";
$var(s28_callee_province_name) = "UNKNOWN";
$var(s28_callee_operator) = "UNKNOWN";
$var(s28_callee_number_type) = "UNKNOWN";
$var(s28_callee_province_code) = "UNKNOWN";
$var(s28_callee_normalized) = "";
$var(s28_reply_code) = 503;
$var(s28_reply_text) = "Routing Not Ready";
if (!cache_raw_query("redis:s20", "EVALSHA cfdc02cbe5528d37fba617947c09e3380770c918 1 cfg:active_version $si $fU $rU $ci", "$avp(s28_hotpath)")) {
if (!cache_raw_query("redis:s20", "EVALSHA 229c06326b97d3d64b0b02deedec77a764a61045 1 cfg:active_version $si $fU $rU $ci", "$avp(s28_hotpath)")) {
xlog("L_ERR", "S28 Redis hotpath unavailable source=$si callid=$ci\n");
$var(s28_reason) = "REDIS_UNAVAILABLE";
$var(s28_reply_code) = 503;
@@ -187,13 +203,24 @@ route[S28_INVITE] {
$var(s28_line_group_id) = $(avp(s28_hotpath)[4]);
$var(s28_policy_id) = $(avp(s28_hotpath)[5]);
$var(s28_customer_id) = $(avp(s28_hotpath)[6]);
$var(s28_vendor_id) = $(avp(s28_hotpath)[7]);
$var(s28_vendor_gateway_id) = $(avp(s28_hotpath)[8]);
$var(s28_vendor_host) = $(avp(s28_hotpath)[9]);
$var(s28_vendor_port) = $(avp(s28_hotpath)[10]);
$var(s28_callee_city_code) = $(avp(s28_hotpath)[11]);
$var(s28_callee_city_name) = $(avp(s28_hotpath)[12]);
$var(s28_callee_province_name) = $(avp(s28_hotpath)[13]);
$var(s28_callee_operator) = $(avp(s28_hotpath)[14]);
$var(s28_callee_number_type) = $(avp(s28_hotpath)[15]);
$var(s28_callee_province_code) = $(avp(s28_hotpath)[16]);
$var(s28_callee_normalized) = $(avp(s28_hotpath)[17]);
if ($var(s28_decision) != "allow") {
update_stat("s28_hotpath_reject_total", 1);
if ($var(s28_reason) == "CONFIG_MISSING") {
$var(s28_reply_code) = 503;
$var(s28_reply_text) = "Config Missing";
} else if ($var(s28_reason) == "NO_POLICY") {
} else if ($var(s28_reason) == "NO_POLICY" || $var(s28_reason) == "NO_VENDOR_ROUTE" || $var(s28_reason) == "NO_VENDOR_ROUTE_REGION_BLOCKED" || $var(s28_reason) == "LINE_GROUP_MISSING" || $var(s28_reason) == "LINE_GROUP_DISABLED") {
$var(s28_reply_code) = 503;
$var(s28_reply_text) = "No Route Policy";
} else {
@@ -206,7 +233,30 @@ route[S28_INVITE] {
}
update_stat("s28_hotpath_allow_total", 1);
xlog("L_INFO", "S28 hotpath allow source=$si callid=$ci customer=$var(s28_customer_id) gateway=$var(s28_gateway_id) policy=$var(s28_policy_id) line_group=$var(s28_line_group_id) version=$var(s28_config_version)\n");
xlog("L_INFO", "S28 hotpath allow source=$si callid=$ci customer=$var(s28_customer_id) gateway=$var(s28_gateway_id) policy=$var(s28_policy_id) line_group=$var(s28_line_group_id) vendor=$var(s28_vendor_id) vendor_gateway=$var(s28_vendor_gateway_id) dst=$var(s28_vendor_host):$var(s28_vendor_port) version=$var(s28_config_version)\n");
if (!create_dialog()) {
xlog("L_ERR", "S28 create_dialog failed callid=$ci\n");
$var(s28_reason) = "DIALOG_CREATE_FAILED";
$var(s28_reply_code) = 500;
$var(s28_reply_text) = "Dialog Error";
route(S28_CDR_FAILURE);
send_reply($var(s28_reply_code), $var(s28_reply_text));
exit;
}
$dlg_val(s28_customer_id) = $var(s28_customer_id);
$dlg_val(s28_gateway_id) = $var(s28_gateway_id);
$dlg_val(s28_policy_id) = $var(s28_policy_id);
$dlg_val(s28_line_group_id) = $var(s28_line_group_id);
$dlg_val(s28_vendor_id) = $var(s28_vendor_id);
$dlg_val(s28_vendor_gateway_id) = $var(s28_vendor_gateway_id);
$dlg_val(s28_config_version) = $var(s28_config_version);
$dlg_val(s28_callee) = $rU;
$dlg_val(s28_callee_city_code) = $var(s28_callee_city_code);
$dlg_val(s28_callee_city_name) = $var(s28_callee_city_name);
$dlg_val(s28_callee_province_name) = $var(s28_callee_province_name);
$dlg_val(s28_callee_operator) = $var(s28_callee_operator);
$dlg_val(s28_callee_number_type) = $var(s28_callee_number_type);
if (has_body("application/sdp")) {
if (!rtpengine_offer("replace-origin replace-session-connection record-call=on")) {
@@ -221,8 +271,8 @@ route[S28_INVITE] {
}
record_route();
$du = "sip:100.93.185.30:50620";
$ru = "sip:" + $rU + "@100.93.185.30:50620";
$du = "sip:" + $var(s28_vendor_host) + ":" + $var(s28_vendor_port);
$ru = "sip:" + $rU + "@" + $var(s28_vendor_host) + ":" + $var(s28_vendor_port);
t_on_reply("S28_REPLY");
if (!t_relay()) {
@@ -247,7 +297,7 @@ onreply_route[S28_REPLY] {
route[S28_CDR_SUCCESS] {
$var(s28_event_id) = "s28-ok-" + $Ts + "-" + $pp + "-" + $ci;
$var(s28_idempotency_key) = $ci + ":s28-ok:" + $Ts;
if (cache_raw_query("redis:s20", "XADD stream:cdr_payload * schema_version 1 event_id $var(s28_event_id) idempotency_key $var(s28_idempotency_key) call_id $ci node_id a1 opensips_instance opensips-a1 ingress_a_ip 100.90.90.90 rtpengine_node a1 source_ip $si caller $fU callee $rU customer_id cus_s28_t customer_gateway_id cgw_s28_t_ip customer_gateway_policy_id cgp_s28_t_default vendor_id ven_s28_t vendor_gateway_id vgw_s28_t_uas line_group_id llg_s28_t started_at $Ts answered_at $Ts ended_at $Ts duration_sec 6 sip_code 200 hangup_reason NORMAL_CLEARING recording_key none config_version $var(s28_config_version) created_at $Ts", "$avp(s28_cdr_id)")) {
if (cache_raw_query("redis:s20", "XADD stream:cdr_payload * schema_version 1 event_id $var(s28_event_id) idempotency_key $var(s28_idempotency_key) call_id $ci node_id a1 opensips_instance opensips-a1 ingress_a_ip 100.90.90.90 rtpengine_node a1 source_ip $si caller $fU callee $dlg_val(s28_callee) callee_city_code $dlg_val(s28_callee_city_code) callee_city_name $dlg_val(s28_callee_city_name) callee_province_name $dlg_val(s28_callee_province_name) callee_operator $dlg_val(s28_callee_operator) callee_number_type $dlg_val(s28_callee_number_type) customer_id $dlg_val(s28_customer_id) customer_gateway_id $dlg_val(s28_gateway_id) customer_gateway_policy_id $dlg_val(s28_policy_id) vendor_id $dlg_val(s28_vendor_id) vendor_gateway_id $dlg_val(s28_vendor_gateway_id) line_group_id $dlg_val(s28_line_group_id) started_at $Ts answered_at $Ts ended_at $Ts duration_sec 6 sip_code 200 hangup_reason NORMAL_CLEARING recording_key none config_version $dlg_val(s28_config_version) created_at $Ts", "$avp(s28_cdr_id)")) {
update_stat("s28_cdr_xadd_total", 1);
xlog("L_INFO", "S28 success CDR XADD ok redis_id=$avp(s28_cdr_id) event_id=$var(s28_event_id) callid=$ci\n");
} else {
@@ -259,7 +309,7 @@ route[S28_CDR_SUCCESS] {
route[S28_CDR_FAILURE] {
$var(s28_event_id) = "s28-fail-" + $Ts + "-" + $pp + "-" + $ci;
$var(s28_idempotency_key) = $ci + ":s28-fail:" + $Ts;
if (cache_raw_query("redis:s20", "XADD stream:cdr_payload * schema_version 1 event_id $var(s28_event_id) idempotency_key $var(s28_idempotency_key) call_id $ci node_id a1 opensips_instance opensips-a1 ingress_a_ip 100.90.90.90 rtpengine_node a1 source_ip $si caller $fU callee $rU customer_id $var(s28_customer_id) customer_gateway_id $var(s28_gateway_id) customer_gateway_policy_id $var(s28_policy_id) vendor_id none vendor_gateway_id none line_group_id $var(s28_line_group_id) started_at $Ts answered_at none ended_at $Ts duration_sec 0 sip_code $var(s28_reply_code) hangup_reason $var(s28_reason) recording_key none config_version $var(s28_config_version) created_at $Ts", "$avp(s28_cdr_id)")) {
if (cache_raw_query("redis:s20", "XADD stream:cdr_payload * schema_version 1 event_id $var(s28_event_id) idempotency_key $var(s28_idempotency_key) call_id $ci node_id a1 opensips_instance opensips-a1 ingress_a_ip 100.90.90.90 rtpengine_node a1 source_ip $si caller $fU callee $rU callee_city_code $var(s28_callee_city_code) callee_city_name $var(s28_callee_city_name) callee_province_name $var(s28_callee_province_name) callee_operator $var(s28_callee_operator) callee_number_type $var(s28_callee_number_type) customer_id $var(s28_customer_id) customer_gateway_id $var(s28_gateway_id) customer_gateway_policy_id $var(s28_policy_id) vendor_id none vendor_gateway_id none line_group_id $var(s28_line_group_id) started_at $Ts answered_at none ended_at $Ts duration_sec 0 sip_code $var(s28_reply_code) hangup_reason $var(s28_reason) recording_key none config_version $var(s28_config_version) created_at $Ts", "$avp(s28_cdr_id)")) {
update_stat("s28_cdr_xadd_total", 1);
} else {
update_stat("s28_cdr_xadd_error_total", 1);