Compare commits

...

284 Commits

Author SHA1 Message Date
  kageds 7599b72720
Merge pull request #2 from itlevel3/patch-3 5 years ago
  Amit Nir 5c095734fb
Update POSTGRES.md 5 years ago
  Alan R Evans 0fc8a646a5 add MY_AMQP_ZONE to cfg 5 years ago
  Alan R Evans 581e879ae7 disable registrar_check_amqp_availability because it fails with error : “no amqp connection available for default worker in zone local” 5 years ago
  Alan R Evans e8d4fc4570 Merge branch '4.3-postgres' of https://github.com/kageds/kazoo-configs-kamailio into 4.3-postgres 5 years ago
  Alan R Evans da25a960b8 add patching kazoo.so 5 years ago
  Alan R Evans cffab48ff9 include kazoo.so until kamailio accepts the PR https://github.com/kamailio/kamailio/pull/2786 5 years ago
  kageds de92b0865c
Merge pull request #1 from itlevel3/patch-2 5 years ago
  Amit Nir 2f28c2fe19
Update POSTGRES.md 5 years ago
  Alan R Evans 89aad8247a increase the max number of connections 5 years ago
  Alan R Evans 593dc13588 add config file location 5 years ago
  Alan R Evans 3fccd80968 add support for postgres backend 5 years ago
  Luis Azedo 3020352097 add dispatcher support for kamailio 5.4 5 years ago
  lazedo 0bbd30790f check for media servers reconnection 5 years ago
  lazedo 30c054bf82 configurable 480 reply from media with session in progress 6 years ago
  Daniel Finke 55b0bf5715 [4.3] Don't overwrite tcp_children for local listener 6 years ago
  lazedo 001f55c6b2 override 480 if call is progress 6 years ago
  lazedo 03a23947d5 fix the check for content-type 6 years ago
  lazedo a2933334ca use descending order to remove preferred route from list 6 years ago
  lazedo f9bfa52a94 use redirect for challenged invites by media servers 6 years ago
  lazedo e9358c6299 support custom dispatcher roles 6 years ago
  Karl Anderson 97d58cd846 cleanup unused redirect logic 6 years ago
  lazedo 6255c37cfe
simplify internal redirects - 4.3 (#127) 6 years ago
  lazedo 796da4e7df sync with kazoo im services 6 years ago
  lazedo ee0b627d8a allow disable of detection mechanism 6 years ago
  lazedo 87e8b4148e bring kazoo-kamailio from master 6 years ago
  lazedo 3fbf6d5ef2 xavp_rm not available until 5.3 6 years ago
  lazedo ac884d8194 remove double auth 6 years ago
  lazedo c8937f7505 process auth for REFER 6 years ago
  lazedo 9ce20f996e add "pass" log to early return 6 years ago
  lazedo 71944ae7b6 early return for in-dialog transactions 6 years ago
  lazedo 5dc142ebc4 order of x-headers 6 years ago
  lazedo 63fec8098a only add x-headers for INVITE|MESSAGE|REFER 6 years ago
  lazedo ae0dbf1ddd add cflags from contact to branch flags 6 years ago
  lazedo 5c91549b6c add NOTIFY for branch_route 6 years ago
  lazedo ae5d0f28d9 allow Token-Proxy override 6 years ago
  lazedo d9a07156ec allow pusher to log contact 6 years ago
  lazedo fe2d40a81d pusher external fault fix 6 years ago
  lazedo 5f07e8c072 pusher nat handling 6 years ago
  lazedo c53a0bb908
allow text/html in message content-type 6 years ago
  lazedo 9c0d879ddd
fix from/to for inbound 6 years ago
  lazedo 3fab3b6fa8
set route-type to onnet 6 years ago
  lazedo cb65cf45e6
Update message-role.cfg 6 years ago
  lazedo 0a4bf7c9ba manage branch in redirect 6 years ago
  Sean Wysor 2c05c2aed3 Update .shipyard.yml 6 years ago
  Sean Wysor 30c9618355 Test dep changes (#117) 6 years ago
  lazedo aa1fec9dda
remove include in local 6 years ago
  Sean Wysor 5d7e1e109a
Update .shipyard.yml 6 years ago
  bitbashing a7e4f02422
Merge pull request #113 from 2600hz/circle-ci-builds-4.3 6 years ago
  Derek Miles 9318161f9e Increasing default EXTERNAL_TO_INTERNAL_NO_RESPONSE_TIMER and INTERNAL_TO_EXTERNAL_NO_RESPONSE_TIMER values to known working values pre any UDP buffer tuning 6 years ago
  swysor 69a7ac3472 removed swap file 6 years ago
  swysor 19d888aa0f updated 4.3 6 years ago
  swysor 0a4ee51a25 setup configs to build packages 6 years ago
  Karl Anderson d0e398bec3 registrar sync binding is using the old format and has a syntax error when enabled 6 years ago
  lazedo 1d0a40676b fix prefered_route check 6 years ago
  lazedo 9a8d560bea simplify next and prefered route 6 years ago
  lazedo 1fa6d4eec0 cleanup 6 years ago
  lazedo c358b42ceb update parking regexp 6 years ago
  lazedo a39b6c4bae add configurable NO_RESPONSE_TIMER 6 years ago
  lazedo d846a15632 support kamailio 5.1/5.2 6 years ago
  lazedo 47046f3435 change some defaults for better user experience 6 years ago
  bitbashing b2c18c86d9
Merge pull request #101 from 2600hz/trusted-4.3 6 years ago
  lazedo fee7835182 remove double escape from json 6 years ago
  lazedo dcb813d7f2 add macro for presence_use_full_entity 7 years ago
  lazedo 55c794c008 keep us in the loop for invite in-dialog requests 7 years ago
  lazedo 784cb70561 this is a targeted reply 7 years ago
  lazedo aabec7673e use sms exchange for delivery report 7 years ago
  lazedo 3e5b6dc898 add federation and simplify reply handling 7 years ago
  lazedo fe1e4d0ede fix spelling 7 years ago
  lazedo 5671d7893f use internal routing for messages 7 years ago
  Luis Azedo e2f19675c0 backport of #100 7 years ago
  bitbashing e03b1813d9
Merge pull request #92 from 2600hz/improvements-4.3 7 years ago
  lazedo 3fba5c0dc7 update presence handling 7 years ago
  lazedo 678cd54505 handle state for presence event 7 years ago
  lazedo 91d3d6f86b change column order to use indexes 7 years ago
  lazedo 637ce55531 use column 7 7 years ago
  lazedo 7e8f70042c check if result of iproute is ip address 7 years ago
  lazedo 772067a794 formatting 7 years ago
  lazedo 8ae0296fff websockets defaults 7 years ago
  lazedo 26cbbfec13 add REFER handling 7 years ago
  lazedo c0cc9501a7 change reparse_on_dns_failover default on tm module 7 years ago
  lazedo 63a2d3a6a3 add X-AUTH-Token from CCVs 7 years ago
  lazedo 23eda1c9fa check event_list diff 7 years ago
  lazedo 6b66c1d1f4 fix antiflood rate log 7 years ago
  lazedo 00bc4a86b4 blocker is a role, no needed for define 7 years ago
  lazedo f7d89cd7bd allow trace failed sanity requests 7 years ago
  lazedo 4eb1dc0758 move sanity script 7 years ago
  lazedo 4ef8835ce1 less restrictive auth 7 years ago
  lazedo fcc2d0904a call status req 7 years ago
  lazedo 58148319ae add Hotdesk-Current-ID and format 7 years ago
  lazedo a7a14f5ddc move block as role, rename keepalive script 7 years ago
  lazedo af4382edc3 move keepalive to a new experimental role 7 years ago
  lazedo 9649e7e978 add ruid to w_location_contact view 7 years ago
  lazedo 2eadcd4bef don't delete registrations on startup 7 years ago
  lazedo 0bc353e552 macros for db_kazoo 7 years ago
  lazedo eb2ce85893 change notify timer interval 7 years ago
  lazedo 172a130fb1 add presence_with_targets_log_level 7 years ago
  lazedo 4261e277e3 add registrar perm error condition & macros & defaults 7 years ago
  lazedo f9235cdd1d add stats to keepalive & change some defaults 7 years ago
  lazedo 241ca7c0d9 add statistics module 7 years ago
  lazedo 7b434329dc registrar stats & cache authn_err 7 years ago
  lazedo a8899cd1fc db changes 7 years ago
  lazedo 490a5be8d2 remove include file 7 years ago
  lazedo 9ae2ed21c3 db module macro 7 years ago
  lazedo 235a4bb8b5 add a block component 7 years ago
  lazedo 21ed266153 move kazoo param to kazoo-bindings & allow db module configuration 7 years ago
  lazedo b435966eda macro/runtime for keepalive failed loglevel 7 years ago
  lazedo f33753d5bc macros/runtime for max notify error and loglevel 7 years ago
  lazedo 5d67f349bd schema update 7 years ago
  lazedo 411634b954 allow options to be loaded from kazoo-kamailio folder 7 years ago
  lazedo a3e967e08a RESET_NON_UDP_ENABLED from env 7 years ago
  lazedo 73d945c4fd runtime for failed threshold 7 years ago
  lazedo 83e89bd837 update keepalive 7 years ago
  lazedo cebd0b11d6 update db schema & views 7 years ago
  lazedo 7195128c9c reset only local options 7 years ago
  lazedo 1733cfef26 don't advertise 127.0.0.1 7 years ago
  lazedo 382f8521d0 add a lock for db ops since we have several workers 7 years ago
  lazedo 4dd00f1612 escape account name 7 years ago
  lazedo 1c5258746d cfgutils lock_set_size param 7 years ago
  lazedo 7e4472f124 add REGISTRAR_DB_REMOVE_EXPIRED_DELAY macro 7 years ago
  lazedo f1acc8fcae disable keepalive for clients that send OPTIONS/NOTIFY 7 years ago
  lazedo 15cab44061 allow runtime configuration of keepalive timeout 7 years ago
  lazedo 50d014a43c handle deregistrations in keepalive 7 years ago
  lazedo dca4afcd79 keepalive defaults 7 years ago
  lazedo d849e98d6a fix table name 7 years ago
  lazedo 40c7de246d remove unused code 7 years ago
  lazedo c6f981a5d4 use db_mode 3 by default on registrar 7 years ago
  lazedo 1a82cb2fa9 add KEEPALIVE_ON_EXPIRED_REGISTRATION 7 years ago
  lazedo f121b5134b comment udp checks 7 years ago
  lazedo dc51608ee4 keepalive cleanup 7 years ago
  lazedo 5758f8c6d3 add keepalive 7 years ago
  lazedo 99f9e80771 option & notify early exit 7 years ago
  lazedo 75acf0ee26 add versions to kazoo specific tables 7 years ago
  lazedo f7f7e3fca3 defaults for nat ping timeout and timer interval 7 years ago
  lazedo e9eb219a92 some tweaks 7 years ago
  lazedo dad34428b7 nat with loop 7 years ago
  lazedo 6857b35c4d apply db diff with primary key 7 years ago
  lazedo 4cad20d6d4 presence nat 7 years ago
  lazedo 1e47348c43 remove watchers on registration expiration 7 years ago
  lazedo ab753be089 log transaction id in registrar 7 years ago
  lazedo 420a4281e6 avoid duplicated pings 7 years ago
  lazedo c6ad6dbb8c macros for tcp parameters 7 years ago
  lazedo ff7874141d add db_url to htable for registrar warm cache 7 years ago
  lazedo 2997c5191c include all sql files from shared dir 7 years ago
  lazedo 9d9fd35023 log contact expiration 7 years ago
  lazedo ae3fc615a4 registrar warm cache 7 years ago
  lazedo 5b47d34d4d websocket with proxy only connections 7 years ago
  lazedo 45e8d5638c reply logs 7 years ago
  lazedo 1a2a6bdeb3 log call-id for park redirect 7 years ago
  lazedo 429a42a6b3 allow exchage configuration for registrar 7 years ago
  lazedo 80f1f1b42d granular reply configuration for presence query 7 years ago
  lazedo 5a2fffaf2b remove dlg from auth 7 years ago
  lazedo a7c27fea0c presence notify logging 7 years ago
  lazedo 34bcc3520c fix relay in dispatcher 7 years ago
  lazedo 1e726da37e setup route & auth 7 years ago
  lazedo 1bddebc043 move auth headers to own file 7 years ago
  lazedo c33bd1cfda nat keepalive options 7 years ago
  lazedo 4c4c07fb6e add empty line for better viewing 7 years ago
  lazedo 23cf96c6aa define L_DEBUG 7 years ago
  lazedo bfec04f8c3 antiflood def moved 7 years ago
  lazedo bb836ad243 tls mod_level and low_mem 7 years ago
  lazedo b4d224e1fd websocker origin_ip 7 years ago
  lazedo 2ecbeda741 allow not logging OPTIONS 7 years ago
  lazedo ec6c9d138b route ANTIFLOOD_LIMIT 7 years ago
  lazedo 1babdafb0d move debugger so other cfg files can declare mod_level 7 years ago
  lazedo a41c15b603 antiflood macros & auth by port 7 years ago
  lazedo 4fa36f07fb move sanity to own cfg file 7 years ago
  lazedo 15a68cbbe2 remove quotes from ips 7 years ago
  lazedo 65e135d00b update ws connection count for proxied connections 7 years ago
  lazedo fd45db66ca change default number of buffer slots 7 years ago
  lazedo 0526ce2f91 registrar nat msg log level 7 years ago
  lazedo 5daf2d9b54 websocket logs and macros 7 years ago
  lazedo 628f661859 more nat related changes 7 years ago
  lazedo d86cca4365 add REGISTRAR_NAT_PING_NAT_ONLY macro and default to 0 7 years ago
  lazedo 2a01496f96 add NAT_SDP route 7 years ago
  lazedo ee94e095c0 fix nat sdp handling 7 years ago
  lazedo 21db836948 16kb default for buffer size 7 years ago
  lazedo 104ac3303e buffer size & slots 7 years ago
  lazedo 5c0df888b2 move AOR back to default 7 years ago
  lazedo 32450fa1b0 allow check for media internal sip addresses 7 years ago
  lazedo 4dab51ee41 optional REGISTRAR_CHECK_AMQP_AVAILABILITY 7 years ago
  lazedo 2a32c9c663 defaults for ip address 7 years ago
  lazedo 4d784e26be add missing defaults 7 years ago
  lazedo 9182cc50cd handle directory flush with cache-only 7 years ago
  lazedo 8ca0cd31f0 missing deltas in mwi / presence 7 years ago
  lazedo 42dce54dd4 log levels for dispatcher 7 years ago
  lazedo ab5c9c69a2 fix log message for min-expires in registrar 7 years ago
  lazedo d13e410d67 change log level in nodes 7 years ago
  lazedo 40a14584f8 allow override of missing expires on REGISTER 7 years ago
  lazedo 0f35dc46b0 change var for logging, fix msg & missing test 7 years ago
  lazedo 20b51d1ff6 less noise in logs unless we want 7 years ago
  lazedo e4b9325583 restrict ack's that need tracing 7 years ago
  lazedo 272409e196 Revert "add option to run (prepare/start)" 7 years ago
  lazedo 742ff3ea17 check database on creation 7 years ago
  lazedo d42460ffcb fix sip trace ack 7 years ago
  lazedo f0de0c7596 add option to run (prepare/start) 7 years ago
  lazedo 03a5c57a6b handle sip trace from one place 7 years ago
  lazedo 013da14864 remove default for amqp 7 years ago
  lazedo 6ba389fcea start moving role specific definitions 7 years ago
  lazedo ee35f2f129 use more meaningful method 7 years ago
  lazedo f672b8926b substdefs for listeners need the IP_ADDRESS resolved 7 years ago
  lazedo 5c3a592c4d origin restriction by default 7 years ago
  lazedo b4b9b670eb more defaults and squashed fast pickup into presence 7 years ago
  lazedo cff16eb6c6 better defaults for ip and hostname 7 years ago
  lazedo 53900274eb remove trailing white spaces 7 years ago
  lazedo c25515bed5 change log level to show by zone 7 years ago
  lazedo fd90d9df19 more bindings and logs 7 years ago
  lazedo 48ba777d00 move search & reset to api 7 years ago
  lazedo a21c799de2 update amqp logging 7 years ago
  lazedo 4c9afb9c94 name the bindings 7 years ago
  lazedo 07de9ebac4 remove FLT_AOR check 7 years ago
  lazedo d58d9481af duplicate definition of FLB_NATB 7 years ago
  lazedo 4014155c1f handle in dialog requests for nat 7 years ago
  lazedo dafab4644d set KZ_NAT_FIX_SDP_REPLY default to 0 7 years ago
  lazedo 88b8e0199e log local generated requests 7 years ago
  lazedo cb5cb9b7ff rework nat 7 years ago
  lazedo f5bb8319ba redefine flags 7 years ago
  lazedo 7d7516b666 indentation 7 years ago
  lazedo 419bed5d83 rework nat with set_contact_alias/handle_ruri_alias 7 years ago
  lazedo 6a0087277b flag AOR usage and move route to registrar-role 7 years ago
  lazedo 1996b28b8b initialize debug settings with macro 7 years ago
  lazedo 88aef4191c flag T38 requests 7 years ago
  lazedo 4bae98240e add some flags 7 years ago
  lazedo ea7712425c memlog must be lower than debug 7 years ago
  lazedo b71fcb0ba9 decouple nat port/contact tests 7 years ago
  lazedo 8ab98e235b add delta logging to registrar 7 years ago
  lazedo df8b23a32c fix log line 7 years ago
  lazedo 5a625d0217 allow tracking all presence packages 7 years ago
  lazedo c4c62c19ed simpler log line 7 years ago
  lazedo 5d56b6eb72 do not try to resize if it doesn't fit 7 years ago
  lazedo 4acd6a26bb presence detail should query based on active watchers 7 years ago
  lazedo 419a670e54 rework presence cleanup 7 years ago
  lazedo 5e4615e173 fix log message for reset zone 7 years ago
  lazedo 02125e77a6 add index to dispatcher 7 years ago
  lazedo 29b6983db5 handle the case where listener is not available for a zone 7 years ago
  lazedo 0d5b9b89b7 less noise in logs 7 years ago
  lazedo 928755686d change default due to loopback channels 7 years ago
  lazedo 6f6e403401 update count and cleanup queries 7 years ago
  lazedo 761a085cb2 allow opt-out str 5 processing andalso change at runtime 7 years ago
  lazedo 1275e9cfd7 remove sanity htable counter 7 years ago
  lazedo c4aa9e0516 remove uac params 7 years ago
  lazedo 646e2e86ab remove 302 condition 7 years ago
  lazedo 93c798b4d2 revert dns enablement 7 years ago
  lazedo 1983d7a458 change log level for publisher cleanup 7 years ago
  lazedo 6ea09368d4 presence reset updates 7 years ago
  lazedo f08248d30e join the event too 7 years ago
  lazedo e4c0a9435a track media instance-id 7 years ago
  lazedo 58a4390cd5 !trydefs for dispatcher groups and runtime selection 7 years ago
  lazedo b8aad0bf3a add extra sets for dispatcher classify 7 years ago
  lazedo 022c0dd8b0 expires in location table is timestamp 7 years ago
  lazedo 4cea7663d6 count distinct callid for presentity count 7 years ago
  lazedo 94c4f74b2d move cseq to trydef 7 years ago
  lazedo e147eae4be increase cseq_offset 7 years ago
  lazedo 968773a653 add runtime variable to force kazoo query on register 7 years ago
  lazedo ce04932247 set log level to notice in core 7 years ago
  lazedo dd9b7133e9 use kamcmd to stop kamailio 7 years ago
  lazedo b8b915eaef mhomed as a #!trydef 7 years ago
  lazedo 05e93bb8cd indentation & remove rr in handle_in_dialog, settings for rr 7 years ago
  lazedo 29831aee90 use proper variable for resetting associations 7 years ago
  lazedo 08c9548a32 check ramdisk size and ensure minimum free space 7 years ago
  lazedo cda63e4ab9 remove stale indication on challenge 7 years ago
  lazedo fa80fef784 use evrexec for deferred init 7 years ago
  lazedo 8349bd727e move rtimer load to default 7 years ago
  lazedo aabcf4a7fb simplify init deferred 7 years ago
  lazedo b249ca299f trydefs 7 years ago
  lazedo 7d1af72c07 use $sel for selectors 7 years ago
  lazedo d5a1f82fd9 remove commented code 7 years ago
  lazedo 5d3f9dfc0d deferred reload for dispatcher 7 years ago
  lazedo 378af34ecd allow extensibility on custom init 7 years ago
  lazedo cdc8bd9b7c remove commented lines 7 years ago
  lazedo e708a00460 HELP-40268 impose a maximum calls per presentity 7 years ago
  lazedo 70e7aef558 allow db downgrade 7 years ago
  lazedo 17092c0bf4 when querying kazoo channels for parking, use *3 so that it handles *5 7 years ago
  lazedo 6bfc74d65c mount & umount review 7 years ago
  lazedo 12eb4bf819 distraction 7 years ago
  lazedo 6c3f23da02 fix comparison & return from ram_disk_enabled 7 years ago
  lazedo 67c96e7009 keep current behaviour 7 years ago
  lazedo be2cdba506 missing files 7 years ago
  lazedo 5437a8e86d fast pickup for *5, looks into *3 7 years ago
  lazedo 7703c1ede3 WIP 7 years ago
  lazedo 14b5b3e702 ignore online/offline probe 7 years ago
  Daniel Finke da7a5a99f5 Add KZQ_HAS_PRESENTITY to db_queries_mysql 7 years ago
  lazedo e113303e9c fix sip trace config initialization 7 years ago
  lazedo e583749e74
add db param to KazooDB 7 years ago
57 changed files with 10766 additions and 1740 deletions
Split View
  1. +84
    -0
      .circleci/config.yml
  2. +86
    -0
      .shipyard.yml
  3. +115
    -0
      POSTGRES.md
  4. +3
    -4
      kamailio/accounting-role.cfg
  5. +6
    -0
      kamailio/acl-role.cfg
  6. +72
    -22
      kamailio/antiflood-role.cfg
  7. +130
    -0
      kamailio/auth.cfg
  8. +23
    -0
      kamailio/authorization-role.cfg
  9. +39
    -0
      kamailio/blocker-role.cfg
  10. +14
    -0
      kamailio/db_kazoo.cfg
  11. +4
    -0
      kamailio/db_mysql.cfg
  12. +4
    -0
      kamailio/db_postgres.cfg
  13. +27
    -9
      kamailio/db_queries_kazoo.cfg
  14. +1
    -0
      kamailio/db_queries_mysql.cfg
  15. +9
    -0
      kamailio/db_queries_postgres.cfg
  16. +46
    -0
      kamailio/db_scripts/check-kazoodb-sql.sh
  17. +4
    -99
      kamailio/db_scripts/create-kazoodb-sql.sh
  18. +34
    -0
      kamailio/db_scripts/db_extra_check.sql
  19. +14
    -0
      kamailio/db_scripts/db_init_watcher_triggers.sql
  20. +106
    -3
      kamailio/db_scripts/db_kazoo-specific
  21. +5811
    -0
      kamailio/db_scripts/kamailio_initdb_postgres.sql
  22. +56
    -0
      kamailio/db_scripts/kazoodb-sql.sh
  23. +20
    -0
      kamailio/db_scripts/vw_presentities.sql
  24. +6
    -0
      kamailio/db_scripts/vw_w_keepalive_contact.sql
  25. +6
    -0
      kamailio/db_scripts/vw_w_location_contact.sql
  26. +6
    -0
      kamailio/db_scripts/vw_w_watchers_contact.sql
  27. +6
    -0
      kamailio/db_scripts/vw_wdispatcher.sql
  28. +440
    -411
      kamailio/default.cfg
  29. +88
    -0
      kamailio/defs-amqp.cfg
  30. +50
    -91
      kamailio/defs.cfg
  31. +306
    -0
      kamailio/dispatcher-role-5.1.cfg
  32. +309
    -0
      kamailio/dispatcher-role-5.2.cfg
  33. +309
    -0
      kamailio/dispatcher-role-5.4.cfg
  34. +309
    -0
      kamailio/dispatcher-role-5.5.cfg
  35. +0
    -264
      kamailio/dispatcher-role.cfg
  36. +17
    -3
      kamailio/kamailio.cfg
  37. +113
    -19
      kamailio/kazoo-bindings.cfg
  38. +343
    -0
      kamailio/keepalive-role.cfg
  39. +29
    -25
      kamailio/local.cfg
  40. +77
    -36
      kamailio/message-role.cfg
  41. +105
    -34
      kamailio/nat-traversal-role.cfg
  42. +86
    -38
      kamailio/nodes-role.cfg
  43. +65
    -27
      kamailio/presence-fast-pickup.cfg
  44. +213
    -0
      kamailio/presence-notify.cfg
  45. +24
    -23
      kamailio/presence-query.cfg
  46. +39
    -20
      kamailio/presence-reset.cfg
  47. +260
    -114
      kamailio/presence-role.cfg
  48. +0
    -117
      kamailio/presence_notify_sync-role.cfg
  49. +53
    -16
      kamailio/pusher-role.cfg
  50. +325
    -192
      kamailio/registrar-role.cfg
  51. +1
    -1
      kamailio/registrar-sync-role.cfg
  52. +67
    -0
      kamailio/sanity.cfg
  53. +49
    -12
      kamailio/sip_trace-role.cfg
  54. +5
    -1
      kamailio/tls-role.cfg
  55. +71
    -50
      kamailio/websockets-role.cfg
  56. BIN
      kazoo_module/kazoo.so
  57. +281
    -109
      system/sbin/kazoo-kamailio

+ 84
- 0
.circleci/config.yml View File

@ -0,0 +1,84 @@
version: 2
workflows:
version: 2
build_branch:
jobs:
- build_centos7
build_release:
jobs:
- build_centos7:
filters:
tags:
only: /^\d+\.\d+\.\d+$/
branches:
ignore: /.*/
jobs:
build_centos7:
docker:
- image: offical2600hz/metapackager:1.0-centos-7
user: circleci
shell: /bin/bash --login
working_directory: /home/circleci/2600hz/the_app
environment:
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
BASH_ENV: "/home/circleci/2600hz/.bashrc"
BUILD_ROOT: "/home/circleci/2600hz/packager"
CORE_ROOT: "/home/circleci/2600hz/the_app"
BUILD_SOURCES: "/home/circleci/2600hz/packager/SOURCES"
BUILD_RPMS: "/home/circleci/2600hz/packager/RPMS"
APP_DIR: "/home/circleci/2600hz/the_app"
steps:
- checkout
- run:
name: Setting up Directories
command: |
APP=${CIRCLE_PROJECT_REPONAME#meta-}
echo -e "export APP=${APP}\n" >> $BASH_ENV
- run:
name: Generating version info
command: |
cd $BUILD_ROOT
VERSION=$(./version)
RELEASE=$(./release)
PACKAGE_NAME=$(./package_name)
echo "export PACKAGE_NAME=${PACKAGE_NAME}" >> $BASH_ENV
echo "export VERSION=${VERSION}" >> $BASH_ENV
echo "export RELEASE=${RELEASE}" >> $BASH_ENV
PACKAGE_NAME=$(./package_name)
echo "export PACKAGE_NAME=${PACKAGE_NAME}" >> $BASH_ENV
echo "build version for ${PACKAGE_NAME} version: ${VERSION} release: ${RELEASE}"
- run:
name: Generating CHANGELOG and VERSION files
command: |
cd $BUILD_ROOT
echo " - generate build version and changelog"
./package_docs
- run:
name: Preparing source for packaging
command: |
echo " - preparing source"
cp -R ${APP_DIR}/* ${BUILD_SOURCES}/
cd $BUILD_SOURCES
echo " - removing files that should not be packaged in the source tar"
rm -rf ${BUILD_SOURCES}/.??*
rm -rf ${BUILD_SOURCES}/doc*
rm -rf ${BUILD_SOURCES}/*.md
echo " - creating the source tar"
cd $BUILD_ROOT
ARTIFACTS_NAME=${PACKAGE_NAME}-${VERSION}
mkdir -p ${ARTIFACTS_NAME}
cp -r ${BUILD_SOURCES}/* ${ARTIFACTS_NAME}/.
tar -cf ${ARTIFACTS_NAME}.tar ${ARTIFACTS_NAME}
cp ${ARTIFACTS_NAME}.tar ${BUILD_SOURCES}/.
- run:
name: Building package
command: |
cd $BUILD_ROOT
./build
- store_artifacts:
path: /home/circleci/2600hz/packager/RPMS

+ 86
- 0
.shipyard.yml View File

@ -0,0 +1,86 @@
name: kazoo-configs-kamailio
base_branch: origin/4.3
base_core: null
template: spec.tmpl
package:
centos7:
name: kazoo-configs-kamailio
group: Productivity/Telephony
license: MPL1.1
build_arch: noarch
build_requires:
- rpm-build
summary: Kazoo specific configuration for Kamailio
description: |
The Kazoo platform uses Kamailio to provide SIP services
as well as dispatch requests to FreeSWITCH. This package
is an elaborate Kamailio configuration based on 'roles' that
configure and perform these actions. If you need help you
can contact us via the dev mailing list or on IRC at #2600hz
on FreeNode.
dist: .el7.centos
requires:
sudo: {}
source: '%{_build_tar}'
prep: '%setup -q'
install: |
mkdir -p %{buildroot}/etc/kazoo
cp -r kamailio %{buildroot}/etc/kazoo
cp CHANGELOG VERSION %{buildroot}/etc/kazoo/kamailio
chmod +x %{buildroot}/etc/kazoo/kamailio/db_scripts/*.sh
find %{buildroot}/etc/kazoo/kamailio -type f > filelist.txt
sed -i 's#%{buildroot}##g' filelist.txt
to_replace="local.cfg tls.cfg"
for NOREPLACE in ${to_replace}
do
sed -i "s!/etc/kazoo/kamailio/$NOREPLACE!%config(noreplace) /etc/kazoo/kamailio/$NOREPLACE!g" filelist.txt
done
cat filelist.txt
mkdir -p %{buildroot}/usr/sbin
cp -r system/sbin/* %{buildroot}/usr/sbin
chmod +x %{buildroot}/usr/sbin/*
mkdir -p %{buildroot}/etc/rsyslog.d
rm -rf system/rsyslog.d/1-default-config-override.conf
rm -rf system/rsyslog.d/5-rate-limits.conf
cp -r system/rsyslog.d/*.conf %{buildroot}/etc/rsyslog.d
mkdir -p %{buildroot}/etc/logrotate.d
cp -r system/logrotate.d/*.conf %{buildroot}/etc/logrotate.d
mkdir -p %{buildroot}/etc/security/limits.d
cp -r system/security/limits.d/*.conf %{buildroot}/etc/security/limits.d
mkdir -p %{buildroot}/usr/lib/systemd/system
cp system/systemd/* %{buildroot}/usr/lib/systemd/system
files:
doc:
- CHANGELOG
- VERSION
list: filelist.txt
dir: /etc/kazoo/kamailio
config:
- mode: noreplace
path: /etc/rsyslog.d/*kamailio*
- mode: noreplace
path: /etc/logrotate.d/*kamailio*
- mode: noreplace
path: /etc/security/limits.d/*kamailio*
path:
- /usr/sbin/kazoo-kamailio
- /usr/lib/systemd/system/kazoo-kamailio.service
post: systemctl -q enable kazoo-kamailio.service
preun: '%{?systemd_preun kazoo-kamailio.service}'
postun: '%{?systemd_postun kazoo-kamailio.service}'
url: 'http://www.2600hz.org'
vendor: 2600Hz
metapackage:
-
name: meta-kazoo-kamailio
package: kazoo-configs-kamailio
type: required
branch: '4.3'

+ 115
- 0
POSTGRES.md View File

@ -0,0 +1,115 @@
## Notes on upgrading to Kamailio 5.5 and moving to Postgres backend.
Thus removing the dependency on KazooDB which is closed source.
First completely remove the current installation
```
Removing existing kazoo-kamailo:
yum remove kazoo-kamailio
yum remove kamailio
yum remove kazoo-configs-kamailio
rm -rf /etc/kazoo
```
Next install the lastest Kamailio (currently 5.5.0)
```
yum -y install yum-utils
yum-config-manager --add-repo https://rpm.kamailio.org/centos/kamailio.repo
yum install git kamailio kamailio-kazoo kamailio-outbound kamailio-presence kamailio-tls kamailio-utils kamailio-uuid kamailio-websocket kamailio-xmpp kamailio-postgresql
```
Now install latest postgres (currently 12.7)
```
# Install the repository RPM:
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-6-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo yum install -y postgresql12-server
/usr/pgsql-12/bin/postgresql-12-setup initdb
sudo chkconfig postgresql-12 on
sudo service postgresql-12 start
```
Create Kamailio DB
```
su - postgres -c '/usr/pgsql-12/bin/createdb kamailio'
```
Add DB user and grant privileges
```
sudo su - postgres -c psql
CREATE USER kamailio WITH PASSWORD 'kamailio';
GRANT ALL privileges on database kamailio to kamailio;
```
Modify default postgres authentication to allow kamailio access
```
vi /var/lib/pgsql/12/data/pg_hba.conf
# "local" is for Unix domain socket connections only
local all all password
# IPv4 local connections:
host all all 127.0.0.1/32 password
# IPv6 local connections:
host all all ::1/128 password
```
Increase the max number of connections and shared memory
```
vi /var/lib/pgsql/12/data/postgresql.conf
shared_buffers = 256MB
max_connections = 500
```
Restart postgres and check kamailio access to DB
```
systemctl restart postgresql-12
psql -U kamailio -d postgres://kamailio:kamailio@127.0.0.1/kamailio
```
Get the postgres kamailio configs:
```
git clone https://github.com/kageds/kazoo-configs-kamailio /etc/kazoo
cd /etc/kazoo/kamailio
git checkout 4.3-postgres
```
Initialize the kamailio database with all the required tables:
```
psql -U kamailio -d postgres://kamailio:kamailio@127.0.0.1/kamailio -f /etc/kazoo/kamailio/db_scripts/kamailio_initdb_postgres.sql
```
Notice that the backend DB in local.cfg is now postgres
```
#!trydef KZ_DB_MODULE postgres
#!substdef "!KAMAILIO_DBMS!postgres!g"
#!substdef "!KAZOO_DB_URL!postgres://kamailio:kamailio@127.0.0.1/kamailio!g"
```
Tell kamailio where the configuration files are
```
vi /etc/sysconfig/kamailio
#
# Kamailio startup options
#
# Amount of shared memory to allocate for the running Kamailio server (in Mb)
#SHM_MEMORY=64
# Amount of per-process (package) memory to allocate for Kamailio (in Mb)
#PKG_MEMORY=4
# Enable the server to leave a core file when it crashes.
# Set this to 'yes' to enable kamailio to leave a core file when it crashes
# or 'no' to disable this feature. This option is case sensitive and only
# accepts 'yes' and 'no' and only in lowercase letters.
# On some systems (e.g. Ubuntu 6.10, Debian 4.0) it is necessary to specify
# a directory for the core files to get a dump. Look into the kamailio
# init file for an example configuration.
DUMP_CORE=no
CFGFILE=/etc/kazoo/kamailio/kamailio.cfg
```
TEMP: Patch the kazoo module
[https://github.com/kamailio/kamailio/pull/2786]
```
cp /etc/kazoo/kazoo_module/kazoo.so /usr/lib64/kamailio/modules/kazoo.so
```
Start kamailio (NOT kazoo-kamailio)
```
systemctl enable kamailio
systemctl start kamailio
```

+ 3
- 4
kamailio/accounting-role.cfg View File

@ -1,8 +1,7 @@
####### Flags #######
flags
FLAG_ACC: 8,
FLAG_ACCMISSED: 9,
FLAG_ACCFAILED: 10;
#!trydef FLAG_ACC 13
#!trydef FLAG_ACCMISSED 14
#!trydef FLAG_ACCFAILED 15
######## Accounting module ########
loadmodule "acc.so"


+ 6
- 0
kamailio/acl-role.cfg View File

@ -265,3 +265,9 @@ event_route[kazoo:consumer-event-acl-acl-flush]
}
}
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)");
}

+ 72
- 22
kamailio/antiflood-role.cfg View File

@ -4,9 +4,17 @@
#!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_CACHE_PERIOD;initval=0")
modparam("htable", "htable", "antiflood=>size=16;autoexpire=ANTIFLOOD_SUBST_CACHE_PERIOD;initval=0")
######## Flood Prevention Module ########
loadmodule "pike.so"
@ -14,6 +22,21 @@ 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]
{
@ -25,13 +48,16 @@ route[ANTIFLOOD_RATE_LIMIT]
# use pike to control the rates
if (!pike_check_req()) {
xlog("L_WARN", "$ci|end|dropping request from $fu due to rate of requests with source $si:$sp\n");
drop();
exit;
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[ANITFLOOD_AUTH_LIMIT]
route[ANTIFLOOD_AUTH_LIMIT]
{
if (has_totag()
|| isflagset(FLAG_TRUSTED_SOURCE)
@ -39,21 +65,38 @@ route[ANITFLOOD_AUTH_LIMIT]
return(1);
}
if ($Au != $null &&
$sht(antiflood=>$Au::$si::count) >= ANTIFLOOD_FAILED_AUTH_DENSITY
$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
) {
xlog("L_NOTICE", "$ci|end|request at authorization failure limit for $Au $si:$sp\n");
$shtex(antiflood=>$Au::$si::count) = ANTIFLOOD_FAILED_AUTH_WINDOW;
$sht(antiflood=>$Au::$si::last) = $Ts;
append_to_reply("Retry-After: 3600\r\n");
send_reply("500", "Retry Later");
exit;
$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]
{
sht_rm_name_re("antiflood=>$(Au{re.subst,/\\./\\\\./g})::$(si{re.subst,/\\./\\\\./g})::.*");
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]
@ -68,23 +111,30 @@ route[ANITFLOOD_FAILED_AUTH]
return;
}
$var(count) = $shtinc(antiflood=>$Au::$si::count);
$sht(antiflood=>$Au::$si::last) = $Ts;
$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) {
if ($var(count) >= ANTIFLOOD_FAILED_AUTH_DENSITY) {
$var(exp) = $Ts - ANTIFLOOD_FAILED_AUTH_WINDOW;
if($sht(antiflood=>$Au::$si::last) > $var(exp)){
xlog("L_NOTICE", "$ci|end|request at authorization failure limit for $Au $si:$sp\n");
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("500", "Retry Later");
send_reply("403", "Forbidden");
exit;
}
}
}
}
event_route[htable:expired:antiflood]
event_route[htable:expired:antiflood]
{
xlog("L_NOTICE", "antiflood expired record $shtrecord(key) => $shtrecord(value)\n");
}

+ 130
- 0
kamailio/auth.cfg View File

@ -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

+ 23
- 0
kamailio/authorization-role.cfg View File

@ -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;
}
}

+ 39
- 0
kamailio/blocker-role.cfg View File

@ -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;
}
}
}
}

+ 14
- 0
kamailio/db_kazoo.cfg View File

@ -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"

+ 4
- 0
kamailio/db_mysql.cfg View File

@ -0,0 +1,4 @@
#### db_mysql module ###
loadmodule "db_mysql.so"
include_file "db_queries_mysql.cfg"

+ 4
- 0
kamailio/db_postgres.cfg View File

@ -0,0 +1,4 @@
#### db_postgres module ###
loadmodule "db_postgres.so"
include_file "db_queries_postgres.cfg"

+ 27
- 9
kamailio/db_queries_kazoo.cfg View File

@ -1,15 +1,33 @@
####### Database queries ########
#!substdef "!KZQ_CHECK_MEDIA_SERVER_INSERT!insert into dispatcher (setid, destination) select \$var(SetId), \"\$var(MediaUrl)\" where not exists(select * from dispatcher where destination = \"\$var(MediaUrl)\")!g"
#!substdef "!KZQ_COUNT_ALL_SUBSCRIBERS!select a.event, count(distinct watcher_username || \"@\" || watcher_domain) count_unique, count(*) count from event_list a, active_watchers b where b.event = a.event group by a.event!g"
#!substdef "!KZQ_CHECK_MEDIA_SERVER_INSERT!insert into dispatcher (setid, destination, flags, attrs, description) select \$var(SetId), \"\$var(MediaUrl)\", \$var(flags), \"\$var(attrs)\", \"added by nodes role\" where not exists(select * from dispatcher where destination = \"\$var(MediaUrl)\")!g"
#!substdef "!KZQ_COUNT_ALL_SUBSCRIBERS!select a.event, count(distinct watcher_uri) count_unique, count(*) count from event_list a left outer join active_watchers b on a.event = b.event group by a.event!g"
#!substdef "!KZQ_COUNT_PRESENTITIES!select event, (select count(*) from presentity b where username = \"\$(var(payload){kz.json,From}{uri.user})\" and domain = \"\$(var(payload){kz.json,From}{uri.domain})\" and b.event = a.event) count from event_list a!g"
#!substdef "!KZQ_COUNT_SUBSCRIBERS!select event, (select count(*) from active_watchers b where presentity_uri = \"\$var(presentity)\" and b.event = a.event) count from event_list a!g"
#!substdef "!KZQ_COUNT_SUBSCRIBERS!select event, (select count(*) from active_watchers b where presentity_uri = \"\$var(presentity)\" and b.event = a.event) count from event_list a union all select \"self\", count(distinct callid) from presentities where presentity_uri = \"\$var(presentity)\" and callid <> \"\$var(callid)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g"
#!substdef "!KZQ_EVENT_PRESENCE_RESET_DELETE!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\" and username = \"\$(kzE{kz.json,Username})\"!g"
#!substdef "!KZQ_HANDLE_NEW_SUBSCRIBE_DELETE1!delete from active_watchers where callid = \"\$ci\"!g"
#!substdef "!KZQ_HANDLE_NEW_SUBSCRIBE_DELETE2!delete from active_watchers where watcher_username=\"\$fU\" and presentity_uri=\"\$var(presentity_uri)\" and to_user=\"\$tU\" and watcher_domain=\"\$fd\" and event=\"\$hdr(Event)\"!g"
#!substdef "!KZQ_RESET_ACCOUNT_DELETE!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\"!g"
#!substdef "!KZQ_RESET_ACCOUNT_UPDATE!update active_watchers set expires = \$TS where watcher_domain=\"\$(kzE{kz.json,Realm})\"!g"
#!substdef "!KZQ_RESET_PUBLISHER_UPDATE!update active_watchers set expires = \$TS where id in (select b.id from presentity a inner join active_watchers b on a.username = b.to_user and a.domain = b.to_domain and a.event = b.event where a.sender = \"\$var(MediaUrl)\")!g"
#!substdef "!KZQ_PRESENCE_SEARCH_DETAIL!select * from active_watchers_log where presentity_uri = \"\$var(presentity_uri)\"!g"
#!substdef "!KZQ_PRESENCE_SEARCH_SUMMARY!select * from active_watchers where watcher_domain = \"\$var(Domain)\"!g"
#!substdef "!KZQ_HANDLE_NEW_SUBSCRIBE_DELETE2!delete from active_watchers where presentity_uri=\"\$var(presentity_uri)\" and event=\"\$hdr(Event)\" and watcher_username=\"\$fU\" and to_user=\"\$tU\" and watcher_domain=\"\$fd\"!g"
#!substdef "!KZQ_PRESENCE_SEARCH_SUMMARY!select * from active_watchers where to_domain = \"\$var(Domain)\"!g"
#!substdef "!KZQ_PRESENCE_SEARCH_DETAIL!select a.*, b.time, b.result, b.sent_msg, b.received_msg from active_watchers a left outer join active_watchers_log b on a.presentity_uri = b.presentity_uri and a.event = b.event and a.callid = b.callid where a.presentity_uri = \"\$var(presentity_uri)\" !g"
#!substdef "!KZQ_HAS_PRESENTITY!select count(*) as count from presentity where username = \"\$subs(to_user)\" and domain = \"\$subs(to_domain)\" and event = \"\$subs(event)\"!g"
#!substdef "!KZQ_REPLACE_WATCHERS_LOG!REPLACE INTO active_watchers_log (presentity_uri, watcher_username, watcher_domain, event, callid, to_user, to_domain, user_agent, time, result, sent_msg, received_msg) VALUES (\"\$subs(uri)\", \"\$subs(watcher_username)\", \"\$subs(watcher_domain)\", \"\$subs(event)\",\"\$subs(callid)\",\"\$subs(to_user)\",\"\$subs(to_domain)\", '\$(subs(user_agent){s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})', \$TS, \$notify_reply(\$rs), '\$(mb{s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})', '\$(notify_reply(\$mb){s.escape.common}{s.replace,\\\',''}{s.replace,\$\$,})')!g"
# # #!substdef "!KZQ_RESET_PUBLISHER_UPDATE!update active_watchers set expires = \$TS where id in (select b.id from presentity a inner join active_watchers b on a.username = b.to_user and a.domain = b.to_domain and a.event = b.event where a.sender = \"\$var(MediaUrl)\")!g"
#!substdef "!KZQ_RESET_PUBLISHER_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where sender = \"\$var(MediaUrl)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g"
#!substdef "!KZQ_PRESENCE_RESET!delete from presentity where sender = \"\$var(MediaUrl)\"!g"
# # #!substdef "!KZQ_RESET_ACCOUNT_UPDATE!update active_watchers set expires = \$TS where watcher_domain=\"\$(kzE{kz.json,Realm})\"!g"
#!substdef "!KZQ_RESET_ACCOUNT_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where domain=\"\$(kzE{kz.json,Realm})\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g"
#!substdef "!KZQ_RESET_ACCOUNT_RESET!delete from presentity where domain=\"\$(kzE{kz.json,Realm})\"!g"
#!substdef "!KZQ_RESET_PUBLISHER_ZONE_UPDATE!INSERT INTO tmp_probe select distinct a.event, a.presentity_uri, 0 from presentities a inner join wdispatcher c on a.sender = c.destination inner join active_watchers b on a.presentity_uri = b.presentity_uri and a.event = b.event where zone = \"\$var(Zone)\" and state in('early', 'confirmed', 'onthephone', 'busy', 'ringing')!g"
#!substdef "!KZQ_PRESENCE_ZONE_RESET!delete from presentity where id in(select a.id from presentities a join wdispatcher c on a.sender = c.destination where zone = \"\$var(Zone)\")!g"
#!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"

+ 1
- 0
kamailio/db_queries_mysql.cfg View File

@ -11,4 +11,5 @@
#!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"

+ 9
- 0
kamailio/db_queries_postgres.cfg View File

@ -12,3 +12,12 @@
#!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"

+ 46
- 0
kamailio/db_scripts/check-kazoodb-sql.sh View File

@ -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

+ 4
- 99
kamailio/db_scripts/create-kazoodb-sql.sh View File

@ -1,104 +1,9 @@
#!/bin/sh -e
#####################################################################################
##
## If you want prepare SQL file for PostgreSQL or MySQL server, then need to execute
## DB_ENGINE=postgres ./create-kazoodb-sql.sh
##
#####################################################################################
KAMAILIO_SHARE_DIR=${KAMAILIO_SHARE_DIR:-/usr/share/kamailio}
DB_ENGINE=${DB_ENGINE:-db_kazoo}
RESULTED_SQL=${RESULTED_SQL:-/tmp/kamailio_initdb.sql}
. $(dirname $0)/kazoodb-sql.sh --source-only
. $(dirname $0)/$DB_ENGINE-specific --source-only
sql_filelist() {
cat << EOF
acc-create.sql
lcr-create.sql
domain-create.sql
group-create.sql
permissions-create.sql
registrar-create.sql
usrloc-create.sql
msilo-create.sql
alias_db-create.sql
uri_db-create.sql
speeddial-create.sql
avpops-create.sql
auth_db-create.sql
pdt-create.sql
dialog-create.sql
dispatcher-create.sql
dialplan-create.sql
topos-create.sql
presence-create.sql
rls-create.sql
imc-create.sql
cpl-create.sql
siptrace-create.sql
domainpolicy-create.sql
carrierroute-create.sql
userblacklist-create.sql
htable-create.sql
purple-create.sql
uac-create.sql
pipelimit-create.sql
mtree-create.sql
sca-create.sql
mohqueue-create.sql
rtpproxy-create.sql
uid_auth_db-create.sql
uid_avp_db-create.sql
uid_domain-create.sql
uid_gflags-create.sql
uid_uri_db-create.sql
EOF
}
sql_all_header() {
cat << EOF
CREATE TABLE version (
table_name VARCHAR(32) NOT NULL,
table_version INTEGER DEFAULT 0 NOT NULL,
CONSTRAINT version_table_name_idx UNIQUE (table_name)
);
INSERT INTO version VALUES('version',1);
EOF
}
sql_all_extra_tables() {
cat << EOF
CREATE TABLE event_list ( event varchar(25) PRIMARY KEY NOT NULL);
INSERT INTO event_list VALUES('dialog');
INSERT INTO event_list VALUES('presence');
INSERT INTO event_list VALUES('message-summary');
INSERT INTO version VALUES('event_list',1);
EOF
}
sql_all_footer() {
cat << EOF
COMMIT;
EOF
}
echo "Creating kamailio database init file in '$RESULTED_SQL'"
sql_db_pre_setup > $RESULTED_SQL
sql_all_header >> $RESULTED_SQL
sql_header >> $RESULTED_SQL
for i in $(sql_filelist); do
cat $KAMAILIO_SHARE_DIR/$DB_ENGINE/$i >> $RESULTED_SQL
done
sql_all_extra_tables >> $RESULTED_SQL
sql_extra_tables >> $RESULTED_SQL
sql_footer >> $RESULTED_SQL
sql_all_footer >> $RESULTED_SQL
sql_setup $RESULTED_SQL
file=$(sql_db_prepare)
echo "setting up kazoo db from init script $file"
sql_setup $file
exit 0

+ 34
- 0
kamailio/db_scripts/db_extra_check.sql View File

@ -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;"
}

+ 14
- 0
kamailio/db_scripts/db_init_watcher_triggers.sql View File

@ -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;

+ 106
- 3
kamailio/db_scripts/db_kazoo-specific View File

@ -6,15 +6,16 @@ cat << EOF
PRAGMA foreign_keys=OFF;
PRAGMA wal=on;
PRAGMA journal_mode=WAL;
PRAGMA wal_autocheckpoint=25;
BEGIN TRANSACTION;
EOF
}
sql_setup() {
DB_KAZOO_LOCATION=${DB_KAZOO_LOCATION:-/etc/kazoo/kamailio/db}
mkdir -p ${DB_KAZOO_LOCATION}
KazooDB ${DB_KAZOO_LOCATION}/kazoo.db < $1
DB_KAZOO_LOCATION=${2:-${DB_KAZOO_LOCATION:-/etc/kazoo/kamailio/db}}
mkdir -p ${DB_KAZOO_LOCATION}
KazooDB -db ${DB_KAZOO_LOCATION}/kazoo.db < $1 > /dev/null
}
sql_header() {
@ -40,6 +41,108 @@ CREATE TABLE active_watchers_log (
user_agent VARCHAR(255) DEFAULT '' COLLATE NOCASE,
CONSTRAINT active_watchers_active_watchers_log_idx UNIQUE (presentity_uri, watcher_username, watcher_domain, event)
);
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,"<state>")+7, instr(body,"</state>") - instr(body,"<state>") - 7)
when event = "presence"
then case when instr(body,"<dm:note>") == 0
then replace(substr(body, instr(body,"<note>")+6, instr(body,"</note>") - instr(body,"<note>") - 6), " ", "")
else replace(substr(body, instr(body,"<dm:note>")+9, instr(body,"</dm:note>") - instr(body,"<dm:note>") - 9), " ", "")
end
when event = "message-summary"
then case when instr(body,"Messages-Waiting: yes") = 0
then "Waiting"
else "Not-Waiting"
end
end as varchar(12))) state
from presentity;
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
}


+ 5811
- 0
kamailio/db_scripts/kamailio_initdb_postgres.sql
File diff suppressed because it is too large
View File


+ 56
- 0
kamailio/db_scripts/kazoodb-sql.sh View File

@ -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"
}

+ 20
- 0
kamailio/db_scripts/vw_presentities.sql View File

@ -0,0 +1,20 @@
CREATE VIEW presentities as
select id, cast(printf("sip:%s@%s",username,domain) as varchar(64)) presentity_uri ,
username, domain, event, cast(substr(etag, instr(etag,"@")+1) as varchar(64)) callid,
datetime(received_time, 'unixepoch') as received,
datetime(expires, 'unixepoch') as expire_date,
expires, cast(sender as varchar(30)) sender,
lower(cast( case when event = "dialog"
then substr(body, instr(BODY,"<state>")+7, instr(body,"</state>") - instr(body,"<state>") - 7)
when event = "presence"
then case when instr(body,"<dm:note>") == 0
then replace(substr(body, instr(body,"<note>")+6, instr(body,"</note>") - instr(body,"<note>") - 6), " ", "")
else replace(substr(body, instr(body,"<dm:note>")+9, instr(body,"</dm:note>") - instr(body,"<dm:note>") - 9), " ", "")
end
when event = "message-summary"
then case when instr(body,"Messages-Waiting: yes") = 0
then "Waiting"
else "Not-Waiting"
end
end as varchar(12))) state
from presentity

+ 6
- 0
kamailio/db_scripts/vw_w_keepalive_contact.sql View File

@ -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

+ 6
- 0
kamailio/db_scripts/vw_w_location_contact.sql View File

@ -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

+ 6
- 0
kamailio/db_scripts/vw_w_watchers_contact.sql View File

@ -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

+ 6
- 0
kamailio/db_scripts/vw_wdispatcher.sql View File

@ -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

+ 440
- 411
kamailio/default.cfg
File diff suppressed because it is too large
View File


+ 88
- 0
kamailio/defs-amqp.cfg View File

@ -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

+ 50
- 91
kamailio/defs.cfg View File

@ -2,125 +2,82 @@
####### defs ########
#!ifndef DEFAULTS_INCLUDED
#!define DEFAULTS_INCLUDED
#!ifndef KAZOO_LOG_LEVEL
#!define KAZOO_LOG_LEVEL L_INFO
#!endif
#!substdef "!MAJOR!$(version(num){re.subst,/^(([^\.])*\.([^\.])*)\..*/\1/})!g"
#!ifndef KAMAILIO_DBMS
#!substdef "!KAMAILIO_DBMS!kazoo!g"
#!endif
#!trydef EXTERNAL_TO_INTERNAL_NO_RESPONSE_TIMER 3500
#!trydef INTERNAL_TO_EXTERNAL_NO_RESPONSE_TIMER 3500
#!ifndef KAZOO_DATA_DIR
#!substdef "!KAZOO_DATA_DIR!/etc/kazoo/kamailio/db!g"
#!endif
#!trydef OVERRIDE_MEDIA_REPLY_480 603
#!ifndef KAZOO_DB_URL
#!substdef "!KAZOO_DB_URL!kazoo:///KAZOO_DATA_DIR/kazoo.db!g"
#!endif
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"
#!ifndef MAX_WHILE_LOOPS
#!substdef "!MAX_WHILE_LOOPS!500!g"
#!endif
kazoo.override_media_reply_480 = OVERRIDE_MEDIA_REPLY_480 descr "sip code to send upstream when media returns 480 with session in progress"
#!ifndef CHILDREN
#!define CHILDREN 25
#!ifndef MY_HOSTNAME
#!substdef "!MY_HOSTNAME!$HN(f)!g"
#!endif
#!ifndef TCP_CHILDREN
#!define TCP_CHILDREN 25
#!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
#!ifndef OPENBTS_AUTH_SECRET
#!substdef "!OPENBTS_AUTH_SECRET!b3a54fa8317c7d9cb1d89d8970947b30eda273124d97fc3a079ccc98ecc2569b!g"
#!endif
#!ifndef KZ_USE_DISPATCHER_LIST
#!trydef KZ_USE_DISPATCHER_TABLE
#!ifndef WEBSOCKET_NO_ORIGIN_RESTRICTION
#!ifndef MY_WEBSOCKET_DOMAIN
#!substdef "!MY_WEBSOCKET_DOMAIN!$HN(d)!g"
#!endif
#!ifndef ANTIFLOOD_CACHE_PERIOD
#!substdef "!ANTIFLOOD_CACHE_PERIOD!600!g"
#!endif
#!ifndef MY_AMQP_MAX_CHANNELS
#!define MY_AMQP_MAX_CHANNELS 25
#!endif
#!trydef KAZOO_LOG_LEVEL L_INFO
#!ifndef MY_AMQP_CONSUMER_PROCESSES
#!define MY_AMQP_CONSUMER_PROCESSES 4
#!endif
#!trydef PV_BUFFER_SIZE 16384
#!trydef PV_BUFFER_SLOTS 30
#!trydef KZ_MEM_SUMMARY 0
#!ifndef MY_AMQP_CONSUMER_WORKERS
#!define MY_AMQP_CONSUMER_WORKERS 16
#!endif
#!trydef KZ_DB_MODULE kazoo
#!substdef "!KAMAILIO_DBMS!$def(KZ_DB_MODULE)!g"
#!ifndef MY_AMQP_HEARTBEATS
#!define MY_AMQP_HEARTBEATS 5
#!ifndef KAZOO_DATA_DIR
#!substdef "!KAZOO_DATA_DIR!/etc/kazoo/kamailio/db!g"
#!endif
#!ifndef BLF_USE_SINGLE_DIALOG
#!define BLF_USE_SINGLE_DIALOG 1
#!ifndef KAZOO_DB_URL
#!substdef "!KAZOO_DB_URL!kazoo:///KAZOO_DATA_DIR/kazoo.db!g"
#!endif
#!ifndef MY_AMQP_ZONE
#!substdef "!MY_AMQP_ZONE!local!g"
#!ifndef MAX_WHILE_LOOPS
#!substdef "!MAX_WHILE_LOOPS!500!g"
#!endif
#!ifndef DISPATCHER_ADD_SERVERS
#!define DISPATCHER_ADD_SERVERS 1
#!endif
#### tcp parameters ##
#!trydef CHILDREN 25
#!trydef TCP_CHILDREN 25
#!ifndef PRESENCE_RESET_BLF_DEFER_UPDATE
#!define PRESENCE_RESET_BLF_DEFER_UPDATE 0
#!endif
#!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
#!ifndef MY_AMQP_PUA_MODE
#!ifdef PRESENCE_ROLE
#!define MY_AMQP_PUA_MODE 1
#!else
#!define MY_AMQP_PUA_MODE 0
#!endif
#!endif
#!include_file "defs-amqp.cfg"
#!ifndef MEDIA_SERVERS_HASH_SIZE
#!substdef "!MEDIA_SERVERS_HASH_SIZE!256!g"
#!endif
#!ifndef KZ_PRESENCE_AMQP_PUBLISH
#!define KZ_PRESENCE_AMQP_PUBLISH 0
#!endif
#!ifndef KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE
#!define KZ_PRESENCE_REQUEST_RESUBSCRIBE_PROBE 0
#!endif
#!ifndef KZ_PRESENCE_REQUEST_PROBE
#!define KZ_PRESENCE_REQUEST_PROBE 1
#!endif
#!ifndef NAT_UAC_TEST_LEVEL
#!substdef "!NAT_UAC_TEST_LEVEL!3!g"
#!endif
#################################
## Defs related to SIP_TRACE_ROLE
##
#!ifdef SIP_TRACE_ROLE
#!trydef KZ_TRACE 0
#!trydef KZ_TRACE_INTERNAL 1
#!trydef KZ_TRACE_EXTERNAL 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
#!ifndef SIP_TRACE_URI
#!substdef "!SIP_TRACE_URI!sip:127.0.0.1:9060!g"
#!endif
#!ifndef HEP_CAPTURE_ID
#!substdef "!HEP_CAPTURE_ID!1!g"
#!endif
#!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
@ -130,7 +87,9 @@
#!trydef KZ_TLS_REGISTRAR_PORT 7000
#!endif
#!trydef KZ_FAST_PICKUP_COOKIES 1
#!trydef KZ_FAST_PICKUP_REALTIME 1
#!trydef KZ_MULTI_HOMED 0
#!endif
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab

+ 306
- 0
kamailio/dispatcher-role-5.1.cfg View File

@ -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

+ 309
- 0
kamailio/dispatcher-role-5.2.cfg View File

@ -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

+ 309
- 0
kamailio/dispatcher-role-5.4.cfg View File

@ -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

+ 309
- 0
kamailio/dispatcher-role-5.5.cfg View File

@ -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

+ 0
- 264
kamailio/dispatcher-role.cfg View File

@ -1,264 +0,0 @@
######## Generic Hash Table container in shared memory ########
modparam("htable", "htable", "failover=>size=16;autoexpire=120")
kazoo.dispatcher_auto_add = DISPATCHER_ADD_SERVERS descr "adds media servers reported by ecallmgr"
####### 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", "setid_pvname", "$var(setid)")
modparam("dispatcher", "ds_ping_method", "OPTIONS")
modparam("dispatcher", "ds_ping_interval", 10)
modparam("dispatcher", "ds_probing_threshold", 3)
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_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)
####### Dispatcher Logic ########
route[DISPATCHER_CLASSIFY_SOURCE]
{
#!import_file "dispatcher-network-classify.cfg"
if (is_myself("$ou")) {
xlog("L_INFO", "$ci|log|original R-URI ($ou) is this proxy, treating as external sources\n");
} else if (
ds_is_from_list(1, 3) ||
ds_is_from_list(2, 3) ||
ds_is_from_list(3, 3) ||
ds_is_from_list(10, 3) ||
ds_is_from_list(20, 3)
) {
xlog("L_INFO", "$ci|log|originated from internal sources\n");
setflag(FLAG_INTERNALLY_SOURCED);
} else {
xlog("L_INFO", "$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]
{
if ($sht(failover=>$ci::current) != $null) {
$du = $sht(failover=>$ci::current);
return;
}
$var(ds_primary_group) = 1;
$var(ds_backup_group) = 2;
#!ifndef PRESENCE_ROLE
if (is_method("SUBSCRIBE")) {
$var(ds_primary_group) = 10;
$var(ds_backup_group) = 11;
}
#!endif
#!ifndef REGISTRAR_ROLE
if (is_method("REGISTER")) {
$var(ds_primary_group) = 20;
$var(ds_backup_group) = 21;
}
#!endif
#!ifdef FAST_PICKUP_ROLE
route(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)", "0") || $(avp(ds_dst)[0]) == $null) {
# we selected from primary group, try again in backup group
if (!ds_select_dst("$var(ds_backup_group)", "0") || $(avp(ds_dst)[0]) == $null) {
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;
$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|log|found redirect for $var(redirect)\n");
if (route(DISPATCHER_REORDER_ROUTES)) {
$avp(AVP_REDIRECT_KEY) = $var(redirect);
}
} else if ($sht(associations=>$var(user_source)) != $null) {
$var(prefered_route) = $sht(associations=>$var(user_source));
xlog("L_INFO", "$ci|log|found association for contact uri $var(user_source)\n");
if (!route(DISPATCHER_REORDER_ROUTES)) {
$sht(associations=>$var(association)) = $null;
}
}
}
route[DISPATCHER_REORDER_ROUTES]
{
$var(i) = 0;
$var(found) = 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)]);
} else {
$var(found) = 1;
}
$var(i) = $var(i) + 1;
}
if (!$var(found) && $var(ds_group) == $var(ds_primary_group) && ds_select_dst("$var(ds_backup_group)", "0")) {
$var(i) = 0;
while($(avp(ds_dst)[$var(i)]) != $null) {
if($(avp(ds_dst)[$var(i)]) == $var(prefered_route)) {
xlog("L_INFO", "$ci|log|found associated media server in backup list\n");
$var(found) = 1;
break;
}
$var(i) = $var(i) + 1;
}
}
if ($var(found)) {
xlog("L_INFO", "$ci|log|re-ordering the dispatcher list to maintain association with $var(prefered_route)\n");
$(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;
} else {
xlog("L_INFO", "$ci|log|associated media server $var(prefered_route) is inactive, moving to $rd\n");
return -1;
}
return 1;
}
route[DISPATCHER_NEXT_ROUTE]
{
$var(failover_count) = $sht(failover=>$ci::counts);
if ($sht(failover=>$ci::counts) == $null) {
$var(i) = 0;
while($(avp(ds_dst)[$var(i)]) != $null) {
$sht(failover=>$ci[$var(i)]) = $(avp(ds_dst)[$var(i)]);
$var(i) = $var(i) + 1;
if ($var(i) >= 3) {
break;
}
}
$sht(failover=>$ci::counts) = $var(i);
$var(failover_count) = $var(i);
}
# try to find a new media server to send the call to
if ($var(failover_count) > 1) {
$var(failover_count) = $var(failover_count) - 1;
$du = $sht(failover=>$ci[$var(failover_count)]);
$sht(failover=>$ci::counts) = $var(failover_count);
$sht(failover=>$ci::current) = $du;
xlog("L_INFO", "$ci|log|remaining failed retry attempts: $var(failover_count)\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;
t_on_reply("INTERNAL_REPLY");
t_on_failure("INTERNAL_FAULT");
# relay the request to the new media server
route(EXTERNAL_TO_INTERNAL_RELAY);
exit();
}
}
event_route[dispatcher:dst-down]
{
xlog("L_ERR", "Destination down: $ru\n");
}
event_route[dispatcher:dst-up]
{
xlog("L_WARNING", "Destination up: $ru\n");
}
route[DISPATCHER_CHECK_MEDIA_SERVER]
{
if(@cfg_get.kazoo.dispatcher_auto_add == 1) {
$var(SetId) = 1;
if($var(Zone) != "MY_AMQP_ZONE") {
$var(SetId) = 2;
}
sql_query("exec", "KZQ_CHECK_MEDIA_SERVER_INSERT");
if($sqlrows(exec) > 0) {
xlog("L_WARNING", "reloading dispatcher table\n");
ds_reload();
}
}
}
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

+ 17
- 3
kamailio/kamailio.cfg View File

@ -10,6 +10,7 @@
#!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"
@ -23,15 +24,28 @@
#!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"
####### DBMS query selection ########
include_file "db_queries_KAMAILIO_DBMS.cfg"
####### Default Configuration ######
include_file "default.cfg"


+ 113
- 19
kamailio/kazoo-bindings.cfg View File

@ -1,21 +1,52 @@
######## kazoo bindings ########
### use this simple form of binding a listener
### kazoo_subscribe("dialoginfo", "direct", "BLF-QUEUE-MY_HOSTNAME", "BLF-MY_HOSTNAME");
###
### or unleash the power of rabbit to kazoo-blf
###
### 'no_ack' : 1 => needs ack,
### 'wait_for_consumer_ack'
### : 1 => when it receives, it processses on the AMQP Worker ad after that it confirms
### : 0 => when it receives, it acks then processes in the AMQP Worker
### only works if no_ack : 0
###
### Rabbit Policy for ha-mode
### pattern : ^BLF
### definition : ha-mode: all
###
###
#!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]
{
@ -36,8 +67,7 @@ event_route[kazoo:mod-init]
#!endif
#!ifdef ACL_ROLE
$var(payload) = "{ 'exchange' : 'frontier_acl' , 'type' : 'topic', 'queue' : 'FRONTIERACL-FLUSH-MY_HOSTNAME', 'routing' : 'flush' }";
kazoo_subscribe("$var(payload)");
route(ACL_BINDINGS);
#!endif
#!import_file "kazoo-custom-bindings.cfg"
@ -46,17 +76,81 @@ event_route[kazoo:mod-init]
event_route[kazoo:consumer-event]
{
xlog("L_INFO","unhandled AMQP event, payload: $kzE\n");
xlog("L_DEBUG","unhandled AMQP event, payload: $kzE\n");
}
event_route[kazoo:consumer-event-connection-open]
{
xlog("L_INFO","connection to $(kzE{kz.json,host}) opened\n");
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_INFO","connection to $(kzE{kz.json,host}) closed\n");
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

+ 343
- 0
kamailio/keepalive-role.cfg View File

@ -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)");
}
}

+ 29
- 25
kamailio/local.cfg View File

@ -8,8 +8,6 @@
#!trydef PRESENCE_ROLE
#!trydef RESPONDER_ROLE
#!trydef NODES_ROLE
#!trydef FAST_PICKUP_ROLE
#!trydef PRESENCE_QUERY_ROLE
## Disabled Roles - remove all but the last '#' to enable
# # #!trydef TRAFFIC_FILTER_ROLE
@ -27,26 +25,39 @@
################################################################################
## SERVER INFORMATION
################################################################################
## CHANGE "kamailio.2600hz.com" TO YOUR SERVERS HOSTNAME
#!substdef "!MY_HOSTNAME!kamailio.2600hz.com!g"
## UNCOMMENT & CHANGE "kamailio.2600hz.com" TO YOUR SERVERS HOSTNAME
# # #!substdef "!MY_HOSTNAME!kamailio.2600hz.com!g"
## CHANGE "127.0.0.1" TO YOUR SERVERS IP ADDRESS
## 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!0.0.0.0!g"
# # #!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!kazoo://guest:guest@127.0.0.1:5672!g"
# # #!substdef "!MY_AMQP_ZONE!local!g"
# # #!substdef "!MY_AMQP_URL!amqp://guest:guest@127.0.0.1:5672!g"
## This parameter is only required if you are using websockets
################################################################################
## 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. If you remove
## it completely the validation will be disabled.
#!substdef "!MY_WEBSOCKET_DOMAIN!2600hz.com!g"
## 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
@ -56,8 +67,9 @@
## remove all but the last '#' and configure the connector
## accordingly. The example shows how to use postgres.
## See the kamailio documentation for more details.
# # #!substdef "!KAMAILIO_DBMS!postgres!g"
# # #!substdef "!KAZOO_DB_URL!postgres://kamailio:kamailio@127.0.0.1/kamailio!g"
#!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
@ -75,13 +87,14 @@
## 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.
mhomed=0
##!define KZ_MULTI_HOMED 1
################################################################################
## KZ_DISABLE_REGISTRAR_PORTS
@ -106,23 +119,14 @@ mhomed=0
##!define KZ_UDP_REGISTRAR_PORT 7000
##!define KZ_TCP_REGISTRAR_PORT 7000
################################################################################
## NAT
################################################################################
## These parameters are OPTIONAL.
## It allows overriding the nat_uac_test with a different value than "3"
## (default) as it is proven that it fixes the issue reported here:
## https://lists.kamailio.org/pipermail/sr-users/2016-August/094211.html
# # #!substdef "!NAT_UAC_TEST_LEVEL!1!g"
################################################################################
## 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
# # #!substdef "!SIP_TRACE_URI!sip:127.0.0.1:9060!g"
# # #!substdef "!HEP_CAPTURE_ID!1!g"
# # #!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


+ 77
- 36
kamailio/message-role.cfg View File

@ -1,60 +1,101 @@
modparam("htable", "htable", "msg=>size=32;autoexpire=60;")
event_route[kazoo:consumer-event-message-route]
route[HANDLE_MESSAGE]
{
$var(uri_username) = "";
kazoo_json($kzE, "Endpoints[0].To-Username", "$var(uri_username)");
$var(x) = $(kzE{kz.json,Endpoints[0].To-Username});
xlog("L_INFO", "received message route for $(kzE{kz.json,Endpoints[0].To-DID})\n");
if( $var(uri_username) != "" ) {
$var(from_uri) = "sip:" + $(kzE{kz.json,Caller-ID-Number}) + "@" + $(kzE{kz.json,Endpoints[0].To-Realm});
$var(to_uri) = "sip:" + $(kzE{kz.json,Endpoints[0].To-Username}) + "@" + $(kzE{kz.json,Endpoints[0].To-Realm});
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 {
$var(from_uri) = "sip:" + $(kzE{kz.json,Caller-ID-Number}) + $(kzE{kz.json,Endpoints[0].To-Realm});
$var(to_uri) = $(kzE{kz.json,Endpoints[0].Route});
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;
}
}
$sht(msg=>$(kzE{kz.json,Call-ID})) = $kzE;
}
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{kz.json,Body});
$uac_req(hdrs)="X-KAZOO-AOR: " + $var(to_uri)+ "\r\nContent-Type: text/plain\r\n";
$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:MY_IP_ADDRESS:5060";
$uac_req(callid) = $(kzE{kz.json,Call-ID});
xlog("L_INFO", "sending message from $var(from_uri) to $var(to_uri) \n");
$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_REPLY]
route[MESSAGE_ROUTE]
{
if( $(sht(msg=>$ci)) == $null) {
exit();
}
remove_hf_re("^X-");
if($T_reply_code != 200 && $T_reply_code != 202) {
$var(Result) = "Failure";
} else {
$var(Result) = "Success";
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));
}
}
$var(Payload) = '{ "Event-Category" : "message", "Event-Name" : "delivery", "Call-ID" : "$(sht(msg=>$ci){kz.json,Call-ID})", "Message-ID" : "$(sht(msg=>$ci){kz.json,Message-ID})" , "Delivery-Result-Code" : "sip:$T_reply_code", "Msg-ID" : "$(sht(msg=>$ci){kz.json,Msg-ID})" , "Status" : "$var(Result)"}';
$var(RoutingKey) = $(sht(msg=>$ci){kz.json,Server-ID});
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";
if($var(RoutingKey) == "") {
$var(exchange) = "sms";
$var(RoutingKey) = "message.delivery." + $(sht(msg=>$ci){kz.json,Call-ID}{kz.encode});
}
xlog("L_INFO", "sending delivery message for $ci\n");
kazoo_publish($var(exchange), $var(RoutingKey), $var(Payload));
$var(RK) = $avp(server_id);
kazoo_publish($var(exchange), $var(RK), $var(Payload));
}
route[MESSAGE_BINDINGS]
{
$var(key) = "kamailio@MY_HOSTNAME";
$var(payload) = "{ 'exchange' : 'sms' , 'type' : 'topic', 'queue' : 'MSG-QUEUE-MY_HOSTNAME', 'routing' : 'message.route." + $(var(key){kz.encode}) + ".*', 'no_ack' : 0 }";
$var(payload) = $_s({"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)");
}


+ 105
- 34
kamailio/nat-traversal-role.cfg View File

@ -1,45 +1,116 @@
######## NAT Traversal module - signaling functions ########
#!ifndef NATHELPER_LOADED
loadmodule "nathelper.so"
#!trydef NATHELPER_LOADED
#!endif
modparam("nathelper", "received_avp", "$avp(AVP_RECV_PARAM)")
modparam("nathelper", "sipping_from", "sip:sipcheck@MY_HOSTNAME")
modparam("nathelper", "sipping_from", "sip:registrar@MY_HOSTNAME")
#!ifdef WEBSOCKETS_ROLE
#!trydef KZ_NAT_DETECT 83
#!else
#!trydef KZ_NAT_DETECT 19
#!endif
#!trydef KZ_NAT_FIX_SDP_REQUEST 1
#!trydef KZ_NAT_FIX_SDP_REPLY 1
#!trydef KZ_NAT_SDP_TEST 8
#!trydef KZ_NAT_SDP_FIX 10
kazoo.nat_fix_sdp_request = KZ_NAT_FIX_SDP_REQUEST descr "performs request sdp replacement of private addresses"
kazoo.nat_fix_sdp_reply = KZ_NAT_FIX_SDP_REPLY descr "performs reply sdp replacement of private addresses"
####### NAT Traversal Logic ########
route[NAT_TEST_AND_CORRECT]
route[NAT_SDP]
{
if( has_body("application/sdp")) {
if( nat_uac_test(KZ_NAT_SDP_TEST)) {
xlog("L_DEBUG", "$ci|log|applying sdp nat fix\n");
$var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX);
xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix is $var(ret)\n");
} else if( is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) {
xlog("L_DEBUG", "$ci|log|applying sdp nat fix for held channel\n");
$var(ret) = fix_nated_sdp(KZ_NAT_SDP_FIX);
xlog("L_DEBUG", "$ci|log|result of applying sdp nat fix for held channel is $var(ret)\n");
}
}
}
route[NAT_DETECT]
{
if($sel(cfg_get.kazoo.nat_fix_sdp_request) == 1) {
route(NAT_SDP);
}
if ($Rp == "5080") {
setflag(FLAG_SKIP_NAT_CORRECTION);
xlog("L_DEBUG", "$ci|log|skipping nat correction on PORT 5080\n");
} else {
if (is_present_hf("Record-Route")) {
$var(i) = 0;
$var(rr_count) = $rr_count;
while($var(i) < $var(rr_count)) {
$var(rr_base) = $(hdr(Record-Route)[$var(i)]);
$var(rr_idx) = 0;
$var(rr) = $(var(rr_base){s.select,$var(rr_idx),,});
while($var(rr) != $null && $var(rr) != "") {
$var(i) = $var(i) + 1;
if (!is_myself("$(var(rr){nameaddr.uri})")) {
setflag(FLAG_SKIP_NAT_CORRECTION);
xlog("L_DEBUG", "$ci|log|skipping nat correction on record-route $(var(rr){nameaddr.uri})\n");
}
$var(rr_idx) = $var(rr_idx) + 1;
$var(rr) = $(var(rr_base){s.select,$var(rr_idx),,});
}
}
}
}
if (isflagset(FLAG_SKIP_NAT_CORRECTION)) {
xlog("L_DEBUG", "$ci|log|skipping nat detection\n");
return;
}
force_rport();
if(nat_uac_test(KZ_NAT_DETECT)) {
xlog("L_DEBUG", "$ci|log|detected nat request\n");
setflag(FLT_NATS);
if (!is_method("REGISTER")) {
if(is_first_hop()) set_contact_alias();
}
}
}
route[NAT_MANAGE]
{
if (is_present_hf("Record-Route")) {
$var(i) = 0;
$var(rr_count) = $rr_count;
while($var(i) < $var(rr_count)) {
$var(rr_base) = $(hdr(Record-Route)[$var(i)]);
$var(rr_idx) = 0;
$var(rr) = $(var(rr_base){s.select,$var(rr_idx),,});
while($var(rr) != $null && $var(rr) != "") {
$var(i) = $var(i) + 1;
if (!is_myself("$(var(rr){nameaddr.uri})")) {
setflag(FLAG_SKIP_NAT_CORRECTION);
}
$var(rr_idx) = $var(rr_idx) + 1;
$var(rr) = $(var(rr_base){s.select,$var(rr_idx),,});
}
}
} else if ($Rp == "5080") {
setflag(FLAG_SKIP_NAT_CORRECTION);
}
if (isflagset(FLAG_SKIP_NAT_CORRECTION)) {
return();
}
if (nat_uac_test("NAT_UAC_TEST_LEVEL")) {
force_rport();
fix_nated_contact();
}
if (has_body("application/sdp") && nat_uac_test("8")) {
fix_nated_sdp("10");
}
if( is_reply() && $sel(cfg_get.kazoo.nat_fix_sdp_reply) == 1) {
route(NAT_SDP);
}
if ( is_request() && isflagset(FLAG_INTERNALLY_SOURCED)) {
setbflag(FLB_NATB);
}
if ( is_request() && has_totag() ) {
setbflag(FLB_NATB);
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) {
return;
}
if (is_reply()) {
if(isflagset(FLT_NATS) || isbflagset(FLB_NATB)) {
if(is_first_hop()) {
set_contact_alias();
}
}
}
}
# vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab

+ 86
- 38
kamailio/nodes-role.cfg View File

@ -1,21 +1,11 @@
######## Nodes role - pushes info to kazoo ########
#!ifndef NODES_EXPIRE
#!define NODES_EXPIRE 10
#!endif
#!ifndef NODES_FUDGE_FACTOR
#!define NODES_FUDGE_FACTOR 10
#!endif
#!trydef NODES_EXPIRE 10
#!trydef NODES_FUDGE_EXPIRE 45
modparam("htable", "htable", "nodes=>size=8;initval=0;autoexpire=60");
modparam("htable", "htable", "media=>size=8;initval=0;autoexpire=60");
####### RTIMER module ##########
#!ifndef RTIMER_LOADED
loadmodule "rtimer.so"
#!trydef RTIMER_LOADED
#!endif
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;")
@ -61,24 +51,24 @@ route(LISTENER_STATUS);
#!endif
$var(Roles) = $_s("Roles" : {"Proxy" : $var(listeners) $var(Dispatcher) $var(Presence) $var(Registrar)});
$var(Payload) = '{"Event-Category" : "nodes", "Event-Name" : "advertise", "Expires" : 15000, "Used-Memory" : $(stat(real_used_size){s.int}), "Startup" : $Tb, "WhApps" : {"kamailio" : {"Startup" : $Tb }}, $var(Roles)}';
$var(Payload) = $_s({"Event-Category" : "nodes", "Event-Name" : "advertise", "Expires" : 15000, "Used-Memory" : $(stat(real_used_size){s.int}), "Startup" : $Tb, "WhApps" : {"kamailio" : {"Startup" : $Tb }}, $var(Roles)});
kazoo_publish("nodes", "", $var(Payload));
}
event_route[kazoo:consumer-event-nodes-advertise]
{
$var(count) = $shtinc(nodes=>$(kzE{kz.json,Node})::count);
$var(count) = $shtinc(nodes=>$(kzE{kz.json,Node})::count);
if($var(count) == 0) {
xlog("L_WARNING", "$(kzE{kz.json,Msg-ID})|nodes|heartbeat for reconnected node $(kzE{kz.json,Node})\n");
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_WARNING", "$(kzE{kz.json,Msg-ID})|nodes|heartbeat from new node $(kzE{kz.json,Node})\n");
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");
}
@ -115,11 +105,11 @@ route[NODE_HEARTBEAT_ROUTE]
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_FACTOR;
$shtex(nodes=>$var(Node)) = ($(var(Payload){kz.json,Expires}{s.int}) / 1000) + NODES_FUDGE_EXPIRE;
$var(runloop) = $var(runloop) + 1;
}
}
}
route[CHECK_MEDIA_SERVERS]
@ -128,6 +118,7 @@ route[CHECK_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});
@ -141,20 +132,48 @@ route[CHECK_MEDIA_SERVERS]
$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).URL});
$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_FACTOR;
xlog("L_DEBUG", "nodes|media|$var(Node) media expiration $var(MediaExpire) for $var(MediaUrl)\n");
$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;
}
@ -173,22 +192,43 @@ event_route[htable:expired:media]
route[MEDIA_SERVER_UP]
{
xlog("L_WARNING", "nodes|media|$var(Node) reported new media server $var(MediaUrl) in zone $var(Zone)\n");
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 FAST_PICKUP_ROLE
route(FAST_PICKUP_START);
#!ifdef PRESENCE_ROLE
route(PRESENCE_FAST_PICKUP_START);
route(RESET_PUBLISHER);
#!endif
}
route[MEDIA_SERVER_DOWN]
{
xlog("L_WARNING", "htable|media|heartbeat expired for media server $var(MediaUrl) in zone $var(Zone)\n");
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
@ -198,7 +238,7 @@ route[MEDIA_SERVER_DOWN]
#!ifndef NODES_CUSTOM_BINDINGS
route[NODES_BINDINGS]
{
$var(payload) = "{ 'exchange' : 'nodes' , 'type' : 'fanout', 'queue' : 'nodes-MY_HOSTNAME', 'exclusive' : 0, 'federate' : 1}";
$var(payload) = $_s({"name": "nodes", "exchange" : "nodes" , "type" : "fanout", "queue" : "nodes-MY_HOSTNAME", "exclusive": false, "federate": true });
kazoo_subscribe("$var(payload)");
}
#!endif
@ -214,17 +254,25 @@ route[LISTENER_STATUS]
$var(listener) = $(jsonrpl(body){kz.json,result[$var(loop)]});
$var(proto) = $(var(listener){kz.json,PROTO});
$var(address) = $(var(listener){kz.json,ADDRLIST.ADDR});
$var(port) = $(var(listener){kz.json,PORT});
$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) = "";
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(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(loop) = $var(loop) + 1;
$var(sep) = " , ";
}
$var(listeners) = $_s({"Listeners" : { $var(listeners) }});
}


kamailio/fast-pickup-role.cfg → kamailio/presence-fast-pickup.cfg View File


+ 213
- 0
kamailio/presence-notify.cfg View File

@ -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)");
}
}

kamailio/presence_query-role.cfg → kamailio/presence-query.cfg View File


+ 39
- 20
kamailio/presence-reset.cfg View File

@ -1,3 +1,4 @@
#!trydef PRESENCE_RESET_BLF_DEFER_UPDATE 0
kazoo.presence_reset_blf_defer_update = PRESENCE_RESET_BLF_DEFER_UPDATE descr "defers blf reset"
@ -14,21 +15,10 @@ route[PRESENCE_RESET_ROUTE]
}
}
route[PRESENCE_RESET_BINDINGS]
{
#!import_file "presence-reset-custom-bindings.cfg"
#!ifndef PRESENCE_RESET_CUSTOM_BINDINGS
$var(payload) = "{ 'exchange' : 'presence' , 'queue' : 'presence-reset-MY_HOSTNAME', 'type' : 'topic', 'routing' : 'presence.reset.*.*', 'exclusive' : 0, 'federate' : 1 }";
kazoo_subscribe("$var(payload)");
#!endif
}
route[RESET_PUBLISHER]
{
xlog("L_INFO", "$var(Msg-ID)|reset|received presence reset for publisher $var(MediaUrl))\n");
if(@cfg_get.kazoo.presence_reset_blf_defer_update == 0) {
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)");
}
@ -36,6 +26,33 @@ route[RESET_PUBLISHER]
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]
@ -62,11 +79,14 @@ route[RESET_SERVER]
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_DELETE');
$var(presentities) = $sqlrows(exec);
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]
@ -98,7 +118,6 @@ route[RESET_WILDCARD]
}
event_route[kazoo:consumer-event-presence-reset]
{
if($(kzE{kz.json,Username}) == "*" || $(kzE{kz.json,Realm}) == "*") {
@ -106,7 +125,7 @@ event_route[kazoo:consumer-event-presence-reset]
exit();
}
xlog("L_INFO", "$(kzE{kz.json,Msg-ID})|reset|received presence reset for $(kzE{kz.json,Username})@$(kzE{kz.json,Realm})\n");
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');
@ -115,21 +134,21 @@ event_route[kazoo:consumer-event-presence-reset]
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_INFO", "$(kzE{kz.json,Msg-ID})|reset|skip message-summary subscriber notification for $var(presentity)\n");
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_INFO", "$(kzE{kz.json,Msg-ID})|reset|skip presence subscriber notification for $var(presentity)\n");
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_INFO", "$(kzE{kz.json,Msg-ID})|reset|skip dialog subscriber notification for $var(presentity)\n");
xlog("L_DEBUG", "$(kzE{kz.json,Msg-ID})|reset|skip dialog subscriber notification for $var(presentity)\n");
}
}

+ 260
- 114
kamailio/presence-role.cfg View File

@ -3,8 +3,36 @@
#!trydef PRESENCE_MIN_EXPIRES_ACTION 1
#!trydef PRESENCE_MAX_EXPIRES 3600
modparam("htable", "htable", "p=>size=32;autoexpire=3600;")
modparam("htable", "htable", "first=>size=32;autoexpire=3600;initval =0;updateexpire=1;")
#!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"
@ -21,65 +49,60 @@ modparam("presence_xml", "disable_bla", 1)
modparam("presence", "subs_db_mode", 3)
modparam("presence", "expires_offset", 0)
modparam("presence", "send_fast_notify", 1)
modparam("presence", "clean_period", 30)
modparam("presence", "db_update_period", 10)
modparam("presence", "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", 0)
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", 1)
modparam("presence", "cseq_offset", KZ_PRESENCE_CSEQ_OFFSET)
modparam("kazoo", "db_url", "KAZOO_DB_URL")
modparam("kazoo", "pua_mode", 1)
#!ifdef NAT_TRAVERSAL_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
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"
#!ifdef FAST_PICKUP_ROLE
#!include_file "fast-pickup-role.cfg"
#!endif
#!ifdef PRESENCE_QUERY_ROLE
#!include_file "presence_query-role.cfg"
#!endif
#!ifdef PRESENCE_NOTIFY_SYNC_ROLE
#!include_file "presence_notify_sync-role.cfg"
#!endif
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 ########
#!ifdef NAT_TRAVERSAL_ROLE
route[PRESENCE_NAT]
{
force_rport();
if (client_nat_test("3")) {
if(is_first_hop())
set_contact_alias();
}
nat_keepalive();
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
}
}
#!endif
route[HANDLE_SUBSCRIBE]
{
@ -87,9 +110,20 @@ route[HANDLE_SUBSCRIBE]
return;
}
#!ifdef NAT_TRAVERSAL_ROLE
route(PRESENCE_NAT);
#!endif
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();
@ -97,11 +131,6 @@ route[HANDLE_SUBSCRIBE]
record_route();
if (!t_newtran()) {
sl_reply_error();
exit;
}
if(has_totag()) {
route(HANDLE_RESUBSCRIBE);
} else {
@ -113,15 +142,22 @@ route[HANDLE_SUBSCRIBE]
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);
};
}
@ -161,8 +197,12 @@ route[HANDLE_NEW_SUBSCRIBE]
if (handle_subscribe()) {
xlog("L_INFO","$ci|end|new $hdr(Event) subscription from $fU to $tU in realm $fd : $sht(first=>$ci) : $sht(first=>$fU::$tU::$fd::$hdr(Event))\n");
route(DELETE_DUPLICATED_SUBSCRIPTIONS);
route(SUBSCRIBE_AMQP);
route(REQUEST_PROBE);
#!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");
}
@ -174,7 +214,7 @@ route[HANDLE_NEW_SUBSCRIBE]
route[SUBSCRIBE_AMQP]
{
if(@cfg_get.kazoo.presence_sync_amqp == 1) {
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));
@ -183,9 +223,9 @@ route[SUBSCRIBE_AMQP]
route[REQUEST_PROBE]
{
if( (@cfg_get.kazoo.presence_request_probe == 1 && (!has_totag()))
|| (@cfg_get.kazoo.presence_request_resubscribe_probe == 1 && has_totag()) ) {
if( route(HAS_PRESENTITY) == 0) {
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);
@ -206,26 +246,40 @@ route[REQUEST_PROBE]
route[REQUEST_MWI]
{
xlog("L_INFO", "$ci|sub|requesting mwi probe for $var(mwi) in realm $subs(to_domain)\n");
$var(rk) = "mwi_queries." + $(subs(to_domain){kz.encode});
$var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "mwi_query", "Username" : "$var(mwi)", "Realm" : "$fd", "Call-ID" : "$ci"});
kazoo_publish("presence", "$var(rk)", $var(amqp_payload_request));
xlog("L_INFO", "$ci|sub|requesting mwi probe for $var(mwi) in realm $subs(to_domain)\n");
$var(rk) = "mwi_queries." + $(subs(to_domain){kz.encode});
$var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "mwi_query", "Username" : "$var(mwi)", "Realm" : "$fd", "Call-ID" : "$ci"});
kazoo_publish("presence", "$var(rk)", $var(amqp_payload_request));
}
route[HANDLE_PUBLISH]
{
if (is_method("PUBLISH")) {
if (!t_newtran()) {
sl_reply_error();
exit;
}
if($hdr(Sender)!= $null)
handle_publish("$hdr(Sender)");
else
handle_publish();
t_release();
if(!is_method("PUBLISH")) {
return;
}
if ($hdr(Event) != "dialog"
&& $hdr(Event) != "presence"
&& $hdr(Event) != "message-summary") {
xlog("L_INFO", "$ci|presence|publish event $hdr(Event) not supported\n");
send_reply(489, "Bad Event");
exit();
}
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]
@ -245,7 +299,7 @@ route[HAS_PRESENTITY]
route[COUNT_PRESENTITIES]
{
$var(Query) = $_s(KZQ_COUNT_PRESENTITIES);
$var(p) = $_s(uri=$var(presentity));
$var(p) = $_s(presence_id='$var(presentity)');
if (sql_xquery("cb", "$var(Query)", "subs") == 1)
{
while($xavp(subs) != $null) {
@ -259,7 +313,7 @@ route[COUNT_PRESENTITIES]
route[COUNT_ALL_PRESENTITIES]
{
$var(Query) = $_s(select event, (select count(*) from presentity b where b.event = a.event) count from event_list a);
$var(p) = "uri=none";
$var(p) = "presence_id=none";
if (sql_xquery("cb", "$var(Query)", "subs") == 1)
{
while($xavp(subs) != $null) {
@ -290,7 +344,7 @@ route[COUNT_ALL_SUBSCRIBERS]
route[COUNT_SUBSCRIBERS]
{
$var(Query) = $_s(KZQ_COUNT_SUBSCRIBERS);
$var(p) = $_s(uri=$var(presentity));
$var(p) = $_s(presence_id='$var(presentity)');
if (sql_xquery("cb", "$var(Query)", "subs") == 1)
{
while($xavp(subs) != $null) {
@ -303,74 +357,155 @@ route[COUNT_SUBSCRIBERS]
event_route[kazoo:consumer-event-presence-dialog-update]
{
$var(Now) = $TS;
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)\n");
$var(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;
#!ifdef FAST_PICKUP_ROLE
route(FAST_PICKUP_INIT);
#!endif
route(PRESENCE_FAST_PICKUP_INIT);
$var(presentity) = $(kzE{kz.json,From});
$var(payload) = $kzE;
route(PRESENCE_UPDATE);
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n");
$var(EndRoute) = $(TV(Sn){s.replace,.,});
$var(delta_to_finish) = $var(EndRoute) - $var(StartRoute);
xlog("$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]
{
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received message-summary update for $(kzE{kz.json,From})\n");
$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 {
xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|skip message-summary update for $(kzE{kz.json,From})\n");
#!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);
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing message-summary update for $(kzE{kz.json,From}) light should be on ? $(kzE{kz.json,Messages-Waiting}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n");
$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]
{
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|received presence update for $(kzE{kz.json,Presence-ID}) : $kzE\n");
$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);
xlog("L_INFO", "$(kzE{kz.json,Call-ID})|log|finished processing $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,From}) state $(kzE{kz.json,State}) from $(kzE{kz.json,Switch-URI}) at $(kzE{kz.json,AMQP-Received})/$var(Now)/$TS\n");
$var(EndRoute) = $(TV(Sn){s.replace,.,});
$var(delta_to_finish) = $var(EndRoute) - $var(StartRoute);
xlog("$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=>dialog) > 0) {
xlog("L_INFO", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) dialog update for $xavp(watchers=>dialog) watchers\n");
kazoo_pua_publish_dialoginfo($var(JObj));
pres_refresh_watchers("$var(presentity)", "dialog", 1);
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 {
xlog("L_DEBUG", "$(var(payload){kz.json,Call-ID})|log|skip dialog update for $var(presentity)\n");
}
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) {
xlog("L_INFO", "$(var(payload){kz.json,Call-ID})|log|publishing $var(presentity) presence update for $xavp(watchers=>presence) watchers\n");
kazoo_pua_publish_presence($var(payload));
pres_refresh_watchers("$var(presentity)", "presence", 1);
} else {
xlog("L_DEBUG", "$(kzE{kz.json,Call-ID})|log|skip presence update for $var(presentity)\n");
}
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
}
}
}
@ -396,44 +531,55 @@ route[MWI_AS_PRESENCE]
$var(State) = "confirmed";
} else {
$var(State) = "terminated";
}
}
$var(payload) = MWI_PRESENCE_BODY
$var(JObj) = $var(payload);
route(PRESENCE_UPDATE);
}
#!include_file "presence-reset.cfg"
route[PRESENCE_BINDINGS]
{
#!import_file "presence-custom-bindings.cfg"
#!ifndef PRESENCE_CUSTOM_BINDINGS
$var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-dialog-MY_HOSTNAME", "routing" : "dialog.*.*", "exclusive" : 0, "federate" : 1 });
$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
$var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-presence-MY_HOSTNAME", "routing" : "update.*.*", "exclusive" : 0, "federate" : 1 });
kazoo_subscribe("$var(payload)");
route(PRESENCE_API_BINDINGS);
$var(payload) = $_s({ "exchange" : "presence", "type" : "topic", "queue" : "presence-mwi-MY_HOSTNAME", "routing" : "mwi_updates.*.*", "exclusive" : 0 , "federate" : 1 });
kazoo_subscribe("$var(payload)");
#!endif
route(PRESENCE_FAST_PICKUP_START);
route(PRESENCE_RESET_BINDINGS);
#!ifdef PRESENCE_QUERY_ROLE
route(PRESENCE_QUERY_BINDINGS);
#!endif
}
#!ifdef FAST_PICKUP_ROLE
route(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

+ 0
- 117
kamailio/presence_notify_sync-role.cfg View File

@ -1,117 +0,0 @@
kazoo.presence_notify = 1 descr "enable/disable sending notify callback to omnipresence"
kazoo.presence_notify_timeout = 3000 descr "timeout in ms waiting for notify reply"
kazoo.presence_notify_log_body = 0 descr "logs the body sent in the notification"
kazoo.presence_notify_log_resp_body = 0 descr "logs the body received from notification"
kazoo.presence_notify_log_to_table = 1 descr "logs notify/reply to active_watchers_log table"
kazoo.presence_notify_log_to_amqp = 0 descr "logs notify/reply to amqp"
kazoo.presence_notify_record_route = 1 descr "add record route header to notify msg sent"
kazoo.presence_notify_log_init_body = 0 descr "logs the body before its sent"
kazoo.presence_notify_force_send_socket = 0 descr "forces the send socket to the contact"
######## Generic Hash Table container in shared memory ########
modparam("htable", "htable", "notify=>size=16;autoexpire=3600;updateexpire=1;initval=0")
#!trydef PRESENCE_NOTIFY_INIT
#!trydef MAX_NOTIFY_ERROR 5
route[PRESENCE_LOCAL_NOTIFY]
{
if($rm != "NOTIFY") {
return;
}
t_set_fr(@cfg_get.kazoo.presence_notify_timeout, @cfg_get.kazoo.presence_notify_timeout);
xlog("L_INFO", "$ci|log|init preparing $subs(event) notify to $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri) : $du\n");
if(@cfg_get.kazoo.presence_notify_log_init_body == 1) {
xlog("L_INFO", "$ci|log|init|body $(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\n");
}
if(@cfg_get.kazoo.presence_notify_force_send_socket == 1) {
$fs = $_s($(pr{s.tolower}):$(hdr(Contact){nameaddr.uri}{uri.host}):$(hdr(Contact){nameaddr.uri}{uri.port}));
xlog("L_INFO", "$ci|log|init|forcing socket to $fs, $(pr{s.tolower}):$(hdr(Contact){nameaddr.uri}{uri.host}):$(hdr(Contact){nameaddr.uri}{uri.port}) , $ct\n");
}
if(@cfg_get.kazoo.presence_notify_record_route == 1) {
record_route();
}
}
modparam("mqueue","mqueue", "name=presence_last_notity")
####### RTIMER module ##########
#!ifndef RTIMER_LOADED
loadmodule "rtimer.so"
#!trydef RTIMER_LOADED
#!endif
modparam("rtimer", "timer", "name=notifytimer;interval=500000u;mode=2;")
modparam("rtimer", "exec", "timer=notifytimer;route=PRESENCE_LOG_TIMER_ROUTE")
event_route[presence:notify-reply]
{
if(@cfg_get.kazoo.presence_notify != 1)
return;
$xavp(pres=>delete_subscription) = 0;
if($subs(reason) == "timeout") {
$xavp(pres=>delete_subscription) = 1;
xlog("L_INFO", "$ci|end|deleting subscribtion $subs(pres_uri) for $subs(watcher_username)@$subs(watcher_domain) due to timeout\n");
} else if($notify_reply($rs) == 200) {
$sht(notify=>$ci) = $null;
$sht(notify=>$ci::count) = 0;
xlog("L_INFO", "$ci|end|notified $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n");
} else {
xlog("L_ERROR", "$ci|error|received $notify_reply($rs) when notifying $subs(watcher_username)@$subs(watcher_domain) on behalf of $subs(pres_uri)\n");
if($rP != "UDP") {
$xavp(pres=>delete_subscription) = 1;
xlog("L_ERROR", "$ci|error|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri)\n");
} else {
$var(shtinc) = $shtinc(notify=>$ci::count);
if($var(shtinc) > MAX_NOTIFY_ERROR) {
$xavp(pres=>delete_subscription) = 1;
xlog("L_ERROR", "$ci|error|removing $rP watcher $subs(watcher_username)@$subs(watcher_domain) for $subs(pres_uri)\n");
}
}
}
if(@cfg_get.kazoo.presence_notify_log_body == 1)
xlog("L_INFO", "$ci|log|sent|body $(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\n");
if(@cfg_get.kazoo.presence_notify_log_resp_body == 1)
xlog("L_INFO", "$ci|log|resp|body $(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})\n");
if(@cfg_get.kazoo.presence_notify_log_to_amqp == 1) {
route(PRESENCE_NOTIFY_AMQP);
}
if(@cfg_get.kazoo.presence_notify_log_to_table == 1) {
$var(Query) = $_s(REPLACE INTO active_watchers_log (presentity_uri, watcher_username, watcher_domain, event, callid, to_user, to_domain, user_agent, time, result, sent_msg, received_msg) VALUES ("$subs(uri)", "$subs(watcher_username)", "$subs(watcher_domain)", "$subs(event)","$subs(callid)","$subs(to_user)","$subs(to_domain)", '$(subs(user_agent){s.escape.common}{s.replace,\',''}{s.replace,$$,})', $TS, $notify_reply($rs), '$(mb{s.escape.common}{s.replace,\',''}{s.replace,$$,})', '$(notify_reply($mb){s.escape.common}{s.replace,\',''}{s.replace,$$,})'));
mq_add("presence_last_notity", "$subs(callid)", "$var(Query)");
}
}
route[PRESENCE_LOG_TIMER_ROUTE]
{
$var(runloop) = 1;
while(mq_fetch("presence_last_notity") == 1 && $var(runloop) < MAX_WHILE_LOOPS) {
$var(ci) = $mqk(presence_last_notity);
xlog("L_DEBUG", "Query : $mqv(presence_last_notity)\n");
$var(sqlres) = sql_query("cb", "$mqv(presence_last_notity)");
xlog("L_DEBUG", "Query result : $var(sqlres)\n");
if($var(sqlres) < 0) {
xlog("L_ERROR", "$var(ci)|log|error updating active_watchers_log\n");
} else {
$var(nrows) = $sqlrows(cb);
xlog("L_DEBUG", "$var(ci)|log|end UPDATED $var(nrows)\n");
if($var(nrows) == 0) {
xlog("L_ERROR", "$var(ci)|log|error no rows affected when updating active_watchers_log\n");
}
}
$var(runloop) = $var(runloop) + 1;
}
}
route[PRESENCE_NOTIFY_AMQP]
{
$var(amqp_payload_request) = $_s({"Event-Category" : "presence", "Event-Name" : "notify", "Event-Package" : "$subs(event)", "Timestamp" : $TS, "Call-ID" : "$subs(callid)", "From" : "$fu", "To" : "$subs(to_user)@$subs(to_domain)", "Sent" : "$(TS{s.ftime,%Y-%m-%d %H:%M:%S})", "Body" : "Hostname : MY_HOSTNAME\r\nTimestamp : $(TS{s.ftime,%Y-%m-%d %H:%M:%S})\r\n$(mb{s.escape.common}{s.replace,\','}{s.replace,$$,})\r\nResponse\r\n$(notify_reply($mb){s.escape.common}{s.replace,\','}{s.replace,$$,})","Remote-CSeq" : $subs(remote_cseq), "Local-CSeq" : $subs(local_cseq), "Sequence" : $cs, "Version" : $subs(version), "Reply" : $notify_reply($rs) });
$var(rk) = "notify." + $(subs(to_domain){kz.encode}) + "." + $(subs(to_user){kz.encode});
kazoo_publish("omnipresence", "$var(rk)", $var(amqp_payload_request));
xlog("L_INFO", "$ci|log|sent notify callback for event $subs(event) : $tu\n");
}

+ 53
- 16
kamailio/pusher-role.cfg View File

@ -1,10 +1,11 @@
## 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;")
modparam("tm", "failure_exec_mode", 1)
route[PUSHER_ROUTE]
{
if ( (!is_method("INVITE")) || (!isflagset(FLAG_INTERNALLY_SOURCED)) || $hdr(X-KAZOO-PUSHER-Token-ID) == $null)
@ -17,6 +18,7 @@ route[PUSHER_ROUTE]
$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");
@ -29,32 +31,32 @@ route[PUSHER_ROUTE]
route[PUSHER_TO_EXTERNAL_RELAY]
{
remove_hf_re("^X-.*");
t_set_fr(0, 2000);
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, "waking the dead guy");
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");
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");
t_reply("$T_reply_code", "pusher failed");
}
}
route[PUSHER_PREPARE_PUSH]
{
if (t_newtran()) {
t_set_fr(20000, 20000);
route(PUSHER_PREPARE_PUSH_PAYLOAD);
remove_hf_re("^X-.*");
t_on_reply("EXTERNAL_REPLY");
t_on_failure("PUSHER_EXTERNAL_FAULT");
t_save_lumps();
t_set_auto_inv_100(0);
return 1;
@ -66,11 +68,15 @@ route[PUSHER_PREPARE_PUSH]
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);
@ -90,13 +96,13 @@ route[PUSHER_PREPARE_PUSH_PAYLOAD]
$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);
}
@ -126,6 +132,7 @@ route[PUSHER_ATTEMPT_REGISTRATION]
$xavp(ulattrs=>custom_channel_vars) = "{}";
$xavp(ulattrs[0]=>x_token_reg) = $hdr(X-Token-Reg);
route(SAVE_LOCATION);
exit;
} else {
xlog("L_INFO", "$ci|pusher|registration x-token-reg '$hdr(X-Token-Reg)' from header was not found\n");
}
@ -139,6 +146,7 @@ route[PUSHER_ATTEMPT_REGISTRATION]
$xavp(ulattrs=>custom_channel_vars) = "{}";
$xavp(ulattrs[0]=>x_token_reg) = $(sel(contact.uri){uri.param,x-token-reg});
route(SAVE_LOCATION);
exit;
} else {
xlog("L_INFO", "$ci|pusher|registration x-token-reg from contact uri param '$(sel(contact.uri){uri.param,x-token-reg})' was not found\n");
}
@ -152,6 +160,7 @@ route[PUSHER_ATTEMPT_REGISTRATION]
$xavp(ulattrs=>custom_channel_vars) = "{}";
$xavp(ulattrs[0]=>x_token_reg) = $(sel(contact){tobody.params}{param.value,x-token-reg});
route(SAVE_LOCATION);
exit;
} else {
xlog("L_INFO", "$ci|pusher|registration x-token-reg from contact param '$(sel(contact){tobody.params}{param.value,x-token-reg})' was not found\n");
}
@ -160,8 +169,8 @@ route[PUSHER_ATTEMPT_REGISTRATION]
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) &&
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");
@ -177,8 +186,36 @@ route[PUSHER_ON_REGISTRATION]
route[PUSHER_DELIVER_CALL]
{
if(reg_fetch_contacts("location", "$hdr(X-KAZOO-AOR)", "callee")) {
$du = $(ulc(callee=>received));
$fs = $(ulc(callee=>socket));
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");


+ 325
- 192
kamailio/registrar-role.cfg View File

@ -1,62 +1,85 @@
#### 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 0
#!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;")
modparam("htable", "htable", "auth_cache=>size=16;autoexpire=7200;REGISTRAR_S_WARM_CACHE")
####### Authentication Interface module ##########
loadmodule "auth.so"
#!ifdef OPENBTS_AUTH_ROLE
loadmodule "auth_openbts.so"
modparam("auth", "qop", "")
modparam("auth", "secret", "OPENBTS_AUTH_SECRET")
modparam("auth_openbts", "challenge_attr", "$avp(digest_challenge)")
#!endif
####### User Location Implementation module ##########
loadmodule "usrloc.so"
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", 1)
modparam("usrloc", "handle_lost_tcp", 1)
modparam("usrloc", "xavp_contact", "ulattrs")
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", "timer_interval", 30)
modparam("usrloc", "timer_procs", 1)
modparam("usrloc", "db_timer_clean", 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)
######## NAT Traversal module - signaling functions ########
#!ifdef NAT_TRAVERSAL_ROLE
#!trydef NATHELPER_LOADED
loadmodule "nathelper.so"
modparam("nathelper", "natping_interval", REGISTRAR_NAT_PING_INTERVAL)
modparam("nathelper", "ping_nated_only", 0)
modparam("nathelper", "natping_processes", REGISTRAR_NAT_PING_WORKERS)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
#!endif
####### 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)
@ -64,172 +87,236 @@ modparam("registrar", "regid_mode", 1)
modparam("registrar", "path_mode", 1)
modparam("registrar", "use_path", 1)
modparam("registrar", "received_param", "")
##modparam("registrar", "xavp_rcd", "ulrcd")
modparam("registrar", "xavp_rcd", "ulrcd")
modparam("registrar", "contact_max_size", REGISTRAR_CONTACT_MAX_SIZE)
##### handle expired registrations realtime params #####
####### 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[HANDLE_REGISTER]
{
if (is_method("REGISTER")) {
#!ifdef NAT_TRAVERSAL_ROLE
if (nat_uac_test("3")) {
xlog("L_INFO", "$ci|log|correcting NATed contact in registration\n");
force_rport();
}
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 =~ "OpenBTS"
|| $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")
)) {
setbflag(FLB_NATB);
xlog("L_DEBUG", "$ci|log|set nat pinging\n");
setbflag(FLB_NATSIPPING);
}
#!endif
route(ATTEMPT_AUTHORIZATION);
} else {
$avp(AVP_RECV_PARAM) = $su;
}
}
route[AUTHORIZATION_CHECK]
route[HANDLE_REGISTER]
{
if (!is_method("MESSAGE|NOTIFY|SUBSCRIBE|PUBLISH"))
if (!is_method("REGISTER")) {
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;
# route(ATTEMPT_AUTHORIZATION);
}
}
route[ATTEMPT_AUTHORIZATION]
{
#!ifdef PUSHER_ROLE
route(PUSHER_ATTEMPT_REGISTRATION);
#!endif
$var(nonce) = $(uuid(g){s.rm,-});
#!ifdef OPENBTS_AUTH_ROLE
if($ua =~ "OpenBTS" && $sht(auth_cache=>$Au::nonce) != $null ) {
$var(nonce) = $sht(auth_cache=>$Au::nonce);
if($sel(cfg_get.kazoo.registrar_failover) == 1) {
xlog("L_INFO", "$ci|log|register|forcing failover\n");
update_stat("registrar:force_failover", "+1");
drop;
}
#!endif
$xavp(regcfg=>match_received) = $su;
if($sht(auth_cache=>$Au) != $null && registered("location", "$rz:$Au", 2, 1) == 1 && $(xavp(ulattrs=>custom_channel_vars){s.len}) > 1) {
$var(password) = $sht(auth_cache=>$Au);
route(SAVE_LOCATION);
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( is_present_hf("Authorization")) {
route(KAZOO_AUTHORIZATION);
if($td =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}" ||
$fd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") {
xlog("L_INFO", "$ci|log|register|invalid domain\n");
update_stat("registrar:ip_realm", "+1");
drop;
}
#!ifdef OPENBTS_AUTH_ROLE
if($ua =~ "OpenBTS") {
openbts_auth_challenge("$fd", "$var(nonce)");
} else {
#!endif
auth_challenge("$fd", "0");
#!ifdef OPENBTS_AUTH_ROLE
if($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;
}
}
#!endif
xlog("L_INFO", "$ci|end|issued auth challenge to new registration for $fu $si:$sp\n");
exit;
}
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;
}
route[KAZOO_AUTHORIZATION]
{
$var(nonce) = $adn;
$var(amqp_payload_request) = $_s({"Event-Category" : "directory" , "Event-Name" : "authn_req", "Method" : "REGISTER", "Auth-Nonce" : "$adn", "Auth-Realm" : "$fd", "Auth-User" : "$fU", "From" : "$fu", "To" : "$tu", "Orig-IP" : "$si", "Orig-Port" : "$sp", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci" });
$var(amqp_routing_key) = "authn.req." + $(fd{kz.encode});
$avp(kz_timeout) = 2500;
if (!t_newtran()) {
sl_reply_error();
exit();
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(kazoo_async_query("callmgr", $var(amqp_routing_key), $var(amqp_payload_request), "KAZOO_AUTHORIZATION_OK", "KAZOO_AUTHORIZATION_ERROR") != 1) {
xlog("L_INFO", "$ci|log|failed to send Kazoo query for authentication credentials for $Au $si:$sp\n");
append_to_reply("Retry-After: 60\r\n");
send_reply("503", "Retry Later");
exit;
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();
}
}
route[KAZOO_AUTHORIZATION_OK]
failure_route[KZ_AUTHORIZATION_TIMEOUT]
{
$var(password) = $(kzR{kz.json,Auth-Password});
$var(nonce) = $adn;
#!ifdef OPENBTS_AUTH_ROLE
if( $(kzR{kz.json,Auth-Nonce}) != "" && $var(nonce) != $(kzR{kz.json,Auth-Nonce})) {
xlog("L_INFO", "$ci|log|nonce replace $var(nonce) with $(kzR{kz.json,Auth-Nonce})\n");
$var(nonce) = $(kzR{kz.json,Auth-Nonce});
$sht(auth_cache=>$Au::nonce) = $var(nonce);
}
#!endif
if( $(kzR{kz.json,Event-Name}) == "authn_err" ) {
auth_challenge("$fd", "0");
xlog("L_INFO", "$ci|end|issued auth challenge to registration attempt for $Au $si:$sp\n");
exit;
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 {
$xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars});
xlog("L_INFO", "$ci|log|authenticating $Au via Kazoo query response\n");
route(CHECK_AUTHORIZATION);
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();
}
route[KAZOO_AUTHORIZATION_ERROR]
onreply_route[KZ_AUTHORIZATION_REPLY]
{
xlog("L_INFO", "$ci|log|failed to query Kazoo for authentication credentials for $Au $si:$sp\n");
append_to_reply("Retry-After: 60\r\n");
send_reply("503", "Retry Later");
exit;
$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($ua =~ "OpenBTS") {
xlog("L_INFO", "$ci|end|OPENBTS attempt for $Au $si:$sp\n");
} else {
if($var(password) == $null || $var(password) == "") {
auth_challenge("$fd", "0");
xlog("L_INFO", "$ci|end|issued auth challenge to registration attempt for $Au $si:$sp\n");
exit;
}
if (!pv_auth_check("$fd", "$var(password)", "0", "0")) {
#!ifdef ANTIFLOOD_ROLE
route(ANITFLOOD_FAILED_AUTH);
#!endif
if (!pv_auth_check("$fd", "$var(password)", "0", "0")) {
#!ifdef ANTIFLOOD_ROLE
route(ANITFLOOD_FAILED_AUTH);
#!endif
auth_challenge("$fd", "0");
xlog("L_WARNING", "$ci|end|issued auth challenge to failed registration attempt for $Au from IP $si:$sp\n");
exit;
}
xlog("L_WARNING", "$ci|end|issuing auth challenge to failed registration attempt for $Au from IP $si:$sp\n");
update_stat("registrar:challenge", "+1");
auth_challenge("$fd", "5");
exit;
}
#!ifdef ANTIFLOOD_ROLE
@ -239,26 +326,27 @@ route[CHECK_AUTHORIZATION]
# user authenticated - remove auth header
consume_credentials();
$xavp(ulattrs=>custom_channel_vars) = $(kzR{kz.json,Custom-Channel-Vars});
$xavp(ulattrs[0]=>token) = $_s($(kzR{kz.json,Custom-Channel-Vars.Authorizing-ID})@$(kzR{kz.json,Custom-Channel-Vars.Account-ID}));
route(SAVE_LOCATION);
}
route[SAVE_LOCATION]
{
if ($sht(auth_cache=>$Au) == $null) {
if ($sht(auth_cache=>$Au) == $null && $var(password) != $null) {
xlog("L_INFO", "$ci|log|caching sip credentials for $Au\n");
};
$sht(auth_cache=>$Au) = $var(password);
#!ifdef OPENBTS_AUTH_ROLE
if($ua =~ "OpenBTS") {
$sht(auth_cache=>$Au::nonce) = $var(nonce);
}
#!endif
route(REGISTRAR_NAT_FLAGS);
$var(save_result) = save("location", "0x04");
if($var(save_result) == -1) {
auth_challenge("$fd", "0");
xlog("L_INFO", "$ci|end|issued auth challenge after failed attempt to save contact for $Au $si:$sp\n");
if($var(save_result) < 0) {
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) {
@ -268,34 +356,17 @@ route[SAVE_LOCATION]
}
}
if((int)@contact.expires) {
$var(expires) = @contact.expires;
if($var(save_result) == 3) {
$var(expires) = 0;
} else {
if(is_present_hf("Expires")) {
$var(expires) = $hdr(Expires);
} else {
$var(expires) = REGISTRAR_MIN_EXPIRES;
}
$var(expires) = $xavp(ulrcd=>expires);
}
## this is what we should be using
## but ulrcd seems to have a weird leak
## if($var(save_result) == 3) {
## $var(expires) = 0;
## } else {
## $var(expires) = $xavp(ulrcd=>expires);
## }
if($var(expires) == 0) {
xlog("L_INFO", "$ci|end|unregister request from $Au $si:$sp\n");
$var(Status) = "Unregistered";
} else {
$var(Status) = "Registered";
if($var(expires) < REGISTRAR_MIN_EXPIRES) {
$var(expires) = REGISTRAR_MIN_EXPIRES;
} else if($var(expires) > REGISTRAR_MAX_EXPIRES) {
$var(expires) = REGISTRAR_MAX_EXPIRES;
}
}
$var(ip) = $Ri;
@ -340,17 +411,20 @@ route[SAVE_LOCATION]
$var(AdvIP) = "[" + $RAi + "]";
}
$var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "$var(Status)", "Event-Timestamp" : $TS, "Expires" : $(var(expires){s.int}), "First-Registration" : $var(new_reg), "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "Realm" : "$fd", "Username" : "$fU", "From-User" : "$fU", "From-Host" : "$fd", "To-User" : "$tU", "To-Host" : "$td", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), "Proxy-Path" : "sip:$var(ip):$var(port)", "Proxy-Protocol" : "$proto", "Proxy-IP" : "$var(AdvIP)", "Proxy-Port" : "$RAp", "Source-IP": "$si", "Source-Port": "$sp" });
$var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "$var(Status)", "Event-Timestamp" : $TS, "Expires" : $(var(expires){s.int}), "First-Registration" : $var(new_reg), "Contact" : "$(ct{s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ci", "Realm" : "$fd", "Username" : "$fU", "From-User" : "$fU", "From-Host" : "$fd", "To-User" : "$tU", "To-Host" : "$td", "User-Agent" : "$(ua{s.escape.common}{s.replace,\','}{s.replace,$$,})" , "Custom-Channel-Vars" : $xavp(ulattrs=>custom_channel_vars), "Proxy-Path" : "sip:MY_IP_ADDRESS:$var(port)", "Proxy-Protocol" : "$proto", "Proxy-IP" : "$var(AdvIP)", "Proxy-Port" : "$RAp", "Source-IP": "$si", "Source-Port": "$sp" });
$var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $(fU{kz.encode});
kazoo_publish("registrar", $var(amqp_routing_key), $var(amqp_payload_request));
xlog("L_INFO", "$ci|end|successful $(var(Status){s.tolower}) with contact : $ct\n");
xlog("L_INFO", "$ci|end|successful $(var(Status){s.tolower}) with contact : $ct : $var(expires)\n");
#!ifdef PUSHER_ROLE
route(PUSHER_ON_REGISTRATION);
#!endif
#!ifdef KEEPALIVE_ROLE
route(KEEPALIVE_ON_REGISTRATION);
#!endif
exit;
}
@ -364,6 +438,10 @@ event_route[kazoo:consumer-event-directory-reg-flush]
$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))) {
@ -379,8 +457,81 @@ event_route[kazoo:consumer-event-directory-reg-flush]
#!endif
}
route[REGISTRAR_BINDINGS]
{
#!import_file "registrar-custom-bindings.cfg"
#!ifndef REGISTRAR_CUSTOM_BINDINGS
$var(payload) = $_s({"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") {
@ -391,25 +542,25 @@ event_route[usrloc:contact-expired]
{
case "ws":
case "wss":
if(@cfg_get.kazoo.registrar_handle_expired_ws == 1) {
if($sel(cfg_get.kazoo.registrar_handle_expired_ws) == 1) {
$var(handle) = 1;
}
break;
case "tls":
if(@cfg_get.kazoo.registrar_handle_expired_tls == 1) {
if($sel(cfg_get.kazoo.registrar_handle_expired_tls) == 1) {
$var(handle) = 1;
}
break;
case "tcp":
if(@cfg_get.kazoo.registrar_handle_expired_tcp == 1) {
if($sel(cfg_get.kazoo.registrar_handle_expired_tcp) == 1) {
$var(handle) = 1;
}
break;
case "udp":
if(@cfg_get.kazoo.registrar_handle_expired_udp == 1) {
if($sel(cfg_get.kazoo.registrar_handle_expired_udp) == 1) {
$var(handle) = 1;
}
break;
@ -425,27 +576,9 @@ event_route[usrloc:contact-expired]
$var(amqp_payload_request) = $_s({"Event-Category" : "directory", "Event-Name" : "reg_success", "Status" : "Unregistered", "Event-Timestamp" : $TS, "Expires" : 0, "First-Registration" : false, "Contact" : "$(ulc(exp=>addr){s.escape.common}{s.replace,\','}{s.replace,$$,})", "Call-ID" : "$ulc(exp=>callid)", "Realm" : "$var(domain)", "Username" : "$var(username)", "From-User" : "$var(username)", "From-Host" : "$var(domain)", "To-User" : "$var(username)", "To-Host" : "$var(domain)", "Proxy-Path" : "$ulc(exp=>socket)", "User-Agent" : "$(ulc(exp=>user_agent){s.escape.common}{s.replace,\','}{s.replace,$$,})"});
$var(amqp_routing_key) = "registration.success." + $(var(domain){kz.encode}) + "." + $(var(username){kz.encode});
kazoo_publish("registrar", $var(amqp_routing_key), $var(amqp_payload_request));
xlog("L_INFO", "$ulc(exp=>callid)|expired|notified kazoo about removed registration with contact : $ulc(exp=>addr)\n");
} else {
xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration with contact : $ulc(exp=>addr)\n");
xlog("L_INFO", "$ulc(exp=>callid)|expired|notified registration removal with contact : $ulc(exp=>addr)\n");
}
}
route[REGISTRAR_BINDINGS]
{
#!import_file "registrar-custom-bindings.cfg"
#!ifndef REGISTRAR_CUSTOM_BINDINGS
$var(payload) = "{ 'exchange' : 'registrar' , 'type' : 'topic', 'queue' : 'registrar-flush-MY_HOSTNAME', 'routing' : 'registration.flush.*', 'federate' : 1 }";
kazoo_subscribe("$var(payload)");
#!endif
#!ifdef REGISTRAR_SYNC_ROLE
route(REGISTRAR_SYNC_BINDINGS);
#!endif
xlog("L_INFO", "$ulc(exp=>callid)|expired|removed registration for $ulc(exp=>aor) with contact : $ulc(exp=>addr)\n");
}
#!ifdef REGISTRAR_SYNC_ROLE


+ 1
- 1
kamailio/registrar-sync-role.cfg View File

@ -26,6 +26,6 @@ event_route[kazoo:consumer-event-directory-reg-sync]
route[REGISTRAR_SYNC_BINDINGS]
{
$var(payload) = "{ 'exchange' : 'registrar' , 'type' : 'topic', 'queue' : 'registrar-sync-MY_HOSTNAME', 'routing' : 'registration.sync' }";
$var(payload) = $_s({"exchange": "registrar", "type": "topic", "queue": "registrar-sync-MY_HOSTNAME", "routing": "registration.sync"});
kazoo_subscribe("$var(payload)");
}

+ 67
- 0
kamailio/sanity.cfg View File

@ -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;
}
}

+ 49
- 12
kamailio/sip_trace-role.cfg View File

@ -1,11 +1,26 @@
#################################
## 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 configration examples at runtime
## 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_INTERNAL descr "activates tracing from external sources"
kazoo.trace_internal = KZ_TRACE_EXTERNAL descr "activates tracing from internal sources"
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"
@ -15,7 +30,7 @@ kazoo.trace_external_outgoing = KZ_TRACE_EXTERNAL_OUTGOING descr "traces the out
####### Siptrace module ##########
loadmodule "siptrace.so"
modparam("siptrace", "duplicate_uri", "SIP_TRACE_URI")
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)
@ -26,33 +41,55 @@ modparam("siptrace", "trace_on", KZ_TRACE)
route[SIP_TRACE_INTERNAL]
{
if(@cfg_get.kazoo.trace_internal == 0) {
if($sel(cfg_get.kazoo.trace_internal) == 0) {
return;
}
if(@cfg_get.kazoo.trace_internal_incoming == 1) {
if($sel(cfg_get.kazoo.trace_internal_incoming) == 1) {
sip_trace();
}
if(@cfg_get.kazoo.trace_internal_outgoing == 1) {
if($sel(cfg_get.kazoo.trace_internal_outgoing) == 1) {
setflag(FLAG_SIP_TRACE);
}
}
route[SIP_TRACE_EXTERNAL]
{
if(@cfg_get.kazoo.trace_external == 0) {
if($sel(cfg_get.kazoo.trace_external) == 0) {
return;
}
if(@cfg_get.kazoo.trace_external_incoming == 1) {
if($sel(cfg_get.kazoo.trace_external_incoming) == 1) {
sip_trace();
}
if(@cfg_get.kazoo.trace_external_outgoing == 1) {
if($sel(cfg_get.kazoo.trace_external_outgoing) == 1) {
setflag(FLAG_SIP_TRACE);
}
}
route[SEND_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_INTERNALLY_SOURCED)) {
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);


+ 5
- 1
kamailio/tls-role.cfg View File

@ -6,4 +6,8 @@ listen=TLS_ALG_SIP
####### TLS Parameters #########
loadmodule "tls.so"
modparam("tls", "config", "/etc/kazoo/kamailio/tls.cfg")
modparam("tls", "low_mem_threshold1", 0)
modparam("tls", "low_mem_threshold1", 1)
modparam("tls", "low_mem_threshold2", 1)
modparam("debugger", "mod_level", "tls=1")

+ 71
- 50
kamailio/websockets-role.cfg View File

@ -1,10 +1,8 @@
tcp_accept_no_cl=yes
listen=TCP_WS
listen=UDP_WS_SIP
#!ifdef TLS_ROLE
listen=TLS_WSS
listen=UDP_WSS_SIP
#!endif
######## NAT Traversal module - signaling functions ########
@ -14,53 +12,37 @@ loadmodule "nathelper.so"
#!endif
######## Generic Hash Table container in shared memory ########
modparam("htable", "htable", "websockets=>size=16;autoexpire=7200;initval=0")
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", 0)
modparam("websocket", "keepalive_timeout", 30)
modparam("websocket", "keepalive_processes", 1)
modparam("websocket", "keepalive_interval", 1)
modparam("websocket", "ping_application_data", "Kazoo encourages you to keep alive")
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 ########
route[HANDLE_WEBSOCKETS]
{
# Do NAT traversal stuff for requests from a WebSocket
# connection - even if it is not behind a NAT!
# This won't be needed in the future if Kamailio and the
# WebSocket client support Outbound and Path.
if (nat_uac_test(64)) {
xlog("L_INFO", "$ci|log|this is a websocket request\n");
force_rport();
if (is_method("REGISTER")) {
fix_nated_register();
} else {
if (!add_contact_alias()) {
xlog("L_INFO", "$ci|stop|error aliasing contact <$ct>\n");
sl_send_reply("400", "Bad Request");
exit;
}
}
}
}
route[NAT_WEBSOCKETS_CORRECT]
{
# Do NAT traversal stuff for replies to a WebSocket connection
# - even if it is not behind a NAT!
# This won't be needed in the future if Kamailio and the
# WebSocket client support Outbound and Path.
if (nat_uac_test(64)) {
xlog("L_INFO", "$ci|log|this is a websocket request\n");
add_contact_alias();
}
}
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]
{
@ -93,21 +75,54 @@ event_route[xhttp:request]
#!ifdef MY_WEBSOCKET_DOMAIN
if (!($hdr(Origin) =~ "MY_WEBSOCKET_DOMAIN")) {
xlog("L_INFO", "websocket|log|rejecting HTTP request with unknown origin $hdr(Origin) from $si:$sp\n");
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($sht(websockets=>$si::count) > 50) {
xlog("L_WARN", "websocket|log|$si:$sp is at the maximum allowable sockets per IP, rejecting request for another websocket\n");
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(shtinc) = $shtinc(websockets=>$si::count);
xlog("L_INFO", "websocket|log|opened websocket $var(count) of 50 for $si:$sp\n");
$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;
}
@ -115,12 +130,18 @@ event_route[xhttp:request]
xhttp_reply("404", "Not Found", "", "");
}
event_route[websocket:closed] {
$var(shtdec) = $shtdec(websockets=>$si::count);
if ($sht(websockets=>$si::count) < 1) {
xlog("L_INFO", "websocket|log|$si:$sp closed last websocket to that IP\n");
sht_rm_name_re("websockets=>$(si{re.subst,/\\./\\\\./g})::.*");
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 from $si:$sp, $var(count) remaining from that IP\n");
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;
}

BIN
kazoo_module/kazoo.so View File


+ 281
- 109
system/sbin/kazoo-kamailio View File

@ -1,20 +1,82 @@
#!/bin/bash
if [ -f /etc/default/kamailio ]; then
. /etc/default/kamailio
. /etc/default/kamailio
fi
if [ -f /etc/sysconfig/kamailio ]; then
. /etc/sysconfig/kamailio
. /etc/sysconfig/kamailio
fi
if [ -f /etc/kazoo/kamailio/options ]; then
. /etc/kazoo/kamailio/options
fi
is_ipaddress ()
{
if [ $(echo $1 | grep -o '\.' | wc -l) -ne 3 ]; then
return 1
elif [ $(echo $1 | tr '.' ' ' | wc -w) -ne 4 ]; then
return 1
else
for OCTET in $(echo $1 | tr '.' ' '); do
if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
return 1
elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
return 1
fi
done
fi
return 0
}
RETVAL=1
USER=${KAMAILIO_USER:-kamailio}
GROUP=${KAMAILIO_GROUP:-kamailio}
GROUP=${KAMAILIO_GROUP:-daemon}
BIN_FILE=${KAMAILIO_BIN:-/usr/sbin/kamailio}
PID_FILE=${KAMAILIO_PID:-/var/run/kamailio/kazoo-kamailio.pid}
CFG_FILE=${KAMAILIO_CONFIG:-/etc/kazoo/kamailio/kamailio.cfg}
CFG_DIR=$(dirname ${CFG_FILE})
export DB_SCRIPT_DIR=${KAMAILIO_DB_SCRIPT_DIR:-${CFG_DIR}/db_scripts}
export DB_LOCATION=${KAMAILIO_DB_LOCATION:-/etc/kazoo/kamailio/db}
export KAMAILIO_SHARE_DIR=${KAMAILIO_SHARE_DIR:-/usr/share/kamailio}
export HOME=${KAMAILIO_HOME:-/var/run/kamailio}
RAM_DISK_SIZE=${RAM_DISK_SIZE:-256m}
RAM_DISK_FREE_SIZE_PERC=${RAM_DISK_FREE_SIZE:-30}
RAM_DISK_ENABLED=${RAM_DISK_ENABLED:-false}
EXTRA_OPTIONS=${EXTRA_OPTIONS:-"-x tlsf -w /tmp"}
LOCAL_IP_INTERFACE=${LOCAL_IP_INTERFACE:-none}
MY_LOCAL_IP=${LISTENER_LOCAL_IP:-none}
MY_PUBLIC_IP=${LISTENER_PUBLIC_IP:-none}
if [[ "${MY_LOCAL_IP}" != "disable" ]]; then
if [[ "${MY_LOCAL_IP}" != "none" ]]; then
EXTRA_OPTIONS+=" -A MY_LOCAL_IP=${MY_LOCAL_IP} -A LOCAL_IP_ARG"
else
if [[ "${LOCAL_IP_INTERFACE}" != "none" ]]; then
MY_LOCAL_IP=$(ip -4 addr show ${LOCAL_IP_INTERFACE} | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
else
MY_LOCAL_IP=$(ip route get 8.8.8.8 2> /dev/null | awk '{print ""$7""; exit}')
fi
if is_ipaddress ${MY_LOCAL_IP}; then
EXTRA_OPTIONS+=" -A MY_LOCAL_IP=${MY_LOCAL_IP} -A LOCAL_IP_AUTO"
fi
fi
fi
if [[ "${MY_PUBLIC_IP}" != "disable" ]]; then
if [[ "${MY_PUBLIC_IP}" != "none" ]]; then
EXTRA_OPTIONS+=" -A MY_PUBLIC_IP=${MY_PUBLIC_IP} -A PUBLIC_IP_ARG"
else
MY_PUBLIC_IP=$(dig @ns1.google.com TXT o-o.myaddr.l.google.com +short -4 2> /dev/null | sed s/\"//g )
if [[ ! -z ${MY_PUBLIC_IP} ]]; then
if is_ipaddress ${MY_PUBLIC_IP}; then
EXTRA_OPTIONS+=" -A MY_PUBLIC_IP=${MY_PUBLIC_IP} -A PUBLIC_IP_AUTO"
fi
fi
fi
fi
SHM_MEMORY=$((`echo $SHM_MEMORY | sed -e 's/[^0-9]//g'`))
PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`))
@ -22,159 +84,269 @@ PKG_MEMORY=$((`echo $PKG_MEMORY | sed -e 's/[^0-9]//g'`))
[ $PKG_MEMORY -le 0 ] && PKG_MEMORY=8
if test "$DUMP_CORE" = "yes" ; then
ulimit -c unlimited
ulimit -c unlimited
fi
prepare() {
mkdir -p /var/run/kamailio
chown -R ${USER} /var/run/kamailio
if [ -e ${PID_FILE} ]; then
rm -rf ${PID_FILE}
fi
if ram_disk_enabled; then
if ! mount_point_exists; then
if [ -f /etc/kazoo/kamailio/kazoo.db ]; then
mv /etc/kazoo/kamailio/db /etc/kazoo/kamailio/db-backup
fi
mount -t tmpfs -o size=256m tmpfs /etc/kazoo/kamailio/db
if [ -f /etc/kazoo/kamailio/db-backup/kazoo.db ]; then
cp -a /etc/kazoo/kamailio/db-backup/* /etc/kazoo/kamailio/db/
fi
fi
fi
if [ ! -f /etc/kazoo/kamailio/db/kazoo.db ]; then
mkdir -p /var/run/kamailio
chown -R ${USER} /var/run/kamailio
if [ -e ${PID_FILE} ]; then
rm -rf ${PID_FILE}
fi
if ram_disk_enabled; then
if ! mount_point_exists; then
if [ -d ${DB_LOCATION}/../db-backup-temp ]; then
rm -rf ${DB_LOCATION}/../db-backup-temp
fi
if [ -d ${DB_LOCATION} ]; then
mkdir -p ${DB_LOCATION}/../db-backup-temp
cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup-temp/
rm -rf ${DB_LOCATION}
fi
mkdir -p ${DB_LOCATION}
mount -t tmpfs -o size=${RAM_DISK_SIZE} tmpfs ${DB_LOCATION}
if [ -f ${DB_LOCATION}/../db-backup-temp/kazoo.db ]; then
cp -f ${DB_LOCATION}/../db-backup-temp/* ${DB_LOCATION}/
fi
if [ -d ${DB_LOCATION}/../db-backup-temp ]; then
rm -rf ${DB_LOCATION}/../db-backup-temp
fi
else
### check ramdisk size
mountcurrentsize=$(mount_point_size)
mountwantedsize=$(convert_size ${RAM_DISK_SIZE})
if [ $mountcurrentsize -lt $mountwantedsize ]; then
echo "current size is $mountcurrentsize is below wanted size of $mountwantedsize, remounting"
rm -rf ${DB_LOCATION}/../db-backup-temp
mkdir -p ${DB_LOCATION}/../db-backup-temp
cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup-temp/
umount ${DB_LOCATION}
rm -rf ${DB_LOCATION}
mkdir -p ${DB_LOCATION}
mount -t tmpfs -o size=${RAM_DISK_SIZE} tmpfs ${DB_LOCATION}
cp -f ${DB_LOCATION}/../db-backup-temp/* ${DB_LOCATION}/
rm -rf ${DB_LOCATION}/../db-backup-temp
elif [ $mountcurrentsize -gt $mountwantedsize ]; then
# check if it fits
echo "wanted size of $mountwantedsize is below current size of $mountcurrentsize , checking sizes"
mountusedsize=$(mount_point_used_size)
requiredsize=$(( mountusedsize * (100 + ${RAM_DISK_FREE_SIZE_PERC}) / 100))
if [ $requiredsize -gt $mountwantedsize ]; then
echo "wanted size of $mountwantedsize doesn't have enough space for required size of $requiredsize"
mountwantedsize=$requiredsize
else
echo "resizing from $mountcurrentsize to $mountwantedsize"
rm -rf ${DB_LOCATION}/../db-backup-temp
mkdir -p ${DB_LOCATION}/../db-backup-temp
cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup-temp/
umount ${DB_LOCATION}
rm -rf ${DB_LOCATION}
mkdir -p ${DB_LOCATION}
mount -t tmpfs -o size=$mountwantedsize tmpfs ${DB_LOCATION}
cp -f ${DB_LOCATION}/../db-backup-temp/* ${DB_LOCATION}/
rm -rf ${DB_LOCATION}/../db-backup-temp
fi
fi
fi
else
if mount_point_exists; then
if [ -d ${DB_LOCATION}/../db-backup-temp ]; then
rm -rf ${DB_LOCATION}/../db-backup-temp
fi
mkdir -p ${DB_LOCATION}/../db-backup-temp
cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup-temp/
umount ${DB_LOCATION}
rm -rf ${DB_LOCATION}
mkdir -p ${DB_LOCATION}
cp -f ${DB_LOCATION}/../db-backup-temp/* ${DB_LOCATION}/
fi
fi
if [ ! -f ${DB_LOCATION}/kazoo.db ]; then
init_database
fi
chown -R ${USER} /etc/kazoo/kamailio/db
RETVAL=$?
else
check_database
fi
chown -R ${USER} ${DB_LOCATION}
RETVAL=$?
}
ram_disk_enabled() {
grep -e "enable_ram_disk = true" /etc/kazoo/kamailio/local.cfg &> /dev/null
return $?
grep -e "enable_ram_disk = true" ${CFG_DIR}/local.cfg &> /dev/null
config_enabled=$?
if [[ $RAM_DISK_ENABLED == "true" ]] || [[ $config_enabled -eq 0 ]]; then
return 0
else
return 1
fi
}
mount_point_exists() {
mount | grep /etc/kazoo/kamailio/db &> /dev/null
return $?
mount | grep $(readlink -f ${DB_LOCATION}) &> /dev/null
return $?
}
mount_point_size() {
echo $(df --block-size=1 | grep $(readlink -f ${DB_LOCATION}) | tr -s ' ' | cut -d ' ' --fields=2)
}
mount_point_used_size() {
echo $(df --block-size=1 | grep $(readlink -f ${DB_LOCATION}) | tr -s ' ' | cut -d ' ' --fields=3)
}
mount_point_free_size() {
echo $(df --block-size=1 | grep $(readlink -f ${DB_LOCATION}) | tr -s ' ' | cut -d ' ' --fields=4)
}
convert_size() {
echo "$1" | awk \
'BEGIN{IGNORECASE = 1}
function printpower(n,b,p) {printf "%u\n", n*b^p; next}
/[0-9]$/{print $1;next};
/K(iB)?$/{printpower($1, 2, 10)};
/M(iB)?$/{printpower($1, 2, 20)};
/G(iB)?$/{printpower($1, 2, 30)};
/T(iB)?$/{printpower($1, 2, 40)};
/KB$/{ printpower($1, 10, 3)};
/MB$/{ printpower($1, 10, 6)};
/GB$/{ printpower($1, 10, 9)};
/TB$/{ printpower($1, 10, 12)}'
}
init_database() {
/etc/kazoo/kamailio/db_scripts/create-kazoodb-sql.sh
${DB_SCRIPT_DIR}/create-kazoodb-sql.sh
check_database
}
check_database() {
${DB_SCRIPT_DIR}/check-kazoodb-sql.sh
}
start() {
cd ${HOME}
cd ${HOME}
check_config
if [ ${RETVAL} -ne 0 ]; then
echo "check config failed on starting Kamailio!"
return
fi
check_config
check_fork
check_fork
if [ ${RETVAL} -ne 0 ]; then
echo "check fork failed on starting Kamailio!"
return
fi
if [ "$(whoami)" == "${USER}" ]; then
set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} ${EXTRA_OPTIONS} "$@"
exec "$@"
else
set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} -u ${USER} -g ${GROUP} ${EXTRA_OPTIONS} "$@"
runuser -s /bin/bash ${USER} -c "$*"
fi
RETVAL=$?
if [ "$(whoami)" == "${USER}" ]; then
set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} ${EXTRA_OPTIONS} "$@"
echo "running: exec $@"
exec "$@"
else
set -- ${BIN_FILE} -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} -u ${USER} -g ${GROUP} ${EXTRA_OPTIONS} "$@"
echo "running -s /bin/bash runuser ${USER} -c $*"
runuser -s /bin/bash ${USER} -c "$*"
fi
RETVAL=$?
if [ ${RETVAL} -ne 0 ]; then
echo "Failed to start Kamailio!"
RETVAL=1
fi
if [ ${RETVAL} -ne 0 ]; then
echo "Failed to start Kamailio!"
RETVAL=1
fi
}
stop() {
killall ${BIN_FILE}
RETVAL=$?
if mount_point_exists; then
if [ -f /etc/kazoo/kamailio/kazoo.db ]; then
mv /etc/kazoo/kamailio/db /etc/kazoo/kamailio/db-backup
fi
fi
kamcmd core.kill
RETVAL=$?
if mount_point_exists; then
mkdir -p ${DB_LOCATION}/../db-backup
cp -f ${DB_LOCATION}/* ${DB_LOCATION}/../db-backup/
fi
}
restart() {
stop
start
stop
start
}
reset-restart() {
cd /etc/kazoo/kamailio/dbtext/
stop
head -n1 active_watchers > active_watchers.tmp
mv -f active_watchers.tmp active_watchers
cd /etc/kazoo/kamailio/dbtext/
stop
head -n1 watchers > watchers.tmp
mv -f watchers.tmp watchers
chown kamailio:daemon *
head -n1 presentity > presentity.tmp
mv -f presentity.tmp presentity
chown kamailio:daemon *
start
start
}
status() {
kamcmd dispatcher.list
RETVAL=$?
kamcmd dispatcher.list
RETVAL=$?
}
# Do not start kamailio if fork=no is set in the config file
# otherwise the boot process will just stop
check_fork ()
{
if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFG_FILE; then
echo "WARNING: fork=no specified in config file"
exit 1
fi
if grep -q "^[[:space:]]*fork[[:space:]]*=[[:space:]]*no.*" $CFG_FILE; then
echo "WARNING: fork=no specified in config file"
exit 1
fi
}
check_config ()
{
local ERRORS=$($BIN_FILE -c -f ${CFG_FILE} 2>&1 > /dev/null)
RETVAL=$?
if [ ${RETVAL} -ne 0 ]; then
echo "ERROR: Invalid configuration file ${CFG_FILE}!"
echo -e "\n${ERRORS}\n"
else
echo "No errors found in ${CFG_FILE}"
fi
ERRORS="$($BIN_FILE -c -f ${CFG_FILE} -m ${SHM_MEMORY} -M ${PKG_MEMORY} ${EXTRA_OPTIONS} "$@" 2>&1 > /dev/null)"
RETVAL=$?
if [ ${RETVAL} -ne 0 ]; then
echo "ERROR: Invalid configuration file ${CFG_FILE}!"
echo -e "\n${ERRORS}\n"
else
echo "No errors found in ${CFG_FILE}"
fi
}
case "$1" in
prepare)
prepare
;;
background)
shift
start $@
;;
start)
shift
start -DD $@
;;
stop)
stop
;;
restart)
restart
;;
reset-restart)
reset-restart
;;
status)
status
;;
check)
check_config
;;
*)
echo $"Usage: $0 {prepare|start|background|stop|restart|reset-restart|status|check|pid}"
prepare)
prepare
;;
background)
shift
start $@
;;
foreground)
shift
start -E -DD $@
;;
start)
shift
start -DD $@
;;
stop)
stop
;;
restart)
restart
;;
reset-restart)
reset-restart
;;
status)
status
;;
check)
check_config
;;
boot)
shift
prepare
start $@
;;
boot-foreground)
shift
prepare
start -E -DD $@
;;
*)
echo $"Usage: $0 {prepare|start|background|foreground|boot|boot-foreground|stop|restart|reset-restart|status|check|pid}"
esac
exit ${RETVAL}

Loading…
Cancel
Save