Module: sip-router Branch: master Commit: 96a1af2f261085db695d8a3b23c1a16f39b393fa URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=96a1af2f...
Author: Peter Dunkley peter.dunkley@crocodile-rcs.com Committer: Peter Dunkley peter.dunkley@crocodile-rcs.com Date: Wed Apr 24 21:07:07 2013 +0100
examples: added WebSocket edge proxy example using outbound for NAT traversal
---
examples/outbound/edge_websocket.cfg | 293 ++++++++++++++++++++++++++++++++++ 1 files changed, 293 insertions(+), 0 deletions(-)
diff --git a/examples/outbound/edge_websocket.cfg b/examples/outbound/edge_websocket.cfg new file mode 100644 index 0000000..843ec20 --- /dev/null +++ b/examples/outbound/edge_websocket.cfg @@ -0,0 +1,293 @@ +#!KAMAILIO +# +# Edge proxy configuration with SIP over WebSocket support +# + +#!substdef "!DBURL!sqlite:///etc/kamailio/db.sqlite!g" +#!substdef "!MY_IP_ADDR!a.b.c.d!g" +#!substdef "!MY_DOMAIN!example.com!g" +#!substdef "!MY_WS_PORT!80!g" +#!substdef "!MY_WSS_PORT!443!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" + +#!substdef "!REGISTRAR_IP!e.f.g.h!g" +#!substdef "!REGISTRAR_PORT!5060!g" +#!substdef "!FLOW_TIMER!20!g" + +#!define WITH_TLS +#!define WITH_WEBSOCKETS + + +####### Global Parameters ######### + +debug=2 +log_stderror=no +log_facility=LOG_LOCAL0 +fork=yes +children=4 +mpath="/usr/lib64/kamailio/modules/" +force_rport=yes + +#!ifdef WITH_TLS +enable_tls=1 +#!endif + +listen=MY_IP_ADDR +#!ifdef WITH_WEBSOCKETS +listen=MY_WS_ADDR +#!ifdef WITH_TLS +listen=MY_WSS_ADDR +#!endif +#!endif + +tcp_connection_lifetime=30 # FLOW_TIMER + 10 +tcp_accept_no_cl=yes +tcp_rd_buf_size=16384 + + +####### Modules Section ######## + +loadmodule "tm.so" +loadmodule "sl.so" +loadmodule "outbound.so" +loadmodule "rr.so" +loadmodule "path.so" +loadmodule "pv.so" +loadmodule "maxfwd.so" +loadmodule "xlog.so" +loadmodule "sanity.so" +loadmodule "ctl.so" +loadmodule "mi_rpc.so" +loadmodule "mi_fifo.so" +loadmodule "textops.so" +loadmodule "siputils.so" +loadmodule "stun.so" +loadmodule "kex.so" +loadmodule "corex.so" +#!ifdef WITH_TLS +loadmodule "tls.so" +#!endif +#!ifdef WITH_WEBSOCKETS +loadmodule "xhttp.so" +loadmodule "websocket.so" +#!endif + +# ----------------- setting module-specific parameters --------------- + +# ----- mi_fifo params ----- +modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") + +# ----- tm params ----- +modparam("tm", "failure_reply_mode", 3) + +# ----- rr params ----- +modparam("rr", "append_fromtag", 0) + +# ----- corex params ----- +modparam("corex", "alias_subdomains", "MY_DOMAIN") + +#!ifdef WITH_TLS +# ----- tls params ----- +modparam("tls", "tls_method", "SSLv23") +modparam("tls", "certificate", "/etc/pki/CA/ser1_cert.pem") +modparam("tls", "private_key", "/etc/pki/CA/privkey.pem") +modparam("tls", "ca_list", "/etc/pki/CA/calist.pem") +#!endif + +#!ifdef WITH_WEBSOCKETS +# ----- websocket params ----- +modparam("websocket", "keepalive_timeout", 25) # FLOW_TIMER + 5 +#!endif + + +####### Routing Logic ######## + +request_route { + if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) + && !(proto == WS || proto == WSS)) { + xlog("L_WARN", "SIP request received on $Rp\n"); + sl_send_reply("403", "Forbidden"); + exit; + } + + route(REQINIT); + + if (is_method("CANCEL")) { + if (t_check_trans()) { + route(RELAY); + } + exit; + } + + route(WITHINDLG); + + t_check_trans(); + + if (is_method("REGISTER")) { + remove_hf("Route"); + add_path(); + $du = "sip:REGISTRAR_IP:REGISTRAR_PORT"; + } else { + if (is_method("INVITE|SUBSCRIBE")) + record_route(); + + if (@via[2] == "") { + # From client so route to registrar... + + if ($rU == $null) { + sl_send_reply("484", "Address Incomplete"); + exit; + } + remove_hf("Route"); + $du = "sip:REGISTRAR_IP:REGISTRAR_PORT"; + } else { + # From registrar so route using "Route:" headers... + + if (!loose_route()) { + switch($rc) { + case -2: + sl_send_reply("403", "Forbidden"); + exit; + default: + xlog("L_ERR", "in request_route\n"); + sl_reply_error(); + exit; + } + } + + t_on_failure("FAIL_OUTBOUND"); + } + } + + route(RELAY); +} + +route[RELAY] { + if (!t_relay()) { + sl_reply_error(); + } + exit; +} + +route[REQINIT] { + if (!mf_process_maxfwd_header("10")) { + sl_send_reply("483","Too Many Hops"); + exit; + } + + if(!sanity_check("1511", "7")) + { + xlog("Malformed SIP message from $si:$sp\n"); + exit; + } +} + +route[WITHINDLG] { + if (has_totag()) { + if (!loose_route()) { + switch($rc) { + case -2: + sl_send_reply("403", "Forbidden"); + exit; + default: + if (is_method("ACK")) { + if ( t_check_trans() ) { + route(RELAY); + exit; + } else { + exit; + } + } + sl_send_reply("404","Not Found"); + } + } else { + if (is_method("NOTIFY")) { + record_route(); + } + route(RELAY); + } + exit; + } +} + +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; + } + + if (!t_check_trans()) { + drop; + } + + if ($rm == "REGISTER" && $rs >= 200 && $rs <= 299) { + remove_hf("Flow-Timer"); + if ($(hdr(Require)[*])=~"outbound") + insert_hf("Flow-Timer: FLOW_TIMER\r\n", "Call-ID"); + } +} + +failure_route[FAIL_OUTBOUND] { + if (t_branch_timeout() || !t_branch_replied()) { + send_reply("430", "Flow Failed"); + } +} + +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"); +}