tcp_accept_no_cl=yes
|
|
|
|
listen=TCP_WS
|
|
#!ifdef TLS-ROLE
|
|
listen=TLS_WSS
|
|
#!endif
|
|
|
|
######## Generic Hash Table container in shared memory ########
|
|
modparam("htable", "htable", "websockets=>size=16;autoexpire=7200")
|
|
|
|
######## Basic HTTP request handling ########
|
|
loadmodule "xhttp.so"
|
|
|
|
######## 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", "sub_protocols", 1)
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
event_route[xhttp:request]
|
|
{
|
|
set_reply_close();
|
|
set_reply_no_connect();
|
|
|
|
if (!($rm =~ "GET")) {
|
|
xlog("L_INFO", "websocket|log|rejecting HTTP request $rm from $si:$sp\n");
|
|
xhttp_reply("405", "Method Not Allowed", "", "");
|
|
exit;
|
|
}
|
|
|
|
if (!($hdr(Connection) =~ "Upgrade")) {
|
|
xlog("L_INFO", "websocket|log|rejecting HTTP connection $hdr(Connection) request from $si:$sp\n");
|
|
xhttp_reply("400", "Bad Request", "", "");
|
|
exit;
|
|
}
|
|
|
|
if (!($hdr(Upgrade) =~ "websocket")) {
|
|
xlog("L_INFO", "websocket|log|rejecting HTTP upgrade $hdr(Upgrade) request from $si:$sp\n");
|
|
xhttp_reply("400", "Bad Request", "", "");
|
|
exit;
|
|
}
|
|
|
|
if (!($hdr(Sec-WebSocket-Protocol) =~ "sip")) {
|
|
xlog("L_INFO", "websocket|log|rejecting request for websocket protocol $hdr(Sec-WebSocket-Protocol) from $si:$sp\n");
|
|
xhttp_reply("400", "Bad Request", "", "");
|
|
exit;
|
|
}
|
|
|
|
#!ifdef MY_WEBSOCKET_DOMAIN
|
|
if (!($hdr(Origin) =~ "MY_WEBSOCKET_DOMAIN")) {
|
|
xlog("L_INFO", "websocket|log|rejecting HTTP request with unknown origin $hdr(Origin) from $si:$sp\n");
|
|
xhttp_reply("400", "Bad Request", "", "");
|
|
exit;
|
|
}
|
|
#!endif
|
|
|
|
if($sht(websockets=>$si::count) == $null) {
|
|
$var(count) = 1;
|
|
} else {
|
|
$var(count) = $sht(websockets=>$si::count) + 1;
|
|
}
|
|
|
|
if($var(count) > 50) {
|
|
xlog("L_WARN", "websocket|log|$si:$sp is at the maximum allowable sockets per IP, rejecting request for another websocket\n");
|
|
xhttp_reply("403", "Forbidden", "", "");
|
|
exit;
|
|
}
|
|
|
|
if (ws_handle_handshake()) {
|
|
$sht(websockets=>$si::count) = $var(count);
|
|
xlog("L_INFO", "websocket|log|opened websocket $var(count) of 50 for $si:$sp\n");
|
|
exit;
|
|
}
|
|
|
|
xlog("L_INFO", "websocket|log|unhandled HTTP request $rm from $si:$sp\n");
|
|
xhttp_reply("404", "Not Found", "", "");
|
|
}
|
|
|
|
event_route[websocket:closed] {
|
|
if($sht(websockets=>$si::count) == $null) {
|
|
xlog("L_INFO", "websocket|log|closed websocket from $si:$sp\n");
|
|
exit();
|
|
}
|
|
|
|
$var(count) = $sht(websockets=>$si::count) - 1;
|
|
|
|
if ($var(count) < 1) {
|
|
xlog("L_INFO", "websocket|log|$si:$sp closed last websocket to that IP\n");
|
|
$sht(websockets=>$si::count) = $null;
|
|
} else {
|
|
$sht(websockets=>$si::count) = $var(count);
|
|
xlog("L_INFO", "websocket|log|closed websocket from $si:$sp, $var(count) remaining from that IP\n");
|
|
}
|
|
}
|