| @ -0,0 +1,105 @@ | |||
| route[AUTH] | |||
| { | |||
| if (!is_method("INVITE|MESSAGE|REFER")) { | |||
| return; | |||
| } | |||
| #!ifdef DISPATCHER_ROLE | |||
| if (!isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| route(SETUP_AUTH_HEADERS); | |||
| } | |||
| #!endif | |||
| } | |||
| route[AUTH_HEADERS] | |||
| { | |||
| remove_hf_re("^X-"); | |||
| xavp_params_implode("hf", "$var(outx)"); | |||
| $var(out) = $(var(outx){re.subst,/^(.*);$$/\1/}); | |||
| $var(c) = $(var(out){param.count}); | |||
| xlog("L_DEBUG", "$ci|auth|headers $var(c) => $var(out) => $var(outx)\n"); | |||
| while($var(c) > 0) { | |||
| $var(idx) = $var(c) - 1; | |||
| xlog("L_DEBUG", "$ci|auth|adding $(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\n"); | |||
| append_hf("$(var(out){param.name,$var(idx)}): $(var(out){param.valueat,$var(idx)}{s.unescape.param})\r\n"); | |||
| $var(c) = $var(c) - 1; | |||
| } | |||
| } | |||
| route[SETUP_AUTH_HEADERS] | |||
| { | |||
| $xavp(hf=>X-AUTH-IP) = $si; | |||
| $xavp(hf[0]=>X-AUTH-PORT) = $sp; | |||
| #!ifdef REGISTRAR_ROLE | |||
| #!ifdef WITH_AUTH_TOKEN | |||
| route(AUTH_TOKEN); | |||
| #!else | |||
| route(AUTH_CCVS); | |||
| #!endif | |||
| #!endif | |||
| } | |||
| #!ifdef REGISTRAR_ROLE | |||
| route[AUTH_TOKEN] | |||
| { | |||
| $xavp(regcfg=>match_received) = $su; | |||
| if (registered("location","$fu", 2, 1) == 1) { | |||
| if($(xavp(ulattrs=>token){s.len}) > 0) { | |||
| $xavp(hf[0]=>X-AUTH-Token) = $xavp(ulattrs=>token); | |||
| } else { | |||
| if($(xavp(ulattrs=>Authorizing-ID){s.len}) > 0 && $(xavp(ulattrs=>Account-ID){s.len})) { | |||
| $xavp(hf[0]=>X-AUTH-Token) = $_s($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID})@$(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID})); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| route[AUTH_CCVS] | |||
| { | |||
| $xavp(regcfg=>match_received) = $su; | |||
| if (registered("location","$fu", 2, 1) != 1) return; | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Account-ID) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-Type}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Authorizing-Type) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-Type}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID}{s.len}) > 0 && $(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-Type}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-AUTH-Token) = $_s($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID})@$(xavp(ulattrs=>custom_channel_vars){kz.json,Account-ID})); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Authorizing-ID) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Authorizing-ID}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Username}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Username) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Username}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Realm}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Realm) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Realm}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Realm}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Account-Realm) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Realm}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Name}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Account-Name) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Account-Name}{s.escape.param}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Presence-ID}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Presence-ID) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Presence-ID}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Owner-ID}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Owner-ID) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Owner-ID}); | |||
| if($(xavp(ulattrs=>custom_channel_vars){kz.json,Hotdesk-Current-ID}{s.len}) > 0) | |||
| $xavp(hf[0]=>X-ecallmgr_Hotdesk-Current-ID) = $(xavp(ulattrs=>custom_channel_vars){kz.json,Hotdesk-Current-ID}); | |||
| } | |||
| #!endif | |||
| @ -0,0 +1,23 @@ | |||
| ## to be enhanced | |||
| route[AUTHORIZATION_CHECK] | |||
| { | |||
| if (!is_method("MESSAGE|NOTIFY|SUBSCRIBE|PUBLISH")) | |||
| return; | |||
| if(has_totag()) | |||
| return; | |||
| if (isflagset(FLAG_INTERNALLY_SOURCED)) | |||
| return; | |||
| if (isflagset(FLAG_TRUSTED_SOURCE)) | |||
| return; | |||
| $xavp(regcfg=>match_received) = $su; | |||
| if(!(registered("location", "$fu", 2, 1) == 1 && $(xavp(ulattrs=>custom_channel_vars){s.len}) > 1)) { | |||
| xlog("L_INFO", "$ci|log|not authorized $fu from $si:$sp\n"); | |||
| send_reply("503", "Not Registered"); | |||
| exit; | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| ######## BLOCK BY IP[PORT] ######## | |||
| #!trydef KZ_BLOCK_ENABLE 1 | |||
| #!trydef KZ_BLOCK_LOG_LEVEL 1 | |||
| #!trydef KZ_BLOCK_LOG_BUFFER 0 | |||
| #!trydef KZ_BLOCK_DRY_RUN 0 | |||
| #!ifdef KZ_BLOCK_COLD_CACHE | |||
| #!substdef "!BLOCK_S_WARM_CACHE!!g" | |||
| #!else | |||
| #!substdef "!BLOCK_S_WARM_CACHE!dbtable=block_cache;dbmode=1;!g" | |||
| #!endif | |||
| modparam("htable", "htable", "block=>size=8;BLOCK_S_WARM_CACHE") | |||
| modparam("statistics","variable", "block:blocked_requests") | |||
| kazoo.block_enable = KZ_BLOCK_ENABLE descr "enable block processing" | |||
| kazoo.block_log_level = KZ_BLOCK_LOG_LEVEL descr "block log level" | |||
| kazoo.block_log_buffer = KZ_BLOCK_LOG_BUFFER descr "log the received buffer" | |||
| kazoo.block_dry_run = KZ_BLOCK_DRY_RUN descr "log but keep processing" | |||
| ## global param to enable route | |||
| received_route_mode=1 | |||
| event_route[core:msg-received] | |||
| { | |||
| if($sel(cfg_get.kazoo.block_enable) == 1) { | |||
| if($sht(block=>$rcv(srcip)) || $sht(block=>$rcv(srcip)::$rcv(srcport))) { | |||
| if($sel(cfg_get.kazoo.block_log_buffer) == 1) { | |||
| xlog("$(sel(cfg_get.kazoo.block_log_level){s.int})", "|block|request from [$rcv(srcip):$rcv(srcport)] to [$rcv(rcvip):$rcv(rcvport)] was blocked => [$rcv(buf)]\n"); | |||
| } else { | |||
| xlog("$(sel(cfg_get.kazoo.block_log_level){s.int})", "|block|request from [$rcv(srcip):$rcv(srcport)] to [$rcv(rcvip):$rcv(rcvport)] was blocked\n"); | |||
| } | |||
| if($sel(cfg_get.kazoo.block_dry_run) == 0) { | |||
| drop; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,14 @@ | |||
| #### db_kazoo module ### | |||
| #!trydef KZ_DB_HOOK_TRACE 1 | |||
| #!trydef KZ_DB_TRACE 0 | |||
| #!trydef KZ_DB_TRACE_LOG_LEVEL 3 | |||
| #!trydef KZ_DB_TRACE_FILTER 110 | |||
| loadmodule "db_kazoo.so" | |||
| modparam("db_kazoo", "trace_hook", KZ_DB_HOOK_TRACE) | |||
| modparam("db_kazoo", "trace_enable", KZ_DB_TRACE) | |||
| modparam("db_kazoo", "trace_log_level", KZ_DB_TRACE_LOG_LEVEL) | |||
| modparam("db_kazoo", "trace_filter", KZ_DB_TRACE_FILTER) | |||
| include_file "db_queries_kazoo.cfg" | |||
| @ -0,0 +1,4 @@ | |||
| #### db_mysql module ### | |||
| loadmodule "db_mysql.so" | |||
| include_file "db_queries_mysql.cfg" | |||
| @ -0,0 +1,4 @@ | |||
| #### db_postgres module ### | |||
| loadmodule "db_postgres.so" | |||
| include_file "db_queries_postgres.cfg" | |||
| @ -1,15 +1,27 @@ | |||
| ####### Database queries ######## | |||
| #!substdef "!KZQ_CHECK_MEDIA_SERVER_INSERT!insert into dispatcher (setid, destination) select \$var(SetId), \"\$var(MediaUrl)\" where not exists(select * from dispatcher where destination = \"\$var(MediaUrl)\")!g" | |||
| #!substdef "!KZQ_COUNT_ALL_SUBSCRIBERS!select a.event, count(distinct watcher_username || \"@\" || watcher_domain) count_unique, count(*) count from event_list a, active_watchers b where b.event = a.event group by a.event!g" | |||
| #!substdef "!KZQ_CHECK_MEDIA_SERVER_INSERT!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)\")!g" | |||
| #!substdef "!KZQ_COUNT_ALL_SUBSCRIBERS!select a.event, count(distinct watcher_uri) count_unique, count(*) count from event_list a left outer join active_watchers b on a.event = b.event group by a.event!g" | |||
| #!substdef "!KZQ_COUNT_PRESENTITIES!select event, (select count(*) from presentity b where username = \"\$(var(payload){kz.json,From}{uri.user})\" and domain = \"\$(var(payload){kz.json,From}{uri.domain})\" and b.event = a.event) count from event_list a!g" | |||
| #!substdef "!KZQ_COUNT_SUBSCRIBERS!select event, (select count(*) from active_watchers b where presentity_uri = \"\$var(presentity)\" and b.event = a.event) count from event_list a!g" | |||
| #!substdef "!KZQ_COUNT_SUBSCRIBERS!select event, (select count(*) from active_watchers b where presentity_uri = \"\$var(presentity)\" and b.event = a.event) count from event_list a union all select \"self\", count(distinct callid) from presentities where presentity_uri = \"\$var(presentity)\" and callid <> \"\$var(callid)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g" | |||
| #!substdef "!KZQ_EVENT_PRESENCE_RESET_DELETE!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\" and username = \"\$(kzE{kz.json,Username})\"!g" | |||
| #!substdef "!KZQ_HANDLE_NEW_SUBSCRIBE_DELETE1!delete from active_watchers where callid = \"\$ci\"!g" | |||
| #!substdef "!KZQ_HANDLE_NEW_SUBSCRIBE_DELETE2!delete from active_watchers where watcher_username=\"\$fU\" and presentity_uri=\"\$var(presentity_uri)\" and to_user=\"\$tU\" and watcher_domain=\"\$fd\" and event=\"\$hdr(Event)\"!g" | |||
| #!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_HANDLE_NEW_SUBSCRIBE_DELETE2!delete from active_watchers where presentity_uri=\"\$var(presentity_uri)\" and event=\"\$hdr(Event)\" and watcher_username=\"\$fU\" and to_user=\"\$tU\" and watcher_domain=\"\$fd\"!g" | |||
| #!substdef "!KZQ_PRESENCE_SEARCH_SUMMARY!select * from active_watchers where to_domain = \"\$var(Domain)\"!g" | |||
| #!substdef "!KZQ_PRESENCE_SEARCH_DETAIL!select a.*, b.time, b.result, b.sent_msg, b.received_msg from active_watchers a left outer join active_watchers_log b on a.presentity_uri = b.presentity_uri and a.event = b.event and a.callid = b.callid where a.presentity_uri = \"\$var(presentity_uri)\" !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_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" | |||
| # # #!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_RESET_PUBLISHER_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where sender = \"\$var(MediaUrl)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g" | |||
| #!substdef "!KZQ_PRESENCE_RESET!delete from presentity where sender = \"\$var(MediaUrl)\"!g" | |||
| # # #!substdef "!KZQ_RESET_ACCOUNT_UPDATE!update active_watchers set expires = \$TS where watcher_domain=\"\$(kzE{kz.json,Realm})\"!g" | |||
| #!substdef "!KZQ_RESET_ACCOUNT_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where domain=\"\$(kzE{kz.json,Realm})\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g" | |||
| #!substdef "!KZQ_RESET_ACCOUNT_RESET!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\"!g" | |||
| #!substdef "!KZQ_RESET_PUBLISHER_ZONE_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join wdispatcher c on a.sender = c.destination inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where zone = \"\$var(Zone)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g" | |||
| #!substdef "!KZQ_PRESENCE_ZONE_RESET!delete from presentity where id in(select a.id from presentities a join wdispatcher c on a.sender = c.destination where zone = \"\$var(Zone)\")!g" | |||
| @ -0,0 +1,46 @@ | |||
| #!/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 -ne $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 --primarykey --table version ${DB_CURRENT_DB} ${TEMP_DB} | KazooDB -db ${DB_CURRENT_DB} | |||
| KazooDB-diff --primarykey --table event_list ${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=${filename#*_} | |||
| 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 | |||
| for INIT in `ls ${DB_SCRIPT_DIR}/db_init_*.sql`; do | |||
| KazooDB -db ${DB_CURRENT_DB} < $INIT | |||
| done | |||
| @ -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 | |||
| @ -0,0 +1,34 @@ | |||
| do_db_extra_check() { | |||
| # location | |||
| if [[ $RESET_NON_UDP_ENABLED == "true" ]]; then | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from location where socket not like 'udp:%';" | |||
| fi | |||
| ##KazooDB -db ${DB_CURRENT_DB} "delete from location where expires > 0 and datetime(expires) < datetime('now', '-30 seconds');" | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from location_attrs where not exists(select id from location where ruid = location_attrs.ruid);" | |||
| ## presence | |||
| if [[ $RESET_NON_UDP_ENABLED == "true" ]]; then | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from active_watchers where socket_info not like 'udp:%';" | |||
| fi | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from active_watchers where expires > 0 and datetime(expires, 'unixepoch') < datetime('now', '-10 seconds');" | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from presentity where expires > 0 AND datetime(expires, 'unixepoch') < datetime('now', '-10 seconds');" | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from presentity where id in(select id from presentities where state in('terminated','available'));" | |||
| KazooDB -db ${DB_CURRENT_DB} "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));" | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from presentity where id in(select id from presentities a where not exists(select * from active_watchers where presentity_uri = a.presentity_uri));" | |||
| ## notify watchers of pending calls | |||
| ## 'create temp table as' because it will be dropped as soon as we ended the session | |||
| KazooDB -db ${DB_CURRENT_DB} "drop table if exists tmp_probe;" | |||
| KazooDB -db ${DB_CURRENT_DB} "create table tmp_probe as select distinct a.event, a.presentity_uri, cast(2 as integer) action from presentities a inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where state in('early', 'confirmed', 'onthephone', 'busy');" | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from presentity where id in(select id from presentities where state in('early', 'confirmed', 'onthephone', 'busy'));" | |||
| ## keepalive | |||
| if [[ $RESET_NON_UDP_ENABLED == "true" ]]; then | |||
| KazooDB -db ${DB_CURRENT_DB} "delete from keepalive where sockinfo NOT LIKE 'udp%';" | |||
| fi | |||
| KazooDB -db ${DB_CURRENT_DB} "update keepalive set selected = 0, time_sent = datetime('now') where selected < 3;" | |||
| } | |||
| @ -0,0 +1,14 @@ | |||
| CREATE TRIGGER if not exists active_watchers_watcher_uri_insert | |||
| AFTER INSERT ON active_watchers | |||
| FOR EACH ROW | |||
| BEGIN | |||
| UPDATE active_watchers SET watcher_uri = "sip:" || NEW.watcher_username || "@" || NEW.watcher_domain where id = NEW.id; | |||
| END; | |||
| CREATE TRIGGER if not exists active_watchers_watcher_uri_update | |||
| AFTER UPDATE ON active_watchers | |||
| FOR EACH ROW | |||
| WHEN OLD.watcher_username <> NEW.watcher_username OR OLD.watcher_domain <> NEW.watcher_domain | |||
| BEGIN | |||
| UPDATE active_watchers SET watcher_uri = "sip:" || NEW.watcher_username || "@" || NEW.watcher_domain where id = NEW.id; | |||
| END; | |||
| @ -0,0 +1,56 @@ | |||
| #!/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() { | |||
| echo `ls -A1 ${KAMAILIO_SHARE_DIR}/${DB_ENGINE}/*.sql | grep -v standard | tr '\n' '\0' | xargs -0 -n 1 basename | sort` | |||
| } | |||
| sql_all_header() { | |||
| cat << EOF | |||
| CREATE TABLE version ( | |||
| table_name VARCHAR(32) NOT NULL, | |||
| table_version INTEGER DEFAULT 0 NOT NULL, | |||
| PRIMARY KEY(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" | |||
| } | |||
| @ -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,"<state>")+7, instr(body,"</state>") - instr(body,"<state>") - 7) | |||
| when event = "presence" | |||
| then case when instr(body,"<dm:note>") == 0 | |||
| then replace(substr(body, instr(body,"<note>")+6, instr(body,"</note>") - instr(body,"<note>") - 6), " ", "") | |||
| else replace(substr(body, instr(body,"<dm:note>")+9, instr(body,"</dm:note>") - instr(body,"<dm:note>") - 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 | |||
| @ -0,0 +1,6 @@ | |||
| CREATE VIEW w_keepalive_contact as | |||
| select id, slot, selected, failed, case when instr(contact,";") > 0 | |||
| then substr(contact, 1, instr(contact,";")-1) | |||
| else contact | |||
| end as contact | |||
| from keepalive | |||
| @ -0,0 +1,6 @@ | |||
| CREATE VIEW w_location_contact as | |||
| select id, ruid, case when instr(contact,";") > 0 | |||
| then substr(contact, 1, instr(contact,";")-1) | |||
| else contact | |||
| end as contact | |||
| from location | |||
| @ -0,0 +1,6 @@ | |||
| CREATE VIEW w_watchers_contact as | |||
| select id, case when instr(contact,";") > 0 | |||
| then substr(contact, 1, instr(contact,";")-1) | |||
| else contact | |||
| end as contact | |||
| from active_watchers | |||
| @ -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 | |||
| @ -0,0 +1,88 @@ | |||
| ## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## | |||
| ####### amqp defs ######## | |||
| #!ifndef AMQP_DEFAULTS_INCLUDED | |||
| #!define AMQP_DEFAULTS_INCLUDED | |||
| #!trydef MY_AMQP_MAX_CHANNELS 25 | |||
| #!trydef MY_AMQP_CONSUMER_PROCESSES 4 | |||
| #!trydef MY_AMQP_CONSUMER_WORKERS 16 | |||
| #!trydef MY_AMQP_HEARTBEATS 5 | |||
| #!ifndef MY_AMQP_ZONE | |||
| #!substdef "!MY_AMQP_ZONE!local!g" | |||
| #!endif | |||
| #!ifdef PRESENCE_ROLE | |||
| #!trydef MY_AMQP_PUA_MODE 1 | |||
| #!else | |||
| #!trydef MY_AMQP_PUA_MODE 0 | |||
| #!endif | |||
| #!ifndef MY_AMQP_URL | |||
| #!ifdef AMQP_URL1 | |||
| #!substdef "!MY_AMQP_URL!$def(AMQP_URL1)!g" | |||
| #!else | |||
| #!substdef "!MY_AMQP_URL!amqp://guest:guest@127.0.0.1:5672!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_SECONDARY_URL | |||
| #!ifdef AMQP_URL2 | |||
| #!substdef "!MY_AMQP_SECONDARY_URL!$def(AMQP_URL2)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_TERTIARY_URL | |||
| #!ifdef AMQP_URL3 | |||
| #!substdef "!MY_AMQP_TERTIARY_URL!$def(AMQP_URL3)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_QUATERNARY_URL | |||
| #!ifdef AMQP_URL4 | |||
| #!substdef "!MY_AMQP_QUATERNARY_URL!$def(AMQP_URL4)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_QUINARY_URL | |||
| #!ifdef AMQP_URL5 | |||
| #!substdef "!MY_AMQP_QUINARY_URL!$def(AMQP_URL5)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_SENARY_URL | |||
| #!ifdef AMQP_URL6 | |||
| #!substdef "!MY_AMQP_SENARY_URL!$def(AMQP_URL6)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_SEPTENARY_URL | |||
| #!ifdef AMQP_URL7 | |||
| #!substdef "!MY_AMQP_SEPTENARY_URL!$def(AMQP_URL7)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_OCTONARY_URL | |||
| #!ifdef AMQP_URL8 | |||
| #!substdef "!MY_AMQP_OCTONARY_URL!$def(AMQP_URL8)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_NONARY_URL | |||
| #!ifdef AMQP_URL9 | |||
| #!substdef "!MY_AMQP_NONARY_URL!$def(AMQP_URL9)!g" | |||
| #!endif | |||
| #!endif | |||
| #!ifndef MY_AMQP_DENARY_URL | |||
| #!ifdef AMQP_URL10 | |||
| #!substdef "!MY_AMQP_DENARY_URL!$def(AMQP_URL10)!g" | |||
| #!endif | |||
| #!endif | |||
| #!endif | |||
| # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,343 @@ | |||
| ######## KEEPALIVE PINGING ######## | |||
| #!trydef KEEPALIVE_ENABLED 1 | |||
| #!trydef KEEPALIVE_NAT_ONLY 0 | |||
| #!trydef KEEPALIVE_UDP_ONLY 0 | |||
| #!trydef KEEPALIVE_TIMERS 4 | |||
| #!trydef KEEPALIVE_INTERVAL 60 | |||
| #!trydef KEEPALIVE_TIMEOUT 5000 | |||
| #!trydef KEEPALIVE_FAILED_THRESHOLD 2 | |||
| #!trydef KEEPALIVE_EXPIRE_SUBSCRIPTIONS 1 | |||
| #!trydef KEEPALIVE_EXPIRE_REGISTRATIONS 1 | |||
| #!trydef KEEPALIVE_FAILED_ACTION 1 | |||
| #!trydef KEEPALIVE_FAILED_LOG_LEVEL 0 | |||
| #!trydef KEEPALIVE_EXPIRED_SUBSCRIPTION_ACTION 1 | |||
| #!trydef KEEPALIVE_EXPIRED_REGISTRATION_ACTION 1 | |||
| #!trydef KEEPALIVE_ON_SUBSCRIPTION_ACTION 1 | |||
| #!trydef KEEPALIVE_ON_REGISTRATION_ACTION 1 | |||
| #!substdef "!KEEPALIVE_S_FROM_URI!sip:keepalive@MY_HOSTNAME!g" | |||
| #!substdef "!KEEPALIVE_S_TIMERS!$def(KEEPALIVE_TIMERS)!g" | |||
| kazoo.keepalive_udp_only = KEEPALIVE_UDP_ONLY descr "should we send keepalive for udp only" | |||
| kazoo.keepalive_nat_only = KEEPALIVE_NAT_ONLY descr "should we send keepalive for nat phones only" | |||
| kazoo.keepalive_timeout = KEEPALIVE_TIMEOUT descr "timeout in ms for keepalive transaction" | |||
| kazoo.keepalive_failed_threshold = KEEPALIVE_FAILED_THRESHOLD descr "how many times can a device fail to respond to OPTIONS" | |||
| kazoo.keepalive_expire_subscriptions = KEEPALIVE_EXPIRE_SUBSCRIPTIONS descr "expires subscriptions that do not respond to OPTIONS" | |||
| kazoo.keepalive_expire_registrations = KEEPALIVE_EXPIRE_REGISTRATIONS descr "expires registrations that do not respond to OPTIONS" | |||
| kazoo.keepalive_failed_log_level = KEEPALIVE_FAILED_LOG_LEVEL descr "loglevel for keepalive failed reply" | |||
| kazoo.keepalive_failed_action = KEEPALIVE_FAILED_ACTION descr "action for devices that exceed the threshold. 1 = disable, 2 = delete" | |||
| kazoo.keepalive_interval = KEEPALIVE_INTERVAL descr "interval in seconds between attempts to send OPTIONS to device" | |||
| kazoo.keepalive_expired_registration_action = KEEPALIVE_EXPIRED_REGISTRATION_ACTION descr "action when registrar expires a registration, 1 = delete , 2 = disable, 0 = none" | |||
| kazoo.keepalive_expired_subscription_action = KEEPALIVE_EXPIRED_SUBSCRIPTION_ACTION descr "action when presence expires a subscription, 1 = delete , 2 = disable, 0 = none" | |||
| kazoo.keepalive_on_registration_action = KEEPALIVE_ON_REGISTRATION_ACTION descr "action on registration, 1 = insert in keepalive , 0 = none" | |||
| kazoo.keepalive_on_subscription_action = KEEPALIVE_ON_SUBSCRIPTION_ACTION descr "action on subscription, 1 = insert in keepalive , 0 = none" | |||
| kazoo.keepalive_enable = KEEPALIVE_ENABLED descr "enable keepalive, 1 = on , 0 = off" | |||
| modparam("rtimer", "timer", "name=keepalive_timer;interval=1;mode=KEEPALIVE_S_TIMERS;") | |||
| modparam("rtimer", "exec", "timer=keepalive_timer;route=KEEPALIVE_TIMER") | |||
| modparam("rtimer", "timer", "name=keepalive_db_timer;interval=1;mode=1;") | |||
| modparam("rtimer", "exec", "timer=keepalive_db_timer;route=KEEPALIVE_DB_TIMER") | |||
| ##modparam("rtimer", "timer", "name=keepalive_cleanup;interval=5;mode=1;") | |||
| ##modparam("rtimer", "exec", "timer=keepalive_cleanup;route=KEEPALIVE_CLEANUP") | |||
| modparam("mqueue","mqueue", "name=keepalive_db_queue") | |||
| modparam("statistics","variable", "keepalive:success") | |||
| modparam("statistics","variable", "keepalive:failure") | |||
| modparam("statistics","variable", "keepalive:db:success") | |||
| modparam("statistics","variable", "keepalive:db:failure") | |||
| modparam("statistics","variable", "keepalive:client_options") | |||
| modparam("statistics","variable", "keepalive:client_notify") | |||
| modparam("statistics","variable", "keepalive:disabled") | |||
| modparam("statistics","variable", "keepalive:removed") | |||
| modparam("statistics","variable", "keepalive:expired_registrations") | |||
| modparam("statistics","variable", "keepalive:expired_subscriptions") | |||
| modparam("statistics","variable", "keepalive:from_registration") | |||
| modparam("statistics","variable", "keepalive:from_subscription") | |||
| modparam("statistics","variable", "keepalive:removed_from_registration") | |||
| modparam("statistics","variable", "keepalive:removed_from_subscription") | |||
| modparam("statistics","variable", "keepalive:disabled_from_expired_registration") | |||
| modparam("statistics","variable", "keepalive:removed_from_expired_registration") | |||
| modparam("statistics","variable", "keepalive:disabled_from_expired_subscription") | |||
| modparam("statistics","variable", "keepalive:removed_from_expired_subscription") | |||
| modparam("htable", "htable", "keepalive=>size=32;") | |||
| route[KEEPALIVE_DB_TIMER] | |||
| { | |||
| $var(runloop) = 1; | |||
| while(mq_fetch("keepalive_db_queue") == 1 && $var(runloop) < MAX_WHILE_LOOPS) { | |||
| $var(ci) = $mqk(keepalive_db_queue); | |||
| xlog("L_DEBUG", "Query : $var(ci) => $mqv(keepalive_db_queue)\n"); | |||
| $var(sqlres) = sql_query("cb", "$mqv(keepalive_db_queue)"); | |||
| xlog("L_DEBUG", "Query result : $var(sqlres)\n"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$var(ci)|log|error running query : $mqv(keepalive_db_queue)\n"); | |||
| } else { | |||
| $var(stat_update) = $_s(+$sqlrows(cb)); | |||
| update_stat("$var(ci)", "$var(stat_update)"); | |||
| $var(nrows) = $sqlrows(cb); | |||
| xlog("L_DEBUG", "$var(ci)|log|end UPDATED $var(nrows) => $var(stat_update)\n"); | |||
| if($var(nrows) == 0) { | |||
| xlog("L_DEBUG", "$var(ci)|log|error no rows affected when running query\n"); | |||
| } | |||
| } | |||
| $var(runloop) = $var(runloop) + 1; | |||
| } | |||
| } | |||
| route[KEEPALIVE_CLEANUP] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| $var(Query) = $_s(UPDATE keepalive SET SELECTED = 9 WHERE slot = $var(slot) AND selected = 0 and failed > $sel(cfg_get.kazoo.keepalive_failed_threshold)); | |||
| # $var(Query) = $_s(UPDATE keepalive SET SELECTED = 9 where selected < 3 and failed > $sel(cfg_get.kazoo.keepalive_failed_threshold)); | |||
| sql_query("cb", "$var(Query)"); | |||
| if($sqlrows(cb) > 0) { | |||
| if($sel(cfg_get.kazoo.keepalive_expire_registrations) == 1) { | |||
| if($def(REGISTRAR_DB_MODE) == 3) { | |||
| $var(Query) = $_s(update location set expires = last_modified where id in(select b.id from w_keepalive_contact a inner join w_location_contact b on a.contact = b.contact where selected = 9)); | |||
| sql_query("cb", "$var(Query)"); | |||
| $var(stat_update) = $_s(+$sqlrows(cb)); | |||
| update_stat("keepalive:expired_registrations", "$var(stat_update)"); | |||
| } else { | |||
| $var(Query) = $_s(update location set expires = last_modified where id in(select b.id from w_keepalive_contact a inner join w_location_contact b on a.contact = b.contact where selected = 9)); | |||
| sql_query("cb", "$var(Query)"); | |||
| $var(stat_update) = $_s(+$sqlrows(cb)); | |||
| update_stat("keepalive:expired_registrations", "$var(stat_update)"); | |||
| } | |||
| } | |||
| if($sel(cfg_get.kazoo.keepalive_expire_subscriptions) == 1) { | |||
| $var(Query) = $_s(DELETE FROM active_watchers where id in(select b.id from w_keepalive_contact a inner join w_watchers_contact b on a.contact = b.contact where selected = 9)); | |||
| sql_query("cb", "$var(Query)"); | |||
| $var(stat_update) = $_s(+$sqlrows(cb)); | |||
| update_stat("keepalive:expired_subscriptions", "$var(stat_update)"); | |||
| } | |||
| if($sel(cfg_get.kazoo.keepalive_failed_action) == 2) { | |||
| ## disable | |||
| $var(Query) = $_s(UPDATE keepalive SET SELECTED = 10 where selected = 9); | |||
| $var(stat) = "keepalive:disabled"; | |||
| } else if($sel(cfg_get.kazoo.keepalive_failed_action) == 1) { | |||
| ## delete - will be recreated on registration/subscription with same contact | |||
| $var(Query) = $_s(DELETE FROM keepalive where selected = 9); | |||
| $var(stat) = "keepalive:removed"; | |||
| } | |||
| sql_query("cb", "$var(Query)"); | |||
| $var(stat_update) = $_s(+$sqlrows(cb)); | |||
| update_stat("$var(stat)", "$var(stat_update)"); | |||
| } | |||
| } | |||
| route[KEEPALIVE_TIMER] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| $var(base_slot) = $rtimer_worker * $sel(cfg_get.kazoo.keepalive_interval); | |||
| $var(slot) = $var(base_slot) + $var(tick); | |||
| $var(Query) = $_s(UPDATE keepalive SET selected = 1 WHERE slot = $var(slot) AND selected = 0 AND time_sent < datetime('now', '-$sel(cfg_get.kazoo.keepalive_interval) seconds')); | |||
| ## xlog("L_NOTICE", "SQLTIMER ($var(base_slot) + $var(tick))> $var(Query)\n"); | |||
| $var(sqlres) = sql_query("cb", "$var(Query)"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$rtimer_worker|$var(tick)|log|error running query : $var(Query)\n"); | |||
| } else { | |||
| $var(nrows) = $sqlrows(cb); | |||
| xlog("L_DEBUG", "$rtimer_worker|$var(tick)|log|selected $var(nrows) endpoints to ping\n"); | |||
| } | |||
| route(KEEPALIVE_CLEANUP); | |||
| $var(Query) = $_s(SELECT id, contact, sockinfo from keepalive WHERE slot = $var(slot) AND selected = 1); | |||
| xlog("L_DEBUG", "$rtimer_worker|$var(tick)|timer|SQL => $var(Query)\n"); | |||
| $var(result) =sql_xquery("cb", "$var(Query)", "ra"); | |||
| if($var(result) == 1) { | |||
| while($xavp(ra) != $null) { | |||
| $var(loop) = 0; | |||
| while($xavp(ra) != $null && $var(loop) < MAX_WHILE_LOOPS) { | |||
| route(KEEPALIVE_SEND_PING); | |||
| pv_unset("$xavp(ra)"); | |||
| $var(loop) = $var(loop) + 1; | |||
| } | |||
| } | |||
| } | |||
| $var(Query) = $_s(UPDATE keepalive SET selected = 2 WHERE slot = $var(slot) AND selected = 1); | |||
| $var(sqlres) = sql_query("cb", "$var(Query)"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$rtimer_worker|$var(tick)|log|error running query : $var(Query)\n"); | |||
| } | |||
| $var(tick) = $var(tick) + 1; | |||
| if($var(tick) > $sel(cfg_get.kazoo.keepalive_interval)) { | |||
| $var(tick) = 0; | |||
| } | |||
| } | |||
| route[KEEPALIVE_SEND_PING] | |||
| { | |||
| $var(CallId) = $uuid(g); | |||
| xlog("L_DEBUG", "$var(CallId)|$rtimer_worker|timer|SENDING PING FROM $xavp(ra=>local_contact) TO => $xavp(ra=>contact)\n"); | |||
| $uac_req(method)="OPTIONS"; | |||
| $uac_req(hdrs) = "X-TM-Local: KEEPALIVE_PING\r\nX-TM-SockInfo: " + $xavp(ra=>sockinfo) + "\r\n"; | |||
| $uac_req(turi) = $xavp(ra=>contact); | |||
| $uac_req(ruri) = $xavp(ra=>contact); | |||
| $uac_req(furi) = $_s(KEEPALIVE_S_FROM_URI;nat_id=$xavp(ra=>id)); | |||
| $uac_req(ouri) = "sip:127.0.0.1:5090;transport=tcp"; | |||
| $uac_req(callid) = $var(CallId); | |||
| uac_req_send(); | |||
| } | |||
| onreply_route[KEEPALIVE_REPLY] | |||
| { | |||
| xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE REPLY $(tu{nameaddr.uri})\n"); | |||
| $var(Query) = $_s(UPDATE keepalive SET selected = 0, failed = 0, time_sent = datetime('now') WHERE id = $(fu{uri.param,nat_id}) AND SELECTED = 2); | |||
| xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE UPDATE SQL => '$var(Query)'\n"); | |||
| mq_add("keepalive_db_queue", "keepalive:db:success", "$var(Query)"); | |||
| update_stat("keepalive:success", "+1"); | |||
| resetflag(FLAG_SIP_TRACE); | |||
| } | |||
| failure_route[KEEPALIVE_FAULT] | |||
| { | |||
| xlog("$(sel(cfg_get.kazoo.keepalive_failed_log_level){s.int})", "$ci|keepalive|received error $T_reply_code $T_reply_reason from $(tu{nameaddr.uri})\n"); | |||
| $var(Query) = $_s(UPDATE keepalive SET selected = 0, failed = failed + 1, time_sent = datetime('now') WHERE id = $(fu{uri.param,nat_id}) AND SELECTED = 2); | |||
| xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE REMOVE SQL => '$var(Query)'\n"); | |||
| mq_add("keepalive_db_queue", "keepalive:db:failure", "$var(Query)"); | |||
| update_stat("keepalive:failure", "+1"); | |||
| resetflag(FLAG_SIP_TRACE); | |||
| } | |||
| route[KEEPALIVE_PING] | |||
| { | |||
| $fs = $hdr(X-TM-SockInfo); | |||
| remove_hf_re("^X-TM-SockInfo"); | |||
| force_rport(); | |||
| handle_ruri_alias(); | |||
| record_route(); | |||
| xlog("L_DEBUG", "$ci|local|sending $proto keepalive using $fs to $ru => $du => $tu\n"); | |||
| t_on_reply("KEEPALIVE_REPLY"); | |||
| t_on_failure("KEEPALIVE_FAULT"); | |||
| t_set_fr(0, $sel(cfg_get.kazoo.keepalive_timeout)); | |||
| t_relay(); | |||
| } | |||
| route[KEEPALIVE_ON_REGISTRATION] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| if($sel(cfg_get.kazoo.keepalive_on_registration_action) == 0) { | |||
| return; | |||
| } | |||
| if($proto == "ws" || $proto == "wss") { | |||
| return; | |||
| } | |||
| if($sht(keepalive=>$si~$sp~$prid) != $null) { | |||
| return; | |||
| } | |||
| if (isbflagset(FLB_NATB)) { | |||
| if(!isbflagset(FLB_NATSIPPING)) { | |||
| return; | |||
| } | |||
| } else { | |||
| if($sel(cfg_get.kazoo.keepalive_nat_only) == 1) { | |||
| return; | |||
| } | |||
| } | |||
| $var(alias) = $(avp(AVP_RECV_PARAM){uri.host}) + "~" + $(avp(AVP_RECV_PARAM){uri.port}) + "~" + $prid; | |||
| $var(contact) = $(ct{nameaddr.uri}) + ";alias=" + $var(alias); | |||
| $var(local_contact) = "sip:" + $Ri + ":" + $Rp + ";transport=" + $proto; | |||
| xlog("L_DEBUG", "$ci|keepalive|KEEPALIVE ON REG $var(save_result) $proto $RAut $var(contact) $var(alias) $(ct{nameaddr.uri}) $ct $avp(AVP_RECV_PARAM) $tu $xavp(ulrcd=>ruid) , $xavp(ulrcd=>contact) , $xavp(ulrcd=>expires)\n"); | |||
| if($var(save_result) == 3) { | |||
| $var(sql) = $_s(DELETE FROM keepalive WHERE contact = "$var(contact)"); | |||
| $var(stat) = "keepalive:removed_from_registration"; | |||
| } else { | |||
| $var(max_slots) = $sel(cfg_get.kazoo.keepalive_interval) * KEEPALIVE_S_TIMERS; | |||
| $var(slot) = $(var(contact){s.corehash, $var(max_slots)}); | |||
| $var(sql) = $_s(INSERT OR IGNORE INTO keepalive (contact, received, sockinfo, slot) values("$var(contact)", "$var(alias)", "$(RAut{uri.tosocket})", $var(slot))); | |||
| $var(stat) = "keepalive:from_registration"; | |||
| } | |||
| mq_add("keepalive_db_queue", "$var(stat)", "$var(sql)"); | |||
| return; | |||
| } | |||
| route[KEEPALIVE_ON_SUBSCRIBE] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| if($sel(cfg_get.kazoo.keepalive_on_subscription_action) == 0) { | |||
| return; | |||
| } | |||
| if($sht(keepalive=>$si~$sp~$prid) != $null) { | |||
| return; | |||
| } | |||
| $var(max_slots) = $sel(cfg_get.kazoo.keepalive_interval) * KEEPALIVE_S_TIMERS; | |||
| $var(slot) = $(subs(contact){s.corehash, $var(max_slots)}); | |||
| $var(alias) = $(subs(contact){uri.param,alias}); | |||
| $var(sql) = $_s(INSERT OR IGNORE INTO keepalive (contact, received, sockinfo, slot) values("$subs(contact)", "$var(alias)", "$subs(sockinfo)", $var(slot))); | |||
| mq_add("keepalive_db_queue", "keepalive:from_subscription", "$var(sql)"); | |||
| } | |||
| route[KEEPALIVE_ON_EXPIRED_REGISTRATION] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| if($sel(cfg_get.kazoo.keepalive_expired_registration_action) == 2) { | |||
| ## disable | |||
| $var(Query) = $_s(UPDATE keepalive SET SELECTED = 10 where selected < 3 and contact like "$ulc(exp=>addr)%"); | |||
| mq_add("keepalive_db_queue", "keepalive:disabled_from_expired_registration", "$var(Query)"); | |||
| } else if($sel(cfg_get.kazoo.keepalive_expired_registration_action) == 1) { | |||
| ## delete - will be recreated on registration with same contact | |||
| $var(Query) = $_s(DELETE FROM keepalive where selected < 3 and contact like "$ulc(exp=>addr)%"); | |||
| mq_add("keepalive_db_queue", "keepalive:removed_from_expired_registration", "$var(Query)"); | |||
| } | |||
| } | |||
| route[KEEPALIVE_ON_OPTIONS] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| if($shtinc(keepalive=>$si~$sp~$prid) == 1) { | |||
| $var(Query) = $_s(UPDATE keepalive set selected = 3 where received = "$si~$sp~$prid" and selected <> 3 ); | |||
| mq_add("keepalive_db_queue", "keepalive:client_options", "$var(Query)"); | |||
| } | |||
| } | |||
| route[KEEPALIVE_ON_NOTIFY] | |||
| { | |||
| if($sel(cfg_get.kazoo.keepalive_enable) == 0) return; | |||
| if($shtinc(keepalive=>$si~$sp~$prid) == 1) { | |||
| $var(Query) = $_s(UPDATE keepalive set selected = 4 where received = "$si~$sp~$prid" and selected <> 4 ); | |||
| mq_add("keepalive_db_queue", "keepalive:client_notify", "$var(Query)"); | |||
| } | |||
| } | |||
| @ -1,45 +1,116 @@ | |||
| ######## 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") | |||
| modparam("nathelper", "sipping_from", "sip:registrar@MY_HOSTNAME") | |||
| #!ifdef WEBSOCKETS_ROLE | |||
| #!trydef KZ_NAT_DETECT 83 | |||
| #!else | |||
| #!trydef KZ_NAT_DETECT 19 | |||
| #!endif | |||
| #!trydef KZ_NAT_FIX_SDP_REQUEST 1 | |||
| #!trydef KZ_NAT_FIX_SDP_REPLY 1 | |||
| #!trydef KZ_NAT_SDP_TEST 8 | |||
| #!trydef KZ_NAT_SDP_FIX 10 | |||
| kazoo.nat_fix_sdp_request = KZ_NAT_FIX_SDP_REQUEST descr "performs request sdp replacement of private addresses" | |||
| kazoo.nat_fix_sdp_reply = KZ_NAT_FIX_SDP_REPLY descr "performs reply sdp replacement of private addresses" | |||
| ####### NAT Traversal Logic ######## | |||
| route[NAT_TEST_AND_CORRECT] | |||
| route[NAT_SDP] | |||
| { | |||
| if( has_body("application/sdp")) { | |||
| if( nat_uac_test(KZ_NAT_SDP_TEST)) { | |||
| xlog("L_DEBUG", "$ci|log|applying sdp nat fix\n"); | |||
| $var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX); | |||
| xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix is $var(ret)\n"); | |||
| } else if( is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) { | |||
| xlog("L_DEBUG", "$ci|log|applying sdp nat fix for held channel\n"); | |||
| $var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX); | |||
| xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix for held channel is $var(ret)\n"); | |||
| } | |||
| } | |||
| } | |||
| route[NAT_DETECT] | |||
| { | |||
| if($sel(cfg_get.kazoo.nat_fix_sdp_request) == 1) { | |||
| route(NAT_SDP); | |||
| } | |||
| if ($Rp == "5080") { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| xlog("L_DEBUG", "$ci|log|skipping nat correction on PORT 5080\n"); | |||
| } else { | |||
| if (is_present_hf("Record-Route")) { | |||
| $var(i) = 0; | |||
| $var(rr_count) = $rr_count; | |||
| while($var(i) < $var(rr_count)) { | |||
| $var(rr_base) = $(hdr(Record-Route)[$var(i)]); | |||
| $var(rr_idx) = 0; | |||
| $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); | |||
| while($var(rr) != $null && $var(rr) != "") { | |||
| $var(i) = $var(i) + 1; | |||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| xlog("L_DEBUG", "$ci|log|skipping nat correction on record-route $(var(rr){nameaddr.uri})\n"); | |||
| } | |||
| $var(rr_idx) = $var(rr_idx) + 1; | |||
| $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||
| xlog("L_DEBUG", "$ci|log|skipping nat detection\n"); | |||
| return; | |||
| } | |||
| force_rport(); | |||
| if(nat_uac_test(KZ_NAT_DETECT)) { | |||
| xlog("L_DEBUG", "$ci|log|detected nat request\n"); | |||
| setflag(FLT_NATS); | |||
| if (!is_method("REGISTER")) { | |||
| if(is_first_hop()) set_contact_alias(); | |||
| } | |||
| } | |||
| } | |||
| route[NAT_MANAGE] | |||
| { | |||
| if (is_present_hf("Record-Route")) { | |||
| $var(i) = 0; | |||
| $var(rr_count) = $rr_count; | |||
| while($var(i) < $var(rr_count)) { | |||
| $var(rr_base) = $(hdr(Record-Route)[$var(i)]); | |||
| $var(rr_idx) = 0; | |||
| $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); | |||
| while($var(rr) != $null && $var(rr) != "") { | |||
| $var(i) = $var(i) + 1; | |||
| if (!is_myself("$(var(rr){nameaddr.uri})")) { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| $var(rr_idx) = $var(rr_idx) + 1; | |||
| $var(rr) = $(var(rr_base){s.select,$var(rr_idx),,}); | |||
| } | |||
| } | |||
| } else if ($Rp == "5080") { | |||
| setflag(FLAG_SKIP_NAT_CORRECTION); | |||
| } | |||
| if (isflagset(FLAG_SKIP_NAT_CORRECTION)) { | |||
| return(); | |||
| } | |||
| if (nat_uac_test("NAT_UAC_TEST_LEVEL")) { | |||
| force_rport(); | |||
| fix_nated_contact(); | |||
| } | |||
| if (has_body("application/sdp") && nat_uac_test("8")) { | |||
| fix_nated_sdp("10"); | |||
| } | |||
| if( is_reply() && $sel(cfg_get.kazoo.nat_fix_sdp_reply) == 1) { | |||
| route(NAT_SDP); | |||
| } | |||
| if ( is_request() && isflagset(FLAG_INTERNALLY_SOURCED)) { | |||
| setbflag(FLB_NATB); | |||
| } | |||
| if ( is_request() && has_totag() ) { | |||
| setbflag(FLB_NATB); | |||
| } | |||
| if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) { | |||
| return; | |||
| } | |||
| if (is_reply()) { | |||
| if(isflagset(FLT_NATS) || isbflagset(FLB_NATB)) { | |||
| if(is_first_hop()) { | |||
| set_contact_alias(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab | |||
| @ -0,0 +1,213 @@ | |||
| #!trydef KZ_PRESENCE_REMOVE_WATCHER_ON_EXPIRED_REGISTRATION 0 | |||
| #!trydef KZ_PRESENCE_MAX_NOTIFY_ERROR 3 | |||
| #!trydef KZ_PRESENCE_NOTIFY_LOG_LEVEL 4 | |||
| kazoo.presence_notify = 1 descr "enable/disable sending notify callback to omnipresence" | |||
| kazoo.presence_notify_timeout = 5000 descr "timeout in ms waiting for notify reply" | |||
| kazoo.presence_notify_log_body = 0 descr "logs the body sent in the notification" | |||
| kazoo.presence_notify_log_resp_body = 0 descr "logs the body received from notification" | |||
| kazoo.presence_notify_log_to_table = 1 descr "logs notify/reply to active_watchers_log table" | |||
| 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 = 1 descr "forces the send socket to the contact" | |||
| kazoo.presence_remove_watcher_on_expired_registration = KZ_PRESENCE_REMOVE_WATCHER_ON_EXPIRED_REGISTRATION descr "removes watcher on expired registration" | |||
| kazoo.presence_max_notify_error = KZ_PRESENCE_MAX_NOTIFY_ERROR descr "number of consecutive fails allowed before removing the subscription" | |||
| kazoo.presence_notify_log_level = KZ_PRESENCE_NOTIFY_LOG_LEVEL descr "loglevel for informational log messages" | |||
| ######## Generic Hash Table container in shared memory ######## | |||
| modparam("htable", "htable", "notify=>size=16;autoexpire=3600;updateexpire=1;initval=0") | |||
| route[PRESENCE_LOCAL_REQ_NOTIFY] | |||
| { | |||
| if($rm != "NOTIFY") { | |||
| return; | |||
| } | |||
| t_set_fr($sel(cfg_get.kazoo.presence_notify_timeout), $sel(cfg_get.kazoo.presence_notify_timeout)); | |||
| 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($sel(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($sel(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_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($sel(cfg_get.kazoo.presence_notify_record_route) == 1) { | |||
| record_route(); | |||
| } | |||
| #!ifdef NAT_TRAVERSAL_ROLE | |||
| if(!isdsturiset()) { | |||
| handle_ruri_alias(); | |||
| } | |||
| #!endif | |||
| } | |||
| modparam("mqueue","mqueue", "name=presence_last_notity") | |||
| modparam("rtimer", "timer", "name=notifytimer;interval=1;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") | |||
| modparam("rtimer", "timer", "name=pres_publisher_cleanup;interval=5;mode=1;") | |||
| modparam("rtimer", "exec", "timer=pres_publisher_cleanup;route=PRESENCE_PUBLISHER_CLEANUP") | |||
| event_route[presence:notify-reply] | |||
| { | |||
| if($sel(cfg_get.kazoo.presence_notify) != 1) | |||
| return; | |||
| $xavp(pres=>delete_subscription) = 0; | |||
| if($notify_reply($rs) == 200) { | |||
| $sht(notify=>$ci) = $null; | |||
| $sht(notify=>$ci::count) = 0; | |||
| xlog("$(sel(cfg_get.kazoo.presence_notify_log_level){s.int})", "$ci|end|notified $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n"); | |||
| } else if($subs(reason) == "timeout") { | |||
| $xavp(pres=>delete_subscription) = 1; | |||
| xlog("L_DEBUG", "$ci|end|deleting subscription $subs(pres_uri) for $subs(watcher_username)@$subs(watcher_domain) due to timeout\n"); | |||
| } else if($notify_reply($rs) == 481 && $subs(reason) == "timeout") { | |||
| xlog("L_DEBUG","$ci|end|sent subscription $hdr(Subscription-State)\n"); | |||
| } else if($notify_reply($rs) == 408) { | |||
| if($rP != "UDP") { | |||
| $xavp(pres=>delete_subscription) = 1; | |||
| xlog("L_ERROR", "$ci|warning|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri) with reply $notify_reply($rs)\n"); | |||
| } else { | |||
| $var(shtinc) = $shtinc(notify=>$ci::count); | |||
| if($var(shtinc) > $sel(cfg_get.kazoo.presence_max_notify_error)) { | |||
| $xavp(pres=>delete_subscription) = 1; | |||
| xlog("L_WARNING", "$ci|error|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri) with reply $notify_reply($rs)\n"); | |||
| } else { | |||
| $var(level) = 6 - $var(shtinc); | |||
| xlog("$var(level)", "$ci|error|received $notify_reply($rs) ($var(shtinc)/$sel(cfg_get.kazoo.presence_max_notify_error)) when notifying $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri) with reply $notify_reply($rs)\n"); | |||
| } | |||
| } | |||
| } else { | |||
| $xavp(pres=>delete_subscription) = 1; | |||
| xlog("L_WARNING", "$ci|end|deleting subscription $subs(pres_uri) as $subs(watcher_username)@$subs(watcher_domain) replied with $notify_reply($rs)\n"); | |||
| } | |||
| if($sel(cfg_get.kazoo.presence_notify_log_body) == 1) | |||
| xlog("L_INFO", "$ci|log|sent|body $(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\n"); | |||
| if($sel(cfg_get.kazoo.presence_notify_log_resp_body) == 1) | |||
| xlog("L_INFO", "$ci|log|resp|body $(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})\n"); | |||
| if($sel(cfg_get.kazoo.presence_notify_log_to_amqp) == 1) { | |||
| route(PRESENCE_NOTIFY_AMQP); | |||
| } | |||
| if($sel(cfg_get.kazoo.presence_notify_log_to_table) == 1) { | |||
| 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)"); | |||
| } | |||
| } | |||
| } | |||
| route[PRESENCE_LOG_TIMER_ROUTE] | |||
| { | |||
| $var(runloop) = 1; | |||
| while(mq_fetch("presence_last_notity") == 1 && $var(runloop) < MAX_WHILE_LOOPS) { | |||
| $var(ci) = $mqk(presence_last_notity); | |||
| xlog("L_DEBUG", "Query : $mqv(presence_last_notity)\n"); | |||
| $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 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_DEBUG", "$var(ci)|log|error no rows affected when running query\n"); | |||
| } | |||
| } | |||
| $var(runloop) = $var(runloop) + 1; | |||
| } | |||
| } | |||
| route[PRESENCE_NOTIFY_AMQP] | |||
| { | |||
| $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "notify", "Event-Package" : "$subs(event)", "Timestamp" : $TS, "Call-ID" : "$subs(callid)", "From" : "$fu", "To" : "$subs(to_user)@$subs(to_domain)", "Sent" : "$(TS{s.ftime,%Y-%m-%d %H:%M:%S})", "Body" : "Hostname : MY_HOSTNAME\r\nTimestamp : $(TS{s.ftime,%Y-%m-%d %H:%M:%S})\r\n$(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\r\nResponse\r\n$(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})","Remote-CSeq" : $subs(remote_cseq), "Local-CSeq" : $subs(local_cseq), "Sequence" : $cs, "Version" : $subs(version), "Reply" : $notify_reply($rs) }); | |||
| $var(rk) = "notify." + $(subs(to_domain){kz.encode}) + "." + $(subs(to_user){kz.encode}); | |||
| 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');); | |||
| 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)"); | |||
| } | |||
| route[PRESENCE_PUBLISHER_CLEANUP] | |||
| { | |||
| xlog("L_DEBUG", "processing presence publisher cleanup\n"); | |||
| $var(sqlres) = sql_query("cb", "update tmp_probe set action = 1 where action = 0"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$var(ci)|log|error cleaning tmp_probe\n"); | |||
| return; | |||
| } else { | |||
| $var(nrows) = $sqlrows(cb); | |||
| if($var(nrows) > 0) { | |||
| if (sql_xquery("cb", "select * from tmp_probe where action = 1", "cleanup_pres") == 1) | |||
| { | |||
| while($xavp(cleanup_pres) != $null) { | |||
| xlog("L_DEBUG", "processing $xavp(cleanup_pres=>event) notifies for $xavp(cleanup_pres=>presentity_uri)\n"); | |||
| pres_refresh_watchers("$xavp(cleanup_pres=>presentity_uri)", "$xavp(cleanup_pres=>event)", 1); | |||
| pv_unset("$xavp(cleanup_pres)"); | |||
| } | |||
| } | |||
| $var(sqlres) = sql_query("cb", "delete from tmp_probe where action = 1"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$var(ci)|log|error cleaning tmp_probe\n"); | |||
| } else { | |||
| $var(nrows) = $sqlrows(cb); | |||
| if($var(nrows) > 0) { | |||
| xlog("L_DEBUG", "presence publisher cleanup processed $var(nrows) rows\n"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| route[PRESENCE_DEFERRED_INIT] | |||
| { | |||
| xlog("L_INFO", "processing presence deferred init\n"); | |||
| $var(sqlres) = sql_query("cb", "update tmp_probe set action = 0 where action = 2"); | |||
| if($var(sqlres) < 0) { | |||
| xlog("L_ERROR", "$var(ci)|log|error cleaning tmp_probe\n"); | |||
| return; | |||
| } else { | |||
| $var(nrows) = $sqlrows(cb); | |||
| if($var(nrows) > 0) { | |||
| xlog("L_NOTICE", "scheduled update for $var(nrows) watched presentities/event\n"); | |||
| } | |||
| } | |||
| } | |||
| route[PRESENCE_EXPIRED_REGISTRATION] | |||
| { | |||
| if($sel(cfg_get.kazoo.presence_remove_watcher_on_expired_registration) == 1) { | |||
| $var(watcher) = $_s(sip:$ulc(exp=>aor)); | |||
| $var(watcher_username) = $(var(watcher){uri.user}); | |||
| $var(watcher_domain) = $(var(watcher){uri.host}); | |||
| $var(Query) = $_s(DELETE FROM active_watchers WHERE watcher_username = "$var(watcher_username)" and watcher_domain = "$var(watcher_domain)";); | |||
| mq_add("presence_last_notity", "$uuid(g)", "$var(Query)"); | |||
| } | |||
| } | |||
| @ -1,117 +0,0 @@ | |||
| kazoo.presence_notify = 1 descr "enable/disable sending notify callback to omnipresence" | |||
| kazoo.presence_notify_timeout = 3000 descr "timeout in ms waiting for notify reply" | |||
| kazoo.presence_notify_log_body = 0 descr "logs the body sent in the notification" | |||
| kazoo.presence_notify_log_resp_body = 0 descr "logs the body received from notification" | |||
| kazoo.presence_notify_log_to_table = 1 descr "logs notify/reply to active_watchers_log table" | |||
| 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" | |||
| ######## Generic Hash Table container in shared memory ######## | |||
| modparam("htable", "htable", "notify=>size=16;autoexpire=3600;updateexpire=1;initval=0") | |||
| #!trydef PRESENCE_NOTIFY_INIT | |||
| #!trydef MAX_NOTIFY_ERROR 5 | |||
| route[PRESENCE_LOCAL_NOTIFY] | |||
| { | |||
| if($rm != "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"); | |||
| 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"); | |||
| } | |||
| if(@cfg_get.kazoo.presence_notify_record_route == 1) { | |||
| record_route(); | |||
| } | |||
| } | |||
| modparam("mqueue","mqueue", "name=presence_last_notity") | |||
| ####### RTIMER module ########## | |||
| #!ifndef RTIMER_LOADED | |||
| loadmodule "rtimer.so" | |||
| #!trydef RTIMER_LOADED | |||
| #!endif | |||
| modparam("rtimer", "timer", "name=notifytimer;interval=500000u;mode=2;") | |||
| modparam("rtimer", "exec", "timer=notifytimer;route=PRESENCE_LOG_TIMER_ROUTE") | |||
| event_route[presence:notify-reply] | |||
| { | |||
| if(@cfg_get.kazoo.presence_notify != 1) | |||
| return; | |||
| $xavp(pres=>delete_subscription) = 0; | |||
| 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"); | |||
| } 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 { | |||
| 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"); | |||
| } else { | |||
| $var(shtinc) = $shtinc(notify=>$ci::count); | |||
| 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"); | |||
| } | |||
| } | |||
| } | |||
| if(@cfg_get.kazoo.presence_notify_log_body == 1) | |||
| xlog("L_INFO", "$ci|log|sent|body $(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\n"); | |||
| if(@cfg_get.kazoo.presence_notify_log_resp_body == 1) | |||
| xlog("L_INFO", "$ci|log|resp|body $(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})\n"); | |||
| if(@cfg_get.kazoo.presence_notify_log_to_amqp == 1) { | |||
| route(PRESENCE_NOTIFY_AMQP); | |||
| } | |||
| 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)"); | |||
| } | |||
| } | |||
| route[PRESENCE_LOG_TIMER_ROUTE] | |||
| { | |||
| $var(runloop) = 1; | |||
| while(mq_fetch("presence_last_notity") == 1 && $var(runloop) < MAX_WHILE_LOOPS) { | |||
| $var(ci) = $mqk(presence_last_notity); | |||
| xlog("L_DEBUG", "Query : $mqv(presence_last_notity)\n"); | |||
| $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"); | |||
| } 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"); | |||
| } | |||
| } | |||
| $var(runloop) = $var(runloop) + 1; | |||
| } | |||
| } | |||
| route[PRESENCE_NOTIFY_AMQP] | |||
| { | |||
| $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "notify", "Event-Package" : "$subs(event)", "Timestamp" : $TS, "Call-ID" : "$subs(callid)", "From" : "$fu", "To" : "$subs(to_user)@$subs(to_domain)", "Sent" : "$(TS{s.ftime,%Y-%m-%d %H:%M:%S})", "Body" : "Hostname : MY_HOSTNAME\r\nTimestamp : $(TS{s.ftime,%Y-%m-%d %H:%M:%S})\r\n$(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\r\nResponse\r\n$(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})","Remote-CSeq" : $subs(remote_cseq), "Local-CSeq" : $subs(local_cseq), "Sequence" : $cs, "Version" : $subs(version), "Reply" : $notify_reply($rs) }); | |||
| $var(rk) = "notify." + $(subs(to_domain){kz.encode}) + "." + $(subs(to_user){kz.encode}); | |||
| kazoo_publish("omnipresence", "$var(rk)", $var(amqp_payload_request)); | |||
| xlog("L_INFO", "$ci|log|sent notify callback for event $subs(event) : $tu\n"); | |||
| } | |||
| @ -0,0 +1,67 @@ | |||
| #!trydef SANITY_CHECK_USE_PORT 1 | |||
| #!trydef SANITY_DROPS_REQUEST 1 | |||
| #!trydef SANITY_DEFAULT_CHECK 17895 | |||
| #!trydef SANITY_URI_CHECKS 7 | |||
| #!trydef SANITY_TRACE_REQUEST 1 | |||
| #!substdef "!SANITY_SUBST_CACHE_PERIOD!$def(SANITY_CACHE_PERIOD)!g" | |||
| ######## SIP message formatting sanity checks [requires sl] ######## | |||
| loadmodule "sanity.so" | |||
| modparam("sanity", "default_checks", SANITY_DEFAULT_CHECK) | |||
| modparam("sanity", "uri_checks", SANITY_URI_CHECKS) | |||
| modparam("sanity", "autodrop", 0) | |||
| modparam("sanity", "noreply", 1) | |||
| modparam("debugger", "mod_level", "sanity=-3") | |||
| kazoo.sanity_check_use_port = SANITY_CHECK_USE_PORT descr "should we keep track of ip and port for sanity failures" | |||
| kazoo.sanity_drops_request = SANITY_DROPS_REQUEST descr "should we drop the request or send error on sanity failure" | |||
| kazoo.sanity_trace_request = SANITY_TRACE_REQUEST descr "should we trace the request if sip trace role is enabled" | |||
| route[SANITY_CHECK] | |||
| { | |||
| ## CVE-2018-14767 | |||
| if($(hdr(To)[1]) != $null) { | |||
| xlog("second To header not null - dropping message"); | |||
| drop; | |||
| } | |||
| $var(sanity_key) = ""; | |||
| if($sel(cfg_get.kazoo.sanity_check_use_port) == 1) { | |||
| $var(sanity_key) = $_s("$si::$sp"); | |||
| } else { | |||
| $var(sanity_key) = $_s("$si"); | |||
| } | |||
| if (!sanity_check()) { | |||
| #!ifdef SIP_TRACE_ROLE | |||
| sip_trace(); | |||
| #!endif | |||
| if($sel(cfg_get.kazoo.sanity_drops_request) == 1) { | |||
| xlog("L_WARN", "$ci|end|dropping insane message from $si:$sp\n"); | |||
| drop; | |||
| } else { | |||
| xlog("L_WARN", "$ci|end|insane message from $si:$sp\n"); | |||
| send_reply("400", "Bad Request"); | |||
| exit; | |||
| } | |||
| } | |||
| if (!mf_process_maxfwd_header("10")) { | |||
| xlog("L_WARN", "$ci|end|too much hops, not enough barley from $si:$sp\n"); | |||
| send_reply("483", "Too Many Hops"); | |||
| exit; | |||
| } | |||
| if ($ua == "friendly-scanner" || | |||
| $ua == "sundayddr" || | |||
| $ua == "pplsip" || | |||
| $ua =~ "NiceGuy" || | |||
| $ua =~ "PortSIP" || | |||
| $ua =~ "sipcli" ) { | |||
| xlog("L_WARN", "$ci|end|dropping message with user-agent $ua from $si:$sp\n"); | |||
| drop; | |||
| } | |||
| } | |||