Author: Patrik Formanek 2014
This tutorial instruct how to add the WebSocket support for your kamailio SIP server. As the prerequisities we need to have successfully installed and working kamailio server (described within several tutorials in this site, for example Installing Kamailio 3.1 within SIP/Kamailio section of this site).
As the first step we need to install websocket modules:
apt-get update apt-get install kamailio-websocket-modules
Then we have to edit the kamailio.cfg file which is located at etc/kamailio/kamailio.cfg
In section with defined values add lines:
#!substdef "!MY_IP_ADDR!<SERVER_IP>!g" #!substdef "!MY_DOMAIN!<SERVER_IP>!g" #!substdef "!MY_WS_PORT!8080!g" #!substdef "!MY_WSS_PORT!4443!g" #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g" #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g" #!define WITH_WEBSOCKETS
Where we have to rewrite values :
- <SERVER_IP> : IP address of your server (e.i. #!substdef “!MY_IP_ADDR!192.168.1.13!g”)
- MY_WS_PORT : port on which will be kamailio listening for ws connections (default is 8080 )
In section global parameters add lines:
listen=MY_IP_ADDR #!ifdef WITH_WEBSOCKETS listen=MY_WS_ADDR #!ifdef WITH_TLS listen=MY_WSS_ADDR #!endif #!endif tcp_connection_lifetime=3604 tcp_accept_no_cl=yes tcp_rd_buf_size=16384 And comment line: #tcp_connection_lifetime=3605
Within modules section we load modules needed by the websocket:
#!ifdef WITH_WEBSOCKETS loadmodule "xhttp.so" loadmodule "websocket.so" loadmodule "nathelper.so" #!endif
In section setting module-specific parameters we will add :
#!ifdef WITH_WEBSOCKETS # ----- nathelper params ----- modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)") # Note: leaving NAT pings turned off here as nathelper is _only_ being used for # WebSocket connections. NAT pings are not needed as WebSockets have # their own keep-alives. #!endif
In section routing-logic in block request_route we add lines like this:
request_route { # per request initial checks route(REQINIT); #!ifdef WITH_WEBSOCKETS if (nat_uac_test(64)) { # 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. force_rport(); if (is_method("REGISTER")) { fix_nated_register(); } else { fix_nated_contact(); if (!add_contact_alias()) { xlog("L_ERR", "Error aliasing contact <$ct>\n"); sl_send_reply("400", "Bad Request"); exit; } } } #!endif ....
We add some lines in route[WITHINDLG] and it should looks like this:
route[WITHINDLG] { if (has_totag()) { # sequential request withing a dialog should # take the path determined by record-routing if (loose_route()) { #!ifdef WITH_WEBSOCKETS if ($du == "") { if (!handle_ruri_alias()) { xlog("L_ERR", "Bad alias <$ru>\n"); sl_send_reply("400", "Bad Request"); exit; } } #!endif ....
At the end of config file we add:
#!ifdef WITH_WEBSOCKETS onreply_route { if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS || proto == WSS))) { xlog("L_WARN", "SIP response received on $Rp\n"); drop; exit; } if (nat_uac_test(64)) { # 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. add_contact_alias(); } } event_route[xhttp:request] { set_reply_close(); set_reply_no_connect(); if ($Rp != MY_WS_PORT #!ifdef WITH_TLS && $Rp != MY_WSS_PORT #!endif ) { xlog("L_WARN", "HTTP request received on $Rp\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } xlog("L_DBG", "HTTP Request Received\n"); if ($hdr(Upgrade)=~"websocket" && $hdr(Connection)=~"Upgrade" && $rm=~"GET") { # Validate Host - make sure the client is using the correct # alias for WebSockets if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) { xlog("L_WARN", "Bad host $hdr(Host)\n"); xhttp_reply("403", "Forbidden", "", ""); exit; } # Optional... validate Origin - make sure the client is from an # authorised website. For example, # # if ($hdr(Origin) != "http://communicator.MY_DOMAIN" # && $hdr(Origin) != "https://communicator.MY_DOMAIN") { # xlog("L_WARN", "Unauthorised client $hdr(Origin)\n"); # xhttp_reply("403", "Forbidden", "", ""); # exit; # } # Optional... perform HTTP authentication # ws_handle_handshake() exits (no further configuration file # processing of the request) when complete. if (ws_handle_handshake()) { # Optional... cache some information about the # successful connection exit; } } xhttp_reply("404", "Not Found", "", ""); } event_route[websocket:closed] { xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n"); } #!endif
Save and exit config file. Now you should use command to check for erros:
kamailio -c kamailio.cfg
If is everything ok and no errors are shown you can restart server with
service kamailio restart
You should see something like this:
Listening on udp: 192.168.1.13:5060 tcp: 192.168.1.13:5060 tcp: 192.168.1.13:8080 Aliases: tcp: debi.local:8080 tcp: debi.local:5060 udp: debi.local:5060