This is a step by step tutorial about how to install and maintain Kamailio SIP Server version 4.0.x using the sources downloaded from GIT repository - the choice for those willing to write code for Kamailio or to try the new features to be released in the future with the next major stable version.

This document focuses on Kamailio v4.0.x with MySQL support, using a Debian unstable system.

The first version in release series 4.0 is 4.0.0, 4.0.x refers to the most recent version released at some point in time that starts with 4.0.

Note that Kamailio provides APT repositories for several Debian/Ubuntu releases, you can use them to do the install from .deb packages, see:

 

Notes on Kamailio vs SER

 

Since version 4.0.0, Kamailio and SER integration was fully completed, there are no more duplicated modules and a single database schema. Default flavour is kamailio, setting this name to the application and database. SER flavour can be compiled using make command line options (practically, flavour system is now just about naming the application and related components).

 

1. Prerequisites

 

To be able to follow the guidelines from this document you need root access.

The following packages are required before proceeding to the next steps.

  • git client: apt-get install git-core - it is recommended to have a recent version, if your Linux distro has an old version, you can download newer one from: http://git-scm.com/
  • gcc compiler: apt-get install gcc
  • flex - apt-get install flex
  • bison - apt-get install bison
  • libmysqlclient-dev - apt-get install libmysqlclient-dev
  • make - apt-get install make
  • if you want to enable more modules, some of them require extra libraries:
    • libssl - apt-get install libssl-dev
    • libcurl - apt-get install libcurl4-openssl-dev
    • libxml2 - apt-get install libxml2-dev
    • libpcre3 - apt-get install libpcre3-dev

 

2. Getting sources from GIT

 

First of all, you have to create a directory on the file system where the sources will be stored.

  mkdir -p /usr/local/src/kamailio-4.0
  cd /usr/local/src/kamailio-4.0

Download the sources from GIT using the following commands.

  git clone --depth 1 --no-single-branch git://git.sip-router.org/sip-router kamailio
  cd kamailio
  git checkout -b 4.0 origin/4.0

Note: if your git client version does not support –no-single-branch command line parameter, then just remove it.

 

3.Tuning Makefiles

 

The first step is to generate config files for build system.

  make cfg

Next step is to enable the MySQL module. Edit modules.lst file:

  nano -w modules.lst

Add db_mysql to the variable include_modules.

include_modules= db_mysql websocket

Save the modules.lst and exit.

NOTE: this is one mechanism to enable modules which are not compiled by default, such as lcr, dialplan, presence – add the modules toinclude_modules variable inside the modules.lst file.

Alternative is to set 'include_modules' variable to specify what extra modules to be included for compilation when building Makefile cfg:

make include_modules="db_mysql" cfg

If you want to install everything in one directory (so you can delete all installed files at once), say /usr/local/kamailio-3.3, then set PREFIX variable to the install path in 'make cfg …' command:

make PREFIX="/usr/local/kamailio-4.0" include_modules="db_mysql" cfg

If you set this PREFIX you have to change most of the paths below from '/usr/local/…' to '/usr/local/kamailio-4.0/…'.

More hints about Makefile system at:

 

4. Compile Kamailio

 

Once you added the mysql module to the list of enabled modules, you can compile Kamailio:

  make all

You can get full compile flags output using:

  make Q=0 all

 

5. Install Kamailio

 

When the compilation is ready, install Kamailio with the following command:

  make install

 

6. What and where was installed

 

The binaries and executable scripts were installed in:

  /usr/local/sbin

These are:

  • kamailio - Kamailio SIP server
  • kamdbctl - script to create and manage the Databases
  • kamctl - script to manage and control Kamailio SIP server
  • sercmd - CLI - command line tool to interface with Kamailio SIP server

To be able to use the binaries from command line, make sure that '/usr/local/sbin' is set in PATH environment variable. You can check that with 'echo $PATH'. If not and you are using 'bash', open '/root/.bash_profile' and at the end add:

  PATH=$PATH:/usr/local/sbin
  export PATH

Kamailio (OpenSER) modules are installed in:

32-Bit

  /usr/local/lib/kamailio/modules/
  /usr/local/lib/kamailio/modules_k/

64-Bit

  /usr/local/lib64/kamailio/modules/
  /usr/local/lib64/kamailio/modules_k/

Replace …/lib/… with ../lib64/… in most of 64b architectures.

The documentation and readme files are installed in:

  /usr/local/share/doc/kamailio/

The man pages are installed in:

  /usr/local/share/man/man5/
  /usr/local/share/man/man8/

The configuration file was installed in:

  /usr/local/etc/kamailio/kamailio.cfg

In case you set the PREFIX variable in 'make cfg …' command, then replace /usr/local in all paths above with the value of PREFIX in order to locate the files installed.

 

7. Create MySQL database

 

To create the MySQL database, you have to use the database setup script. First edit kamctlrc file to set the database server type:

  nano -w /usr/local/etc/kamailio/kamctlrc

Locate DBENGINE variable and set it to MYSQL:

DBENGINE=MYSQL

You can change other values in kamctlrc file, at least it is recommended to change the default passwords for the users to be created to connect to database.

Once you are done updating kamctlrc file, run the script to create the database used by Kamailio:

  /usr/local/sbin/kamdbctl create

You can call this script without any parameter to get some help for the usage. You will be asked for the domain name Kamailio is going to serve (e.g., mysipserver.com) and the password of the 'root' MySQL user. The script will create a database named 'kamailio' containing the tables required by Kamailio. You can change the default settings in the kamctlrc file mentioned above.

The script will add two users in MySQL:

kamailio - (with default password 'kamailiorw') - user which has full access rights to 'kamailio' database

kamailioro - (with default password 'kamailioro') - user which has read-only access rights to 'kamailio' database

Do change the passwords for these two users to something different that the default values that come with sources.

 

8. Edit configuration file

 

To fit your requirements for the VoIP platform, you have to edit the configuration file.

  /usr/local/etc/kamailio/kamailio.cfg

Follow the instruction in the comments to enable usage of MySQL. Basically you have to add several lines at the top of config file, like:

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB

If you changed the password for the 'kamailio' user of MySQL, you have to update the value for 'db_url' parameters.

You can browse kamailio.cfg online on GIT repository.

 

9. The init.d script

 

The init.d script can be used to start/stop the Kamailio server in a nicer way. A sample of init.d script for Kamailio is provided at:

/usr/local/src/kamailio-4.0/kamailio/pkg/kamailio/deb/debian/kamailio.init

Just copy the init file into the /etc/init.d/kamailio. Then change the permissions:

  chmod 755 /etc/init.d/kamailio 

then edit the file updating the $DAEMON and $CFGFILE values:

  DAEMON=/usr/local/sbin/kamailio
  CFGFILE=/usr/local/etc/kamailio/kamailio.cfg

You need also setup a configuration file in the /etc/default/ directory. This file can be found at:

  /usr/local/src/kamailio-4.0/kamailio/pkg/kamailio/debian/kamailio.default

You need to rename the file to 'kamailio' after you've copied it. Then edit this file and set RUN_KAMAILIO=yes. Edit the other options at your convenience.

Create the directory for pid file:

mkdir -p /var/run/kamailio

Default setting is to run Kamailio as user “kamailio” and group “kamailio”. For that you need to create the user:

adduser --quiet --system --group --disabled-password \
        --shell /bin/false --gecos "Kamailio" \
        --home /var/run/kamailio kamailio

# set ownership to /var/run/kamailio
chown kamailio:kamailio /var/run/kamailio

Then you can start/stop Kamailio using the following commands:

  /etc/init.d/kamailio start
  /etc/init.d/kamailio stop

 

10. Ready to rock

 

Now everything is in place. You can start the VoIP service, creating new accounts and setting the phones.

A new account can be added using 'kamctl' tool via 'kamctl add <username> <password> <email>'. (or try without the email)

kamctl add test testpasswd test@mysipserver.com

If you are asked for SIP_DOMAIN environment variable do one of the following option.

  1.
  export SIP_DOMAIN=mysipserver.com

  2.
  edit '/root/.kamctlrc' and add:
  SIP_DOMAIN=mysipserver.com

 

11. Maintenance

 

The maintenance process is very simple right now. You have to be user 'root' and execute following commands:

  cd /usr/local/src/kamailio-4.0/kamailio
  git pull origin
  make all
  make install
  /etc/init.d/kamailio restart

Now you have the latest Kamailio devel running on your system.

 

12. Time for maintenance service

 

Notification about GIT commits are sent to the mailing list: sr-dev@lists.sip-router.org. Each commit notification contains the reference to the branch where the commit has been done. If the commit message contains the lines:

Module: sip-router
Branch: 4.0

then an update has been made to Kamailio devel version and it will be available to the public GIT in no time.

 

 

 

kamailio.cfg

 

  1. #!KAMAILIO  
  2. #  
  3. # Kamailio (OpenSER) SIP Server v4.0 - default configuration script  
  4. #     - web: http://www.kamailio.org  
  5. #     - git: http://sip-router.org  
  6. #  
  7. # Direct your questions about this file to: <sr-users@lists.sip-router.org>  
  8. #  
  9. # Refer to the Core CookBook at http://www.kamailio.org/wiki/  
  10. # for an explanation of possible statements, functions and parameters.  
  11. #  
  12. # Several features can be enabled using '#!define WITH_FEATURE' directives:  
  13. #  
  14. # *** To run in debug mode:   
  15. #     - define WITH_DEBUG  
  16. #  
  17. # *** To enable mysql:   
  18. #     - define WITH_MYSQL  
  19. #  
  20. # *** To enable authentication execute:  
  21. #     - enable mysql  
  22. #     - define WITH_AUTH  
  23. #     - add users using 'kamctl'  
  24. #  
  25. # *** To enable IP authentication execute:  
  26. #     - enable mysql  
  27. #     - enable authentication  
  28. #     - define WITH_IPAUTH  
  29. #     - add IP addresses with group id '1' to 'address' table  
  30. #  
  31. # *** To enable persistent user location execute:  
  32. #     - enable mysql  
  33. #     - define WITH_USRLOCDB  
  34. #  
  35. # *** To enable presence server execute:  
  36. #     - enable mysql  
  37. #     - define WITH_PRESENCE  
  38. #  
  39. # *** To enable nat traversal execute:  
  40. #     - define WITH_NAT  
  41. #     - install RTPProxy: http://www.rtpproxy.org  
  42. #     - start RTPProxy:  
  43. #        rtpproxy -l _your_public_ip_ -s udp:localhost:7722  
  44. #  
  45. # *** To enable PSTN gateway routing execute:  
  46. #     - define WITH_PSTN  
  47. #     - set the value of pstn.gw_ip  
  48. #     - check route[PSTN] for regexp routing condition  
  49. #  
  50. # *** To enable database aliases lookup execute:  
  51. #     - enable mysql  
  52. #     - define WITH_ALIASDB  
  53. #  
  54. # *** To enable speed dial lookup execute:  
  55. #     - enable mysql  
  56. #     - define WITH_SPEEDDIAL  
  57. #  
  58. # *** To enable multi-domain support execute:  
  59. #     - enable mysql  
  60. #     - define WITH_MULTIDOMAIN  
  61. #  
  62. # *** To enable TLS support execute:  
  63. #     - adjust CFGDIR/tls.cfg as needed  
  64. #     - define WITH_TLS  
  65. #  
  66. # *** To enable XMLRPC support execute:  
  67. #     - define WITH_XMLRPC  
  68. #     - adjust route[XMLRPC] for access policy  
  69. #  
  70. # *** To enable anti-flood detection execute:  
  71. #     - adjust pike and htable=>ipban settings as needed (default is  
  72. #       block if more than 16 requests in 2 seconds and ban for 300 seconds)  
  73. #     - define WITH_ANTIFLOOD  
  74. #  
  75. # *** To block 3XX redirect replies execute:  
  76. #     - define WITH_BLOCK3XX  
  77. #  
  78. # *** To enable VoiceMail routing execute:  
  79. #     - define WITH_VOICEMAIL  
  80. #     - set the value of voicemail.srv_ip  
  81. #     - adjust the value of voicemail.srv_port  
  82. #  
  83. # *** To enhance accounting execute:  
  84. #     - enable mysql  
  85. #     - define WITH_ACCDB  
  86. #     - add following columns to database  
  87. #!ifdef ACCDB_COMMENT  
  88.   ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';  
  89.   ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';  
  90.   ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';  
  91.   ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';  
  92.   ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';  
  93.   ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';  
  94.   ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';  
  95.   ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';  
  96.   ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';  
  97.   ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';  
  98.   ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';  
  99.   ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';  
  100. #!endif  
  101.    
  102. ####### Include Local Config If Exists #########  
  103. import_file "kamailio-local.cfg"  
  104.    
  105. ####### Defined Values #########  
  106.    
  107. #!define WITH_MYSQL  
  108. #!define WITH_AUTH  
  109. #!define WITH_USRLOCDB  
  110.    
  111. #!substdef "!MY_IP_ADDR!<SERVER_IP>!g"  
  112. #!substdef "!MY_DOMAIN!<SERVER_IP>!g"  
  113. #!substdef "!MY_WS_PORT!8080!g"  
  114. #!substdef "!MY_WSS_PORT!4443!g"  
  115. #!substdef "!MY_MSRP_PORT!9000!g"  
  116. #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"  
  117. #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"  
  118. #!substdef "!MY_MSRP_ADDR!tls:MY_IP_ADDR:MY_MSRP_PORT!g"  
  119. #!substdef "!MSRP_MIN_EXPIRES!1800!g"  
  120. #!substdef "!MSRP_MAX_EXPIRES!3600!g"  
  121.    
  122. ##!define LOCAL_TEST_RUN  
  123. ##!define WITH_TLS  
  124. #!define WITH_WEBSOCKETS  
  125. ##!define WITH_MSRP  
  126.    
  127. # *** Value defines - IDs used later in config  
  128. #!ifdef WITH_MYSQL  
  129. # - database URL - used to connect to database server by modules such  
  130. #       as: auth_db, acc, usrloc, a.s.o.  
  131. #!ifndef DBURL  
  132. #!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio"  
  133. #!endif  
  134. #!endif  
  135. #!ifdef WITH_MULTIDOMAIN  
  136. # - the value for 'use_domain' parameters  
  137. #!define MULTIDOMAIN 1  
  138. #!else  
  139. #!define MULTIDOMAIN 0  
  140. #!endif  
  141.    
  142. # - flags  
  143. #   FLT_ - per transaction (message) flags  
  144. #   FLB_ - per branch flags  
  145. #!define FLT_ACC 1  
  146. #!define FLT_ACCMISSED 2  
  147. #!define FLT_ACCFAILED 3  
  148. #!define FLT_NATS 5  
  149.    
  150. #!define FLB_NATB 6  
  151. #!define FLB_NATSIPPING 7  
  152.    
  153. ####### Global Parameters #########  
  154.    
  155. ### LOG Levels: 3=DBG, 2=INFO, 1=NOTICE, 0=WARN, -1=ERR  
  156. #!ifdef WITH_DEBUG  
  157. debug=4  
  158. log_stderror=yes  
  159. #!else  
  160. debug=2  
  161. log_stderror=no  
  162. #!endif  
  163.    
  164. memdbg=5  
  165. memlog=5  
  166.    
  167. log_facility=LOG_LOCAL0  
  168.    
  169. fork=yes  
  170. children=4  
  171.    
  172. /* uncomment the next line to disable TCP (default on) */  
  173. #disable_tcp=yes  
  174.    
  175. /* uncomment the next line to disable the auto discovery of local aliases  
  176.    based on reverse DNS on IPs (default on) */  
  177. #auto_aliases=no  
  178.    
  179. /* add local domain aliases */  
  180. #alias="sip.mydomain.com"  
  181.    
  182. /* uncomment and configure the following line if you want Kamailio to   
  183.    bind on a specific interface/port/proto (default bind on all available) */  
  184. #listen=udp:10.0.0.10:5060  
  185.    
  186. /* port to listen to  
  187.  * - can be specified more than once if needed to listen on many ports */  
  188. port=5060  
  189.    
  190. #!ifdef WITH_TLS  
  191. enable_tls=yes  
  192. #!endif  
  193.    
  194. listen=MY_IP_ADDR  
  195. #!ifdef WITH_WEBSOCKETS  
  196. listen=MY_WS_ADDR  
  197. #!ifdef WITH_TLS  
  198. listen=MY_WSS_ADDR  
  199. #!endif  
  200. #!endif  
  201. #!ifdef WITH_MSRP  
  202. listen=MY_MSRP_ADDR  
  203. #!endif  
  204.    
  205. tcp_connection_lifetime=3604  
  206. tcp_accept_no_cl=yes  
  207. tcp_rd_buf_size=16384  
  208.    
  209. syn_branch=0  
  210.    
  211. # life time of TCP connection when there is no traffic  
  212. # - a bit higher than registration expires to cope with UA behind NAT  
  213. # tcp_connection_lifetime=3605  
  214.    
  215. ####### Custom Parameters #########  
  216.    
  217. # These parameters can be modified runtime via RPC interface  
  218. # - see the documentation of 'cfg_rpc' module.  
  219. #  
  220. # Format: group.id = value 'desc' description  
  221. # Access: $sel(cfg_get.group.id) or @cfg_get.group.id  
  222. #  
  223.    
  224. #!ifdef WITH_PSTN  
  225. # PSTN GW Routing  
  226. #  
  227. # - pstn.gw_ip: valid IP or hostname as string value, example:  
  228. # pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"  
  229. #  
  230. # - by default is empty to avoid misrouting  
  231. pstn.gw_ip = "" desc "PSTN GW Address"  
  232. pstn.gw_port = "" desc "PSTN GW Port"  
  233. #!endif  
  234.    
  235. #!ifdef WITH_VOICEMAIL  
  236. # VoiceMail Routing on offline, busy or no answer  
  237. #  
  238. # - by default Voicemail server IP is empty to avoid misrouting  
  239. voicemail.srv_ip = "" desc "VoiceMail IP Address"  
  240. voicemail.srv_port = "5060" desc "VoiceMail Port"  
  241. #!endif  
  242.    
  243. ####### Modules Section ########  
  244.    
  245. # set paths to location of modules (to sources or installation folders)  
  246. #!ifdef WITH_SRCPATH  
  247. mpath="modules_k:modules"  
  248. #!else  
  249. mpath="/usr/local/lib/kamailio/modules_k/:/usr/lib/kamailio/modules/"  
  250. #!endif  
  251.    
  252. #!ifdef WITH_MYSQL  
  253. loadmodule "db_mysql.so"  
  254. #!endif  
  255.    
  256. loadmodule "mi_fifo.so"  
  257. loadmodule "kex.so"  
  258. loadmodule "corex.so"  
  259. loadmodule "tm.so"  
  260. loadmodule "tmx.so"  
  261. loadmodule "sl.so"  
  262. loadmodule "rr.so"  
  263. loadmodule "pv.so"  
  264. loadmodule "maxfwd.so"  
  265. loadmodule "usrloc.so"  
  266. loadmodule "registrar.so"  
  267. loadmodule "textops.so"  
  268. loadmodule "siputils.so"  
  269. loadmodule "xlog.so"  
  270. loadmodule "sanity.so"  
  271. loadmodule "ctl.so"  
  272. loadmodule "cfg_rpc.so"  
  273. loadmodule "mi_rpc.so"  
  274. loadmodule "acc.so"  
  275.    
  276. #!ifdef WITH_AUTH  
  277. loadmodule "auth.so"  
  278. loadmodule "auth_db.so"  
  279. #!ifdef WITH_IPAUTH  
  280. loadmodule "permissions.so"  
  281. #!endif  
  282. #!endif  
  283.    
  284. #!ifdef WITH_ALIASDB  
  285. loadmodule "alias_db.so"  
  286. #!endif  
  287.    
  288. #!ifdef WITH_SPEEDDIAL  
  289. loadmodule "speeddial.so"  
  290. #!endif  
  291.    
  292. #!ifdef WITH_MULTIDOMAIN  
  293. loadmodule "domain.so"  
  294. #!endif  
  295.    
  296. #!ifdef WITH_PRESENCE  
  297. loadmodule "presence.so"  
  298. loadmodule "presence_xml.so"  
  299. #!endif  
  300.    
  301. #!ifdef WITH_NAT  
  302. loadmodule "nathelper.so"  
  303. loadmodule "rtpproxy.so"  
  304. #!endif  
  305.    
  306. #!ifdef WITH_TLS  
  307. loadmodule "tls.so"  
  308. #!endif  
  309.    
  310. #!ifdef WITH_MSRP  
  311. loadmodule "msrp.so"  
  312. loadmodule "htable.so"  
  313. loadmodule "cfgutils.so"  
  314. #!endif  
  315.    
  316. #!ifdef WITH_WEBSOCKETS  
  317. loadmodule "xhttp.so"  
  318. loadmodule "websocket.so"  
  319. loadmodule "nathelper.so"  
  320. #!endif  
  321.    
  322. #!ifdef WITH_ANTIFLOOD  
  323. loadmodule "htable.so"  
  324. loadmodule "pike.so"  
  325. #!endif  
  326.    
  327. #!ifdef WITH_XMLRPC  
  328. loadmodule "xmlrpc.so"  
  329. #!endif  
  330.    
  331. #!ifdef WITH_DEBUG  
  332. loadmodule "debugger.so"  
  333. #!endif  
  334.    
  335. # ----------------- setting module-specific parameters ---------------  
  336.    
  337.    
  338. # ----- mi_fifo params -----  
  339. modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")  
  340.    
  341.    
  342. # ----- tm params -----  
  343. # auto-discard branches from previous serial forking leg  
  344. modparam("tm", "failure_reply_mode", 3)  
  345. # default retransmission timeout: 30sec  
  346. modparam("tm", "fr_timer", 30000)  
  347. # default invite retransmission timeout after 1xx: 120sec  
  348. modparam("tm", "fr_inv_timer", 120000)  
  349.    
  350.    
  351. # ----- rr params -----  
  352. # add value to ;lr param to cope with most of the UAs  
  353. modparam("rr", "enable_full_lr", 1)  
  354. # do not append from tag to the RR (no need for this script)  
  355. modparam("rr", "append_fromtag", 0)  
  356.    
  357.    
  358. # ----- registrar params -----  
  359. modparam("registrar", "method_filtering", 1)  
  360. /* uncomment the next line to disable parallel forking via location */  
  361. # modparam("registrar", "append_branches", 0)  
  362. /* uncomment the next line not to allow more than 10 contacts per AOR */  
  363. #modparam("registrar", "max_contacts", 10)  
  364. # max value for expires of registrations  
  365. modparam("registrar", "max_expires", 120)  
  366. # set it to 1 to enable GRUU  
  367. modparam("registrar", "gruu_enabled", 0)  
  368.    
  369.    
  370. # ----- acc params -----  
  371. /* what special events should be accounted ? */  
  372. modparam("acc", "early_media", 0)  
  373. modparam("acc", "report_ack", 0)  
  374. modparam("acc", "report_cancels", 0)  
  375. /* by default ww do not adjust the direct of the sequential requests.  
  376.    if you enable this parameter, be sure the enable "append_fromtag"  
  377.    in "rr" module */  
  378. modparam("acc", "detect_direction", 0)  
  379. /* account triggers (flags) */  
  380. modparam("acc", "log_flag", FLT_ACC)  
  381. modparam("acc", "log_missed_flag", FLT_ACCMISSED)  
  382. modparam("acc", "log_extra",   
  383.     "src_user=$fU;src_domain=$fd;src_ip=$si;"  
  384.     "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")  
  385. modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)  
  386. /* enhanced DB accounting */  
  387. #!ifdef WITH_ACCDB  
  388. modparam("acc", "db_flag", FLT_ACC)  
  389. modparam("acc", "db_missed_flag", FLT_ACCMISSED)  
  390. modparam("acc", "db_url", DBURL)  
  391. modparam("acc", "db_extra",  
  392.     "src_user=$fU;src_domain=$fd;src_ip=$si;"  
  393.     "dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")  
  394. #!endif  
  395.    
  396.    
  397. # ----- usrloc params -----  
  398. /* enable DB persistency for location entries */  
  399. #!ifdef WITH_USRLOCDB  
  400. modparam("usrloc", "db_url", DBURL)  
  401. modparam("usrloc", "db_mode", 2)  
  402. modparam("usrloc", "use_domain", MULTIDOMAIN)  
  403. #!endif  
  404.    
  405.    
  406. # ----- auth_db params -----  
  407. #!ifdef WITH_AUTH  
  408. modparam("auth_db", "db_url", DBURL)  
  409. modparam("auth_db", "calculate_ha1", yes)  
  410. modparam("auth_db", "password_column", "password")  
  411. modparam("auth_db", "load_credentials", "")  
  412. modparam("auth_db", "use_domain", MULTIDOMAIN)  
  413.    
  414. # ----- permissions params -----  
  415. #!ifdef WITH_IPAUTH  
  416. modparam("permissions", "db_url", DBURL)  
  417. modparam("permissions", "db_mode", 1)  
  418. #!endif  
  419.    
  420. #!endif  
  421.    
  422.    
  423. # ----- alias_db params -----  
  424. #!ifdef WITH_ALIASDB  
  425. modparam("alias_db", "db_url", DBURL)  
  426. modparam("alias_db", "use_domain", MULTIDOMAIN)  
  427. #!endif  
  428.    
  429.    
  430. # ----- speeddial params -----  
  431. #!ifdef WITH_SPEEDDIAL  
  432. modparam("speeddial", "db_url", DBURL)  
  433. modparam("speeddial", "use_domain", MULTIDOMAIN)  
  434. #!endif  
  435.    
  436.    
  437. # ----- domain params -----  
  438. #!ifdef WITH_MULTIDOMAIN  
  439. modparam("domain", "db_url", DBURL)  
  440. # register callback to match myself condition with domains list  
  441. modparam("domain", "register_myself", 1)  
  442. #!endif  
  443.    
  444.    
  445. #!ifdef WITH_PRESENCE  
  446. # ----- presence params -----  
  447. modparam("presence", "db_url", DBURL)  
  448.    
  449. # ----- presence_xml params -----  
  450. modparam("presence_xml", "db_url", DBURL)  
  451. modparam("presence_xml", "force_active", 1)  
  452. #!endif  
  453.    
  454.    
  455. #!ifdef WITH_NAT  
  456. # ----- rtpproxy params -----  
  457. modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")  
  458.    
  459. # ----- nathelper params -----  
  460. modparam("nathelper", "natping_interval", 30)  
  461. modparam("nathelper", "ping_nated_only", 1)  
  462. modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)  
  463. modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org")  
  464.    
  465. # params needed for NAT traversal in other modules  
  466. modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")  
  467. modparam("usrloc", "nat_bflag", FLB_NATB)  
  468. #!endif  
  469.    
  470.    
  471. #!ifdef WITH_TLS  
  472. # ----- tls params -----  
  473. modparam("tls", "config", "/etc/kamailio/tls.cfg")  
  474. #!endif  
  475.    
  476. #!ifdef WITH_WEBSOCKETS  
  477. # ----- nathelper params -----  
  478. modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")  
  479. # Note: leaving NAT pings turned off here as nathelper is _only_ being used for  
  480. #       WebSocket connections.  NAT pings are not needed as WebSockets have  
  481. #       their own keep-alives.  
  482. #!endif  
  483.    
  484. #!ifdef WITH_MSRP  
  485. # ----- htable params -----  
  486. modparam("htable", "htable", "msrp=>size=8;autoexpire=MSRP_MAX_EXPIRES;")  
  487. #!endif  
  488.    
  489. #!ifdef WITH_ANTIFLOOD  
  490. # ----- pike params -----  
  491. modparam("pike", "sampling_time_unit", 2)  
  492. modparam("pike", "reqs_density_per_unit", 16)  
  493. modparam("pike", "remove_latency", 4)  
  494.    
  495. # ----- htable params -----  
  496. # ip ban htable with autoexpire after 5 minutes  
  497. modparam("htable", "htable", "ipban=>size=8;autoexpire=300;")  
  498. #!endif  
  499.    
  500. #!ifdef WITH_XMLRPC  
  501. # ----- xmlrpc params -----  
  502. modparam("xmlrpc", "route", "XMLRPC");  
  503. modparam("xmlrpc", "url_match", "^/RPC")  
  504. #!endif  
  505.    
  506. #!ifdef WITH_DEBUG  
  507. # ----- debugger params -----  
  508. modparam("debugger", "cfgtrace", 1)  
  509. #!endif  
  510.    
  511. ####### Routing Logic ########  
  512.    
  513.    
  514. # Main SIP request routing logic  
  515. # - processing of any incoming SIP request starts with this route  
  516. # - note: this is the same as route { ... }  
  517. request_route {  
  518.    
  519.     # per request initial checks  
  520.     route(REQINIT);  
  521.    
  522. #!ifdef WITH_WEBSOCKETS  
  523.     if (nat_uac_test(64)) {  
  524.         # Do NAT traversal stuff for requests from a WebSocket  
  525.         # connection - even if it is not behind a NAT!  
  526.         # This won't be needed in the future if Kamailio and the  
  527.         # WebSocket client support Outbound and Path.  
  528.         force_rport();  
  529.         if (is_method("REGISTER")) {  
  530.             fix_nated_register();  
  531.         } else {  
  532.             if (!add_contact_alias()) {  
  533.                 xlog("L_ERR", "Error aliasing contact <$ct>\n");  
  534.                 sl_send_reply("400", "Bad Request");  
  535.                 exit;  
  536.             }  
  537.         }  
  538.     }  
  539. #!endif  
  540.    
  541.     # NAT detection  
  542.     route(NATDETECT);  
  543.    
  544.     # CANCEL processing  
  545.     if (is_method("CANCEL"))  
  546.     {  
  547.         if (t_check_trans()) {  
  548.             route(RELAY);  
  549.         }  
  550.         exit;  
  551.     }  
  552.    
  553.     # handle requests within SIP dialogs  
  554.     route(WITHINDLG);  
  555.    
  556.     ### only initial requests (no To tag)  
  557.    
  558.     t_check_trans();  
  559.    
  560.     # authentication  
  561.     route(AUTH);  
  562.    
  563.     # record routing for dialog forming requests (in case they are routed)  
  564.     # - remove preloaded route headers  
  565.     remove_hf("Route");  
  566.     if (is_method("INVITE|SUBSCRIBE"))  
  567.         record_route();  
  568.    
  569.     # account only INVITEs  
  570.     if (is_method("INVITE"))  
  571.     {  
  572.         setflag(FLT_ACC); # do accounting  
  573.     }  
  574.    
  575.     # dispatch requests to foreign domains  
  576.     route(SIPOUT);  
  577.    
  578.     ### requests for my local domains  
  579.    
  580.     # handle presence related requests  
  581.     route(PRESENCE);  
  582.    
  583.     # handle registrations  
  584.     route(REGISTRAR);  
  585.    
  586.     if ($rU==$null)  
  587.     {  
  588.         # request with no Username in RURI  
  589.         sl_send_reply("484","Address Incomplete");  
  590.         exit;  
  591.     }  
  592.    
  593.     # dispatch destinations to PSTN  
  594.     route(PSTN);  
  595.    
  596.     # user location service  
  597.     route(LOCATION);  
  598. }  
  599.    
  600.    
  601. route[RELAY] {  
  602.    
  603.     # enable additional event routes for forwarded requests  
  604.     # - serial forking, RTP relaying handling, a.s.o.  
  605.     if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {  
  606.         if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");  
  607.     }  
  608.     if (is_method("INVITE|SUBSCRIBE|UPDATE")) {  
  609.         if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");  
  610.     }  
  611.     if (is_method("INVITE")) {  
  612.         if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");  
  613.     }  
  614.    
  615.     if (!t_relay()) {  
  616.         sl_reply_error();  
  617.     }  
  618.     exit;  
  619. }  
  620.    
  621. # Per SIP request initial checks  
  622. route[REQINIT] {  
  623. #!ifdef WITH_ANTIFLOOD  
  624.     # flood dection from same IP and traffic ban for a while  
  625.     # be sure you exclude checking trusted peers, such as pstn gateways  
  626.     # - local host excluded (e.g., loop to self)  
  627.     if(src_ip!=myself)  
  628.     {  
  629.         if($sht(ipban=>$si)!=$null)  
  630.         {  
  631.             # ip is already blocked  
  632.             xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");  
  633.             exit;  
  634.         }  
  635.         if (!pike_check_req())  
  636.         {  
  637.             xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");  
  638.             $sht(ipban=>$si) = 1;  
  639.             exit;  
  640.         }  
  641.     }  
  642. #!endif  
  643.    
  644.     if (!mf_process_maxfwd_header("10")) {  
  645.         sl_send_reply("483","Too Many Hops");  
  646.         exit;  
  647.     }  
  648.    
  649.     if(!sanity_check("1511", "7"))  
  650.     {  
  651.         xlog("Malformed SIP message from $si:$sp\n");  
  652.         exit;  
  653.     }  
  654. }  
  655.    
  656. # Handle requests within SIP dialogs  
  657. route[WITHINDLG] {  
  658.     if (has_totag()) {  
  659.         # sequential request withing a dialog should  
  660.         # take the path determined by record-routing  
  661.         if (loose_route()) {  
  662. #!ifdef WITH_WEBSOCKETS  
  663.             if ($du == "") {  
  664.                 if (!handle_ruri_alias()) {  
  665.                     xlog("L_ERR", "Bad alias <$ru>\n");  
  666.                     sl_send_reply("400", "Bad Request");  
  667.                     exit;  
  668.                 }  
  669.             }  
  670. #!endif  
  671.             route(DLGURI);  
  672.             if (is_method("BYE")) {  
  673.                 setflag(FLT_ACC); # do accounting ...  
  674.                 setflag(FLT_ACCFAILED); # ... even if the transaction fails  
  675.             }  
  676.             else if ( is_method("ACK") ) {  
  677.                 # ACK is forwarded statelessy  
  678.                 route(NATMANAGE);  
  679.             }  
  680.             else if ( is_method("NOTIFY") ) {  
  681.                 # Add Record-Route for in-dialog NOTIFY as per RFC 6665.  
  682.                 record_route();  
  683.             }  
  684.             route(RELAY);  
  685.         } else {  
  686.             if (is_method("SUBSCRIBE") && uri == myself) {  
  687.                 # in-dialog subscribe requests  
  688.                 route(PRESENCE);  
  689.                 exit;  
  690.             }  
  691.             if ( is_method("ACK") ) {  
  692.                 if ( t_check_trans() ) {  
  693.                     # no loose-route, but stateful ACK;  
  694.                     # must be an ACK after a 487  
  695.                     # or e.g. 404 from upstream server  
  696.                     route(RELAY);  
  697.                     exit;  
  698.                 } else {  
  699.                     # ACK without matching transaction ... ignore and discard  
  700.                     exit;  
  701.                 }  
  702.             }  
  703.             sl_send_reply("404","Not here");  
  704.         }  
  705.         exit;  
  706.     }  
  707. }  
  708.    
  709. # Handle SIP registrations  
  710. route[REGISTRAR] {  
  711.     if (is_method("REGISTER"))  
  712.     {  
  713.         if(isflagset(FLT_NATS))  
  714.         {  
  715.             setbflag(FLB_NATB);  
  716.             # uncomment next line to do SIP NAT pinging   
  717.             ## setbflag(FLB_NATSIPPING);  
  718.         }  
  719.         if (!save("location"))  
  720.             sl_reply_error();  
  721.    
  722.         exit;  
  723.     }  
  724. }  
  725.    
  726. # USER location service  
  727. route[LOCATION] {  
  728.    
  729. #!ifdef WITH_SPEEDDIAL  
  730.     # search for short dialing - 2-digit extension  
  731.     if($rU=~"^[0-9][0-9]$")  
  732.         if(sd_lookup("speed_dial"))  
  733.             route(SIPOUT);  
  734. #!endif  
  735.    
  736. #!ifdef WITH_ALIASDB  
  737.     # search in DB-based aliases  
  738.     if(alias_db_lookup("dbaliases"))  
  739.         route(SIPOUT);  
  740. #!endif  
  741.    
  742.     $avp(oexten) = $rU;  
  743.     if (!lookup("location")) {  
  744.         $var(rc) = $rc;  
  745.         route(TOVOICEMAIL);  
  746.         t_newtran();  
  747.         switch ($var(rc)) {  
  748.             case -1:  
  749.             case -3:  
  750.                 send_reply("404", "Not Found");  
  751.                 exit;  
  752.             case -2:  
  753.                 send_reply("405", "Method Not Allowed");  
  754.                 exit;  
  755.         }  
  756.     }  
  757.    
  758.     # when routing via usrloc, log the missed calls also  
  759.     if (is_method("INVITE"))  
  760.     {  
  761.         setflag(FLT_ACCMISSED);  
  762.     }  
  763.    
  764.     route(RELAY);  
  765.     exit;  
  766. }  
  767.    
  768. # Presence server route  
  769. route[PRESENCE] {  
  770.     if(!is_method("PUBLISH|SUBSCRIBE"))  
  771.         return;  
  772.    
  773. #!ifdef WITH_PRESENCE  
  774.     if (!t_newtran())  
  775.     {  
  776.         sl_reply_error();  
  777.         exit;  
  778.     };  
  779.    
  780.     if(is_method("PUBLISH"))  
  781.     {  
  782.         handle_publish();  
  783.         t_release();  
  784.     }  
  785.     else  
  786.     if( is_method("SUBSCRIBE"))  
  787.     {  
  788.         handle_subscribe();  
  789.         t_release();  
  790.     }  
  791.     exit;  
  792. #!endif  
  793.       
  794.     # if presence enabled, this part will not be executed  
  795.     if (is_method("PUBLISH") || $rU==$null)  
  796.     {  
  797.         sl_send_reply("404", "Not here");  
  798.         exit;  
  799.     }  
  800.     return;  
  801. }  
  802.    
  803. # Authentication route  
  804. route[AUTH] {  
  805. #!ifdef WITH_AUTH  
  806.    
  807. #!ifdef WITH_IPAUTH  
  808.     if((!is_method("REGISTER")) && allow_source_address())  
  809.     {  
  810.         # source IP allowed  
  811.         return;  
  812.     }  
  813. #!endif  
  814.    
  815.     if (is_method("REGISTER") || from_uri==myself)  
  816.     {  
  817.         # authenticate requests  
  818.         if (!auth_check("$fd", "subscriber", "1")) {  
  819.             auth_challenge("$fd", "0");  
  820.             exit;  
  821.         }  
  822.         # user authenticated - remove auth header  
  823.         if(!is_method("REGISTER|PUBLISH"))  
  824.             consume_credentials();  
  825.     }  
  826.     # if caller is not local subscriber, then check if it calls  
  827.     # a local destination, otherwise deny, not an open relay here  
  828.     if (from_uri!=myself && uri!=myself)  
  829.     {  
  830.         sl_send_reply("403","Not relaying");  
  831.         exit;  
  832.     }  
  833.    
  834. #!endif  
  835.     return;  
  836. }  
  837.    
  838. # Caller NAT detection route  
  839. route[NATDETECT] {  
  840. #!ifdef WITH_NAT  
  841.     force_rport();  
  842.     if (nat_uac_test("19")) {  
  843.         if (is_method("REGISTER")) {  
  844.             fix_nated_register();  
  845.         } else {  
  846.             add_contact_alias();  
  847.         }  
  848.         setflag(FLT_NATS);  
  849.     }  
  850. #!endif  
  851.     return;  
  852. }  
  853.    
  854. # RTPProxy control  
  855. route[NATMANAGE] {  
  856. #!ifdef WITH_NAT  
  857.     if (is_request()) {  
  858.         if(has_totag()) {  
  859.             if(check_route_param("nat=yes")) {  
  860.                 setbflag(FLB_NATB);  
  861.             }  
  862.         }  
  863.     }  
  864.     if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))  
  865.         return;  
  866.    
  867.     rtpproxy_manage();  
  868.    
  869.     if (is_request()) {  
  870.         if (!has_totag()) {  
  871.             add_rr_param(";nat=yes");  
  872.         }  
  873.     }  
  874.     if (is_reply()) {  
  875.         if(isbflagset(FLB_NATB)) {  
  876.             add_contact_alias();  
  877.         }  
  878.     }  
  879. #!endif  
  880.     return;  
  881. }  
  882.    
  883. # URI update for dialog requests  
  884. route[DLGURI] {  
  885. #!ifdef WITH_NAT  
  886.     if(!isdsturiset()) {  
  887.         handle_ruri_alias();  
  888.     }  
  889. #!endif  
  890.     return;  
  891. }  
  892.    
  893. # Routing to foreign domains  
  894. route[SIPOUT] {  
  895.     if (!uri==myself)  
  896.     {  
  897.         append_hf("P-hint: outbound\r\n");  
  898.         route(RELAY);  
  899.     }  
  900. }  
  901.    
  902. # PSTN GW routing  
  903. route[PSTN] {  
  904. #!ifdef WITH_PSTN  
  905.     # check if PSTN GW IP is defined  
  906.     if (strempty($sel(cfg_get.pstn.gw_ip))) {  
  907.         xlog("SCRIPT: PSTN rotuing enabled but pstn.gw_ip not defined\n");  
  908.         return;  
  909.     }  
  910.    
  911.     # route to PSTN dialed numbers starting with '+' or '00'  
  912.     #     (international format)  
  913.     # - update the condition to match your dialing rules for PSTN routing  
  914.     if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))  
  915.         return;  
  916.    
  917.     # only local users allowed to call  
  918.     if(from_uri!=myself) {  
  919.         sl_send_reply("403", "Not Allowed");  
  920.         exit;  
  921.     }  
  922.    
  923.     if (strempty($sel(cfg_get.pstn.gw_port))) {  
  924.         $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);  
  925.     } else {  
  926.         $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":"  
  927.                     + $sel(cfg_get.pstn.gw_port);  
  928.     }  
  929.    
  930.     route(RELAY);  
  931.     exit;  
  932. #!endif  
  933.    
  934.     return;  
  935. }  
  936.    
  937. # XMLRPC routing  
  938. #!ifdef WITH_XMLRPC  
  939. route[XMLRPC] {  
  940.     # allow XMLRPC from localhost  
  941.     if ((method=="POST" || method=="GET")  
  942.             && (src_ip==127.0.0.1)) {  
  943.         # close connection only for xmlrpclib user agents (there is a bug in  
  944.         # xmlrpclib: it waits for EOF before interpreting the response).  
  945.         if ($hdr(User-Agent) =~ "xmlrpclib")  
  946.             set_reply_close();  
  947.         set_reply_no_connect();  
  948.         dispatch_rpc();  
  949.         exit;  
  950.     }  
  951.     send_reply("403", "Forbidden");  
  952.     exit;  
  953. }  
  954. #!endif  
  955.    
  956. # route to voicemail server  
  957. route[TOVOICEMAIL] {  
  958. #!ifdef WITH_VOICEMAIL  
  959.     if(!is_method("INVITE"))  
  960.         return;  
  961.    
  962.     # check if VoiceMail server IP is defined  
  963.     if (strempty($sel(cfg_get.voicemail.srv_ip))) {  
  964.         xlog("SCRIPT: VoiceMail rotuing enabled but IP not defined\n");  
  965.         return;  
  966.     }  
  967.     if($avp(oexten)==$null)  
  968.         return;  
  969.    
  970.     $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)  
  971.                 + ":" + $sel(cfg_get.voicemail.srv_port);  
  972.     route(RELAY);  
  973.     exit;  
  974. #!endif  
  975.    
  976.     return;  
  977. }  
  978.    
  979. # manage outgoing branches  
  980. branch_route[MANAGE_BRANCH] {  
  981.     xdbg("new branch [$T_branch_idx] to $ru\n");  
  982.     route(NATMANAGE);  
  983. }  
  984.    
  985. # manage incoming replies  
  986. onreply_route[MANAGE_REPLY] {  
  987.     xdbg("incoming reply\n");  
  988.     if(status=~"[12][0-9][0-9]")  
  989.         route(NATMANAGE);  
  990. }  
  991.    
  992. # manage failure routing cases  
  993. failure_route[MANAGE_FAILURE] {  
  994.     route(NATMANAGE);  
  995.    
  996.     if (t_is_canceled()) {  
  997.         exit;  
  998.     }  
  999.    
  1000. #!ifdef WITH_BLOCK3XX  
  1001.     # block call redirect based on 3xx replies.  
  1002.     if (t_check_status("3[0-9][0-9]")) {  
  1003.         t_reply("404","Not found");  
  1004.         exit;  
  1005.     }  
  1006. #!endif  
  1007.    
  1008. #!ifdef WITH_VOICEMAIL  
  1009.     # serial forking  
  1010.     # - route to voicemail on busy or no answer (timeout)  
  1011.     if (t_check_status("486|408")) {  
  1012.         route(TOVOICEMAIL);  
  1013.         exit;  
  1014.     }  
  1015. #!endif  
  1016. }  
  1017.    
  1018. #!ifdef WITH_WEBSOCKETS  
  1019. onreply_route {  
  1020.     if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)  
  1021.         && !(proto == WS || proto == WSS)) || $Rp == MY_MSRP_PORT) {  
  1022.         xlog("L_WARN", "SIP response received on $Rp\n");  
  1023.         drop;  
  1024.         exit;  
  1025.     }  
  1026.    
  1027.     if (nat_uac_test(64)) {  
  1028.         # Do NAT traversal stuff for replies to a WebSocket connection  
  1029.         # - even if it is not behind a NAT!  
  1030.         # This won't be needed in the future if Kamailio and the  
  1031.         # WebSocket client support Outbound and Path.  
  1032.         add_contact_alias();  
  1033.     }  
  1034. }  
  1035.    
  1036. event_route[xhttp:request] {  
  1037.     set_reply_close();  
  1038.     set_reply_no_connect();  
  1039.       
  1040.     if ($Rp != MY_WS_PORT  
  1041. #!ifdef WITH_TLS  
  1042.         && $Rp != MY_WSS_PORT  
  1043. #!endif  
  1044.     ) {  
  1045.         xlog("L_WARN", "HTTP request received on $Rp\n");  
  1046.         xhttp_reply("403", "Forbidden", "", "");  
  1047.         exit;  
  1048.     }  
  1049.    
  1050.     xlog("L_DBG", "HTTP Request Received\n");  
  1051.    
  1052.     if ($hdr(Upgrade)=~"websocket"  
  1053.             && $hdr(Connection)=~"Upgrade"  
  1054.             && $rm=~"GET") {  
  1055.    
  1056.         # Validate Host - make sure the client is using the correct  
  1057.         # alias for WebSockets  
  1058.         if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {  
  1059.             xlog("L_WARN", "Bad host $hdr(Host)\n");  
  1060.             xhttp_reply("403", "Forbidden", "", "");  
  1061.             exit;  
  1062.         }  
  1063.    
  1064.         # Optional... validate Origin - make sure the client is from an  
  1065.         # authorised website.  For example,  
  1066.         #  
  1067.         # if ($hdr(Origin) != "http://communicator.MY_DOMAIN"  
  1068.         #     && $hdr(Origin) != "https://communicator.MY_DOMAIN") {  
  1069.         #   xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");  
  1070.         #   xhttp_reply("403", "Forbidden", "", "");  
  1071.         #   exit;  
  1072.         # }  
  1073.    
  1074.         # Optional... perform HTTP authentication  
  1075.    
  1076.         # ws_handle_handshake() exits (no further configuration file  
  1077.         # processing of the request) when complete.  
  1078.         if (ws_handle_handshake())  
  1079.         {  
  1080.             # Optional... cache some information about the  
  1081.             # successful connection  
  1082.             exit;  
  1083.         }  
  1084.     }  
  1085.    
  1086.     xhttp_reply("404", "Not Found", "", "");  
  1087. }  
  1088.    
  1089. event_route[websocket:closed] {  
  1090.     xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");  
  1091. }  
  1092. #!endif  
  1093.    
  1094. #!ifdef WITH_MSRP  
  1095. event_route[msrp:frame-in] {  
  1096.     msrp_reply_flags("1");  
  1097.    
  1098.     if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)  
  1099.         && !(proto == WS || proto == WSS)) && $Rp != MY_MSRP_PORT) {  
  1100.         xlog("L_WARN", "MSRP request received on $Rp\n");  
  1101.         msrp_reply("403", "Action-not-allowed");  
  1102.         exit;  
  1103.     }  
  1104.    
  1105.     if (msrp_is_reply()) {  
  1106.         msrp_relay();  
  1107.     } else if($msrp(method)=="AUTH") {  
  1108.         if($msrp(nexthops)>0) {  
  1109.             msrp_relay();  
  1110.             exit;  
  1111.         }  
  1112.    
  1113.         if (!www_authenticate("MY_DOMAIN", "subscriber",  
  1114.                     "$msrp(method)")) {  
  1115.             if (auth_get_www_authenticate("MY_DOMAIN", "1",  
  1116.                             "$var(wauth)")) {  
  1117.                 msrp_reply("401", "Unauthorized",  
  1118.                             "$var(wauth)");  
  1119.             } else {  
  1120.                 msrp_reply("500", "Server Error");  
  1121.             }  
  1122.             exit;  
  1123.         }  
  1124.    
  1125.         if ($hdr(Expires) != $null) {  
  1126.             $var(expires) = (int) $hdr(Expires);  
  1127.             if ($var(expires) < MSRP_MIN_EXPIRES) {  
  1128.                 msrp_reply("423", "Interval Out-of-Bounds",  
  1129.                     "Min-Expires: MSRP_MIN_EXPIRES\r\n");  
  1130.                 exit;  
  1131.             } else if ($var(expires) > MSRP_MAX_EXPIRES) {  
  1132.                 msrp_reply("423", "Interval Out-of-Bounds",  
  1133.                     "Max-Expires: MSRP_MAX_EXPIRES\r\n");  
  1134.                 exit;  
  1135.             }  
  1136.         } else {  
  1137.             $var(expires) = MSRP_MAX_EXPIRES;  
  1138.         }  
  1139.    
  1140.         $var(cnt) = $var(cnt) + 1;  
  1141.         pv_printf("$var(sessid)", "s.$(pp).$(var(cnt)).$(RANDOM)");  
  1142.         $sht(msrp=>$var(sessid)::srcaddr) = $msrp(srcaddr);  
  1143.         $sht(msrp=>$var(sessid)::srcsock) = $msrp(srcsock);  
  1144.         $shtex(msrp=>$var(sessid)) = $var(expires) + 5;  
  1145.         # - Use-Path: the MSRP address for server + session id  
  1146.         $var(hdrs) = "Use-Path: msrps://MY_IP_ADDR:MY_MSRP_PORT/"  
  1147.                     + $var(sessid) + ";tcp\r\n"  
  1148.                     + "Expires: " + $var(expires) + "\r\n";  
  1149.         msrp_reply("200", "OK", "$var(hdrs)");  
  1150.     } else if ($msrp(method)=="SEND" || $msrp(method)=="REPORT") {  
  1151.         if ($msrp(nexthops)>1) {  
  1152.             if ($msrp(method)!="REPORT") {  
  1153.                 msrp_reply("200", "OK");  
  1154.             }  
  1155.             msrp_relay();  
  1156.             exit;  
  1157.         }  
  1158.         $var(sessid) = $msrp(sessid);  
  1159.         if ($sht(msrp=>$var(sessid)::srcaddr) == $null) {  
  1160.             # one more hop, but we don't have address in htable  
  1161.             msrp_reply("481", "Session-does-not-exist");  
  1162.             exit;  
  1163.         } else if ($msrp(method)!="REPORT") {  
  1164.             msrp_reply("200", "OK");  
  1165.         }  
  1166.         msrp_relay_flags("1");  
  1167.         msrp_set_dst("$sht(msrp=>$var(sessid)::srcaddr)",  
  1168.                 "$sht(msrp=>$var(sessid)::srcsock)");  
  1169.         msrp_relay();  
  1170.     } else {  
  1171.         msrp_reply("501", "Request-method-not-understood");  
  1172.     }  
  1173. }  
  1174. #!endif