diff --git a/kamailio-proxy-proxy/accounting-role.cfg b/kamailio-proxy-proxy/accounting-role.cfg
new file mode 100644
index 0000000..13b866d
--- /dev/null
+++ b/kamailio-proxy-proxy/accounting-role.cfg
@@ -0,0 +1,21 @@
+####### Flags #######
+#!trydef FLAG_ACC 13
+#!trydef FLAG_ACCMISSED 14
+#!trydef FLAG_ACCFAILED 15
+
+######## Accounting module ########
+loadmodule "acc.so"
+
+######## Accounting params ########
+modparam("acc", "early_media", 0)
+modparam("acc", "report_ack", 0)
+modparam("acc", "report_cancels", 1)
+modparam("acc", "detect_direction", 0)
+modparam("acc", "log_flag", 7)
+modparam("acc", "log_level", 2)
+modparam("acc", "log_missed_flag", 8)
+modparam("acc", "failed_transaction_flag", 9)
+modparam("acc", "log_extra",
+ "src_user=$fU;src_domain=$fd;src_ip=$si;"
+ "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
+modparam("acc", "log_facility", "LOG_LOCAL6")
diff --git a/kamailio-proxy-proxy/acl-role.cfg b/kamailio-proxy-proxy/acl-role.cfg
new file mode 100644
index 0000000..f4fc1df
--- /dev/null
+++ b/kamailio-proxy-proxy/acl-role.cfg
@@ -0,0 +1,273 @@
+######## DoS prevention module ########
+# Default "order" is "deny,allow".
+# So if there is no data from DB request will be permitted by default.
+#
+modparam("htable", "htable", "acl=>initval=-1;autoexpire=7200")
+
+#!trydef ACL_MESSAGE_DENY "Rejected by ACL"
+#!trydef ACL_CODE_DENY "603"
+#!trydef ACL_ORDER_ALLOW_DENY "allow,deny"
+#!trydef ACL_IP_ADDR_ANY "0.0.0.0/0"
+
+#!trydef IP_REGEX "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}"
+
+## Route for ACL functionality
+route[ACL_CHECK] {
+
+ # If packet came from platform or from 4 class MERA, do not check it
+ if (isflagset(FLAG_INTERNALLY_SOURCED) || isflagset(FLAG_TRUSTED_SOURCE) ) {
+ xlog("L_DEBUG", "$ci|ACL|Trusted source IP($si) ignoring\n");
+ return;
+ }
+
+
+ if (isflagset(FLAG_IS_REPLY)) {
+ $var(sip-packet) = $rs;
+ } else {
+ $var(sip-packet) = $rm;
+ }
+
+ # FIX for BYE method with IP instead of REALM in From, take REALM from To header
+ if ($fd =~ IP_REGEX) {
+ xlog("L_WARNING","$ci|ACL-realm|Fix for $var(sip-packet) with IP in from URI: use to-domain\n");
+ $var(realm) = $td;
+ } else {
+ $var(realm) = $fd;
+ }
+
+ $var(acl-realm-request) = "false";
+ $var(acl-device-request) = "false";
+
+ $var(realm-decision) = $sht(acl=>$var(realm)/$si);
+
+ if ($var(realm-decision) == -1) { # we do not have cached decision
+ $var(acl-realm-request) = "true";
+ } else if ($var(realm-decision) == 1 ){ # We have cached decision, let's use it
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(realm)\n");
+ } else {
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(realm)\n");
+ exit;
+ }
+
+ if (not_empty("$fU")) {
+ if ($fd =~ IP_REGEX) {
+ xlog("L_WARNING","$ci|ACL-device|Fix for $var(sip-packet) with IP in from URI: use to-domain\n");
+ $var(device) = $fU + "@" + $td;
+ } else {
+ $var(device) = $fU + "@" + $fd;
+ }
+ $var(device-decision) = $sht(acl=>$var(device)/$si);
+
+ if ($var(device-decision) == -1) { # we do not have cached decision
+ $var(acl-device-request) = "true";
+ } else if ($var(device-decision) == 1 ){ # We have cached decision, let's use it
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(device)\n");
+ } else {
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(device)\n");
+ exit;
+ }
+ }
+
+
+ if ($var(acl-realm-request) == "true" || $var(acl-device-request) == "true") {
+ if (not_empty("$fU"))
+ $var(query) = "{'Event-Category': 'acl', 'Event-Name': 'query', 'Entity': '" + $var(device) + "', 'With-Realm': " + $var(acl-realm-request) + "}";
+ else
+ $var(query) = "{'Event-Category': 'acl', 'Event-Name': 'query', 'Entity': '" + $var(realm) + "'}";
+ xlog("L_DBG", "$ci|ACL log|Query: $var(query)\n");
+ sl_send_reply("100", "Attempting K query");
+ if (kazoo_query("frontier", "sbc_config", $var(query), "$var(acl-response)")) {
+ xlog("L_DBG", "$ci|ACL log|Response: $var(acl-response)\n");
+
+ kazoo_json($var(acl-response), "Realm.Order", "$var(acl-realm-order)");
+ kazoo_json($var(acl-response), "Realm.CIDR", "$var(acl-realm-cidr)");
+ kazoo_json($var(acl-response), "Device.Order", "$var(acl-device-order)");
+ kazoo_json($var(acl-response), "Device.CIDR", "$var(acl-device-cidr)");
+ kazoo_json($var(acl-response), "Device.User-Agent", "$var(acl-device-ua)");
+
+ } else {
+ xlog("L_ERROR","$ci|ACL log|DB is unreachable\n");
+ $sht(acl=>$var(device)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(device)\n");
+ return;
+ }
+
+ route(ACL_CHECK_REALM);
+ if (not_empty("$fU")) {
+ route(ACL_CHECK_DEVICE);
+ }
+ }
+
+}
+
+# Check ORDER setting for REALM
+route[ACL_CHECK_REALM] {
+ if (not_empty("$var(acl-realm-order)")) {
+ if ($var(acl-realm-order) == ACL_ORDER_ALLOW_DENY) {
+ route(ACL_CHECK_REALM_ALLOW);
+ } else {
+ route(ACL_CHECK_REALM_DENY);
+ }
+ } else {
+ xlog("L_INFO","$ci|ACL-realm|undefined Order in response for $var(realm)\n");
+ $sht(acl=>$var(realm)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(realm)\n");
+ }
+}
+
+route[ACL_CHECK_REALM_ALLOW] {
+ if (not_empty("$var(acl-realm-cidr)")) {
+ $var(i) = 0;
+ kazoo_json($var(acl-response), "Realm.CIDR[$var(i)]", "$var(record)");;
+ while(not_empty("$var(record)")) {
+ xlog("L_INFO", "$ci|ACL-realm|checking if $si is in $var(record)\n");
+ if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) {
+ $sht(acl=>$var(realm)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(realm)\n");
+ return;
+ }
+ $var(i) = $var(i) + 1;
+ kazoo_json($var(acl-response), "Realm.CIDR[$var(i)]", "$var(record)");;
+ }
+ } else {
+ xlog("L_INFO", "$ci|ACL-realm|undefined CIDR in response for $var(realm)\n");
+ }
+ # Remember in CACHE and DENY
+ $sht(acl=>$var(realm)/$si) = 0;
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(realm)\n");
+ exit;
+}
+
+route[ACL_CHECK_REALM_DENY] {
+ $var(size) = $(kzR{kz.json,Realm.CIDR.length});
+ if (not_empty("$var(acl-realm-cidr)")) {
+ $var(i) = 0;
+ kazoo_json($var(acl-response), "Realm.CIDR[$var(i)]", "$var(record)");;
+ while(not_empty("$var(record)")) {
+ xlog("L_INFO", "$ci|ACL-realm|checking if $si is in $var(record)\n");
+ if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) {
+ $sht(acl=>$var(realm)/$si) = 0;
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(realm)\n");
+ exit;
+ }
+ $var(i) = $var(i) + 1;
+ kazoo_json($var(acl-response), "Realm.CIDR[$var(i)]", "$var(record)");;
+ }
+ } else {
+ xlog("L_INFO", "$ci|ACL-realm|undefined CIDR in response for $var(realm)\n");
+ }
+ # Remember in CACHE and ALLOW
+ $sht(acl=>$var(realm)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(realm)\n");
+ return;
+}
+
+# Check ORDER setting for DEVICE
+route[ACL_CHECK_DEVICE] {
+ if (not_empty("$var(acl-device-order)")) {
+ if ($var(acl-device-order) == ACL_ORDER_ALLOW_DENY) {
+ route(ACL_CHECK_DEVICE_ALLOW);
+ } else {
+ route(ACL_CHECK_DEVICE_DENY);
+ }
+ } else {
+ xlog("L_INFO","$ci|ACL-device|undefined Order in response for $var(device)\n");
+ $sht(acl=>$var(device)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(device)\n");
+ }
+}
+
+route[ACL_CHECK_DEVICE_ALLOW] {
+ if (!not_empty("$var(acl-device-ua)") || (not_empty("$var(acl-device-ua)") && $ua =~ $var(acl-device-ua))) {
+ if (not_empty("$var(acl-device-cidr)")) {
+ $var(i) = 0;
+ kazoo_json($var(acl-response), "Device.CIDR[$var(i)]", "$var(record)");;
+ while(not_empty("$var(record)")) {
+ xlog("L_INFO", "$ci|ACL-realm|checking if $si is in $var(record)\n");
+ if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) {
+ $sht(acl=>$var(device)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(device)\n");
+ return;
+ }
+ $var(i) = $var(i) + 1;
+ kazoo_json($var(acl-response), "Device.CIDR[$var(i)]", "$var(record)");;
+ }
+ } else {
+ xlog("L_INFO", "$ci|ACL-realm|undefined CIDR in response for $var(device)\n");
+ }
+ }
+ # Remember in CACHE and DENY
+ $sht(acl=>$var(device)/$si) = 0;
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(device)\n");
+ exit;
+}
+
+route[ACL_CHECK_DEVICE_DENY] {
+ if (not_empty("$var(acl-device-ua)") && !($ua =~ $var(acl-device-ua))) {
+ $sht(acl=>$var(device)/$si) = 0;
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(device)\n");
+ exit;
+ }
+
+ if (not_empty("$var(acl-device-cidr)")) {
+ $var(i) = 0;
+ kazoo_json($var(acl-response), "Device.CIDR[$var(i)]", "$var(record)");;
+ while(not_empty("$var(record)")) {
+ xlog("L_INFO", "$ci|ACL-device|checking if $si is in $var(record)\n");
+ if (($var(record) == ACL_IP_ADDR_ANY) || is_in_subnet("$si", $var(record))) {
+ $sht(acl=>$var(device)/$si) = 0;
+ if (!isflagset(FLAG_IS_REPLY)) {
+ sl_send_reply(ACL_CODE_DENY, ACL_MESSAGE_DENY);
+ }
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is rejected by ACL for $var(device)\n");
+ exit;
+ }
+ $var(i) = $var(i) + 1;
+ kazoo_json($var(acl-response), "Device.CIDR[$var(i)]", "$var(record)");;
+ }
+ } else {
+ xlog("L_INFO", "$ci|ACL-device|undefined CIDR in response for $var(device)\n");
+ }
+ # Remember in CACHE and ALLOW
+ $sht(acl=>$var(device)/$si) = 1;
+ xlog("L_INFO", "$ci|ACL|$var(sip-packet) from $si is permitted by ACL for $var(device)\n");
+ return;
+}
+
+event_route[kazoo:consumer-event-acl-acl-flush]
+{
+ if( $(kzE{kz.json,Device}) != "" ) {
+ $var(device_regexp) = $(kzE{kz.json,Device}) + "@" + $(kzE{kz.json,Realm}) + "/.*" ;
+ xlog("L_INFO","|ACL-Flush| Flush ACL for Device. Regexp: $var(device_regexp)\n");
+ sht_rm_name_re("acl=>$var(device_regexp)");
+ } else {
+ $var(realm_regexp) = "^" + $(kzE{kz.json,Realm}) + "/.*" ;
+ xlog("L_INFO","|ACL-Flush| Flush ACL for Realm. Regexp: $var(realm_regexp)\n");
+ sht_rm_name_re("acl=>$var(realm_regexp)");
+ }
+
+}
+
+route[ACL_BINDINGS]
+{
+ $var(payload) = $_s({"name": "acl-role", "exchange" : "frontier_acl" , "type" : "topic", "queue" : "FRONTIERACL-FLUSH-MY_HOSTNAME", "routing" : "flush" });
+ kazoo_subscribe("$var(payload)");
+}
\ No newline at end of file
diff --git a/kamailio-proxy-proxy/antiflood-role.cfg b/kamailio-proxy-proxy/antiflood-role.cfg
new file mode 100644
index 0000000..3a98318
--- /dev/null
+++ b/kamailio-proxy-proxy/antiflood-role.cfg
@@ -0,0 +1,140 @@
+
+#!trydef ANTIFLOOD_RATE_WINDOW 2
+#!trydef ANTIFLOOD_RATE_DENSITY 50
+#!trydef ANTIFLOOD_RATE_EXPIRE 4
+#!trydef ANTIFLOOD_FAILED_AUTH_WINDOW 300
+#!trydef ANTIFLOOD_FAILED_AUTH_DENSITY 4
+#!trydef ANTIFLOOD_FAILED_AUTH_USE_PORT 1
+#!trydef ANTIFLOOD_FAILED_AUTH_ACTION 2
+#!trydef ANTIFLOOD_RATE_LIMIT_ENABLED 1
+#!trydef ANTIFLOOD_AUTH_LIMIT_ENABLED 1
+#!trydef ANTIFLOOD_RATE_DROP 1
+#!trydef ANTIFLOOD_CACHE_PERIOD 300
+
+#!substdef "!ANTIFLOOD_SUBST_CACHE_PERIOD!$def(ANTIFLOOD_CACHE_PERIOD)!g"
+
+######## Flood Prevention Hash Tables ########
+modparam("htable", "htable", "antiflood=>size=16;autoexpire=ANTIFLOOD_SUBST_CACHE_PERIOD;initval=0")
+
+######## Flood Prevention Module ########
+loadmodule "pike.so"
+modparam("pike", "sampling_time_unit", ANTIFLOOD_RATE_WINDOW)
+modparam("pike", "reqs_density_per_unit", ANTIFLOOD_RATE_DENSITY)
+modparam("pike", "remove_latency", ANTIFLOOD_RATE_EXPIRE)
+
+kazoo.antiflood_failed_auth_use_port = ANTIFLOOD_FAILED_AUTH_USE_PORT descr "should we keep track of ip and port for auth failures"
+kazoo.antiflood_failed_auth_action = ANTIFLOOD_FAILED_AUTH_ACTION descr "0 - log, 1 - drop, 2 - reply with 403"
+kazoo.antiflood_rate_limit_enabled = ANTIFLOOD_RATE_LIMIT_ENABLED descr "antiflood rate limit enabled"
+kazoo.antiflood_auth_limit_enabled = ANTIFLOOD_AUTH_LIMIT_ENABLED descr "antiflood auth limit enabled"
+kazoo.antiflood_rate_drop = ANTIFLOOD_RATE_DROP descr "should we drop on rate limit"
+
+route[ANTIFLOOD_LIMIT]
+{
+ if($sel(cfg_get.kazoo.antiflood_rate_limit_enabled) == 1) {
+ route(ANTIFLOOD_RATE_LIMIT);
+ }
+ if($sel(cfg_get.kazoo.antiflood_auth_limit_enabled) == 1) {
+ route(ANTIFLOOD_AUTH_LIMIT);
+ }
+}
+
+route[ANTIFLOOD_RATE_LIMIT]
+{
+ if (has_totag()
+ || isflagset(FLAG_TRUSTED_SOURCE)
+ || isflagset(FLAG_INTERNALLY_SOURCED)) {
+ return;
+ }
+
+ # use pike to control the rates
+ if (!pike_check_req()) {
+ if($sel(cfg_get.kazoo.antiflood_rate_drop) == 1) {
+ xlog("L_WARN", "$ci|end|dropping request from $fu due to rate of requests with source $si:$sp\n");
+ drop();
+ } else {
+ xlog("L_WARN", "$ci|allowed|request from $fu exceeded rate of requests with source $si:$sp\n");
+ }
+ }
+}
+
+route[ANTIFLOOD_AUTH_LIMIT]
+{
+ if (has_totag()
+ || isflagset(FLAG_TRUSTED_SOURCE)
+ || isflagset(FLAG_INTERNALLY_SOURCED)) {
+ return(1);
+ }
+
+ $var(auth_key) = "";
+ if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
+ $var(auth_key) = $_s("$Au::$si::$sp");
+ } else {
+ $var(auth_key) = $_s("$Au::$si");
+ }
+ if ($Au != $null &&
+ $sht(antiflood=>$var(auth_key)::count) >= ANTIFLOOD_FAILED_AUTH_DENSITY
+ ) {
+ $shtex(antiflood=>$var(auth_key)::count) = ANTIFLOOD_FAILED_AUTH_WINDOW;
+ $sht(antiflood=>$var(auth_key)::last) = $Ts;
+ if($sel(cfg_get.kazoo.antiflood_failed_auth_action) == 1) {
+ xlog("L_WARNING", "$ci|end|dropping request authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
+ drop();
+ } else if($sel(cfg_get.kazoo.antiflood_failed_auth_action) == 2) {
+ xlog("L_NOTICE", "$ci|end|authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
+ append_to_reply("Retry-After: 3600\r\n");
+ send_reply("403", "Forbidden");
+ exit;
+ } else {
+ xlog("L_NOTICE", "$ci|log|authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
+ }
+ }
+}
+
+route[ANTIFLOOD_SUCCESSFUL_AUTH]
+{
+ if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
+ sht_rm_name_re("antiflood=>$(Au{re.subst,/\\./\\\\./g})::$(si{re.subst,/\\./\\\\./g})::$sp::.*");
+ } else {
+ sht_rm_name_re("antiflood=>$(Au{re.subst,/\\./\\\\./g})::$(si{re.subst,/\\./\\\\./g})::.*");
+ }
+}
+
+route[ANTIFLOOD_RESET_AUTH]
+{
+ $var(user) = $(kzE{kz.json,Username}) + "@" + $(kzE{kz.json,Realm});
+ sht_rm_name_re("antiflood=>$(var(user){re.subst,/\\./\\\\./g})::.*");
+}
+
+route[ANITFLOOD_FAILED_AUTH]
+{
+ if (isflagset(FLAG_TRUSTED_SOURCE)) {
+ return;
+ }
+
+ $var(auth_key) = "";
+ if($sel(cfg_get.kazoo.antiflood_failed_auth_use_port) == 1) {
+ $var(auth_key) = $_s("$Au::$si::$sp");
+ } else {
+ $var(auth_key) = $_s("$Au::$si");
+ }
+
+ $var(count) = $shtinc(antiflood=>$var(auth_key)::count);
+ $sht(antiflood=>$var(auth_key)::last) = $Ts;
+
+ xlog("L_INFO", "$ci|log|$var(count) errounous authorization response for $Au $si:$sp\n");
+
+ if ($var(count) >= ANTIFLOOD_FAILED_AUTH_DENSITY) {
+ $var(exp) = $Ts - ANTIFLOOD_FAILED_AUTH_WINDOW;
+ if($sht(antiflood=>$var(auth_key)::last) > $var(exp)) {
+ xlog("L_NOTICE", "$ci|end|request at authorization failure limit $def(ANTIFLOOD_FAILED_AUTH_DENSITY) for $Au $si:$sp\n");
+ append_to_reply("Retry-After: 3600\r\n");
+ send_reply("403", "Forbidden");
+ exit;
+ }
+ }
+}
+
+event_route[htable:expired:antiflood]
+{
+ xlog("L_NOTICE", "antiflood expired record $shtrecord(key) => $shtrecord(value)\n");
+}
diff --git a/kamailio-proxy-proxy/auth.cfg b/kamailio-proxy-proxy/auth.cfg
new file mode 100644
index 0000000..12ca14b
--- /dev/null
+++ b/kamailio-proxy-proxy/auth.cfg
@@ -0,0 +1,130 @@
+
+
+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-");
+
+ if (!is_method("INVITE|MESSAGE|REFER")) {
+ return;
+ }
+
+ 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[AUTH_HEADERS_JSON]
+{
+ xavp_params_implode("hf", "$var(outx)");
+ $var(out) = $(var(outx){re.subst,/^(.*);$$/\1/});
+ $var(c) = $(var(out){param.count});
+ $var(headers_json) = "";
+ $var(sep) = "";
+ 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(headers_json) = $_s($var(headers_json)$var(sep)"$(var(out){param.name,$var(idx)})" : "$(var(out){param.valueat,$var(idx)}{s.unescape.param})");
+ $var(c) = $var(c) - 1;
+ $var(sep) = " , ";
+ }
+ $var(headers_json) = $_s({ $var(headers_json) });
+}
+
+route[SETUP_AUTH_HEADERS]
+{
+
+ $xavp(hf=>X-AUTH-IP) = $si;
+ $xavp(hf[0]=>X-AUTH-PORT) = $sp;
+
+ #!ifdef REGISTRAR_ROLE
+
+ $avp(is_registered) = "false";
+ $xavp(regcfg=>match_received) = $su;
+ if (registered("location","$fu", 2, 1) != 1) return;
+
+ $avp(is_registered) = "true";
+ #!ifdef WITH_AUTH_TOKEN
+ route(AUTH_TOKEN);
+ #!else
+ route(AUTH_CCVS);
+ #!endif
+
+ #!endif
+
+}
+
+#!ifdef REGISTRAR_ROLE
+
+route[AUTH_TOKEN]
+{
+ 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]
+{
+ 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,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,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
diff --git a/kamailio-proxy-proxy/authorization-role.cfg b/kamailio-proxy-proxy/authorization-role.cfg
new file mode 100644
index 0000000..5b55be2
--- /dev/null
+++ b/kamailio-proxy-proxy/authorization-role.cfg
@@ -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;
+ }
+}
diff --git a/kamailio-proxy-proxy/blocker-role.cfg b/kamailio-proxy-proxy/blocker-role.cfg
new file mode 100644
index 0000000..8da3adf
--- /dev/null
+++ b/kamailio-proxy-proxy/blocker-role.cfg
@@ -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;
+ }
+ }
+ }
+}
diff --git a/kamailio-proxy-proxy/certs/.placeholder b/kamailio-proxy-proxy/certs/.placeholder
new file mode 100644
index 0000000..9581629
--- /dev/null
+++ b/kamailio-proxy-proxy/certs/.placeholder
@@ -0,0 +1 @@
+ensure certs directory gets created
\ No newline at end of file
diff --git a/kamailio-proxy-proxy/db_kazoo.cfg b/kamailio-proxy-proxy/db_kazoo.cfg
new file mode 100644
index 0000000..4989a32
--- /dev/null
+++ b/kamailio-proxy-proxy/db_kazoo.cfg
@@ -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"
diff --git a/kamailio-proxy-proxy/db_mysql.cfg b/kamailio-proxy-proxy/db_mysql.cfg
new file mode 100644
index 0000000..9000b57
--- /dev/null
+++ b/kamailio-proxy-proxy/db_mysql.cfg
@@ -0,0 +1,4 @@
+#### db_mysql module ###
+loadmodule "db_mysql.so"
+
+include_file "db_queries_mysql.cfg"
diff --git a/kamailio-proxy-proxy/db_postgres.cfg b/kamailio-proxy-proxy/db_postgres.cfg
new file mode 100644
index 0000000..51dbd44
--- /dev/null
+++ b/kamailio-proxy-proxy/db_postgres.cfg
@@ -0,0 +1,4 @@
+#### db_postgres module ###
+loadmodule "db_postgres.so"
+
+include_file "db_queries_postgres.cfg"
diff --git a/kamailio-proxy-proxy/db_queries_kazoo.cfg b/kamailio-proxy-proxy/db_queries_kazoo.cfg
new file mode 100644
index 0000000..128e3e4
--- /dev/null
+++ b/kamailio-proxy-proxy/db_queries_kazoo.cfg
@@ -0,0 +1,33 @@
+####### Database queries ########
+#!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 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 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"
+
+#!substdef "!KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_EXPIRES!DELETE FROM active_watchers WHERE expires > 0 AND datetime(expires, 'unixepoch') < datetime('now', '-90 seconds')!g"
+#!substdef "!KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_PRESENTITY!DELETE FROM ACTIVE_WATCHERS WHERE PRESENTITY_URI=\"\$subs(uri)\" AND EVENT=\"\$subs(event)\" AND FROM_USER = \"\$subs(from_user)\" AND FROM_DOMAIN=\"\$subs(from_domain)\" AND CALLID <> \"\$subs(callid)\"!g"
+#!substdef "!KZQ_DELETE_FROM_PRESENTITY_WHERE_EXPIRES!DELETE FROM PRESENTITY WHERE expires > 0 AND datetime(expires, 'unixepoch') < datetime('now')!g"
+#!substdef "!KZQ_DELETE_FROM_PRESENTITY_WHERE_DIALOG_TERMINATED!DELETE FROM PRESENTITY WHERE ID IN(select id from presentities where event = 'dialog' and state = 'terminated' and received < datetime('now', '-5 minutes'))!g"
+
diff --git a/kamailio-proxy-proxy/db_queries_mysql.cfg b/kamailio-proxy-proxy/db_queries_mysql.cfg
new file mode 100644
index 0000000..7385add
--- /dev/null
+++ b/kamailio-proxy-proxy/db_queries_mysql.cfg
@@ -0,0 +1,15 @@
+####### Database queries ########
+#!substdef "!KZQ_CHECK_MEDIA_SERVER_INSERT!insert into dispatcher (setid, destination) select \$var(SetId), \"\$var(MediaUrl)\" from DUAL 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_COUNT_PRESENTITIES!select event, (select count(*) from presentity b where username = \"\$(kzE{kz.json,From}{uri.user})\" and domain = \"\$(kzE{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_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_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"
diff --git a/kamailio-proxy-proxy/db_queries_postgres.cfg b/kamailio-proxy-proxy/db_queries_postgres.cfg
new file mode 100644
index 0000000..4b1ce60
--- /dev/null
+++ b/kamailio-proxy-proxy/db_queries_postgres.cfg
@@ -0,0 +1,23 @@
+####### 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_COUNT_PRESENTITIES!select event, (select count(*) from presentity b where username = '\$(kzE{kz.json,From}{uri.user})' and domain = '\$(kzE{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_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_PRESENCE_RESET!delete from presentity where sender = '\$var(MediaUrl)'!g"
+
+#!substdef "!KZQ_REPLACE_WATCHERS_LOG!INSERT 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.replace,\\\',''}{s.replace,\$\$,''})', '\$(notify_reply(\$mb){s.replace,\\\',''}{s.replace,\$\$,''})') ON CONFLICT (presentity_uri, watcher_username, watcher_domain, event) DO UPDATE SET presentity_uri = excluded.presentity_uri, watcher_username = excluded.watcher_username, watcher_domain = excluded.watcher_domain, event = excluded.event!g"
+
+#!substdef "!KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_EXPIRES!DELETE FROM active_watchers WHERE expires > 0 AND to_timestamp(expires) < now() - interval '90 seconds'!g"
+#!substdef "!KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_PRESENTITY!DELETE FROM ACTIVE_WATCHERS WHERE PRESENTITY_URI='\$subs(uri)' AND EVENT='\$subs(event)' AND FROM_USER = '\$subs(from_user)' AND FROM_DOMAIN='\$subs(from_domain)' AND CALLID <> '\$subs(callid)'!g"
+#!substdef "!KZQ_DELETE_FROM_PRESENTITY_WHERE_EXPIRES!DELETE FROM PRESENTITY WHERE expires > 0 AND to_timestamp(expires) < now()!g"
+#!substdef "!KZQ_DELETE_FROM_PRESENTITY_WHERE_DIALOG_TERMINATED!DELETE FROM PRESENTITY WHERE ID IN(select id from presentities where event = 'dialog' and state = 'terminated' and received < now() - interval '5 minutes'))!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"
+
diff --git a/kamailio-proxy-proxy/db_scripts/check-kazoodb-sql.sh b/kamailio-proxy-proxy/db_scripts/check-kazoodb-sql.sh
new file mode 100755
index 0000000..4ff700a
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/check-kazoodb-sql.sh
@@ -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
diff --git a/kamailio-proxy-proxy/db_scripts/create-kazoodb-sql.sh b/kamailio-proxy-proxy/db_scripts/create-kazoodb-sql.sh
new file mode 100755
index 0000000..b720415
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/create-kazoodb-sql.sh
@@ -0,0 +1,9 @@
+#!/bin/sh -e
+
+. $(dirname $0)/kazoodb-sql.sh --source-only
+
+file=$(sql_db_prepare)
+echo "setting up kazoo db from init script $file"
+sql_setup $file
+
+exit 0
diff --git a/kamailio-proxy-proxy/db_scripts/db_extra_check.sql b/kamailio-proxy-proxy/db_scripts/db_extra_check.sql
new file mode 100644
index 0000000..88210bd
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/db_extra_check.sql
@@ -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;"
+
+}
diff --git a/kamailio-proxy-proxy/db_scripts/db_init_watcher_triggers.sql b/kamailio-proxy-proxy/db_scripts/db_init_watcher_triggers.sql
new file mode 100644
index 0000000..8e5a202
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/db_init_watcher_triggers.sql
@@ -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;
diff --git a/kamailio-proxy-proxy/db_scripts/db_kazoo-specific b/kamailio-proxy-proxy/db_scripts/db_kazoo-specific
new file mode 100644
index 0000000..2f87516
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/db_kazoo-specific
@@ -0,0 +1,152 @@
+#!/bin/sh
+
+sql_db_pre_setup() {
+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=${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() {
+cat << EOF
+EOF
+}
+
+sql_extra_tables() {
+cat << EOF
+CREATE TABLE active_watchers_log (
+ id INTEGER PRIMARY KEY NOT NULL,
+ presentity_uri VARCHAR(128) NOT NULL COLLATE NOCASE,
+ watcher_username VARCHAR(64) NOT NULL COLLATE NOCASE,
+ watcher_domain VARCHAR(64) NOT NULL COLLATE NOCASE,
+ to_user VARCHAR(64) NOT NULL COLLATE NOCASE,
+ to_domain VARCHAR(64) NOT NULL COLLATE NOCASE,
+ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
+ callid VARCHAR(255) NOT NULL,
+ time INTEGER NOT NULL,
+ result INTEGER NOT NULL,
+ sent_msg BLOB NOT NULL,
+ received_msg BLOB NOT NULL,
+ user_agent VARCHAR(255) DEFAULT '' COLLATE NOCASE,
+ CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
+ );
+INSERT INTO version (table_name, table_version) values ('active_watchers_log','1');
+
+CREATE TABLE keepalive (
+ id INTEGER PRIMARY KEY NOT NULL,
+ contact VARCHAR(2048) NOT NULL COLLATE NOCASE,
+ received VARCHAR(32) NOT NULL COLLATE NOCASE,
+ sockinfo VARCHAR(128) NOT NULL COLLATE NOCASE,
+ time_inserted timestamp DEFAULT CURRENT_TIMESTAMP,
+ time_sent timestamp DEFAULT CURRENT_TIMESTAMP,
+ slot INTEGER NOT NULL,
+ selected INTEGER DEFAULT 0,
+ failed INTEGER DEFAULT 0,
+ CONSTRAINT keepalive_idx UNIQUE (contact),
+ CONSTRAINT keepalive_idx_2 UNIQUE (slot, failed, contact)
+ );
+
+CREATE INDEX keepalive_idx_3 ON keepalive (slot, selected, time_sent);
+CREATE INDEX keepalive_idx_4 ON keepalive (received, selected);
+
+INSERT INTO version (table_name, table_version) values ('keepalive','4');
+
+ALTER TABLE active_watchers ADD COLUMN watcher_uri varchar(64) NOT NULL DEFAULT "sip:no_watcher@no_domain";
+
+CREATE TRIGGER 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 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;
+
+CREATE UNIQUE INDEX active_watchers_contact ON active_watchers (contact, id);
+CREATE INDEX active_watchers_event_watcher_uri ON active_watchers (event, watcher_uri);
+
+
+CREATE INDEX location_attrs_ruid ON location_attrs (ruid);
+CREATE UNIQUE INDEX location_ruid ON location (ruid);
+
+create table auth_cache as select * from htable;
+INSERT INTO version (table_name, table_version) select 'auth_cache', table_version from version where table_name = 'htable';
+
+create table block_cache as select * from htable;
+INSERT INTO version (table_name, table_version) select 'block_cache', table_version from version where table_name = 'htable';
+
+
+ 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;
+
+ create unique index if not exists idx_dispatcher_destination on dispatcher(destination);
+
+
+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;
+
+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;
+
+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;
+
+EOF
+}
+
+sql_footer() {
+cat << EOF
+EOF
+}
diff --git a/kamailio-proxy-proxy/db_scripts/kamailio_initdb_postgres.sql b/kamailio-proxy-proxy/db_scripts/kamailio_initdb_postgres.sql
new file mode 100644
index 0000000..03adf1f
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/kamailio_initdb_postgres.sql
@@ -0,0 +1,5811 @@
+--
+-- PostgreSQL database dump
+--
+
+-- Dumped from database version 12.7
+-- Dumped by pg_dump version 12.7
+
+SET statement_timeout = 0;
+SET lock_timeout = 0;
+SET idle_in_transaction_session_timeout = 0;
+SET client_encoding = 'UTF8';
+SET standard_conforming_strings = on;
+SELECT pg_catalog.set_config('search_path', '', false);
+SET check_function_bodies = false;
+SET xmloption = content;
+SET client_min_messages = warning;
+SET row_security = off;
+
+SET default_tablespace = '';
+
+SET default_table_access_method = heap;
+
+--
+-- Name: acc; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.acc (
+ id integer NOT NULL,
+ method character varying(16) DEFAULT ''::character varying NOT NULL,
+ from_tag character varying(64) DEFAULT ''::character varying NOT NULL,
+ to_tag character varying(64) DEFAULT ''::character varying NOT NULL,
+ callid character varying(255) DEFAULT ''::character varying NOT NULL,
+ sip_code character varying(3) DEFAULT ''::character varying NOT NULL,
+ sip_reason character varying(128) DEFAULT ''::character varying NOT NULL,
+ "time" timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.acc OWNER TO kamailio;
+
+--
+-- Name: acc_cdrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.acc_cdrs (
+ id integer NOT NULL,
+ start_time timestamp without time zone DEFAULT '2000-01-01 00:00:00'::timestamp without time zone NOT NULL,
+ end_time timestamp without time zone DEFAULT '2000-01-01 00:00:00'::timestamp without time zone NOT NULL,
+ duration real DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.acc_cdrs OWNER TO kamailio;
+
+--
+-- Name: acc_cdrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.acc_cdrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.acc_cdrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: acc_cdrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.acc_cdrs_id_seq OWNED BY public.acc_cdrs.id;
+
+
+--
+-- Name: acc_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.acc_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.acc_id_seq OWNER TO kamailio;
+
+--
+-- Name: acc_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.acc_id_seq OWNED BY public.acc.id;
+
+
+--
+-- Name: active_watchers; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.active_watchers (
+ id integer NOT NULL,
+ presentity_uri character varying(128) NOT NULL,
+ watcher_username character varying(64) NOT NULL,
+ watcher_domain character varying(64) NOT NULL,
+ to_user character varying(64) NOT NULL,
+ to_domain character varying(64) NOT NULL,
+ event character varying(64) DEFAULT 'presence'::character varying NOT NULL,
+ event_id character varying(64),
+ to_tag character varying(64) NOT NULL,
+ from_tag character varying(64) NOT NULL,
+ callid character varying(255) NOT NULL,
+ local_cseq integer NOT NULL,
+ remote_cseq integer NOT NULL,
+ contact character varying(128) NOT NULL,
+ record_route text,
+ expires integer NOT NULL,
+ status integer DEFAULT 2 NOT NULL,
+ reason character varying(64),
+ version integer DEFAULT 0 NOT NULL,
+ socket_info character varying(64) NOT NULL,
+ local_contact character varying(128) NOT NULL,
+ from_user character varying(64) NOT NULL,
+ from_domain character varying(64) NOT NULL,
+ updated integer NOT NULL,
+ updated_winfo integer NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ user_agent character varying(255) DEFAULT ''::character varying
+);
+
+
+ALTER TABLE public.active_watchers OWNER TO kamailio;
+
+--
+-- Name: active_watchers_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.active_watchers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.active_watchers_id_seq OWNER TO kamailio;
+
+--
+-- Name: active_watchers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.active_watchers_id_seq OWNED BY public.active_watchers.id;
+
+
+--
+-- Name: active_watchers_log; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.active_watchers_log (
+ id integer NOT NULL,
+ presentity_uri character varying(128) NOT NULL,
+ watcher_username character varying(64) NOT NULL,
+ watcher_domain character varying(64) NOT NULL,
+ to_user character varying(64) NOT NULL,
+ to_domain character varying(64) NOT NULL,
+ event character varying(64) DEFAULT 'presence'::character varying NOT NULL,
+ callid character varying(255) NOT NULL,
+ "time" integer NOT NULL,
+ result integer NOT NULL,
+ sent_msg bytea NOT NULL,
+ received_msg bytea NOT NULL,
+ user_agent character varying(255) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.active_watchers_log OWNER TO kamailio;
+
+--
+-- Name: active_watchers_log_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.active_watchers_log_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.active_watchers_log_id_seq OWNER TO kamailio;
+
+--
+-- Name: active_watchers_log_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.active_watchers_log_id_seq OWNED BY public.active_watchers_log.id;
+
+
+--
+-- Name: address; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.address (
+ id integer NOT NULL,
+ grp integer DEFAULT 1 NOT NULL,
+ ip_addr character varying(50) NOT NULL,
+ mask integer DEFAULT 32 NOT NULL,
+ port smallint DEFAULT 0 NOT NULL,
+ tag character varying(64)
+);
+
+
+ALTER TABLE public.address OWNER TO kamailio;
+
+--
+-- Name: address_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.address_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.address_id_seq OWNER TO kamailio;
+
+--
+-- Name: address_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.address_id_seq OWNED BY public.address.id;
+
+
+--
+-- Name: aliases; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.aliases (
+ id integer NOT NULL,
+ ruid character varying(64) DEFAULT ''::character varying NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT NULL::character varying,
+ contact character varying(255) DEFAULT ''::character varying NOT NULL,
+ received character varying(128) DEFAULT NULL::character varying,
+ path character varying(512) DEFAULT NULL::character varying,
+ expires timestamp without time zone DEFAULT '2030-05-28 21:32:15'::timestamp without time zone NOT NULL,
+ q real DEFAULT 1.0 NOT NULL,
+ callid character varying(255) DEFAULT 'Default-Call-ID'::character varying NOT NULL,
+ cseq integer DEFAULT 1 NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ cflags integer DEFAULT 0 NOT NULL,
+ user_agent character varying(255) DEFAULT ''::character varying NOT NULL,
+ socket character varying(64) DEFAULT NULL::character varying,
+ methods integer,
+ instance character varying(255) DEFAULT NULL::character varying,
+ reg_id integer DEFAULT 0 NOT NULL,
+ server_id integer DEFAULT 0 NOT NULL,
+ connection_id integer DEFAULT 0 NOT NULL,
+ keepalive integer DEFAULT 0 NOT NULL,
+ partition integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.aliases OWNER TO kamailio;
+
+--
+-- Name: aliases_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.aliases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.aliases_id_seq OWNER TO kamailio;
+
+--
+-- Name: aliases_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.aliases_id_seq OWNED BY public.aliases.id;
+
+
+--
+-- Name: carrier_name; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.carrier_name (
+ id integer NOT NULL,
+ carrier character varying(64) DEFAULT NULL::character varying
+);
+
+
+ALTER TABLE public.carrier_name OWNER TO kamailio;
+
+--
+-- Name: carrier_name_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.carrier_name_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.carrier_name_id_seq OWNER TO kamailio;
+
+--
+-- Name: carrier_name_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.carrier_name_id_seq OWNED BY public.carrier_name.id;
+
+
+--
+-- Name: carrierfailureroute; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.carrierfailureroute (
+ id integer NOT NULL,
+ carrier integer DEFAULT 0 NOT NULL,
+ domain integer DEFAULT 0 NOT NULL,
+ scan_prefix character varying(64) DEFAULT ''::character varying NOT NULL,
+ host_name character varying(128) DEFAULT ''::character varying NOT NULL,
+ reply_code character varying(3) DEFAULT ''::character varying NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ mask integer DEFAULT 0 NOT NULL,
+ next_domain integer DEFAULT 0 NOT NULL,
+ description character varying(255) DEFAULT NULL::character varying
+);
+
+
+ALTER TABLE public.carrierfailureroute OWNER TO kamailio;
+
+--
+-- Name: carrierfailureroute_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.carrierfailureroute_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.carrierfailureroute_id_seq OWNER TO kamailio;
+
+--
+-- Name: carrierfailureroute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.carrierfailureroute_id_seq OWNED BY public.carrierfailureroute.id;
+
+
+--
+-- Name: carrierroute; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.carrierroute (
+ id integer NOT NULL,
+ carrier integer DEFAULT 0 NOT NULL,
+ domain integer DEFAULT 0 NOT NULL,
+ scan_prefix character varying(64) DEFAULT ''::character varying NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ mask integer DEFAULT 0 NOT NULL,
+ prob real DEFAULT 0 NOT NULL,
+ strip integer DEFAULT 0 NOT NULL,
+ rewrite_host character varying(128) DEFAULT ''::character varying NOT NULL,
+ rewrite_prefix character varying(64) DEFAULT ''::character varying NOT NULL,
+ rewrite_suffix character varying(64) DEFAULT ''::character varying NOT NULL,
+ description character varying(255) DEFAULT NULL::character varying
+);
+
+
+ALTER TABLE public.carrierroute OWNER TO kamailio;
+
+--
+-- Name: carrierroute_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.carrierroute_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.carrierroute_id_seq OWNER TO kamailio;
+
+--
+-- Name: carrierroute_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.carrierroute_id_seq OWNED BY public.carrierroute.id;
+
+
+--
+-- Name: cpl; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.cpl (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ cpl_xml text,
+ cpl_bin text
+);
+
+
+ALTER TABLE public.cpl OWNER TO kamailio;
+
+--
+-- Name: cpl_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.cpl_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.cpl_id_seq OWNER TO kamailio;
+
+--
+-- Name: cpl_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.cpl_id_seq OWNED BY public.cpl.id;
+
+
+--
+-- Name: dbaliases; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dbaliases (
+ id integer NOT NULL,
+ alias_username character varying(64) DEFAULT ''::character varying NOT NULL,
+ alias_domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dbaliases OWNER TO kamailio;
+
+--
+-- Name: dbaliases_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dbaliases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dbaliases_id_seq OWNER TO kamailio;
+
+--
+-- Name: dbaliases_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dbaliases_id_seq OWNED BY public.dbaliases.id;
+
+
+--
+-- Name: dialog; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dialog (
+ id integer NOT NULL,
+ hash_entry integer NOT NULL,
+ hash_id integer NOT NULL,
+ callid character varying(255) NOT NULL,
+ from_uri character varying(128) NOT NULL,
+ from_tag character varying(64) NOT NULL,
+ to_uri character varying(128) NOT NULL,
+ to_tag character varying(64) NOT NULL,
+ caller_cseq character varying(20) NOT NULL,
+ callee_cseq character varying(20) NOT NULL,
+ caller_route_set character varying(512),
+ callee_route_set character varying(512),
+ caller_contact character varying(128) NOT NULL,
+ callee_contact character varying(128) NOT NULL,
+ caller_sock character varying(64) NOT NULL,
+ callee_sock character varying(64) NOT NULL,
+ state integer NOT NULL,
+ start_time integer NOT NULL,
+ timeout integer DEFAULT 0 NOT NULL,
+ sflags integer DEFAULT 0 NOT NULL,
+ iflags integer DEFAULT 0 NOT NULL,
+ toroute_name character varying(32),
+ req_uri character varying(128) NOT NULL,
+ xdata character varying(512)
+);
+
+
+ALTER TABLE public.dialog OWNER TO kamailio;
+
+--
+-- Name: dialog_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dialog_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dialog_id_seq OWNER TO kamailio;
+
+--
+-- Name: dialog_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dialog_id_seq OWNED BY public.dialog.id;
+
+
+--
+-- Name: dialog_vars; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dialog_vars (
+ id integer NOT NULL,
+ hash_entry integer NOT NULL,
+ hash_id integer NOT NULL,
+ dialog_key character varying(128) NOT NULL,
+ dialog_value character varying(512) NOT NULL
+);
+
+
+ALTER TABLE public.dialog_vars OWNER TO kamailio;
+
+--
+-- Name: dialog_vars_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dialog_vars_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dialog_vars_id_seq OWNER TO kamailio;
+
+--
+-- Name: dialog_vars_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dialog_vars_id_seq OWNED BY public.dialog_vars.id;
+
+
+--
+-- Name: dialplan; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dialplan (
+ id integer NOT NULL,
+ dpid integer NOT NULL,
+ pr integer NOT NULL,
+ match_op integer NOT NULL,
+ match_exp character varying(64) NOT NULL,
+ match_len integer NOT NULL,
+ subst_exp character varying(64) NOT NULL,
+ repl_exp character varying(256) NOT NULL,
+ attrs character varying(64) NOT NULL
+);
+
+
+ALTER TABLE public.dialplan OWNER TO kamailio;
+
+--
+-- Name: dialplan_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dialplan_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dialplan_id_seq OWNER TO kamailio;
+
+--
+-- Name: dialplan_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dialplan_id_seq OWNED BY public.dialplan.id;
+
+
+--
+-- Name: dispatcher; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dispatcher (
+ id integer NOT NULL,
+ setid integer DEFAULT 0 NOT NULL,
+ destination character varying(192) DEFAULT ''::character varying NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ priority integer DEFAULT 0 NOT NULL,
+ attrs character varying(128) DEFAULT ''::character varying NOT NULL,
+ description character varying(64) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dispatcher OWNER TO kamailio;
+
+--
+-- Name: dispatcher_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dispatcher_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dispatcher_id_seq OWNER TO kamailio;
+
+--
+-- Name: dispatcher_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dispatcher_id_seq OWNED BY public.dispatcher.id;
+
+
+--
+-- Name: domain; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.domain (
+ id integer NOT NULL,
+ domain character varying(64) NOT NULL,
+ did character varying(64) DEFAULT NULL::character varying,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.domain OWNER TO kamailio;
+
+--
+-- Name: domain_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.domain_attrs (
+ id integer NOT NULL,
+ did character varying(64) NOT NULL,
+ name character varying(32) NOT NULL,
+ type integer NOT NULL,
+ value character varying(255) NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.domain_attrs OWNER TO kamailio;
+
+--
+-- Name: domain_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.domain_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.domain_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: domain_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.domain_attrs_id_seq OWNED BY public.domain_attrs.id;
+
+
+--
+-- Name: domain_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.domain_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.domain_id_seq OWNER TO kamailio;
+
+--
+-- Name: domain_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.domain_id_seq OWNED BY public.domain.id;
+
+
+--
+-- Name: domain_name; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.domain_name (
+ id integer NOT NULL,
+ domain character varying(64) DEFAULT NULL::character varying
+);
+
+
+ALTER TABLE public.domain_name OWNER TO kamailio;
+
+--
+-- Name: domain_name_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.domain_name_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.domain_name_id_seq OWNER TO kamailio;
+
+--
+-- Name: domain_name_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.domain_name_id_seq OWNED BY public.domain_name.id;
+
+
+--
+-- Name: domainpolicy; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.domainpolicy (
+ id integer NOT NULL,
+ rule character varying(255) NOT NULL,
+ type character varying(255) NOT NULL,
+ att character varying(255),
+ val character varying(128),
+ description character varying(255) NOT NULL
+);
+
+
+ALTER TABLE public.domainpolicy OWNER TO kamailio;
+
+--
+-- Name: domainpolicy_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.domainpolicy_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.domainpolicy_id_seq OWNER TO kamailio;
+
+--
+-- Name: domainpolicy_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.domainpolicy_id_seq OWNED BY public.domainpolicy.id;
+
+
+--
+-- Name: dr_gateways; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dr_gateways (
+ gwid integer NOT NULL,
+ type integer DEFAULT 0 NOT NULL,
+ address character varying(128) NOT NULL,
+ strip integer DEFAULT 0 NOT NULL,
+ pri_prefix character varying(64) DEFAULT NULL::character varying,
+ attrs character varying(255) DEFAULT NULL::character varying,
+ description character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dr_gateways OWNER TO kamailio;
+
+--
+-- Name: dr_gateways_gwid_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dr_gateways_gwid_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dr_gateways_gwid_seq OWNER TO kamailio;
+
+--
+-- Name: dr_gateways_gwid_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dr_gateways_gwid_seq OWNED BY public.dr_gateways.gwid;
+
+
+--
+-- Name: dr_groups; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dr_groups (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ domain character varying(128) DEFAULT ''::character varying NOT NULL,
+ groupid integer DEFAULT 0 NOT NULL,
+ description character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dr_groups OWNER TO kamailio;
+
+--
+-- Name: dr_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dr_groups_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dr_groups_id_seq OWNER TO kamailio;
+
+--
+-- Name: dr_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dr_groups_id_seq OWNED BY public.dr_groups.id;
+
+
+--
+-- Name: dr_gw_lists; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dr_gw_lists (
+ id integer NOT NULL,
+ gwlist character varying(255) NOT NULL,
+ description character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dr_gw_lists OWNER TO kamailio;
+
+--
+-- Name: dr_gw_lists_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dr_gw_lists_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dr_gw_lists_id_seq OWNER TO kamailio;
+
+--
+-- Name: dr_gw_lists_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dr_gw_lists_id_seq OWNED BY public.dr_gw_lists.id;
+
+
+--
+-- Name: dr_rules; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.dr_rules (
+ ruleid integer NOT NULL,
+ groupid character varying(255) NOT NULL,
+ prefix character varying(64) NOT NULL,
+ timerec character varying(255) NOT NULL,
+ priority integer DEFAULT 0 NOT NULL,
+ routeid character varying(64) NOT NULL,
+ gwlist character varying(255) NOT NULL,
+ description character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.dr_rules OWNER TO kamailio;
+
+--
+-- Name: dr_rules_ruleid_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.dr_rules_ruleid_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.dr_rules_ruleid_seq OWNER TO kamailio;
+
+--
+-- Name: dr_rules_ruleid_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.dr_rules_ruleid_seq OWNED BY public.dr_rules.ruleid;
+
+
+--
+-- Name: event_list; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.event_list (
+ event character varying(25) NOT NULL
+);
+
+
+ALTER TABLE public.event_list OWNER TO kamailio;
+
+--
+-- Name: globalblacklist; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.globalblacklist (
+ id integer NOT NULL,
+ prefix character varying(64) DEFAULT ''::character varying NOT NULL,
+ whitelist smallint DEFAULT 0 NOT NULL,
+ description character varying(255) DEFAULT NULL::character varying
+);
+
+
+ALTER TABLE public.globalblacklist OWNER TO kamailio;
+
+--
+-- Name: globalblacklist_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.globalblacklist_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.globalblacklist_id_seq OWNER TO kamailio;
+
+--
+-- Name: globalblacklist_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.globalblacklist_id_seq OWNED BY public.globalblacklist.id;
+
+
+--
+-- Name: grp; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.grp (
+ id integer NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ grp character varying(64) DEFAULT ''::character varying NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.grp OWNER TO kamailio;
+
+--
+-- Name: grp_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.grp_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.grp_id_seq OWNER TO kamailio;
+
+--
+-- Name: grp_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.grp_id_seq OWNED BY public.grp.id;
+
+
+--
+-- Name: htable; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.htable (
+ id integer NOT NULL,
+ key_name character varying(64) DEFAULT ''::character varying NOT NULL,
+ key_type integer DEFAULT 0 NOT NULL,
+ value_type integer DEFAULT 0 NOT NULL,
+ key_value character varying(128) DEFAULT ''::character varying NOT NULL,
+ expires integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.htable OWNER TO kamailio;
+
+--
+-- Name: htable_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.htable_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.htable_id_seq OWNER TO kamailio;
+
+--
+-- Name: htable_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.htable_id_seq OWNED BY public.htable.id;
+
+
+--
+-- Name: imc_members; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.imc_members (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ domain character varying(64) NOT NULL,
+ room character varying(64) NOT NULL,
+ flag integer NOT NULL
+);
+
+
+ALTER TABLE public.imc_members OWNER TO kamailio;
+
+--
+-- Name: imc_members_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.imc_members_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.imc_members_id_seq OWNER TO kamailio;
+
+--
+-- Name: imc_members_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.imc_members_id_seq OWNED BY public.imc_members.id;
+
+
+--
+-- Name: imc_rooms; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.imc_rooms (
+ id integer NOT NULL,
+ name character varying(64) NOT NULL,
+ domain character varying(64) NOT NULL,
+ flag integer NOT NULL
+);
+
+
+ALTER TABLE public.imc_rooms OWNER TO kamailio;
+
+--
+-- Name: imc_rooms_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.imc_rooms_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.imc_rooms_id_seq OWNER TO kamailio;
+
+--
+-- Name: imc_rooms_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.imc_rooms_id_seq OWNED BY public.imc_rooms.id;
+
+
+--
+-- Name: lcr_gw; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.lcr_gw (
+ id integer NOT NULL,
+ lcr_id smallint NOT NULL,
+ gw_name character varying(128),
+ ip_addr character varying(50),
+ hostname character varying(64),
+ port smallint,
+ params character varying(64),
+ uri_scheme smallint,
+ transport smallint,
+ strip smallint,
+ prefix character varying(16) DEFAULT NULL::character varying,
+ tag character varying(64) DEFAULT NULL::character varying,
+ flags integer DEFAULT 0 NOT NULL,
+ defunct integer
+);
+
+
+ALTER TABLE public.lcr_gw OWNER TO kamailio;
+
+--
+-- Name: lcr_gw_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.lcr_gw_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.lcr_gw_id_seq OWNER TO kamailio;
+
+--
+-- Name: lcr_gw_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.lcr_gw_id_seq OWNED BY public.lcr_gw.id;
+
+
+--
+-- Name: lcr_rule; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.lcr_rule (
+ id integer NOT NULL,
+ lcr_id smallint NOT NULL,
+ prefix character varying(16) DEFAULT NULL::character varying,
+ from_uri character varying(64) DEFAULT NULL::character varying,
+ request_uri character varying(64) DEFAULT NULL::character varying,
+ mt_tvalue character varying(128) DEFAULT NULL::character varying,
+ stopper integer DEFAULT 0 NOT NULL,
+ enabled integer DEFAULT 1 NOT NULL
+);
+
+
+ALTER TABLE public.lcr_rule OWNER TO kamailio;
+
+--
+-- Name: lcr_rule_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.lcr_rule_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.lcr_rule_id_seq OWNER TO kamailio;
+
+--
+-- Name: lcr_rule_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.lcr_rule_id_seq OWNED BY public.lcr_rule.id;
+
+
+--
+-- Name: lcr_rule_target; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.lcr_rule_target (
+ id integer NOT NULL,
+ lcr_id smallint NOT NULL,
+ rule_id integer NOT NULL,
+ gw_id integer NOT NULL,
+ priority smallint NOT NULL,
+ weight integer DEFAULT 1 NOT NULL
+);
+
+
+ALTER TABLE public.lcr_rule_target OWNER TO kamailio;
+
+--
+-- Name: lcr_rule_target_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.lcr_rule_target_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.lcr_rule_target_id_seq OWNER TO kamailio;
+
+--
+-- Name: lcr_rule_target_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.lcr_rule_target_id_seq OWNED BY public.lcr_rule_target.id;
+
+
+--
+-- Name: location; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.location (
+ id integer NOT NULL,
+ ruid character varying(64) DEFAULT ''::character varying NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT NULL::character varying,
+ contact character varying(512) DEFAULT ''::character varying NOT NULL,
+ received character varying(128) DEFAULT NULL::character varying,
+ path character varying(512) DEFAULT NULL::character varying,
+ expires timestamp without time zone DEFAULT '2030-05-28 21:32:15'::timestamp without time zone NOT NULL,
+ q real DEFAULT 1.0 NOT NULL,
+ callid character varying(255) DEFAULT 'Default-Call-ID'::character varying NOT NULL,
+ cseq integer DEFAULT 1 NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ cflags integer DEFAULT 0 NOT NULL,
+ user_agent character varying(255) DEFAULT ''::character varying NOT NULL,
+ socket character varying(64) DEFAULT NULL::character varying,
+ methods integer,
+ instance character varying(255) DEFAULT NULL::character varying,
+ reg_id integer DEFAULT 0 NOT NULL,
+ server_id integer DEFAULT 0 NOT NULL,
+ connection_id integer DEFAULT 0 NOT NULL,
+ keepalive integer DEFAULT 0 NOT NULL,
+ partition integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.location OWNER TO kamailio;
+
+--
+-- Name: location_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.location_attrs (
+ id integer NOT NULL,
+ ruid character varying(64) DEFAULT ''::character varying NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT NULL::character varying,
+ aname character varying(64) DEFAULT ''::character varying NOT NULL,
+ atype integer DEFAULT 0 NOT NULL,
+ avalue character varying(512) DEFAULT ''::character varying NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.location_attrs OWNER TO kamailio;
+
+--
+-- Name: location_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.location_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.location_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: location_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.location_attrs_id_seq OWNED BY public.location_attrs.id;
+
+
+--
+-- Name: location_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.location_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.location_id_seq OWNER TO kamailio;
+
+--
+-- Name: location_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.location_id_seq OWNED BY public.location.id;
+
+
+--
+-- Name: matrix; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.matrix (
+ first integer NOT NULL,
+ second smallint NOT NULL,
+ res integer NOT NULL
+);
+
+
+ALTER TABLE public.matrix OWNER TO kamailio;
+
+--
+-- Name: missed_calls; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.missed_calls (
+ id integer NOT NULL,
+ method character varying(16) DEFAULT ''::character varying NOT NULL,
+ from_tag character varying(64) DEFAULT ''::character varying NOT NULL,
+ to_tag character varying(64) DEFAULT ''::character varying NOT NULL,
+ callid character varying(255) DEFAULT ''::character varying NOT NULL,
+ sip_code character varying(3) DEFAULT ''::character varying NOT NULL,
+ sip_reason character varying(128) DEFAULT ''::character varying NOT NULL,
+ "time" timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.missed_calls OWNER TO kamailio;
+
+--
+-- Name: missed_calls_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.missed_calls_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.missed_calls_id_seq OWNER TO kamailio;
+
+--
+-- Name: missed_calls_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.missed_calls_id_seq OWNED BY public.missed_calls.id;
+
+
+--
+-- Name: mohqcalls; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.mohqcalls (
+ id integer NOT NULL,
+ mohq_id integer NOT NULL,
+ call_id character varying(100) NOT NULL,
+ call_status integer NOT NULL,
+ call_from character varying(100) NOT NULL,
+ call_contact character varying(100),
+ call_time timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.mohqcalls OWNER TO kamailio;
+
+--
+-- Name: mohqcalls_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.mohqcalls_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.mohqcalls_id_seq OWNER TO kamailio;
+
+--
+-- Name: mohqcalls_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.mohqcalls_id_seq OWNED BY public.mohqcalls.id;
+
+
+--
+-- Name: mohqueues; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.mohqueues (
+ id integer NOT NULL,
+ name character varying(25) NOT NULL,
+ uri character varying(100) NOT NULL,
+ mohdir character varying(100),
+ mohfile character varying(100) NOT NULL,
+ debug integer NOT NULL
+);
+
+
+ALTER TABLE public.mohqueues OWNER TO kamailio;
+
+--
+-- Name: mohqueues_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.mohqueues_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.mohqueues_id_seq OWNER TO kamailio;
+
+--
+-- Name: mohqueues_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.mohqueues_id_seq OWNED BY public.mohqueues.id;
+
+
+--
+-- Name: mtree; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.mtree (
+ id integer NOT NULL,
+ tprefix character varying(32) DEFAULT ''::character varying NOT NULL,
+ tvalue character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.mtree OWNER TO kamailio;
+
+--
+-- Name: mtree_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.mtree_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.mtree_id_seq OWNER TO kamailio;
+
+--
+-- Name: mtree_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.mtree_id_seq OWNED BY public.mtree.id;
+
+
+--
+-- Name: mtrees; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.mtrees (
+ id integer NOT NULL,
+ tname character varying(128) DEFAULT ''::character varying NOT NULL,
+ tprefix character varying(32) DEFAULT ''::character varying NOT NULL,
+ tvalue character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.mtrees OWNER TO kamailio;
+
+--
+-- Name: mtrees_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.mtrees_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.mtrees_id_seq OWNER TO kamailio;
+
+--
+-- Name: mtrees_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.mtrees_id_seq OWNED BY public.mtrees.id;
+
+
+--
+-- Name: pdt; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.pdt (
+ id integer NOT NULL,
+ sdomain character varying(128) NOT NULL,
+ prefix character varying(32) NOT NULL,
+ domain character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.pdt OWNER TO kamailio;
+
+--
+-- Name: pdt_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.pdt_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.pdt_id_seq OWNER TO kamailio;
+
+--
+-- Name: pdt_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.pdt_id_seq OWNED BY public.pdt.id;
+
+
+--
+-- Name: pl_pipes; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.pl_pipes (
+ id integer NOT NULL,
+ pipeid character varying(64) DEFAULT ''::character varying NOT NULL,
+ algorithm character varying(32) DEFAULT ''::character varying NOT NULL,
+ plimit integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.pl_pipes OWNER TO kamailio;
+
+--
+-- Name: pl_pipes_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.pl_pipes_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.pl_pipes_id_seq OWNER TO kamailio;
+
+--
+-- Name: pl_pipes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.pl_pipes_id_seq OWNED BY public.pl_pipes.id;
+
+
+--
+-- Name: presentity; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.presentity (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ domain character varying(64) NOT NULL,
+ event character varying(64) NOT NULL,
+ etag character varying(128) NOT NULL,
+ expires integer NOT NULL,
+ received_time integer NOT NULL,
+ body bytea NOT NULL,
+ sender character varying(128) NOT NULL,
+ priority integer DEFAULT 0 NOT NULL,
+ ruid character varying(64)
+);
+
+
+ALTER TABLE public.presentity OWNER TO kamailio;
+
+--
+-- Name: presentities; Type: VIEW; Schema: public; Owner: kamailio
+--
+
+CREATE VIEW public.presentities AS
+ SELECT presentity.id,
+ ((('sip:'::text || (presentity.username)::text) || '@'::text) || (presentity.domain)::text) AS presentity_uri,
+ presentity.username,
+ presentity.domain,
+ presentity.event,
+ "substring"((presentity.etag)::text, 1, ("position"((presentity.etag)::text, '@'::text) - 1)) AS callid,
+ to_timestamp((presentity.received_time)::double precision) AS received,
+ to_timestamp((presentity.expires)::double precision) AS expire_date,
+ presentity.expires,
+ (presentity.sender)::character varying(30) AS sender,
+ lower(((
+ CASE
+ WHEN ((presentity.event)::text = 'dialog'::text) THEN "substring"(encode(presentity.body, 'escape'::text), ("position"(presentity.body, '\x3c73746174653e'::bytea) + 7), (("position"(presentity.body, '\x3c2f73746174653e'::bytea) - "position"(presentity.body, '\x3c73746174653e'::bytea)) - 7))
+ WHEN ((presentity.event)::text = 'presence'::text) THEN
+ CASE
+ WHEN ("position"(encode(presentity.body, 'escape'::text), ''::text) = 0) THEN replace("substring"(encode(presentity.body, 'escape'::text), ("position"(encode(presentity.body, 'escape'::text), ''::text) + 6), (("position"(encode(presentity.body, 'escape'::text), ''::text) - "position"(encode(presentity.body, 'escape'::text), ''::text)) - 6)), ' '::text, ''::text)
+ ELSE replace("substring"(encode(presentity.body, 'escape'::text), ("position"(encode(presentity.body, 'escape'::text), ''::text) + 9), (("position"(encode(presentity.body, 'escape'::text), ''::text) - "position"(encode(presentity.body, 'escape'::text), ''::text)) - 9)), ' '::text, ''::text)
+ END
+ WHEN ((presentity.event)::text = 'message-summary'::text) THEN
+ CASE
+ WHEN ("position"(encode(presentity.body, 'escape'::text), 'Messages-Waiting: yes'::text) = 0) THEN 'Waiting'::text
+ ELSE 'Not-Waiting'::text
+ END
+ ELSE NULL::text
+ END)::character varying(21))::text) AS state
+ FROM public.presentity;
+
+
+ALTER TABLE public.presentities OWNER TO kamailio;
+
+--
+-- Name: presentity_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.presentity_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.presentity_id_seq OWNER TO kamailio;
+
+--
+-- Name: presentity_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.presentity_id_seq OWNED BY public.presentity.id;
+
+
+--
+-- Name: pua; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.pua (
+ id integer NOT NULL,
+ pres_uri character varying(128) NOT NULL,
+ pres_id character varying(255) NOT NULL,
+ event integer NOT NULL,
+ expires integer NOT NULL,
+ desired_expires integer NOT NULL,
+ flag integer NOT NULL,
+ etag character varying(128) NOT NULL,
+ tuple_id character varying(64),
+ watcher_uri character varying(128) NOT NULL,
+ call_id character varying(255) NOT NULL,
+ to_tag character varying(64) NOT NULL,
+ from_tag character varying(64) NOT NULL,
+ cseq integer NOT NULL,
+ record_route text,
+ contact character varying(128) NOT NULL,
+ remote_contact character varying(128) NOT NULL,
+ version integer NOT NULL,
+ extra_headers text NOT NULL
+);
+
+
+ALTER TABLE public.pua OWNER TO kamailio;
+
+--
+-- Name: pua_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.pua_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.pua_id_seq OWNER TO kamailio;
+
+--
+-- Name: pua_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.pua_id_seq OWNED BY public.pua.id;
+
+
+--
+-- Name: purplemap; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.purplemap (
+ id integer NOT NULL,
+ sip_user character varying(128) NOT NULL,
+ ext_user character varying(128) NOT NULL,
+ ext_prot character varying(16) NOT NULL,
+ ext_pass character varying(64)
+);
+
+
+ALTER TABLE public.purplemap OWNER TO kamailio;
+
+--
+-- Name: purplemap_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.purplemap_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.purplemap_id_seq OWNER TO kamailio;
+
+--
+-- Name: purplemap_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.purplemap_id_seq OWNED BY public.purplemap.id;
+
+
+--
+-- Name: re_grp; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.re_grp (
+ id integer NOT NULL,
+ reg_exp character varying(128) DEFAULT ''::character varying NOT NULL,
+ group_id integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.re_grp OWNER TO kamailio;
+
+--
+-- Name: re_grp_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.re_grp_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.re_grp_id_seq OWNER TO kamailio;
+
+--
+-- Name: re_grp_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.re_grp_id_seq OWNED BY public.re_grp.id;
+
+
+--
+-- Name: rls_presentity; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.rls_presentity (
+ id integer NOT NULL,
+ rlsubs_did character varying(255) NOT NULL,
+ resource_uri character varying(128) NOT NULL,
+ content_type character varying(255) NOT NULL,
+ presence_state bytea NOT NULL,
+ expires integer NOT NULL,
+ updated integer NOT NULL,
+ auth_state integer NOT NULL,
+ reason character varying(64) NOT NULL
+);
+
+
+ALTER TABLE public.rls_presentity OWNER TO kamailio;
+
+--
+-- Name: rls_presentity_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.rls_presentity_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.rls_presentity_id_seq OWNER TO kamailio;
+
+--
+-- Name: rls_presentity_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.rls_presentity_id_seq OWNED BY public.rls_presentity.id;
+
+
+--
+-- Name: rls_watchers; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.rls_watchers (
+ id integer NOT NULL,
+ presentity_uri character varying(128) NOT NULL,
+ to_user character varying(64) NOT NULL,
+ to_domain character varying(64) NOT NULL,
+ watcher_username character varying(64) NOT NULL,
+ watcher_domain character varying(64) NOT NULL,
+ event character varying(64) DEFAULT 'presence'::character varying NOT NULL,
+ event_id character varying(64),
+ to_tag character varying(64) NOT NULL,
+ from_tag character varying(64) NOT NULL,
+ callid character varying(255) NOT NULL,
+ local_cseq integer NOT NULL,
+ remote_cseq integer NOT NULL,
+ contact character varying(128) NOT NULL,
+ record_route text,
+ expires integer NOT NULL,
+ status integer DEFAULT 2 NOT NULL,
+ reason character varying(64) NOT NULL,
+ version integer DEFAULT 0 NOT NULL,
+ socket_info character varying(64) NOT NULL,
+ local_contact character varying(128) NOT NULL,
+ from_user character varying(64) NOT NULL,
+ from_domain character varying(64) NOT NULL,
+ updated integer NOT NULL
+);
+
+
+ALTER TABLE public.rls_watchers OWNER TO kamailio;
+
+--
+-- Name: rls_watchers_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.rls_watchers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.rls_watchers_id_seq OWNER TO kamailio;
+
+--
+-- Name: rls_watchers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.rls_watchers_id_seq OWNED BY public.rls_watchers.id;
+
+
+--
+-- Name: rtpengine; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.rtpengine (
+ id integer NOT NULL,
+ setid integer DEFAULT 0 NOT NULL,
+ url character varying(64) NOT NULL,
+ weight integer DEFAULT 1 NOT NULL,
+ disabled integer DEFAULT 0 NOT NULL,
+ stamp timestamp without time zone DEFAULT '1900-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.rtpengine OWNER TO kamailio;
+
+--
+-- Name: rtpengine_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.rtpengine_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.rtpengine_id_seq OWNER TO kamailio;
+
+--
+-- Name: rtpengine_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.rtpengine_id_seq OWNED BY public.rtpengine.id;
+
+
+--
+-- Name: rtpproxy; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.rtpproxy (
+ id integer NOT NULL,
+ setid character varying(32) DEFAULT 0 NOT NULL,
+ url character varying(64) DEFAULT ''::character varying NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ weight integer DEFAULT 1 NOT NULL,
+ description character varying(64) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.rtpproxy OWNER TO kamailio;
+
+--
+-- Name: rtpproxy_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.rtpproxy_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.rtpproxy_id_seq OWNER TO kamailio;
+
+--
+-- Name: rtpproxy_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.rtpproxy_id_seq OWNED BY public.rtpproxy.id;
+
+
+--
+-- Name: sca_subscriptions; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.sca_subscriptions (
+ id integer NOT NULL,
+ subscriber character varying(255) NOT NULL,
+ aor character varying(255) NOT NULL,
+ event integer DEFAULT 0 NOT NULL,
+ expires integer DEFAULT 0 NOT NULL,
+ state integer DEFAULT 0 NOT NULL,
+ app_idx integer DEFAULT 0 NOT NULL,
+ call_id character varying(255) NOT NULL,
+ from_tag character varying(64) NOT NULL,
+ to_tag character varying(64) NOT NULL,
+ record_route text,
+ notify_cseq integer NOT NULL,
+ subscribe_cseq integer NOT NULL,
+ server_id integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.sca_subscriptions OWNER TO kamailio;
+
+--
+-- Name: sca_subscriptions_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.sca_subscriptions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.sca_subscriptions_id_seq OWNER TO kamailio;
+
+--
+-- Name: sca_subscriptions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.sca_subscriptions_id_seq OWNED BY public.sca_subscriptions.id;
+
+
+--
+-- Name: silo; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.silo (
+ id integer NOT NULL,
+ src_addr character varying(128) DEFAULT ''::character varying NOT NULL,
+ dst_addr character varying(128) DEFAULT ''::character varying NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ inc_time integer DEFAULT 0 NOT NULL,
+ exp_time integer DEFAULT 0 NOT NULL,
+ snd_time integer DEFAULT 0 NOT NULL,
+ ctype character varying(32) DEFAULT 'text/plain'::character varying NOT NULL,
+ body bytea,
+ extra_hdrs text,
+ callid character varying(128) DEFAULT ''::character varying NOT NULL,
+ status integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.silo OWNER TO kamailio;
+
+--
+-- Name: silo_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.silo_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.silo_id_seq OWNER TO kamailio;
+
+--
+-- Name: silo_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.silo_id_seq OWNED BY public.silo.id;
+
+
+--
+-- Name: sip_trace; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.sip_trace (
+ id integer NOT NULL,
+ time_stamp timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL,
+ time_us integer DEFAULT 0 NOT NULL,
+ callid character varying(255) DEFAULT ''::character varying NOT NULL,
+ traced_user character varying(128) DEFAULT ''::character varying NOT NULL,
+ msg text NOT NULL,
+ method character varying(50) DEFAULT ''::character varying NOT NULL,
+ status character varying(128) DEFAULT ''::character varying NOT NULL,
+ fromip character varying(50) DEFAULT ''::character varying NOT NULL,
+ toip character varying(50) DEFAULT ''::character varying NOT NULL,
+ fromtag character varying(64) DEFAULT ''::character varying NOT NULL,
+ totag character varying(64) DEFAULT ''::character varying NOT NULL,
+ direction character varying(4) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.sip_trace OWNER TO kamailio;
+
+--
+-- Name: sip_trace_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.sip_trace_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.sip_trace_id_seq OWNER TO kamailio;
+
+--
+-- Name: sip_trace_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.sip_trace_id_seq OWNED BY public.sip_trace.id;
+
+
+--
+-- Name: speed_dial; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.speed_dial (
+ id integer NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ sd_username character varying(64) DEFAULT ''::character varying NOT NULL,
+ sd_domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ new_uri character varying(128) DEFAULT ''::character varying NOT NULL,
+ fname character varying(64) DEFAULT ''::character varying NOT NULL,
+ lname character varying(64) DEFAULT ''::character varying NOT NULL,
+ description character varying(64) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.speed_dial OWNER TO kamailio;
+
+--
+-- Name: speed_dial_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.speed_dial_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.speed_dial_id_seq OWNER TO kamailio;
+
+--
+-- Name: speed_dial_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.speed_dial_id_seq OWNED BY public.speed_dial.id;
+
+
+--
+-- Name: subscriber; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.subscriber (
+ id integer NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ password character varying(64) DEFAULT ''::character varying NOT NULL,
+ ha1 character varying(128) DEFAULT ''::character varying NOT NULL,
+ ha1b character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.subscriber OWNER TO kamailio;
+
+--
+-- Name: subscriber_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.subscriber_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.subscriber_id_seq OWNER TO kamailio;
+
+--
+-- Name: subscriber_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.subscriber_id_seq OWNED BY public.subscriber.id;
+
+
+--
+-- Name: tmp_probe; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.tmp_probe (
+ event text,
+ presentity_uri text,
+ action integer
+);
+
+
+ALTER TABLE public.tmp_probe OWNER TO kamailio;
+
+--
+-- Name: topos_d; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.topos_d (
+ id integer NOT NULL,
+ rectime timestamp without time zone NOT NULL,
+ s_method character varying(64) DEFAULT ''::character varying NOT NULL,
+ s_cseq character varying(64) DEFAULT ''::character varying NOT NULL,
+ a_callid character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_uuid character varying(255) DEFAULT ''::character varying NOT NULL,
+ b_uuid character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ as_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ bs_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ a_tag character varying(255) DEFAULT ''::character varying NOT NULL,
+ b_tag character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_rr text,
+ b_rr text,
+ s_rr text,
+ iflags integer DEFAULT 0 NOT NULL,
+ a_uri character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_uri character varying(128) DEFAULT ''::character varying NOT NULL,
+ r_uri character varying(128) DEFAULT ''::character varying NOT NULL,
+ a_srcaddr character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_srcaddr character varying(128) DEFAULT ''::character varying NOT NULL,
+ a_socket character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_socket character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.topos_d OWNER TO kamailio;
+
+--
+-- Name: topos_d_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.topos_d_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.topos_d_id_seq OWNER TO kamailio;
+
+--
+-- Name: topos_d_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.topos_d_id_seq OWNED BY public.topos_d.id;
+
+
+--
+-- Name: topos_t; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.topos_t (
+ id integer NOT NULL,
+ rectime timestamp without time zone NOT NULL,
+ s_method character varying(64) DEFAULT ''::character varying NOT NULL,
+ s_cseq character varying(64) DEFAULT ''::character varying NOT NULL,
+ a_callid character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_uuid character varying(255) DEFAULT ''::character varying NOT NULL,
+ b_uuid character varying(255) DEFAULT ''::character varying NOT NULL,
+ direction integer DEFAULT 0 NOT NULL,
+ x_via text,
+ x_vbranch character varying(255) DEFAULT ''::character varying NOT NULL,
+ x_rr text,
+ y_rr text,
+ s_rr text,
+ x_uri character varying(128) DEFAULT ''::character varying NOT NULL,
+ a_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ as_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ bs_contact character varying(128) DEFAULT ''::character varying NOT NULL,
+ x_tag character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_tag character varying(255) DEFAULT ''::character varying NOT NULL,
+ b_tag character varying(255) DEFAULT ''::character varying NOT NULL,
+ a_srcaddr character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_srcaddr character varying(128) DEFAULT ''::character varying NOT NULL,
+ a_socket character varying(128) DEFAULT ''::character varying NOT NULL,
+ b_socket character varying(128) DEFAULT ''::character varying NOT NULL
+);
+
+
+ALTER TABLE public.topos_t OWNER TO kamailio;
+
+--
+-- Name: topos_t_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.topos_t_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.topos_t_id_seq OWNER TO kamailio;
+
+--
+-- Name: topos_t_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.topos_t_id_seq OWNED BY public.topos_t.id;
+
+
+--
+-- Name: trusted; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.trusted (
+ id integer NOT NULL,
+ src_ip character varying(50) NOT NULL,
+ proto character varying(4) NOT NULL,
+ from_pattern character varying(64) DEFAULT NULL::character varying,
+ ruri_pattern character varying(64) DEFAULT NULL::character varying,
+ tag character varying(64),
+ priority integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.trusted OWNER TO kamailio;
+
+--
+-- Name: trusted_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.trusted_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.trusted_id_seq OWNER TO kamailio;
+
+--
+-- Name: trusted_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.trusted_id_seq OWNED BY public.trusted.id;
+
+
+--
+-- Name: uacreg; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uacreg (
+ id integer NOT NULL,
+ l_uuid character varying(64) DEFAULT ''::character varying NOT NULL,
+ l_username character varying(64) DEFAULT ''::character varying NOT NULL,
+ l_domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ r_username character varying(64) DEFAULT ''::character varying NOT NULL,
+ r_domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ realm character varying(64) DEFAULT ''::character varying NOT NULL,
+ auth_username character varying(64) DEFAULT ''::character varying NOT NULL,
+ auth_password character varying(64) DEFAULT ''::character varying NOT NULL,
+ auth_ha1 character varying(128) DEFAULT ''::character varying NOT NULL,
+ auth_proxy character varying(128) DEFAULT ''::character varying NOT NULL,
+ expires integer DEFAULT 0 NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ reg_delay integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.uacreg OWNER TO kamailio;
+
+--
+-- Name: uacreg_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uacreg_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uacreg_id_seq OWNER TO kamailio;
+
+--
+-- Name: uacreg_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uacreg_id_seq OWNED BY public.uacreg.id;
+
+
+--
+-- Name: uid_credentials; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_credentials (
+ id integer NOT NULL,
+ auth_username character varying(64) NOT NULL,
+ did character varying(64) DEFAULT '_default'::character varying NOT NULL,
+ realm character varying(64) NOT NULL,
+ password character varying(28) DEFAULT ''::character varying NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ ha1 character varying(32) NOT NULL,
+ ha1b character varying(32) DEFAULT ''::character varying NOT NULL,
+ uid character varying(64) NOT NULL
+);
+
+
+ALTER TABLE public.uid_credentials OWNER TO kamailio;
+
+--
+-- Name: uid_credentials_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_credentials_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_credentials_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_credentials_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_credentials_id_seq OWNED BY public.uid_credentials.id;
+
+
+--
+-- Name: uid_domain; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_domain (
+ id integer NOT NULL,
+ did character varying(64) NOT NULL,
+ domain character varying(64) NOT NULL,
+ flags integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.uid_domain OWNER TO kamailio;
+
+--
+-- Name: uid_domain_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_domain_attrs (
+ id integer NOT NULL,
+ did character varying(64),
+ name character varying(32) NOT NULL,
+ type integer DEFAULT 0 NOT NULL,
+ value character varying(128),
+ flags integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.uid_domain_attrs OWNER TO kamailio;
+
+--
+-- Name: uid_domain_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_domain_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_domain_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_domain_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_domain_attrs_id_seq OWNED BY public.uid_domain_attrs.id;
+
+
+--
+-- Name: uid_domain_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_domain_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_domain_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_domain_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_domain_id_seq OWNED BY public.uid_domain.id;
+
+
+--
+-- Name: uid_global_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_global_attrs (
+ id integer NOT NULL,
+ name character varying(32) NOT NULL,
+ type integer DEFAULT 0 NOT NULL,
+ value character varying(128),
+ flags integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.uid_global_attrs OWNER TO kamailio;
+
+--
+-- Name: uid_global_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_global_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_global_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_global_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_global_attrs_id_seq OWNED BY public.uid_global_attrs.id;
+
+
+--
+-- Name: uid_uri; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_uri (
+ id integer NOT NULL,
+ uid character varying(64) NOT NULL,
+ did character varying(64) NOT NULL,
+ username character varying(64) NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ scheme character varying(8) DEFAULT 'sip'::character varying NOT NULL
+);
+
+
+ALTER TABLE public.uid_uri OWNER TO kamailio;
+
+--
+-- Name: uid_uri_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_uri_attrs (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ did character varying(64) NOT NULL,
+ name character varying(32) NOT NULL,
+ value character varying(128),
+ type integer DEFAULT 0 NOT NULL,
+ flags integer DEFAULT 0 NOT NULL,
+ scheme character varying(8) DEFAULT 'sip'::character varying NOT NULL
+);
+
+
+ALTER TABLE public.uid_uri_attrs OWNER TO kamailio;
+
+--
+-- Name: uid_uri_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_uri_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_uri_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_uri_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_uri_attrs_id_seq OWNED BY public.uid_uri_attrs.id;
+
+
+--
+-- Name: uid_uri_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_uri_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_uri_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_uri_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_uri_id_seq OWNED BY public.uid_uri.id;
+
+
+--
+-- Name: uid_user_attrs; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uid_user_attrs (
+ id integer NOT NULL,
+ uid character varying(64) NOT NULL,
+ name character varying(32) NOT NULL,
+ value character varying(128),
+ type integer DEFAULT 0 NOT NULL,
+ flags integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.uid_user_attrs OWNER TO kamailio;
+
+--
+-- Name: uid_user_attrs_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uid_user_attrs_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uid_user_attrs_id_seq OWNER TO kamailio;
+
+--
+-- Name: uid_user_attrs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uid_user_attrs_id_seq OWNED BY public.uid_user_attrs.id;
+
+
+--
+-- Name: uri; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.uri (
+ id integer NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ uri_user character varying(64) DEFAULT ''::character varying NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.uri OWNER TO kamailio;
+
+--
+-- Name: uri_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.uri_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.uri_id_seq OWNER TO kamailio;
+
+--
+-- Name: uri_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.uri_id_seq OWNED BY public.uri.id;
+
+
+--
+-- Name: userblacklist; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.userblacklist (
+ id integer NOT NULL,
+ username character varying(64) DEFAULT ''::character varying NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ prefix character varying(64) DEFAULT ''::character varying NOT NULL,
+ whitelist smallint DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.userblacklist OWNER TO kamailio;
+
+--
+-- Name: userblacklist_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.userblacklist_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.userblacklist_id_seq OWNER TO kamailio;
+
+--
+-- Name: userblacklist_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.userblacklist_id_seq OWNED BY public.userblacklist.id;
+
+
+--
+-- Name: usr_preferences; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.usr_preferences (
+ id integer NOT NULL,
+ uuid character varying(64) DEFAULT ''::character varying NOT NULL,
+ username character varying(128) DEFAULT 0 NOT NULL,
+ domain character varying(64) DEFAULT ''::character varying NOT NULL,
+ attribute character varying(32) DEFAULT ''::character varying NOT NULL,
+ type integer DEFAULT 0 NOT NULL,
+ value character varying(128) DEFAULT ''::character varying NOT NULL,
+ last_modified timestamp without time zone DEFAULT '2000-01-01 00:00:01'::timestamp without time zone NOT NULL
+);
+
+
+ALTER TABLE public.usr_preferences OWNER TO kamailio;
+
+--
+-- Name: usr_preferences_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.usr_preferences_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.usr_preferences_id_seq OWNER TO kamailio;
+
+--
+-- Name: usr_preferences_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.usr_preferences_id_seq OWNED BY public.usr_preferences.id;
+
+
+--
+-- Name: version; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.version (
+ table_name character varying(32) NOT NULL,
+ table_version integer DEFAULT 0 NOT NULL
+);
+
+
+ALTER TABLE public.version OWNER TO kamailio;
+
+--
+-- Name: watchers; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.watchers (
+ id integer NOT NULL,
+ presentity_uri character varying(128) NOT NULL,
+ watcher_username character varying(64) NOT NULL,
+ watcher_domain character varying(64) NOT NULL,
+ event character varying(64) DEFAULT 'presence'::character varying NOT NULL,
+ status integer NOT NULL,
+ reason character varying(64),
+ inserted_time integer NOT NULL
+);
+
+
+ALTER TABLE public.watchers OWNER TO kamailio;
+
+--
+-- Name: watchers_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.watchers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.watchers_id_seq OWNER TO kamailio;
+
+--
+-- Name: watchers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.watchers_id_seq OWNED BY public.watchers.id;
+
+
+--
+-- Name: xcap; Type: TABLE; Schema: public; Owner: kamailio
+--
+
+CREATE TABLE public.xcap (
+ id integer NOT NULL,
+ username character varying(64) NOT NULL,
+ domain character varying(64) NOT NULL,
+ doc bytea NOT NULL,
+ doc_type integer NOT NULL,
+ etag character varying(128) NOT NULL,
+ source integer NOT NULL,
+ doc_uri character varying(255) NOT NULL,
+ port integer NOT NULL
+);
+
+
+ALTER TABLE public.xcap OWNER TO kamailio;
+
+--
+-- Name: xcap_id_seq; Type: SEQUENCE; Schema: public; Owner: kamailio
+--
+
+CREATE SEQUENCE public.xcap_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+ALTER TABLE public.xcap_id_seq OWNER TO kamailio;
+
+--
+-- Name: xcap_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: kamailio
+--
+
+ALTER SEQUENCE public.xcap_id_seq OWNED BY public.xcap.id;
+
+
+--
+-- Name: acc id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.acc ALTER COLUMN id SET DEFAULT nextval('public.acc_id_seq'::regclass);
+
+
+--
+-- Name: acc_cdrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.acc_cdrs ALTER COLUMN id SET DEFAULT nextval('public.acc_cdrs_id_seq'::regclass);
+
+
+--
+-- Name: active_watchers id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers ALTER COLUMN id SET DEFAULT nextval('public.active_watchers_id_seq'::regclass);
+
+
+--
+-- Name: active_watchers_log id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers_log ALTER COLUMN id SET DEFAULT nextval('public.active_watchers_log_id_seq'::regclass);
+
+
+--
+-- Name: address id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.address ALTER COLUMN id SET DEFAULT nextval('public.address_id_seq'::regclass);
+
+
+--
+-- Name: aliases id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.aliases ALTER COLUMN id SET DEFAULT nextval('public.aliases_id_seq'::regclass);
+
+
+--
+-- Name: carrier_name id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrier_name ALTER COLUMN id SET DEFAULT nextval('public.carrier_name_id_seq'::regclass);
+
+
+--
+-- Name: carrierfailureroute id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrierfailureroute ALTER COLUMN id SET DEFAULT nextval('public.carrierfailureroute_id_seq'::regclass);
+
+
+--
+-- Name: carrierroute id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrierroute ALTER COLUMN id SET DEFAULT nextval('public.carrierroute_id_seq'::regclass);
+
+
+--
+-- Name: cpl id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.cpl ALTER COLUMN id SET DEFAULT nextval('public.cpl_id_seq'::regclass);
+
+
+--
+-- Name: dbaliases id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dbaliases ALTER COLUMN id SET DEFAULT nextval('public.dbaliases_id_seq'::regclass);
+
+
+--
+-- Name: dialog id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialog ALTER COLUMN id SET DEFAULT nextval('public.dialog_id_seq'::regclass);
+
+
+--
+-- Name: dialog_vars id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialog_vars ALTER COLUMN id SET DEFAULT nextval('public.dialog_vars_id_seq'::regclass);
+
+
+--
+-- Name: dialplan id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialplan ALTER COLUMN id SET DEFAULT nextval('public.dialplan_id_seq'::regclass);
+
+
+--
+-- Name: dispatcher id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dispatcher ALTER COLUMN id SET DEFAULT nextval('public.dispatcher_id_seq'::regclass);
+
+
+--
+-- Name: domain id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain ALTER COLUMN id SET DEFAULT nextval('public.domain_id_seq'::regclass);
+
+
+--
+-- Name: domain_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain_attrs ALTER COLUMN id SET DEFAULT nextval('public.domain_attrs_id_seq'::regclass);
+
+
+--
+-- Name: domain_name id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain_name ALTER COLUMN id SET DEFAULT nextval('public.domain_name_id_seq'::regclass);
+
+
+--
+-- Name: domainpolicy id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domainpolicy ALTER COLUMN id SET DEFAULT nextval('public.domainpolicy_id_seq'::regclass);
+
+
+--
+-- Name: dr_gateways gwid; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_gateways ALTER COLUMN gwid SET DEFAULT nextval('public.dr_gateways_gwid_seq'::regclass);
+
+
+--
+-- Name: dr_groups id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_groups ALTER COLUMN id SET DEFAULT nextval('public.dr_groups_id_seq'::regclass);
+
+
+--
+-- Name: dr_gw_lists id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_gw_lists ALTER COLUMN id SET DEFAULT nextval('public.dr_gw_lists_id_seq'::regclass);
+
+
+--
+-- Name: dr_rules ruleid; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_rules ALTER COLUMN ruleid SET DEFAULT nextval('public.dr_rules_ruleid_seq'::regclass);
+
+
+--
+-- Name: globalblacklist id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.globalblacklist ALTER COLUMN id SET DEFAULT nextval('public.globalblacklist_id_seq'::regclass);
+
+
+--
+-- Name: grp id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.grp ALTER COLUMN id SET DEFAULT nextval('public.grp_id_seq'::regclass);
+
+
+--
+-- Name: htable id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.htable ALTER COLUMN id SET DEFAULT nextval('public.htable_id_seq'::regclass);
+
+
+--
+-- Name: imc_members id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_members ALTER COLUMN id SET DEFAULT nextval('public.imc_members_id_seq'::regclass);
+
+
+--
+-- Name: imc_rooms id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_rooms ALTER COLUMN id SET DEFAULT nextval('public.imc_rooms_id_seq'::regclass);
+
+
+--
+-- Name: lcr_gw id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_gw ALTER COLUMN id SET DEFAULT nextval('public.lcr_gw_id_seq'::regclass);
+
+
+--
+-- Name: lcr_rule id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule ALTER COLUMN id SET DEFAULT nextval('public.lcr_rule_id_seq'::regclass);
+
+
+--
+-- Name: lcr_rule_target id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule_target ALTER COLUMN id SET DEFAULT nextval('public.lcr_rule_target_id_seq'::regclass);
+
+
+--
+-- Name: location id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.location ALTER COLUMN id SET DEFAULT nextval('public.location_id_seq'::regclass);
+
+
+--
+-- Name: location_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.location_attrs ALTER COLUMN id SET DEFAULT nextval('public.location_attrs_id_seq'::regclass);
+
+
+--
+-- Name: missed_calls id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.missed_calls ALTER COLUMN id SET DEFAULT nextval('public.missed_calls_id_seq'::regclass);
+
+
+--
+-- Name: mohqcalls id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqcalls ALTER COLUMN id SET DEFAULT nextval('public.mohqcalls_id_seq'::regclass);
+
+
+--
+-- Name: mohqueues id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqueues ALTER COLUMN id SET DEFAULT nextval('public.mohqueues_id_seq'::regclass);
+
+
+--
+-- Name: mtree id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtree ALTER COLUMN id SET DEFAULT nextval('public.mtree_id_seq'::regclass);
+
+
+--
+-- Name: mtrees id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtrees ALTER COLUMN id SET DEFAULT nextval('public.mtrees_id_seq'::regclass);
+
+
+--
+-- Name: pdt id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pdt ALTER COLUMN id SET DEFAULT nextval('public.pdt_id_seq'::regclass);
+
+
+--
+-- Name: pl_pipes id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pl_pipes ALTER COLUMN id SET DEFAULT nextval('public.pl_pipes_id_seq'::regclass);
+
+
+--
+-- Name: presentity id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.presentity ALTER COLUMN id SET DEFAULT nextval('public.presentity_id_seq'::regclass);
+
+
+--
+-- Name: pua id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pua ALTER COLUMN id SET DEFAULT nextval('public.pua_id_seq'::regclass);
+
+
+--
+-- Name: purplemap id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.purplemap ALTER COLUMN id SET DEFAULT nextval('public.purplemap_id_seq'::regclass);
+
+
+--
+-- Name: re_grp id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.re_grp ALTER COLUMN id SET DEFAULT nextval('public.re_grp_id_seq'::regclass);
+
+
+--
+-- Name: rls_presentity id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_presentity ALTER COLUMN id SET DEFAULT nextval('public.rls_presentity_id_seq'::regclass);
+
+
+--
+-- Name: rls_watchers id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_watchers ALTER COLUMN id SET DEFAULT nextval('public.rls_watchers_id_seq'::regclass);
+
+
+--
+-- Name: rtpengine id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rtpengine ALTER COLUMN id SET DEFAULT nextval('public.rtpengine_id_seq'::regclass);
+
+
+--
+-- Name: rtpproxy id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rtpproxy ALTER COLUMN id SET DEFAULT nextval('public.rtpproxy_id_seq'::regclass);
+
+
+--
+-- Name: sca_subscriptions id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.sca_subscriptions ALTER COLUMN id SET DEFAULT nextval('public.sca_subscriptions_id_seq'::regclass);
+
+
+--
+-- Name: silo id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.silo ALTER COLUMN id SET DEFAULT nextval('public.silo_id_seq'::regclass);
+
+
+--
+-- Name: sip_trace id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.sip_trace ALTER COLUMN id SET DEFAULT nextval('public.sip_trace_id_seq'::regclass);
+
+
+--
+-- Name: speed_dial id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.speed_dial ALTER COLUMN id SET DEFAULT nextval('public.speed_dial_id_seq'::regclass);
+
+
+--
+-- Name: subscriber id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.subscriber ALTER COLUMN id SET DEFAULT nextval('public.subscriber_id_seq'::regclass);
+
+
+--
+-- Name: topos_d id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.topos_d ALTER COLUMN id SET DEFAULT nextval('public.topos_d_id_seq'::regclass);
+
+
+--
+-- Name: topos_t id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.topos_t ALTER COLUMN id SET DEFAULT nextval('public.topos_t_id_seq'::regclass);
+
+
+--
+-- Name: trusted id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.trusted ALTER COLUMN id SET DEFAULT nextval('public.trusted_id_seq'::regclass);
+
+
+--
+-- Name: uacreg id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uacreg ALTER COLUMN id SET DEFAULT nextval('public.uacreg_id_seq'::regclass);
+
+
+--
+-- Name: uid_credentials id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_credentials ALTER COLUMN id SET DEFAULT nextval('public.uid_credentials_id_seq'::regclass);
+
+
+--
+-- Name: uid_domain id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain ALTER COLUMN id SET DEFAULT nextval('public.uid_domain_id_seq'::regclass);
+
+
+--
+-- Name: uid_domain_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain_attrs ALTER COLUMN id SET DEFAULT nextval('public.uid_domain_attrs_id_seq'::regclass);
+
+
+--
+-- Name: uid_global_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_global_attrs ALTER COLUMN id SET DEFAULT nextval('public.uid_global_attrs_id_seq'::regclass);
+
+
+--
+-- Name: uid_uri id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_uri ALTER COLUMN id SET DEFAULT nextval('public.uid_uri_id_seq'::regclass);
+
+
+--
+-- Name: uid_uri_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_uri_attrs ALTER COLUMN id SET DEFAULT nextval('public.uid_uri_attrs_id_seq'::regclass);
+
+
+--
+-- Name: uid_user_attrs id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_user_attrs ALTER COLUMN id SET DEFAULT nextval('public.uid_user_attrs_id_seq'::regclass);
+
+
+--
+-- Name: uri id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uri ALTER COLUMN id SET DEFAULT nextval('public.uri_id_seq'::regclass);
+
+
+--
+-- Name: userblacklist id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.userblacklist ALTER COLUMN id SET DEFAULT nextval('public.userblacklist_id_seq'::regclass);
+
+
+--
+-- Name: usr_preferences id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.usr_preferences ALTER COLUMN id SET DEFAULT nextval('public.usr_preferences_id_seq'::regclass);
+
+
+--
+-- Name: watchers id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.watchers ALTER COLUMN id SET DEFAULT nextval('public.watchers_id_seq'::regclass);
+
+
+--
+-- Name: xcap id; Type: DEFAULT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.xcap ALTER COLUMN id SET DEFAULT nextval('public.xcap_id_seq'::regclass);
+
+
+--
+-- Data for Name: acc; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.acc (id, method, from_tag, to_tag, callid, sip_code, sip_reason, "time") FROM stdin;
+\.
+
+
+--
+-- Data for Name: acc_cdrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.acc_cdrs (id, start_time, end_time, duration) FROM stdin;
+\.
+
+
+--
+-- Data for Name: active_watchers; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.active_watchers (id, presentity_uri, watcher_username, watcher_domain, to_user, to_domain, event, event_id, to_tag, from_tag, callid, local_cseq, remote_cseq, contact, record_route, expires, status, reason, version, socket_info, local_contact, from_user, from_domain, updated, updated_winfo, flags, user_agent) FROM stdin;
+\.
+
+
+--
+-- Data for Name: active_watchers_log; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.active_watchers_log (id, presentity_uri, watcher_username, watcher_domain, to_user, to_domain, event, callid, "time", result, sent_msg, received_msg, user_agent) FROM stdin;
+\.
+
+
+--
+-- Data for Name: address; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.address (id, grp, ip_addr, mask, port, tag) FROM stdin;
+\.
+
+
+--
+-- Data for Name: aliases; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.aliases (id, ruid, username, domain, contact, received, path, expires, q, callid, cseq, last_modified, flags, cflags, user_agent, socket, methods, instance, reg_id, server_id, connection_id, keepalive, partition) FROM stdin;
+\.
+
+
+--
+-- Data for Name: carrier_name; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.carrier_name (id, carrier) FROM stdin;
+\.
+
+
+--
+-- Data for Name: carrierfailureroute; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.carrierfailureroute (id, carrier, domain, scan_prefix, host_name, reply_code, flags, mask, next_domain, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: carrierroute; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.carrierroute (id, carrier, domain, scan_prefix, flags, mask, prob, strip, rewrite_host, rewrite_prefix, rewrite_suffix, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: cpl; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.cpl (id, username, domain, cpl_xml, cpl_bin) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dbaliases; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dbaliases (id, alias_username, alias_domain, username, domain) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dialog; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dialog (id, hash_entry, hash_id, callid, from_uri, from_tag, to_uri, to_tag, caller_cseq, callee_cseq, caller_route_set, callee_route_set, caller_contact, callee_contact, caller_sock, callee_sock, state, start_time, timeout, sflags, iflags, toroute_name, req_uri, xdata) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dialog_vars; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dialog_vars (id, hash_entry, hash_id, dialog_key, dialog_value) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dialplan; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dialplan (id, dpid, pr, match_op, match_exp, match_len, subst_exp, repl_exp, attrs) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dispatcher; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dispatcher (id, setid, destination, flags, priority, attrs, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: domain; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.domain (id, domain, did, last_modified) FROM stdin;
+\.
+
+
+--
+-- Data for Name: domain_attrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.domain_attrs (id, did, name, type, value, last_modified) FROM stdin;
+\.
+
+
+--
+-- Data for Name: domain_name; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.domain_name (id, domain) FROM stdin;
+\.
+
+
+--
+-- Data for Name: domainpolicy; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.domainpolicy (id, rule, type, att, val, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dr_gateways; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dr_gateways (gwid, type, address, strip, pri_prefix, attrs, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dr_groups; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dr_groups (id, username, domain, groupid, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dr_gw_lists; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dr_gw_lists (id, gwlist, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: dr_rules; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.dr_rules (ruleid, groupid, prefix, timerec, priority, routeid, gwlist, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: event_list; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.event_list (event) FROM stdin;
+dialog
+presence
+message-summary
+\.
+
+
+--
+-- Data for Name: globalblacklist; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.globalblacklist (id, prefix, whitelist, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: grp; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.grp (id, username, domain, grp, last_modified) FROM stdin;
+\.
+
+
+--
+-- Data for Name: htable; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.htable (id, key_name, key_type, value_type, key_value, expires) FROM stdin;
+\.
+
+
+--
+-- Data for Name: imc_members; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.imc_members (id, username, domain, room, flag) FROM stdin;
+\.
+
+
+--
+-- Data for Name: imc_rooms; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.imc_rooms (id, name, domain, flag) FROM stdin;
+\.
+
+
+--
+-- Data for Name: lcr_gw; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.lcr_gw (id, lcr_id, gw_name, ip_addr, hostname, port, params, uri_scheme, transport, strip, prefix, tag, flags, defunct) FROM stdin;
+\.
+
+
+--
+-- Data for Name: lcr_rule; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.lcr_rule (id, lcr_id, prefix, from_uri, request_uri, mt_tvalue, stopper, enabled) FROM stdin;
+\.
+
+
+--
+-- Data for Name: lcr_rule_target; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.lcr_rule_target (id, lcr_id, rule_id, gw_id, priority, weight) FROM stdin;
+\.
+
+
+--
+-- Data for Name: location; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.location (id, ruid, username, domain, contact, received, path, expires, q, callid, cseq, last_modified, flags, cflags, user_agent, socket, methods, instance, reg_id, server_id, connection_id, keepalive, partition) FROM stdin;
+\.
+
+
+--
+-- Data for Name: matrix; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.matrix (first, second, res) FROM stdin;
+\.
+
+
+--
+-- Data for Name: missed_calls; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.missed_calls (id, method, from_tag, to_tag, callid, sip_code, sip_reason, "time") FROM stdin;
+\.
+
+
+--
+-- Data for Name: mohqcalls; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.mohqcalls (id, mohq_id, call_id, call_status, call_from, call_contact, call_time) FROM stdin;
+\.
+
+
+--
+-- Data for Name: mohqueues; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.mohqueues (id, name, uri, mohdir, mohfile, debug) FROM stdin;
+\.
+
+
+--
+-- Data for Name: mtree; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.mtree (id, tprefix, tvalue) FROM stdin;
+\.
+
+
+--
+-- Data for Name: mtrees; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.mtrees (id, tname, tprefix, tvalue) FROM stdin;
+\.
+
+
+--
+-- Data for Name: pdt; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.pdt (id, sdomain, prefix, domain) FROM stdin;
+\.
+
+
+--
+-- Data for Name: pl_pipes; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.pl_pipes (id, pipeid, algorithm, plimit) FROM stdin;
+\.
+
+
+--
+-- Data for Name: presentity; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.presentity (id, username, domain, event, etag, expires, received_time, body, sender, priority, ruid) FROM stdin;
+\.
+
+
+--
+-- Data for Name: pua; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.pua (id, pres_uri, pres_id, event, expires, desired_expires, flag, etag, tuple_id, watcher_uri, call_id, to_tag, from_tag, cseq, record_route, contact, remote_contact, version, extra_headers) FROM stdin;
+\.
+
+
+--
+-- Data for Name: purplemap; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.purplemap (id, sip_user, ext_user, ext_prot, ext_pass) FROM stdin;
+\.
+
+
+--
+-- Data for Name: re_grp; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.re_grp (id, reg_exp, group_id) FROM stdin;
+\.
+
+
+--
+-- Data for Name: rls_presentity; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.rls_presentity (id, rlsubs_did, resource_uri, content_type, presence_state, expires, updated, auth_state, reason) FROM stdin;
+\.
+
+
+--
+-- Data for Name: rls_watchers; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.rls_watchers (id, presentity_uri, to_user, to_domain, watcher_username, watcher_domain, event, event_id, to_tag, from_tag, callid, local_cseq, remote_cseq, contact, record_route, expires, status, reason, version, socket_info, local_contact, from_user, from_domain, updated) FROM stdin;
+\.
+
+
+--
+-- Data for Name: rtpengine; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.rtpengine (id, setid, url, weight, disabled, stamp) FROM stdin;
+\.
+
+
+--
+-- Data for Name: rtpproxy; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.rtpproxy (id, setid, url, flags, weight, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: sca_subscriptions; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.sca_subscriptions (id, subscriber, aor, event, expires, state, app_idx, call_id, from_tag, to_tag, record_route, notify_cseq, subscribe_cseq, server_id) FROM stdin;
+\.
+
+
+--
+-- Data for Name: silo; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.silo (id, src_addr, dst_addr, username, domain, inc_time, exp_time, snd_time, ctype, body, extra_hdrs, callid, status) FROM stdin;
+\.
+
+
+--
+-- Data for Name: sip_trace; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.sip_trace (id, time_stamp, time_us, callid, traced_user, msg, method, status, fromip, toip, fromtag, totag, direction) FROM stdin;
+\.
+
+
+--
+-- Data for Name: speed_dial; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.speed_dial (id, username, domain, sd_username, sd_domain, new_uri, fname, lname, description) FROM stdin;
+\.
+
+
+--
+-- Data for Name: subscriber; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.subscriber (id, username, domain, password, ha1, ha1b) FROM stdin;
+\.
+
+
+--
+-- Data for Name: tmp_probe; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.tmp_probe (event, presentity_uri, action) FROM stdin;
+\.
+
+
+--
+-- Data for Name: topos_d; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.topos_d (id, rectime, s_method, s_cseq, a_callid, a_uuid, b_uuid, a_contact, b_contact, as_contact, bs_contact, a_tag, b_tag, a_rr, b_rr, s_rr, iflags, a_uri, b_uri, r_uri, a_srcaddr, b_srcaddr, a_socket, b_socket) FROM stdin;
+\.
+
+
+--
+-- Data for Name: topos_t; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.topos_t (id, rectime, s_method, s_cseq, a_callid, a_uuid, b_uuid, direction, x_via, x_vbranch, x_rr, y_rr, s_rr, x_uri, a_contact, b_contact, as_contact, bs_contact, x_tag, a_tag, b_tag, a_srcaddr, b_srcaddr, a_socket, b_socket) FROM stdin;
+\.
+
+
+--
+-- Data for Name: trusted; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.trusted (id, src_ip, proto, from_pattern, ruri_pattern, tag, priority) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uacreg; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uacreg (id, l_uuid, l_username, l_domain, r_username, r_domain, realm, auth_username, auth_password, auth_ha1, auth_proxy, expires, flags, reg_delay) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_credentials; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_credentials (id, auth_username, did, realm, password, flags, ha1, ha1b, uid) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_domain; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_domain (id, did, domain, flags) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_domain_attrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_domain_attrs (id, did, name, type, value, flags) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_global_attrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_global_attrs (id, name, type, value, flags) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_uri; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_uri (id, uid, did, username, flags, scheme) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_uri_attrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_uri_attrs (id, username, did, name, value, type, flags, scheme) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uid_user_attrs; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uid_user_attrs (id, uid, name, value, type, flags) FROM stdin;
+\.
+
+
+--
+-- Data for Name: uri; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.uri (id, username, domain, uri_user, last_modified) FROM stdin;
+\.
+
+
+--
+-- Data for Name: userblacklist; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.userblacklist (id, username, domain, prefix, whitelist) FROM stdin;
+\.
+
+
+--
+-- Data for Name: usr_preferences; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.usr_preferences (id, uuid, username, domain, attribute, type, value, last_modified) FROM stdin;
+\.
+
+
+--
+-- Data for Name: version; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.version (table_name, table_version) FROM stdin;
+version 1
+acc 5
+acc_cdrs 2
+missed_calls 4
+dbaliases 1
+subscriber 7
+usr_preferences 2
+carrierroute 3
+carrierfailureroute 2
+carrier_name 1
+domain_name 1
+cpl 1
+dialog 7
+dialog_vars 1
+dialplan 2
+dispatcher 4
+domain 2
+domain_attrs 1
+domainpolicy 2
+dr_gateways 3
+dr_rules 3
+dr_gw_lists 1
+dr_groups 2
+grp 2
+re_grp 1
+htable 2
+imc_rooms 1
+imc_members 1
+lcr_gw 3
+lcr_rule_target 1
+lcr_rule 3
+matrix 1
+mohqcalls 1
+mohqueues 1
+silo 8
+mtree 1
+mtrees 2
+pdt 1
+trusted 6
+address 6
+pl_pipes 1
+presentity 5
+active_watchers 12
+watchers 3
+xcap 4
+pua 7
+purplemap 1
+aliases 8
+rls_presentity 1
+rls_watchers 3
+rtpengine 1
+rtpproxy 1
+sca_subscriptions 2
+sip_trace 4
+speed_dial 2
+topos_d 1
+topos_t 1
+uacreg 3
+uid_credentials 7
+uid_user_attrs 3
+uid_domain 2
+uid_domain_attrs 1
+uid_global_attrs 1
+uid_uri 3
+uid_uri_attrs 2
+uri 1
+userblacklist 1
+globalblacklist 1
+location 9
+location_attrs 1
+event_list 1
+\.
+
+
+--
+-- Data for Name: watchers; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.watchers (id, presentity_uri, watcher_username, watcher_domain, event, status, reason, inserted_time) FROM stdin;
+\.
+
+
+--
+-- Data for Name: xcap; Type: TABLE DATA; Schema: public; Owner: kamailio
+--
+
+COPY public.xcap (id, username, domain, doc, doc_type, etag, source, doc_uri, port) FROM stdin;
+\.
+
+
+--
+-- Name: acc_cdrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.acc_cdrs_id_seq', 1, false);
+
+
+--
+-- Name: acc_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.acc_id_seq', 1, false);
+
+
+--
+-- Name: active_watchers_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.active_watchers_id_seq', 2526, true);
+
+
+--
+-- Name: active_watchers_log_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.active_watchers_log_id_seq', 672642, true);
+
+
+--
+-- Name: address_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.address_id_seq', 1, false);
+
+
+--
+-- Name: aliases_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.aliases_id_seq', 1, false);
+
+
+--
+-- Name: carrier_name_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.carrier_name_id_seq', 1, false);
+
+
+--
+-- Name: carrierfailureroute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.carrierfailureroute_id_seq', 1, false);
+
+
+--
+-- Name: carrierroute_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.carrierroute_id_seq', 1, false);
+
+
+--
+-- Name: cpl_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.cpl_id_seq', 1, false);
+
+
+--
+-- Name: dbaliases_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dbaliases_id_seq', 1, false);
+
+
+--
+-- Name: dialog_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dialog_id_seq', 1, false);
+
+
+--
+-- Name: dialog_vars_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dialog_vars_id_seq', 1, false);
+
+
+--
+-- Name: dialplan_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dialplan_id_seq', 1, false);
+
+
+--
+-- Name: dispatcher_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dispatcher_id_seq', 6, true);
+
+
+--
+-- Name: domain_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.domain_attrs_id_seq', 1, false);
+
+
+--
+-- Name: domain_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.domain_id_seq', 1, false);
+
+
+--
+-- Name: domain_name_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.domain_name_id_seq', 1, false);
+
+
+--
+-- Name: domainpolicy_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.domainpolicy_id_seq', 1, false);
+
+
+--
+-- Name: dr_gateways_gwid_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dr_gateways_gwid_seq', 1, false);
+
+
+--
+-- Name: dr_groups_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dr_groups_id_seq', 1, false);
+
+
+--
+-- Name: dr_gw_lists_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dr_gw_lists_id_seq', 1, false);
+
+
+--
+-- Name: dr_rules_ruleid_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.dr_rules_ruleid_seq', 1, false);
+
+
+--
+-- Name: globalblacklist_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.globalblacklist_id_seq', 1, false);
+
+
+--
+-- Name: grp_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.grp_id_seq', 1, false);
+
+
+--
+-- Name: htable_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.htable_id_seq', 1, false);
+
+
+--
+-- Name: imc_members_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.imc_members_id_seq', 1, false);
+
+
+--
+-- Name: imc_rooms_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.imc_rooms_id_seq', 1, false);
+
+
+--
+-- Name: lcr_gw_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.lcr_gw_id_seq', 1, false);
+
+
+--
+-- Name: lcr_rule_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.lcr_rule_id_seq', 1, false);
+
+
+--
+-- Name: lcr_rule_target_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.lcr_rule_target_id_seq', 1, false);
+
+
+--
+-- Name: location_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.location_attrs_id_seq', 299672, true);
+
+
+--
+-- Name: location_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.location_id_seq', 332, true);
+
+
+--
+-- Name: missed_calls_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.missed_calls_id_seq', 1, false);
+
+
+--
+-- Name: mohqcalls_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.mohqcalls_id_seq', 1, false);
+
+
+--
+-- Name: mohqueues_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.mohqueues_id_seq', 1, false);
+
+
+--
+-- Name: mtree_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.mtree_id_seq', 1, false);
+
+
+--
+-- Name: mtrees_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.mtrees_id_seq', 1, false);
+
+
+--
+-- Name: pdt_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.pdt_id_seq', 1, false);
+
+
+--
+-- Name: pl_pipes_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.pl_pipes_id_seq', 1, false);
+
+
+--
+-- Name: presentity_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.presentity_id_seq', 3284, true);
+
+
+--
+-- Name: pua_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.pua_id_seq', 1, false);
+
+
+--
+-- Name: purplemap_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.purplemap_id_seq', 1, false);
+
+
+--
+-- Name: re_grp_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.re_grp_id_seq', 1, false);
+
+
+--
+-- Name: rls_presentity_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.rls_presentity_id_seq', 1, false);
+
+
+--
+-- Name: rls_watchers_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.rls_watchers_id_seq', 1, false);
+
+
+--
+-- Name: rtpengine_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.rtpengine_id_seq', 1, false);
+
+
+--
+-- Name: rtpproxy_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.rtpproxy_id_seq', 1, false);
+
+
+--
+-- Name: sca_subscriptions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.sca_subscriptions_id_seq', 1, false);
+
+
+--
+-- Name: silo_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.silo_id_seq', 1, false);
+
+
+--
+-- Name: sip_trace_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.sip_trace_id_seq', 1, false);
+
+
+--
+-- Name: speed_dial_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.speed_dial_id_seq', 1, false);
+
+
+--
+-- Name: subscriber_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.subscriber_id_seq', 1, false);
+
+
+--
+-- Name: topos_d_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.topos_d_id_seq', 1, false);
+
+
+--
+-- Name: topos_t_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.topos_t_id_seq', 1, false);
+
+
+--
+-- Name: trusted_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.trusted_id_seq', 1, false);
+
+
+--
+-- Name: uacreg_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uacreg_id_seq', 1, false);
+
+
+--
+-- Name: uid_credentials_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_credentials_id_seq', 1, false);
+
+
+--
+-- Name: uid_domain_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_domain_attrs_id_seq', 1, false);
+
+
+--
+-- Name: uid_domain_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_domain_id_seq', 1, false);
+
+
+--
+-- Name: uid_global_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_global_attrs_id_seq', 1, false);
+
+
+--
+-- Name: uid_uri_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_uri_attrs_id_seq', 1, false);
+
+
+--
+-- Name: uid_uri_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_uri_id_seq', 1, false);
+
+
+--
+-- Name: uid_user_attrs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uid_user_attrs_id_seq', 1, false);
+
+
+--
+-- Name: uri_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.uri_id_seq', 1, false);
+
+
+--
+-- Name: userblacklist_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.userblacklist_id_seq', 1, false);
+
+
+--
+-- Name: usr_preferences_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.usr_preferences_id_seq', 1, false);
+
+
+--
+-- Name: watchers_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.watchers_id_seq', 1, false);
+
+
+--
+-- Name: xcap_id_seq; Type: SEQUENCE SET; Schema: public; Owner: kamailio
+--
+
+SELECT pg_catalog.setval('public.xcap_id_seq', 1, false);
+
+
+--
+-- Name: acc_cdrs acc_cdrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.acc_cdrs
+ ADD CONSTRAINT acc_cdrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: acc acc_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.acc
+ ADD CONSTRAINT acc_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: active_watchers active_watchers_active_watchers_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers
+ ADD CONSTRAINT active_watchers_active_watchers_idx UNIQUE (callid, to_tag, from_tag);
+
+
+--
+-- Name: active_watchers_log active_watchers_active_watchers_log_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers_log
+ ADD CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event);
+
+
+--
+-- Name: active_watchers_log active_watchers_log_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers_log
+ ADD CONSTRAINT active_watchers_log_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: active_watchers active_watchers_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.active_watchers
+ ADD CONSTRAINT active_watchers_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: address address_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.address
+ ADD CONSTRAINT address_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: aliases aliases_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.aliases
+ ADD CONSTRAINT aliases_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: aliases aliases_ruid_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.aliases
+ ADD CONSTRAINT aliases_ruid_idx UNIQUE (ruid);
+
+
+--
+-- Name: carrier_name carrier_name_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrier_name
+ ADD CONSTRAINT carrier_name_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: carrierfailureroute carrierfailureroute_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrierfailureroute
+ ADD CONSTRAINT carrierfailureroute_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: carrierroute carrierroute_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.carrierroute
+ ADD CONSTRAINT carrierroute_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: cpl cpl_account_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.cpl
+ ADD CONSTRAINT cpl_account_idx UNIQUE (username, domain);
+
+
+--
+-- Name: cpl cpl_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.cpl
+ ADD CONSTRAINT cpl_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dbaliases dbaliases_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dbaliases
+ ADD CONSTRAINT dbaliases_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dialog dialog_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialog
+ ADD CONSTRAINT dialog_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dialog_vars dialog_vars_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialog_vars
+ ADD CONSTRAINT dialog_vars_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dialplan dialplan_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dialplan
+ ADD CONSTRAINT dialplan_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dispatcher dispatcher_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dispatcher
+ ADD CONSTRAINT dispatcher_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: domain_attrs domain_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain_attrs
+ ADD CONSTRAINT domain_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: domain domain_domain_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain
+ ADD CONSTRAINT domain_domain_idx UNIQUE (domain);
+
+
+--
+-- Name: domain_name domain_name_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain_name
+ ADD CONSTRAINT domain_name_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: domain domain_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domain
+ ADD CONSTRAINT domain_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: domainpolicy domainpolicy_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domainpolicy
+ ADD CONSTRAINT domainpolicy_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: domainpolicy domainpolicy_rav_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.domainpolicy
+ ADD CONSTRAINT domainpolicy_rav_idx UNIQUE (rule, att, val);
+
+
+--
+-- Name: dr_gateways dr_gateways_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_gateways
+ ADD CONSTRAINT dr_gateways_pkey PRIMARY KEY (gwid);
+
+
+--
+-- Name: dr_groups dr_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_groups
+ ADD CONSTRAINT dr_groups_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dr_gw_lists dr_gw_lists_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_gw_lists
+ ADD CONSTRAINT dr_gw_lists_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: dr_rules dr_rules_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.dr_rules
+ ADD CONSTRAINT dr_rules_pkey PRIMARY KEY (ruleid);
+
+
+--
+-- Name: event_list event_list_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.event_list
+ ADD CONSTRAINT event_list_pkey PRIMARY KEY (event);
+
+
+--
+-- Name: globalblacklist globalblacklist_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.globalblacklist
+ ADD CONSTRAINT globalblacklist_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: grp grp_account_group_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.grp
+ ADD CONSTRAINT grp_account_group_idx UNIQUE (username, domain, grp);
+
+
+--
+-- Name: grp grp_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.grp
+ ADD CONSTRAINT grp_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: htable htable_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.htable
+ ADD CONSTRAINT htable_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: imc_members imc_members_account_room_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_members
+ ADD CONSTRAINT imc_members_account_room_idx UNIQUE (username, domain, room);
+
+
+--
+-- Name: imc_members imc_members_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_members
+ ADD CONSTRAINT imc_members_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: imc_rooms imc_rooms_name_domain_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_rooms
+ ADD CONSTRAINT imc_rooms_name_domain_idx UNIQUE (name, domain);
+
+
+--
+-- Name: imc_rooms imc_rooms_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.imc_rooms
+ ADD CONSTRAINT imc_rooms_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: lcr_gw lcr_gw_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_gw
+ ADD CONSTRAINT lcr_gw_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: lcr_rule lcr_rule_lcr_id_prefix_from_uri_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule
+ ADD CONSTRAINT lcr_rule_lcr_id_prefix_from_uri_idx UNIQUE (lcr_id, prefix, from_uri);
+
+
+--
+-- Name: lcr_rule lcr_rule_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule
+ ADD CONSTRAINT lcr_rule_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: lcr_rule_target lcr_rule_target_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule_target
+ ADD CONSTRAINT lcr_rule_target_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: lcr_rule_target lcr_rule_target_rule_id_gw_id_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.lcr_rule_target
+ ADD CONSTRAINT lcr_rule_target_rule_id_gw_id_idx UNIQUE (rule_id, gw_id);
+
+
+--
+-- Name: location_attrs location_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.location_attrs
+ ADD CONSTRAINT location_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: location location_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.location
+ ADD CONSTRAINT location_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: location location_ruid_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.location
+ ADD CONSTRAINT location_ruid_idx UNIQUE (ruid);
+
+
+--
+-- Name: missed_calls missed_calls_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.missed_calls
+ ADD CONSTRAINT missed_calls_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: mohqcalls mohqcalls_mohqcalls_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqcalls
+ ADD CONSTRAINT mohqcalls_mohqcalls_idx UNIQUE (call_id);
+
+
+--
+-- Name: mohqcalls mohqcalls_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqcalls
+ ADD CONSTRAINT mohqcalls_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: mohqueues mohqueues_mohqueue_name_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqueues
+ ADD CONSTRAINT mohqueues_mohqueue_name_idx UNIQUE (name);
+
+
+--
+-- Name: mohqueues mohqueues_mohqueue_uri_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqueues
+ ADD CONSTRAINT mohqueues_mohqueue_uri_idx UNIQUE (uri);
+
+
+--
+-- Name: mohqueues mohqueues_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mohqueues
+ ADD CONSTRAINT mohqueues_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: mtree mtree_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtree
+ ADD CONSTRAINT mtree_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: mtree mtree_tprefix_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtree
+ ADD CONSTRAINT mtree_tprefix_idx UNIQUE (tprefix);
+
+
+--
+-- Name: mtrees mtrees_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtrees
+ ADD CONSTRAINT mtrees_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: mtrees mtrees_tname_tprefix_tvalue_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.mtrees
+ ADD CONSTRAINT mtrees_tname_tprefix_tvalue_idx UNIQUE (tname, tprefix, tvalue);
+
+
+--
+-- Name: pdt pdt_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pdt
+ ADD CONSTRAINT pdt_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: pdt pdt_sdomain_prefix_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pdt
+ ADD CONSTRAINT pdt_sdomain_prefix_idx UNIQUE (sdomain, prefix);
+
+
+--
+-- Name: pl_pipes pl_pipes_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pl_pipes
+ ADD CONSTRAINT pl_pipes_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: presentity presentity_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.presentity
+ ADD CONSTRAINT presentity_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: presentity presentity_presentity_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.presentity
+ ADD CONSTRAINT presentity_presentity_idx UNIQUE (username, domain, event, etag);
+
+
+--
+-- Name: presentity presentity_ruid_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.presentity
+ ADD CONSTRAINT presentity_ruid_idx UNIQUE (ruid);
+
+
+--
+-- Name: pua pua_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pua
+ ADD CONSTRAINT pua_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: pua pua_pua_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.pua
+ ADD CONSTRAINT pua_pua_idx UNIQUE (etag, tuple_id, call_id, from_tag);
+
+
+--
+-- Name: purplemap purplemap_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.purplemap
+ ADD CONSTRAINT purplemap_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: re_grp re_grp_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.re_grp
+ ADD CONSTRAINT re_grp_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: rls_presentity rls_presentity_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_presentity
+ ADD CONSTRAINT rls_presentity_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: rls_presentity rls_presentity_rls_presentity_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_presentity
+ ADD CONSTRAINT rls_presentity_rls_presentity_idx UNIQUE (rlsubs_did, resource_uri);
+
+
+--
+-- Name: rls_watchers rls_watchers_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_watchers
+ ADD CONSTRAINT rls_watchers_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: rls_watchers rls_watchers_rls_watcher_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rls_watchers
+ ADD CONSTRAINT rls_watchers_rls_watcher_idx UNIQUE (callid, to_tag, from_tag);
+
+
+--
+-- Name: rtpengine rtpengine_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rtpengine
+ ADD CONSTRAINT rtpengine_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: rtpengine rtpengine_rtpengine_nodes; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rtpengine
+ ADD CONSTRAINT rtpengine_rtpengine_nodes UNIQUE (setid, url);
+
+
+--
+-- Name: rtpproxy rtpproxy_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.rtpproxy
+ ADD CONSTRAINT rtpproxy_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: sca_subscriptions sca_subscriptions_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.sca_subscriptions
+ ADD CONSTRAINT sca_subscriptions_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: sca_subscriptions sca_subscriptions_sca_subscriptions_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.sca_subscriptions
+ ADD CONSTRAINT sca_subscriptions_sca_subscriptions_idx UNIQUE (subscriber, call_id, from_tag, to_tag);
+
+
+--
+-- Name: silo silo_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.silo
+ ADD CONSTRAINT silo_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: sip_trace sip_trace_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.sip_trace
+ ADD CONSTRAINT sip_trace_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: speed_dial speed_dial_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.speed_dial
+ ADD CONSTRAINT speed_dial_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: speed_dial speed_dial_speed_dial_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.speed_dial
+ ADD CONSTRAINT speed_dial_speed_dial_idx UNIQUE (username, domain, sd_domain, sd_username);
+
+
+--
+-- Name: subscriber subscriber_account_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.subscriber
+ ADD CONSTRAINT subscriber_account_idx UNIQUE (username, domain);
+
+
+--
+-- Name: subscriber subscriber_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.subscriber
+ ADD CONSTRAINT subscriber_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: topos_d topos_d_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.topos_d
+ ADD CONSTRAINT topos_d_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: topos_t topos_t_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.topos_t
+ ADD CONSTRAINT topos_t_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: trusted trusted_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.trusted
+ ADD CONSTRAINT trusted_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uacreg uacreg_l_uuid_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uacreg
+ ADD CONSTRAINT uacreg_l_uuid_idx UNIQUE (l_uuid);
+
+
+--
+-- Name: uacreg uacreg_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uacreg
+ ADD CONSTRAINT uacreg_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_credentials uid_credentials_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_credentials
+ ADD CONSTRAINT uid_credentials_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_domain_attrs uid_domain_attrs_domain_attr_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain_attrs
+ ADD CONSTRAINT uid_domain_attrs_domain_attr_idx UNIQUE (did, name, value);
+
+
+--
+-- Name: uid_domain_attrs uid_domain_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain_attrs
+ ADD CONSTRAINT uid_domain_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_domain uid_domain_domain_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain
+ ADD CONSTRAINT uid_domain_domain_idx UNIQUE (domain);
+
+
+--
+-- Name: uid_domain uid_domain_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_domain
+ ADD CONSTRAINT uid_domain_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_global_attrs uid_global_attrs_global_attrs_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_global_attrs
+ ADD CONSTRAINT uid_global_attrs_global_attrs_idx UNIQUE (name, value);
+
+
+--
+-- Name: uid_global_attrs uid_global_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_global_attrs
+ ADD CONSTRAINT uid_global_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_uri_attrs uid_uri_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_uri_attrs
+ ADD CONSTRAINT uid_uri_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_uri_attrs uid_uri_attrs_uriattrs_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_uri_attrs
+ ADD CONSTRAINT uid_uri_attrs_uriattrs_idx UNIQUE (username, did, name, value, scheme);
+
+
+--
+-- Name: uid_uri uid_uri_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_uri
+ ADD CONSTRAINT uid_uri_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_user_attrs uid_user_attrs_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_user_attrs
+ ADD CONSTRAINT uid_user_attrs_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: uid_user_attrs uid_user_attrs_userattrs_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uid_user_attrs
+ ADD CONSTRAINT uid_user_attrs_userattrs_idx UNIQUE (uid, name, value);
+
+
+--
+-- Name: uri uri_account_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uri
+ ADD CONSTRAINT uri_account_idx UNIQUE (username, domain, uri_user);
+
+
+--
+-- Name: uri uri_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.uri
+ ADD CONSTRAINT uri_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: userblacklist userblacklist_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.userblacklist
+ ADD CONSTRAINT userblacklist_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: usr_preferences usr_preferences_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.usr_preferences
+ ADD CONSTRAINT usr_preferences_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: version version_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.version
+ ADD CONSTRAINT version_pkey PRIMARY KEY (table_name);
+
+
+--
+-- Name: watchers watchers_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.watchers
+ ADD CONSTRAINT watchers_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: watchers watchers_watcher_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.watchers
+ ADD CONSTRAINT watchers_watcher_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event);
+
+
+--
+-- Name: xcap xcap_doc_uri_idx; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.xcap
+ ADD CONSTRAINT xcap_doc_uri_idx UNIQUE (doc_uri);
+
+
+--
+-- Name: xcap xcap_pkey; Type: CONSTRAINT; Schema: public; Owner: kamailio
+--
+
+ALTER TABLE ONLY public.xcap
+ ADD CONSTRAINT xcap_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: acc_callid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX acc_callid_idx ON public.acc USING btree (callid);
+
+
+--
+-- Name: acc_cdrs_start_time_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX acc_cdrs_start_time_idx ON public.acc_cdrs USING btree (start_time);
+
+
+--
+-- Name: active_watchers_active_watchers_expires; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX active_watchers_active_watchers_expires ON public.active_watchers USING btree (expires);
+
+
+--
+-- Name: active_watchers_active_watchers_pres; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX active_watchers_active_watchers_pres ON public.active_watchers USING btree (presentity_uri, event);
+
+
+--
+-- Name: active_watchers_updated_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX active_watchers_updated_idx ON public.active_watchers USING btree (updated);
+
+
+--
+-- Name: active_watchers_updated_winfo_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX active_watchers_updated_winfo_idx ON public.active_watchers USING btree (updated_winfo, presentity_uri);
+
+
+--
+-- Name: aliases_account_contact_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX aliases_account_contact_idx ON public.aliases USING btree (username, domain, contact);
+
+
+--
+-- Name: aliases_expires_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX aliases_expires_idx ON public.aliases USING btree (expires);
+
+
+--
+-- Name: dbaliases_alias_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX dbaliases_alias_idx ON public.dbaliases USING btree (alias_username, alias_domain);
+
+
+--
+-- Name: dbaliases_alias_user_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX dbaliases_alias_user_idx ON public.dbaliases USING btree (alias_username);
+
+
+--
+-- Name: dbaliases_target_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX dbaliases_target_idx ON public.dbaliases USING btree (username, domain);
+
+
+--
+-- Name: dialog_hash_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX dialog_hash_idx ON public.dialog USING btree (hash_entry, hash_id);
+
+
+--
+-- Name: dialog_vars_hash_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX dialog_vars_hash_idx ON public.dialog_vars USING btree (hash_entry, hash_id);
+
+
+--
+-- Name: domain_attrs_domain_attrs_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX domain_attrs_domain_attrs_idx ON public.domain_attrs USING btree (did, name);
+
+
+--
+-- Name: domainpolicy_rule_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX domainpolicy_rule_idx ON public.domainpolicy USING btree (rule);
+
+
+--
+-- Name: globalblacklist_globalblacklist_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX globalblacklist_globalblacklist_idx ON public.globalblacklist USING btree (prefix);
+
+
+--
+-- Name: lcr_gw_lcr_id_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX lcr_gw_lcr_id_idx ON public.lcr_gw USING btree (lcr_id);
+
+
+--
+-- Name: lcr_rule_target_lcr_id_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX lcr_rule_target_lcr_id_idx ON public.lcr_rule_target USING btree (lcr_id);
+
+
+--
+-- Name: location_account_contact_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX location_account_contact_idx ON public.location USING btree (username, domain, contact);
+
+
+--
+-- Name: location_attrs_account_record_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX location_attrs_account_record_idx ON public.location_attrs USING btree (username, domain, ruid);
+
+
+--
+-- Name: location_attrs_last_modified_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX location_attrs_last_modified_idx ON public.location_attrs USING btree (last_modified);
+
+
+--
+-- Name: location_connection_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX location_connection_idx ON public.location USING btree (server_id, connection_id);
+
+
+--
+-- Name: location_expires_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX location_expires_idx ON public.location USING btree (expires);
+
+
+--
+-- Name: matrix_matrix_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX matrix_matrix_idx ON public.matrix USING btree (first, second);
+
+
+--
+-- Name: missed_calls_callid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX missed_calls_callid_idx ON public.missed_calls USING btree (callid);
+
+
+--
+-- Name: presentity_account_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX presentity_account_idx ON public.presentity USING btree (username, domain, event);
+
+
+--
+-- Name: presentity_presentity_expires; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX presentity_presentity_expires ON public.presentity USING btree (expires);
+
+
+--
+-- Name: pua_dialog1_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX pua_dialog1_idx ON public.pua USING btree (pres_id, pres_uri);
+
+
+--
+-- Name: pua_dialog2_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX pua_dialog2_idx ON public.pua USING btree (call_id, from_tag);
+
+
+--
+-- Name: pua_expires_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX pua_expires_idx ON public.pua USING btree (expires);
+
+
+--
+-- Name: pua_record_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX pua_record_idx ON public.pua USING btree (pres_id);
+
+
+--
+-- Name: re_grp_group_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX re_grp_group_idx ON public.re_grp USING btree (group_id);
+
+
+--
+-- Name: rls_presentity_expires_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_presentity_expires_idx ON public.rls_presentity USING btree (expires);
+
+
+--
+-- Name: rls_presentity_rlsubs_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_presentity_rlsubs_idx ON public.rls_presentity USING btree (rlsubs_did);
+
+
+--
+-- Name: rls_presentity_updated_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_presentity_updated_idx ON public.rls_presentity USING btree (updated);
+
+
+--
+-- Name: rls_watchers_rls_watchers_expires; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_watchers_rls_watchers_expires ON public.rls_watchers USING btree (expires);
+
+
+--
+-- Name: rls_watchers_rls_watchers_update; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_watchers_rls_watchers_update ON public.rls_watchers USING btree (watcher_username, watcher_domain, event);
+
+
+--
+-- Name: rls_watchers_updated_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX rls_watchers_updated_idx ON public.rls_watchers USING btree (updated);
+
+
+--
+-- Name: sca_subscriptions_sca_expires_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sca_subscriptions_sca_expires_idx ON public.sca_subscriptions USING btree (server_id, expires);
+
+
+--
+-- Name: sca_subscriptions_sca_subscribers_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sca_subscriptions_sca_subscribers_idx ON public.sca_subscriptions USING btree (subscriber, event);
+
+
+--
+-- Name: silo_account_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX silo_account_idx ON public.silo USING btree (username, domain);
+
+
+--
+-- Name: sip_trace_callid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sip_trace_callid_idx ON public.sip_trace USING btree (callid);
+
+
+--
+-- Name: sip_trace_date_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sip_trace_date_idx ON public.sip_trace USING btree (time_stamp);
+
+
+--
+-- Name: sip_trace_fromip_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sip_trace_fromip_idx ON public.sip_trace USING btree (fromip);
+
+
+--
+-- Name: sip_trace_traced_user_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX sip_trace_traced_user_idx ON public.sip_trace USING btree (traced_user);
+
+
+--
+-- Name: subscriber_username_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX subscriber_username_idx ON public.subscriber USING btree (username);
+
+
+--
+-- Name: topos_d_a_callid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_d_a_callid_idx ON public.topos_d USING btree (a_callid);
+
+
+--
+-- Name: topos_d_a_uuid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_d_a_uuid_idx ON public.topos_d USING btree (a_uuid);
+
+
+--
+-- Name: topos_d_b_uuid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_d_b_uuid_idx ON public.topos_d USING btree (b_uuid);
+
+
+--
+-- Name: topos_d_rectime_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_d_rectime_idx ON public.topos_d USING btree (rectime);
+
+
+--
+-- Name: topos_t_a_callid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_t_a_callid_idx ON public.topos_t USING btree (a_callid);
+
+
+--
+-- Name: topos_t_a_uuid_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_t_a_uuid_idx ON public.topos_t USING btree (a_uuid);
+
+
+--
+-- Name: topos_t_rectime_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_t_rectime_idx ON public.topos_t USING btree (rectime);
+
+
+--
+-- Name: topos_t_x_vbranch_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX topos_t_x_vbranch_idx ON public.topos_t USING btree (x_vbranch);
+
+
+--
+-- Name: trusted_peer_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX trusted_peer_idx ON public.trusted USING btree (src_ip);
+
+
+--
+-- Name: uid_credentials_cred_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_credentials_cred_idx ON public.uid_credentials USING btree (auth_username, did);
+
+
+--
+-- Name: uid_credentials_did_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_credentials_did_idx ON public.uid_credentials USING btree (did);
+
+
+--
+-- Name: uid_credentials_realm_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_credentials_realm_idx ON public.uid_credentials USING btree (realm);
+
+
+--
+-- Name: uid_credentials_uid; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_credentials_uid ON public.uid_credentials USING btree (uid);
+
+
+--
+-- Name: uid_domain_attrs_domain_did; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_domain_attrs_domain_did ON public.uid_domain_attrs USING btree (did, flags);
+
+
+--
+-- Name: uid_domain_did_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_domain_did_idx ON public.uid_domain USING btree (did);
+
+
+--
+-- Name: uid_uri_uri_idx1; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_uri_uri_idx1 ON public.uid_uri USING btree (username, did, scheme);
+
+
+--
+-- Name: uid_uri_uri_uid; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX uid_uri_uri_uid ON public.uid_uri USING btree (uid);
+
+
+--
+-- Name: userblacklist_userblacklist_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX userblacklist_userblacklist_idx ON public.userblacklist USING btree (username, domain, prefix);
+
+
+--
+-- Name: usr_preferences_ua_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX usr_preferences_ua_idx ON public.usr_preferences USING btree (uuid, attribute);
+
+
+--
+-- Name: usr_preferences_uda_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX usr_preferences_uda_idx ON public.usr_preferences USING btree (username, domain, attribute);
+
+
+--
+-- Name: xcap_account_doc_type_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX xcap_account_doc_type_idx ON public.xcap USING btree (username, domain, doc_type);
+
+
+--
+-- Name: xcap_account_doc_type_uri_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX xcap_account_doc_type_uri_idx ON public.xcap USING btree (username, domain, doc_type, doc_uri);
+
+
+--
+-- Name: xcap_account_doc_uri_idx; Type: INDEX; Schema: public; Owner: kamailio
+--
+
+CREATE INDEX xcap_account_doc_uri_idx ON public.xcap USING btree (username, domain, doc_uri);
+
+
+--
+-- PostgreSQL database dump complete
+--
+
diff --git a/kamailio-proxy-proxy/db_scripts/kazoodb-sql.sh b/kamailio-proxy-proxy/db_scripts/kazoodb-sql.sh
new file mode 100755
index 0000000..6351266
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/kazoodb-sql.sh
@@ -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"
+}
diff --git a/kamailio-proxy-proxy/db_scripts/mysql-specific b/kamailio-proxy-proxy/db_scripts/mysql-specific
new file mode 100644
index 0000000..cbcc993
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/mysql-specific
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+sql_db_pre_setup() {
+cat << EOF
+START TRANSACTION;
+EOF
+}
+
+sql_setup() {
+cat << EOF
+EOF
+}
+
+sql_header() {
+cat << EOF
+EOF
+}
+
+sql_extra_tables() {
+cat << EOF
+CREATE TABLE active_watchers_log (
+ id SERIAL PRIMARY KEY NOT NULL,
+ presentity_uri VARCHAR(128) NOT NULL,
+ watcher_username VARCHAR(64) NOT NULL,
+ watcher_domain VARCHAR(64) NOT NULL,
+ to_user VARCHAR(64) NOT NULL,
+ to_domain VARCHAR(64) NOT NULL,
+ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
+ callid VARCHAR(255) NOT NULL,
+ time INTEGER NOT NULL,
+ result INTEGER NOT NULL,
+ sent_msg BLOB NOT NULL,
+ received_msg BLOB NOT NULL,
+ user_agent VARCHAR(255) DEFAULT '' NOT NULL,
+ CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
+);
+EOF
+}
+
+sql_footer() {
+cat << EOF
+ALTER TABLE location_attrs MODIFY avalue varchar(512);
+EOF
+}
diff --git a/kamailio-proxy-proxy/db_scripts/postgres-specific b/kamailio-proxy-proxy/db_scripts/postgres-specific
new file mode 100644
index 0000000..7401e46
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/postgres-specific
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+sql_db_pre_setup() {
+cat << EOF
+BEGIN TRANSACTION;
+EOF
+}
+
+sql_setup() {
+cat << EOF
+EOF
+}
+
+sql_header() {
+cat << EOF
+EOF
+}
+
+sql_extra_tables() {
+cat << EOF
+CREATE TABLE active_watchers_log (
+ id SERIAL PRIMARY KEY NOT NULL,
+ presentity_uri VARCHAR(128) NOT NULL,
+ watcher_username VARCHAR(64) NOT NULL,
+ watcher_domain VARCHAR(64) NOT NULL,
+ to_user VARCHAR(64) NOT NULL,
+ to_domain VARCHAR(64) NOT NULL,
+ event VARCHAR(64) DEFAULT 'presence' NOT NULL,
+ callid VARCHAR(255) NOT NULL,
+ time INTEGER NOT NULL,
+ result INTEGER NOT NULL,
+ sent_msg BYTEA NOT NULL,
+ received_msg BYTEA NOT NULL,
+ user_agent VARCHAR(255) DEFAULT '' NOT NULL,
+ CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
+);
+EOF
+}
+
+sql_footer() {
+cat << EOF
+ALTER TABLE location_attrs ALTER COLUMN avalue TYPE varchar(512);
+EOF
+}
diff --git a/kamailio-proxy-proxy/db_scripts/vw_presentities.sql b/kamailio-proxy-proxy/db_scripts/vw_presentities.sql
new file mode 100644
index 0000000..4c95a38
--- /dev/null
+++ b/kamailio-proxy-proxy/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-proxy-proxy/db_scripts/vw_w_keepalive_contact.sql b/kamailio-proxy-proxy/db_scripts/vw_w_keepalive_contact.sql
new file mode 100644
index 0000000..1639650
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/vw_w_keepalive_contact.sql
@@ -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
diff --git a/kamailio-proxy-proxy/db_scripts/vw_w_location_contact.sql b/kamailio-proxy-proxy/db_scripts/vw_w_location_contact.sql
new file mode 100644
index 0000000..6914519
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/vw_w_location_contact.sql
@@ -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
diff --git a/kamailio-proxy-proxy/db_scripts/vw_w_watchers_contact.sql b/kamailio-proxy-proxy/db_scripts/vw_w_watchers_contact.sql
new file mode 100644
index 0000000..96d0186
--- /dev/null
+++ b/kamailio-proxy-proxy/db_scripts/vw_w_watchers_contact.sql
@@ -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
diff --git a/kamailio-proxy-proxy/db_scripts/vw_wdispatcher.sql b/kamailio-proxy-proxy/db_scripts/vw_wdispatcher.sql
new file mode 100644
index 0000000..884fdbf
--- /dev/null
+++ b/kamailio-proxy-proxy/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, "duid=")+5, instr(attrs, ";node")-instr(attrs, "duid=")-5) as integer) idx,
+ cast(substr(attrs, instr(attrs, "node=")+5) as varchar(50)) node
+ from dispatcher
diff --git a/kamailio-proxy-proxy/default.cfg b/kamailio-proxy-proxy/default.cfg
new file mode 100644
index 0000000..95297fd
--- /dev/null
+++ b/kamailio-proxy-proxy/default.cfg
@@ -0,0 +1,966 @@
+## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ##
+
+####### Flags #######
+#!trydef FLAG_INTERNALLY_SOURCED 1
+#!trydef FLAG_ASSOCIATE_SERVER 2
+#!trydef FLAG_SKIP_NAT_CORRECTION 3
+#!trydef FLAG_ASSOCIATE_USER 4
+#!trydef FLAG_TRUSTED_SOURCE 5
+#!trydef FLAG_SESSION_PROGRESS 6
+#!trydef FLAG_IS_REPLY 7
+#!trydef FLAG_SIP_TRACE 8
+#!trydef FLT_AOR 9
+#!trydef FLT_T38 10
+#!trydef FLT_NATS 11
+#!trydef FLAG_LOCAL_REQUEST 12
+#!trydef FLAG_LOCAL_ROUTE 17
+#!trydef FLAG_NETWORK_CLASSIFIED 18
+
+####### Global Parameters #########
+fork = yes
+children = CHILDREN
+server_signature = no
+server_header = "Server: Kazoo"
+user_agent_header = "User-Agent: Kazoo"
+shm_force_alloc = yes
+mlock_pages = yes
+phone2tel = 1
+max_while_loops = MAX_WHILE_LOOPS
+
+pv_buffer_size = PV_BUFFER_SIZE
+pv_buffer_slots = PV_BUFFER_SLOTS
+
+mem_join=1
+
+####### Logging Parameters #########
+debug = KAZOO_LOG_LEVEL
+memdbg = 10
+memlog = L_BUG
+corelog = L_ERR
+mem_summary = KZ_MEM_SUMMARY
+log_stderror = no
+log_facility = LOG_LOCAL0
+log_name="kamailio"
+
+####### Alias Parameters #########
+auto_aliases = yes
+
+####### Binding Parameters #########
+tos = IPTOS_LOWDELAY
+
+####### TCP Parameters #########
+tcp_children = TCP_CHILDREN
+disable_tcp = no
+tcp_max_connections = TCP_MAX_CONNECTIONS
+tcp_connection_lifetime = TCP_CONNECTION_LIFETIME
+tcp_accept_aliases = no
+tcp_async = yes
+tcp_connect_timeout = TCP_CONNECTION_TIMEOUT
+tcp_conn_wq_max = 65536
+tcp_crlf_ping = yes
+tcp_delayed_ack = yes
+tcp_fd_cache = yes
+tcp_keepalive = TCP_KEEP_ALIVE
+tcp_keepcnt = TCP_KEEP_COUNT
+tcp_keepidle = TCP_KEEP_IDLE
+tcp_keepintvl = TCP_KEEP_INTERVAL
+tcp_linger2 = 30
+tcp_rd_buf_size = 80000
+tcp_send_timeout = TCP_SEND_TIMEOUT
+tcp_wq_blk_size = 2100
+tcp_wq_max = 10485760
+
+####### UDP Parameters #########
+udp4_raw = 0
+#udp4_raw_mtu = 800
+# # pmtu_discovery = no
+#udp_mtu = 800
+# #udp_mtu_try_proto = TCP
+
+####### DNS Parameters #########
+dns = no
+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_mem = 1000
+dns_cache_negative_ttl = 60
+dns_try_naptr = no
+use_dns_failover = off
+dns_srv_lb = off
+
+####### SCTP Parameters #########
+disable_sctp = yes
+
+####### multi homed #########
+mhomed=KZ_MULTI_HOMED
+
+######## Kamailio mqueue module ########
+loadmodule "mqueue.so"
+
+######## Kamailio outbound module ########
+loadmodule "outbound.so"
+
+######## Kamailio stun module ########
+loadmodule "stun.so"
+
+######## Kamailio path module ########
+loadmodule "path.so"
+
+######## Kamailio control connector module ########
+loadmodule "ctl.so"
+modparam("ctl", "binrpc_buffer_size", 4096)
+loadmodule "cfg_rpc.so"
+
+######## Kamailio config utils module ########
+loadmodule "cfgutils.so"
+modparam("cfgutils", "lock_set_size", 4)
+
+######## Kamailio corex module ########
+loadmodule "corex.so"
+
+######## Kamailio uuid module ########
+loadmodule "uuid.so"
+
+######## Kamailio core extensions module ########
+loadmodule "kex.so"
+
+######## Transaction (stateful) module ########
+loadmodule "tm.so"
+loadmodule "tmx.so"
+modparam("tm", "auto_inv_100", 1)
+modparam("tm", "auto_inv_100_reason", "Attempting to connect your call")
+modparam("tm", "cancel_b_method", 2)
+modparam("tm", "ruri_matching", 0)
+modparam("tm", "failure_reply_mode", 3)
+modparam("tm", "failure_exec_mode", 1)
+modparam("tm", "reparse_on_dns_failover", 0)
+
+
+# modparam("tm", "fr_timer", 30000)
+# modparam("tm", "fr_inv_timer", 120000)
+
+######## Stateless replier module ########
+loadmodule "sl.so"
+
+######## Record-Route and Route module ########
+loadmodule "rr.so"
+modparam("rr", "enable_full_lr", RR_FULL_LR)
+modparam("rr", "enable_double_rr", RR_DOUBLE_RR)
+modparam("rr", "force_send_socket", RR_FORCE_SOCKET)
+
+######## Max-Forward processor module ########
+loadmodule "maxfwd.so"
+modparam("maxfwd", "max_limit", 50)
+
+######## SIP utilities [requires sl] ########
+loadmodule "siputils.so"
+
+######## Text operations module ########
+loadmodule "textopsx.so"
+
+######## sdp operations module ########
+loadmodule "sdpops.so"
+
+######## Generic Hash Table container in shared memory ########
+loadmodule "htable.so"
+modparam("htable", "htable", "associations=>size=16;autoexpire=7200")
+modparam("htable", "htable", "redirects=>size=16;autoexpire=5")
+modparam("htable", "db_url", "KAZOO_DB_URL")
+
+####### RTIMER module ##########
+loadmodule "rtimer.so"
+
+####### evrexec module ##########
+loadmodule "evrexec.so"
+modparam("evrexec", "exec", "name=evrexec:DEFERRED_INIT;wait=20000000;workers=1;")
+
+######## Advanced logger module ########
+loadmodule "xlog.so"
+
+######## UAC ########
+loadmodule "uac.so"
+
+######## AVP's ########
+loadmodule "avp.so"
+loadmodule "avpops.so"
+
+######## UAC Redirection module ########
+loadmodule "uac_redirect.so"
+
+#### json rpc ####
+loadmodule "jsonrpcs.so"
+
+####### SQL OPS module ##########
+loadmodule "sqlops.so"
+modparam("sqlops","sqlcon", "cb=>KAZOO_DB_URL")
+modparam("sqlops","sqlcon", "exec=>KAZOO_DB_URL")
+
+####### DEBUG ######
+loadmodule "debugger.so"
+modparam("debugger", "mod_hash_size", 5)
+modparam("debugger", "mod_level_mode", 1)
+modparam("debugger", "mod_level", "core=1")
+
+####### STATISTICS ######
+loadmodule "statistics.so"
+
+####### DATABASE module ##########
+include_file "db_KAMAILIO_DBMS.cfg"
+
+###### kazoo bindings ######
+#!ifdef NODES_ROLE
+include_file "kazoo-bindings.cfg"
+#!endif
+
+####### Role Configurations ##########
+#!ifdef AUTHORIZATION_ROLE
+include_file "authorization-role.cfg"
+#!endif
+#!ifdef DISPATCHER_ROLE
+include_file "dispatcher-role-MAJOR.cfg"
+#!endif
+#!ifdef REGISTRAR_ROLE
+include_file "registrar-role.cfg"
+#!endif
+#!ifdef PRESENCE_ROLE
+include_file "presence-role.cfg"
+#!endif
+#!ifdef MESSAGE_ROLE
+include_file "message-role.cfg"
+#!endif
+#!ifdef NAT_TRAVERSAL_ROLE
+include_file "nat-traversal-role.cfg"
+#!endif
+#!ifdef WEBSOCKETS_ROLE
+include_file "websockets-role.cfg"
+#!endif
+#!ifdef TLS_ROLE
+include_file "tls-role.cfg"
+#!endif
+#!ifdef ACCOUNTING_ROLE
+include_file "accounting-role.cfg"
+#!endif
+#!ifdef ANTIFLOOD_ROLE
+include_file "antiflood-role.cfg"
+#!endif
+#!ifdef TRAFFIC_FILTER_ROLE
+include_file "traffic-filter-role.cfg"
+#!endif
+#!ifdef ACL_ROLE
+include_file "acl-role.cfg"
+#!endif
+#!ifdef RATE_LIMITER_ROLE
+include_file "rate-limiter-role.cfg"
+#!endif
+#!ifdef PUSHER_ROLE
+include_file "pusher-role.cfg"
+#!endif
+#!ifdef RESPONDER_ROLE
+include_file "responder-role.cfg"
+#!endif
+#!ifdef NODES_ROLE
+include_file "nodes-role.cfg"
+#!endif
+#!ifdef SIP_TRACE_ROLE
+include_file "sip_trace-role.cfg"
+#!endif
+#!ifdef KEEPALIVE_ROLE
+include_file "keepalive-role.cfg"
+#!endif
+#!ifdef BLOCKER_ROLE
+include_file "blocker-role.cfg"
+#!endif
+
+## sanity ##
+include_file "sanity.cfg"
+
+## auth ##
+include_file "auth.cfg"
+
+####### Permissions module ##########
+loadmodule "permissions.so"
+modparam("permissions", "db_url", "KAZOO_DB_URL")
+modparam("permissions", "db_mode", 1)
+
+###### local route ######
+socket_workers=10
+listen=tcp:127.0.0.1:5090
+
+####### Routing Logic ########
+route
+{
+ route(LOCAL_REQUEST);
+
+ route(SANITY_CHECK);
+
+ route(CHECK_RETRANS);
+
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANTIFLOOD_LIMIT);
+ #!endif
+
+ #!ifdef TRAFFIC_FILTER_ROLE
+ route(FILTER_REQUEST);
+ #!endif
+
+ #!ifdef ACL_ROLE
+ route(ACL_CHECK);
+ #!endif
+
+ #!ifdef RATE_LIMITER_ROLE
+ route(DOS_PREVENTION);
+ #!endif
+
+ route(LOG_REQUEST);
+
+ route(CLASSIFY_SOURCE);
+
+ #!ifdef NAT_TRAVERSAL_ROLE
+ route(NAT_DETECT);
+ #!endif
+
+ route(HANDLE_OPTIONS);
+
+ #!ifdef SIP_TRACE_ROLE
+ route(SIP_TRACE);
+ #!endif
+
+ route_if_exists("CUSTOM_START_ROUTES");
+
+ route(HANDLE_NOTIFY);
+
+ #!ifdef AUTHORIZATION_ROLE
+ route(AUTHORIZATION_CHECK);
+ #!endif
+
+ #!ifdef MESSAGE_ROLE
+ route(HANDLE_MESSAGE);
+ #!else
+ if (is_method("MESSAGE")) {
+ sl_send_reply("405", "Method Not Allowed");
+ exit;
+ }
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(HANDLE_SUBSCRIBE);
+ route(HANDLE_PUBLISH);
+ #!endif
+
+ #!ifdef REGISTRAR_ROLE
+ route(HANDLE_REGISTER);
+ #!endif
+
+ route(HANDLE_REFER);
+
+ route(HANDLE_IN_DIALOG_REQUESTS);
+
+ route(PREPARE_INITIAL_REQUESTS);
+
+ #!ifdef PUSHER_ROLE
+ route(PUSHER_ROUTE);
+ #!endif
+
+ #!ifdef RESPONDER_ROLE
+ if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(HANDLE_RESPOND);
+ }
+ #!endif
+
+ route(AUTH);
+
+ route(SETUP);
+
+}
+
+#!trydef KZ_LOG_REQUEST_OPTIONS 0
+kazoo.log_request_options = KZ_LOG_REQUEST_OPTIONS descr "log OPTIONS requests, default is 0 for preserving log size"
+
+route[LOG_REQUEST]
+{
+ if($sel(cfg_get.kazoo.log_request_options) == 0 && is_method("OPTIONS")) {
+ $var(log_request_level) = L_DBG;
+ } else {
+ $var(log_request_level) = L_INFO;
+ }
+
+ # log the basic info regarding this call
+ xlog("$var(log_request_level)", "$ci|start|received $pr request $rm $ou\n");
+ xlog("$var(log_request_level)", "$ci|log|source $si:$sp -> $RAi:$RAp\n");
+ xlog("$var(log_request_level)", "$ci|log|from $fu\n");
+ xlog("$var(log_request_level)", "$ci|log|to $tu\n");
+}
+
+route[CHECK_RETRANS]
+{
+ # handle retransmissions
+ if (!is_method("ACK")) {
+ if(t_precheck_trans()) {
+ t_check_trans();
+ exit;
+ }
+ t_check_trans();
+ }
+}
+
+route[CLASSIFY_SOURCE]
+{
+ #!ifdef DISPATCHER_ROLE
+ route(DISPATCHER_CLASSIFY_SOURCE);
+ #!endif
+
+ if (allow_source_address(TRUSTED_ADR_GROUP)) {
+ xlog("$var(log_request_level)", "$ci|log|request from trusted IP\n");
+ setflag(FLAG_TRUSTED_SOURCE);
+ }
+
+ if (isflagset(FLAG_INTERNALLY_SOURCED) || is_myself($si)) {
+ setflag(FLAG_TRUSTED_SOURCE);
+ }
+
+}
+
+route[HANDLE_OPTIONS]
+{
+ if (!is_method("OPTIONS")) {
+ return;
+ }
+ handle_ruri_alias();
+ if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(INTERNAL_TO_EXTERNAL_RELAY);
+ } else {
+ #!ifdef TRAFFIC_FILTER_ROLE
+ if (!isflagset(FLAG_TRUSTED_SOURCE)) {
+ route(FILTER_REQUEST_DOMAIN);
+ }
+ #!endif
+
+ sl_send_reply("200", "Rawr!!");
+
+ #!ifdef KEEPALIVE_ROLE
+ route(KEEPALIVE_ON_OPTIONS);
+ #!endif
+ }
+ exit;
+}
+
+route[HANDLE_NOTIFY]
+{
+ if (!is_method("NOTIFY")) return;
+
+ if (has_totag()) return;
+
+ if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ if (loose_route()) {
+ xlog("L_INFO", "$ci|log|Able to loose-route. Cool beans!\n");
+ }
+
+ #!ifdef REGISTRAR_ROLE
+ if (registered("location")) {
+ lookup("location");
+ xlog("L_INFO", "$ci|log|routing to $ruid\n");
+ }
+ #!endif
+
+ ## verify we're not routing to ourselves
+ if(is_myself($du)) {
+ xlog("L_INFO", "$ci|log|notify from internal to invalid destination $ruid\n");
+ sl_send_reply("200", "Rawr!!");
+ exit;
+ }
+
+ route(INTERNAL_TO_EXTERNAL_RELAY);
+ } else {
+ #!ifdef TRAFFIC_FILTER_ROLE
+ if (!isflagset(FLAG_TRUSTED_SOURCE)) {
+ route(FILTER_REQUEST_DOMAIN);
+ }
+ #!endif
+
+ if($hdr(Event) == "keep-alive") {
+ xlog("L_INFO", "$ci|stop|replying to keep alive\n");
+ sl_send_reply("405", "Stay Alive / Method Not Allowed");
+ } else {
+ xlog("L_INFO", "$ci|stop|consuming event $hdr(Event)\n");
+ sl_send_reply("200", "Rawr!!");
+ }
+
+ #!ifdef KEEPALIVE_ROLE
+ route(KEEPALIVE_ON_NOTIFY);
+ #!endif
+
+ }
+ exit;
+}
+
+route[HANDLE_REFER]
+{
+ if (!is_method("REFER")) {
+ return;
+ }
+
+ if(is_present_hf("Referred-By")) {
+ $var(referred_by) = $hdr(Referred-By);
+ } else {
+ $var(referred_by) = $_s(;created=true);
+ }
+ route(AUTH);
+ if($avp(is_registered) = "true") {
+ $var(referred_by) = $_s($var(referred_by);endpoint_id=$(xavp(ulattrs=>token){re.subst,/(.*)@(.*)/\1/});account_id=$(xavp(ulattrs=>token){re.subst,/(.*)@(.*)/\2/}));
+ }
+
+ remove_hf_re("^Referred-By");
+ append_hf("Referred-By: $var(referred_by)\r\n");
+
+}
+
+route[HANDLE_IN_DIALOG_REQUESTS]
+{
+ if (!has_totag()) return;
+
+ if (is_method("INVITE")) {
+ setflag(FLAG_SESSION_PROGRESS);
+ record_route();
+ }
+
+ if (loose_route()) {
+
+ #!ifdef NAT_TRAVERSAL_ROLE
+ if(!isdsturiset()) {
+ handle_ruri_alias();
+ }
+ if ( is_method("ACK") ) {
+ # ACK is forwarded statelessly
+ route(NAT_MANAGE);
+ }
+ #!endif
+
+ #!ifdef ACCOUNTING_ROLE
+ if (is_method("BYE")) {
+ setflag(FLAG_ACC);
+ setflag(FLAG_ACCFAILED);
+ }
+ #!endif
+
+ xlog("L_INFO", "$ci|log|loose_route in-dialog message\n");
+ # Called on in-dialog requests
+ # If the request in an Invite for on hold from external to internal,
+ # associate the contact with the media server
+ # if Invite for on hold, we need to associate the contact URI with the next hop
+ if (is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) {
+ setflag(FLAG_ASSOCIATE_USER);
+ }
+
+ # If the request in an Invite for t38 from internal,
+ # mark the request with FLT_T38
+ if (is_method("INVITE") && isflagset(FLAG_INTERNALLY_SOURCED) && sdp_with_media("image")) {
+ xlog("L_DEBUG", "$ci|log|T38 RE-INVITE\n");
+ setflag(FLT_T38);
+ }
+
+ if ( is_method("NOTIFY") ) {
+ # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
+ record_route();
+ }
+ route(RELAY);
+ } else if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ xlog("L_INFO", "$ci|log|relay internally sourced in-dialog message without loose_route\n");
+ route(RELAY);
+ } else if (t_check_trans()) {
+ xlog("L_INFO", "$ci|log|allow message for a known transaction\n");
+ route(RELAY);
+ } else {
+ xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed\n");
+ sl_send_reply("481", "Call Leg/Transaction Does Not Exist");
+ }
+ exit();
+}
+
+route[PREPARE_INITIAL_REQUESTS]
+{
+ if (is_method("CANCEL")) {
+ if (t_check_trans()) {
+ route(RELAY);
+ } else {
+ sl_send_reply("481", "Call leg/transaction does not exist");
+ }
+ exit();
+ } else if (is_method("ACK")) {
+ if (t_check_trans()) {
+ route(RELAY);
+ }
+ exit();
+ }
+
+ if (is_method("UPDATE")) {
+ xlog("L_WARN", "$ci|end|update outside dialog not allowed\n");
+ send_reply("403", "Dialog does not exist");
+ break;
+ }
+
+ if (is_method("BYE|PRACK")) {
+ xlog("L_WARN", "$ci|end|originating subsequent requests outside dialog not allowed\n");
+ send_reply("403", "Dialog does not exist");
+ break;
+ }
+
+## if (loose_route()) {
+## #!ifdef REGISTRAR_ROLE
+## $xavp(regcfg=>match_received) = $su;
+## if(registered("location", "$rz:$Au", 2) == 1) {
+## xlog("L_INFO", "$ci|log|allowing initial route-set for $Au\n");
+## } else {
+## #!endif
+## xlog("L_WARN", "$ci|end|dropping initial request with route-set\n");
+## sl_send_reply("403", "No pre-loaded routes");
+## exit();
+## #!ifdef REGISTRAR_ROLE
+## }
+## #!endif
+## }
+
+ record_route();
+}
+
+route[SETUP]
+{
+ #!ifdef DISPATCHER_ROLE
+ if (!isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(DISPATCHER_FIND_ROUTES);
+ }
+ #!endif
+
+#!ifdef REGISTRAR_ROLE
+ if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(ROUTE_TO_AOR);
+ }
+#!endif
+ handle_ruri_alias();
+
+ route(RELAY);
+}
+
+route[BRANCH_HEADERS]
+{
+ if (!isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(AUTH_HEADERS);
+ } else {
+ remove_hf_re("^X-");
+ }
+
+}
+
+# Manage outgoing branches
+branch_route[MANAGE_BRANCH] {
+ xlog("L_DEBUG", "$ci|branch|new branch [$T_branch_idx] to $ru => $du\n");
+ #!ifdef NAT_TRAVERSAL_ROLE
+ route(NAT_MANAGE);
+ #!endif
+
+ route(BRANCH_HEADERS);
+ route_if_exists("CUSTOM_BRANCH_HEADERS");
+}
+
+route[RELAY]
+{
+ if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE|NOTIFY|REFER")) {
+ if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
+ }
+
+ if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(INTERNAL_TO_EXTERNAL_RELAY);
+ } else {
+ route(EXTERNAL_TO_INTERNAL_RELAY);
+ }
+
+ exit();
+}
+
+route[INTERNAL_TO_EXTERNAL_RELAY]
+{
+ #!ifdef ACCOUNTING_ROLE
+ if (is_method("INVITE")) {
+ setflag(FLAG_ACC);
+ setflag(FLAG_ACCFAILED);
+ }
+ #!endif
+
+
+ t_on_reply("EXTERNAL_REPLY");
+
+ t_set_fr(0, $sel(cfg_get.kazoo.to_external_no_response_timer));
+
+ t_relay();
+}
+
+route[EXTERNAL_TO_INTERNAL_RELAY]
+{
+ #!ifdef ACCOUNTING_ROLE
+ if (is_method("INVITE") && is_present_hf("Proxy-Authorization")) {
+ setflag(FLAG_ACC);
+ setflag(FLAG_ACCFAILED);
+ }
+ #!endif
+
+ t_on_reply("INTERNAL_REPLY");
+ t_on_failure("INTERNAL_FAULT");
+
+ t_set_fr(0, $sel(cfg_get.kazoo.to_internal_no_response_timer));
+
+ t_relay();
+}
+
+onreply_route[EXTERNAL_REPLY]
+{
+ xlog("L_INFO", "$ci|log|external reply $T_reply_code $T_reply_reason\n");
+
+ #!ifdef NAT_TRAVERSAL_ROLE
+ if(status=~"[12][0-9][0-9]") {
+ route(NAT_MANAGE);
+ }
+ #!endif
+
+ #!ifdef ACL_ROLE
+ setflag(FLAG_IS_REPLY);
+ route(ACL_CHECK);
+ #!endif
+
+ #!ifdef RATE_LIMITER_ROLE
+ setflag(FLAG_IS_REPLY);
+ route(DOS_PREVENTION);
+ #!endif
+
+}
+
+onreply_route[INTERNAL_REPLY]
+{
+ # this route handles replies that are comming from our media server
+ if ($rs < 300) {
+ xlog("L_INFO", "$ci|log|internal reply $T_reply_code $T_reply_reason\n");
+ xlog("L_DEBUG", "$ci|log|source $si:$sp\n");
+ }
+
+ #!ifdef NAT_TRAVERSAL_ROLE
+ if(status=~"[12][0-9][0-9]") {
+ route(NAT_MANAGE);
+ }
+ #!endif
+
+ #!ifdef ACL_ROLE
+ setflag(FLAG_IS_REPLY);
+ route(ACL_CHECK);
+ #!endif
+
+ #!ifdef RATE_LIMITER_ROLE
+ setflag(FLAG_IS_REPLY);
+ route(DOS_PREVENTION);
+ #!endif
+
+ if (is_method("INVITE") &&
+ !isflagset(FLAG_SESSION_PROGRESS) &&
+ t_check_status("(180)|(183)|(200)")
+ ) {
+ xlog("L_INFO", "$ci|log|call setup, now ignoring abnormal termination\n");
+ setflag(FLAG_SESSION_PROGRESS);
+
+ # clear the redirect
+ if ($avp(AVP_REDIRECT_KEY) != $null && $sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null) {
+ xlog("L_INFO", "$ci|log|removing redirect mapping $avp(AVP_REDIRECT_KEY)\n");
+ $sht(redirects=>$avp(AVP_REDIRECT_KEY)) = $null;
+ }
+
+ }
+
+ if ($rs < 300) {
+ xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)\n");
+ }
+
+}
+
+failure_route[INTERNAL_FAULT]
+{
+ # this branch handles failures (>=300) to our media servers,
+ # which we can sometimes overcome by routing to another server
+
+ # if the failure cause was due to the transaction being
+ # cancelled then we are complete
+ if (t_is_canceled()) {
+ xlog("L_INFO", "$ci|log|transaction was cancelled\n");
+ exit;
+ }
+
+ if (!is_method("INVITE") || has_totag()) {
+ xlog("L_INFO", "$ci|failure|internal reply $T_reply_code $T_reply_reason\n");
+ xlog("L_INFO", "$ci|pass|$si:$sp\n");
+ return;
+ }
+
+ # Handle redirects
+ if (t_check_status("302") && $T_rpl($hdr(X-Redirect-Server)) != $null) {
+ route(INTERNAL_REDIRECT);
+ }
+
+ remove_hf_re("^X-.*");
+
+ # handle challenges replies from media server, we want to route to same media server
+ if (t_check_status("407")) {
+ xlog("L_INFO", "$ci|log|media $xavp(ds_dst=>uri) challenged the invite, creating redirect\n");
+ $var(redirect) = @from.uri.user + "@" + @from.uri.host + "->" + @ruri.user + "@" + @ruri.host;
+ $sht(redirects=>$var(redirect)) = $xavp(ds_dst=>uri);
+
+ # change 6xx to 4xx
+ } else 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|failure|sending $T_reply_code 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 ($T_reply_reason =~ "call barred") {
+ xlog("L_INFO", "$ci|failure|ignoring call barred\n");
+ } else if (isflagset(FLAG_SESSION_PROGRESS)) {
+ xlog("L_INFO", "$ci|failure|ignoring failure after session progress\n");
+ if (t_check_status("480")) {
+ xlog("L_INFO", "$ci|failure|overriding reply code 480 with $sel(cfg_get.kazoo.override_media_reply_480)\n");
+ send_reply("$(sel(cfg_get.kazoo.override_media_reply_480){s.int})", "Endpoint Not Available");
+ }
+ } else if (t_check_status("403") && $T_reply_reason=="Forbidden") {
+ xlog("L_WARNING", "$ci|failure|Failed auth from IP $si\n");
+ } else if (t_check_status("(401)|(486)")) {
+ xlog("L_INFO", "$ci|failure|auth reply $T_reply_code $T_reply_reason\n");
+ } else if (t_check_status("402")) {
+ xlog("L_INFO", "$ci|failure|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|failure|internal reply $T_reply_code $T_reply_reason\n");
+
+ #!ifdef DISPATCHER_ROLE
+ route(DISPATCHER_NEXT_ROUTE);
+ #!endif
+
+ send_reply("486", "Unable to Comply");
+
+ } else {
+ xlog("L_INFO", "$ci|failure|internal reply $T_reply_code $T_reply_reason\n");
+ send_reply("$T_reply_code", "$T_reply_reason");
+ }
+ xlog("L_INFO", "$ci|pass|$si:$sp\n");
+}
+
+route[INTERNAL_REDIRECT]
+{
+ xlog("L_INFO", "$ci|log|redirect to $T_rpl($hdr(X-Redirect-Server))\n");
+ $du = $T_rpl($hdr(X-Redirect-Server));
+ t_on_branch("MANAGE_BRANCH");
+ t_on_reply("INTERNAL_REPLY");
+ t_on_failure("INTERNAL_FAULT");
+ t_set_fr(0, 1000);
+ t_relay();
+ exit();
+}
+
+onsend_route {
+ if (isflagset(FLAG_ASSOCIATE_USER)) {
+ $var(user_source) = $(ct{tobody.user}) + "@" + $si + ":" + $sp;
+ xlog("L_INFO", "$ci|log|associate traffic from $var(user_source) with media server sip:$sndto(ip):$sndto(port)\n");
+ $sht(associations=>$var(user_source))= "sip:" + $sndto(ip) + ":" + $sndto(port);
+ }
+
+ #!ifdef SIP_TRACE_ROLE
+ if (is_method("ACK") && isflagset(FLAG_SIP_TRACE)) {
+ sip_trace();
+ }
+ #!endif
+
+ if(!isflagset(FLAG_LOCAL_ROUTE)) {
+ xlog("L_INFO", "$ci|pass|$sndfrom(ip):$sndfrom(port) -> $sndto(ip):$sndto(port)\n");
+ }
+}
+
+#!ifdef REGISTRAR_ROLE
+route[ROUTE_TO_AOR]
+{
+ if ($hdr(X-KAZOO-AOR) == $null) {
+ return;
+ }
+
+ xlog("L_INFO", "$ci|log|using AOR $hdr(X-KAZOO-AOR)\n");
+ if ($hdr(X-KAZOO-INVITE-FORMAT) == "contact") {
+ if(lookup("location", "$hdr(X-KAZOO-AOR)") > 0){
+ xlog("L_INFO", "$ci|end|routing to contact $ru\n");
+ handle_ruri_alias();
+ } else {
+ xlog("L_INFO", "$ci|end|lookup for AOR $hdr(X-KAZOO-AOR) failed\n");
+ sl_send_reply("410", "Not registered");
+ exit;
+ }
+ } else if (reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) {
+ $du = $(ulc(callee=>received));
+ $fs = $(ulc(callee=>socket));
+ $bf = $bf | $(ulc(callee=>cflags));
+ xlog("L_INFO", "$ci|log|routing $hdr(X-KAZOO-AOR) to $du via $fs\n");
+ } else {
+ xlog("L_INFO", "$ci|end|user is not registered\n");
+ sl_send_reply("410", "Not registered");
+ exit;
+ }
+}
+#!endif
+
+event_route[tm:local-request]
+{
+ setflag(FLAG_LOCAL_REQUEST);
+ xlog("L_DEBUG", "$ci|local|start $pr request $rm $ou\n");
+ xlog("L_DEBUG", "$ci|local|source $si:$sp -> $dd:$dp\n");
+ xlog("L_DEBUG", "$ci|local|from $fu\n");
+ xlog("L_DEBUG", "$ci|local|to $tu\n");
+
+ #!ifdef SIP_TRACE_ROLE
+ route(SIP_TRACE);
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_LOCAL_REQUEST);
+ #!endif
+
+}
+
+event_route[evrexec:DEFERRED_INIT]
+{
+ xlog("L_INFO", "processing deferred init\n");
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_DEFERRED_INIT);
+ #!endif
+
+ #!import_file "custom-init.cfg"
+
+}
+
+route[LOCAL_REQUEST]
+{
+ if(src_ip != myself || $hdr(X-TM-Local) == $null) {
+ return;
+ }
+
+ xlog("L_DEBUG", "internal route $hdr(X-TM-Local)\n");
+
+ setflag(FLAG_LOCAL_ROUTE);
+
+ #!ifdef SIP_TRACE_ROLE
+ route(SIP_TRACE);
+ #!endif
+
+ $var(LocalRoute) = $hdr(X-TM-Local);
+ remove_hf_re("^X-TM-Local");
+ route_if_exists("$var(LocalRoute)");
+ exit;
+}
+
+#!import_file "custom-routes.cfg"
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/defs-amqp.cfg b/kamailio-proxy-proxy/defs-amqp.cfg
new file mode 100644
index 0000000..fa116c9
--- /dev/null
+++ b/kamailio-proxy-proxy/defs-amqp.cfg
@@ -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
diff --git a/kamailio-proxy-proxy/defs.cfg b/kamailio-proxy-proxy/defs.cfg
new file mode 100644
index 0000000..46bf445
--- /dev/null
+++ b/kamailio-proxy-proxy/defs.cfg
@@ -0,0 +1,95 @@
+## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ##
+
+
+####### defs ########
+#!ifndef DEFAULTS_INCLUDED
+#!define DEFAULTS_INCLUDED
+
+#!substdef "!MAJOR!$(version(num){re.subst,/^(([^\.])*\.([^\.])*)\..*/\1/})!g"
+
+#!trydef EXTERNAL_TO_INTERNAL_NO_RESPONSE_TIMER 3500
+#!trydef INTERNAL_TO_EXTERNAL_NO_RESPONSE_TIMER 3500
+
+#!trydef OVERRIDE_MEDIA_REPLY_480 603
+
+kazoo.to_internal_no_response_timer = EXTERNAL_TO_INTERNAL_NO_RESPONSE_TIMER descr "external to internal no response timer"
+kazoo.to_external_no_response_timer = INTERNAL_TO_EXTERNAL_NO_RESPONSE_TIMER descr "internal to external no response timer"
+
+kazoo.override_media_reply_480 = OVERRIDE_MEDIA_REPLY_480 descr "sip code to send upstream when media returns 480 with session in progress"
+
+#!ifndef MY_HOSTNAME
+#!substdef "!MY_HOSTNAME!$HN(f)!g"
+#!endif
+
+#!ifndef MY_IP_ADDRESS
+#!ifdef MY_LOCAL_IP
+#!substdef "!MY_IP_ADDRESS!$def(MY_LOCAL_IP)!g"
+#!else
+#!substdef "!MY_IP_ADDRESS!$HN(i)!g"
+#!endif
+#!endif
+
+#!ifndef WEBSOCKET_NO_ORIGIN_RESTRICTION
+#!ifndef MY_WEBSOCKET_DOMAIN
+#!substdef "!MY_WEBSOCKET_DOMAIN!$HN(d)!g"
+#!endif
+#!endif
+
+#!trydef KAZOO_LOG_LEVEL L_INFO
+
+#!trydef PV_BUFFER_SIZE 16384
+#!trydef PV_BUFFER_SLOTS 30
+#!trydef KZ_MEM_SUMMARY 0
+
+#!trydef KZ_DB_MODULE kazoo
+#!substdef "!KAMAILIO_DBMS!$def(KZ_DB_MODULE)!g"
+
+#!ifndef KAZOO_DATA_DIR
+#!substdef "!KAZOO_DATA_DIR!/etc/kazoo/kamailio/db!g"
+#!endif
+
+#!ifndef KAZOO_DB_URL
+#!substdef "!KAZOO_DB_URL!kazoo:///KAZOO_DATA_DIR/kazoo.db!g"
+#!endif
+
+#!ifndef MAX_WHILE_LOOPS
+#!substdef "!MAX_WHILE_LOOPS!500!g"
+#!endif
+
+#### tcp parameters ##
+#!trydef CHILDREN 25
+#!trydef TCP_CHILDREN 25
+
+#!trydef TCP_MAX_CONNECTIONS 4096
+#!trydef TCP_CONNECTION_LIFETIME 3605
+#!trydef TCP_CONNECTION_TIMEOUT 5
+#!trydef TCP_KEEP_ALIVE yes
+#!trydef TCP_KEEP_COUNT 3
+#!trydef TCP_KEEP_IDLE 30
+#!trydef TCP_KEEP_INTERVAL 30
+#!trydef TCP_SEND_TIMEOUT 3
+
+#!include_file "defs-amqp.cfg"
+
+#!ifndef MEDIA_SERVERS_HASH_SIZE
+#!substdef "!MEDIA_SERVERS_HASH_SIZE!256!g"
+#!endif
+
+#!trydef RR_FULL_LR 1
+#!trydef RR_DOUBLE_RR 1
+#!trydef RR_FORCE_SOCKET 1
+
+#!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
+
+#!trydef KZ_MULTI_HOMED 0
+
+
+#!endif
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/dispatcher-role-5.1.cfg b/kamailio-proxy-proxy/dispatcher-role-5.1.cfg
new file mode 100644
index 0000000..e860ba8
--- /dev/null
+++ b/kamailio-proxy-proxy/dispatcher-role-5.1.cfg
@@ -0,0 +1,306 @@
+### DISPATCHER ROLE ####
+
+#!trydef KZ_DISPATCHER_PROBE_MODE 1
+#!trydef DISPATCHER_ADD_SERVERS 1
+#!trydef DISPATCHER_ADD_SECONDARY_IP 1
+#!trydef DISPATCHER_SECONDARY_IP_GROUP 3
+#!trydef DISPATCHER_ALG 0
+#!trydef KZ_DISPATCHER_HASH_SIZE 8
+#!trydef KZ_DISPATCHER_ADD_FLAGS 9
+#!trydef KZ_DISPATCHER_PRIMARY_GROUP 1
+#!trydef KZ_DISPATCHER_SECONDARY_GROUP 2
+#!trydef KZ_DISPATCHER_CLASSIFY_GROUP 3
+#!trydef KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP 51
+#!trydef KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP 52
+#!trydef KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP 53
+#!trydef KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP 54
+#!trydef KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP 10
+#!trydef KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP 11
+#!trydef KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP 20
+#!trydef KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP 21
+#!trydef KZ_DISPATCHER_MAX_RETRIES 2
+#!trydef KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA 1
+#!trydef KZ_DISPATCHER_CLASSIFY_FLAGS 2
+
+
+kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip = DISPATCHER_ADD_SECONDARY_IP descr "adds internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip_group = DISPATCHER_SECONDARY_IP_GROUP descr "sets the group where to add internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_algorithm = DISPATCHER_ALG descr "dispatcher algorithm to use"
+kazoo.dispatcher_primary_group = KZ_DISPATCHER_PRIMARY_GROUP descr "dispatcher primary group"
+kazoo.dispatcher_secondary_group = KZ_DISPATCHER_SECONDARY_GROUP descr "dispatcher secondary group"
+kazoo.dispatcher_max_retries = KZ_DISPATCHER_MAX_RETRIES descr "max number of retries for media servers"
+kazoo.dispatcher_route_to_associated_media = KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA descr "routes to associated media for atxfer"
+kazoo.dispatcher_classify_flags = KZ_DISPATCHER_CLASSIFY_FLAGS descr "dispatch classifier flags"
+
+####### Dispatcher module ########
+loadmodule "dispatcher.so"
+modparam("dispatcher", "db_url", "KAZOO_DB_URL")
+modparam("dispatcher", "flags", 2)
+modparam("dispatcher", "use_default", 0)
+modparam("dispatcher", "force_dst", 1)
+modparam("dispatcher", "dst_avp", "$avp(ds_dst)")
+modparam("dispatcher", "attrs_avp", "$avp(ds_attrs)")
+modparam("dispatcher", "grp_avp", "$avp(ds_grp)")
+modparam("dispatcher", "cnt_avp", "$avp(ds_cnt)")
+modparam("dispatcher", "hash_pvar", "$avp(ds_grp)")
+modparam("dispatcher", "ds_hash_size", KZ_DISPATCHER_HASH_SIZE)
+modparam("dispatcher", "setid_pvname", "$var(setid)")
+modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+modparam("dispatcher", "ds_ping_method", "OPTIONS")
+modparam("dispatcher", "ds_ping_interval", 10)
+modparam("dispatcher", "ds_probing_threshold", 3)
+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")
+
+#!import_file "dispatcher-network-params.cfg"
+
+## Dispatcher Groups:
+## 1 - Primary media servers
+## 2 - Backup media servers
+## 3 - Alternate media server IPs (used only for classification)
+## 10 - Presence servers (if not locally handled)
+## 20 - Registrar servers (if not locally handled)
+
+
+modparam("rtimer", "timer", "name=dispatcher_reload;interval=20;mode=1;")
+modparam("rtimer", "exec", "timer=dispatcher_reload;route=DISPATCHER_RELOAD")
+
+####### Dispatcher Logic ########
+route[DISPATCHER_CLASSIFY_SOURCE]
+{
+ #!import_file "dispatcher-network-classify.cfg"
+
+ if (is_myself("$ou")) {
+ xlog("$var(log_request_level)", "$ci|log|original R-URI ($ou) is this proxy, treating as external sources\n");
+ } else {
+ $var(classify_dispatcher_flag) = $(sel(cfg_get.kazoo.dispatcher_classify_flags){s.int});
+ if (ds_is_from_list(KZ_DISPATCHER_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_CLASSIFY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP, "$var(classify_dispatcher_flag)")) {
+ xlog("$var(log_request_level)", "$ci|log|originated from internal sources\n");
+ setflag(FLAG_INTERNALLY_SOURCED);
+ } else {
+ xlog("$var(log_request_level)", "$ci|log|originated from external sources\n");
+ }
+ }
+}
+
+# Take the routes from dispatcher - hash over callid
+# If prefered route defined, reorder the destionations
+route[DISPATCHER_FIND_ROUTES]
+{
+
+ $var(ds_primary_group) = $sel(cfg_get.kazoo.dispatcher_primary_group);
+ $var(ds_backup_group) = $sel(cfg_get.kazoo.dispatcher_secondary_group);
+
+ #!ifndef PRESENCE_ROLE
+ if (is_method("SUBSCRIBE")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP;
+ add_path();
+ }
+ #!endif
+
+ #!ifndef REGISTRAR_ROLE
+ if (is_method("REGISTER")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP;
+ add_path();
+ }
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_FAST_PICKUP_ATTEMPT);
+ #!endif
+
+ #!import_file "dispatcher-network-find.cfg"
+
+ $var(ds_group) = $var(ds_primary_group);
+
+ 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)", "$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;
+ } else {
+ $var(ds_group) = $var(ds_backup_group);
+ }
+ }
+
+ $var(user_source) = $(ct{tobody.user}) + "@" + $si + ":" + $sp;
+ if ($sht(associations=>$var(user_source)) != $null) {
+ if($sel(cfg_get.kazoo.dispatcher_route_to_associated_media) == 1) {
+ $var(prefered_route) = $sht(associations=>$var(user_source));
+ xlog("L_INFO", "$ci|route|found association for contact uri $var(user_source)\n");
+ route(DISPATCHER_PREFERRED_ROUTE);
+ }
+ $sht(associations=>$var(user_source)) = $null;
+ }
+
+ $avp(ds_retries) = 0;
+
+}
+
+route[DISPATCHER_PREFERRED_ROUTE]
+{
+ ######
+ # check if the preferred route is active
+ ######
+ if(!ds_is_from_list(-1, 6, "$var(prefered_route)")) {
+ xlog("L_INFO", "$ci|log|associated media server $var(prefered_route) is inactive, moving to $avp(ds_dst)\n");
+ return -1;
+ }
+
+ xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to maintain association with $var(prefered_route)\n");
+
+ ######
+ # filters current list from prefered route
+ # * saves the current list to temp avp removing the preferred route if it exists
+ # * resets current list
+ # * copies the temp back to list
+ # sets the prefered at top
+ # sets $du (destination) to prefered
+ ######
+
+ $var(i) = 0;
+ while($(avp(ds_dst)[$var(i)]) != $null) {
+ if($(avp(ds_dst)[$var(i)]) != $var(prefered_route)) {
+ $avp(tmp_ds_dst) = $(avp(ds_dst)[$var(i)]);
+ }
+ $var(i) = $var(i) + 1;
+ }
+
+ $(avp(ds_dst)[*]) = $null;
+
+ $var(i) = 0;
+ while($(avp(tmp_ds_dst)[$var(i)]) != $null) {
+ $avp(ds_dst) = $(avp(tmp_ds_dst)[$var(i)]);
+ $var(i) = $var(i) + 1;
+ }
+
+ $avp(ds_dst) = $var(prefered_route);
+ $du = $var(prefered_route);
+
+ $(avp(tmp_ds_dst)[*]) = $null;
+
+ return 1;
+}
+
+route[DISPATCHER_NEXT_ROUTE]
+{
+ if($avp(ds_retries) >= $sel(cfg_get.kazoo.dispatcher_max_retries)) return;
+
+ $avp(ds_retries) = $avp(ds_retries) + 1;
+ $var(remaining) = $(sel(cfg_get.kazoo.dispatcher_max_retries){s.int}) - $avp(ds_retries);
+
+ if(ds_next_dst()) {
+
+ xlog("L_INFO", "$ci|log|remaining failed retry attempts: $var(remaining)\n");
+ xlog("L_INFO", "$ci|log|routing call to next media server $du\n");
+
+ setflag(FLAG_SKIP_NAT_CORRECTION);
+
+ # reset the final reply timer
+ $avp(final_reply_timer) = 3;
+
+ # relay the request to the new media server
+ route(RELAY);
+
+ exit();
+ }
+}
+
+event_route[dispatcher:dst-down]
+{
+ xlog("L_WARNING", "Destination down: $ru\n");
+}
+
+event_route[dispatcher:dst-up]
+{
+ xlog("L_NOTICE", "Destination up: $ru\n");
+}
+
+
+route[DISPATCHER_CHECK_MEDIA_SERVER]
+{
+ $var(check_media_server_ret) = 0;
+ if($sel(cfg_get.kazoo.dispatcher_auto_add) == 1) {
+ $var(SetId) = 1;
+ if($var(Zone) != "MY_AMQP_ZONE") {
+ $var(SetId) = 2;
+ }
+ $var(flags) = KZ_DISPATCHER_ADD_FLAGS;
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ #!import_file "dispatcher-custom-media-check.cfg"
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+
+ if($sel(cfg_get.kazoo.dispatcher_add_secondary_ip) == 1) {
+ if($var(MediaIP) != "" && $var(MediaIP) != $(var(MediaUrl){uri.host})) {
+ $var(MediaUrlBack) = $var(MediaUrl);
+ $var(MediaUrl) = $_s($(var(MediaUrlBack){uri.scheme}):$var(MediaIP):$(var(MediaUrlBack){uri.port}));
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ $var(SetId) = $sel(cfg_get.kazoo.dispatcher_add_secondary_ip_group);
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+ $var(MediaUrl) = $var(MediaUrlBack);
+ }
+ }
+
+ }
+ return $var(check_media_server_ret);
+}
+
+route[DISPATCHER_RELOAD]
+{
+ if($shv(dispatcher_reload) == 1) {
+ xlog("L_NOTICE", "reloading dispatcher table\n");
+ ds_reload();
+ };
+ $shv(dispatcher_reload) = 0;
+}
+
+route[DISPATCHER_STATUS]
+{
+ jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.list", "id": 1}');
+ $var(Sets) = $(jsonrpl(body){kz.json, result.NRSETS});
+ $var(i) = 0;
+ $var(ds_groups_json)="";
+ $var(Sep1) = "";
+ while($var(i) < $var(Sets)) {
+ $var(Set) = $(jsonrpl(body){kz.json, result.RECORDS[$var(i)].SET});
+ $var(SetCount) = $(var(Set){kz.json.count,TARGETS});
+ $var(Sep2)="";
+ $var(ds_group_json)="";
+ $var(c) = 0;
+ while($var(c) < $var(SetCount)) {
+ $var(Dest) = $(var(Set){kz.json,TARGETS[$var(c)].DEST});
+ $var(record) = $_s("$(var(Dest){kz.json,URI})" : {"destination" : "$(var(Dest){kz.json,URI})", "flags" : "$(var(Dest){kz.json,FLAGS})", "priority" : $(var(Dest){kz.json,PRIORITY}), "attrs" : "$(var(Dest){kz.json,ATTRS.BODY})"});
+ $var(ds_group_json) = $var(ds_group_json) + $var(Sep2) + $var(record);
+ $var(Sep2) = ",";
+ $var(c) = $var(c) + 1;
+ }
+ $var(ds_groups_json) = $var(ds_groups_json) + $var(Sep1) + $_s("$(var(Set){kz.json,ID})" : { $var(ds_group_json) });
+ $var(Sep1)=", ";
+ $var(i) = $var(i) + 1;
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/dispatcher-role-5.2.cfg b/kamailio-proxy-proxy/dispatcher-role-5.2.cfg
new file mode 100644
index 0000000..be0348d
--- /dev/null
+++ b/kamailio-proxy-proxy/dispatcher-role-5.2.cfg
@@ -0,0 +1,309 @@
+### DISPATCHER ROLE ####
+
+#!trydef KZ_DISPATCHER_PROBE_MODE 1
+#!trydef DISPATCHER_ADD_SERVERS 1
+#!trydef DISPATCHER_ADD_SECONDARY_IP 1
+#!trydef DISPATCHER_SECONDARY_IP_GROUP 3
+#!trydef DISPATCHER_ALG 0
+#!trydef KZ_DISPATCHER_HASH_SIZE 8
+#!trydef KZ_DISPATCHER_ADD_FLAGS 9
+#!trydef KZ_DISPATCHER_PRIMARY_GROUP 1
+#!trydef KZ_DISPATCHER_SECONDARY_GROUP 2
+#!trydef KZ_DISPATCHER_CLASSIFY_GROUP 3
+#!trydef KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP 51
+#!trydef KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP 52
+#!trydef KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP 53
+#!trydef KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP 54
+#!trydef KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP 10
+#!trydef KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP 11
+#!trydef KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP 20
+#!trydef KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP 21
+#!trydef KZ_DISPATCHER_MAX_RETRIES 2
+#!trydef KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA 1
+#!trydef KZ_DISPATCHER_CLASSIFY_FLAGS 2
+#!trydef KZ_DISPATCHER_PRINT_ROUTES 1
+
+kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip = DISPATCHER_ADD_SECONDARY_IP descr "adds internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip_group = DISPATCHER_SECONDARY_IP_GROUP descr "sets the group where to add internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_algorithm = DISPATCHER_ALG descr "dispatcher algorithm to use"
+kazoo.dispatcher_primary_group = KZ_DISPATCHER_PRIMARY_GROUP descr "dispatcher primary group"
+kazoo.dispatcher_secondary_group = KZ_DISPATCHER_SECONDARY_GROUP descr "dispatcher secondary group"
+kazoo.dispatcher_max_retries = KZ_DISPATCHER_MAX_RETRIES descr "max number of retries for media servers"
+kazoo.dispatcher_route_to_associated_media = KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA descr "routes to associated media for atxfer"
+kazoo.dispatcher_classify_flags = KZ_DISPATCHER_CLASSIFY_FLAGS descr "dispatch classifier flags"
+kazoo.dispatcher_print_routes = KZ_DISPATCHER_PRINT_ROUTES descr "should we log the selected routes"
+
+
+####### Dispatcher module ########
+loadmodule "dispatcher.so"
+modparam("dispatcher", "db_url", "KAZOO_DB_URL")
+modparam("dispatcher", "flags", 2)
+modparam("dispatcher", "use_default", 0)
+modparam("dispatcher", "force_dst", 1)
+modparam("dispatcher", "hash_pvar", "$avp(ds_grp)")
+modparam("dispatcher", "setid_pvname", "$var(setid)")
+modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+modparam("dispatcher", "ds_ping_method", "OPTIONS")
+modparam("dispatcher", "ds_ping_interval", 10)
+modparam("dispatcher", "ds_probing_threshold", 3)
+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")
+modparam("dispatcher", "xavp_dst", "ds_dst")
+modparam("dispatcher", "xavp_ctx", "ds_ctx")
+modparam("dispatcher", "ds_hash_size", KZ_DISPATCHER_HASH_SIZE)
+
+## Dispatcher Groups:
+## 1 - Primary media servers
+## 2 - Backup media servers
+## 3 - Alternate media server IPs (used only for classification)
+## 10 - Presence servers (if not locally handled)
+## 20 - Registrar servers (if not locally handled)
+
+
+modparam("rtimer", "timer", "name=dispatcher_reload;interval=20;mode=1;")
+modparam("rtimer", "exec", "timer=dispatcher_reload;route=DISPATCHER_RELOAD")
+
+####### Dispatcher Logic ########
+route[DISPATCHER_CLASSIFY_SOURCE]
+{
+ route_if_exists("DISPATCHER_CUSTOM_NETWORK_CLASSIFY");
+
+ if (!isflagset(FLAG_NETWORK_CLASSIFIED)) {
+ if (is_myself("$ou")) {
+ xlog("$var(log_request_level)", "$ci|log|original R-URI ($ou) is this proxy, treating as external sources\n");
+ } else {
+ $var(classify_dispatcher_flag) = $(sel(cfg_get.kazoo.dispatcher_classify_flags){s.int});
+ if (ds_is_from_list(KZ_DISPATCHER_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_CLASSIFY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP, "$var(classify_dispatcher_flag)")) {
+ xlog("$var(log_request_level)", "$ci|log|originated from internal sources\n");
+ setflag(FLAG_INTERNALLY_SOURCED);
+ } else {
+ xlog("$var(log_request_level)", "$ci|log|originated from external sources\n");
+ }
+ }
+ }
+}
+
+# Take the routes from dispatcher - hash over callid
+# If prefered route defined, reorder the destionations
+route[DISPATCHER_FIND_ROUTES]
+{
+
+ $var(ds_primary_group) = $(sel(cfg_get.kazoo.dispatcher_primary_group){s.int});
+ $var(ds_backup_group) = $(sel(cfg_get.kazoo.dispatcher_secondary_group){s.int});
+
+ #!ifndef PRESENCE_ROLE
+ if (is_method("SUBSCRIBE")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifndef REGISTRAR_ROLE
+ if (is_method("REGISTER")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_FAST_PICKUP_ATTEMPT);
+ #!endif
+
+ route_if_exists("DISPATCHER_CUSTOM_SET_GROUPS");
+
+ $var(ds_group) = $var(ds_primary_group);
+
+ $var(ds_alg) = $sel(cfg_get.kazoo.dispatcher_algorithm);
+ if(ds_list_exists("$var(ds_backup_group)")) {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg);$var(ds_backup_group)=$var(ds_alg));
+ } else {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg));
+ }
+
+ ds_select_routes("$var(ds_rule)", "2");
+ if ($xavp(ds_ctx=>cnt) == 0) {
+ xlog("L_WARN", "$ci|end|no servers available in primary or backup group\n");
+ sl_send_reply("480", "All servers busy");
+ exit;
+ }
+
+ route(PRINT_ROUTES);
+
+ $var(user_source) = $(ct{tobody.user}) + "@" + $si + ":" + $sp;
+ $var(redirect) = @from.uri.user + "@" + @from.uri.host + "->"
+ + @ruri.user + "@" + @ruri.host;
+ if ($sht(redirects=>$var(redirect)) != $null) {
+ $var(prefered_route) = $sht(redirects=>$var(redirect));
+ xlog("L_INFO", "$ci|route|found redirect for $var(redirect) to $var(prefered_route)\n");
+ $avp(AVP_REDIRECT_KEY) = $var(redirect);
+ route(DISPATCHER_PREFERRED_ROUTE);
+ } else if ($sht(associations=>$var(user_source)) != $null) {
+ if($sel(cfg_get.kazoo.dispatcher_route_to_associated_media) == 1) {
+ $var(prefered_route) = $sht(associations=>$var(user_source));
+ xlog("L_INFO", "$ci|route|found association for contact uri $var(user_source)\n");
+ route(DISPATCHER_PREFERRED_ROUTE);
+ }
+ $sht(associations=>$var(user_source)) = $null;
+ }
+
+ $avp(ds_group) = $xavp(ds_dst=>grp);
+ $avp(ds_retries) = 0;
+ ds_set_dst();
+
+}
+
+route[DISPATCHER_PREFERRED_ROUTE]
+{
+ if(!ds_is_from_list(-1, 6, "$var(prefered_route)")) {
+ xlog("L_INFO", "$ci|log|associated media server $var(prefered_route) is inactive, moving to $xavp(ds_dst=>uri)\n");
+ return -1;
+ }
+
+ xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to maintain association with $var(prefered_route)\n");
+
+ $var(i) = $xavp(ds_ctx=>cnt) - 1;
+ while($var(i) >= 0) {
+ if($xavp(ds_dst[$var(i)]=>uri) == $var(prefered_route)) {
+ $xavp(ds_dst[$var(i)]) = $null;
+ }
+ $var(i) = $var(i) - 1;
+ }
+
+ $xavp(ds_dst=>uri) = $var(prefered_route);
+ $xavp(ds_dst[0]=>grp) = $var(setid);
+ $xavp(ds_dst[0]=>attrs) = $var(attrs);
+
+ return 1;
+}
+
+route[PRINT_ROUTES]
+{
+ if($sel(cfg_get.kazoo.dispatcher_print_routes) == 0) return;
+
+ $var(i) = 0;
+ while($xavp(ds_dst[$var(i)]=>uri) != $null) {
+ xlog("L_INFO", "$ci|route|group $xavp(ds_dst[$var(i)]=>grp) => $xavp(ds_dst[$var(i)]=>uri) => zone $(xavp(ds_dst[$var(i)]=>attrs){param.value,zone})\n");
+ $var(i) = $var(i) + 1;
+ }
+
+}
+
+#!import_file "dispatcher-next-route.cfg"
+
+#!ifndef CUSTOM_DISPATCHER_NEXT_ROUTE
+# Try next destinations in failure route
+route[DISPATCHER_NEXT_ROUTE]
+{
+
+ if($avp(ds_retries) >= $sel(cfg_get.kazoo.dispatcher_max_retries)) return;
+
+ $avp(ds_retries) = $avp(ds_retries) + 1;
+ if(ds_next_dst()) {
+ xlog("L_INFO", "$ci|log|routing call to next media server $du\n");
+
+ setflag(FLAG_SKIP_NAT_CORRECTION);
+
+ # relay the request to the new media server
+ route(RELAY);
+
+ exit;
+ }
+}
+#!endif
+
+event_route[dispatcher:dst-down]
+{
+ xlog("L_WARNING", "Destination down: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+event_route[dispatcher:dst-up]
+{
+ xlog("L_WARNING", "Destination up: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+
+route[DISPATCHER_CHECK_MEDIA_SERVER]
+{
+ $var(check_media_server_ret) = 0;
+ if($sel(cfg_get.kazoo.dispatcher_auto_add) == 1) {
+ $var(SetId) = 1;
+ if($var(Zone) != "MY_AMQP_ZONE") {
+ $var(SetId) = 2;
+ }
+ $var(flags) = KZ_DISPATCHER_ADD_FLAGS;
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+
+ if($sel(cfg_get.kazoo.dispatcher_add_secondary_ip) == 1) {
+ if($var(MediaIP) != "" && $var(MediaIP) != $(var(MediaUrl){uri.host})) {
+ $var(MediaUrlBack) = $var(MediaUrl);
+ $var(MediaUrl) = $_s($(var(MediaUrlBack){uri.scheme}):$var(MediaIP):$(var(MediaUrlBack){uri.port}));
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ $var(SetId) = $sel(cfg_get.kazoo.dispatcher_add_secondary_ip_group);
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+ $var(MediaUrl) = $var(MediaUrlBack);
+ }
+ }
+
+ }
+ return $var(check_media_server_ret);
+}
+
+route[DISPATCHER_RELOAD]
+{
+ if($shv(dispatcher_reload) == 1) {
+ xlog("L_WARNING", "reloading dispatcher table\n");
+ ds_reload();
+ };
+ $shv(dispatcher_reload) = 0;
+}
+
+route[DISPATCHER_STATUS]
+{
+ jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.list", "id": 1}');
+ $var(Sets) = $(jsonrpl(body){kz.json, result.NRSETS});
+ $var(i) = 0;
+ $var(ds_groups_json)="";
+ $var(Sep1) = "";
+ while($var(i) < $var(Sets)) {
+ $var(Set) = $(jsonrpl(body){kz.json, result.RECORDS[$var(i)].SET});
+ $var(SetCount) = $(var(Set){kz.json.count,TARGETS});
+ $var(Sep2)="";
+ $var(ds_group_json)="";
+ $var(c) = 0;
+ while($var(c) < $var(SetCount)) {
+ $var(Dest) = $(var(Set){kz.json,TARGETS[$var(c)].DEST});
+ $var(record) = $_s("$(var(Dest){kz.json,URI})" : {"destination" : "$(var(Dest){kz.json,URI})", "flags" : "$(var(Dest){kz.json,FLAGS})", "priority" : $(var(Dest){kz.json,PRIORITY}), "attrs" : "$(var(Dest){kz.json,ATTRS.BODY})"});
+ $var(ds_group_json) = $var(ds_group_json) + $var(Sep2) + $var(record);
+ $var(Sep2) = ",";
+ $var(c) = $var(c) + 1;
+ }
+ $var(ds_groups_json) = $var(ds_groups_json) + $var(Sep1) + $_s("$(var(Set){kz.json,ID})" : { $var(ds_group_json) });
+ $var(Sep1)=", ";
+ $var(i) = $var(i) + 1;
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/dispatcher-role-5.4.cfg b/kamailio-proxy-proxy/dispatcher-role-5.4.cfg
new file mode 100644
index 0000000..be0348d
--- /dev/null
+++ b/kamailio-proxy-proxy/dispatcher-role-5.4.cfg
@@ -0,0 +1,309 @@
+### DISPATCHER ROLE ####
+
+#!trydef KZ_DISPATCHER_PROBE_MODE 1
+#!trydef DISPATCHER_ADD_SERVERS 1
+#!trydef DISPATCHER_ADD_SECONDARY_IP 1
+#!trydef DISPATCHER_SECONDARY_IP_GROUP 3
+#!trydef DISPATCHER_ALG 0
+#!trydef KZ_DISPATCHER_HASH_SIZE 8
+#!trydef KZ_DISPATCHER_ADD_FLAGS 9
+#!trydef KZ_DISPATCHER_PRIMARY_GROUP 1
+#!trydef KZ_DISPATCHER_SECONDARY_GROUP 2
+#!trydef KZ_DISPATCHER_CLASSIFY_GROUP 3
+#!trydef KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP 51
+#!trydef KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP 52
+#!trydef KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP 53
+#!trydef KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP 54
+#!trydef KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP 10
+#!trydef KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP 11
+#!trydef KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP 20
+#!trydef KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP 21
+#!trydef KZ_DISPATCHER_MAX_RETRIES 2
+#!trydef KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA 1
+#!trydef KZ_DISPATCHER_CLASSIFY_FLAGS 2
+#!trydef KZ_DISPATCHER_PRINT_ROUTES 1
+
+kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip = DISPATCHER_ADD_SECONDARY_IP descr "adds internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip_group = DISPATCHER_SECONDARY_IP_GROUP descr "sets the group where to add internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_algorithm = DISPATCHER_ALG descr "dispatcher algorithm to use"
+kazoo.dispatcher_primary_group = KZ_DISPATCHER_PRIMARY_GROUP descr "dispatcher primary group"
+kazoo.dispatcher_secondary_group = KZ_DISPATCHER_SECONDARY_GROUP descr "dispatcher secondary group"
+kazoo.dispatcher_max_retries = KZ_DISPATCHER_MAX_RETRIES descr "max number of retries for media servers"
+kazoo.dispatcher_route_to_associated_media = KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA descr "routes to associated media for atxfer"
+kazoo.dispatcher_classify_flags = KZ_DISPATCHER_CLASSIFY_FLAGS descr "dispatch classifier flags"
+kazoo.dispatcher_print_routes = KZ_DISPATCHER_PRINT_ROUTES descr "should we log the selected routes"
+
+
+####### Dispatcher module ########
+loadmodule "dispatcher.so"
+modparam("dispatcher", "db_url", "KAZOO_DB_URL")
+modparam("dispatcher", "flags", 2)
+modparam("dispatcher", "use_default", 0)
+modparam("dispatcher", "force_dst", 1)
+modparam("dispatcher", "hash_pvar", "$avp(ds_grp)")
+modparam("dispatcher", "setid_pvname", "$var(setid)")
+modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+modparam("dispatcher", "ds_ping_method", "OPTIONS")
+modparam("dispatcher", "ds_ping_interval", 10)
+modparam("dispatcher", "ds_probing_threshold", 3)
+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")
+modparam("dispatcher", "xavp_dst", "ds_dst")
+modparam("dispatcher", "xavp_ctx", "ds_ctx")
+modparam("dispatcher", "ds_hash_size", KZ_DISPATCHER_HASH_SIZE)
+
+## Dispatcher Groups:
+## 1 - Primary media servers
+## 2 - Backup media servers
+## 3 - Alternate media server IPs (used only for classification)
+## 10 - Presence servers (if not locally handled)
+## 20 - Registrar servers (if not locally handled)
+
+
+modparam("rtimer", "timer", "name=dispatcher_reload;interval=20;mode=1;")
+modparam("rtimer", "exec", "timer=dispatcher_reload;route=DISPATCHER_RELOAD")
+
+####### Dispatcher Logic ########
+route[DISPATCHER_CLASSIFY_SOURCE]
+{
+ route_if_exists("DISPATCHER_CUSTOM_NETWORK_CLASSIFY");
+
+ if (!isflagset(FLAG_NETWORK_CLASSIFIED)) {
+ if (is_myself("$ou")) {
+ xlog("$var(log_request_level)", "$ci|log|original R-URI ($ou) is this proxy, treating as external sources\n");
+ } else {
+ $var(classify_dispatcher_flag) = $(sel(cfg_get.kazoo.dispatcher_classify_flags){s.int});
+ if (ds_is_from_list(KZ_DISPATCHER_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_CLASSIFY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP, "$var(classify_dispatcher_flag)")) {
+ xlog("$var(log_request_level)", "$ci|log|originated from internal sources\n");
+ setflag(FLAG_INTERNALLY_SOURCED);
+ } else {
+ xlog("$var(log_request_level)", "$ci|log|originated from external sources\n");
+ }
+ }
+ }
+}
+
+# Take the routes from dispatcher - hash over callid
+# If prefered route defined, reorder the destionations
+route[DISPATCHER_FIND_ROUTES]
+{
+
+ $var(ds_primary_group) = $(sel(cfg_get.kazoo.dispatcher_primary_group){s.int});
+ $var(ds_backup_group) = $(sel(cfg_get.kazoo.dispatcher_secondary_group){s.int});
+
+ #!ifndef PRESENCE_ROLE
+ if (is_method("SUBSCRIBE")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifndef REGISTRAR_ROLE
+ if (is_method("REGISTER")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_FAST_PICKUP_ATTEMPT);
+ #!endif
+
+ route_if_exists("DISPATCHER_CUSTOM_SET_GROUPS");
+
+ $var(ds_group) = $var(ds_primary_group);
+
+ $var(ds_alg) = $sel(cfg_get.kazoo.dispatcher_algorithm);
+ if(ds_list_exists("$var(ds_backup_group)")) {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg);$var(ds_backup_group)=$var(ds_alg));
+ } else {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg));
+ }
+
+ ds_select_routes("$var(ds_rule)", "2");
+ if ($xavp(ds_ctx=>cnt) == 0) {
+ xlog("L_WARN", "$ci|end|no servers available in primary or backup group\n");
+ sl_send_reply("480", "All servers busy");
+ exit;
+ }
+
+ route(PRINT_ROUTES);
+
+ $var(user_source) = $(ct{tobody.user}) + "@" + $si + ":" + $sp;
+ $var(redirect) = @from.uri.user + "@" + @from.uri.host + "->"
+ + @ruri.user + "@" + @ruri.host;
+ if ($sht(redirects=>$var(redirect)) != $null) {
+ $var(prefered_route) = $sht(redirects=>$var(redirect));
+ xlog("L_INFO", "$ci|route|found redirect for $var(redirect) to $var(prefered_route)\n");
+ $avp(AVP_REDIRECT_KEY) = $var(redirect);
+ route(DISPATCHER_PREFERRED_ROUTE);
+ } else if ($sht(associations=>$var(user_source)) != $null) {
+ if($sel(cfg_get.kazoo.dispatcher_route_to_associated_media) == 1) {
+ $var(prefered_route) = $sht(associations=>$var(user_source));
+ xlog("L_INFO", "$ci|route|found association for contact uri $var(user_source)\n");
+ route(DISPATCHER_PREFERRED_ROUTE);
+ }
+ $sht(associations=>$var(user_source)) = $null;
+ }
+
+ $avp(ds_group) = $xavp(ds_dst=>grp);
+ $avp(ds_retries) = 0;
+ ds_set_dst();
+
+}
+
+route[DISPATCHER_PREFERRED_ROUTE]
+{
+ if(!ds_is_from_list(-1, 6, "$var(prefered_route)")) {
+ xlog("L_INFO", "$ci|log|associated media server $var(prefered_route) is inactive, moving to $xavp(ds_dst=>uri)\n");
+ return -1;
+ }
+
+ xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to maintain association with $var(prefered_route)\n");
+
+ $var(i) = $xavp(ds_ctx=>cnt) - 1;
+ while($var(i) >= 0) {
+ if($xavp(ds_dst[$var(i)]=>uri) == $var(prefered_route)) {
+ $xavp(ds_dst[$var(i)]) = $null;
+ }
+ $var(i) = $var(i) - 1;
+ }
+
+ $xavp(ds_dst=>uri) = $var(prefered_route);
+ $xavp(ds_dst[0]=>grp) = $var(setid);
+ $xavp(ds_dst[0]=>attrs) = $var(attrs);
+
+ return 1;
+}
+
+route[PRINT_ROUTES]
+{
+ if($sel(cfg_get.kazoo.dispatcher_print_routes) == 0) return;
+
+ $var(i) = 0;
+ while($xavp(ds_dst[$var(i)]=>uri) != $null) {
+ xlog("L_INFO", "$ci|route|group $xavp(ds_dst[$var(i)]=>grp) => $xavp(ds_dst[$var(i)]=>uri) => zone $(xavp(ds_dst[$var(i)]=>attrs){param.value,zone})\n");
+ $var(i) = $var(i) + 1;
+ }
+
+}
+
+#!import_file "dispatcher-next-route.cfg"
+
+#!ifndef CUSTOM_DISPATCHER_NEXT_ROUTE
+# Try next destinations in failure route
+route[DISPATCHER_NEXT_ROUTE]
+{
+
+ if($avp(ds_retries) >= $sel(cfg_get.kazoo.dispatcher_max_retries)) return;
+
+ $avp(ds_retries) = $avp(ds_retries) + 1;
+ if(ds_next_dst()) {
+ xlog("L_INFO", "$ci|log|routing call to next media server $du\n");
+
+ setflag(FLAG_SKIP_NAT_CORRECTION);
+
+ # relay the request to the new media server
+ route(RELAY);
+
+ exit;
+ }
+}
+#!endif
+
+event_route[dispatcher:dst-down]
+{
+ xlog("L_WARNING", "Destination down: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+event_route[dispatcher:dst-up]
+{
+ xlog("L_WARNING", "Destination up: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+
+route[DISPATCHER_CHECK_MEDIA_SERVER]
+{
+ $var(check_media_server_ret) = 0;
+ if($sel(cfg_get.kazoo.dispatcher_auto_add) == 1) {
+ $var(SetId) = 1;
+ if($var(Zone) != "MY_AMQP_ZONE") {
+ $var(SetId) = 2;
+ }
+ $var(flags) = KZ_DISPATCHER_ADD_FLAGS;
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+
+ if($sel(cfg_get.kazoo.dispatcher_add_secondary_ip) == 1) {
+ if($var(MediaIP) != "" && $var(MediaIP) != $(var(MediaUrl){uri.host})) {
+ $var(MediaUrlBack) = $var(MediaUrl);
+ $var(MediaUrl) = $_s($(var(MediaUrlBack){uri.scheme}):$var(MediaIP):$(var(MediaUrlBack){uri.port}));
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ $var(SetId) = $sel(cfg_get.kazoo.dispatcher_add_secondary_ip_group);
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+ $var(MediaUrl) = $var(MediaUrlBack);
+ }
+ }
+
+ }
+ return $var(check_media_server_ret);
+}
+
+route[DISPATCHER_RELOAD]
+{
+ if($shv(dispatcher_reload) == 1) {
+ xlog("L_WARNING", "reloading dispatcher table\n");
+ ds_reload();
+ };
+ $shv(dispatcher_reload) = 0;
+}
+
+route[DISPATCHER_STATUS]
+{
+ jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.list", "id": 1}');
+ $var(Sets) = $(jsonrpl(body){kz.json, result.NRSETS});
+ $var(i) = 0;
+ $var(ds_groups_json)="";
+ $var(Sep1) = "";
+ while($var(i) < $var(Sets)) {
+ $var(Set) = $(jsonrpl(body){kz.json, result.RECORDS[$var(i)].SET});
+ $var(SetCount) = $(var(Set){kz.json.count,TARGETS});
+ $var(Sep2)="";
+ $var(ds_group_json)="";
+ $var(c) = 0;
+ while($var(c) < $var(SetCount)) {
+ $var(Dest) = $(var(Set){kz.json,TARGETS[$var(c)].DEST});
+ $var(record) = $_s("$(var(Dest){kz.json,URI})" : {"destination" : "$(var(Dest){kz.json,URI})", "flags" : "$(var(Dest){kz.json,FLAGS})", "priority" : $(var(Dest){kz.json,PRIORITY}), "attrs" : "$(var(Dest){kz.json,ATTRS.BODY})"});
+ $var(ds_group_json) = $var(ds_group_json) + $var(Sep2) + $var(record);
+ $var(Sep2) = ",";
+ $var(c) = $var(c) + 1;
+ }
+ $var(ds_groups_json) = $var(ds_groups_json) + $var(Sep1) + $_s("$(var(Set){kz.json,ID})" : { $var(ds_group_json) });
+ $var(Sep1)=", ";
+ $var(i) = $var(i) + 1;
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/dispatcher-role-5.5.cfg b/kamailio-proxy-proxy/dispatcher-role-5.5.cfg
new file mode 100644
index 0000000..73bf895
--- /dev/null
+++ b/kamailio-proxy-proxy/dispatcher-role-5.5.cfg
@@ -0,0 +1,311 @@
+### DISPATCHER ROLE ####
+
+#!trydef KZ_DISPATCHER_PROBE_MODE 1
+#!trydef DISPATCHER_ADD_SERVERS 1
+#!trydef DISPATCHER_ADD_SECONDARY_IP 1
+#!trydef DISPATCHER_SECONDARY_IP_GROUP 3
+#!trydef DISPATCHER_ALG 0
+#!trydef KZ_DISPATCHER_HASH_SIZE 8
+#!trydef KZ_DISPATCHER_ADD_FLAGS 9
+#!trydef KZ_DISPATCHER_PRIMARY_GROUP 1
+#!trydef KZ_DISPATCHER_SECONDARY_GROUP 2
+#!trydef KZ_DISPATCHER_CLASSIFY_GROUP 3
+#!trydef KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP 51
+#!trydef KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP 52
+#!trydef KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP 53
+#!trydef KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP 54
+#!trydef KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP 10
+#!trydef KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP 11
+#!trydef KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP 20
+#!trydef KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP 21
+#!trydef KZ_DISPATCHER_MAX_RETRIES 2
+#!trydef KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA 1
+#!trydef KZ_DISPATCHER_CLASSIFY_FLAGS 2
+#!trydef KZ_DISPATCHER_PRINT_ROUTES 1
+
+kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip = DISPATCHER_ADD_SECONDARY_IP descr "adds internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_add_secondary_ip_group = DISPATCHER_SECONDARY_IP_GROUP descr "sets the group where to add internal ip from media servers reported by ecallmgr"
+kazoo.dispatcher_algorithm = DISPATCHER_ALG descr "dispatcher algorithm to use"
+kazoo.dispatcher_primary_group = KZ_DISPATCHER_PRIMARY_GROUP descr "dispatcher primary group"
+kazoo.dispatcher_secondary_group = KZ_DISPATCHER_SECONDARY_GROUP descr "dispatcher secondary group"
+kazoo.dispatcher_max_retries = KZ_DISPATCHER_MAX_RETRIES descr "max number of retries for media servers"
+kazoo.dispatcher_route_to_associated_media = KZ_DISPATCHER_ROUTE_ASSOCIATED_MEDIA descr "routes to associated media for atxfer"
+kazoo.dispatcher_classify_flags = KZ_DISPATCHER_CLASSIFY_FLAGS descr "dispatch classifier flags"
+kazoo.dispatcher_print_routes = KZ_DISPATCHER_PRINT_ROUTES descr "should we log the selected routes"
+
+
+####### Dispatcher module ########
+loadmodule "dispatcher.so"
+modparam("dispatcher", "db_url", "KAZOO_DB_URL")
+modparam("dispatcher", "flags", 2)
+modparam("dispatcher", "use_default", 0)
+modparam("dispatcher", "force_dst", 1)
+modparam("dispatcher", "hash_pvar", "$avp(ds_grp)")
+modparam("dispatcher", "setid_pvname", "$var(setid)")
+modparam("dispatcher", "attrs_pvname", "$var(attrs)")
+modparam("dispatcher", "ds_ping_method", "OPTIONS")
+modparam("dispatcher", "ds_ping_interval", 10)
+modparam("dispatcher", "ds_probing_threshold", 3)
+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")
+modparam("dispatcher", "xavp_dst", "ds_dst")
+modparam("dispatcher", "xavp_ctx", "ds_ctx")
+modparam("dispatcher", "ds_hash_size", KZ_DISPATCHER_HASH_SIZE)
+
+## Dispatcher Groups:
+## 1 - Primary media servers
+## 2 - Backup media servers
+## 3 - Alternate media server IPs (used only for classification)
+## 10 - Presence servers (if not locally handled)
+## 20 - Registrar servers (if not locally handled)
+
+
+modparam("rtimer", "timer", "name=dispatcher_reload;interval=20;mode=1;")
+modparam("rtimer", "exec", "timer=dispatcher_reload;route=DISPATCHER_RELOAD")
+
+####### Dispatcher Logic ########
+route[DISPATCHER_CLASSIFY_SOURCE]
+{
+ route_if_exists("DISPATCHER_CUSTOM_NETWORK_CLASSIFY");
+
+ if (!isflagset(FLAG_NETWORK_CLASSIFIED)) {
+ if (is_myself("$ou")) {
+ xlog("$var(log_request_level)", "$ci|log|original R-URI ($ou) is this proxy, treating as external sources\n");
+ } else {
+ $var(classify_dispatcher_flag) = $(sel(cfg_get.kazoo.dispatcher_classify_flags){s.int});
+ if (ds_is_from_list(KZ_DISPATCHER_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_CLASSIFY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET1_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_ALTNET2_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP, "$var(classify_dispatcher_flag)") ||
+ ds_is_from_list(KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP, "$var(classify_dispatcher_flag)")) {
+ xlog("$var(log_request_level)", "$ci|log|originated from internal sources\n");
+ setflag(FLAG_INTERNALLY_SOURCED);
+ } else {
+ xlog("$var(log_request_level)", "$ci|log|originated from external sources\n");
+ }
+ }
+ }
+}
+
+# Take the routes from dispatcher - hash over callid
+# If prefered route defined, reorder the destionations
+route[DISPATCHER_FIND_ROUTES]
+{
+
+ $var(ds_primary_group) = $(sel(cfg_get.kazoo.dispatcher_primary_group){s.int});
+ $var(ds_backup_group) = $(sel(cfg_get.kazoo.dispatcher_secondary_group){s.int});
+
+ #!ifndef PRESENCE_ROLE
+ if (is_method("SUBSCRIBE")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_PRESENCE_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_PRESENCE_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifndef REGISTRAR_ROLE
+ if (is_method("REGISTER")) {
+ $var(ds_primary_group) = KZ_DISPATCHER_REGISTRAR_PRIMARY_GROUP;
+ $var(ds_backup_group) = KZ_DISPATCHER_REGISTRAR_SECONDARY_GROUP;
+ }
+ #!endif
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_FAST_PICKUP_ATTEMPT);
+ #!endif
+
+ route_if_exists("DISPATCHER_CUSTOM_SET_GROUPS");
+
+ $var(ds_group) = $var(ds_primary_group);
+
+ $var(ds_alg) = $sel(cfg_get.kazoo.dispatcher_algorithm);
+ if(ds_list_exists("$var(ds_backup_group)")) {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg);$var(ds_backup_group)=$var(ds_alg));
+ } else {
+ $var(ds_rule) = $_s($var(ds_primary_group)=$var(ds_alg));
+ }
+
+ ds_select_routes("$var(ds_rule)", "2");
+ if ($xavp(ds_ctx=>cnt) == 0) {
+ xlog("L_WARN", "$ci|end|no servers available in primary or backup group rule: $var(ds_rule)\n");
+ sl_send_reply("480", "All servers busy");
+ exit;
+ }
+
+ route(PRINT_ROUTES);
+
+ $var(user_source) = $(ct{tobody.user}) + "@" + $si + ":" + $sp;
+ $var(redirect) = @from.uri.user + "@" + @from.uri.host + "->"
+ + @ruri.user + "@" + @ruri.host;
+ if ($sht(redirects=>$var(redirect)) != $null) {
+ $var(prefered_route) = $sht(redirects=>$var(redirect));
+ xlog("L_INFO", "$ci|route|found redirect for $var(redirect) to $var(prefered_route)\n");
+ $avp(AVP_REDIRECT_KEY) = $var(redirect);
+ route(DISPATCHER_PREFERRED_ROUTE);
+ } else if ($sht(associations=>$var(user_source)) != $null) {
+ if($sel(cfg_get.kazoo.dispatcher_route_to_associated_media) == 1) {
+ $var(prefered_route) = $sht(associations=>$var(user_source));
+ xlog("L_INFO", "$ci|route|found association for contact uri $var(user_source)\n");
+ route(DISPATCHER_PREFERRED_ROUTE);
+ }
+ $sht(associations=>$var(user_source)) = $null;
+ }
+
+ $avp(ds_group) = $xavp(ds_dst=>grp);
+ $avp(ds_retries) = 0;
+ ds_set_dst();
+
+}
+
+route[DISPATCHER_PREFERRED_ROUTE]
+{
+ if(!ds_is_from_list(-1, 6, "$var(prefered_route)")) {
+ xlog("L_INFO", "$ci|log|associated media server $var(prefered_route) is inactive, moving to $xavp(ds_dst=>uri)\n");
+ return -1;
+ }
+
+ xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to maintain association with $var(prefered_route)\n");
+
+ $var(i) = $xavp(ds_ctx=>cnt) - 1;
+ while($var(i) >= 0) {
+ if($xavp(ds_dst[$var(i)]=>uri) == $var(prefered_route)) {
+ $xavp(ds_dst[$var(i)]) = $null;
+ }
+ $var(i) = $var(i) - 1;
+ }
+
+ $xavp(ds_dst=>uri) = $var(prefered_route);
+ $xavp(ds_dst[0]=>grp) = $var(setid);
+ $xavp(ds_dst[0]=>attrs) = $var(attrs);
+
+ return 1;
+}
+
+route[PRINT_ROUTES]
+{
+ if($sel(cfg_get.kazoo.dispatcher_print_routes) == 0) return;
+
+ $var(i) = 0;
+ while($xavp(ds_dst[$var(i)]=>uri) != $null) {
+ xlog("L_INFO", "$ci|route|group $xavp(ds_dst[$var(i)]=>grp) => $xavp(ds_dst[$var(i)]=>uri) => zone $(xavp(ds_dst[$var(i)]=>attrs){param.value,zone})\n");
+ $var(i) = $var(i) + 1;
+ }
+
+}
+
+#!import_file "dispatcher-next-route.cfg"
+
+#!ifndef CUSTOM_DISPATCHER_NEXT_ROUTE
+# Try next destinations in failure route
+route[DISPATCHER_NEXT_ROUTE]
+{
+
+ if($avp(ds_retries) >= $sel(cfg_get.kazoo.dispatcher_max_retries)) return;
+
+ $avp(ds_retries) = $avp(ds_retries) + 1;
+ if(ds_next_dst()) {
+ xlog("L_INFO", "$ci|log|routing call to next media server $du\n");
+
+ setflag(FLAG_SKIP_NAT_CORRECTION);
+
+ # relay the request to the new media server
+ route(RELAY);
+
+ exit;
+ }
+}
+#!endif
+
+event_route[dispatcher:dst-down]
+{
+ xlog("L_WARNING", "Destination down: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+event_route[dispatcher:dst-up]
+{
+ xlog("L_WARNING", "Destination up: $ru , $xavp(ds_dst=>uri), $xavp(ds_dst=>grp), $xavp(ds_dst=>attrs)\n");
+}
+
+
+route[DISPATCHER_CHECK_MEDIA_SERVER]
+{
+ $var(check_media_server_ret) = 0;
+ if($sel(cfg_get.kazoo.dispatcher_auto_add) == 1) {
+ $var(SetId) = 1;
+ if($var(Zone) != "MY_AMQP_ZONE") {
+ $var(SetId) = 2;
+ }
+ $var(flags) = KZ_DISPATCHER_ADD_FLAGS;
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+
+ if($sel(cfg_get.kazoo.dispatcher_add_secondary_ip) == 1) {
+ if($var(MediaIP) != "" && $var(MediaIP) != $(var(MediaUrl){uri.host})) {
+ $var(MediaUrlBack) = $var(MediaUrl);
+ $var(MediaUrl) = $_s($(var(MediaUrlBack){uri.scheme}):$var(MediaIP):$(var(MediaUrlBack){uri.port}));
+ $var(attrs) = $_s(zone=$var(Zone);profile=$var(MediaProfile);duid=$(var(MediaUrl){s.corehash, MEDIA_SERVERS_HASH_SIZE});node=$var(MediaName));
+ $var(SetId) = $sel(cfg_get.kazoo.dispatcher_add_secondary_ip_group);
+ route_if_exists("DISPATCHER_CUSTOM_MEDIA_CHECK");
+ sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
+ if($sqlrows(exec) > 0) {
+ $shv(dispatcher_reload) = 1;
+ $var(check_media_server_ret) = 1;
+ }
+ $var(MediaUrl) = $var(MediaUrlBack);
+ }
+ }
+
+ }
+ return $var(check_media_server_ret);
+}
+
+route[DISPATCHER_RELOAD]
+{
+ if($shv(dispatcher_reload) == 1) {
+ xlog("L_WARNING", "reloading dispatcher table\n");
+ ds_reload();
+ };
+ $shv(dispatcher_reload) = 0;
+}
+
+#!ifdef NODES_ROLE
+route[DISPATCHER_STATUS]
+{
+ jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.list", "id": 1}');
+ $var(Sets) = $(jsonrpl(body){kz.json, result.NRSETS});
+ $var(i) = 0;
+ $var(ds_groups_json)="";
+ $var(Sep1) = "";
+ while($var(i) < $var(Sets)) {
+ $var(Set) = $(jsonrpl(body){kz.json, result.RECORDS[$var(i)].SET});
+ $var(SetCount) = $(var(Set){kz.json.count,TARGETS});
+ $var(Sep2)="";
+ $var(ds_group_json)="";
+ $var(c) = 0;
+ while($var(c) < $var(SetCount)) {
+ $var(Dest) = $(var(Set){kz.json,TARGETS[$var(c)].DEST});
+ $var(record) = $_s("$(var(Dest){kz.json,URI})" : {"destination" : "$(var(Dest){kz.json,URI})", "flags" : "$(var(Dest){kz.json,FLAGS})", "priority" : $(var(Dest){kz.json,PRIORITY}), "attrs" : "$(var(Dest){kz.json,ATTRS.BODY})"});
+ $var(ds_group_json) = $var(ds_group_json) + $var(Sep2) + $var(record);
+ $var(Sep2) = ",";
+ $var(c) = $var(c) + 1;
+ }
+ $var(ds_groups_json) = $var(ds_groups_json) + $var(Sep1) + $_s("$(var(Set){kz.json,ID})" : { $var(ds_group_json) });
+ $var(Sep1)=", ";
+ $var(i) = $var(i) + 1;
+ }
+}
+#!endif
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/kamailio.cfg b/kamailio-proxy-proxy/kamailio.cfg
new file mode 100644
index 0000000..4cc4abc
--- /dev/null
+++ b/kamailio-proxy-proxy/kamailio.cfg
@@ -0,0 +1,52 @@
+## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ##
+
+#### Preprocessor Directives #########
+#!define L_ALERT -5
+#!define L_BUG -4
+#!define L_CRIT2 -3
+#!define L_CRIT -2
+#!define L_ERR -1
+#!define L_WARN 0
+#!define L_NOTICE 1
+#!define L_INFO 2
+#!define L_DBG 3
+#!define L_DEBUG 4
+
+#!define AVP_RECV_PARAM "recv_param"
+#!define AVP_LOG_LEVEL "log_level"
+#!define AVP_ROUTE_CNT "route_cnt"
+#!define AVP_ASSOCIATED_SERVER "associated_server"
+#!define AVP_ASSOCIATE_CONTACT "associate_contact"
+#!define AVP_REDIRECT_KEY "redirect_key"
+
+#!define FLB_NATB 1
+#!define FLB_NATSIPPING 2
+#!define FLB_UAC_REDIRECT 3
+#!define TRUSTED_ADR_GROUP 1
+
+################
+# Kamailio modules to help substdef setup
+# these need to go before local.cfg
+# so they can be used
+#
+# ipops - ip , domain, hostname
+# pv - $def(existing definition)
+# textops - apply regexp
+#
+#
+################
+loadmodule "ipops.so"
+loadmodule "pv.so"
+loadmodule "textops.so"
+
+
+####### Local Configuration ########
+include_file "local.cfg"
+
+####### defaults not configured in local ########
+include_file "defs.cfg"
+
+####### Default Configuration ######
+include_file "default.cfg"
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/kazoo-bindings.cfg b/kamailio-proxy-proxy/kazoo-bindings.cfg
new file mode 100644
index 0000000..d0187a9
--- /dev/null
+++ b/kamailio-proxy-proxy/kazoo-bindings.cfg
@@ -0,0 +1,156 @@
+######## kazoo bindings ########
+###
+###
+
+#!trydef KZ_PUA_PRESENCE_USE_FULL_ENTITY 1
+
+####### Kazoo Integration module ##########
+loadmodule "kazoo.so"
+modparam("kazoo", "pua_mode", MY_AMQP_PUA_MODE)
+modparam("kazoo", "amqp_primary_zone", "MY_AMQP_ZONE")
+modparam("kazoo", "amqp_query_timeout_avp", "$avp(kz_timeout)")
+modparam("kazoo", "node_hostname", "MY_HOSTNAME")
+modparam("kazoo", "amqp_heartbeats", MY_AMQP_HEARTBEATS)
+modparam("kazoo", "amqp_max_channels", MY_AMQP_MAX_CHANNELS)
+modparam("kazoo", "amqp_consumer_processes", MY_AMQP_CONSUMER_PROCESSES)
+modparam("kazoo", "amqp_consumer_workers", MY_AMQP_CONSUMER_WORKERS)
+modparam("kazoo", "presence_use_full_entity", KZ_PUA_PRESENCE_USE_FULL_ENTITY)
+## amqp connections
+#!ifdef MY_AMQP_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_URL")
+#!endif
+#!ifdef MY_AMQP_SECONDARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_SECONDARY_URL")
+#!endif
+#!ifdef MY_AMQP_TERTIARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_TERTIARY_URL")
+#!endif
+#!ifdef MY_AMQP_QUATERNARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_QUATERNARY_URL")
+#!endif
+#!ifdef MY_AMQP_QUINARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_QUINARY_URL")
+#!endif
+#!ifdef MY_AMQP_SENARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_SENARY_URL")
+#!endif
+#!ifdef MY_AMQP_SEPTENARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_SEPTENARY_URL")
+#!endif
+#!ifdef MY_AMQP_OCTONARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_OCTONARY_URL")
+#!endif
+#!ifdef MY_AMQP_NONARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_NONARY_URL")
+#!endif
+#!ifdef MY_AMQP_DENARY_URL
+modparam("kazoo", "amqp_connection", "MY_AMQP_DENARY_URL")
+#!endif
+
+event_route[kazoo:mod-init]
+{
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_BINDINGS);
+ #!endif
+
+ #!ifdef MESSAGE_ROLE
+ route(MESSAGE_BINDINGS);
+ #!endif
+
+ #!ifdef REGISTRAR_ROLE
+ route(REGISTRAR_BINDINGS);
+ #!endif
+
+ #!ifdef NODES_ROLE
+ route(NODES_BINDINGS);
+ #!endif
+
+ #!ifdef ACL_ROLE
+ route(ACL_BINDINGS);
+ #!endif
+
+ #!import_file "kazoo-custom-bindings.cfg"
+
+}
+
+event_route[kazoo:consumer-event]
+{
+ xlog("L_DEBUG","unhandled AMQP event, payload: $kzE\n");
+}
+
+event_route[kazoo:consumer-event-connection-open]
+{
+ xlog("L_DEBUG","connection to $(kzE{kz.json,host}) opened\n");
+}
+
+event_route[kazoo:consumer-event-connection-error]
+{
+ xlog("L_ERR","amqp|error|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|$(kzE{kz.json,message})\n");
+}
+
+event_route[kazoo:consumer-event-connection-message]
+{
+ xlog("L_DEBUG","amqp|msg|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|$(kzE{kz.json,message})\n");
+}
+
+event_route[kazoo:consumer-event-connection-closed]
+{
+ xlog("L_DEBUG","amqp|closed|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|connection to $(kzE{kz.json,host}) closed\n");
+}
+
+event_route[kazoo:consumer-event-connection-zone-available]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is available\n");
+}
+
+event_route[kazoo:consumer-event-connection-zone-unavailable]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is unavailable\n");
+}
+
+event_route[kazoo:consumer-event-connection-available]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is available\n");
+}
+
+event_route[kazoo:consumer-event-connection-unavailable]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is unavailable\n");
+}
+
+event_route[kazoo:consumer-event-connection-zone-listener-available]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is available\n");
+}
+
+event_route[kazoo:consumer-event-connection-zone-listener-unavailable]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is unavailable\n");
+}
+
+event_route[kazoo:consumer-event-connection-listener-zone-available]
+{
+ xlog("L_NOTICE","amqp|connection|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|listener available\n");
+}
+
+event_route[kazoo:consumer-event-connection-listener-zone-unavailable]
+{
+ xlog("L_WARN","amqp|connection|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|listener unavailable\n");
+
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_ZONE_UNAVAILABLE);
+ #!endif
+}
+
+event_route[kazoo:consumer-event-connection-listener-available]
+{
+ xlog("L_DEBUG","amqp|connection|$(kzE{kz.json,zone})|$(kzE{kz.json,name})|listener available\n");
+}
+
+event_route[kazoo:consumer-event-connection-listener-unavailable]
+{
+ xlog("L_DEBUG","amqp zone $(kzE{kz.json,zone}) is unavailable\n");
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/keepalive-role.cfg b/kamailio-proxy-proxy/keepalive-role.cfg
new file mode 100644
index 0000000..b7d28e1
--- /dev/null
+++ b/kamailio-proxy-proxy/keepalive-role.cfg
@@ -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)");
+ }
+
+}
diff --git a/kamailio-proxy-proxy/local.cfg b/kamailio-proxy-proxy/local.cfg
new file mode 100644
index 0000000..d75bb39
--- /dev/null
+++ b/kamailio-proxy-proxy/local.cfg
@@ -0,0 +1,158 @@
+################################################################################
+## ROLES
+################################################################################
+## Enabled Roles
+#!trydef DISPATCHER_ROLE
+#!trydef NAT_TRAVERSAL_ROLE
+# # #!trydef REGISTRAR_ROLE
+# # #!trydef PRESENCE_ROLE
+#!trydef RESPONDER_ROLE
+# # #!trydef NODES_ROLE
+
+#!trydef WEBSOCKETS_ROLE
+#!trydef REGISTRAR_MIN_EXPIRES 300
+
+## Disabled Roles - remove all but the last '#' to enable
+# # #!trydef TRAFFIC_FILTER_ROLE
+# # #!trydef TLS_ROLE
+# # #!trydef ANTIFLOOD_ROLE
+# # #!trydef RATE_LIMITER_ROLE
+# # #!trydef ACL_ROLE
+# # #!trydef MESSAGE_ROLE
+# # #!trydef PUSHER_ROLE
+# # #!trydef REGISTRAR_SYNC_ROLE
+# # #!trydef PRESENCE_NOTIFY_SYNC_ROLE
+# # #!trydef SIP_TRACE_ROLE
+
+################################################################################
+## SERVER INFORMATION
+################################################################################
+## UNCOMMENT & CHANGE "kamailio.2600hz.com" TO YOUR SERVERS HOSTNAME
+# # #!substdef "!MY_HOSTNAME!kamailio.2600hz.com!g"
+
+## UNCOMMENT & CHANGE "127.0.0.1" TO YOUR SERVERS IP ADDRESS
+## Usually your public IP. If you need
+## to listen on addtional ports or IPs
+## add them in "BINDINGS" at the bottom.
+# # #!substdef "!MY_IP_ADDRESS!127.0.0.1!g"
+
+## CHANGE "kazoo://guest:guest@127.0.0.1:5672" TO THE AMQP URL
+## This should be the primary RabbitMQ server
+## in the zone that this server will service.
+# # #!substdef "!MY_AMQP_URL!amqp://guest:guest@127.0.0.1:5672!g"
+
+################################################################################
+## WEBSOCKETS
+################################################################################
+##
+## These parameters are only required if you are using websockets
+##
+## MY_WEBSOCKET_DOMAIN
+## This value must be present in the HTTP
+## Origin header on a new websocket request
+## or it will be rejected. default value is
+## domain of this server.
+## #!substdef "!MY_WEBSOCKET_DOMAIN!2600hz.com!g"
+##
+## WEBSOCKET_NO_ORIGIN_RESTRICTION
+## if defined, it will disable the origin validation.
+##
+## #!trydef WEBSOCKET_NO_ORIGIN_RESTRICTION
+##
+
+################################################################################
+## DATABASE
+################################################################################
+## This parameter is OPTIONAL
+## If you would like to use an external database
+## remove all but the last '#' and configure the connector
+## accordingly. The example shows how to use postgres.
+## See the kamailio documentation for more details.
+#!trydef KZ_DB_MODULE postgres
+#!substdef "!KAMAILIO_DBMS!postgres!g"
+#!substdef "!KAZOO_DB_URL!postgres://kamailio:kamailio@127.0.0.1/kamailio!g"
+
+################################################################################
+## UDP PARAMETERS
+################################################################################
+## This parameter is OPTIONAL
+## If large UDP packets are dropped by the
+## interface try uncommenting this option.
+## However, you MUST match this to your
+## network adapter! If they do not match,
+## all UDP packets over this limit WILL FAIL!
+## E.g.: Add MTU=1472 to the /etc/sysconfig/network-scripts/XXX
+# udp4_raw_mtu = 1472
+
+################################################################################
+## BINDINGS
+################################################################################
+## This parameter is OPTIONAL.
+## when set to 1,
+## 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.
+##!define KZ_MULTI_HOMED 1
+
+################################################################################
+## KZ_DISABLE_REGISTRAR_PORTS
+################################################################################
+## This parameter is OPTIONAL.
+## It will disable publishing single proxy port on registrar success messages
+## By default single port proxy is send on registrar success messages
+## for websockets/tls protocols. the default port is 7000
+## which enables config less in freeswitch for handling webrtc/tls
+## ie, no certs in freeswitch, no webrtc/tls listeners on freeswitch
+## by disabling single port proxy, ecallmgr needs to be started with
+## 'use_transport_for_fs_path' set to true in its environment configuration
+##
+###!define KZ_DISABLE_WEBSOCKETS_REGISTRAR_PORT 1
+###!define KZ_DISABLE_TLS_REGISTRAR_PORT 1
+##
+## you can also change the ports used for single port redirect
+##!define KZ_WEBSOCKETS_REGISTRAR_PORT 5060
+##!define KZ_TLS_REGISTRAR_PORT 5060
+##
+## also available for udp/tcp if it works for you
+##!define KZ_UDP_REGISTRAR_PORT 7000
+##!define KZ_TCP_REGISTRAR_PORT 7000
+
+################################################################################
+## SIP traffic mirroring to SIP_TRACE server
+################################################################################
+## This parameter is OPTIONAL.
+## If you have installed SIP_TRACE server (Homer as example),
+## then you can mirror INVITE and MESSAGE here
+# # #!define SIP_TRACE_URI "sip:127.0.0.1:9060"
+# # #!define HEP_CAPTURE_ID 1
+
+## YOU SHOULD NOT HAVE TO CHANGE THESE!
+## By setting MY_IP_ADDRESS above these will resolve
+## to the proper bindings. These are here
+## for those with complex layouts who know
+## what they are doing :)
+#!substdef "!UDP_SIP!udp:MY_IP_ADDRESS:5060!g"
+#!substdef "!TCP_SIP!tcp:MY_IP_ADDRESS:5060!g"
+#!substdef "!TLS_SIP!tls:MY_IP_ADDRESS:5061!g"
+#!substdef "!UDP_ALG_SIP!udp:MY_IP_ADDRESS:7000!g"
+#!substdef "!TCP_ALG_SIP!tcp:MY_IP_ADDRESS:7000!g"
+#!substdef "!TLS_ALG_SIP!tls:MY_IP_ADDRESS:7001!g"
+#!substdef "!TCP_WS!tcp:MY_IP_ADDRESS:5064!g"
+#!substdef "!UDP_WS_SIP!udp:MY_IP_ADDRESS:5064!g"
+#!substdef "!TLS_WSS!tls:MY_IP_ADDRESS:5065!g"
+#!substdef "!UDP_WSS_SIP!udp:MY_IP_ADDRESS:5065!g"
+
+## YOU SHOULD NOT HAVE TO CHANGE THESE!
+## This will bind the default SIP listeners
+## as determined above. The tls-role and
+## websocket-role will use the appropriate
+## definitions if enabled. These are here
+## for those with complex layouts who know
+## what they are doing :)
+listen=UDP_SIP
+listen=TCP_SIP
+listen=UDP_ALG_SIP
+listen=TCP_ALG_SIP
diff --git a/kamailio-proxy-proxy/message-role.cfg b/kamailio-proxy-proxy/message-role.cfg
new file mode 100644
index 0000000..5ce1d09
--- /dev/null
+++ b/kamailio-proxy-proxy/message-role.cfg
@@ -0,0 +1,102 @@
+
+route[HANDLE_MESSAGE]
+{
+ if (!is_method("MESSAGE")) return;
+
+ if (isflagset(FLAG_INTERNALLY_SOURCED) || src_ip == myself) return;
+
+ xlog("L_INFO", "$ci|log|MESSAGE from $fu to $tu\n");
+ route(AUTH);
+ $xavp(regcfg=>match_received) = $su;
+ if($avp(is_registered) != "true") {
+ sl_send_reply("403", "Forbidden");
+ exit;
+ } else {
+ if($hdr(Content-Type) =~ "text/plain" ||
+ $hdr(Content-Type) =~ "text/html") {
+ route(MESSAGE_INBOUND);
+ } else {
+ xlog("L_WARN", "$ci|end|dropping MESSAGE $hdr(Content-Type)\n");
+ sl_send_reply("200", "OK");
+ exit;
+ }
+ }
+}
+
+route[MESSAGE_INBOUND]
+{
+ $var(key) = "kamailio@MY_HOSTNAME";
+ route(AUTH_HEADERS_JSON);
+ $var(Payload) = $_s({"Event-Category" : "sms", "Event-Name" : "inbound", "Call-ID" : "$ci", "Message-ID" : "$ci", "Route-Type" : "onnet", "Route-ID" : "$(var(key){kz.encode})", "From" : "$fU", "To" : "$tU", "Body" : "$rb", "Custom-SIP-Headers" : $var(headers_json), "Msg-ID" : "$uuid(g)"});
+
+ $var(exchange) = "im";
+ $var(RoutingKey) = $_s(sms.inbound.onnet.$(ci{kz.encode}));
+ xlog("L_INFO", "$ci|msg|sending inbound message $var(RoutingKey) => $var(Payload)\n");
+ kazoo_publish($var(exchange), $var(RoutingKey), $var(Payload));
+ sl_send_reply("200", "OK");
+ exit;
+
+}
+
+event_route[kazoo:consumer-event-sms-outbound]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Message-ID})|log|received message outbound for $(kzE{kz.json,Endpoints[0].To-DID})\n");
+ $var(from_uri) = $_s(sip:$(kzE{kz.json,From})@$(kzE{kz.json,Custom-Vars.Realm}));
+ $var(to_uri) = $_s(sip:$(kzE{kz.json,Endpoints[0].To-Username})@$(kzE{kz.json,Endpoints[0].To-Realm}));
+ $uac_req(method)="MESSAGE";
+ $uac_req(body)= $kzE;
+ $uac_req(hdrs)="X-TM-Local: MESSAGE_ROUTE\r\nX-KAZOO-AOR: " + $var(to_uri)+ "\r\nContent-Type: text/plain\r\n";
+ $uac_req(turi) = $var(to_uri);
+ $uac_req(ruri) = $var(to_uri);
+ $uac_req(furi) = $var(from_uri);
+ $uac_req(ouri) = "sip:127.0.0.1:5090;transport=tcp";
+ $uac_req(callid) = $(kzE{kz.json,Message-ID});
+ xlog("L_INFO", "$(kzE{kz.json,Message-ID})|log|sending message from $var(from_uri) to $var(to_uri) \n");
+ uac_req_send();
+}
+
+route[MESSAGE_ROUTE]
+{
+ remove_hf_re("^X-");
+
+ route(ROUTE_TO_AOR);
+ $var(JObj) = $rb;
+ set_body("$(var(JObj){kz.json,Body})", "text/plain");
+ $avp(message_id) = $(var(JObj){kz.json,Message-ID});
+ $avp(msg_id) = $(var(JObj){kz.json,Msg-ID});
+ $avp(server_id) = $(var(JObj){kz.json,Server-ID});
+ t_on_reply("MESSAGE_REPLY");
+ t_on_failure("MESSAGE_FAULT");
+
+ t_relay();
+
+}
+
+onreply_route[MESSAGE_REPLY]
+{
+ if($T_reply_code < 300) {
+ xlog("L_INFO", "$ci|log|sending success delivery message to $avp(server_id)\n");
+ $var(Payload) = $_s({"Event-Category" : "message", "Event-Name" : "delivery", "Call-ID" : "$ci", "Message-ID" : "$avp(message_id)" , "Delivery-Result-Code" : "sip:$T_reply_code", "Msg-ID" : "$avp(msg_id)" , "Status" : "delivered"});
+ $var(exchange) = "targeted";
+ $var(RK) = $avp(server_id);
+ kazoo_publish($var(exchange), $var(RK), $var(Payload));
+ }
+}
+
+failure_route[MESSAGE_FAULT]
+{
+ xlog("L_INFO", "$ci|log|sending failure delivery message to $avp(server_id)\n");
+ $var(Payload) = $_s({"Event-Category" : "message", "Event-Name" : "delivery", "Call-ID" : "$ci", "Message-ID" : "$avp(message_id)" , "Delivery-Result-Code" : "sip:$T_reply_code", "Msg-ID" : "$avp(msg_id)" , "Status" : "failure"});
+ $var(exchange) = "targeted";
+ $var(RK) = $avp(server_id);
+ kazoo_publish($var(exchange), $var(RK), $var(Payload));
+}
+
+route[MESSAGE_BINDINGS]
+{
+ $var(key) = "kamailio@MY_HOSTNAME";
+ $var(payload) = $_s({"name": "sms", "exchange": "im", "type": "topic", "queue": "MSG-QUEUE-MY_HOSTNAME", "routing": "sms.outbound.$(var(key){kz.encode}).*", "no_ack": false, "federate": true });
+ kazoo_subscribe("$var(payload)");
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/nat-traversal-role.cfg b/kamailio-proxy-proxy/nat-traversal-role.cfg
new file mode 100644
index 0000000..42ec2b0
--- /dev/null
+++ b/kamailio-proxy-proxy/nat-traversal-role.cfg
@@ -0,0 +1,120 @@
+######## 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: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_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()) {
+ xlog("L_DEBUG", "$ci|log|is_first_hop set_contact_alias\n");
+ set_contact_alias();
+ msg_apply_changes();
+ }
+# }
+ }
+
+}
+
+route[NAT_MANAGE]
+{
+ 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
diff --git a/kamailio-proxy-proxy/nodes-role.cfg b/kamailio-proxy-proxy/nodes-role.cfg
new file mode 100644
index 0000000..7eebb8c
--- /dev/null
+++ b/kamailio-proxy-proxy/nodes-role.cfg
@@ -0,0 +1,281 @@
+######## Nodes role - pushes info to kazoo ########
+
+#!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");
+
+modparam("rtimer", "timer", "name=ta;interval=2;mode=2;")
+modparam("rtimer", "timer", "name=retry;interval=5;mode=2;")
+modparam("rtimer", "timer", "name=pub;interval=10;mode=1;")
+modparam("rtimer", "exec", "timer=ta;route=NODE_HEARTBEAT_ROUTE")
+modparam("rtimer", "exec", "timer=retry;route=NODE_TRACK_ROUTE")
+modparam("rtimer", "exec", "timer=pub;route=NODES_ADVERTISE_ROUTE")
+
+
+modparam("mqueue","mqueue", "name=node_track")
+modparam("mqueue","mqueue", "name=node_heartbeat")
+
+
+####### NODES Logic ########
+route[NODES_ADVERTISE_ROUTE]
+{
+
+route(LISTENER_STATUS);
+
+#!ifdef DISPATCHER_ROLE
+ route(DISPATCHER_STATUS);
+ $var(Dispatcher) = $_s(, "Dispatcher" : {"Groups" : { $var(ds_groups_json) }});
+#!else
+ $var(Dispatcher) = "";
+#!endif
+
+#!ifdef PRESENCE_ROLE
+ route(COUNT_ALL_SUBSCRIBERS);
+ $var(Subscriptions) = $_s("Subscriptions" : { $var(Subscriptions) });
+ $var(Subscribers) = $_s("Subscribers" : { $var(Subscribers) });
+
+ route(COUNT_ALL_PRESENTITIES);
+ $var(Presentities) = $_s("Presentities" : {"message-summary" : $xavp(watchers=>message-summary), "dialog" : $xavp(watchers=>dialog), "presence" : $xavp(watchers=>presence)});
+
+ $var(Presence) = $_s(, "Presence" : {$var(Subscribers), $var(Subscriptions), $var(Presentities)});
+#!else
+ $var(Presence) = "";
+#!endif
+
+#!ifdef REGISTRAR_ROLE
+ $var(Registrar) = $_s(, "Registrar" : {"Registrations" : $(stat(registered_users){s.int})});
+#!else
+ $var(Registrar) = "";
+#!endif
+
+ $var(Roles) = $_s("Roles" : {"Proxy" : $var(listeners) $var(Dispatcher) $var(Presence) $var(Registrar)});
+ $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));
+}
+
+
+event_route[kazoo:consumer-event-nodes-advertise]
+{
+ $var(count) = $shtinc(nodes=>$(kzE{kz.json,Node})::count);
+ if($var(count) == 0) {
+ xlog("L_NOTICE", "$(kzE{kz.json,Msg-ID})|nodes|heartbeat for reconnected node $(kzE{kz.json,Node})\n");
+ $var(count) = $shtinc(nodes=>$(kzE{kz.json,Node})::count);
+ } else {
+ if($var(count) == 1) {
+ xlog("L_NOTICE", "$(kzE{kz.json,Msg-ID})|nodes|heartbeat from new node $(kzE{kz.json,Node})\n");
+ } else {
+ xlog("L_DEBUG", "$(kzE{kz.json,Msg-ID})|nodes|heartbeat from existing node $(kzE{kz.json,Node})\n");
+ }
+ }
+ mq_add("node_heartbeat", "$(kzE{kz.json,Node})", "$kzE");
+}
+
+event_route[htable:expired:nodes]
+{
+ if($shtrecord(key) =~ "::count$$") {
+ if($shtrecord(value) == -1) {
+ xlog("L_WARNING", "htable|nodes|node $(shtrecord(key){s.rm,::count}) is still unreachable\n");
+ }
+ mq_add("node_track", "$shtrecord(key)", "");
+ return;
+ }
+
+ xlog("L_WARNING", "htable|nodes|heartbeat expired for node $shtrecord(key)\n");
+}
+
+route[NODE_TRACK_ROUTE]
+{
+ $var(runloop) = 1;
+ while(mq_fetch("node_track") == 1 && $var(runloop) < MAX_WHILE_LOOPS) {
+ $var(Key) = $mqk(node_track);
+ $sht(nodes=>$var(Key)) = -1;
+ $var(runloop) = $var(runloop) + 1;
+ }
+}
+
+
+route[NODE_HEARTBEAT_ROUTE]
+{
+ $var(runloop) = 1;
+ while(mq_fetch("node_heartbeat") == 1 && $var(runloop) < MAX_WHILE_LOOPS) {
+ $var(Node) = $mqk(node_heartbeat);
+ $var(Payload) = $mqv(node_heartbeat);
+ xlog("L_DEBUG", "$(var(Payload){kz.json,Msg-ID})|nodes|processing heartbeat for node $var(Node)\n");
+
+ route(CHECK_MEDIA_SERVERS);
+
+ $sht(nodes=>$var(Node)) = $var(Payload);
+ $shtex(nodes=>$var(Node)) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_EXPIRE;
+ $var(runloop) = $var(runloop) + 1;
+ }
+}
+
+route[CHECK_MEDIA_SERVERS]
+{
+ if($(var(Payload){kz.json,Media-Servers}) == "") {
+ return;
+ }
+
+ $var(Msg-ID) = $(var(Payload){kz.json,Msg-ID});
+ $var(Media) = $(var(Payload){kz.json,Media-Servers});
+ $var(Zone) = $(var(Payload){kz.json,AMQP-Broker-Zone});
+
+ $var(Dot) = ".";
+ $var(Perc) = "%";
+ avp_delete("$avp(MediaKeys)/g");
+ if(kazoo_json_keys($var(Payload), "Media-Servers", "$avp(MediaKeys)") == 1) {
+ $var(Count) = $cnt($avp(MediaKeys));
+ $var(Idx) = 0;
+ while( $var(Idx) < $var(Count) ) {
+ $var(MediaName) = $(avp(MediaKeys)[$var(Idx)]);
+ $var(MediaKey) = $(var(MediaName){s.replace,$var(Dot),$var(Perc)});
+ avp_delete("$avp(ProfileKeys)/g");
+
+ $var(MediaReconnected) = 0;
+ $var(MediaConnected) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Startup});
+ $var(ExistingMediaConnected) = $sht(media=>$var(MediaKey)::connected::$var(Node));
+ xlog("L_DEBUG", "$var(Msg-ID)|nodes|$var(MediaKey) from $var(Node) => $var(MediaConnected) vs $var(ExistingMediaConnected)\n");
+ if($var(ExistingMediaConnected) != $null && $var(MediaConnected) > $var(ExistingMediaConnected)) {
+ $var(MediaReconnected) = 1;
+ }
+ $sht(media=>$var(MediaKey)::connected::$var(Node)) = $var(MediaConnected);
+ $shtex(media=>$var(MediaKey)::connected::$var(Node)) = 0;
+
+ if(kazoo_json_keys($var(Payload), "Media-Servers.$var(MediaKey).Interfaces", "$avp(ProfileKeys)") == 1) {
+ $var(ProfileCount) = $cnt($avp(ProfileKeys));
+ $var(ProfileIdx) = 0;
+ while( $var(ProfileIdx) < $var(ProfileCount) ) {
+ $var(MediaProfile) = $(avp(ProfileKeys)[$var(ProfileIdx)]);
+ $var(MediaRawUrl) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Interfaces.$var(MediaProfile).info.url});
+ if($var(MediaRawUrl) == "") {
+ $var(MediaRawUrl) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Interfaces.$var(MediaProfile).URL});
+ }
+ $var(MediaUrl) = $(var(MediaRawUrl){re.subst,/^sip:(.*)@(.*)/sip:\2/});
+ $var(MediaInstanceUUID) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Instance-UUID});
+ $var(MediaIP) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Interfaces.$var(MediaProfile).info.sip-ip});
+ if($var(MediaIP) == "") {
+ $var(MediaIP) = $(var(Payload){kz.json,Media-Servers.$var(MediaKey).Interfaces.$var(MediaProfile).SIP-IP});
+ }
+ if($shtinc(media=>$var(MediaUrl)::count) == 1) {
+ $sht(media=>$var(MediaUrl)::zone) = $var(Zone);
+ $shtex(media=>$var(MediaUrl)::zone) = 0;
+ $sht(media=>$var(MediaUrl)::uuid) = $var(MediaInstanceUUID);
+ $shtex(media=>$var(MediaUrl)::uuid) = 0;
+ route(MEDIA_SERVER_UP);
+ } else if($sht(media=>$var(MediaUrl)::uuid) != $var(MediaInstanceUUID)) {
+ $sht(media=>$var(MediaUrl)::uuid) = $var(MediaInstanceUUID);
+ $shtex(media=>$var(MediaUrl)::uuid) = 0;
+ $var(Zone) = $sht(media=>$var(MediaUrl)::zone);
+ route(MEDIA_SERVER_RESTART);
+ } else if($var(MediaReconnected) == 1) {
+ route(MEDIA_SERVER_RECONNECTED);
+ };
+ $var(MediaExpire) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_EXPIRE;
+ xlog("L_DEBUG", "$var(Msg-ID)|nodes|$var(Node) media expiration $var(MediaExpire) for $var(MediaUrl)\n");
+ $shtex(media=>$var(MediaUrl)::count) = $var(MediaExpire);
+ $var(ProfileIdx) = $var(ProfileIdx) + 1;
+ }
+ }
+ $var(Idx) = $var(Idx) + 1;
+ }
+ };
+}
+
+event_route[htable:expired:media]
+{
+ $var(MediaUrl) = $(shtrecord(key){re.subst,/(.*)::(.*)/\1/});
+ $var(Zone) = $sht(media=>$var(MediaUrl)::zone);
+ route(MEDIA_SERVER_DOWN);
+}
+
+route[MEDIA_SERVER_UP]
+{
+ xlog("L_NOTICE", "$var(Msg-ID)|nodes|$var(Node) reported new media server $var(MediaUrl) in zone $var(Zone)\n");
+
+#!ifdef DISPATCHER_ROLE
+ route(DISPATCHER_CHECK_MEDIA_SERVER);
+#!endif
+
+#!ifdef PRESENCE_ROLE
+ route(PRESENCE_FAST_PICKUP_START);
+ route(RESET_PUBLISHER);
+#!endif
+
+}
+
+route[MEDIA_SERVER_DOWN]
+{
+ xlog("L_WARNING", "expired|nodes|heartbeat expired for media server $var(MediaUrl) in zone $var(Zone)\n");
+
+#!ifdef PRESENCE_ROLE
+ route(RESET_PUBLISHER);
+#!endif
+
+}
+
+route[MEDIA_SERVER_RESTART]
+{
+ xlog("L_NOTICE", "$var(Msg-ID)|nodes|media server $var(MediaUrl) restarted in zone $var(Zone)\n");
+
+#!ifdef PRESENCE_ROLE
+ route(RESET_PUBLISHER);
+#!endif
+
+}
+
+route[MEDIA_SERVER_RECONNECTED]
+{
+ xlog("L_NOTICE", "$var(Msg-ID)|nodes|media server $var(MediaUrl) reconnected to $var(Node) in zone $var(Zone)\n");
+
+#!ifdef PRESENCE_ROLE
+ route(RESET_PUBLISHER);
+#!endif
+
+}
+
+#!ifndef NODES_CUSTOM_BINDINGS
+route[NODES_BINDINGS]
+{
+ $var(payload) = $_s({"name": "nodes", "exchange" : "nodes" , "type" : "fanout", "queue" : "nodes-MY_HOSTNAME", "exclusive": false, "federate": true });
+ kazoo_subscribe("$var(payload)");
+}
+#!endif
+
+route[LISTENER_STATUS]
+{
+ jsonrpc_exec('{"jsonrpc": "2.0", "method": "corex.list_sockets", "id": 1}');
+ $var(count) = $(jsonrpl(body){kz.json.count,result});
+ $var(loop) = 0;
+ $var(sep) = "";
+ $var(listeners) = "";
+ while( $var(loop) < $var(count) ) {
+ $var(listener) = $(jsonrpl(body){kz.json,result[$var(loop)]});
+ $var(proto) = $(var(listener){kz.json,PROTO});
+ $var(address) = $(var(listener){kz.json,ADDRLIST.ADDR});
+ if($var(address) != "127.0.0.1") {
+ $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})");
+ } else {
+ $var(advertise) = "";
+ }
+ $var(x) = $_s("$var(uri)" : {"proto" : "$var(proto)", "address" : "$var(address)", "port" : $var(port) $var(advertise) });
+ $var(listeners) = $_s($var(listeners)$var(sep)$var(x));
+ $var(sep) = " , ";
+ }
+ $var(loop) = $var(loop) + 1;
+ }
+ $var(listeners) = $_s({"Listeners" : { $var(listeners) }});
+}
+
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/presence-fast-pickup.cfg b/kamailio-proxy-proxy/presence-fast-pickup.cfg
new file mode 100644
index 0000000..11813b7
--- /dev/null
+++ b/kamailio-proxy-proxy/presence-fast-pickup.cfg
@@ -0,0 +1,197 @@
+######## FAST PICKUP ROLE ########
+modparam("htable", "htable", "park=>size=16;autoexpire=600")
+modparam("htable", "htable", "fp=>size=8");
+
+#!trydef KZ_PRESENCE_FAST_PICKUP_COOKIES 1
+#!trydef KZ_PRESENCE_FAST_PICKUP_REALTIME 1
+#!trydef KZ_PRESENCE_FAST_PICKUP_STAR_5 1
+
+kazoo.presence_fast_pickup_cookies = KZ_PRESENCE_FAST_PICKUP_COOKIES descr "maintains a hash table for correlating call-ids with media servers"
+kazoo.presence_fast_pickup_realtime = KZ_PRESENCE_FAST_PICKUP_REALTIME descr "queries channels api for realtime status of call-id"
+kazoo.presence_fast_pickup_star_5 = KZ_PRESENCE_FAST_PICKUP_STAR_5 descr "treats *5 as park pickup, queries state of *3"
+
+route[PRESENCE_FAST_PICKUP_START]
+{
+ $sht(fp=>count) = 0;
+}
+
+route[PRESENCE_FAST_PICKUP_LOAD]
+{
+ sht_reset("fp");
+ xlog("L_INFO", "$ci|log|fast|initializing fastpick hash table from dispatcher\n");
+ if (sql_xquery("exec", "select destination from dispatcher", "ra") == 1) {
+ while($xavp(ra) != $null) {
+ $var(host) = $(xavp(ra=>destination){uri.host});
+ $var(port) = $(xavp(ra=>destination){uri.port});
+ $var(destination) = $xavp(ra=>destination);
+ $var(i) = 0;
+ if(!is_ip("$var(host)")) {
+ xlog("L_INFO", "$ci|log|fast|ignoring $var(host) since its not a ip address\n");
+ } else {
+ xlog("L_INFO", "$ci|log|fast|adding key $(var(destination){s.md5}) for $var(destination)\n");
+ $sht(fp=>$(var(destination){s.md5})) = $var(destination);
+ }
+ pv_unset("$xavp(ra)");
+ }
+ }
+}
+
+route[PRESENCE_FAST_PICKUP_ATTEMPT]
+{
+ if (!is_method("INVITE")) {
+ return;
+ }
+
+ $var(replaced_call_id) = "none";
+
+ if($hdr(Replaces)!= $null) {
+ $var(replaced_call_id) = $(hdr(Replaces){s.select,0,;});
+ }
+
+ if($var(replaced_call_id) =~ "kfp+") {
+ if($shtinc(fp=>count) == 1) {
+ route(PRESENCE_FAST_PICKUP_LOAD);
+ }
+ remove_hf_re("^Replaces");
+ $var(PickupOptions) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\1/}{s.decode.hexa});
+ $var(md5) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\2/});
+ $var(replaced_call_id) = $(var(replaced_call_id){re.subst,/^kfp\+(.{2})([^@]*)@(.*)/\3/});
+ if( $sht(fp=>$var(md5)) != $null) {
+ route(PRESENCE_FAST_PICKUP_OPTION);
+ $du = $sht(fp=>$var(md5));
+ append_hf("Replaces: $var(replaced_call_id)$var(Pickup)\r\n");
+ append_hf("k-cid: $var(replaced_call_id)\r\n");
+ xlog("L_INFO", "$ci|log|fast|found shortcut for call-id $var(replaced_call_id) , redirecting ($(ru{uri.user})) to $du\n");
+ route(RELAY);
+ exit();
+ } else {
+ xlog("L_INFO", "$ci|log|fast|shortcut $var(md5) invalid in this server, using standard routing\n");
+ }
+ }
+
+ if($sel(cfg_get.kazoo.presence_fast_pickup_realtime) == 1) {
+ if($var(replaced_call_id) != "none") {
+ xlog("L_INFO", "$ci|log|request has replaces call-id $var(replaced_call_id)\n");
+ $var(amqp_payload_request) = '{"Event-Category" : "call_event" , "Event-Name" : "channel_status_req", "Call-ID" : "' + $var(replaced_call_id) + '", "Active-Only" : true }';
+ $var(amqp_routing_key) = "call.status_req." + $(var(replaced_call_id){kz.encode});
+ sl_send_reply("100", "locating your call");
+ xlog("L_INFO", "$ci|log|querying cluster for the location of call-id $var(replaced_call_id)\n");
+ if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request))) {
+ $du = $(kzR{kz.json,Switch-URL});
+ if($du != $null) {
+ if($(kzR{kz.json,Other-Leg-Call-ID}) == "") {
+ ## not bridged
+ $var(rep) = $_s($var(replaced_call_id);a-leg=true);
+ } else {
+ ## ensure early-only=true
+ $var(rep) = $_s($var(replaced_call_id);early-only=true);
+ }
+ remove_hf_re("^Replaces");
+ append_hf("Replaces: $var(rep)\r\n");
+ append_hf("k-cid: $var(replaced_call_id)\r\n");
+ xlog("L_INFO", "$ci|log|call-id $var(replaced_call_id) found, redirecting call ($(ru{uri.user})) to $du => $var(rep)\n");
+ route(RELAY);
+ exit();
+ } else {
+ xlog("L_WARN", "$ci|log|call-id $var(replaced_call_id) not found in cluster, proceeding with normal dispatch\n");
+ }
+ } else {
+ xlog("L_WARN", "$ci|log|error querying cluster for call-id $var(replaced_call_id), proceeding with normal dispatch\n");
+ }
+ }
+ }
+
+ ##### CALL-PARK ####
+
+ ##### STAR 5 CHECK ####
+ if($sel(cfg_get.kazoo.presence_fast_pickup_star_5) == 1) {
+ if($(ru{uri.user}) =~ "^\*5") {
+ $var(park) = $_s(*3$(ru{uri.user}{s.substr,2,0})@$(ru{uri.domain}));
+ if($sht(park=>$var(park)) != $null) {
+ $du = $sht(park=>$var(park));
+ append_hf("k-cid: $sht(park=>$var(park)::callid)\r\n");
+ xlog("L_INFO", "$ci|log|redirecting park request to $du , callid : $sht(park=>$var(park)::callid)\n");
+ route(RELAY);
+ exit();
+ }
+ }
+ }
+
+ if($sht(park=>$(ru{uri.user})@$(ru{uri.domain})) != $null) {
+ $du = $sht(park=>$(ru{uri.user})@$(ruri{uri.domain}));
+ append_hf("k-cid: $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})::callid)\r\n");
+ xlog("L_INFO", "$ci|log|redirecting park request to $du, callid: $sht(park=>$(ru{uri.user})@$(ruri{uri.domain})::callid)\n");
+ route(RELAY);
+ exit();
+ }
+
+ ##### CALL-PARK IN KAZOO ####
+ $var(park_extension) = "^\*3";
+ if($sel(cfg_get.kazoo.presence_fast_pickup_star_5) == 1) {
+ $var(park_extension) = "^\*[3,5]";
+ }
+ if($(ru{uri.user}) =~ $var(park_extension) && !is_ip($rd)) {
+ xlog("L_INFO", "$ci|log|checking park request to $(ru{uri.user})@$(ru{uri.domain})\n");
+ $var(amqp_payload_request) = '{"Event-Category" : "call_event" , "Event-Name" : "query_user_channels_req", "Username" : "*3$(ru{uri.user}{s.substr,2,0})", "Realm" : "$(ru{uri.domain})", "Active-Only" : true }';
+ $var(amqp_routing_key) = "call.status_req." + $(ci{kz.encode});
+ if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request))) {
+ $du = $(kzR{kz.json,Channels[0].switch_url});
+ if($du != $null) {
+ xlog("L_INFO", "$ci|log|redirecting park request to $du from realtime query reply\n");
+ append_hf("k-cid: $(kzR{kz.json,Channels[0].call_id})\r\n");
+ route(RELAY);
+ exit();
+ }
+ }
+ }
+}
+
+route[PRESENCE_FAST_PICKUP_OPTION]
+{
+ $var(Pickup) = "";
+ switch($var(PickupOptions))
+ {
+ case 1:
+ $var(Pickup) = ";a-leg=true";
+ break;
+ case 2:
+ $var(Pickup) = ";early-only=true";
+ break;
+ default:
+ break;
+ }
+}
+
+route[PRESENCE_FAST_PICKUP_INIT]
+{
+ $var(AppName) = $(kzE{kz.json,App-Name});
+
+ ## park redirects without replaces header
+ if($var(AppName) == "park") {
+ if($(kzE{kz.json,State}) == "terminated") {
+ $sht(park=>$(kzE{kz.json,Presence-ID})) = $null;
+ $sht(park=>$(kzE{kz.json,Presence-ID})::callid) = $null;
+ } else {
+ $sht(park=>$(kzE{kz.json,Presence-ID})) = $(kzE{kz.json,Switch-URI});
+ $sht(park=>$(kzE{kz.json,Presence-ID})::callid) = $(kzE{kz.json,Call-ID});
+ }
+ }
+
+ ## fast pickup with cookies
+ if($sel(cfg_get.kazoo.presence_fast_pickup_cookies) == 1) {
+ if($var(AppName) == "park") {
+ $var(Pickup) = 1; #";a-leg=true";
+ } else {
+ $var(Pickup) = 2; #";early-only=true";
+ }
+
+ $var(Option) = $(var(Pickup){s.encode.hexa});
+ $var(Cookie) = $(kzE{kz.json,Switch-URI}{s.md5});
+ $var(call_id) = $(kzE{kz.json,Call-ID});
+ $var(JObj) = $(kzE{re.subst,/"Call-ID"\s*\:\s*"([^"]*)"/"Call-ID" : "kfp+$var(Option)$var(Cookie)@\1"/});
+ xlog("L_DEBUG", "$var(call_id)|fast|shortcut ($var(Pickup)) kfp+$var(Option)$var(Cookie)@$var(call_id)\n");
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
+
diff --git a/kamailio-proxy-proxy/presence-notify.cfg b/kamailio-proxy-proxy/presence-notify.cfg
new file mode 100644
index 0000000..33ca06a
--- /dev/null
+++ b/kamailio-proxy-proxy/presence-notify.cfg
@@ -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(KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_EXPIRES;);
+ mq_add("presence_last_notity", "$uuid(g)", "$var(Query)");
+ $var(Query) = $_s(KZQ_DELETE_FROM_PRESENTITY_WHERE_EXPIRES;);
+ mq_add("presence_last_notity", "$uuid(g)", "$var(Query)");
+ $var(Query) = $_s(KZQ_DELETE_FROM_PRESENTITY_WHERE_DIALOG_TERMINATED;);
+ 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)");
+ }
+}
diff --git a/kamailio-proxy-proxy/presence-query.cfg b/kamailio-proxy-proxy/presence-query.cfg
new file mode 100644
index 0000000..04bbb41
--- /dev/null
+++ b/kamailio-proxy-proxy/presence-query.cfg
@@ -0,0 +1,113 @@
+######## Presence query server module ########
+
+#!trydef KZ_PRESENCE_QUERY_REPLY_ZONES 0
+kazoo.presence_query_reply_zones = KZ_PRESENCE_QUERY_REPLY_ZONES descr "0 - all, 1 - local, 2 - remote"
+
+route[PRESENCE_SEARCH_SUMMARY]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|query|processing presence summary query for $(kzE{kz.json,Realm})\n");
+ $var(Queue) = $(kzE{kz.json,Server-ID});
+ $var(Event) = $(kzE{kz.json,Event-Package});
+ $var(Domain) = $(kzE{kz.json,Realm});
+ $var(Username) = $(kzE{kz.json,Username});
+ $var(Now) = $TS;
+ $var(Items) = "";
+ $var(Query) = $_s(KZQ_PRESENCE_SEARCH_SUMMARY);
+ if($var(Event) != "") {
+ $var(Query) = $var(Query) + $_s( and event = "$var(Event)");
+ }
+ if($var(Username) != "") {
+ $var(Query) = $var(Query) + $_s( and watcher_username = "$var(Username)");
+ }
+ $var(Query) = $var(Query) + " order by presentity_uri, event, watcher_username, callid";
+ xlog("L_DEBUG", "$ci| QUERY $var(Query)\n");
+
+ if (sql_xquery("cb", "$var(Query)", "ra") == 1)
+ {
+ $var(Subs) = "";
+ $var(Sep1) = "";
+ while($xavp(ra) != $null) {
+ $var(Username) = $(xavp(ra=>presentity_uri){s.tolower});
+ $var(Sep2)="";
+ $var(Evt)="";
+ while($xavp(ra) != $null && $var(Username) == $(xavp(ra=>presentity_uri){s.tolower}) )
+ {
+ $var(Event) = $xavp(ra=>event);
+ $var(Sep3)="";
+ $var(Sub)="";
+ $var(Count) = 0;
+ while($xavp(ra) != $null && $var(Username) == $(xavp(ra=>presentity_uri){s.tolower}) && $var(Event) == $xavp(ra=>event))
+ {
+ $var(Count) = $var(Count) + 1;
+ pv_unset("$xavp(ra)");
+ }
+ $var(Evt) = $var(Evt) + $var(Sep2) + $_s("$var(Event)" : $var(Count));
+ $var(Sep2)=", ";
+ }
+ $var(Subs) = $var(Subs) + $var(Sep1) + $_s("$(var(Username){uri.user})") + " : { " + $var(Evt) + " }";
+ $var(Sep1)=", ";
+ }
+ }
+ xlog("L_DEBUG", "$ci| RESULT \"Subscriptions\" : { $var(Subs) }\n");
+
+ $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "search_resp", "Msg-ID" : "$(kzE{kz.json,Msg-ID})", "Subscriptions" : { $var(Subs) } });
+ kazoo_publish("targeted", "$var(Queue)", $var(amqp_payload_request));
+
+}
+
+route[PRESENCE_SEARCH_DETAIL]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|query|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});
+ $var(presentity_uri) = "sip:" + $var(Username) + "@" + $var(Domain);
+ $var(Now) = $TS;
+ $var(Items) = "";
+ $var(Query) = $_s(KZQ_PRESENCE_SEARCH_DETAIL);
+ if($var(Event) != "") {
+ $var(Query) = $var(Query) + $_s( and a.event = "$var(Event)");
+ }
+ $var(Query) = $var(Query) + " order by event, watcher_username, callid";
+ xlog("L_DEBUG", "$ci| STATUS QUERY $var(Query)\n");
+
+ if (sql_xquery("cb", "$var(Query)", "ra") == 1) {
+ while($xavp(ra) != $null) {
+ $var(Event) = $xavp(ra=>event);
+ 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,$$,}{re.subst,/\\\\\\"/\\"/g})", "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" : "$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" : "$var(Msg-ID)" }';
+ kazoo_publish("targeted", "$var(Queue)", $var(amqp_payload_request));
+
+}
+
+event_route[kazoo:consumer-event-presence-search-req]
+{
+ $var(Zone) = $(kzE{kz.json,AMQP-Broker-Zone});
+ if( ($var(Zone) == "MY_AMQP_ZONE" && $sel(cfg_get.kazoo.presence_query_reply_zones) != 2) ||
+ ($var(Zone) != "MY_AMQP_ZONE" && $sel(cfg_get.kazoo.presence_query_reply_zones) != 1)) {
+
+ switch($(kzE{kz.json,Search-Type})) {
+ case "summary":
+ route(PRESENCE_SEARCH_SUMMARY);
+ break;
+ case "detail":
+ route(PRESENCE_SEARCH_DETAIL);
+ break;
+ default:
+ xlog("L_INFO", "$ci|search type '$(kzE{kz.json,Search-Type})' not handled\n");
+ }
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/presence-reset.cfg b/kamailio-proxy-proxy/presence-reset.cfg
new file mode 100644
index 0000000..61315e7
--- /dev/null
+++ b/kamailio-proxy-proxy/presence-reset.cfg
@@ -0,0 +1,154 @@
+#!trydef PRESENCE_RESET_BLF_DEFER_UPDATE 0
+
+kazoo.presence_reset_blf_defer_update = PRESENCE_RESET_BLF_DEFER_UPDATE descr "defers blf reset"
+
+
+##### PRESENCE RESET ROUTINES
+
+route[PRESENCE_RESET_ROUTE]
+{
+ $var(runloop) = 1;
+ while(mq_fetch("blf_reset") == 1 && $var(runloop) < MAX_WHILE_LOOPS) {
+ $var(Key) = $mqk(blf_reset);
+ $sht(nodes=>$var(Key)) = 0;
+ $var(runloop) = $var(runloop) + 1;
+ }
+}
+
+route[RESET_PUBLISHER]
+{
+ xlog("L_INFO", "$var(Msg-ID)|reset|received presence reset for publisher $var(MediaUrl)\n");
+ if($sel(cfg_get.kazoo.presence_reset_blf_defer_update) == 0) {
+ $var(Query) = $_s(KZQ_RESET_PUBLISHER_UPDATE);
+ sql_query("exec", "$var(Query)");
+ }
+ $var(Query) = $_s(KZQ_PRESENCE_RESET);
+ sql_query("exec", "$var(Query)");
+ $var(presentities) = $sqlrows(exec);
+ xlog("L_INFO", "$var(Msg-ID)|reset|removed $var(presentities) presentities from publisher $var(MediaUrl)\n");
+ if($var(presentities) > 0) {
+ route(PRESENCE_PUBLISHER_CLEANUP);
+ }
+}
+
+route[PRESENCE_ZONE_UNAVAILABLE]
+{
+ if($(kzE{kz.json,name}) == "presence") {
+ $var(Zone) = $(kzE{kz.json,zone});
+ xlog("L_WARN", "amqp|reset|resetting publisher zone $var(Zone)\n");
+ route(RESET_PUBLISHER_ZONE);
+ }
+}
+
+route[RESET_PUBLISHER_ZONE]
+{
+ if($sel(cfg_get.kazoo.presence_reset_blf_defer_update) == 0) {
+ $var(Query) = $_s(KZQ_RESET_PUBLISHER_ZONE_UPDATE);
+ sql_query("exec", "$var(Query)");
+ }
+ $var(Query) = $_s(KZQ_PRESENCE_ZONE_RESET);
+ sql_query("exec", "$var(Query)");
+ $var(presentities) = $sqlrows(exec);
+ xlog("L_INFO", "amqp|reset|removed $var(presentities) presentities from zone $var(Zone)\n");
+ if($var(presentities) > 0) {
+ route(PRESENCE_PUBLISHER_CLEANUP);
+ }
+}
+
+route[RESET_ALL]
+{
+ xlog("L_INFO", "$var(Msg-ID)|reset|received presence reset ALL\n");
+ sql_query("exec", "delete from presentity");
+ $var(presentities) = $sqlrows(exec);
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|removed $var(presentities) presentities\n");
+}
+
+route[RESET_ZONE]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for this zone (MY_AMQP_ZONE)\n");
+ route(RESET_ALL);
+}
+
+
+route[RESET_SERVER]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for this server (MY_HOSTNAME)\n");
+ route(RESET_ALL);
+}
+
+route[RESET_ACCOUNT]
+{
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for realm $(kzE{kz.json,Realm})\n");
+ sql_query("exec", 'KZQ_RESET_ACCOUNT_UPDATE');
+ $var(watchers) = $sqlrows(exec);
+ sql_query("exec", 'KZQ_RESET_ACCOUNT_RESET');
+ $var(presentities) = $sqlrows(exec);
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|removed $var(presentities) presentities and expired $var(watchers) subscribers for realm $(kzE{kz.json,Realm})\n");
+ if($var(watchers) > 0) {
+ route(PRESENCE_PUBLISHER_CLEANUP);
+ }
+}
+
+route[RESET_WILDCARD]
+{
+ if($(kzE{kz.json,Realm}) == "*" && $(kzE{kz.json,Username}) == "*") {
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for cluster\n");
+ route(RESET_ALL);
+ } else {
+ if($(kzE{kz.json,Realm}) == "*") {
+ if($(kzE{kz.json,Username}) == "MY_AMQP_ZONE") {
+ route(RESET_ZONE);
+ } else {
+ if($(kzE{kz.json,Username}) == "MY_HOSTNAME") {
+ route(RESET_SERVER);
+ } else {
+ if($(kzE{kz.json,Username}) =~ "sip:") {
+ $var(Msg-ID) = $(kzE{kz.json,Msg-ID});
+ $var(MediaUrl) = $(kzE{kz.json,Username});
+ route(RESET_PUBLISHER);
+ } else {
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence wildcard reset for $(kzE{kz.json,Username}). 'MY_AMQP_ZONE/MY_HOSTNAME' doesn't care\n");
+ }
+ }
+ }
+ } else {
+ route(RESET_ACCOUNT);
+ }
+ }
+
+}
+
+event_route[kazoo:consumer-event-presence-reset]
+{
+ if($(kzE{kz.json,Username}) == "*" || $(kzE{kz.json,Realm}) == "*") {
+ route(RESET_WILDCARD);
+ exit();
+ }
+
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for $(kzE{kz.json,Username})@$(kzE{kz.json,Realm})\n");
+ $var(presentity) = $_s(sip:$(kzE{kz.json,Username})@$(kzE{kz.json,Realm}));
+ route(COUNT_SUBSCRIBERS);
+ sql_query("exec", 'KZQ_EVENT_PRESENCE_RESET_DELETE');
+
+ if($xavp(watchers=>message-summary) > 0) {
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|notifying $xavp(watchers=>message-summary) message-summary subscribers of $var(presentity)\n");
+ pres_refresh_watchers("$var(presentity)", "message-summary", 1);
+ } else {
+ xlog("L_DEBUG", "$(kzE{kz.json,Msg-ID})|reset|skip message-summary subscriber notification for $var(presentity)\n");
+ }
+
+ if($xavp(watchers=>presence) > 0) {
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|notifying $xavp(watchers=>presence) presence subscribers of $var(presentity)\n");
+ pres_refresh_watchers("$var(presentity)", "presence", 1);
+ } else {
+ xlog("L_DEBUG", "$(kzE{kz.json,Msg-ID})|reset|skip presence subscriber notification for $var(presentity)\n");
+ }
+
+ if($xavp(watchers=>dialog) > 0) {
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|notifying $xavp(watchers=>dialog) dialog subscribers of $var(presentity)\n");
+ pres_refresh_watchers("$var(presentity)", "dialog", 1);
+ } else {
+ xlog("L_DEBUG", "$(kzE{kz.json,Msg-ID})|reset|skip dialog subscriber notification for $var(presentity)\n");
+ }
+
+}
diff --git a/kamailio-proxy-proxy/presence-role.cfg b/kamailio-proxy-proxy/presence-role.cfg
new file mode 100644
index 0000000..df20b5c
--- /dev/null
+++ b/kamailio-proxy-proxy/presence-role.cfg
@@ -0,0 +1,585 @@
+######## Presence server module ########
+#!trydef PRESENCE_MIN_EXPIRES 300
+#!trydef PRESENCE_MIN_EXPIRES_ACTION 1
+#!trydef PRESENCE_MAX_EXPIRES 3600
+
+#!trydef KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP 1
+#!trydef KZ_PRESENCE_CSEQ_OFFSET 2
+#!trydef KZ_PRESENCE_MAX_CALL_PER_PRESENTITY 20
+#!trydef BLF_USE_SINGLE_DIALOG 1
+#!trydef KZ_PRESENCE_AMQP_PUBLISH 0
+#!trydef KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE 0
+#!trydef KZ_PRESENCE_REQUEST_PROBE 1
+#!trydef KZ_PRESENCE_NO_TARGETS_LOG_LEVEL L_DBG
+#!trydef KZ_PRESENCE_WITH_TARGETS_LOG_LEVEL L_INFO
+#!trydef KZ_PRESENCE_REQUIRE_AUTHN 0
+#!trydef KZ_PRESENCE_KEEPALIVE_NAT_ONLY 1
+#!trydef KZ_PRESENCE_KEEPALIVE_UDP_ONLY 1
+
+
+#!ifdef NAT_TRAVERSAL_ROLE
+#!ifndef KEEPALIVE_ROLE
+#!ifndef NAT_TRAVERSAL_LOADED
+#!trydef NAT_TRAVERSAL_LOADED
+loadmodule "nat_traversal.so"
+#!endif
+
+modparam("nat_traversal", "keepalive_method", "OPTIONS")
+modparam("nat_traversal", "keepalive_from", "sip:sipcheck@MY_HOSTNAME")
+modparam("nat_traversal", "keepalive_state_file", "KAZOO_DATA_DIR/keep_alive_state")
+modparam("nat_traversal", "keepalive_interval", 45)
+#!endif
+#!endif
+
+
+modparam("htable", "htable", "first=>size=32;autoexpire=3600;initval=0;")
+
+loadmodule "presence.so"
+loadmodule "presence_dialoginfo.so"
+loadmodule "presence_mwi.so"
+loadmodule "presence_xml.so"
+
+modparam("presence_dialoginfo", "force_dummy_dialog", 1)
+modparam("presence_dialoginfo", "force_single_dialog", BLF_USE_SINGLE_DIALOG)
+
+modparam("presence_xml", "force_dummy_presence", 1)
+modparam("presence_xml", "force_active", 1)
+modparam("presence_xml", "disable_winfo", 1)
+modparam("presence_xml", "disable_bla", 1)
+
+modparam("presence", "subs_db_mode", 3)
+modparam("presence", "expires_offset", 0)
+modparam("presence", "send_fast_notify", 0)
+
+modparam("presence", "clean_period", 0)
+modparam("presence", "db_update_period", 0)
+
+modparam("presence", "publ_cache", 0)
+modparam("presence", "min_expires_action", PRESENCE_MIN_EXPIRES_ACTION)
+modparam("presence", "min_expires", PRESENCE_MIN_EXPIRES)
+modparam("presence", "max_expires", PRESENCE_MAX_EXPIRES)
+modparam("presence", "sip_uri_match", 1)
+modparam("presence", "waitn_time", 1)
+modparam("presence", "notifier_processes", 1)
+modparam("presence", "db_url", "KAZOO_DB_URL")
+modparam("presence", "xavp_cfg", "pres")
+modparam("presence", "local_log_level", 6)
+modparam("presence", "startup_mode", 0)
+modparam("presence", "force_delete", 1)
+modparam("presence", "timeout_rm_subs", 0)
+modparam("presence", "cseq_offset", KZ_PRESENCE_CSEQ_OFFSET)
+
+modparam("kazoo", "db_url", "KAZOO_DB_URL")
+modparam("kazoo", "pua_mode", 1)
+
+kazoo.presence_sync_amqp = KZ_PRESENCE_AMQP_PUBLISH descr "sync subscriptions to amqp"
+kazoo.presence_request_probe = KZ_PRESENCE_REQUEST_PROBE descr "request probe for new subscriptions"
+kazoo.presence_request_resubscribe_probe = KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE descr "request probe for resubscriptions"
+kazoo.presence_ignore_status_probe_resp = KZ_PRESENCE_IGNORE_STATUS_PROBE_RESP descr "ignore online/offline probe replies"
+kazoo.presence_max_call_per_presentity = KZ_PRESENCE_MAX_CALL_PER_PRESENTITY descr "max number of calls per presentity"
+kazoo.presence_no_targets_log_level = KZ_PRESENCE_NO_TARGETS_LOG_LEVEL descr "when a presence event is received and there no targets we can log at another level"
+kazoo.presence_with_targets_log_level = KZ_PRESENCE_WITH_TARGETS_LOG_LEVEL descr "when a presence event is received and there are targets we can log at another level"
+kazoo.presence_require_authn = KZ_PRESENCE_REQUIRE_AUTHN descr "require authenticated devices for presence"
+kazoo.presence_keepalive_udp_only = KZ_PRESENCE_KEEPALIVE_UDP_ONLY descr "should we send keepalive for udp only"
+kazoo.presence_keepalive_nat_only = KZ_PRESENCE_KEEPALIVE_NAT_ONLY descr "should we send keepalive for nat phones only"
+
+#!include_file "presence-query.cfg"
+#!include_file "presence-notify.cfg"
+#!include_file "presence-reset.cfg"
+#!include_file "presence-fast-pickup.cfg"
+
+####### Presence Logic ########
+
+route[PRESENCE_NAT]
+{
+ if(!( ($sel(cfg_get.kazoo.presence_keepalive_udp_only) == 1 && $proto != "udp")
+ || (!isflagset(FLT_NATS) && $sel(cfg_get.kazoo.presence_keepalive_nat_only) == 1)
+ || ($proto == "ws" || $proto == "wss")
+ )) {
+ #!ifdef KEEPALIVE_ROLE
+ route(KEEPALIVE_ON_SUBSCRIBE);
+ #!else
+ nat_keepalive();
+ #!endif
+ }
+}
+
+route[HANDLE_SUBSCRIBE]
+{
+ if (!is_method("SUBSCRIBE")) {
+ return;
+ }
+
+ 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();
+ }
+
+ route(PRESENCE_AUTHN);
+
+ if (!t_newtran()) {
+ sl_reply_error();
+ exit;
+ }
+
+ if(has_totag()) {
+ loose_route();
+ }
+
+ record_route();
+
+ if(has_totag()) {
+ route(HANDLE_RESUBSCRIBE);
+ } else {
+ route(HANDLE_NEW_SUBSCRIBE);
+ }
+
+ t_release();
+
+ exit;
+}
+
+route[DELETE_DUPLICATED_SUBSCRIPTIONS]
+{
+ sql_query("exec", 'KZQ_DELETE_FROM_ACTIVE_WATCHERS_WHERE_PRESENTITY');
+}
+
+route[HANDLE_RESUBSCRIBE]
+{
+
+ if(handle_subscribe()) {
+ if($subs(remote_cseq) < 5) {
+ $sht(first=>$subs(callid)) = $null;
+ $sht(first=>$subs(from_user)::$subs(pres_uri)::$subs(from_domain)::$subs(event)) = $null;
+ }
+ route(DELETE_DUPLICATED_SUBSCRIPTIONS);
+ route(SUBSCRIBE_AMQP);
+ route(REQUEST_PROBE);
+ };
+}
+
+
+route[HANDLE_NEW_SUBSCRIBE]
+{
+ if ($hdr(Event) == "dialog"
+ || $hdr(Event) == "presence"
+ || $hdr(Event) == "message-summary") {
+
+
+ if ($tU == $null) {
+ xlog("L_INFO", "$ci|stop|ignoring subscribe with empty TO username from a $ua\n");
+ send_reply(400, "Missing TO username");
+ return;
+ }
+
+ if ($fU == $null) {
+ xlog("L_INFO", "$ci|stop|ignoring subscribe with empty FROM username from a $ua\n");
+ send_reply(400, "Missing FROM username");
+ return;
+ }
+
+ if($shtinc(first=>$ci) > 1) {
+ sql_query("exec", 'KZQ_HANDLE_NEW_SUBSCRIBE_DELETE1');
+ xlog("L_INFO", "$ci|subscribe|resetting $hdr(Event) subscription from $fU to $tU in realm $fd : $sqlrows(exec)\n");
+ } else {
+ $var(presentity_uri) = $ru;
+ if($(var(presentity_uri){uri.user}) == "") {
+ $var(presentity_uri) = $tu;
+ }
+ if($shtinc(first=>$fU::$var(presentity_uri)::$fd::$hdr(Event)) > 1) {
+ sql_query("exec", 'KZQ_HANDLE_NEW_SUBSCRIBE_DELETE2');
+ xlog("L_INFO", "$ci|subscribe|resetting $hdr(Event) subscription from $fU to $var(presentity_uri) in realm $fd : $sqlrows(exec)\n");
+ }
+ }
+
+ if (handle_subscribe()) {
+ xlog("L_INFO","$ci|end|new $hdr(Event) subscription from $fU to $tU in realm $fd : $sht(first=>$ci) : $sht(first=>$fU::$tU::$fd::$hdr(Event))\n");
+ route(DELETE_DUPLICATED_SUBSCRIPTIONS);
+ route(SUBSCRIBE_AMQP);
+ route(REQUEST_PROBE);
+ #!ifdef NAT_TRAVERSAL_ROLE
+ route(PRESENCE_NAT);
+ #!endif
+ } else {
+ xlog("L_INFO", "$ci|stop|error $T_reply_code for new $hdr(Event) subscription from $fU to $tU in realm $fd\n");
+ }
+ } else {
+ xlog("L_INFO", "$ci|stop|unsupported subscription package $hdr(Event) from $fU to $tU in realm $fd\n");
+ send_reply(489, "Bad Event");
+ }
+}
+
+route[SUBSCRIBE_AMQP]
+{
+ if($sel(cfg_get.kazoo.presence_sync_amqp) == 1) {
+ $var(rk) = "subscribe." + $(subs(to_domain){kz.encode}) + "." + $(subs(to_user){kz.encode});
+ $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "subscription", "Event-Package" : "$hdr(event)", "Expires" : $subs(expires), "Queue" : "BLF-MY_HOSTNAME", "Server-ID" : "BLF-MY_HOSTNAME" , "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "From" : "$fu", "User" : "$subs(uri)", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" });
+ kazoo_publish("omnipresence", "$var(rk)", $var(amqp_payload_request));
+ }
+}
+
+route[REQUEST_PROBE]
+{
+ if( ($sel(cfg_get.kazoo.presence_request_probe) == 1 && (!has_totag()))
+ || ($sel(cfg_get.kazoo.presence_request_resubscribe_probe) == 1 && has_totag()) ) {
+ if( route(HAS_PRESENTITY) == 0) {
+ if($hdr(event) == "message-summary") {
+ $var(mwi) = $tU;
+ route(REQUEST_MWI);
+ } else {
+ if($tU =~ "\*98") {
+ $var(mwi) = $(tU{s.substr,3,0});
+ route(REQUEST_MWI);
+ } else {
+ xlog("L_INFO", "$ci|sub|requesting $hdr(Event) probe for $subs(to_user) in realm $subs(to_domain)\n");
+ $var(rk) = "probes." + $hdr(Event);
+ $var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "probe", "Event-Package" : "$hdr(event)", "Username" : "$tU", "Realm" : "$fd", "Call-ID" : "$ci"});
+ kazoo_publish("presence", "$var(rk)", $var(amqp_payload_request));
+ }
+ }
+ }
+ }
+}
+
+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));
+}
+
+route[HANDLE_PUBLISH]
+{
+ 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();
+ }
+
+ route(PRESENCE_AUTHN);
+
+ if (!t_newtran()) {
+ sl_reply_error();
+ exit;
+ }
+
+ if($hdr(Sender)!= $null) {
+ handle_publish("$hdr(Sender)");
+ } else {
+ handle_publish();
+ }
+ t_release();
+ exit;
+}
+
+route[HAS_PRESENTITY]
+{
+ $var(Query) = $_s(KZQ_HAS_PRESENTITY);
+ $var(res) = 0;
+ if (sql_xquery("cb", "$var(Query)", "subs") == 1)
+ {
+ if($xavp(subs) != $null) {
+ $var(res) = $xavp(subs=>count);
+ pv_unset("$xavp(subs)");
+ }
+ }
+ return $var(res);
+}
+
+route[COUNT_PRESENTITIES]
+{
+ $var(Query) = $_s(KZQ_COUNT_PRESENTITIES);
+ $var(p) = $_s(presence_id='$var(presentity)');
+ if (sql_xquery("cb", "$var(Query)", "subs") == 1)
+ {
+ while($xavp(subs) != $null) {
+ $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count);
+ pv_unset("$xavp(subs)");
+ }
+ }
+ xavp_params_explode($var(p), "watchers");
+}
+
+route[COUNT_ALL_PRESENTITIES]
+{
+ $var(Query) = $_s(select event, (select count(*) from presentity b where b.event = a.event) count from event_list a);
+ $var(p) = "presence_id=none";
+ if (sql_xquery("cb", "$var(Query)", "subs") == 1)
+ {
+ while($xavp(subs) != $null) {
+ $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count);
+ pv_unset("$xavp(subs)");
+ }
+ }
+ xavp_params_explode($var(p), "watchers");
+}
+
+route[COUNT_ALL_SUBSCRIBERS]
+{
+ $var(Query) = $_s(KZQ_COUNT_ALL_SUBSCRIBERS);
+ if (sql_xquery("cb", "$var(Query)", "subs") == 1)
+ {
+ $var(sep) = "";
+ $var(Subscribers) = "";
+ $var(Subscriptions) = "";
+ while($xavp(subs) != $null) {
+ $var(Subscribers) = $var(Subscribers) + $var(sep) + $_s("$xavp(subs=>event)" : $xavp(subs=>count_unique));
+ $var(Subscriptions) = $var(Subscriptions) + $var(sep) + $_s("$xavp(subs=>event)" : $xavp(subs=>count));
+ $var(sep) = " , ";
+ pv_unset("$xavp(subs)");
+ }
+ }
+}
+
+route[COUNT_SUBSCRIBERS]
+{
+ $var(Query) = $_s(KZQ_COUNT_SUBSCRIBERS);
+ $var(p) = $_s(presence_id='$var(presentity)');
+ if (sql_xquery("cb", "$var(Query)", "subs") == 1)
+ {
+ while($xavp(subs) != $null) {
+ $var(p) = $var(p) + ";" + $xavp(subs=>event) + "=" + $xavp(subs=>count);
+ pv_unset("$xavp(subs)");
+ }
+ }
+ xavp_params_explode($var(p), "watchers");
+}
+
+event_route[kazoo:consumer-event-presence-dialog-update]
+{
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int});
+ $var(StartRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received});
+ xlog("L_DEBUG", "$(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;
+ route(PRESENCE_FAST_PICKUP_INIT);
+
+ $var(presentity) = $(kzE{kz.json,From});
+ $var(payload) = $kzE;
+
+ route(PRESENCE_UPDATE);
+
+ $var(EndRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute);
+
+ xlog("$var(kz_presence_log_level)", "$(kzE{kz.json,Call-ID})|log|$(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,AMQP-Broker-Zone}) => $(kzE{kz.json,Switch-URI}) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n");
+}
+
+event_route[kazoo:consumer-event-presence-mwi-update]
+{
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int});
+ $var(StartRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received});
+ xlog("L_DBG", "$(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) {
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ 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 {
+#!ifdef PRESENCE_TRACK_ALL_PKG_MWI
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|saving $var(presentity) from mwi update => $var(payload)\n");
+ if(kazoo_pua_publish_mwi($kzE) != 1) {
+ xlog("L_ERR", "$(var(payload){kz.json,Call-ID})|log|error publishing $var(presentity) mwi update => $var(payload)\n");
+ }
+#!else
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|skip mwi update for $var(presentity)\n");
+#!endif
+ }
+
+ route(MWI_AS_PRESENCE);
+ $var(mwi_state) = "ON";
+ if($(kzE{kz.json,Messages-Waiting}) == "no") {
+ $var(mwi_state) = "OFF";
+ }
+
+ $var(EndRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute);
+
+ xlog("$var(kz_presence_log_level)", "$(kzE{kz.json,Call-ID})|log|message-summary update for $(kzE{kz.json,From}) light should be $var(mwi_state) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n");
+
+}
+
+event_route[kazoo:consumer-event-presence-update]
+{
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_no_targets_log_level){s.int});
+ $var(StartRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_start) = $var(StartRoute) - $(kzE{kz.json,AMQP-Received});
+ if($sel(cfg_get.kazoo.presence_ignore_status_probe_resp) == 1) {
+ if($(kzE{kz.json,State}) == "offline" || $(kzE{kz.json,State}) == "online") {
+ xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|ignoring $(kzE{kz.json,State}) state $(kzE{kz.json,Presence-ID})\n");
+ return;
+ }
+ }
+
+ 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);
+
+ $var(EndRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_finish) = $var(EndRoute) - $var(StartRoute);
+
+ xlog("$var(kz_presence_log_level)", "$(kzE{kz.json,Call-ID})|log|$(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,AMQP-Broker-Zone}) => $(kzE{kz.json,Switch-URI}) (Δ1 $(kzE{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_to_finish) μs)\n");
+}
+
+route[PRESENCE_UPDATE]
+{
+ $var(callid) = $(var(payload){kz.json,Call-ID});
+ if($(var(payload){kz.json,State}) == "terminated") {
+ route(COUNT_PRESENTITIES);
+ } else {
+ route(COUNT_SUBSCRIBERS);
+ }
+
+ if($xavp(watchers=>self) > $sel(cfg_get.kazoo.presence_max_call_per_presentity) &&
+ ( $(var(payload){kz.json,State}) == "early" ||
+ ($(var(payload){kz.json,State}) == "confirmed" && $(var(payload){kz.json,State}) == "initiator")
+ )) {
+ xlog("L_WARN", "$(var(payload){kz.json,Call-ID})|log|not publishing state $(var(payload){kz.json,State}) for presentity $var(presentity) with $xavp(watchers=>self) calls, policy limit of $sel(cfg_get.kazoo.presence_max_call_per_presentity) calls per presentity \n");
+ } else {
+ if($xavp(watchers=>dialog) > 0) {
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ if($(var(payload){kz.json,State}) == "terminated") {
+ xlog("L_DEBUG", "$(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");
+ };
+ } else {
+#!ifdef PRESENCE_TRACK_ALL_PKG_DIALOG
+ if($(kzE{kz.json,Event-Package}) == "dialog") {
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|saving $var(presentity) from dialog update => $var(payload)\n");
+ if(kazoo_pua_publish_dialoginfo($var(JObj)) != 1) {
+ xlog("L_ERR", "$(var(payload){kz.json,Call-ID})|log|error publishing $var(presentity) dialog update => $var(payload)\n");
+ }
+ }
+#!else
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|skip dialog update for $var(presentity)\n");
+#!endif
+ }
+
+ if($xavp(watchers=>presence) > 0) {
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ if($(var(payload){kz.json,State}) == "terminated") {
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) presence update for terminated dialog\n");
+ } else {
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) presence update for $xavp(watchers=>presence) watchers\n");
+ }
+ if(kazoo_pua_publish_presence($var(JObj)) == 1) {
+ pres_refresh_watchers("$var(presentity)", "presence", 1);
+ } else {
+ xlog("L_ERR", "$(var(payload){kz.json,Call-ID})|log|error publishing $var(presentity) presence update\n");
+ };
+ } else {
+#!ifdef PRESENCE_TRACK_ALL_PKG_PRESENCE
+ if($(kzE{kz.json,Event-Package}) == "presence") {
+ $var(kz_presence_log_level) = $(sel(cfg_get.kazoo.presence_with_targets_log_level){s.int});
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|saving $var(presentity) from presence update => $var(payload)\n");
+ if(kazoo_pua_publish_presence($var(JObj)) != 1) {
+ xlog("L_ERR", "$(var(payload){kz.json,Call-ID})|log|error publishing $var(presentity) presence update => $var(payload)\n");
+ }
+ }
+#!else
+ xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|skip presence update for $var(presentity)\n");
+#!endif
+ }
+ }
+
+}
+
+#!define MWI_PRESENCE_BODY $(kzE{re.subst,/"Messages-Waiting"\s*\:\s*"[^"]*"/"State" : "$var(State)"/} \
+{re.subst,/"From"\s*\:\s*"[^"]*"/"From" : "$var(presentity)"/} \
+{re.subst,/"From-User"\s*\:\s*"[^"]*"/"From-User" : "$var(user)"/} \
+{re.subst,/"To"\s*\:\s*"[^"]*"/"To" : "$var(presentity)"/} \
+{re.subst,/"To-User"\s*\:\s*"[^"]*"/"To-User" : "$var(user)"/} \
+{re.subst,/"Messages-New"\s*\:\s*[^,]*/"Direction" : "initiator"/} \
+{re.subst,/"Event-Name"\s*\:\s*"[^"]*"/"Event-Name" : "presence"/});
+
+
+route[MWI_AS_PRESENCE]
+{
+ if( $(kzE{kz.json,Extended-Presence-ID}) == "" ) {
+ return;
+ }
+
+ $var(realm) = $(kzE{kz.json,From-Realm});
+ $var(user) = $(kzE{kz.json,Extended-Presence-ID});
+ $var(presentity) = $_s(sip:$var(user)@$var(realm));
+ if( $(kzE{kz.json,Messages-Waiting}) == "yes" ) {
+ $var(State) = "confirmed";
+ } else {
+ $var(State) = "terminated";
+ }
+
+ $var(payload) = MWI_PRESENCE_BODY
+ $var(JObj) = $var(payload);
+ route(PRESENCE_UPDATE);
+
+}
+
+route[PRESENCE_BINDINGS]
+{
+ #!import_file "presence-custom-bindings.cfg"
+
+ #!ifndef PRESENCE_CUSTOM_BINDINGS
+ $var(payload) = $_s({ "name" : "presence", "exchange" : "presence", "type" : "topic", "queue" : "presence-dialog-MY_HOSTNAME", "routing" : ["dialog.*.*", "update.*.*", "mwi_updates.*.*"], "exclusive" : false, "federate" : true });
+ kazoo_subscribe("$var(payload)");
+ #!endif
+
+ route(PRESENCE_API_BINDINGS);
+
+ route(PRESENCE_FAST_PICKUP_START);
+
+}
+
+route[PRESENCE_API_BINDINGS]
+{
+ #!import_file "presence-api-custom-bindings.cfg"
+
+ #!ifndef PRESENCE_API_CUSTOM_BINDINGS
+ $var(payload) = $_s({"name": "presence-api", "exchange": "presence", "type": "topic", "queue": "presence-api-MY_HOSTNAME", "routing": ["presence.search_req.*", "presence.reset.*.*"], "exclusive": false, "federate": true });
+ kazoo_subscribe("$var(payload)");
+ #!endif
+
+}
+
+route[PRESENCE_LOCAL_REQUEST]
+{
+ route(PRESENCE_LOCAL_REQ_NOTIFY);
+}
+
+route[PRESENCE_AUTHN]
+{
+ if($sel(cfg_get.kazoo.presence_require_authn) == 1) {
+ $xavp(regcfg=>match_received) = $su;
+ if(registered("location", "$rz:$Au", 2, 1) != 1) {
+ xlog("L_WARNING", "$ci|stop|$rm from unregistered ($rz:$Au) user agent $ua => $su\n");
+ send_reply(403, "Forbidden");
+ exit;
+ }
+ }
+}
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/pusher-role.cfg b/kamailio-proxy-proxy/pusher-role.cfg
new file mode 100644
index 0000000..0420c58
--- /dev/null
+++ b/kamailio-proxy-proxy/pusher-role.cfg
@@ -0,0 +1,223 @@
+## PUSHER ROLE
+
+#!trydef KZ_PUSHER_LOG_CONTACT 0
+kazoo.pusher_log_contacts = KZ_PUSHER_LOG_CONTACT descr "logs contacts after registration"
+
+######## Generic Hash Table container in shared memory ########
+modparam("htable", "htable", "push_cache=>autoexpire=60;")
+
+route[PUSHER_ROUTE]
+{
+ if ( (!is_method("INVITE")) || (!isflagset(FLAG_INTERNALLY_SOURCED)) || $hdr(X-KAZOO-PUSHER-Token-ID) == $null)
+ return;
+
+ xlog("L_INFO", "$ci|pusher|start deliver call to $hdr(X-KAZOO-PUSHER-Token-ID)\n");
+ if(route(PUSHER_PREPARE_PUSH)) {
+ if(reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) {
+ $du = $(ulc(callee=>received));
+ $fs = $(ulc(callee=>socket));
+ xlog("L_INFO", "$ci|pusher|routing $hdr(X-KAZOO-AOR) to contact $du\n");
+ send_reply(100, "calling a push device");
+ t_set_fr(0, 2000);
+ route(PUSHER_TO_EXTERNAL_RELAY);
+ } else {
+ send_reply(100, "waking the push device");
+ route(PUSHER_SEND_PUSH_NOTIFICATION);
+ }
+ }
+ exit();
+}
+
+route[PUSHER_TO_EXTERNAL_RELAY]
+{
+ remove_hf_re("^X-.*");
+ set_forward_no_connect();
+ t_on_branch("MANAGE_BRANCH");
+ t_on_reply("EXTERNAL_REPLY");
+ t_on_failure("PUSHER_EXTERNAL_FAULT");
+ t_relay();
+}
+
+failure_route[PUSHER_EXTERNAL_FAULT]
+{
+ if (!t_check_status("486|487|603") && $avp(push_sent) != 1) {
+ send_reply(182, "sending push notification");
+ route(PUSHER_SEND_PUSH_NOTIFICATION);
+ } else if (t_check_status("487")) {
+ xlog("L_INFO", "$ci|pusher|push transaction canceled\n");
+ t_reply("$T_reply_code", "pusher canceled");
+ } else {
+ xlog("L_INFO", "$ci|pusher|push transaction result - $T_reply_code\n");
+ t_reply("$T_reply_code", "pusher failed");
+ }
+}
+
+route[PUSHER_PREPARE_PUSH]
+{
+ if (t_newtran()) {
+ route(PUSHER_PREPARE_PUSH_PAYLOAD);
+ remove_hf_re("^X-.*");
+ t_save_lumps();
+ t_set_auto_inv_100(0);
+ return 1;
+ } else {
+ sl_send_reply(500, "error creating transaction for waking the dead guy");
+ return 0;
+ }
+}
+
+route[PUSHER_PREPARE_PUSH_PAYLOAD]
+{
+
+ $var(TokenID) = $hdr(X-KAZOO-PUSHER-Token-ID);
+ $var(TokenType) = $hdr(X-KAZOO-PUSHER-Token-Type);
+ $var(TokenApp) = $hdr(X-KAZOO-PUSHER-Token-App);
+
+ $var(TokenProxy) = $hdr(X-KAZOO-PUSHER-Token-Proxy);
+ #!ifdef PUSHER_TOKEN_PROXY
+ $var(TokenProxy) = $_s(PUSHER_TOKEN_PROXY);
+ #!endif
+
+ ### token for fast reg ###
+ $var(TokenReg) = $uuid(g);
+ $sht(push_cache=>$var(TokenReg)) = 1;
+
+ ### caller-id ###
+ if($hdr(Remote-Party-ID) != $null) {
+ $var(from_user) = $(hdr(Remote-Party-ID){tobody.user});
+ $var(from_name) = $(hdr(Remote-Party-ID){tobody.display}{re.subst,/"//g});
+ } else if($hdr(P-Asserted-Identity) != $null) {
+ $var(from_user) = $(hdr(P-Asserted-Identity){tobody.user});
+ $var(from_name) = $(hdr(P-Asserted-Identity){tobody.display}{re.subst,/"//g});
+ } else if($hdr(P-Preferred-Identity) != $null) {
+ $var(from_user) = $(hdr(P-Preferred-Identity){tobody.user});
+ $var(from_name) = $(hdr(P-Preferred-Identity){tobody.display}{re.subst,/"//g});
+ } else {
+ $var(from_user) = $(hdr(From){tobody.user});
+ $var(from_name) = $(hdr(From){tobody.display}{re.subst,/"//g});
+ }
+
+ $var(from) = $_s($var(from_user) - $var(from_name));
+
+
+ $var(PushPayload) = $_s({"call-id" : "$ci", "proxy" : "$var(TokenProxy)", "caller-id-number" : "$var(from_user)", "caller-id-name" : "$var(from_name)", "registration-token" : "$var(TokenReg)"});
+ $var(Payload) = $_s({ "Event-Category" : "notification", "Event-Name" : "push_req", "Call-ID" : "$ci", "Token-ID" : "$var(TokenID)", "Token-Type" : "$var(TokenType)", "Token-App" : "$var(TokenApp)", "Alert-Key" : "IC_SIL", "Alert-Params" : ["$var(from)"], "Sound" : "ring.caf", "Payload" : $var(PushPayload) });
+
+ $avp(push_routing_key) = "notification.push." + $var(TokenType) + "." + $var(TokenID);
+ $avp(push_payload) = $var(Payload);
+}
+
+route[PUSHER_SEND_PUSH_NOTIFICATION]
+{
+ xlog("L_INFO", "$ci|pusher|sending push notification request\n");
+ xlog("L_DEBUG", "$ci|pusher|pushing to $avp(push_routing_key) : $avp(push_payload)\n");
+ t_set_fr(20000, 20000);
+ $avp(push_sent) = 1;
+ t_suspend();
+ $sht(push_cache=>$(tu{s.tolower})) = $_s(a=0;index=$T(id_index);label=$T(id_label));
+ kazoo_publish("pushes", $avp(push_routing_key), $avp(push_payload));
+}
+
+route[PUSHER_ATTEMPT_REGISTRATION]
+{
+ if (!is_method("REGISTER")) {
+ return;
+ }
+
+ if($hdr(X-Token-Reg) != $null) {
+ if($sht(push_cache=>$hdr(X-Token-Reg)) != $null) {
+ $var(password) = $null;
+ $sht(push_cache=>$hdr(X-Token-Reg)) = $null;
+ xlog("L_INFO", "$ci|pusher|registration with x-token-reg $hdr(X-Token-Reg)\n");
+ $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");
+ }
+ }
+
+ if($(sel(contact.uri){uri.param,x-token-reg}) != "") {
+ if($sht(push_cache=>$(sel(contact.uri){uri.param,x-token-reg})) != $null) {
+ $var(password) = $null;
+ $sht(push_cache=>$(sel(contact.uri){uri.param,x-token-reg})) = $null;
+ xlog("L_INFO", "$ci|pusher|registration with x-token-reg $(sel(contact.uri){uri.param,x-token-reg})\n");
+ $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");
+ }
+ }
+
+ if($(sel(contact){tobody.params}{param.value,x-token-reg}) != "") {
+ if($sht(push_cache=>$(sel(contact){tobody.params}{param.value,x-token-reg})) != $null) {
+ $var(password) = $null;
+ $sht(push_cache=>$(sel(contact){tobody.params}{param.value,x-token-reg})) = $null;
+ xlog("L_INFO", "$ci|pusher|registration with x-token-reg $(sel(contact){tobody.params}{param.value,x-token-reg})\n");
+ $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");
+ }
+ }
+}
+
+route[PUSHER_ON_REGISTRATION]
+{
+ if( ( $(xavp(ulattrs=>x_token_reg){s.len}) > 0 ||
+ $(xavp(ulattrs=>custom_channel_vars){kz.json,Pusher-Application}{s.len}) > 0) &&
+ $var(Status) == "Registered") {
+ if($sht(push_cache=>$(tu{s.tolower})) != $null) {
+ xlog("L_INFO", "$ci|pusher|device registered, delivering the call\n");
+ $var(ref) = $sht(push_cache=>$(tu{s.tolower}));
+ $sht(push_cache=>$(tu{s.tolower})) = $null;
+ $var(t_index) = $(var(ref){param.value,index}{s.int});
+ $var(t_label) = $(var(ref){param.value,label}{s.int});
+ t_continue("$var(t_index)", "$var(t_label)", "PUSHER_DELIVER_CALL");
+ }
+ }
+}
+
+route[PUSHER_DELIVER_CALL]
+{
+ if(reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) {
+ if($sel(cfg_get.kazoo.pusher_log_contacts) == 1) {
+ xlog("L_NOTICE", "callee=>aor: $(ulc(callee=>aor))\n");
+ xlog("L_NOTICE", "callee=>count: $(ulc(callee=>count))\n");
+ xlog("L_NOTICE", "callee=>domain: $(ulc(callee=>domain))\n");
+ xlog("L_NOTICE", "callee=>aorhash $(ulc(callee=>aorhash))\n");
+ $var(i) = 0;
+ while($var(i) < $(ulc(callee=>count))) {
+ xlog("L_NOTICE", "--- contact [$var(i)]\n");
+ xlog("L_NOTICE", "callee=>addr: $(ulc(callee=>addr)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>path: $(ulc(callee=>path)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>received: $(ulc(callee=>received)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>expires: $(ulc(callee=>expires)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>callid: $(ulc(callee=>callid)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>regid: $(ulc(callee=>regid)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>q: $(ulc(callee=>q)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>cseq: $(ulc(callee=>cseq)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>flags: $(ulc(callee=>flags)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>cflags: $(ulc(callee=>cflags)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>user_agent: $(ulc(callee=>user_agent)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>socket: $(ulc(callee=>socket)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>modified: $(ulc(callee=>modified)[$var(i)])\n");
+ xlog("L_NOTICE", "callee=>methods: $(ulc(callee=>methods)[$var(i)])\n");
+ $var(i) = $var(i) + 1;
+ }
+ }
+
+ $var(idx) = $ulc(callee=>count) - 1;
+ $du = $(ulc(callee=>received)[$var(idx)]);
+ $fs = $(ulc(callee=>socket)[$var(idx)]);
+ t_set_fr(30000, 30000);
+ route(PUSHER_TO_EXTERNAL_RELAY);
+ } else {
+ t_reply(486, "Failed to lookup after resume");
+ }
+}
diff --git a/kamailio-proxy-proxy/rate-limiter-role.cfg b/kamailio-proxy-proxy/rate-limiter-role.cfg
new file mode 100644
index 0000000..7ef4426
--- /dev/null
+++ b/kamailio-proxy-proxy/rate-limiter-role.cfg
@@ -0,0 +1,254 @@
+######## DoS prevention module ########
+modparam("htable", "timer_interval", 10)
+modparam("htable", "htable", "rps=>size=8;initval=0;autoexpire=60")
+modparam("htable", "htable", "rpm=>size=8;initval=0;autoexpire=180")
+modparam("htable", "htable", "tps=>size=8;initval=0;autoexpire=60")
+modparam("htable", "htable", "tpm=>size=8;initval=0;autoexpire=180")
+modparam("htable", "htable", "rate_limits=>initval=-1;autoexpire=60") # initval = -1 means that record is expired and we need an update from DB
+
+#!trydef RATE_LIMIT_MESSAGE "Over rate Limit"
+#!trydef RATE_LIMIT_CODE "603"
+
+#!trydef IP_REGEX "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}"
+
+route[DOS_PREVENTION] {
+
+ # If packet came from platform or from 4 class MERA, do not check it
+ if (isflagset(FLAG_INTERNALLY_SOURCED) || isflagset(FLAG_TRUSTED_SOURCE) ) {
+ xlog("L_DEBUG", "$ci |RL| Trusted source IP($si) ignoring\n");
+ return;
+ }
+
+ # Initially we do not want to get data
+ $var(with-realm-request) = "false";
+ $var(with-realm-total) = "false";
+ $var(with-device-request) = "false";
+ $var(with-device-total) = "false";
+ $var(method-key) = "Method";
+ $var(method-value) = "\"TOTAL\"";
+
+ # SIP methods INVITE and REGISTER have personal counters
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ $var(lrpm_realm) = $fd+"/"+$rm+"/min";
+ $var(lrps_realm) = $fd+"/"+$rm+"/sec";
+
+ $var(lrpm_device) = $fU+"@"+$fd+"/"+$rm+"/min";
+ $var(lrps_device) = $fU+"@"+$fd+"/"+$rm+"/sec";
+ $var(method-value) = "\"" + $rm + "\"";
+ }
+
+ # For BYE method we use REALM from To SIP header
+ if ($fd =~ IP_REGEX) {
+ xlog("L_WARNING","$ci|RL-realm log| Fixup for $rm method with IP in from URI: use to-domain\n");
+ $var(ltpm_realm) = $td+"/TOTAL/min";
+ $var(ltps_realm) = $td+"/TOTAL/sec";
+ $var(ltpm_device) = $fU+"@"+$td+"/TOTAL/min";
+ $var(ltps_device) = $fU+"@"+$td+"/TOTAL/sec";
+ $var(entity) = $td;
+ } else {
+ $var(ltpm_realm) = $fd+"/TOTAL/min";
+ $var(ltps_realm) = $fd+"/TOTAL/sec";
+ $var(ltpm_device) = $fU+"@"+$fd+"/TOTAL/min";
+ $var(ltps_device) = $fU+"@"+$fd+"/TOTAL/sec";
+ $var(entity) = $fd;
+ }
+
+ # REALM check
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ if ($sht(rate_limits=>$var(lrpm_realm)) == -1
+ || $sht(rate_limits=>$var(lrps_realm)) == -1) {
+ xlog("L_INFO", "$ci|RL-realm log| Can't find HASHed rate for $var(entity) with $rm method\n");
+ $var(with-realm-request) = "true";
+ }
+ }
+
+ if ($sht(rate_limits=>$var(ltpm_realm)) == -1
+ || $sht(rate_limits=>$var(ltps_realm)) == -1) {
+ xlog("L_INFO", "$ci|RL-realm log| Can't find HASHed rate for $var(entity) with $rm method\n");
+ $var(with-realm-total) = "true";
+ }
+
+ if (not_empty("$fU")) {
+ if ($fd =~ IP_REGEX) {
+ xlog("L_WARNING","$ci|RL-realm log| Fixup for $rm method with IP in from URI: use to-domain\n");
+ $var(entity) = $fU+"@"+$td;
+ } else {
+ $var(entity) = $fU+"@"+$fd;
+ }
+
+ #DEVICE check
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ if ($sht(rate_limits=>$var(lrpm_device)) == -1
+ || $sht(rate_limits=>$var(lrps_device)) == -1) {
+ xlog("L_INFO", "$ci|RL-device log| Can't find HASHed rate for $var(entity) with $rm method\n");
+ $var(with-device-request) = "true";
+ }
+ }
+
+ if ($sht(rate_limits=>$var(ltpm_device)) == -1 || $sht(rate_limits=>$var(ltps_device)) == -1) {
+ xlog("L_INFO", "$ci|RL-device log| Can't find HASHed rate for $var(entity) with $rm method\n");
+ $var(with-device-total) = "true";
+ }
+ }
+
+ if ((is_method("INVITE") || is_method("REGISTER"))
+ && (($var(with-device-request) == "true" && $var(with-device-total) == "true")
+ || ($var(with-realm-request) == "true" && $var(with-realm-total) == "true"))) {
+ $var(method-key) = "Method-List";
+ $var(method-value) = "[\"" + $rm + "\", \"TOTAL\"]";
+ }
+
+ if ( $var(with-device-request) == "true"
+ || $var(with-device-total) == "true"
+ || $var(with-realm-request) == "true"
+ || $var(with-realm-total) == "true" ) {
+
+ avp_printf("$avp(s:query-request)", "{\"Entity\" : \"$var(entity)\", \"$var(method-key)\" : $var(method-value), \"Event-Category\" : \"rate_limit\", \"Event-Name\" : \"query\", \"With-Realm\" : $var(with-realm-request)}");
+ xlog("L_INFO", "$ci|RL log| Query: $avp(s:query-request)\n");
+ sl_send_reply("100", "Attempting K query");
+ if (kazoo_query("frontier", "sbc_config", $avp(s:query-request), "$var(amqp_result)")) {
+ xlog("L_INFO", "$ci|RL log| Response: $var(amqp_result)\n");
+
+ kazoo_json($var(amqp_result), "Realm.Minute." + $rm, "$var(realm-min)");
+ kazoo_json($var(amqp_result), "Realm.Second." + $rm, "$var(realm-sec)");
+ kazoo_json($var(amqp_result), "Realm.Minute.TOTAL", "$var(realm-min-total)");
+ kazoo_json($var(amqp_result), "Realm.Second.TOTAL", "$var(realm-sec-total)");
+ kazoo_json($var(amqp_result), "Device.Minute." + $rm, "$var(device-min)");
+ kazoo_json($var(amqp_result), "Device.Second." + $rm, "$var(device-sec)");
+ kazoo_json($var(amqp_result), "Device.Minute.TOTAL", "$var(device-min-total)");
+ kazoo_json($var(amqp_result), "Device.Second.TOTAL", "$var(device-sec-total)");
+
+ if ( not_empty("$var(realm-min)") ) {
+ $sht(rate_limits=>$var(lrpm_realm)) = $(var(realm-min){s.int});
+ xlog("L_INFO", "$ci|RL-realm log| $rm DB=>HASH for $var(lrpm_realm)=$sht(rate_limits=>$var(lrpm_realm))\n");
+ }
+ if ( not_empty("$var(realm-sec)") ) {
+ $sht(rate_limits=>$var(lrps_realm)) = $(var(realm-sec){s.int});
+ xlog("L_INFO", "$ci|RL-realm log| $rm DB=>HASH for $var(lrps_realm)=$sht(rate_limits=>$var(lrps_realm))\n");
+ }
+ if ( not_empty("$var(realm-min-total)") ) {
+ $sht(rate_limits=>$var(ltpm_realm)) = $(var(realm-min-total){s.int});
+ xlog("L_INFO", "$ci|RL-realm log| $rm DB=>HASH for $var(ltpm_realm)=$sht(rate_limits=>$var(ltpm_realm))\n");
+ }
+ if ( not_empty("$var(realm-sec-total)") ) {
+ $sht(rate_limits=>$var(ltps_realm)) = $(var(realm-sec-total){s.int});
+ xlog("L_INFO", "$ci|RL-realm log| $rm DB=>HASH for $var(ltps_realm)=$sht(rate_limits=>$var(ltps_realm))\n");
+ }
+ if ( not_empty("$var(device-min)") ) {
+ $sht(rate_limits=>$var(lrpm_device)) = $(var(device-min){s.int});
+ xlog("L_INFO", "$ci|RL-device log| $rm DB=>HASH for $var(lrpm_device)=$sht(rate_limits=>$var(lrpm_device))\n");
+ }
+ if ( not_empty("$var(device-sec)") ) {
+ $sht(rate_limits=>$var(lrps_device)) = $(var(device-sec){s.int});
+ xlog("L_INFO", "$ci|RL-device log| $rm DB=>HASH for $var(lrps_device)=$sht(rate_limits=>$var(lrps_device))\n");
+ }
+ if ( not_empty("$var(device-min-total)") ) {
+ $sht(rate_limits=>$var(ltpm_device)) = $(var(device-min-total){s.int});
+ xlog("L_INFO", "$ci|RL-device log| $rm DB=>HASH for $var(ltpm_device)=$sht(rate_limits=>$var(ltpm_device))\n");
+ }
+ if ( not_empty("$var(device-sec-total)") ) {
+ $sht(rate_limits=>$var(ltps_device)) = $(var(device-sec-total){s.int});
+ xlog("L_INFO", "$ci|RL-device log| $rm DB=>HASH for $var(ltps_device)=$sht(rate_limits=>$var(ltps_device))\n");
+ }
+ } else {
+ xlog("L_ERROR", "$ci|RL log| $rm DB unreachable for entity: $var(entity)\n");
+ return;
+ }
+ }
+
+ if ($fd =~ IP_REGEX) {
+ xlog("L_WARNING","$ci|RL-device log| Fixup for $rm method with IP in from URI: use to-domain\n");
+ $var(entity) = $td;
+ } else {
+ $var(entity) = $fd;
+ }
+ $var(entity-type) = "realm";
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ $var(lrpm) = $sht(rate_limits=>$var(lrpm_realm));
+ $var(lrps) = $sht(rate_limits=>$var(lrps_realm));
+ }
+ $var(ltpm) = $sht(rate_limits=>$var(ltpm_realm));
+ $var(ltps) = $sht(rate_limits=>$var(ltps_realm));
+
+
+ route(DO_DOS_PREVENTION);
+ if ( not_empty("$fU") ) {
+ if ($fd =~ IP_REGEX) {
+ $var(entity) = $fU+"@"+$td;
+ xlog("L_WARNING","$ci|RL-device log| Fixup for $rm method with IP in from URI: use to-domain\n");
+ } else {
+ $var(entity) = $fU+"@"+$fd;
+ }
+ $var(entity-type) = "device";
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ $var(lrpm) = $sht(rate_limits=>$var(lrpm_device));
+ $var(lrps) = $sht(rate_limits=>$var(lrps_device));
+ }
+ $var(ltpm) = $sht(rate_limits=>$var(ltpm_device));
+ $var(ltps) = $sht(rate_limits=>$var(ltps_device));
+ route(DO_DOS_PREVENTION);
+ }
+}
+
+# This route do counting and decide either to ACCEPT or DECLINE packet
+route[DO_DOS_PREVENTION] {
+ # Personal counters for INVITE and REGISTER
+ if ((is_method("INVITE") || is_method("REGISTER"))) {
+ $var(rpm) = $var(entity)+":"+$rm+":min:"+$timef(%Y/%m/%d_%H_%M_00);
+ $var(rps) = $var(entity)+":"+$rm+":sec:"+$timef(%Y/%m/%d_%H_%M_%S);
+ }
+ # Commmon counters for ALL packet including INVITE and REGISTER
+ $var(tpm) = $var(entity)+":TOTAL:min:"+$timef(%Y/%m/%d_%H_%M_00);
+ $var(tps) = $var(entity)+":TOTAL:sec:"+$timef(%Y/%m/%d_%H_%M_%S);
+
+ # Personal debug for INVITE and REGISTER
+ if ((is_method("INVITE") || is_method("REGISTER"))) {
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| L/C for $var(rpm) = $var(lrpm)/$sht(rpm=>$var(rpm))\n");
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| L/C for $var(rps) = $var(lrps)/$sht(rps=>$var(rps))\n");
+ }
+ # Commmon debug for ALL packet including INVITE and REGISTER
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| L/C for $var(tpm) = $var(ltpm)/$sht(tpm=>$var(tpm))\n");
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| L/C for $var(tps) = $var(ltps)/$sht(tps=>$var(tps))\n");
+
+ # Personal increment just for INVITE and REGISTER
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ $sht(rpm=>$var(rpm)) = $shtinc(rpm=>$var(rpm));
+ $sht(rps=>$var(rps)) = $shtinc(rps=>$var(rps));
+ }
+ # Commmon increment for ALL packet including INVITE and REGISTER
+ $sht(tpm=>$var(tpm)) = $shtinc(tpm=>$var(tpm));
+ $sht(tps=>$var(tps)) = $shtinc(tps=>$var(tps));
+
+ # Personal checks for INVITE and REGISTER
+ if ((is_method("INVITE") || is_method("REGISTER")) && (!isflagset(FLAG_IS_REPLY))) {
+ if ($sht(rps=>$var(rps)) > $var(lrps)) {
+ sl_send_reply(RATE_LIMIT_CODE, RATE_LIMIT_MESSAGE);
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of $rm $var(rps) rate limits: $sht(rps=>$var(rps)) > $var(lrps))\n");
+ exit;
+ }
+ if ($sht(rpm=>$var(rpm)) > $var(lrpm)) {
+ sl_send_reply(RATE_LIMIT_CODE, RATE_LIMIT_MESSAGE);
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of $rm $var(rpm) rate limits: $sht(rpm=>$var(rpm)) > $var(lrpm))\n");
+ exit;
+ }
+ }
+ # Commmon checks for ALL packet including INVITE and REGISTER
+ if ($sht(tps=>$var(tps)) > $var(ltps)) {
+ if (isflagset(FLAG_IS_REPLY)) {
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of TOTAL($rm::$rs $rr) $var(tps) rate limits: $sht(tps=>$var(tps)) > $var(ltps))\n");
+ } else {
+ sl_send_reply(RATE_LIMIT_CODE, RATE_LIMIT_MESSAGE);
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of TOTAL($rm) $var(tps) rate limits: $sht(tps=>$var(tps)) > $var(ltps))\n");
+ }
+ exit;
+ }
+ if ($sht(tpm=>$var(tpm)) > $var(ltpm)) {
+ if (isflagset(FLAG_IS_REPLY)) {
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of TOTAL($rm::$rs $rr) $var(tpm) rate limits: $sht(tpm=>$var(tpm)) > $var(ltpm))\n");
+ } else {
+ sl_send_reply(RATE_LIMIT_CODE, RATE_LIMIT_MESSAGE);
+ xlog("L_INFO", "$ci|RL-$var(entity-type) log| Out of TOTAL($rm) $var(tpm) rate limits: $sht(tpm=>$var(tpm)) > $var(ltpm))\n");
+ }
+ exit;
+ }
+}
diff --git a/kamailio-proxy-proxy/registrar-role.cfg b/kamailio-proxy-proxy/registrar-role.cfg
new file mode 100644
index 0000000..e88e302
--- /dev/null
+++ b/kamailio-proxy-proxy/registrar-role.cfg
@@ -0,0 +1,588 @@
+#### NAT PINGING PARAMS ###
+#!trydef REGISTRAR_NAT_PING_INTERVAL 30
+
+## REGISTRAR_NAT_PING_TIMEOUT should be (REGISTRAR_NAT_PING_INTERVAL * 3 + 10) or 0 to disable
+#!trydef REGISTRAR_NAT_PING_TIMEOUT 0
+
+#!trydef REGISTRAR_NAT_PING_NAT_ONLY 1
+#!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_ERROR_MISSING_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
+#!trydef REGISTRAR_HANDLE_EXPIRED_TCP 1
+#!trydef REGISTRAR_HANDLE_EXPIRED_UDP 0
+#!trydef REGISTRAR_HANDLE_EXPIRED_TLS 1
+#!trydef REGISTRAR_HANDLE_EXPIRED_WS 1
+#!trydef REGISTRAR_FORCE_QUERY 0
+#!trydef REGISTRAR_FORCE_FAILOVER 0
+#!trydef REGISTRAR_CHECK_AMQP_AVAILABILITY 1
+#!trydef KZ_REGISTRAR_KEEPALIVE_UDP_ONLY 1
+#!trydef REGISTRAR_AMQP_EXCHANGE callmgr
+#!trydef REGISTRAR_AMQP_FLAGS 0
+#!trydef REGISTRAR_AMQP_RK_PREFIX authn.req.
+#!trydef REGISTRAR_SEND_100 1
+#!trydef REGISTRAR_DB_MODE 2
+#!trydef REGISTRAR_DB_TIMER_CLEANUP 0
+#!trydef REGISTRAR_DB_REMOVE_EXPIRED_DELAY 0
+#!trydef REGISTRAR_SYNC_TIMER_INTERVAL 5
+#!trydef REGISTRAR_SYNC_TIMER_PROCS 1
+
+
+#!ifdef REGISTRAR_WARM_CACHE
+#!substdef "!REGISTRAR_S_WARM_CACHE!dbtable=auth_cache;dbmode=1;!g"
+#!else
+#!substdef "!REGISTRAR_S_WARM_CACHE!!g"
+#!endif
+
+######## Generic Hash Table container in shared memory ########
+modparam("htable", "htable", "auth_cache=>size=16;autoexpire=7200;REGISTRAR_S_WARM_CACHE")
+
+####### Authentication Interface module ##########
+loadmodule "auth.so"
+
+####### User Location Implementation module ##########
+loadmodule "usrloc.so"
+modparam("usrloc", "db_update_as_insert", 0)
+modparam("usrloc", "use_domain", 1)
+modparam("usrloc", "nat_bflag", FLB_NATB)
+modparam("usrloc", "db_url", "KAZOO_DB_URL")
+
+modparam("usrloc", "db_mode", REGISTRAR_DB_MODE)
+
+modparam("usrloc", "db_timer_clean", REGISTRAR_DB_TIMER_CLEANUP)
+modparam("usrloc", "handle_lost_tcp", REGISTRAR_HANDLE_LOST_TCP)
+modparam("usrloc", "rm_expired_delay", REGISTRAR_DB_REMOVE_EXPIRED_DELAY)
+
+modparam("usrloc", "db_check_update", 1)
+modparam("usrloc", "db_ops_ruid", 1)
+
+
+modparam("usrloc", "xavp_contact", "ulattrs")
+modparam("usrloc", "timer_interval", REGISTRAR_SYNC_TIMER_INTERVAL)
+modparam("usrloc", "timer_procs", REGISTRAR_SYNC_TIMER_PROCS)
+
+modparam("usrloc", "fetch_rows", 400)
+modparam("usrloc", "handle_lost_tcp", REGISTRAR_HANDLE_LOST_TCP)
+modparam("usrloc", "close_expired_tcp", REGISTRAR_CLOSE_EXPIRED_TCP)
+
+####### SIP Registrar implementation module ##########
+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)
+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", "contact_max_size", REGISTRAR_CONTACT_MAX_SIZE)
+
+####### NAT ##########
+#!ifdef NAT_TRAVERSAL_ROLE
+#!ifndef NATHELPER_LOADED
+loadmodule "nathelper.so"
+#!trydef NATHELPER_LOADED
+#!endif
+#!ifdef KEEPALIVE_ROLE
+modparam("nathelper", "natping_interval", 0)
+modparam("nathelper", "natping_processes", 0)
+#!else
+modparam("nathelper", "natping_interval", REGISTRAR_NAT_PING_INTERVAL)
+modparam("nathelper", "ping_nated_only", REGISTRAR_NAT_PING_NAT_ONLY)
+modparam("nathelper", "natping_processes", REGISTRAR_NAT_PING_WORKERS)
+modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
+modparam("nathelper", "keepalive_timeout", REGISTRAR_NAT_PING_TIMEOUT)
+#!endif
+#!endif
+
+## stats ##
+modparam("statistics","variable", "registrar:force_failover")
+modparam("statistics","variable", "registrar:cached")
+modparam("statistics","variable", "registrar:ip_realm")
+modparam("statistics","variable", "registrar:new_tran")
+modparam("statistics","variable", "registrar:amqp_not_available")
+modparam("statistics","variable", "registrar:challenge")
+modparam("statistics","variable", "registrar:amqp_async_error")
+modparam("statistics","variable", "registrar:amqp_returned")
+modparam("statistics","variable", "registrar:amqp_timeout")
+modparam("statistics","variable", "registrar:drops")
+modparam("statistics","variable", "registrar:authn_perm_err")
+modparam("statistics","variable", "registrar:authn_err")
+modparam("statistics","variable", "registrar:authn_resp")
+modparam("statistics","variable", "registrar:authn_unknown")
+modparam("statistics","variable", "registrar:save_error")
+modparam("statistics","variable", "registrar:missing_expires")
+modparam("statistics","variable", "registrar:missing_expires_allowed")
+modparam("statistics","variable", "registrar:min_expires")
+modparam("statistics","variable", "registrar:min_expires_allowed")
+
+
+##### registrar realtime params #####
+kazoo.registrar_error_min_expires = REGISTRAR_ERROR_MIN_EXPIRES descr "send error when UAS sends expires < min-expires"
+kazoo.registrar_error_missing_expires = REGISTRAR_ERROR_MISSING_EXPIRES descr "send error when UAS do not send expires header"
+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 = REGISTRAR_FORCE_FAILOVER descr "force failover if 1"
+kazoo.registrar_force_query = REGISTRAR_FORCE_QUERY descr "force query if 1"
+kazoo.registrar_check_amqp_availability = REGISTRAR_CHECK_AMQP_AVAILABILITY descr "checks if amqp connection is available before querying registrar"
+kazoo.registrar_keepalive_udp_only = KZ_REGISTRAR_KEEPALIVE_UDP_ONLY descr "should we keepalive nat phones for udp only"
+kazoo.registrar_send_100 = REGISTRAR_SEND_100 descr "should we send 100 reply while doing directory search"
+
+####### Registrar Logic ########
+
+route[REGISTRAR_NAT_FLAGS]
+{
+ if (isflagset(FLT_NATS)) {
+ xlog("L_DEBUG", "$ci|log|fixing contact for nat request\n");
+ setbflag(FLB_NATB);
+ fix_nated_register();
+
+ ## KAZOO-1846: Cisco SPA8000 freaks out on options pings
+ if (!($ua =~ "Linksys/SPA8000"
+ || $ua =~ "SIPp"
+ || (af==INET6)
+ || ($sel(cfg_get.kazoo.registrar_keepalive_udp_only) == 1 && $proto != "udp")
+ || ($proto =="ws" || $proto == "wss")
+ || ($(xavp(ulattrs=>custom_channel_vars){kz.json,Keep-Alive}) == "false")
+ )) {
+ xlog("L_DEBUG", "$ci|log|set nat pinging\n");
+ setbflag(FLB_NATSIPPING);
+ }
+ } else {
+ $avp(AVP_RECV_PARAM) = $su;
+ }
+}
+
+route[HANDLE_REGISTER]
+{
+ if (!is_method("REGISTER")) {
+ return;
+ }
+
+ #!ifdef PUSHER_ROLE
+ route(PUSHER_ATTEMPT_REGISTRATION);
+ #!endif
+
+ if($sel(cfg_get.kazoo.registrar_failover) == 1) {
+ xlog("L_INFO", "$ci|log|register|forcing failover\n");
+ update_stat("registrar:force_failover", "+1");
+ drop;
+ }
+
+ if($sel(cfg_get.kazoo.registrar_force_query) == 0) {
+ if($sht(auth_cache=>$Au) == "authn_perm_err") {
+ xlog("L_INFO", "$ci|end|issuing auth challenge to cached permanent failed registration attempt for $Au from IP $si:$sp\n");
+ update_stat("registrar:authn_perm_err", "+1");
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANITFLOOD_FAILED_AUTH);
+ #!endif
+ update_stat("registrar:challenge", "+1");
+ auth_challenge("$fd", "4");
+ exit;
+ } else if($sht(auth_cache=>$Au) != $null) {
+ $xavp(regcfg=>match_received) = $su;
+ if(registered("location", "$rz:$Au", 2, 1) == 1) {
+ if($(xavp(ulattrs=>custom_channel_vars){s.len}) > 1) {
+ $var(password) = $sht(auth_cache=>$Au);
+ update_stat("registrar:cached", "+1");
+ route(SAVE_LOCATION);
+ exit;
+ }
+ }
+ }
+ }
+
+ 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");
+ update_stat("registrar:ip_realm", "+1");
+ drop;
+ }
+
+ if($sel(cfg_get.kazoo.registrar_check_amqp_availability) == 1) {
+ if($xavp(amqpc=>default::MY_AMQP_ZONE) == 0) {
+ xlog("L_WARNING", "$ci|end|register|no amqp connection available for default worker in zone MY_AMQP_ZONE\n");
+ update_stat("registrar:amqp_not_available", "+1");
+ drop;
+ }
+ }
+
+ route(REGISTRAR_BOUNDS);
+
+ $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", "4");
+ update_stat("registrar:challenge", "+1");
+ if($var(auth) != 1) {
+ xlog("L_ERROR", "$ci|register|error creating or sending challenge to registration attempt for $fu from $si:$sp\n");
+ drop;
+ }
+ exit;
+ }
+
+ if (!t_newtran()) {
+ xlog("L_ERROR", "$ci|log|failed to create transaction to query for authentication credentials for $Au $si:$sp\n");
+ update_stat("registrar:new_tran", "+1");
+ drop;
+ }
+
+ if($sel(cfg_get.kazoo.registrar_send_100) == 1) {
+ sl_send_reply("100", "checking your credentials");
+ }
+
+ $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) = $_s($def(REGISTRAR_AMQP_RK_PREFIX)$(fd{kz.encode}));
+ $avp(kz_timeout) = $sel(cfg_get.kazoo.registrar_query_timeout_ms);
+ $xavp(deltas=>query) = $(TV(Sn){s.replace,.,});
+
+ xlog("L_DEBUG", "$ci|amqp|publishing to $def(REGISTRAR_AMQP_EXCHANGE) => $var(amqp_routing_key) : $def(REGISTRAR_AMQP_FLAGS) : $var(amqp_payload_request)\n");
+ if(kazoo_async_query("$def(REGISTRAR_AMQP_EXCHANGE)", $var(amqp_routing_key), $var(amqp_payload_request), "KZ_AUTHORIZATION_REPLY", "KZ_AUTHORIZATION_TIMEOUT", "$def(REGISTRAR_AMQP_FLAGS)") != 1) {
+ xlog("L_INFO", "$ci|log|failed to send registrar query for authentication credentials for $Au $si:$sp\n");
+ update_stat("registrar:amqp_async_error", "+1");
+ t_drop();
+ }
+}
+
+failure_route[KZ_AUTHORIZATION_TIMEOUT]
+{
+ if($(kzR{kz.json,Event-Name}) == "message_returned" ) {
+ xlog("L_WARNING", "$ci|amqp|message was returned by broker $(kzR{kz.json,Error-Code}) $(kzR{kz.json,Error-Reason})\n");
+ update_stat("registrar:amqp_returned", "+1");
+ } else {
+ xlog("L_WARNING", "$ci|end|failed $T_reply_code $T_reply_reason [$T(id_index):$T(id_label)] querying directory for authentication credentials for $Au $si:$sp\n");
+ update_stat("registrar:amqp_timeout", "+1");
+ }
+ update_stat("registrar:drops", "+1");
+ t_drop();
+}
+
+onreply_route[KZ_AUTHORIZATION_REPLY]
+{
+ $var(StartRoute) = $(TV(Sn){s.replace,.,});
+ $var(delta_to_start) = $var(StartRoute) - $(kzR{kz.json,AMQP-Received});
+ $var(delta_from_query) = $(kzR{kz.json,AMQP-Received}) - $xavp(deltas=>query);
+ 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}) (Δ1 $(kzR{kz.json,AMQP-Elapsed-Micro}) μs , Δ2 $var(delta_to_start) μs, Δ3 $var(delta_from_query) μs)\n");
+ $var(password) = $(kzR{kz.json,Auth-Password});
+ $var(nonce) = $adn;
+ if( $(kzR{kz.json,Event-Name}) == "authn_err" ) {
+ if($(kzR{kz.json,Permanent-Error}) == "true") {
+ $sht(auth_cache=>$Au) = "authn_perm_err";
+ }
+ update_stat("registrar:authn_err", "+1");
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANITFLOOD_FAILED_AUTH);
+ #!endif
+ update_stat("registrar:challenge", "+1");
+ auth_challenge("$fd", "4");
+ xlog("L_INFO", "$ci|end|challenging $Au $si:$sp via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version}) response\n");
+ exit;
+ } else if( $(kzR{kz.json,Event-Name}) == "authn_resp" ) {
+ update_stat("registrar:authn_resp", "+1");
+ xlog("L_INFO", "$ci|log|authenticating $Au via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version}) response\n");
+ route(CHECK_AUTHORIZATION);
+ } else {
+ update_stat("registrar:authn_unknown", "+1");
+ update_stat("registrar:drops", "+1");
+ xlog("L_INFO", "$ci|log|unhandle response from directory $Au via $(kzR{kz.json,App-Name})-$(kzR{kz.json,App-Version})\n");
+ t_drop();
+ }
+}
+
+route[CHECK_AUTHORIZATION]
+{
+
+ if (!pv_auth_check("$fd", "$var(password)", "0", "0")) {
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANITFLOOD_FAILED_AUTH);
+ #!endif
+
+ xlog("L_WARNING", "$ci|end|issuing auth challenge to failed registration attempt for $Au from IP $si:$sp\n");
+ update_stat("registrar:challenge", "+1");
+ auth_challenge("$fd", "5");
+ exit;
+ }
+
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANTIFLOOD_SUCCESSFUL_AUTH);
+ #!endif
+
+ # 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 && $var(password) != $null) {
+ xlog("L_INFO", "$ci|log|caching sip credentials for $Au\n");
+ };
+ $sht(auth_cache=>$Au) = $var(password);
+
+ route(REGISTRAR_NAT_FLAGS);
+
+ $var(save_result) = save("location", "0x04");
+ if($var(save_result) < 0) {
+ xlog("L_WARNING", "$ci|end|not expected result $var(save_result) when saving $Au registration from IP $si:$sp\n");
+ update_stat("registrar:save_error", "+1");
+ exit;
+ } else {
+ if($var(save_result) == 1) {
+ $var(new_reg) = "true";
+ } else {
+ $var(new_reg) = "false";
+ }
+ }
+
+ 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";
+ }
+
+ $var(ip) = $Ri;
+ if(af==INET6) {
+ $var(ip) = "[" + $Ri + "]";
+ }
+
+ # allow port redirection on registration
+ switch($proto)
+ {
+ #!ifdef KZ_WEBSOCKETS_REGISTRAR_PORT
+ case "ws":
+ case "wss":
+ $var(port) = KZ_WEBSOCKETS_REGISTRAR_PORT;
+ break;
+ #!endif
+
+ #!ifdef KZ_TLS_REGISTRAR_PORT
+ case "tls":
+ $var(port) = KZ_TLS_REGISTRAR_PORT;
+ break;
+ #!endif
+
+ #!ifdef KZ_UDP_REGISTRAR_PORT
+ case "udp":
+ $var(port) = KZ_UDP_REGISTRAR_PORT;
+ break;
+ #!endif
+
+ #!ifdef KZ_TCP_REGISTRAR_PORT
+ case "tcp":
+ $var(port) = KZ_TCP_REGISTRAR_PORT;
+ break;
+ #!endif
+
+ 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: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 : $var(expires)\n");
+
+ #!ifdef PUSHER_ROLE
+ route(PUSHER_ON_REGISTRATION);
+ #!endif
+
+ #!ifdef KEEPALIVE_ROLE
+ route(KEEPALIVE_ON_REGISTRATION);
+ #!endif
+
+ exit;
+}
+
+## kazoo event route , {"directory", "reg_flush") => reg-flush by kamailio limitations
+## when a Event-Category or Event-Name has a underscore (_) we need to declare it with a dash (-)
+event_route[kazoo:consumer-event-directory-reg-flush]
+{
+ $var(user) = $(kzE{kz.json,Username}) + "@" + $(kzE{kz.json,Realm});
+ xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|log|received directory flush for $var(user)\n");
+ if ($sht(auth_cache=>$var(user)) != $null) {
+ $sht(auth_cache=>$var(user)) = $null;
+ }
+
+ if( $(kzE{kz.json,Cache-Only}) == "true") {
+ return;
+ }
+
+ if(reg_fetch_contacts("location", "sip:$var(user)", "caller")) {
+ $var(i) = 0;
+ while($var(i) < $(ulc(caller=>count))) {
+ unregister("location", "sip:$(ulc(caller=>aor))", "$(ulc(caller=>ruid)[$var(i)])");
+ $var(i) = $var(i) + 1;
+ }
+ reg_free_contacts("caller");
+ }
+
+
+ #!ifdef ANTIFLOOD_ROLE
+ route(ANTIFLOOD_RESET_AUTH);
+ #!endif
+}
+
+route[REGISTRAR_BINDINGS]
+{
+ #!import_file "registrar-custom-bindings.cfg"
+
+ #!ifndef REGISTRAR_CUSTOM_BINDINGS
+
+ $var(payload) = $_s({"name": "registrar-api", "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 {
+ if($sel(cfg_get.kazoo.registrar_error_missing_expires) == 1) {
+ xlog("L_WARNING", "$ci|end|missing expires registering $Au from IP $si:$sp\n");
+ send_reply("400", "Missing Expires");
+ update_stat("registrar:missing_expires", "+1");
+ exit;
+ } else {
+ update_stat("registrar:missing_expires_allowed", "+1");
+ xlog("L_WARNING", "$ci|end|allowing missing expires registering $Au from IP $si:$sp\n");
+ }
+ }
+
+ if($var(expires) != 0) {
+ if($var(expires) < REGISTRAR_MIN_EXPIRES) {
+ if($sel(cfg_get.kazoo.registrar_error_min_expires) == 1) {
+ xlog("L_WARNING", "$ci|end|expires $var(expires) too brief (configured $def(REGISTRAR_MIN_EXPIRES)) registering $Au from IP $si:$sp\n");
+ append_to_reply("Min-Expires: $def(REGISTRAR_MIN_EXPIRES)\r\n");
+ send_reply("423", "Interval Too Brief");
+ update_stat("registrar:min_expires", "+1");
+ exit;
+ } else {
+ update_stat("registrar:min_expires_allowed", "+1");
+ xlog("L_WARNING", "$ci|end|allowing expires $var(expires) too brief (configured $def(REGISTRAR_MIN_EXPIRES)) registering $Au from IP $si:$sp\n");
+ }
+ }
+ }
+
+}
+
+##
+## 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]
+{
+ #!ifdef PRESENCE_ROLE
+ route(PRESENCE_EXPIRED_REGISTRATION);
+ #!endif
+
+ #!ifdef KEEPALIVE_ROLE
+ route(KEEPALIVE_ON_EXPIRED_REGISTRATION);
+ #!endif
+
+ ## return until we handle this in ecallmr
+ xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration for $ulc(exp=>aor) with contact : $ulc(exp=>addr)\n");
+ return;
+
+ $var(transport) = $(ulc(exp=>received){uri.transport});
+ $var(proto) = $(ulc(exp=>socket){re.subst,/^([^:]*):(.*)/\1/});
+ if($var(proto) == "tls" && $var(transport) == "ws") {
+ $var(proto) = "wss";
+ }
+ $var(handle) = 0;
+ switch($var(proto))
+ {
+ case "ws":
+ case "wss":
+ if($sel(cfg_get.kazoo.registrar_handle_expired_ws) == 1) {
+ $var(handle) = 1;
+ }
+ break;
+
+ case "tls":
+ if($sel(cfg_get.kazoo.registrar_handle_expired_tls) == 1) {
+ $var(handle) = 1;
+ }
+ break;
+
+ case "tcp":
+ if($sel(cfg_get.kazoo.registrar_handle_expired_tcp) == 1) {
+ $var(handle) = 1;
+ }
+ break;
+
+ case "udp":
+ if($sel(cfg_get.kazoo.registrar_handle_expired_udp) == 1) {
+ $var(handle) = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if($var(handle) == 1) {
+ $var(aor) = $_s(sip:$ulc(exp=>aor));
+ $var(username) = $(var(aor){uri.user});
+ $var(domain) = $(var(aor){uri.host});
+ $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 registration removal with contact : $ulc(exp=>addr)\n");
+ }
+ xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration for $ulc(exp=>aor) with contact : $ulc(exp=>addr)\n");
+}
+
+#!ifdef REGISTRAR_SYNC_ROLE
+#!include_file "registrar-sync-role.cfg"
+#!endif
+
+# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
diff --git a/kamailio-proxy-proxy/registrar-sync-role.cfg b/kamailio-proxy-proxy/registrar-sync-role.cfg
new file mode 100644
index 0000000..b864f99
--- /dev/null
+++ b/kamailio-proxy-proxy/registrar-sync-role.cfg
@@ -0,0 +1,31 @@
+######## Presence sync server module ########
+
+event_route[kazoo:consumer-event-directory-reg-sync]
+{
+ $var(Server) = $(kzE{kz.json,Server-ID});
+ xlog("L_INFO", "received registrar sync from $var(Server) : $kzE\n");
+
+ if (sql_xquery("cb", "select * from location", "ra") == 1)
+ {
+ while($xavp(ra) != $null) {
+ $var(runloop) = 1;
+ while($xavp(ra) != $null && $var(runloop) < MAX_WHILE_LOOPS ) {
+ if(registered("location", "sip:$xavp(ra=>username)@$xavp(ra=>domain)", 0, 1)) {
+ xlog("L_INFO", "[id, username, domain] = [$xavp(ra=>id), $xavp(ra=>username), $xavp(ra=>domain)]\n");
+ $var(Expires) = $xavp(ra=>expires) - $TS;
+ $var(amqp_payload_request) = '{"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "Success", "Event-Timestamp" : $TS, "Expires" : $(var(Expires){s.int}), "First-Registration" : false, "Contact" : "$(xavp(ra=>contact){s.escape.common})", "Call-ID" : "$xavp(ra=>callid)", "Realm" : "$xavp(ra=>domain)", "Username" : "$xavp(ra=>username)", "From-User" : "$xavp(ra=>username)", "From-Host" : "$xavp(ra=>domain)", "To-User" : "$xavp(ra=>username)", "To-Host" : "$xavp(ra=>domain)", "User-Agent" : "$(xavp(ra=>user_agent){s.escape.common})" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), "Proxy-Path" : "sip:$(xavp(ra=>socket){s.substr,4,0})" }';
+ kazoo_publish("targeted", "$var(Server)", $var(amqp_payload_request));
+ }
+ pv_unset("$xavp(ra)");
+ $var(runloop) = $var(runloop) + 1;
+ }
+ }
+ }
+
+}
+
+route[REGISTRAR_SYNC_BINDINGS]
+{
+ $var(payload) = $_s({"exchange": "registrar", "type": "topic", "queue": "registrar-sync-MY_HOSTNAME", "routing": "registration.sync"});
+ kazoo_subscribe("$var(payload)");
+}
diff --git a/kamailio-proxy-proxy/responder-role.cfg b/kamailio-proxy-proxy/responder-role.cfg
new file mode 100644
index 0000000..15885af
--- /dev/null
+++ b/kamailio-proxy-proxy/responder-role.cfg
@@ -0,0 +1,12 @@
+####### Responder Logic ########
+route[HANDLE_RESPOND]
+{
+ $var(header) = $hdr(X-KAZOO-Respond-With);
+ if (not_empty("$var(header)")) {
+ $var(code) = $(var(header){s.substr,0,3}{s.int});
+ $var(msg) = $(var(header){s.substr,4,0});
+ xlog("L_INFO", "$ci|end|Responding with [$var(code)/$var(msg)]\n");
+ sl_send_reply("$var(code)", "$var(msg)");
+ exit();
+ }
+}
diff --git a/kamailio-proxy-proxy/sanity.cfg b/kamailio-proxy-proxy/sanity.cfg
new file mode 100644
index 0000000..92ba2fc
--- /dev/null
+++ b/kamailio-proxy-proxy/sanity.cfg
@@ -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;
+ }
+}
diff --git a/kamailio-proxy-proxy/sip_trace-role.cfg b/kamailio-proxy-proxy/sip_trace-role.cfg
new file mode 100644
index 0000000..afae3c7
--- /dev/null
+++ b/kamailio-proxy-proxy/sip_trace-role.cfg
@@ -0,0 +1,97 @@
+#################################
+## SIP_TRACE_ROLE Defs
+
+#!trydef KZ_TRACE 0
+#!trydef KZ_TRACE_INTERNAL 1
+#!trydef KZ_TRACE_EXTERNAL 1
+#!trydef KZ_TRACE_LOCAL 1
+#!trydef KZ_TRACE_INTERNAL_INCOMING 1
+#!trydef KZ_TRACE_INTERNAL_OUTGOING 1
+#!trydef KZ_TRACE_EXTERNAL_INCOMING 1
+#!trydef KZ_TRACE_EXTERNAL_OUTGOING 1
+#!trydef SIP_TRACE_URI "sip:127.0.0.1:9060"
+#!trydef HEP_CAPTURE_ID 1
+
+##############################################################
+## Kamailio siptrace settings configuration examples at runtime
+## kamcmd siptrace.status on
+## kamcmd cfg.seti kazoo trace_external 0
+## kamcmd cfg.seti kazoo trace_internal 0
+
+kazoo.trace_external = KZ_TRACE_EXTERNAL descr "activates tracing from external sources"
+kazoo.trace_internal = KZ_TRACE_INTERNAL descr "activates tracing from internal sources"
+kazoo.trace_local = KZ_TRACE_LOCAL descr "activates tracing for local requests"
+
+kazoo.trace_internal_incoming = KZ_TRACE_INTERNAL_INCOMING descr "traces the original request as received from internal sources"
+kazoo.trace_internal_outgoing = KZ_TRACE_INTERNAL_OUTGOING descr "traces the outgoing request to external sources after possible modification"
+kazoo.trace_external_incoming = KZ_TRACE_EXTERNAL_INCOMING descr "traces the original request as received from external sources"
+kazoo.trace_external_outgoing = KZ_TRACE_EXTERNAL_OUTGOING descr "traces the outgoing request to internal sources after possible modification"
+
+####### Siptrace module ##########
+
+loadmodule "siptrace.so"
+modparam("siptrace", "duplicate_uri", SIP_TRACE_URI)
+modparam("siptrace", "hep_mode_on", 1)
+modparam("siptrace", "hep_version", 3)
+modparam("siptrace", "hep_capture_id", HEP_CAPTURE_ID)
+modparam("siptrace", "trace_to_database", 0)
+## `trace_flag` value must be equal to FLAG_SIP_TRACE value at head of "default.cfg" file
+modparam("siptrace", "trace_flag", 8)
+modparam("siptrace", "trace_on", KZ_TRACE)
+
+route[SIP_TRACE_INTERNAL]
+{
+ if($sel(cfg_get.kazoo.trace_internal) == 0) {
+ return;
+ }
+ if($sel(cfg_get.kazoo.trace_internal_incoming) == 1) {
+ sip_trace();
+ }
+ if($sel(cfg_get.kazoo.trace_internal_outgoing) == 1) {
+ setflag(FLAG_SIP_TRACE);
+ }
+}
+
+route[SIP_TRACE_EXTERNAL]
+{
+ if($sel(cfg_get.kazoo.trace_external) == 0) {
+ return;
+ }
+ if($sel(cfg_get.kazoo.trace_external_incoming) == 1) {
+ sip_trace();
+ }
+ if($sel(cfg_get.kazoo.trace_external_outgoing) == 1) {
+ setflag(FLAG_SIP_TRACE);
+ }
+}
+
+route[SIP_TRACE_LOCAL]
+{
+ if($sel(cfg_get.kazoo.trace_local) == 0) {
+ return;
+ }
+
+ if($hdr(X-TM-Local) != $null) {
+ return;
+ }
+
+ sip_trace();
+}
+
+route[SIP_TRACE_LOCAL_ROUTE]
+{
+ setflag(FLAG_SIP_TRACE);
+}
+
+route[SIP_TRACE]
+{
+ if (isflagset(FLAG_LOCAL_ROUTE)) {
+ route(SIP_TRACE_LOCAL_ROUTE);
+ } else if (isflagset(FLAG_LOCAL_REQUEST)) {
+ route(SIP_TRACE_LOCAL);
+ } else if (isflagset(FLAG_INTERNALLY_SOURCED)) {
+ route(SIP_TRACE_INTERNAL);
+ } else {
+ route(SIP_TRACE_EXTERNAL);
+ }
+}
diff --git a/kamailio-proxy-proxy/tls-role.cfg b/kamailio-proxy-proxy/tls-role.cfg
new file mode 100644
index 0000000..df6507e
--- /dev/null
+++ b/kamailio-proxy-proxy/tls-role.cfg
@@ -0,0 +1,13 @@
+enable_tls = yes
+
+listen=TLS_SIP
+listen=TLS_ALG_SIP
+
+####### TLS Parameters #########
+loadmodule "tls.so"
+modparam("tls", "config", "/etc/kazoo/kamailio/tls.cfg")
+modparam("tls", "low_mem_threshold1", 1)
+modparam("tls", "low_mem_threshold2", 1)
+
+modparam("debugger", "mod_level", "tls=1")
+
diff --git a/kamailio-proxy-proxy/tls.cfg b/kamailio-proxy-proxy/tls.cfg
new file mode 100644
index 0000000..2112f4e
--- /dev/null
+++ b/kamailio-proxy-proxy/tls.cfg
@@ -0,0 +1,52 @@
+#
+# $Id$
+#
+# Example Kamailio TLS Configuration File
+#
+
+# This is the default server domain, settings
+# in this domain will be used for all incoming
+# connections that do not match any other server
+# domain in this configuration file.
+#
+# We do not enable anything else than TLSv1
+# over the public internet. Clients do not have
+# to present client certificates by default.
+#
+[server:default]
+method = SSLv23
+verify_certificate = no
+require_certificate = no
+#crl = /etc/kazoo/kamailio/certs/crl.pem
+certificate = /etc/kazoo/kamailio/certs/cert.pem
+private_key = /etc/kazoo/kamailio/certs/key.pem
+#ca_list = /etc/kazoo/kamailio/certs/ca.pem
+
+# This is the default client domain, settings
+# in this domain will be used for all outgoing
+# TLS connections that do not match any other
+# client domain in this configuration file.
+# We require that servers present valid certificate.
+#
+[client:default]
+verify_certificate = no
+require_certificate = no
+
+# This is an example server domain for TLS connections
+# received from the loopback interface. We allow
+# the use of SSLv2 and SSLv3 protocols here, we do
+# not require that clients present client certificates
+# but if they present it it must be valid. We also use
+# a special certificate and CA list for loopback
+# interface.
+#
+#[server:127.0.0.1:5061]
+#method = SSLv23
+#verify_certificate = yes
+#require_certificate = no
+#private_key = /etc/kazoo/kamailio/certs/local_key.pem
+#certificate = /etc/kazoo/kamailio/certs/local_cert.pem
+#verify_depth = 3
+#ca_list = /etc/kazoo/kamailio/certs/local_ca.pem
+#crl = /etc/kazoo/kamailio/certs/local_crl.pem
+
diff --git a/kamailio-proxy-proxy/traffic-filter-role.cfg b/kamailio-proxy-proxy/traffic-filter-role.cfg
new file mode 100644
index 0000000..8fe1013
--- /dev/null
+++ b/kamailio-proxy-proxy/traffic-filter-role.cfg
@@ -0,0 +1,57 @@
+route[FILTER_REQUEST]
+{
+ # allow request from internal network or from whitelist
+ if (isflagset(FLAG_TRUSTED_SOURCE)) {
+ return;
+ }
+
+ # drop requests with no To domain or IP To domain (friendly-scanner)
+ if (is_method("REGISTER|SUBSCRIBE")) {
+ route(FILTER_TO_DOMAIN);
+ route(FILTER_FROM_DOMAIN);
+ }
+
+ # drop Invite with IP auth realm
+ if (is_method("INVITE")) {
+ route(FILTER_REQUEST_DOMAIN);
+ route(FILTER_AUTHORIZATION_DOMAIN);
+ }
+}
+
+route[FILTER_REQUEST_DOMAIN]
+{
+ if ($rd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") {
+ xlog("L_WARN", "$ci|end|dropping $rm request with IP domain\n");
+ drop();
+ exit();
+ }
+}
+
+route[FILTER_AUTHORIZATION_DOMAIN]
+{
+ if (is_present_hf("Proxy-Authorization") &&
+ $ar =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}" ) {
+ xlog("L_WARN", "$ci|end|dropping request with IP domain in Proxy-Authorization header\n");
+ drop();
+ exit;
+ }
+}
+
+route[FILTER_FROM_DOMAIN]
+{
+ if ($fd =~ "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})") {
+ xlog("L_WARN", "$ci|end|dropping request with IP domain in From header\n");
+ drop();
+ exit;
+ }
+}
+
+route[FILTER_TO_DOMAIN]
+{
+ if ($td =~ "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})") {
+ xlog("L_WARN", "$ci|end|dropping request with IP domain in To header\n");
+ drop();
+ exit;
+ }
+}
+
diff --git a/kamailio-proxy-proxy/websockets-role.cfg b/kamailio-proxy-proxy/websockets-role.cfg
new file mode 100644
index 0000000..53c9c8d
--- /dev/null
+++ b/kamailio-proxy-proxy/websockets-role.cfg
@@ -0,0 +1,147 @@
+tcp_accept_no_cl=yes
+
+listen=TCP_WS
+#!ifdef TLS_ROLE
+listen=TLS_WSS
+#!endif
+
+######## NAT Traversal module - signaling functions ########
+#!ifndef NATHELPER_LOADED
+#!trydef NATHELPER_LOADED
+loadmodule "nathelper.so"
+#!endif
+
+######## Generic Hash Table container in shared memory ########
+modparam("htable", "htable", "websockets=>size=16;initval=0")
+
+######## Basic HTTP request handling ########
+loadmodule "xhttp.so"
+
+
+#!trydef WS_KEEPALIVE_MECHANISM 3
+#!trydef WS_KEEPALIVE_TIMEOUT 30
+#!trydef WS_KEEPALIVE_PROCESSES 3
+#!trydef WS_KEEPALIVE_INTERVAL 1
+#!trydef WS_KEEPALIVE_DATA "Kazoo encourages you to keep alive"
+#!trydef WS_MAX_CONNECTIONS_PER_IP 50
+#!trydef WS_MAX_CONNECTIONS_PER_PROXY 0
+#!trydef WS_ALLOWED_PROXIES "0.0.0.0/0"
+#!trydef WS_CONNECTIONS_FROM_PROXY_ONLY 0
+
+######## Websocket module ########
+loadmodule "websocket.so"
+modparam("websocket", "keepalive_mechanism", WS_KEEPALIVE_MECHANISM)
+modparam("websocket", "keepalive_timeout", WS_KEEPALIVE_TIMEOUT)
+modparam("websocket", "keepalive_processes", WS_KEEPALIVE_PROCESSES)
+modparam("websocket", "keepalive_interval", WS_KEEPALIVE_INTERVAL)
+modparam("websocket", "ping_application_data", WS_KEEPALIVE_DATA)
+modparam("websocket", "sub_protocols", 1)
+
+####### Websocket Logic ########
+
+kazoo.ws_allowed_proxies = WS_ALLOWED_PROXIES desc "comma separated list of allowed proxies in cidr notation"
+kazoo.ws_max_connection_per_ip = WS_MAX_CONNECTIONS_PER_IP desc "max connections per ip"
+kazoo.ws_max_connection_per_proxy = WS_MAX_CONNECTIONS_PER_PROXY desc "max connections per proxy"
+kazoo.ws_connections_via_proxy_only = WS_CONNECTIONS_FROM_PROXY_ONLY desc "only allow connections via proxy"
+
+event_route[xhttp:request]
+{
+ set_reply_close();
+ set_reply_no_connect();
+
+ if (!($rm =~ "GET")) {
+ xlog("L_INFO", "websocket|log|rejecting HTTP request $rm from $si:$sp\n");
+ xhttp_reply("405", "Method Not Allowed", "", "");
+ exit;
+ }
+
+ if (!($hdr(Connection) =~ "Upgrade")) {
+ xlog("L_INFO", "websocket|log|rejecting HTTP connection $hdr(Connection) request from $si:$sp\n");
+ xhttp_reply("400", "Bad Request", "", "");
+ exit;
+ }
+
+ if (!($hdr(Upgrade) =~ "websocket")) {
+ xlog("L_INFO", "websocket|log|rejecting HTTP upgrade $hdr(Upgrade) request from $si:$sp\n");
+ xhttp_reply("400", "Bad Request", "", "");
+ exit;
+ }
+
+ if (!($hdr(Sec-WebSocket-Protocol) =~ "sip")) {
+ xlog("L_INFO", "websocket|log|rejecting request for websocket protocol $hdr(Sec-WebSocket-Protocol) from $si:$sp\n");
+ xhttp_reply("400", "Bad Request", "", "");
+ exit;
+ }
+
+ #!ifdef MY_WEBSOCKET_DOMAIN
+ if (!($hdr(Origin) =~ "MY_WEBSOCKET_DOMAIN")) {
+ xlog("L_INFO", "websocket|log|rejecting HTTP request with unauthorized origin $hdr(Origin) from $si:$sp, allowed origin is MY_WEBSOCKET_DOMAIN\n");
+ xhttp_reply("400", "Bad Request", "", "");
+ exit;
+ }
+ #!endif
+
+ if ($hdr(X-Forwarded-For) == $null) {
+ if($sel(cfg_get.kazoo.ws_connections_via_proxy_only) == 1) {
+ xlog("L_INFO", "websocket|log|request from $si without X-Forwarded-For Header and only allowed connections are via proxy\n");
+ xhttp_reply("403", "Forbidden", "", "");
+ exit;
+ } else {
+ $var(ws_orig_ip) = $si;
+ }
+ } else {
+ xlog("L_INFO", "websocket|log|request X-Forwarded-For $hdr(X-Forwarded-For) from $si\n");
+ $var(ws_orig_ip) = $hdr(X-Forwarded-For);
+ }
+
+ if($si != $var(ws_orig_ip)) {
+ if(!is_in_subnet($si, $sel(cfg_get.kazoo.ws_allowed_proxies))) {
+ xlog("L_WARNING", "websocket|log|request X-Forwarded-For $hdr(X-Forwarded-For) from invalid ip $si - allowed $sel(cfg_get.kazoo.ws_allowed_proxies)\n");
+ xhttp_reply("403", "Forbidden", "", "");
+ exit;
+ }
+
+ if($sel(cfg_get.kazoo.ws_max_connection_per_proxy) > 0 && $sht(websockets=>$si::count) > $sel(cfg_get.kazoo.ws_max_connection_per_proxy)) {
+ xlog("L_WARN", "websocket|log|$si is at the maximum $sel(cfg_get.kazoo.ws_max_connection_per_proxy) allowable sockets per PROXY IP, rejecting request for another websocket\n");
+ xhttp_reply("403", "Forbidden", "", "");
+ exit;
+ }
+ }
+
+ if($sel(cfg_get.kazoo.ws_max_connection_per_ip) > 0 && $sht(websockets=>$var(ws_orig_ip)::count) > $sel(cfg_get.kazoo.ws_max_connection_per_ip)) {
+ xlog("L_WARN", "websocket|log|$var(ws_orig_ip) is at the maximum $sel(cfg_get.kazoo.ws_max_connection_per_ip) allowable sockets per IP, rejecting request for another websocket\n");
+ xhttp_reply("403", "Forbidden", "", "");
+ exit;
+ }
+
+ if (ws_handle_handshake()) {
+ $var(count) = $shtinc(websockets=>$var(ws_orig_ip)::count);
+ $sht(websockets=>$ws_conid::ws_orig_ip) = $var(ws_orig_ip);
+ if($si != $var(ws_orig_ip)) {
+ $var(proxy_count) = $shtinc(websockets=>$si::count);
+ xlog("L_INFO", "websocket|log|opened proxied websocket $ws_conid from $si for $var(ws_orig_ip):$sp\n");
+ } else {
+ xlog("L_INFO", "websocket|log|opened websocket $ws_conid from $var(ws_orig_ip):$sp\n");
+ }
+ exit;
+ }
+
+ xlog("L_INFO", "websocket|log|unhandled HTTP request $rm from $si:$sp\n");
+ xhttp_reply("404", "Not Found", "", "");
+}
+
+event_route[websocket:closed]
+{
+ $var(ws_orig_ip) = $sht(websockets=>$ws_conid::ws_orig_ip);
+ $sht(websockets=>$ws_conid::ws_orig_ip) = $null;
+
+ $var(count) = $shtdec(websockets=>$si::count);
+ if($var(ws_orig_ip) != $null && $si != $var(ws_orig_ip)) {
+ $var(countip) = $shtdec(websockets=>$var(ws_orig_ip)::count);
+ xlog("L_INFO", "websocket|log|$si closed proxied websocket $ws_conid for $var(ws_orig_ip):$sp\n");
+ if ($var(countip) < 1) $sht(websockets=>$var(ws_orig_ip)::count) = $null;
+ } else {
+ xlog("L_INFO", "websocket|log|closed websocket $ws_conid from $var(ws_orig_ip):$sp\n");
+ }
+ if ($var(count) < 1) $sht(websockets=>$si::count) = $null;
+}