You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

197 lines
8.2 KiB

######## FAST PICKUP ROLE ########
modparam("htable", "htable", "park=>size=16;autoexpire=600")
modparam("htable", "htable", "fp=>size=8");
#!trydef KZ_PRESENCE_FAST_PICKUP_COOKIES 1
#!trydef KZ_PRESENCE_FAST_PICKUP_REALTIME 1
#!trydef KZ_PRESENCE_FAST_PICKUP_STAR_5 1
kazoo.presence_fast_pickup_cookies = KZ_PRESENCE_FAST_PICKUP_COOKIES descr "maintains a hash table for correlating call-ids with media servers"
kazoo.presence_fast_pickup_realtime = KZ_PRESENCE_FAST_PICKUP_REALTIME descr "queries channels api for realtime status of call-id"
kazoo.presence_fast_pickup_star_5 = KZ_PRESENCE_FAST_PICKUP_STAR_5 descr "treats *5 as park pickup, queries state of *3"
route[PRESENCE_FAST_PICKUP_START]
{
$sht(fp=>count) = 0;
}
route[PRESENCE_FAST_PICKUP_LOAD]
{
sht_reset("fp");
xlog("L_INFO", "$ci|log|fast|initializing fastpick hash table from dispatcher\n");
if (sql_xquery("exec", "select destination from dispatcher", "ra") == 1) {
while($xavp(ra) != $null) {
$var(host) = $(xavp(ra=>destination){uri.host});
$var(port) = $(xavp(ra=>destination){uri.port});
$var(destination) = $xavp(ra=>destination);
$var(i) = 0;
if(!is_ip("$var(host)")) {
xlog("L_INFO", "$ci|log|fast|ignoring $var(host) since its not a ip address\n");
} else {
xlog("L_INFO", "$ci|log|fast|adding key $(var(destination){s.md5}) for $var(destination)\n");
$sht(fp=>$(var(destination){s.md5})) = $var(destination);
}
pv_unset("$xavp(ra)");
}
}
}
route[PRESENCE_FAST_PICKUP_ATTEMPT]
{
if (!is_method("INVITE")) {
return;
}
$var(replaced_call_id) = "none";
if($hdr(Replaces)!= $null) {
$var(replaced_call_id) = $(hdr(Replaces){s.select,0,;});
}
if($var(replaced_call_id) =~ "kfp+") {
if($shtinc(fp=>count) == 1) {
route(PRESENCE_FAST_PICKUP_LOAD);
}
remove_hf_re("^Replaces");
$var(PickupOptions) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\1/}{s.decode.hexa});
$var(md5) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\2/});
$var(replaced_call_id) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\3/});
if( $sht(fp=>$var(md5)) != $null) {
route(PRESENCE_FAST_PICKUP_OPTION);
$du = $sht(fp=>$var(md5));
append_hf("Replaces: $var(replaced_call_id)$var(Pickup)\r\n");
append_hf("k-cid: $var(replaced_call_id)\r\n");
xlog("L_INFO", "$ci|log|fast|found shortcut for call-id $var(replaced_call_id) , redirecting ($(ru{uri.user})) to $du\n");
route(RELAY);
exit();
} else {
xlog("L_INFO", "$ci|log|fast|shortcut $var(md5) invalid in this server, using standard routing\n");
}
}
if($sel(cfg_get.kazoo.presence_fast_pickup_realtime) == 1) {
if($var(replaced_call_id) != "none") {
xlog("L_INFO", "$ci|log|request has replaces call-id $var(replaced_call_id)\n");
$var(amqp_payload_request) = '{"Event-Category" : "call_event" , "Event-Name" : "channel_status_req", "Call-ID" : "' + $var(replaced_call_id) + '", "Active-Only" : true }';
$var(amqp_routing_key) = "call.status_req." + $(var(replaced_call_id){kz.encode});
sl_send_reply("100", "locating your call");
xlog("L_INFO", "$ci|log|querying cluster for the location of call-id $var(replaced_call_id)\n");
if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request))) {
$du = $(kzR{kz.json,Switch-URL});
if($du != $null) {
if($(kzR{kz.json,Other-Leg-Call-ID}) == "") {
## not bridged
$var(rep) = $_s($var(replaced_call_id);a-leg=true);
} else {
## ensure early-only=true
$var(rep) = $_s($var(replaced_call_id);early-only=true);
}
remove_hf_re("^Replaces");
append_hf("Replaces: $var(rep)\r\n");
append_hf("k-cid: $var(replaced_call_id)\r\n");
xlog("L_INFO", "$ci|log|call-id $var(replaced_call_id) found, redirecting call ($(ru{uri.user})) to $du => $var(rep)\n");
route(RELAY);
exit();
} else {
xlog("L_WARN", "$ci|log|call-id $var(replaced_call_id) not found in cluster, proceeding with normal dispatch\n");
}
} else {
xlog("L_WARN", "$ci|log|error querying cluster for call-id $var(replaced_call_id), proceeding with normal dispatch\n");
}
}
}
##### CALL-PARK ####
##### STAR 5 CHECK ####
if($sel(cfg_get.kazoo.presence_fast_pickup_star_5) == 1) {
if($(ru{uri.user}) =~ "^\*5") {
$var(park) = $_s(*3$(ru{uri.user}{s.substr,2,0})@$(ru{uri.domain}));
if($sht(park=>$var(park)) != $null) {
$du = $sht(park=>$var(park));
append_hf("k-cid: $sht(park=>$var(park)::callid)\r\n");
xlog("L_INFO", "$ci|log|redirecting park request to $du , callid : $sht(park=>$var(park)::callid)\n");
route(RELAY);
exit();
}
}
}
if($sht(park=>$(ru{uri.user})@$(ru{uri.domain})) != $null) {
$du = $sht(park=>$(ru{uri.user})@$(ruri{uri.domain}));
append_hf("k-cid: $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})::callid)\r\n");
xlog("L_INFO", "$ci|log|redirecting park request to $du, callid: $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})::callid)\n");
route(RELAY);
exit();
}
##### CALL-PARK IN KAZOO ####
$var(park_extension) = "^\*3";
if($sel(cfg_get.kazoo.presence_fast_pickup_star_5) == 1) {
$var(park_extension) = "^\*[3,5]";
}
if($(ru{uri.user}) =~ $var(park_extension) && !is_ip($rd)) {
xlog("L_INFO", "$ci|log|checking park request to $(ru{uri.user})@$(ru{uri.domain})\n");
$var(amqp_payload_request) = '{"Event-Category" : "call_event" , "Event-Name" : "query_user_channels_req", "Username" : "*3$(ru{uri.user}{s.substr,2,0})", "Realm" : "$(ru{uri.domain})", "Active-Only" : true }';
$var(amqp_routing_key) = "call.status_req." + $(ci{kz.encode});
if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request))) {
$du = $(kzR{kz.json,Channels[0].switch_url});
if($du != $null) {
xlog("L_INFO", "$ci|log|redirecting park request to $du from realtime query reply\n");
append_hf("k-cid: $(kzR{kz.json,Channels[0].call_id})\r\n");
route(RELAY);
exit();
}
}
}
}
route[PRESENCE_FAST_PICKUP_OPTION]
{
$var(Pickup) = "";
switch($var(PickupOptions))
{
case 1:
$var(Pickup) = ";a-leg=true";
break;
case 2:
$var(Pickup) = ";early-only=true";
break;
default:
break;
}
}
route[PRESENCE_FAST_PICKUP_INIT]
{
$var(AppName) = $(kzE{kz.json,App-Name});
## park redirects without replaces header
if($var(AppName) == "park") {
if($(kzE{kz.json,State}) == "terminated") {
$sht(park=>$(kzE{kz.json,Presence-ID})) = $null;
$sht(park=>$(kzE{kz.json,Presence-ID})::callid) = $null;
} else {
$sht(park=>$(kzE{kz.json,Presence-ID})) = $(kzE{kz.json,Switch-URI});
$sht(park=>$(kzE{kz.json,Presence-ID})::callid) = $(kzE{kz.json,Call-ID});
}
}
## fast pickup with cookies
if($sel(cfg_get.kazoo.presence_fast_pickup_cookies) == 1) {
if($var(AppName) == "park") {
$var(Pickup) = 1; #";a-leg=true";
} else {
$var(Pickup) = 2; #";early-only=true";
}
$var(Option) = $(var(Pickup){s.encode.hexa});
$var(Cookie) = $(kzE{kz.json,Switch-URI}{s.md5});
$var(call_id) = $(kzE{kz.json,Call-ID});
$var(JObj) = $(kzE{re.subst,/"Call-ID"\s*\:\s*"([^"]*)"/"Call-ID" : "kfp+$var(Option)$var(Cookie)@\1"/});
xlog("L_DEBUG", "$var(call_id)|fast|shortcut ($var(Pickup)) kfp+$var(Option)$var(Cookie)@$var(call_id)\n");
}
}
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab