######## Presence server module ######## #!trydef PRESENCE_MIN_EXPIRES 300 #!trydef PRESENCE_MIN_EXPIRES_ACTION 1 #!trydef PRESENCE_MAX_EXPIRES 3600 #!trydef KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP 0 #!trydef KZ_PRESENCE_CSEQ_OFFSET 2 #!trydef KZ_PRESENCE_MAX_CALL_PER_PRESENTITY 20 #!trydef BLF_USE_SINGLE_DIALOG 1 #!trydef KZ_PRESENCE_AMQP_PUBLISH 0 #!trydef KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE 0 #!trydef KZ_PRESENCE_REQUEST_PROBE 1 #!trydef KZ_PRESENCE_NO_TARGETS_LOG_LEVEL L_DBG #!trydef KZ_PRESENCE_WITH_TARGETS_LOG_LEVEL L_INFO #!trydef KZ_PRESENCE_REQUIRE_AUTHN 0 #!trydef KZ_PRESENCE_KEEPALIVE_NAT_ONLY 1 #!trydef KZ_PRESENCE_KEEPALIVE_UDP_ONLY 1 #!trydef KZ_PRESENCE_FAST_NOTIFY 1 #!ifdef NAT_TRAVERSAL_ROLE #!ifndef KEEPALIVE_ROLE #!ifndef NAT_TRAVERSAL_LOADED #!trydef NAT_TRAVERSAL_LOADED loadmodule "nat_traversal.so" #!endif modparam("nat_traversal", "keepalive_method", "OPTIONS") modparam("nat_traversal", "keepalive_from", "sip:sipcheck@MY_HOSTNAME") modparam("nat_traversal", "keepalive_state_file", "KAZOO_DATA_DIR/keep_alive_state") modparam("nat_traversal", "keepalive_interval", 45) #!endif #!endif modparam("htable", "htable", "first=>size=32;autoexpire=3600;initval=0;") loadmodule "presence.so" loadmodule "presence_dialoginfo.so" loadmodule "presence_mwi.so" loadmodule "presence_xml.so" modparam("presence_dialoginfo", "force_dummy_dialog", 1) modparam("presence_dialoginfo", "force_single_dialog", BLF_USE_SINGLE_DIALOG) modparam("presence_xml", "force_dummy_presence", 1) modparam("presence_xml", "force_active", 1) modparam("presence_xml", "disable_winfo", 1) modparam("presence_xml", "disable_bla", 1) modparam("presence", "subs_db_mode", 3) modparam("presence", "expires_offset", 0) modparam("presence", "send_fast_notify", KZ_PRESENCE_FAST_NOTIFY) modparam("presence", "clean_period", 0) modparam("presence", "db_update_period", 0) modparam("presence", "publ_cache", 0) modparam("presence", "min_expires_action", PRESENCE_MIN_EXPIRES_ACTION) modparam("presence", "min_expires", PRESENCE_MIN_EXPIRES) modparam("presence", "max_expires", PRESENCE_MAX_EXPIRES) modparam("presence", "sip_uri_match", 1) modparam("presence", "waitn_time", 1) modparam("presence", "notifier_processes", 0) modparam("presence", "db_url", "KAZOO_DB_URL") modparam("presence", "xavp_cfg", "pres") modparam("presence", "local_log_level", 6) modparam("presence", "startup_mode", 0) modparam("presence", "force_delete", 1) modparam("presence", "timeout_rm_subs", 0) modparam("presence", "cseq_offset", KZ_PRESENCE_CSEQ_OFFSET) modparam("kazoo", "db_url", "KAZOO_DB_URL") modparam("kazoo", "pua_mode", 1) kazoo.presence_sync_amqp = KZ_PRESENCE_AMQP_PUBLISH descr "sync subscriptions to amqp" kazoo.presence_request_probe = KZ_PRESENCE_REQUEST_PROBE descr "request probe for new subscriptions" kazoo.presence_request_resubscribe_probe = KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE descr "request probe for resubscriptions" kazoo.presence_ignore_status_probe_resp = KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP descr "ignore online/offline probe replies" kazoo.presence_max_call_per_presentity = KZ_PRESENCE_MAX_CALL_PER_PRESENTITY descr "max number of calls per presentity" kazoo.presence_no_targets_log_level = KZ_PRESENCE_NO_TARGETS_LOG_LEVEL descr "when a presence event is received and there no targets we can log at another level" kazoo.presence_with_targets_log_level = KZ_PRESENCE_WITH_TARGETS_LOG_LEVEL descr "when a presence event is received and there are targets we can log at another level" kazoo.presence_require_authn = KZ_PRESENCE_REQUIRE_AUTHN descr "require authenticated devices for presence" kazoo.presence_keepalive_udp_only = KZ_PRESENCE_KEEPALIVE_UDP_ONLY descr "should we send keepalive for udp only" kazoo.presence_keepalive_nat_only = KZ_PRESENCE_KEEPALIVE_NAT_ONLY descr "should we send keepalive for nat phones only" #!include_file "presence-query.cfg" #!include_file "presence-notify.cfg" #!include_file "presence-reset.cfg" #!include_file "presence-fast-pickup.cfg" ####### Presence Logic ######## route[PRESENCE_NAT] { if(!( ($sel(cfg_get.kazoo.presence_keepalive_udp_only) == 1 && $proto != "udp") || (!isflagset(FLT_NATS) && $sel(cfg_get.kazoo.presence_keepalive_nat_only) == 1) || ($proto == "ws" || $proto == "wss") )) { #!ifdef KEEPALIVE_ROLE route(KEEPALIVE_ON_SUBSCRIBE); #!else nat_keepalive(); #!endif } } route[HANDLE_SUBSCRIBE] { if (!is_method("SUBSCRIBE")) { return; } route_if_exists("CUSTOM_HANDLE_SUBSCRIBE"); if ($hdr(Event) != "dialog" && $hdr(Event) != "presence" && $hdr(Event) != "message-summary") { xlog("L_INFO", "$ci|presence|subscribe event $hdr(Event) not supported\n"); send_reply(489, "Bad Event"); exit(); } if(has_totag()) { loose_route(); } record_route(); if(has_totag()) { route(HANDLE_RESUBSCRIBE); } else { route(HANDLE_NEW_SUBSCRIBE); } exit; } route[DELETE_DUPLICATED_SUBSCRIPTIONS] { sql_query("exec", '$_s(DELETE FROM ACTIVE_WATCHERS WHERE PRESENTITY_URI="$subs(uri)" AND EVENT="$subs(event)" AND FROM_USER = "$subs(from_user)" AND FROM_DOMAIN="$subs(from_domain)" AND CALLID <> "$subs(callid)")'); } route[HANDLE_RESUBSCRIBE] { if(handle_subscribe()) { if($subs(remote_cseq) < 5) { $sht(first=>$subs(callid)) = $null; $sht(first=>$subs(from_user)::$subs(pres_uri)::$subs(from_domain)::$subs(event)) = $null; } route(DELETE_DUPLICATED_SUBSCRIPTIONS); route(SUBSCRIBE_AMQP); route(REQUEST_PROBE); }; } route[HANDLE_NEW_SUBSCRIBE] { if ($hdr(Event) == "dialog" || $hdr(Event) == "presence" || $hdr(Event) == "message-summary") { if ($tU == $null) { xlog("L_INFO", "$ci|end|ignoring subscribe with empty TO username from a $ua\n"); send_reply(400, "Missing TO username"); return; } if ($fU == $null) { xlog("L_INFO", "$ci|end|ignoring subscribe with empty FROM username from a $ua\n"); send_reply(400, "Missing FROM username"); return; } if($shtinc(first=>$ci) > 1) { sql_query("exec", 'KZQ_HANDLE_NEW_SUBSCRIBE_DELETE1'); xlog("L_INFO", "$ci|presence|resetting $hdr(Event) subscription from $fU to $tU in realm $fd : $sqlrows(exec)\n"); } else { $var(presentity_uri) = $ru; if($(var(presentity_uri){uri.user}) == "") { $var(presentity_uri) = $tu; } if($shtinc(first=>$fU::$var(presentity_uri)::$fd::$hdr(Event)) > 1) { sql_query("exec", 'KZQ_HANDLE_NEW_SUBSCRIBE_DELETE2'); xlog("L_INFO", "$ci|presence|resetting $hdr(Event) subscription from $fU to $var(presentity_uri) in realm $fd : $sqlrows(exec)\n"); } } if (handle_subscribe()) { xlog("L_INFO","$ci|end|new $hdr(Event) subscription from $fU to $tU in realm $fd : $sht(first=>$ci) : $sht(first=>$fU::$tU::$fd::$hdr(Event))\n"); route(DELETE_DUPLICATED_SUBSCRIPTIONS); route(SUBSCRIBE_AMQP); route(REQUEST_PROBE); #!ifdef NAT_TRAVERSAL_ROLE route(PRESENCE_NAT); #!endif } else { xlog("L_INFO", "$ci|end|error $T_reply_code for new $hdr(Event) subscription from $fU to $tU in realm $fd\n"); } } else { xlog("L_INFO", "$ci|end|unsupported subscription package $hdr(Event) from $fU to $tU in realm $fd\n"); send_reply(489, "Bad Event"); } } route[SUBSCRIBE_AMQP] { if($sel(cfg_get.kazoo.presence_sync_amqp) == 1) { $var(rk) = "subscribe." + $(subs(to_domain){kz.encode}) + "." + $(subs(to_user){kz.encode}); $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "subscription", "Event-Package" : "$hdr(event)", "Expires" : $subs(expires), "Queue" : "BLF-MY_HOSTNAME", "Server-ID" : "BLF-MY_HOSTNAME" , "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "From" : "$fu", "User" : "$subs(uri)", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" }); kazoo_publish("omnipresence", "$var(rk)", $var(amqp_payload_request)); } } route[REQUEST_PROBE] { if( ($sel(cfg_get.kazoo.presence_request_probe) == 1 && (!has_totag())) || ($sel(cfg_get.kazoo.presence_request_resubscribe_probe) == 1 && has_totag()) ) { if( route(HAS_PRESENTITY) == 0) { if($hdr(event) == "message-summary") { $var(mwi) = $tU; route(REQUEST_MWI); } else { if($tU =~ "\*98") { $var(mwi) = $(tU{s.substr,3,0}); route(REQUEST_MWI); } else { xlog("L_INFO", "$ci|presence|requesting $hdr(Event) probe for $subs(to_user) in realm $subs(to_domain)\n"); $var(rk) = "probes." + $hdr(Event); $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "probe", "Event-Package" : "$hdr(event)", "Username" : "$subs(to_user)", "Realm" : "$subs(to_domain)", "Call-ID" : "$ci"}); kazoo_publish("presence", "$var(rk)", $var(amqp_payload_request)); } } } } } route[REQUEST_MWI] { xlog("L_INFO", "$ci|presence|requesting mwi probe for $var(mwi) in realm $subs(to_domain)\n"); $var(rk) = "mwi_queries." + $(subs(to_domain){kz.encode}); $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "mwi_query", "Username" : "$var(mwi)", "Realm" : "$fd", "Call-ID" : "$ci"}); kazoo_publish("presence", "$var(rk)", $var(amqp_payload_request)); } route[HANDLE_PUBLISH] { if(!is_method("PUBLISH")) { return; } route_if_exists("CUSTOM_HANDLE_PUBLISH"); if ($hdr(Event) != "dialog" && $hdr(Event) != "presence" && $hdr(Event) != "message-summary") { xlog("L_INFO", "$ci|presence|publish event $hdr(Event) not supported\n"); send_reply(489, "Bad Event"); exit(); } if($hdr(Sender)!= $null) { handle_publish("$hdr(Sender)"); } else { handle_publish(); } exit; } route[HAS_PRESENTITY] { $var(Query) = $_s(KZQ_HAS_PRESENTITY); $var(res) = 0; if (sql_xquery("cb", "$var(Query)", "subs") == 1) { if($xavp(subs) != $null) { $var(res) = $xavp(subs=>count); pv_unset("$xavp(subs)"); } } return $var(res); } route[COUNT_PRESENTITIES] { $var(Query) = $_s(KZQ_COUNT_PRESENTITIES); $var(p) = $_s(presence_id='$var(presentity)'); if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count); pv_unset("$xavp(subs)"); } } xavp_params_explode($var(p), "watchers"); } route[COUNT_ALL_PRESENTITIES] { $var(Query) = $_s(select event, (select count(*) from presentity b where b.event = a.event) count from event_list a); $var(p) = "presence_id=none"; if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count); pv_unset("$xavp(subs)"); } } xavp_params_explode($var(p), "watchers"); } route[COUNT_ALL_SUBSCRIBERS] { $var(Query) = $_s(KZQ_COUNT_ALL_SUBSCRIBERS); if (sql_xquery("cb", "$var(Query)", "subs") == 1) { $var(sep) = ""; $var(Subscribers) = ""; $var(Subscriptions) = ""; while($xavp(subs) != $null) { $var(Subscribers) = $var(Subscribers) + $var(sep) + $_s("$xavp(subs=>event)" : $xavp(subs=>count_unique)); $var(Subscriptions) = $var(Subscriptions) + $var(sep) + $_s("$xavp(subs=>event)" : $xavp(subs=>count)); $var(sep) = " , "; pv_unset("$xavp(subs)"); } } } route[COUNT_SUBSCRIBERS] { $var(Query) = $_s(KZQ_COUNT_SUBSCRIBERS); $var(p) = $_s(presence_id='$var(presentity)'); if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count); pv_unset("$xavp(subs)"); } } xavp_params_explode($var(p), "watchers"); } event_route[kazoo:consumer-event-presence-dialog-update] { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int}); $var(StartRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received}); xlog("L_DEBUG", "event|presence|$(kzE{kz.json,Call-ID}) received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,AMQP-Broker-Zone}) => $(kzE{kz.json,Switch-URI}) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs)\n"); $var(JObj) = $kzE; route(PRESENCE_FAST_PICKUP_INIT); $var(presentity) = $(kzE{kz.json,From}); $var(payload) = $kzE; route(PRESENCE_UPDATE); $var(EndRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute); xlog("$var(kz_presence_log_level)", "event|presence|$(kzE{kz.json,Call-ID}) $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,AMQP-Broker-Zone}) => $(kzE{kz.json,Switch-URI}) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n"); } event_route[kazoo:consumer-event-presence-mwi-update] { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int}); $var(StartRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received}); xlog("L_DBG", "event|presence|$(kzE{kz.json,Call-ID}) received message-summary update for $(kzE{kz.json,From}) ($(kzE{kz.json,AMQP-Broker-Zone}))\n"); $var(presentity) = $(kzE{kz.json,From}); $var(payload) = $kzE; route(COUNT_SUBSCRIBERS); if($xavp(watchers=>message-summary) > 0) { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); xlog("L_INFO", "event|presence|$(kzE{kz.json,Call-ID}) publishing $(kzE{kz.json,From}) message-summary update for $xavp(watchers=>message-summary) watchers\n"); kazoo_pua_publish_mwi($kzE); pres_refresh_watchers("$(kzE{kz.json,From})", "message-summary", 1); } else { #!ifdef PRESENCE_TRACK_ALL_PKG_MWI $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) saving $var(presentity) from mwi update => $var(payload)\n"); if(kazoo_pua_publish_mwi($kzE) != 1) { xlog("L_ERR", "event|presence|$(var(payload){kz.json,Call-ID}) error publishing $var(presentity) mwi update => $var(payload)\n"); } #!else xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) skip mwi update for $var(presentity)\n"); #!endif } route(MWI_AS_PRESENCE); $var(mwi_state) = "ON"; if($(kzE{kz.json,Messages-Waiting}) == "no") { $var(mwi_state) = "OFF"; } $var(EndRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute); xlog("$var(kz_presence_log_level)", "event|presence|$(kzE{kz.json,Call-ID}) message-summary update for $(kzE{kz.json,From}) light should be $var(mwi_state) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n"); } event_route[kazoo:consumer-event-presence-update] { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int}); $var(StartRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received}); if($sel(cfg_get.kazoo.presence_ignore_status_probe_resp) == 1) { if($(kzE{kz.json,State}) == "offline" || $(kzE{kz.json,State}) == "online") { xlog("L_DEBUG", "event|presence|$(kzE{kz.json,Call-ID}) ignoring $(kzE{kz.json,State}) state $(kzE{kz.json,Presence-ID})\n"); return; } } xlog("L_DEBUG", "event|presence|$(kzE{kz.json,Call-ID}) received presence update for $(kzE{kz.json,Presence-ID})\n"); $var(JObj) = $kzE; $var(presentity) = $_s(sip:$(kzE{kz.json,Presence-ID})); $var(payload) = $kzE; route(PRESENCE_UPDATE); $var(EndRoute) = $(TV(Sn){s.replace,.,}); $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute); xlog("$var(kz_presence_log_level)", "event|presence|$(kzE{kz.json,Call-ID}) $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,AMQP-Broker-Zone}) => $(kzE{kz.json,Switch-URI}) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n"); } route[PRESENCE_UPDATE] { $var(callid) = $(var(payload){kz.json,Call-ID}); if($(var(payload){kz.json,State}) == "terminated") { route(COUNT_PRESENTITIES); } else { route(COUNT_SUBSCRIBERS); } if($xavp(watchers=>self) > $sel(cfg_get.kazoo.presence_max_call_per_presentity) && ( $(var(payload){kz.json,State}) == "early" || ($(var(payload){kz.json,State}) == "confirmed" && $(var(payload){kz.json,State}) == "initiator") )) { xlog("L_WARN", "event|presence|$(var(payload){kz.json,Call-ID}) not publishing state $(var(payload){kz.json,State}) for presentity $var(presentity) with $xavp(watchers=>self) calls, policy limit of $sel(cfg_get.kazoo.presence_max_call_per_presentity) calls per presentity \n"); } else { if($xavp(watchers=>dialog) > 0) { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); if($(var(payload){kz.json,State}) == "terminated") { xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) publishing $var(presentity) dialog update for terminated dialog\n"); } else { xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) publishing $var(presentity) dialog update for $xavp(watchers=>dialog) watchers\n"); } if(kazoo_pua_publish_dialoginfo($var(JObj)) == 1) { pres_refresh_watchers("$var(presentity)", "dialog", 1); } else { xlog("L_ERR", "event|presence|$(var(payload){kz.json,Call-ID}) error publishing $var(presentity) dialog update\n"); }; } else { #!ifdef PRESENCE_TRACK_ALL_PKG_DIALOG if($(kzE{kz.json,Event-Package}) == "dialog") { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) saving $var(presentity) from dialog update => $var(payload)\n"); if(kazoo_pua_publish_dialoginfo($var(JObj)) != 1) { xlog("L_ERR", "event|presence|$(var(payload){kz.json,Call-ID}) error publishing $var(presentity) dialog update => $var(payload)\n"); } } #!else xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) skip dialog update for $var(presentity)\n"); #!endif } if($xavp(watchers=>presence) > 0) { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); if($(var(payload){kz.json,State}) == "terminated") { xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) publishing $var(presentity) presence update for terminated dialog\n"); } else { xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) publishing $var(presentity) presence update for $xavp(watchers=>presence) watchers\n"); } if(kazoo_pua_publish_presence($var(JObj)) == 1) { pres_refresh_watchers("$var(presentity)", "presence", 1); } else { xlog("L_ERR", "event|presence|$(var(payload){kz.json,Call-ID}) error publishing $var(presentity) presence update\n"); }; } else { #!ifdef PRESENCE_TRACK_ALL_PKG_PRESENCE if($(kzE{kz.json,Event-Package}) == "presence") { $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int}); xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) saving $var(presentity) from presence update => $var(payload)\n"); if(kazoo_pua_publish_presence($var(JObj)) != 1) { xlog("L_ERR", "event|presence|$(var(payload){kz.json,Call-ID}) error publishing $var(presentity) presence update => $var(payload)\n"); } } #!else xlog("L_DEBUG", "event|presence|$(var(payload){kz.json,Call-ID}) skip presence update for $var(presentity)\n"); #!endif } } } route[MWI_PRESENCE_BODY] { $var(mwi_body) = $(kzE{re.subst,/"Messages-Waiting"\s*\:\s*"[^"]*"/"State" : "$var(State)"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"From"\s*\:\s*"[^"]*"/"From" : "$var(presentity)"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"From-User"\s*\:\s*"[^"]*"/"From-User" : "$var(user)"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"To"\s*\:\s*"[^"]*"/"To" : "$var(presentity)"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"To-User"\s*\:\s*"[^"]*"/"To-User" : "$var(user)"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"Messages-New"\s*\:\s*[^,]*/"Direction" : "initiator"/}); $var(mwi_body) = $(var(mwi_body){re.subst,/"Event-Name"\s*\:\s*"[^"]*"/"Event-Name" : "presence"/}); } route[MWI_AS_PRESENCE] { if( $(kzE{kz.json,Extended-Presence-ID}) == "" ) { return; } $var(realm) = $(kzE{kz.json,From-Realm}); $var(user) = $(kzE{kz.json,Extended-Presence-ID}); $var(presentity) = $_s(sip:$var(user)@$var(realm)); if( $(kzE{kz.json,Messages-Waiting}) == "yes" ) { $var(State) = "confirmed"; } else { $var(State) = "terminated"; } route(MWI_PRESENCE_BODY); $var(payload) = $var(mwi_body); $var(JObj) = $var(payload); route(PRESENCE_UPDATE); } route[KZ_AMQP_BINDING_PRESENCE] { if(!check_route_exists("KZ_AMQP_BINDING_CUSTOM_PRESENCE")) { $var(payload) = $_s({ "name" : "presence", "exchange" : "presence", "type" : "topic", "queue" : "presence-dialog-MY_HOSTNAME", "routing" : ["dialog.*.*", "update.*.*", "mwi_updates.*.*"], "exclusive" : false, "federate" : true }); kazoo_subscribe("$var(payload)"); } } route[KZ_AMQP_BINDING_PRESENCE_API] { if(!check_route_exists("KZ_AMQP_BINDING_CUSTOM_PRESENCE_API")) { $var(payload) = $_s({"name": "presence-api", "exchange": "presence", "type": "topic", "queue": "presence-api-MY_HOSTNAME", "routing": ["presence.search_req.*", "presence.reset.*.*"], "exclusive": false, "federate": true }); kazoo_subscribe("$var(payload)"); } } route[PRESENCE_AUTHN] { if($sel(cfg_get.kazoo.presence_require_authn) == 1) { $xavp(regcfg=>match_received) = $su; if(registered("location", "$rz:$Au", 2, 1) != 1) { xlog("L_WARNING", "$ci|stop|$rm from unregistered ($rz:$Au) user agent $ua => $su\n"); send_reply(403, "Forbidden"); exit; } } } # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab