diff --git a/kamailio/db_queries_kazoo.cfg b/kamailio/db_queries_kazoo.cfg index b7e542d..29801d5 100644 --- a/kamailio/db_queries_kazoo.cfg +++ b/kamailio/db_queries_kazoo.cfg @@ -9,7 +9,8 @@ #!substdef "!KZQ_RESET_ACCOUNT_DELETE!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\"!g" #!substdef "!KZQ_RESET_ACCOUNT_UPDATE!update active_watchers set expires = \$TS where watcher_domain=\"\$(kzE{kz.json,Realm})\"!g" #!substdef "!KZQ_RESET_PUBLISHER_UPDATE!update active_watchers set expires = \$TS where id in (select b.id from presentity a inner join active_watchers b on a.username = b.to_user and a.domain = b.to_domain and a.event = b.event where a.sender = \"\$var(MediaUrl)\")!g" -#!substdef "!KZQ_PRESENCE_SEARCH_DETAIL!select * from active_watchers_log where presentity_uri = \"\$var(presentity_uri)\"!g" -#!substdef "!KZQ_PRESENCE_SEARCH_SUMMARY!select * from active_watchers where watcher_domain = \"\$var(Domain)\"!g" +#!substdef "!KZQ_PRESENCE_SEARCH_DETAIL!select * from active_watchers_log where presentity_uri = \"\$var(presentity_uri)\" and callid in(select callid from active_watchers where presentity_uri = \"\$var(presentity_uri)\")!g" +#!substdef "!KZQ_PRESENCE_SEARCH_SUMMARY!select * from active_watchers where to_domain = \"\$var(Domain)\"!g" #!substdef "!KZQ_HAS_PRESENTITY!select count(*) as count from presentity where username = \"\$subs(to_user)\" and domain = \"\$subs(to_domain)\" and event = \"\$subs(event)\"!g" #!substdef "!KZQ_PRESENCE_RESET!delete from presentity where sender = \"\$var(MediaUrl)\"!g" +#!substdef "!KZQ_REPLACE_WATCHERS_LOG!REPLACE INTO active_watchers_log (presentity_uri, watcher_username, watcher_domain, event, callid, to_user, to_domain, user_agent, time, result, sent_msg, received_msg) VALUES (\"\$subs(uri)\", \"\$subs(watcher_username)\", \"\$subs(watcher_domain)\", \"\$subs(event)\",\"\$subs(callid)\",\"\$subs(to_user)\",\"\$subs(to_domain)\", '\$(subs(user_agent){s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})', \$TS, \$notify_reply(\$rs), '\$(mb{s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})', '\$(notify_reply(\$mb){s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})')!g" diff --git a/kamailio/db_scripts/check-kazoodb-sql.sh b/kamailio/db_scripts/check-kazoodb-sql.sh new file mode 100755 index 0000000..6db754d --- /dev/null +++ b/kamailio/db_scripts/check-kazoodb-sql.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +TEMP_DB_LOCATION=/tmp/db +TEMP_DB=${TEMP_DB_LOCATION}/kazoo.db + +rm -rf ${TEMP_DB_LOCATION} +. $(dirname $0)/kazoodb-sql.sh --source-only + +file=$(sql_db_prepare) +sql_setup $file ${TEMP_DB_LOCATION} + +DB_VERSION=`KazooDB -db ${TEMP_DB} "select sum(table_version) from version;"` + +DB_CURRENT_DB=${DB_LOCATION:-/etc/kazoo/kamailio}/kazoo.db +DB_CURRENT_VERSION=`KazooDB -db ${DB_CURRENT_DB} "select sum(table_version) from version;"` + + +if [[ $DB_CURRENT_VERSION -lt $DB_VERSION ]]; then + echo "db required version is ${DB_VERSION}, existing version is ${DB_CURRENT_VERSION}, applying diff" + KazooDB-diff --schema ${DB_CURRENT_DB} ${TEMP_DB} | KazooDB -db ${DB_CURRENT_DB} + KazooDB-diff --table version ${DB_CURRENT_DB} ${TEMP_DB} | KazooDB -db ${DB_CURRENT_DB} +fi + + +for VIEW in `ls ${DB_SCRIPT_DIR}/vw_*.sql`; do + filename=$(basename -- "$VIEW") + filename="${filename%.*}" + viewname=$(echo -n "$filename" | cut -d'_' -f2) + v1=$(KazooDB -db ${DB_CURRENT_DB} "select sql from sqlite_master where type='view' and name='$viewname'" 2> /dev/null | tr -d ' ' | md5sum | cut -d ' ' -f1) + v2=$(cat $VIEW | tr -d ' ' | md5sum | cut -d ' ' -f1) + if [[ "$v1" != "$v2" ]]; then + echo "rebuilding view $viewname" + KazooDB -db ${DB_CURRENT_DB} "drop view if exists $viewname;" + KazooDB -db ${DB_CURRENT_DB} < $VIEW + fi +done + +if [ -f ${DB_SCRIPT_DIR}/db_extra_check.sql ]; then + . ${DB_SCRIPT_DIR}/db_extra_check.sql --source-only + do_db_extra_check; +fi diff --git a/kamailio/db_scripts/create-kazoodb-sql.sh b/kamailio/db_scripts/create-kazoodb-sql.sh index 0663a0e..ebfc0ae 100755 --- a/kamailio/db_scripts/create-kazoodb-sql.sh +++ b/kamailio/db_scripts/create-kazoodb-sql.sh @@ -1,104 +1,9 @@ #!/bin/sh -e -##################################################################################### -## -## If you want prepare SQL file for PostgreSQL or MySQL server, then need to execute -## DB_ENGINE=postgres ./create-kazoodb-sql.sh -## -##################################################################################### -KAMAILIO_SHARE_DIR=${KAMAILIO_SHARE_DIR:-/usr/share/kamailio} -DB_ENGINE=${DB_ENGINE:-db_kazoo} -RESULTED_SQL=${RESULTED_SQL:-/tmp/kamailio_initdb.sql} +. $(dirname $0)/kazoodb-sql.sh --source-only -. $(dirname $0)/$DB_ENGINE-specific --source-only - -sql_filelist() { -cat << EOF -acc-create.sql -lcr-create.sql -domain-create.sql -group-create.sql -permissions-create.sql -registrar-create.sql -usrloc-create.sql -msilo-create.sql -alias_db-create.sql -uri_db-create.sql -speeddial-create.sql -avpops-create.sql -auth_db-create.sql -pdt-create.sql -dialog-create.sql -dispatcher-create.sql -dialplan-create.sql -topos-create.sql -presence-create.sql -rls-create.sql -imc-create.sql -cpl-create.sql -siptrace-create.sql -domainpolicy-create.sql -carrierroute-create.sql -userblacklist-create.sql -htable-create.sql -purple-create.sql -uac-create.sql -pipelimit-create.sql -mtree-create.sql -sca-create.sql -mohqueue-create.sql -rtpproxy-create.sql -uid_auth_db-create.sql -uid_avp_db-create.sql -uid_domain-create.sql -uid_gflags-create.sql -uid_uri_db-create.sql -EOF -} - -sql_all_header() { -cat << EOF -CREATE TABLE version ( - table_name VARCHAR(32) NOT NULL, - table_version INTEGER DEFAULT 0 NOT NULL, - CONSTRAINT version_table_name_idx UNIQUE (table_name) -); -INSERT INTO version VALUES('version',1); - -EOF -} - -sql_all_extra_tables() { -cat << EOF - -CREATE TABLE event_list ( event varchar(25) PRIMARY KEY NOT NULL); -INSERT INTO event_list VALUES('dialog'); -INSERT INTO event_list VALUES('presence'); -INSERT INTO event_list VALUES('message-summary'); -INSERT INTO version VALUES('event_list',1); - -EOF -} - -sql_all_footer() { -cat << EOF -COMMIT; -EOF -} - -echo "Creating kamailio database init file in '$RESULTED_SQL'" - -sql_db_pre_setup > $RESULTED_SQL -sql_all_header >> $RESULTED_SQL -sql_header >> $RESULTED_SQL -for i in $(sql_filelist); do - cat $KAMAILIO_SHARE_DIR/$DB_ENGINE/$i >> $RESULTED_SQL -done -sql_all_extra_tables >> $RESULTED_SQL -sql_extra_tables >> $RESULTED_SQL -sql_footer >> $RESULTED_SQL -sql_all_footer >> $RESULTED_SQL - -sql_setup $RESULTED_SQL +$file=$(sql_db_prepare) +echo "setting up kazoo db from init script $file" +sql_setup $file exit 0 diff --git a/kamailio/db_scripts/db_kazoo-specific b/kamailio/db_scripts/db_kazoo-specific index 014fd78..e21ab71 100644 --- a/kamailio/db_scripts/db_kazoo-specific +++ b/kamailio/db_scripts/db_kazoo-specific @@ -6,15 +6,16 @@ cat << EOF PRAGMA foreign_keys=OFF; PRAGMA wal=on; PRAGMA journal_mode=WAL; +PRAGMA wal_autocheckpoint=25; BEGIN TRANSACTION; EOF } sql_setup() { - DB_KAZOO_LOCATION=${DB_KAZOO_LOCATION:-/etc/kazoo/kamailio/db} - mkdir -p ${DB_KAZOO_LOCATION} - KazooDB -db ${DB_KAZOO_LOCATION}/kazoo.db < $1 + DB_KAZOO_LOCATION=${2:-${DB_KAZOO_LOCATION:-/etc/kazoo/kamailio/db}} + mkdir -p ${DB_KAZOO_LOCATION} + KazooDB -db ${DB_KAZOO_LOCATION}/kazoo.db < $1 > /dev/null } sql_header() { @@ -40,6 +41,33 @@ CREATE TABLE active_watchers_log ( user_agent VARCHAR(255) DEFAULT '' COLLATE NOCASE, CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event) ); + + create view presentities as select id, cast(printf("sip:%s@%s",username,domain) as varchar(64)) presentity_uri , + username, domain, event, cast(substr(etag, instr(etag,"@")+1) as varchar(64)) callid, + datetime(received_time, 'unixepoch') as received, + datetime(expires, 'unixepoch') as expire_date, + expires, cast(sender as varchar(30)) sender, + lower(cast( case when event = "dialog" + then substr(body, instr(BODY,"")+7, instr(body,"") - instr(body,"") - 7) + when event = "presence" + then case when instr(body,"") == 0 + then replace(substr(body, instr(body,"")+6, instr(body,"") - instr(body,"") - 6), " ", "") + else replace(substr(body, instr(body,"")+9, instr(body,"") - instr(body,"") - 9), " ", "") + end + when event = "message-summary" + then case when instr(body,"Messages-Waiting: yes") = 0 + then "Waiting" + else "Not-Waiting" + end + end as varchar(12))) state + from presentity; + + create view wdispatcher as select *, + cast(substr(attrs, instr(attrs, "zone=")+5, instr(attrs, ";profile")-instr(attrs, "zone=")-5) as varchar(20)) zone, + cast(substr(attrs, instr(attrs, "idx=")+4, instr(attrs, ";node")-instr(attrs, "idx=")-4) as integer) idx, + cast(substr(attrs, instr(attrs, "node=")+5) as varchar(50)) node + from dispatcher; + EOF } diff --git a/kamailio/db_scripts/kazoodb-sql.sh b/kamailio/db_scripts/kazoodb-sql.sh new file mode 100755 index 0000000..e4e36dd --- /dev/null +++ b/kamailio/db_scripts/kazoodb-sql.sh @@ -0,0 +1,96 @@ +#!/bin/sh -e + +KAMAILIO_SHARE_DIR=${KAMAILIO_SHARE_DIR:-/usr/share/kamailio} +DB_ENGINE=${DB_ENGINE:-db_kazoo} +RESULTED_SQL=${RESULTED_SQL:-/tmp/kamailio_initdb.sql} + +. $(dirname $0)/$DB_ENGINE-specific --source-only + +sql_filelist() { +cat << EOF +acc-create.sql +lcr-create.sql +domain-create.sql +group-create.sql +permissions-create.sql +registrar-create.sql +usrloc-create.sql +msilo-create.sql +alias_db-create.sql +uri_db-create.sql +speeddial-create.sql +avpops-create.sql +auth_db-create.sql +pdt-create.sql +dialog-create.sql +dispatcher-create.sql +dialplan-create.sql +topos-create.sql +presence-create.sql +rls-create.sql +imc-create.sql +cpl-create.sql +siptrace-create.sql +domainpolicy-create.sql +carrierroute-create.sql +userblacklist-create.sql +htable-create.sql +purple-create.sql +uac-create.sql +pipelimit-create.sql +mtree-create.sql +sca-create.sql +mohqueue-create.sql +rtpproxy-create.sql +uid_auth_db-create.sql +uid_avp_db-create.sql +uid_domain-create.sql +uid_gflags-create.sql +uid_uri_db-create.sql +EOF +} + +sql_all_header() { +cat << EOF +CREATE TABLE version ( + table_name VARCHAR(32) NOT NULL, + table_version INTEGER DEFAULT 0 NOT NULL, + CONSTRAINT version_table_name_idx UNIQUE (table_name) +); +INSERT INTO version VALUES('version',1); + +EOF +} + +sql_all_extra_tables() { +cat << EOF + +CREATE TABLE event_list ( event varchar(25) PRIMARY KEY NOT NULL); +INSERT INTO event_list VALUES('dialog'); +INSERT INTO event_list VALUES('presence'); +INSERT INTO event_list VALUES('message-summary'); +INSERT INTO version VALUES('event_list',1); + +EOF +} + +sql_all_footer() { +cat << EOF +COMMIT; +EOF +} + +sql_db_prepare() { + sql_db_pre_setup > $RESULTED_SQL + sql_all_header >> $RESULTED_SQL + sql_header >> $RESULTED_SQL + for i in $(sql_filelist); do + cat $KAMAILIO_SHARE_DIR/$DB_ENGINE/$i >> $RESULTED_SQL + done + sql_all_extra_tables >> $RESULTED_SQL + sql_extra_tables >> $RESULTED_SQL + sql_footer >> $RESULTED_SQL + sql_all_footer >> $RESULTED_SQL + + echo "$RESULTED_SQL" +} diff --git a/kamailio/db_scripts/vw_presentities.sql b/kamailio/db_scripts/vw_presentities.sql new file mode 100644 index 0000000..4c95a38 --- /dev/null +++ b/kamailio/db_scripts/vw_presentities.sql @@ -0,0 +1,20 @@ +CREATE VIEW presentities as +select id, cast(printf("sip:%s@%s",username,domain) as varchar(64)) presentity_uri , + username, domain, event, cast(substr(etag, instr(etag,"@")+1) as varchar(64)) callid, + datetime(received_time, 'unixepoch') as received, + datetime(expires, 'unixepoch') as expire_date, + expires, cast(sender as varchar(30)) sender, + lower(cast( case when event = "dialog" + then substr(body, instr(BODY,"")+7, instr(body,"") - instr(body,"") - 7) + when event = "presence" + then case when instr(body,"") == 0 + then replace(substr(body, instr(body,"")+6, instr(body,"") - instr(body,"") - 6), " ", "") + else replace(substr(body, instr(body,"")+9, instr(body,"") - instr(body,"") - 9), " ", "") + end + when event = "message-summary" + then case when instr(body,"Messages-Waiting: yes") = 0 + then "Waiting" + else "Not-Waiting" + end + end as varchar(12))) state + from presentity diff --git a/kamailio/db_scripts/vw_wdispatcher.sql b/kamailio/db_scripts/vw_wdispatcher.sql new file mode 100644 index 0000000..1643b92 --- /dev/null +++ b/kamailio/db_scripts/vw_wdispatcher.sql @@ -0,0 +1,6 @@ +CREATE VIEW wdispatcher as + select *, + cast(substr(attrs, instr(attrs, "zone=")+5, instr(attrs, ";profile")-instr(attrs, "zone=")-5) as varchar(20)) zone, + cast(substr(attrs, instr(attrs, "idx=")+4, instr(attrs, ";node")-instr(attrs, "idx=")-4) as integer) idx, + cast(substr(attrs, instr(attrs, "node=")+5) as varchar(50)) node + from dispatcher diff --git a/kamailio/default.cfg b/kamailio/default.cfg index bf51561..09c2d55 100644 --- a/kamailio/default.cfg +++ b/kamailio/default.cfg @@ -30,7 +30,7 @@ debug = KAZOO_LOG_LEVEL memdbg = 10 memlog = L_INFO corelog = L_ERR -mem_summary = 12 +mem_summary = 0 log_stderror = no log_facility = LOG_LOCAL0 log_name="kamailio" @@ -71,14 +71,14 @@ udp4_raw = 0 # #udp_mtu_try_proto = TCP ####### DNS Parameters ######### -dns = no +dns = yes rev_dns = no dns_try_ipv6 = no use_dns_cache = on dns_cache_del_nonexp = yes dns_cache_flags = 1 dns_cache_gc_interval = 120 -dns_cache_init = 0 +dns_cache_init = 1 dns_cache_mem = 1000 dns_cache_negative_ttl = 60 dns_try_naptr = no @@ -299,7 +299,7 @@ route # log the basic info regarding this call xlog("L_INFO", "$ci|start|received $pr request $rm $ou\n"); - xlog("L_INFO", "$ci|log|source $si:$sp -> $Ri:$Rp\n"); + xlog("L_INFO", "$ci|log|source $si:$sp -> $RAi:$RAp\n"); xlog("L_INFO", "$ci|log|from $fu\n"); xlog("L_INFO", "$ci|log|to $tu\n"); @@ -380,17 +380,20 @@ route[CHECK_RETRANS] } } + +modparam("htable", "htable", "insane=>size=32;autoexpire=120;initval=0;updateexpire=1;") + route[SANITY_CHECK] { - ## CVE-2018-14767 - if($(hdr(To)[1]) != $null) { - xlog("second To header not null - dropping message"); + if($sht(insane=>$si:$sp) > 3) { drop; - } - - if (!sanity_check()) { - xlog("L_WARN", "$ci|end|message from $si:$sp is insane\n"); exit; + }; + + if (!sanity_check()) { + $var(insane) = $shtinc(insane=>$si:$sp); + xlog("L_WARN", "$ci|end|message from $si:$sp is insane ($var(insane))\n"); + drop; } if (!mf_process_maxfwd_header("10")) { @@ -406,7 +409,7 @@ route[SANITY_CHECK] $ua =~ "PortSIP" || $ua =~ "sipcli" ) { xlog("L_WARN", "$ci|end|dropping message with user-agent $ua from $si:$sp\n"); - exit; + drop; } } @@ -729,7 +732,9 @@ onreply_route[EXTERNAL_REPLY] #!endif #!ifdef NAT_TRAVERSAL_ROLE + if(!t_check_status("302")) { route(NAT_TEST_AND_CORRECT); + } #!endif #!ifdef ACL_ROLE @@ -752,7 +757,7 @@ onreply_route[EXTERNAL_REPLY] onreply_route[INTERNAL_REPLY] { # this route handles replies that are comming from our media server - xlog("L_INFO", "$ci|start|received internal reply $T_reply_code $rr\n"); + xlog("L_INFO", "$ci|start|received internal reply $T_reply_code $T_reply_reason\n"); xlog("L_INFO", "$ci|log|source $si:$sp\n"); #!ifdef WEBSOCKETS_ROLE @@ -787,7 +792,6 @@ onreply_route[INTERNAL_REPLY] xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)\n"); } - $var(reply_reason) = $rr; } failure_route[INTERNAL_FAULT] @@ -824,24 +828,24 @@ failure_route[INTERNAL_FAULT] # change 6xx to 4xx if (t_check_status("6[0-9][0-9]") && !t_check_status("600|603|604|606")) { $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); - xlog("L_INFO", "$ci|log|sending 6XX reply as $var(new_code) $var(reply_reason)\n"); - t_reply("$(var(new_code){s.int})", "$var(reply_reason)"); + xlog("L_INFO", "$ci|log|sending 6XX reply as $var(new_code) $T_reply_reason\n"); + t_reply("$(var(new_code){s.int})", "$T_reply_reason"); # if the failure case was something that we should recover # from then try to find a new media server - } else if ($var(reply_reason) =~ "call barred") { + } else if ($T_reply_reason =~ "call barred") { xlog("L_INFO", "$ci|log|failure route ignoring call barred\n"); } else if (isflagset(FLAG_SESSION_PROGRESS)) { xlog("L_INFO", "$ci|log|failure route ignoring failure after session progress\n"); - } else if (t_check_status("403") && $var(reply_reason)=="Forbidden") { + } else if (t_check_status("403") && $T_reply_reason=="Forbidden") { xlog("L_WARNING", "$ci|log|failure route ignoring. Failed auth from IP $si\n"); } else if (t_check_status("(401)|(407)|(486)|(403)")) { - xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $var(reply_reason)\n"); + xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $T_reply_reason\n"); } else if (t_check_status("402")) { xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486\n"); send_reply("486", "Insufficient Funds"); } else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])")) { - xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr\n"); + xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $T_reply_reason\n"); #!ifdef DISPATCHER_ROLE route(DISPATCHER_NEXT_ROUTE); @@ -849,7 +853,8 @@ failure_route[INTERNAL_FAULT] send_reply("486", "Unable to Comply"); } else { - xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr\n"); + xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $T_reply_reason\n"); + send_reply("$T_reply_code", "$T_reply_reason"); } xlog("L_INFO", "$ci|pass|$si:$sp\n"); } @@ -885,6 +890,28 @@ onsend_route { } #!ifdef REGISTRAR_ROLE + +#!ifdef WITH_AUTH_TOKEN +route[ADD_AUTHORIZATION_HEADERS] +{ + if (!is_method("INVITE|MESSAGE|REFER")) { + return; + } + + $xavp(regcfg=>match_received) = $su; + if (registered("location","$fu", 2, 1) == 1) { + if($(xavp(ulattrs=>token){s.len}) > 0) { + append_hf("X-AUTH-Token: $xavp(ulattrs=>token)\r\n"); + } else { + if($(xavp(ulattrs=>Authorizing-ID){s.len}) > 0 && $(xavp(ulattrs=>Account-ID){s.len})) { + append_hf("X-AUTH-Token: $xavp(ulattrs=>Authorizing-ID)@$xavp(ulattrs=>Account-ID)\r\n"); + } + } + } +} + +#!else + route[ADD_AUTHORIZATION_HEADERS] { if (!is_method("INVITE|MESSAGE|REFER")) { @@ -923,11 +950,15 @@ route[ADD_AUTHORIZATION_HEADERS] } #!endif -#!ifdef PRESENCE_NOTIFY_INIT +#!endif + +#!ifdef PRESENCE_ROLE event_route[tm:local-request] { route(PRESENCE_LOCAL_NOTIFY); } #!endif +#!import_file "custom-init.cfg" + # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/defs.cfg b/kamailio/defs.cfg index 2cb4cc7..24b72ae 100644 --- a/kamailio/defs.cfg +++ b/kamailio/defs.cfg @@ -31,14 +31,6 @@ #!define TCP_CHILDREN 25 #!endif -#!ifndef OPENBTS_AUTH_SECRET -#!substdef "!OPENBTS_AUTH_SECRET!b3a54fa8317c7d9cb1d89d8970947b30eda273124d97fc3a079ccc98ecc2569b!g" -#!endif - -#!ifndef KZ_USE_DISPATCHER_LIST -#!trydef KZ_USE_DISPATCHER_TABLE -#!endif - #!ifndef ANTIFLOOD_CACHE_PERIOD #!substdef "!ANTIFLOOD_CACHE_PERIOD!600!g" #!endif @@ -67,10 +59,6 @@ #!substdef "!MY_AMQP_ZONE!local!g" #!endif -#!ifndef DISPATCHER_ADD_SERVERS -#!define DISPATCHER_ADD_SERVERS 1 -#!endif - #!ifndef PRESENCE_RESET_BLF_DEFER_UPDATE #!define PRESENCE_RESET_BLF_DEFER_UPDATE 0 #!endif @@ -87,17 +75,10 @@ #!substdef "!MEDIA_SERVERS_HASH_SIZE!256!g" #!endif -#!ifndef KZ_PRESENCE_AMQP_PUBLISH -#!define KZ_PRESENCE_AMQP_PUBLISH 0 -#!endif - -#!ifndef KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE -#!define KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE 0 -#!endif +#!trydef KZ_PRESENCE_AMQP_PUBLISH 0 -#!ifndef KZ_PRESENCE_REQUEST_PROBE -#!define KZ_PRESENCE_REQUEST_PROBE 1 -#!endif +#!trydef KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE 0 +#!trydef KZ_PRESENCE_REQUEST_PROBE 1 #!ifndef NAT_UAC_TEST_LEVEL #!substdef "!NAT_UAC_TEST_LEVEL!3!g" @@ -130,6 +111,32 @@ #!trydef KZ_TLS_REGISTRAR_PORT 7000 #!endif +#!trydef KZ_FAST_PICKUP_COOKIES 1 +#!trydef KZ_FAST_PICKUP_REALTIME 1 + +#!trydef KZ_MULTI_HOMED 0 + +#!ifndef KZ_DISABLE_WEBSOCKETS_REGISTRAR_PORT +#!trydef KZ_WEBSOCKETS_REGISTRAR_PORT 7000 +#!endif + +#!ifndef KZ_DISABLE_TLS_REGISTRAR_PORT +#!trydef KZ_TLS_REGISTRAR_PORT 7000 +#!endif + +################################################################################ +## BINDINGS +################################################################################ +## This parameter is OPTIONAL. +## It will try to locate outbound interface +## on multihomed host. By default forward +## requests use the incoming socket disregarding +## the destination location. When enabled Kamailio +## will select a socket that can reach the +## destination. This reduces performance. +mhomed=KZ_MULTI_HOMED + + #!trydef KZ_FAST_PICKUP_COOKIES 1 #!trydef KZ_FAST_PICKUP_REALTIME 1 diff --git a/kamailio/dispatcher-role.cfg b/kamailio/dispatcher-role.cfg index 24b26cc..8dfeef2 100644 --- a/kamailio/dispatcher-role.cfg +++ b/kamailio/dispatcher-role.cfg @@ -1,7 +1,12 @@ ######## Generic Hash Table container in shared memory ######## modparam("htable", "htable", "failover=>size=16;autoexpire=120") +#!trydef KZ_DISPATCHER_PROBE_MODE 1 +#!trydef DISPATCHER_ADD_SERVERS 1 +#!trydef DISPATCHER_ALG 4 + kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr" +kazoo.dispatcher_algorithm = DISPATCHER_ALG descr "dispatcher algorithm to use" ####### Dispatcher module ######## loadmodule "dispatcher.so" @@ -18,7 +23,7 @@ modparam("dispatcher", "setid_pvname", "$var(setid)") modparam("dispatcher", "ds_ping_method", "OPTIONS") modparam("dispatcher", "ds_ping_interval", 10) modparam("dispatcher", "ds_probing_threshold", 3) -modparam("dispatcher", "ds_probing_mode", 1) +modparam("dispatcher", "ds_probing_mode", KZ_DISPATCHER_PROBE_MODE) modparam("dispatcher", "ds_ping_reply_codes", "501,403,404,400,200") modparam("dispatcher", "ds_ping_from", "sip:sipcheck@MY_HOSTNAME") @@ -87,9 +92,9 @@ route[DISPATCHER_FIND_ROUTES] $var(ds_group) = $var(ds_primary_group); - if (!ds_select_dst("$var(ds_primary_group)", "0") || $(avp(ds_dst)[0]) == $null) { + if (!ds_select_dst("$var(ds_primary_group)", "$sel(cfg_get.kazoo.dispatcher_algorithm)") || $(avp(ds_dst)[0]) == $null) { # we selected from primary group, try again in backup group - if (!ds_select_dst("$var(ds_backup_group)", "0") || $(avp(ds_dst)[0]) == $null) { + if (!ds_select_dst("$var(ds_backup_group)", "$sel(cfg_get.kazoo.dispatcher_algorithm)") || $(avp(ds_dst)[0]) == $null) { xlog("L_WARN", "$ci|end|no servers available in primary or backup group\n"); sl_send_reply("480", "All servers busy"); exit; @@ -227,12 +232,19 @@ route[DISPATCHER_CHECK_MEDIA_SERVER] if($var(Zone) != "MY_AMQP_ZONE") { $var(SetId) = 2; } - sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT"); + if($(var(MediaUrl){uri.port}) == 12000) { + $var(SetId) = $var(SetId) + 50; + } + $var(flags) = 10; + $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);idx=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName)); + sql_query("exec", "insert into dispatcher (setid, destination, flags, attrs, description) select $var(SetId), \"$var(MediaUrl)\", $var(flags), \"$var(attrs)\", \"added by nodes role\" where not exists(select * from dispatcher where destination = \"$var(MediaUrl)\")"); if($sqlrows(exec) > 0) { xlog("L_WARNING", "reloading dispatcher table\n"); ds_reload(); + return 1; } } + return 0; } route[DISPATCHER_STATUS] diff --git a/kamailio/fast-pickup-role.cfg b/kamailio/fast-pickup-role.cfg index 36c05e7..2714eb3 100644 --- a/kamailio/fast-pickup-role.cfg +++ b/kamailio/fast-pickup-role.cfg @@ -13,7 +13,6 @@ route[FAST_PICKUP_START] route[FAST_PICKUP_LOAD] { sht_reset("fp"); -#!ifndef KZ_USE_DISPATCHER_LIST 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) { @@ -31,9 +30,6 @@ route[FAST_PICKUP_LOAD] pv_unset("$xavp(ra)"); } } -#!else - xlog("L_INFO", "$ci|log|fast|cannot initialize hash table from dispatcher. check KZ_USE_DISPATCHER_LIST option in local.cfg\n"); -#!endif } route[FAST_PICKUP_ATTEMPT] @@ -107,6 +103,21 @@ route[FAST_PICKUP_ATTEMPT] route(EXTERNAL_TO_INTERNAL_RELAY); exit(); } + + ##### CALL-PARK IN KAZOO #### + if($(ru{uri.user}) =~ "\*[3-4]" && !($rd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") ) { + 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" : "$(ru{uri.user})", "Realm" : "$(ru{uri.domain})", "Active-Only" : true }'; + $var(amqp_routing_key) = "call.status_req." + $(var(replaced_call_id){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, courtesy of kazoo\n"); + route(EXTERNAL_TO_INTERNAL_RELAY); + exit(); + } + } + } } route[FAST_PICKUP_OPTION] @@ -136,7 +147,6 @@ route[FAST_PICKUP_INIT] } else { $sht(park=>$(kzE{kz.json,Presence-ID})) = $(kzE{kz.json,Switch-URI}); } - } ## fast pickup with cookies @@ -151,7 +161,7 @@ route[FAST_PICKUP_INIT] $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_INFO", "$var(call_id)|fast|shortcut ($var(Pickup)) kfp+$var(Option)$var(Cookie)@$var(call_id)\n"); + xlog("L_DEBUG", "$var(call_id)|fast|shortcut ($var(Pickup)) kfp+$var(Option)$var(Cookie)@$var(call_id)\n"); } } diff --git a/kamailio/kazoo-bindings.cfg b/kamailio/kazoo-bindings.cfg index c4c520f..cf243b7 100644 --- a/kamailio/kazoo-bindings.cfg +++ b/kamailio/kazoo-bindings.cfg @@ -59,4 +59,14 @@ event_route[kazoo:consumer-event-connection-closed] xlog("L_INFO","connection to $(kzE{kz.json,host}) closed\n"); } +event_route[kazoo:consumer-event-connection-zone-available] +{ + xlog("L_NOTICE","amqp zone $(kzE{kz.json,zone}) is available\n"); +} + +event_route[kazoo:consumer-event-connection-zone-unavailable] +{ + xlog("L_WARN","amqp zone $(kzE{kz.json,zone}) is unavailable\n"); +} + # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/message-role.cfg b/kamailio/message-role.cfg index a0fa312..1b56a5a 100644 --- a/kamailio/message-role.cfg +++ b/kamailio/message-role.cfg @@ -54,7 +54,7 @@ route[MESSAGE_REPLY] route[MESSAGE_BINDINGS] { $var(key) = "kamailio@MY_HOSTNAME"; - $var(payload) = "{ 'exchange' : 'sms' , 'type' : 'topic', 'queue' : 'MSG-QUEUE-MY_HOSTNAME', 'routing' : 'message.route." + $(var(key){kz.encode}) + ".*', 'no_ack' : 0 }"; + $var(payload) = $_s({"exchange": "sms", "type": "topic", "queue": "MSG-QUEUE-MY_HOSTNAME", "routing": "message.route.$(var(key){kz.encode}).*", "no_ack": 0 }); kazoo_subscribe("$var(payload)"); } diff --git a/kamailio/nat-traversal-role.cfg b/kamailio/nat-traversal-role.cfg index 7166446..7b087bf 100644 --- a/kamailio/nat-traversal-role.cfg +++ b/kamailio/nat-traversal-role.cfg @@ -1,6 +1,7 @@ ######## NAT Traversal module - signaling functions ######## #!ifndef NATHELPER_LOADED loadmodule "nathelper.so" +#!trydef NATHELPER_LOADED #!endif modparam("nathelper", "received_avp", "$avp(AVP_RECV_PARAM)") modparam("nathelper", "sipping_from", "sip:sipcheck@MY_HOSTNAME") diff --git a/kamailio/nodes-role.cfg b/kamailio/nodes-role.cfg index c3df110..8faf114 100644 --- a/kamailio/nodes-role.cfg +++ b/kamailio/nodes-role.cfg @@ -1,12 +1,7 @@ ######## Nodes role - pushes info to kazoo ######## -#!ifndef NODES_EXPIRE -#!define NODES_EXPIRE 10 -#!endif - -#!ifndef NODES_FUDGE_FACTOR -#!define NODES_FUDGE_FACTOR 10 -#!endif +#!trydef NODES_EXPIRE 10 +#!trydef NODES_FUDGE_EXPIRE 45 modparam("htable", "htable", "nodes=>size=8;initval=0;autoexpire=60"); modparam("htable", "htable", "media=>size=8;initval=0;autoexpire=60"); @@ -61,7 +56,7 @@ route(LISTENER_STATUS); #!endif $var(Roles) = $_s("Roles" : {"Proxy" : $var(listeners) $var(Dispatcher) $var(Presence) $var(Registrar)}); - $var(Payload) = '{"Event-Category" : "nodes", "Event-Name" : "advertise", "Expires" : 15000, "Used-Memory" : $(stat(real_used_size){s.int}), "Startup" : $Tb, "WhApps" : {"kamailio" : {"Startup" : $Tb }}, $var(Roles)}'; + $var(Payload) = $_s({"Event-Category" : "nodes", "Event-Name" : "advertise", "Expires" : 15000, "Used-Memory" : $(stat(real_used_size){s.int}), "Startup" : $Tb, "WhApps" : {"kamailio" : {"Startup" : $Tb }}, $var(Roles)}); kazoo_publish("nodes", "", $var(Payload)); } @@ -117,7 +112,7 @@ route[NODE_HEARTBEAT_ROUTE] route(CHECK_MEDIA_SERVERS); $sht(nodes=>$var(Node)) = $var(Payload); - $shtex(nodes=>$var(Node)) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_FACTOR; + $shtex(nodes=>$var(Node)) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_EXPIRE; $var(runloop) = $var(runloop) + 1; } } @@ -153,7 +148,7 @@ route[CHECK_MEDIA_SERVERS] $shtex(media=>$var(MediaUrl)::zone) = 0; route(MEDIA_SERVER_UP); }; - $var(MediaExpire) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_FACTOR; + $var(MediaExpire) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_EXPIRE; xlog("L_DEBUG", "nodes|media|$var(Node) media expiration $var(MediaExpire) for $var(MediaUrl)\n"); $shtex(media=>$var(MediaUrl)::count) = $var(MediaExpire); $var(ProfileIdx) = $var(ProfileIdx) + 1; @@ -198,7 +193,7 @@ route[MEDIA_SERVER_DOWN] #!ifndef NODES_CUSTOM_BINDINGS route[NODES_BINDINGS] { - $var(payload) = "{ 'exchange' : 'nodes' , 'type' : 'fanout', 'queue' : 'nodes-MY_HOSTNAME', 'exclusive' : 0, 'federate' : 1}"; + $var(payload) = $_s({"exchange" : "nodes" , "type" : "fanout", "queue" : "nodes-MY_HOSTNAME", "exclusive":0, "federate":1 }); kazoo_subscribe("$var(payload)"); } #!endif @@ -215,6 +210,12 @@ route[LISTENER_STATUS] $var(proto) = $(var(listener){kz.json,PROTO}); $var(address) = $(var(listener){kz.json,ADDRLIST.ADDR}); $var(port) = $(var(listener){kz.json,PORT}); + if($var(port) == "WS_PORT") { + $var(proto) = "ws"; + } + if($var(port) == "WSS_PORT") { + $var(proto) = "wss"; + } $var(uri) = $_s($var(proto):$var(address):$var(port)); if($(var(listener){kz.json,ADVERTISE}) != "-") { $var(advertise) = $_s( , "advertise" : "$(var(listener){kz.json,ADVERTISE})"); diff --git a/kamailio/presence_notify_sync-role.cfg b/kamailio/presence-notify.cfg similarity index 64% rename from kamailio/presence_notify_sync-role.cfg rename to kamailio/presence-notify.cfg index d8b4b8e..107f740 100644 --- a/kamailio/presence_notify_sync-role.cfg +++ b/kamailio/presence-notify.cfg @@ -6,7 +6,7 @@ kazoo.presence_notify_log_to_table = 1 descr "logs notify/reply to active_watche kazoo.presence_notify_log_to_amqp = 0 descr "logs notify/reply to amqp" kazoo.presence_notify_record_route = 1 descr "add record route header to notify msg sent" kazoo.presence_notify_log_init_body = 0 descr "logs the body before its sent" -kazoo.presence_notify_force_send_socket = 0 descr "forces the send socket to the contact" +kazoo.presence_notify_force_send_socket = 1 descr "forces the send socket to the contact" ######## Generic Hash Table container in shared memory ######## modparam("htable", "htable", "notify=>size=16;autoexpire=3600;updateexpire=1;initval=0") @@ -20,17 +20,22 @@ route[PRESENCE_LOCAL_NOTIFY] return; } t_set_fr(@cfg_get.kazoo.presence_notify_timeout, @cfg_get.kazoo.presence_notify_timeout); - xlog("L_INFO", "$ci|log|init preparing $subs(event) notify to $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri) : $du\n"); + xlog("L_DEBUG", "$ci|log|init preparing $subs(event) notify to $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri) : $du\n"); if(@cfg_get.kazoo.presence_notify_log_init_body == 1) { xlog("L_INFO", "$ci|log|init|body $(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\n"); } if(@cfg_get.kazoo.presence_notify_force_send_socket == 1) { $fs = $_s($(pr{s.tolower}):$(hdr(Contact){nameaddr.uri}{uri.host}):$(hdr(Contact){nameaddr.uri}{uri.port})); - xlog("L_INFO", "$ci|log|init|forcing socket to $fs, $(pr{s.tolower}):$(hdr(Contact){nameaddr.uri}{uri.host}):$(hdr(Contact){nameaddr.uri}{uri.port}) , $ct\n"); + xlog("L_DEBUG", "$ci|log|init|forcing socket to $fs, $(pr{s.tolower}):$(hdr(Contact){nameaddr.uri}{uri.host}):$(hdr(Contact){nameaddr.uri}{uri.port}) , $ct\n"); } if(@cfg_get.kazoo.presence_notify_record_route == 1) { record_route(); } + + #!ifdef SIP_TRACE_ROLE + route(SEND_SIP_TRACE); + #!endif + } modparam("mqueue","mqueue", "name=presence_last_notity") @@ -40,9 +45,10 @@ modparam("mqueue","mqueue", "name=presence_last_notity") loadmodule "rtimer.so" #!trydef RTIMER_LOADED #!endif -modparam("rtimer", "timer", "name=notifytimer;interval=500000u;mode=2;") +modparam("rtimer", "timer", "name=notifytimer;interval=500000u;mode=1;") modparam("rtimer", "exec", "timer=notifytimer;route=PRESENCE_LOG_TIMER_ROUTE") - +modparam("rtimer", "timer", "name=pres_cleanup;interval=10;mode=1;") +modparam("rtimer", "exec", "timer=pres_cleanup;route=PRESENCE_CLEANUP") event_route[presence:notify-reply] { @@ -53,13 +59,17 @@ event_route[presence:notify-reply] if($subs(reason) == "timeout") { $xavp(pres=>delete_subscription) = 1; - xlog("L_INFO", "$ci|end|deleting subscribtion $subs(pres_uri) for $subs(watcher_username)@$subs(watcher_domain) due to timeout\n"); + xlog("L_INFO", "$ci|end|deleting subscription $subs(pres_uri) for $subs(watcher_username)@$subs(watcher_domain) due to timeout\n"); } else if($notify_reply($rs) == 200) { $sht(notify=>$ci) = $null; $sht(notify=>$ci::count) = 0; xlog("L_INFO", "$ci|end|notified $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n"); + } else if($notify_reply($rs) == 481 && $subs(reason) == "timeout") { + xlog("L_INFO","$ci|end|sent subscription $hdr(Subscription-State)\n"); + } else if($notify_reply($rs) == 481) { + $xavp(pres=>delete_subscription) = 1; + xlog("L_INFO", "$ci|end|deleting subscription $subs(pres_uri) as $subs(watcher_username)@$subs(watcher_domain) replied with 481 (non existent)\n"); } else { - xlog("L_ERROR", "$ci|error|received $notify_reply($rs) when notifying $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n"); if($rP != "UDP") { $xavp(pres=>delete_subscription) = 1; xlog("L_ERROR", "$ci|error|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri)\n"); @@ -68,6 +78,9 @@ event_route[presence:notify-reply] if($var(shtinc) > MAX_NOTIFY_ERROR) { $xavp(pres=>delete_subscription) = 1; xlog("L_ERROR", "$ci|error|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri)\n"); + } else { + $var(max_notify) = MAX_NOTIFY_ERROR; + xlog("L_WARN", "$ci|error|received $notify_reply($rs) ($var(shtinc)/$var(max_notify)) when notifying $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n"); } } } @@ -81,8 +94,10 @@ event_route[presence:notify-reply] } if(@cfg_get.kazoo.presence_notify_log_to_table == 1) { - $var(Query) = $_s(REPLACE INTO active_watchers_log (presentity_uri, watcher_username, watcher_domain, event, callid, to_user, to_domain, user_agent, time, result, sent_msg, received_msg) VALUES ("$subs(uri)", "$subs(watcher_username)", "$subs(watcher_domain)", "$subs(event)","$subs(callid)","$subs(to_user)","$subs(to_domain)", '$(subs(user_agent){s.escape.common}{s.replace,\',''}{s.replace,$$,})', $TS, $notify_reply($rs), '$(mb{s.escape.common}{s.replace,\',''}{s.replace,$$,})', '$(notify_reply($mb){s.escape.common}{s.replace,\',''}{s.replace,$$,})')); - mq_add("presence_last_notity", "$subs(callid)", "$var(Query)"); + if($xavp(pres=>delete_subscription) != 1 && $subs(reason) != "timeout") { + $var(Query) = $_s(KZQ_REPLACE_WATCHERS_LOG); + mq_add("presence_last_notity", "$subs(callid)", "$var(Query)"); + } } } @@ -96,12 +111,12 @@ route[PRESENCE_LOG_TIMER_ROUTE] $var(sqlres) = sql_query("cb", "$mqv(presence_last_notity)"); xlog("L_DEBUG", "Query result : $var(sqlres)\n"); if($var(sqlres) < 0) { - xlog("L_ERROR", "$var(ci)|log|error updating active_watchers_log\n"); + xlog("L_ERROR", "$var(ci)|log|error running query : $mqv(presence_last_notity)\n"); } else { $var(nrows) = $sqlrows(cb); xlog("L_DEBUG", "$var(ci)|log|end UPDATED $var(nrows)\n"); if($var(nrows) == 0) { - xlog("L_ERROR", "$var(ci)|log|error no rows affected when updating active_watchers_log\n"); + xlog("L_DEBUG", "$var(ci)|log|error no rows affected when running query\n"); } } $var(runloop) = $var(runloop) + 1; @@ -115,3 +130,18 @@ route[PRESENCE_NOTIFY_AMQP] kazoo_publish("omnipresence", "$var(rk)", $var(amqp_payload_request)); xlog("L_INFO", "$ci|log|sent notify callback for event $subs(event) : $tu\n"); } + + +route[PRESENCE_CLEANUP] +{ + $var(Query) = $_s(DELETE FROM active_watchers WHERE expires > 0 AND datetime(expires, 'unixepoch') < datetime('now', '-90 seconds');); + mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); + $var(Query) = $_s(DELETE FROM PRESENTITY WHERE expires > 0 AND datetime(expires, 'unixepoch') < datetime('now', '-90 seconds');); + mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); + $var(Query) = $_s(DELETE FROM PRESENTITY WHERE ID IN(select id from presentities where event = "dialog" and state = "terminated" and received < datetime('now', '-5 minutes'));); + mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); + $var(Query) = $_s(DELETE FROM ACTIVE_WATCHERS_LOG WHERE ID IN(select id from active_watchers_log a where not exists(select callid from active_watchers b where b.callid = a.callid and b.watcher_username = a.watcher_username and b.watcher_domain = a.watcher_domain));); + mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); +} + +#!import_file "presence-custom-cleanup.cfg" diff --git a/kamailio/presence_query-role.cfg b/kamailio/presence-query.cfg similarity index 91% rename from kamailio/presence_query-role.cfg rename to kamailio/presence-query.cfg index ac087cc..2041cb0 100644 --- a/kamailio/presence_query-role.cfg +++ b/kamailio/presence-query.cfg @@ -56,6 +56,7 @@ route[PRESENCE_SEARCH_DETAIL] { xlog("L_INFO", "processing presence query detail for $(kzE{kz.json,Username}) in realm $(kzE{kz.json,Realm})\n"); $var(Queue) = $(kzE{kz.json,Server-ID}); + $var(Msg-ID) = $(kzE{kz.json,Msg-ID}); $var(Event) = $(kzE{kz.json,Event-Package}); $var(Domain) = $(kzE{kz.json,Realm}); $var(Username) = $(kzE{kz.json,Username}); @@ -75,14 +76,14 @@ route[PRESENCE_SEARCH_DETAIL] while($xavp(ra) != $null && $var(Event) == $xavp(ra=>event)) { $var(Sub) = $_s("$var(Username)" : {"$xavp(ra=>event)" : { "$xavp(ra=>watcher_username)" : {"kamailio@MY_HOSTNAME" : {"$xavp(ra=>callid)" : {"time" : $xavp(ra=>time), "result" : $xavp(ra=>result), "sent" : "$(xavp(ra=>sent_msg){s.escape.common}{s.replace,\','}{s.replace,$$,})", "received" : "$(xavp(ra=>received_msg){s.escape.common}{s.replace,\','}{s.replace,$$,})", "user_agent" : "$(xavp(ra=>user_agent){s.escape.common}{s.replace,\','}{s.replace,$$,})"}}}}}); xlog("L_DEBUG", "$ci| RESULT \"Subscriptions\" : { $var(Sub) }\n"); - $var(amqp_payload_request) = '{"Event-Category" : "presence", "Event-Name" : "search_partial_resp", "Msg-ID" : "$(kzE{kz.json,Msg-ID})", "Subscriptions" : { $var(Sub) } }'; + $var(amqp_payload_request) = '{"Event-Category" : "presence", "Event-Name" : "search_partial_resp", "Msg-ID" : "$var(Msg-ID)", "Subscriptions" : { $var(Sub) } }'; kazoo_publish("targeted", "$var(Queue)", $var(amqp_payload_request)); pv_unset("$xavp(ra)"); } } } - $var(amqp_payload_request) = '{"Event-Category" : "presence", "Event-Name" : "search_resp", "Msg-ID" : "$(kzE{kz.json,Msg-ID})" }'; + $var(amqp_payload_request) = '{"Event-Category" : "presence", "Event-Name" : "search_resp", "Msg-ID" : "$var(Msg-ID)" }'; kazoo_publish("targeted", "$var(Queue)", $var(amqp_payload_request)); } @@ -105,7 +106,7 @@ event_route[kazoo:consumer-event-presence-search-req] route[PRESENCE_QUERY_BINDINGS] { - $var(payload) = "{ 'exchange' : 'presence' , 'type' : 'topic', 'queue' : 'presence-search-MY_HOSTNAME', 'routing' : 'presence.search_req.*', 'exclusive' : 0, 'federate' : 1 }"; + $var(payload) = $_s({"exchange": "presence", "type": "topic", "queue": "presence-search-MY_HOSTNAME", "routing": "presence.search_req.*", "exclusive": 0, "federate": 1 }); kazoo_subscribe("$var(payload)"); } diff --git a/kamailio/presence-reset.cfg b/kamailio/presence-reset.cfg index eafd672..b450ad7 100644 --- a/kamailio/presence-reset.cfg +++ b/kamailio/presence-reset.cfg @@ -19,7 +19,7 @@ route[PRESENCE_RESET_BINDINGS] #!import_file "presence-reset-custom-bindings.cfg" #!ifndef PRESENCE_RESET_CUSTOM_BINDINGS - $var(payload) = "{ 'exchange' : 'presence' , 'queue' : 'presence-reset-MY_HOSTNAME', 'type' : 'topic', 'routing' : 'presence.reset.*.*', 'exclusive' : 0, 'federate' : 1 }"; + $var(payload) = $_s({"exchange": "presence", "queue": "presence-reset-MY_HOSTNAME", "type": "topic", "routing": "presence.reset.*.*", "exclusive": 0, "federate": 1 }); kazoo_subscribe("$var(payload)"); #!endif @@ -98,7 +98,6 @@ route[RESET_WILDCARD] } - event_route[kazoo:consumer-event-presence-reset] { if($(kzE{kz.json,Username}) == "*" || $(kzE{kz.json,Realm}) == "*") { diff --git a/kamailio/presence-role.cfg b/kamailio/presence-role.cfg index d5d4997..3ce222f 100644 --- a/kamailio/presence-role.cfg +++ b/kamailio/presence-role.cfg @@ -2,7 +2,6 @@ #!trydef PRESENCE_MIN_EXPIRES 300 #!trydef PRESENCE_MIN_EXPIRES_ACTION 1 #!trydef PRESENCE_MAX_EXPIRES 3600 - #!trydef KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP 1 modparam("htable", "htable", "p=>size=32;autoexpire=3600;") @@ -24,8 +23,10 @@ modparam("presence_xml", "disable_bla", 1) modparam("presence", "subs_db_mode", 3) modparam("presence", "expires_offset", 0) modparam("presence", "send_fast_notify", 1) -modparam("presence", "clean_period", 30) -modparam("presence", "db_update_period", 10) + +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) @@ -63,12 +64,10 @@ kazoo.presence_ignore_status_probe_resp = KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP d #!ifdef FAST_PICKUP_ROLE #!include_file "fast-pickup-role.cfg" #!endif -#!ifdef PRESENCE_QUERY_ROLE -#!include_file "presence_query-role.cfg" -#!endif -#!ifdef PRESENCE_NOTIFY_SYNC_ROLE -#!include_file "presence_notify_sync-role.cfg" -#!endif + +#!include_file "presence-query.cfg" +#!include_file "presence-notify.cfg" +#!include_file "presence-reset.cfg" ####### Presence Logic ######## @@ -90,8 +89,25 @@ route[HANDLE_SUBSCRIBE] return; } + 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 (!t_newtran()) { + sl_reply_error(); + exit; + } + + #!ifdef SIP_TRACE_ROLE + route(SEND_SIP_TRACE); + #!endif + #!ifdef NAT_TRAVERSAL_ROLE - route(PRESENCE_NAT); + route(PRESENCE_NAT); #!endif if(has_totag()) { @@ -100,11 +116,6 @@ route[HANDLE_SUBSCRIBE] record_route(); - if (!t_newtran()) { - sl_reply_error(); - exit; - } - if(has_totag()) { route(HANDLE_RESUBSCRIBE); } else { @@ -116,6 +127,11 @@ route[HANDLE_SUBSCRIBE] exit; } +route[DELETE_DUPLICATED_SUBSCRIPTIONS] +{ + sql_query("exec", '$_s(DELETE FROM ACTIVE_WATCHERS WHERE FROM_USER = "$subs(from_user)" AND FROM_DOMAIN="$subs(from_domain)" AND EVENT="$subs(event)" AND PRESENTITY_URI="$subs(uri)" AND CALLID <> "$subs(callid)")'); +} + route[HANDLE_RESUBSCRIBE] { @@ -124,7 +140,9 @@ route[HANDLE_RESUBSCRIBE] $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); }; } @@ -164,6 +182,7 @@ route[HANDLE_NEW_SUBSCRIBE] 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); } else { @@ -209,26 +228,38 @@ route[REQUEST_PROBE] route[REQUEST_MWI] { - xlog("L_INFO", "$ci|sub|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)); + xlog("L_INFO", "$ci|sub|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")) { - if (!t_newtran()) { - sl_reply_error(); - exit; - } - if($hdr(Sender)!= $null) - handle_publish("$hdr(Sender)"); - else - handle_publish(); - t_release(); + if(!is_method("PUBLISH")) { + return; + } + + 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 (!t_newtran()) { + sl_reply_error(); exit; } + + if($hdr(Sender)!= $null) { + handle_publish("$hdr(Sender)"); + } else { + handle_publish(); + } + t_release(); + exit; } route[HAS_PRESENTITY] @@ -248,7 +279,7 @@ route[HAS_PRESENTITY] route[COUNT_PRESENTITIES] { $var(Query) = $_s(KZQ_COUNT_PRESENTITIES); - $var(p) = $_s(uri=$var(presentity)); + $var(p) = $_s(presence_id='$var(presentity)'); if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { @@ -262,7 +293,7 @@ route[COUNT_PRESENTITIES] 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) = "uri=none"; + $var(p) = "presence_id=none"; if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { @@ -293,7 +324,7 @@ route[COUNT_ALL_SUBSCRIBERS] route[COUNT_SUBSCRIBERS] { $var(Query) = $_s(KZQ_COUNT_SUBSCRIBERS); - $var(p) = $_s(uri=$var(presentity)); + $var(p) = $_s(presence_id='$var(presentity)'); if (sql_xquery("cb", "$var(Query)", "subs") == 1) { while($xavp(subs) != $null) { @@ -306,37 +337,40 @@ route[COUNT_SUBSCRIBERS] event_route[kazoo:consumer-event-presence-dialog-update] { - $var(Now) = $TS; - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)\n"); + $var(StartRoute) = $(TV(Sn){s.replace,.,}); + $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received}); + xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|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; #!ifdef FAST_PICKUP_ROLE route(FAST_PICKUP_INIT); #!endif - + $var(presentity) = $(kzE{kz.json,From}); $var(payload) = $kzE; - + route(PRESENCE_UPDATE); - - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n"); + $var(EndRoute) = $(TV(Sn){s.replace,.,}); + $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute); + + xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing $(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] { - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received message-summary update for $(kzE{kz.json,From})\n"); + xlog("L_DBG", "$(kzE{kz.json,Call-ID})|log|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) { xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|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 { - xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|skip message-summary update for $(kzE{kz.json,From})\n"); } route(MWI_AS_PRESENCE); - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing message-summary update for $(kzE{kz.json,From}) light should be on ? $(kzE{kz.json,Messages-Waiting}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n"); + xlog("L_DBG", "$(kzE{kz.json,Call-ID})|log|finished processing message-summary update for $(kzE{kz.json,From}) light should be on ? $(kzE{kz.json,Messages-Waiting}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n"); } @@ -344,17 +378,18 @@ event_route[kazoo:consumer-event-presence-update] { if(@cfg_get.kazoo.presence_ignore_status_probe_resp == 1) { if($(kzE{kz.json,State}) == "offline" || $(kzE{kz.json,State}) == "online") { + xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|ignoring $(kzE{kz.json,State}) state $(kzE{kz.json,Presence-ID})\n"); return; } } - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received presence update for $(kzE{kz.json,Presence-ID})\n"); + xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|received presence update for $(kzE{kz.json,Presence-ID})"); $var(JObj) = $kzE; $var(presentity) = $_s(sip:$(kzE{kz.json,Presence-ID})); $var(payload) = $kzE; route(PRESENCE_UPDATE); - xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n"); + xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|finished processing $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) Δ at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n"); } route[PRESENCE_UPDATE] @@ -366,20 +401,23 @@ route[PRESENCE_UPDATE] } if($xavp(watchers=>dialog) > 0) { - xlog("L_INFO", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) dialog update for $xavp(watchers=>dialog) watchers\n"); - kazoo_pua_publish_dialoginfo($var(JObj)); - pres_refresh_watchers("$var(presentity)", "dialog", 1); - } else { - xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|skip dialog update for $var(presentity)\n"); + if($(var(payload){kz.json,State}) == "terminated") { + xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) dialog update for terminated dialog\n"); + } else { + xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|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", "$(var(payload){kz.json,Call-ID})|log|error publishing $var(presentity) dialog update\n"); + }; } if($xavp(watchers=>presence) > 0) { - xlog("L_INFO", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) presence update for $xavp(watchers=>presence) watchers\n"); + xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) presence update for $xavp(watchers=>presence) watchers\n"); kazoo_pua_publish_presence($var(payload)); pres_refresh_watchers("$var(presentity)", "presence", 1); - } else { - xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|skip presence update for $var(presentity)\n"); - } + } } @@ -405,38 +443,26 @@ route[MWI_AS_PRESENCE] $var(State) = "confirmed"; } else { $var(State) = "terminated"; - } + } $var(payload) = MWI_PRESENCE_BODY $var(JObj) = $var(payload); - route(PRESENCE_UPDATE); } -#!include_file "presence-reset.cfg" - route[PRESENCE_BINDINGS] { #!import_file "presence-custom-bindings.cfg" #!ifndef PRESENCE_CUSTOM_BINDINGS - $var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-dialog-MY_HOSTNAME", "routing" : "dialog.*.*", "exclusive" : 0, "federate" : 1 }); - kazoo_subscribe("$var(payload)"); - - - $var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-presence-MY_HOSTNAME", "routing" : "update.*.*", "exclusive" : 0, "federate" : 1 }); + $var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-dialog-MY_HOSTNAME", "routing" : ["dialog.*.*", "update.*.*", "mwi_updates.*.*"], "exclusive" : 0, "federate" : 1 }); kazoo_subscribe("$var(payload)"); - $var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-mwi-MY_HOSTNAME", "routing" : "mwi_updates.*.*", "exclusive" : 0 , "federate" : 1 }); - kazoo_subscribe("$var(payload)"); #!endif route(PRESENCE_RESET_BINDINGS); - - #!ifdef PRESENCE_QUERY_ROLE route(PRESENCE_QUERY_BINDINGS); - #!endif #!ifdef FAST_PICKUP_ROLE route(FAST_PICKUP_START); @@ -445,4 +471,5 @@ route[PRESENCE_BINDINGS] } + # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab diff --git a/kamailio/pusher-role.cfg b/kamailio/pusher-role.cfg index 6097a06..a15ec68 100644 --- a/kamailio/pusher-role.cfg +++ b/kamailio/pusher-role.cfg @@ -126,6 +126,7 @@ route[PUSHER_ATTEMPT_REGISTRATION] $xavp(ulattrs=>custom_channel_vars) = "{}"; $xavp(ulattrs[0]=>x_token_reg) = $hdr(X-Token-Reg); route(SAVE_LOCATION); + exit; } else { xlog("L_INFO", "$ci|pusher|registration x-token-reg '$hdr(X-Token-Reg)' from header was not found\n"); } @@ -139,6 +140,7 @@ route[PUSHER_ATTEMPT_REGISTRATION] $xavp(ulattrs=>custom_channel_vars) = "{}"; $xavp(ulattrs[0]=>x_token_reg) = $(sel(contact.uri){uri.param,x-token-reg}); route(SAVE_LOCATION); + exit; } else { xlog("L_INFO", "$ci|pusher|registration x-token-reg from contact uri param '$(sel(contact.uri){uri.param,x-token-reg})' was not found\n"); } @@ -152,6 +154,7 @@ route[PUSHER_ATTEMPT_REGISTRATION] $xavp(ulattrs=>custom_channel_vars) = "{}"; $xavp(ulattrs[0]=>x_token_reg) = $(sel(contact){tobody.params}{param.value,x-token-reg}); route(SAVE_LOCATION); + exit; } else { xlog("L_INFO", "$ci|pusher|registration x-token-reg from contact param '$(sel(contact){tobody.params}{param.value,x-token-reg})' was not found\n"); } diff --git a/kamailio/registrar-role.cfg b/kamailio/registrar-role.cfg index 3474fd0..e5aa6fc 100644 --- a/kamailio/registrar-role.cfg +++ b/kamailio/registrar-role.cfg @@ -2,8 +2,12 @@ #!trydef REGISTRAR_NAT_PING_WORKERS 5 #!trydef REGISTRAR_MIN_EXPIRES 300 #!trydef REGISTRAR_MAX_EXPIRES 3600 +#!trydef REGISTRAR_DEFAULT_EXPIRES 600 +#!trydef REGISTRAR_ERROR_MIN_EXPIRES 1 #!trydef REGISTRAR_CONTACT_MAX_SIZE 2048 +#!trydef REGISTRAR_QUERY_TIMEOUT_MS 2500 + #!trydef REGISTRAR_HANDLE_LOST_TCP 1 #!trydef REGISTRAR_CLOSE_EXPIRED_TCP 1 @@ -17,13 +21,10 @@ modparam("htable", "htable", "auth_cache=>size=16;autoexpire=7200;") ####### Authentication Interface module ########## loadmodule "auth.so" +modparam("auth", "auth_checks_register", 11) +modparam("auth", "qop", "auth") +modparam("auth", "nonce_expire", 90) -#!ifdef OPENBTS_AUTH_ROLE -loadmodule "auth_openbts.so" -modparam("auth", "qop", "") -modparam("auth", "secret", "OPENBTS_AUTH_SECRET") -modparam("auth_openbts", "challenge_attr", "$avp(digest_challenge)") -#!endif ####### User Location Implementation module ########## loadmodule "usrloc.so" @@ -47,7 +48,7 @@ modparam("usrloc", "close_expired_tcp", REGISTRAR_CLOSE_EXPIRED_TCP) #!trydef NATHELPER_LOADED loadmodule "nathelper.so" modparam("nathelper", "natping_interval", REGISTRAR_NAT_PING_INTERVAL) -modparam("nathelper", "ping_nated_only", 0) +modparam("nathelper", "ping_nated_only", 1) modparam("nathelper", "natping_processes", REGISTRAR_NAT_PING_WORKERS) modparam("nathelper", "sipping_bflag", FLB_NATSIPPING) #!endif @@ -57,6 +58,7 @@ loadmodule "registrar.so" modparam("registrar", "received_avp", "$avp(AVP_RECV_PARAM)") modparam("registrar", "min_expires", REGISTRAR_MIN_EXPIRES) modparam("registrar", "max_expires", REGISTRAR_MAX_EXPIRES) +modparam("registrar", "default_expires", REGISTRAR_DEFAULT_EXPIRES) modparam("registrar", "xavp_cfg", "regcfg") modparam("registrar", "gruu_enabled", 1) modparam("registrar", "outbound_mode", 1) @@ -64,41 +66,52 @@ modparam("registrar", "regid_mode", 1) modparam("registrar", "path_mode", 1) modparam("registrar", "use_path", 1) modparam("registrar", "received_param", "") -##modparam("registrar", "xavp_rcd", "ulrcd") +modparam("registrar", "xavp_rcd", "ulrcd") modparam("registrar", "contact_max_size", REGISTRAR_CONTACT_MAX_SIZE) +kazoo.registrar_error_min_expires = REGISTRAR_ERROR_MIN_EXPIRES descr "send error when UAS sends expires < min-expires" + ##### handle expired registrations realtime params ##### kazoo.registrar_handle_expired_tcp = REGISTRAR_HANDLE_EXPIRED_TCP descr "handles expired tcp registrations" kazoo.registrar_handle_expired_udp = REGISTRAR_HANDLE_EXPIRED_UDP descr "handles expired udp registrations" kazoo.registrar_handle_expired_tls = REGISTRAR_HANDLE_EXPIRED_TLS descr "handles expired tls registrations" kazoo.registrar_handle_expired_ws = REGISTRAR_HANDLE_EXPIRED_WS descr "handles expired ws registrations" +kazoo.registrar_query_timeout_ms = REGISTRAR_QUERY_TIMEOUT_MS descr "timeout waiting for reply from registrar" + +kazoo.registrar_failover = 0 descr "force failover if 1" + ####### Registrar Logic ######## route[HANDLE_REGISTER] { - if (is_method("REGISTER")) { - - #!ifdef NAT_TRAVERSAL_ROLE - if (nat_uac_test("3")) { - xlog("L_INFO", "$ci|log|correcting NATed contact in registration\n"); - force_rport(); - } - fix_nated_register(); - - ## KAZOO-1846: Cisco SPA8000 freaks out on options pings - if (!($ua =~ "Linksys/SPA8000" - || $ua =~ "OpenBTS" - || $ua =~ "SIPp" - || (af==INET6) - )) { - setbflag(FLB_NATB); - setbflag(FLB_NATSIPPING); - } - #!endif + if (!is_method("REGISTER")) { + return; + } - route(ATTEMPT_AUTHORIZATION); + resetbflag(FLB_NATB); + resetbflag(FLB_NATSIPPING); + #!ifdef NAT_TRAVERSAL_ROLE + if (nat_uac_test("3")) { + xlog("L_INFO", "$ci|log|correcting NATed contact in registration\n"); + force_rport(); + } + fix_nated_register(); + + ## KAZOO-1846: Cisco SPA8000 freaks out on options pings + if (!($ua =~ "Linksys/SPA8000" + || $ua =~ "SIPp" + || (af==INET6) + )) { + setbflag(FLB_NATB); + setbflag(FLB_NATSIPPING); } + #!else + $avp(AVP_RECV_PARAM) = $su; + #!endif + + route(ATTEMPT_AUTHORIZATION); + } route[AUTHORIZATION_CHECK] @@ -120,7 +133,6 @@ route[AUTHORIZATION_CHECK] xlog("L_INFO", "$ci|log|not authorized $fu from $si:$sp\n"); send_reply("503", "Not Registered"); exit; -# route(ATTEMPT_AUTHORIZATION); } } @@ -130,106 +142,101 @@ route[ATTEMPT_AUTHORIZATION] route(PUSHER_ATTEMPT_REGISTRATION); #!endif - $var(nonce) = $(uuid(g){s.rm,-}); - #!ifdef OPENBTS_AUTH_ROLE - if($ua =~ "OpenBTS" && $sht(auth_cache=>$Au::nonce) != $null ) { - $var(nonce) = $sht(auth_cache=>$Au::nonce); - } - #!endif - $xavp(regcfg=>match_received) = $su; - if($sht(auth_cache=>$Au) != $null && registered("location", "$rz:$Au", 2, 1) == 1 && $(xavp(ulattrs=>custom_channel_vars){s.len}) > 1) { + if($sht(auth_cache=>$Au) != $null + && registered("location", "$rz:$Au", 2, 1) == 1 + && $(xavp(ulattrs=>custom_channel_vars){s.len}) > 1) + && @cfg_get.kazoo.registrar_failover == 0 { $var(password) = $sht(auth_cache=>$Au); route(SAVE_LOCATION); + exit; } - if( is_present_hf("Authorization")) { - route(KAZOO_AUTHORIZATION); + if($td =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}" || + $fd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") { + xlog("L_INFO", "$ci|log|register|invalid domain\n"); + drop; } - #!ifdef OPENBTS_AUTH_ROLE - if($ua =~ "OpenBTS") { - openbts_auth_challenge("$fd", "$var(nonce)"); - } else { - #!endif - auth_challenge("$fd", "0"); - #!ifdef OPENBTS_AUTH_ROLE + if (!t_newtran()) { + xlog("L_ERROR", "$ci|log|failed to create transaction to query for authentication credentials for $Au $si:$sp\n"); + drop; } - #!endif - xlog("L_INFO", "$ci|end|issued auth challenge to new registration for $fu $si:$sp\n"); - exit; -} + if($xavp(amqpc=>default::MY_AMQP_ZONE) == 0) { + xlog("L_INFO", "$ci|log|register|no amqp connection available for default worker in zone MY_AMQP_ZONE\n"); + t_drop(); + } -route[KAZOO_AUTHORIZATION] -{ - $var(nonce) = $adn; - $var(amqp_payload_request) = $_s({"Event-Category" : "directory" , "Event-Name" : "authn_req", "Method" : "REGISTER", "Auth-Nonce" : "$adn", "Auth-Realm" : "$fd", "Auth-User" : "$fU", "From" : "$fu", "To" : "$tu", "Orig-IP" : "$si", "Orig-Port" : "$sp", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci" }); - $var(amqp_routing_key) = "authn.req." + $(fd{kz.encode}); - $avp(kz_timeout) = 2500; - if (!t_newtran()) { - sl_reply_error(); - exit(); + if(@cfg_get.kazoo.registrar_failover == 1) { + xlog("L_INFO", "$ci|log|register|forcing failover\n"); + t_drop(); + } + + if(@cfg_get.kazoo.registrar_error_min_expires == 1) { + route(REGISTRAR_BOUNDS); } - if(kazoo_async_query("callmgr", $var(amqp_routing_key), $var(amqp_payload_request), "KAZOO_AUTHORIZATION_OK", "KAZOO_AUTHORIZATION_ERROR") != 1) { - xlog("L_INFO", "$ci|log|failed to send Kazoo query for authentication credentials for $Au $si:$sp\n"); - append_to_reply("Retry-After: 60\r\n"); - send_reply("503", "Retry Later"); + + $var(auth) = pv_auth_check("$fd", "$uuid(g)", "0", "0"); + if($var(auth) != -2) { + xlog("L_INFO", "$ci|end|challenging $Au $si:$sp\n"); + $var(auth) = auth_challenge("$fd", "21"); + if($var(auth) != 1) { + xlog("L_ERROR", "$ci|register|error creating or sending challenge to registration attempt for $fu from $si:$sp\n"); + t_drop(); + } exit; } + + $var(amqp_payload_request) = $_s({"Event-Category" : "directory" , "Event-Name" : "authn_req", "Method" : "REGISTER", "Auth-Nonce" : "$adn", "Auth-Realm" : "$fd", "Auth-User" : "$fU", "From" : "$fu", "To" : "$tu", "Orig-IP" : "$si", "Orig-Port" : "$sp", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci" }); + $var(amqp_routing_key) = "authn.req." + $(fd{kz.encode}); + $avp(kz_timeout) = $sel(cfg_get.kazoo.registrar_query_timeout_ms); + + sl_send_reply("100", "checking your credentials"); + + if(kazoo_async_query("callmgr", $var(amqp_routing_key), $var(amqp_payload_request), "KZ_AUTHORIZATION_OK", "KZ_AUTHORIZATION_ERROR") != 1) { + xlog("L_INFO", "$ci|log|failed to send registrar query for authentication credentials for $Au $si:$sp\n"); + t_drop(); + } } -route[KAZOO_AUTHORIZATION_OK] +failure_route[KZ_AUTHORIZATION_ERROR] { + xlog("L_INFO", "$ci|log|failed $T_reply_code to query Kazoo for authentication credentials for $Au $si:$sp\n"); + t_drop(); +} + +onreply_route[KZ_AUTHORIZATION_OK] +{ + xlog("L_INFO", "$ci|log|received $(kzR{kz.json,Event-Category}) $(kzR{kz.json,Event-Name}) reply from $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version})\n"); $var(password) = $(kzR{kz.json,Auth-Password}); $var(nonce) = $adn; - #!ifdef OPENBTS_AUTH_ROLE - if( $(kzR{kz.json,Auth-Nonce}) != "" && $var(nonce) != $(kzR{kz.json,Auth-Nonce})) { - xlog("L_INFO", "$ci|log|nonce replace $var(nonce) with $(kzR{kz.json,Auth-Nonce})\n"); - $var(nonce) = $(kzR{kz.json,Auth-Nonce}); - $sht(auth_cache=>$Au::nonce) = $var(nonce); - } - #!endif - if( $(kzR{kz.json,Event-Name}) == "authn_err" ) { - auth_challenge("$fd", "0"); - xlog("L_INFO", "$ci|end|issued auth challenge to registration attempt for $Au $si:$sp\n"); + if( $(kzR{kz.json,Event-Name}) == "authn_err" ) { + #!ifdef ANTIFLOOD_ROLE + route(ANITFLOOD_FAILED_AUTH); + #!endif + auth_challenge("$fd", "21"); + xlog("L_INFO", "$ci|end|challenging $Au $si:$sp via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version}) response\n"); exit; } else { - $xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars}); - xlog("L_INFO", "$ci|log|authenticating $Au via Kazoo query response\n"); + xlog("L_INFO", "$ci|log|authenticating $Au via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version}) response\n"); route(CHECK_AUTHORIZATION); } } -route[KAZOO_AUTHORIZATION_ERROR] -{ - xlog("L_INFO", "$ci|log|failed to query Kazoo for authentication credentials for $Au $si:$sp\n"); - append_to_reply("Retry-After: 60\r\n"); - send_reply("503", "Retry Later"); - exit; -} + route[CHECK_AUTHORIZATION] { - if($ua =~ "OpenBTS") { - xlog("L_INFO", "$ci|end|OPENBTS attempt for $Au $si:$sp\n"); - } else { - if($var(password) == $null || $var(password) == "") { - auth_challenge("$fd", "0"); - xlog("L_INFO", "$ci|end|issued auth challenge to registration attempt for $Au $si:$sp\n"); - exit; - } - - if (!pv_auth_check("$fd", "$var(password)", "0", "0")) { - #!ifdef ANTIFLOOD_ROLE - route(ANITFLOOD_FAILED_AUTH); - #!endif + if (!pv_auth_check("$fd", "$var(password)", "0", "0")) { + #!ifdef ANTIFLOOD_ROLE + route(ANITFLOOD_FAILED_AUTH); + #!endif - auth_challenge("$fd", "0"); - xlog("L_WARNING", "$ci|end|issued auth challenge to failed registration attempt for $Au from IP $si:$sp\n"); - exit; - } + xlog("L_WARNING", "$ci|end|issuing auth challenge to failed registration attempt for $Au from IP $si:$sp\n"); + auth_challenge("$fd", "21"); + exit; } #!ifdef ANTIFLOOD_ROLE @@ -239,26 +246,23 @@ route[CHECK_AUTHORIZATION] # user authenticated - remove auth header consume_credentials(); + $xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars}); + $xavp(ulattrs[0]=>token) = $_s($(kzR{kz.json,Custom-Channel-Vars.Authorizing-ID})@$(kzR{kz.json,Custom-Channel-Vars.Account-ID})); + route(SAVE_LOCATION); } route[SAVE_LOCATION] { - if ($sht(auth_cache=>$Au) == $null) { + + if ($sht(auth_cache=>$Au) == $null && $var(password) != $null) { xlog("L_INFO", "$ci|log|caching sip credentials for $Au\n"); }; $sht(auth_cache=>$Au) = $var(password); - #!ifdef OPENBTS_AUTH_ROLE - if($ua =~ "OpenBTS") { - $sht(auth_cache=>$Au::nonce) = $var(nonce); - } - #!endif $var(save_result) = save("location", "0x04"); - if($var(save_result) == -1) { - auth_challenge("$fd", "0"); - xlog("L_INFO", "$ci|end|issued auth challenge after failed attempt to save contact for $Au $si:$sp\n"); + if($var(save_result) < 0) { exit; } else { if($var(save_result) == 1) { @@ -268,34 +272,17 @@ route[SAVE_LOCATION] } } - if((int)@contact.expires) { - $var(expires) = @contact.expires; + if($var(save_result) == 3) { + $var(expires) = 0; } else { - if(is_present_hf("Expires")) { - $var(expires) = $hdr(Expires); - } else { - $var(expires) = REGISTRAR_MIN_EXPIRES; - } + $var(expires) = $xavp(ulrcd=>expires); } -## this is what we should be using -## but ulrcd seems to have a weird leak -## if($var(save_result) == 3) { -## $var(expires) = 0; -## } else { -## $var(expires) = $xavp(ulrcd=>expires); -## } - if($var(expires) == 0) { xlog("L_INFO", "$ci|end|unregister request from $Au $si:$sp\n"); $var(Status) = "Unregistered"; } else { $var(Status) = "Registered"; - if($var(expires) < REGISTRAR_MIN_EXPIRES) { - $var(expires) = REGISTRAR_MIN_EXPIRES; - } else if($var(expires) > REGISTRAR_MAX_EXPIRES) { - $var(expires) = REGISTRAR_MAX_EXPIRES; - } } $var(ip) = $Ri; @@ -334,18 +321,17 @@ route[SAVE_LOCATION] default: $var(port) = $Rp; } - + $var(AdvIP) = $RAi; if(af==INET6) { $var(AdvIP) = "[" + $RAi + "]"; } - - $var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "$var(Status)", "Event-Timestamp" : $TS, "Expires" : $(var(expires){s.int}), "First-Registration" : $var(new_reg), "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "Realm" : "$fd", "Username" : "$fU", "From-User" : "$fU", "From-Host" : "$fd", "To-User" : "$tU", "To-Host" : "$td", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), "Proxy-Path" : "sip:$var(ip):$var(port)", "Proxy-Protocol" : "$proto", "Proxy-IP" : "$var(AdvIP)", "Proxy-Port" : "$RAp", "Source-IP": "$si", "Source-Port": "$sp" }); + $var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "$var(Status)", "Event-Timestamp" : $TS, "Expires" : $(var(expires){s.int}), "First-Registration" : $var(new_reg), "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "Realm" : "$fd", "Username" : "$fU", "From-User" : "$fU", "From-Host" : "$fd", "To-User" : "$tU", "To-Host" : "$td", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), "Proxy-Path" : "sip:MY_IP_ADDRESS:$var(port)", "Proxy-Protocol" : "$proto", "Proxy-IP" : "$var(AdvIP)", "Proxy-Port" : "$RAp", "Source-IP": "$si", "Source-Port": "$sp" }); $var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $(fU{kz.encode}); kazoo_publish("registrar", $var(amqp_routing_key), $var(amqp_payload_request)); - xlog("L_INFO", "$ci|end|successful $(var(Status){s.tolower}) with contact : $ct\n"); + xlog("L_INFO", "$ci|end|successful $(var(Status){s.tolower}) with contact : $ct : $var(expires)\n"); #!ifdef PUSHER_ROLE route(PUSHER_ON_REGISTRATION); @@ -379,8 +365,59 @@ event_route[kazoo:consumer-event-directory-reg-flush] #!endif } +route[REGISTRAR_BINDINGS] +{ + #!import_file "registrar-custom-bindings.cfg" + + #!ifndef REGISTRAR_CUSTOM_BINDINGS + + $var(payload) = $_s({"exchange": "registrar", "type": "topic", "queue": "registrar-flush-MY_HOSTNAME", "routing": "registration.flush.*", "federate": 1 }); + kazoo_subscribe("$var(payload)"); + + #!endif + + #!ifdef REGISTRAR_SYNC_ROLE + route(REGISTRAR_SYNC_BINDINGS); + #!endif + +} + +route[REGISTRAR_BOUNDS] +{ + if((int)@contact.expires) { + $var(expires) = @contact.expires; + } else if(is_present_hf("Expires")) { + $var(expires) = $hdr(Expires); + } else if($(sel(contact){tobody.params}{param.value,expires}) != "") { + $var(expires) = $(sel(contact){tobody.params}{param.value,expires}{s.int}); + } else { + send_reply("400", "Missing Expires"); + exit; + } + + if($var(expires) != 0) { + if($var(expires) < REGISTRAR_MIN_EXPIRES) { + $var(expires) = REGISTRAR_MIN_EXPIRES; + append_to_reply("Min-Expires: $var(expires)\r\n"); + send_reply("423", "Interval Too Brief"); + exit; + } + } + +} + +## +## this needs handling logic in ecallmgr +## because we will fire the unregister from this server +## after device registers in another proxy +## causing ecallmgr to delete the registration +## from the other server +## event_route[usrloc:contact-expired] { + ## return until we handle this in ecallmr + return; + $var(transport) = $(ulc(exp=>received){uri.transport}); $var(proto) = $(ulc(exp=>socket){re.subst,/^([^:]*):(.*)/\1/}); if($var(proto) == "tls" && $var(transport) == "ws") { @@ -425,27 +462,9 @@ event_route[usrloc:contact-expired] $var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "Unregistered", "Event-Timestamp" : $TS, "Expires" : 0, "First-Registration" : false, "Contact" : "$(ulc(exp=>addr){s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ulc(exp=>callid)", "Realm" : "$var(domain)", "Username" : "$var(username)", "From-User" : "$var(username)", "From-Host" : "$var(domain)", "To-User" : "$var(username)", "To-Host" : "$var(domain)", "Proxy-Path" : "$ulc(exp=>socket)", "User-Agent" : "$(ulc(exp=>user_agent){s.escape.common}{s.replace,\','}{s.replace,$$,})"}); $var(amqp_routing_key) = "registration.success." + $(var(domain){kz.encode}) + "." + $(var(username){kz.encode}); kazoo_publish("registrar", $var(amqp_routing_key), $var(amqp_payload_request)); - xlog("L_INFO", "$ulc(exp=>callid)|expired|notified kazoo about removed registration with contact : $ulc(exp=>addr)\n"); - } else { - xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration with contact : $ulc(exp=>addr)\n"); + xlog("L_INFO", "$ulc(exp=>callid)|expired|notified registration removal with contact : $ulc(exp=>addr)\n"); } -} - -route[REGISTRAR_BINDINGS] -{ - #!import_file "registrar-custom-bindings.cfg" - - #!ifndef REGISTRAR_CUSTOM_BINDINGS - - $var(payload) = "{ 'exchange' : 'registrar' , 'type' : 'topic', 'queue' : 'registrar-flush-MY_HOSTNAME', 'routing' : 'registration.flush.*', 'federate' : 1 }"; - kazoo_subscribe("$var(payload)"); - - #!endif - - #!ifdef REGISTRAR_SYNC_ROLE - route(REGISTRAR_SYNC_BINDINGS); - #!endif - + xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration with contact : $ulc(exp=>addr)\n"); } #!ifdef REGISTRAR_SYNC_ROLE diff --git a/kamailio/websockets-role.cfg b/kamailio/websockets-role.cfg index 0f6ee8a..3d28127 100644 --- a/kamailio/websockets-role.cfg +++ b/kamailio/websockets-role.cfg @@ -1,10 +1,8 @@ tcp_accept_no_cl=yes listen=TCP_WS -listen=UDP_WS_SIP #!ifdef TLS_ROLE listen=TLS_WSS -listen=UDP_WSS_SIP #!endif ######## NAT Traversal module - signaling functions ######## diff --git a/system/sbin/kazoo-kamailio b/system/sbin/kazoo-kamailio index 9fa4e00..f8d7539 100755 --- a/system/sbin/kazoo-kamailio +++ b/system/sbin/kazoo-kamailio @@ -1,20 +1,26 @@ #!/bin/bash if [ -f /etc/default/kamailio ]; then - . /etc/default/kamailio + . /etc/default/kamailio fi if [ -f /etc/sysconfig/kamailio ]; then - . /etc/sysconfig/kamailio + . /etc/sysconfig/kamailio fi RETVAL=1 USER=${KAMAILIO_USER:-kamailio} -GROUP=${KAMAILIO_GROUP:-kamailio} +GROUP=${KAMAILIO_GROUP:-daemon} BIN_FILE=${KAMAILIO_BIN:-/usr/sbin/kamailio} PID_FILE=${KAMAILIO_PID:-/var/run/kamailio/kazoo-kamailio.pid} CFG_FILE=${KAMAILIO_CONFIG:-/etc/kazoo/kamailio/kamailio.cfg} +CFG_DIR=$(dirname ${CFG_FILE}) +export DB_SCRIPT_DIR=${KAMAILIO_DB_SCRIPT_DIR:-${CFG_DIR}/db_scripts} +export DB_LOCATION=${KAMAILIO_DB_LOCATION:-/etc/kazoo/kamailio/db} +export KAMAILIO_SHARE_DIR=${KAMAILIO_SHARE_DIR:-/usr/share/kamailio} export HOME=${KAMAILIO_HOME:-/var/run/kamailio} +RAM_DISK_SIZE=${RAM_DISK_SIZE:-256m} +RAM_DISK_ENABLED=${RAM_DISK_ENABLED:-false} SHM_MEMORY=$((`echo $SHM_MEMORY | sed -e 's/[^0-9]//g'`)) PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`)) @@ -22,159 +28,164 @@ PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`)) [ $PKG_MEMORY -le 0 ] && PKG_MEMORY=8 if test "$DUMP_CORE" = "yes" ; then - ulimit -c unlimited + ulimit -c unlimited fi prepare() { - mkdir -p /var/run/kamailio - chown -R ${USER} /var/run/kamailio - if [ -e ${PID_FILE} ]; then - rm -rf ${PID_FILE} - fi - if ram_disk_enabled; then - if ! mount_point_exists; then - if [ -f /etc/kazoo/kamailio/kazoo.db ]; then - mv /etc/kazoo/kamailio/db /etc/kazoo/kamailio/db-backup - fi - mount -t tmpfs -o size=256m tmpfs /etc/kazoo/kamailio/db - if [ -f /etc/kazoo/kamailio/db-backup/kazoo.db ]; then - cp -a /etc/kazoo/kamailio/db-backup/* /etc/kazoo/kamailio/db/ - fi - fi - fi - if [ ! -f /etc/kazoo/kamailio/db/kazoo.db ]; then + mkdir -p /var/run/kamailio + chown -R ${USER} /var/run/kamailio + if [ -e ${PID_FILE} ]; then + rm -rf ${PID_FILE} + fi + if ram_disk_enabled; then + if ! mount_point_exists; then + if [ -d ${DB_LOCATION} ]; then + mv ${DB_LOCATION} ${DB_LOCATION}/../db-backup-temp + mkdir -p ${DB_LOCATION} + fi + mount -t tmpfs -o size=${RAM_DISK_SIZE} tmpfs ${DB_LOCATION} + if [ -f ${DB_LOCATION}/../db-backup-temp/kazoo.db ]; then + cp -f ${DB_LOCATION}/../db-backup-temp/* ${DB_LOCATION}/ + fi + if [ -d ${DB_LOCATION}/../db-backup-temp ]; then + rm -rf ${DB_LOCATION}/../db-backup-temp + fi + fi + fi + if [ ! -f ${DB_LOCATION}/kazoo.db ]; then init_database - fi - chown -R ${USER} /etc/kazoo/kamailio/db - RETVAL=$? + else + check_database + fi + chown -R ${USER} ${DB_LOCATION} + RETVAL=$? } ram_disk_enabled() { - grep -e "enable_ram_disk = true" /etc/kazoo/kamailio/local.cfg &> /dev/null - return $? + + grep -e "enable_ram_disk = true" ${CFG_DIR}/local.cfg &> /dev/null + config_enabled=$? + if [[ $RAM_DISK_ENABLED -eq "true" ]] || [[ $config_enabled -eq 0 ]]; then + return 0 + else + return 1 + fi } mount_point_exists() { - mount | grep /etc/kazoo/kamailio/db &> /dev/null - return $? + mount | grep $(readlink -f ${DB_LOCATION}) &> /dev/null + return $? } init_database() { - /etc/kazoo/kamailio/db_scripts/create-kazoodb-sql.sh + ${DB_SCRIPT_DIR}/create-kazoodb-sql.sh } +check_database() { + ${DB_SCRIPT_DIR}/check-kazoodb-sql.sh +} start() { - cd ${HOME} - - check_config - check_fork - - if [ "$(whoami)" == "${USER}" ]; then - set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} ${EXTRA_OPTIONS} "$@" - exec "$@" - else - set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} -u ${USER} -g ${GROUP} ${EXTRA_OPTIONS} "$@" - runuser -s /bin/bash ${USER} -c "$*" - fi - RETVAL=$? - - if [ ${RETVAL} -ne 0 ]; then - echo "Failed to start Kamailio!" - RETVAL=1 - fi + cd ${HOME} + + check_config + check_fork + + if [ "$(whoami)" == "${USER}" ]; then + set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} ${EXTRA_OPTIONS} "$@" + exec "$@" + else + set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} -u ${USER} -g ${GROUP} ${EXTRA_OPTIONS} "$@" + runuser -s /bin/bash ${USER} -c "$*" + fi + RETVAL=$? + + if [ ${RETVAL} -ne 0 ]; then + echo "Failed to start Kamailio!" + RETVAL=1 + fi } stop() { - killall ${BIN_FILE} - RETVAL=$? - if mount_point_exists; then - if [ -f /etc/kazoo/kamailio/kazoo.db ]; then - mv /etc/kazoo/kamailio/db /etc/kazoo/kamailio/db-backup - fi - fi + killall ${BIN_FILE} + RETVAL=$? + if mount_point_exists; then + mkdir -p ${DB_LOCATION}/../db-backup + cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup/ + fi } restart() { - stop - start + stop + start } reset-restart() { - cd /etc/kazoo/kamailio/dbtext/ - stop - - head -n1 active_watchers > active_watchers.tmp - mv -f active_watchers.tmp active_watchers - - head -n1 watchers > watchers.tmp - mv -f watchers.tmp watchers - - head -n1 presentity > presentity.tmp - mv -f presentity.tmp presentity + cd /etc/kazoo/kamailio/dbtext/ + stop - chown kamailio:daemon * + chown kamailio:daemon * - start + start } status() { - kamcmd dispatcher.list - RETVAL=$? + kamcmd dispatcher.list + RETVAL=$? } # Do not start kamailio if fork=no is set in the config file # otherwise the boot process will just stop check_fork () { - if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFG_FILE; then - echo "WARNING: fork=no specified in config file" - exit 1 - fi + if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFG_FILE; then + echo "WARNING: fork=no specified in config file" + exit 1 + fi } check_config () { - local ERRORS=$($BIN_FILE -c -f ${CFG_FILE} 2>&1 > /dev/null) - RETVAL=$? - - if [ ${RETVAL} -ne 0 ]; then - echo "ERROR: Invalid configuration file ${CFG_FILE}!" - echo -e "\n${ERRORS}\n" - else - echo "No errors found in ${CFG_FILE}" - fi + local ERRORS=$($BIN_FILE -c -f ${CFG_FILE} 2>&1 > /dev/null) + RETVAL=$? + + if [ ${RETVAL} -eq 0 ]; then + echo "ERROR: Invalid configuration file ${CFG_FILE}!" + echo -e "\n${ERRORS}\n" + else + echo "No errors found in ${CFG_FILE}" + fi } case "$1" in - prepare) - prepare - ;; - background) - shift - start $@ - ;; - start) - shift - start -DD $@ - ;; - stop) - stop - ;; - restart) - restart - ;; - reset-restart) - reset-restart - ;; - status) - status - ;; - check) - check_config - ;; - *) - echo $"Usage: $0 {prepare|start|background|stop|restart|reset-restart|status|check|pid}" + prepare) + prepare + ;; + background) + shift + start $@ + ;; + start) + shift + start -DD $@ + ;; + stop) + stop + ;; + restart) + restart + ;; + reset-restart) + reset-restart + ;; + status) + status + ;; + check) + check_config + ;; + *) + echo $"Usage: $0 {prepare|start|background|stop|restart|reset-restart|status|check|pid}" esac exit ${RETVAL}