src/modules/websocket/README
c3958092
 WebSocket Module
 
 Peter Dunkley
 
    Crocodile RCS Ltd
 
00f108df
    Copyright © 2012-2013 Crocodile RCS Ltd
3d5c6699
      __________________________________________________________________
c3958092
 
    Table of Contents
 
    1. Admin Guide
 
         1. Overview
         2. How it works
 
               2.1. Initiating a connection
               2.2. SIP message routing
132509a7
               2.3. MSRP message routing
c3958092
 
         3. Dependencies
 
               3.1. Kamailio Modules
               3.2. External Libraries or Applications
 
         4. Parameters
 
               4.1. keepalive_mechanism (integer)
               4.2. keepalive_timeout (integer)
               4.3. keepalive_processes (integer)
               4.4. keepalive_interval (integer)
               4.5. ping_application_data (string)
132509a7
               4.6. sub_protocols (integer)
3d5c6699
               4.7. cors_mode (integer)
e8f25501
               4.8. verbose_list (int)
20af8da0
               4.9. event_callback (str)
fbfca70e
               4.10. timer_interval (integer)
               4.11. rm_delay_interval (integer)
c3958092
 
         5. Functions
 
3d5c6699
               5.1. ws_handle_handshake()
9af456f2
               5.2. ws_close([status, reason[, connection_id]])
c3958092
 
951905da
         6. RPC Commands
c3958092
 
               6.1. ws.dump
               6.2. ws.close
               6.3. ws.ping
               6.4. ws.pong
               6.5. ws.disable
               6.6. ws.enable
 
6f928a54
         7. Event routes
 
3d5c6699
               7.1. websocket:closed
6f928a54
 
00f108df
         8. Exported Pseudo Variables
 
               8.1. $ws_conid
 
c3958092
    List of Examples
 
    1.1. event_route[xhttp:request]
    1.2. WebSocket SIP Routing
    1.3. Set keepalive_mechanism parameter
    1.4. Set keepalive_timeout parameter
    1.5. Set keepalive_processes parameter
    1.6. Set keepalive_interval parameter
    1.7. Set ping_application_data parameter
132509a7
    1.8. Set sub_protocols parameter
3d5c6699
    1.9. Set cors_mode parameter
e8f25501
    1.10. Set verbose_list parameter
20af8da0
    1.11. Set event_callback parameter
fbfca70e
    1.12. Set timer_intervalparameter
a8395274
    1.13. Set rm_delay_intervalparameter
fbfca70e
    1.14. ws_handle_handshake usage
    1.15. ws_close usage
    1.16. event_route[websocket:closed] usage
    1.17. $ws_conid usage
c3958092
 
 Chapter 1. Admin Guide
 
    Table of Contents
 
    1. Overview
    2. How it works
 
         2.1. Initiating a connection
         2.2. SIP message routing
132509a7
         2.3. MSRP message routing
c3958092
 
    3. Dependencies
 
         3.1. Kamailio Modules
         3.2. External Libraries or Applications
 
    4. Parameters
 
         4.1. keepalive_mechanism (integer)
         4.2. keepalive_timeout (integer)
         4.3. keepalive_processes (integer)
         4.4. keepalive_interval (integer)
         4.5. ping_application_data (string)
132509a7
         4.6. sub_protocols (integer)
3d5c6699
         4.7. cors_mode (integer)
e8f25501
         4.8. verbose_list (int)
20af8da0
         4.9. event_callback (str)
fbfca70e
         4.10. timer_interval (integer)
         4.11. rm_delay_interval (integer)
c3958092
 
    5. Functions
 
3d5c6699
         5.1. ws_handle_handshake()
9af456f2
         5.2. ws_close([status, reason[, connection_id]])
c3958092
 
951905da
    6. RPC Commands
c3958092
 
         6.1. ws.dump
         6.2. ws.close
         6.3. ws.ping
         6.4. ws.pong
         6.5. ws.disable
         6.6. ws.enable
 
6f928a54
    7. Event routes
 
3d5c6699
         7.1. websocket:closed
6f928a54
 
00f108df
    8. Exported Pseudo Variables
 
         8.1. $ws_conid
 
c3958092
 1. Overview
 
3d5c6699
    This module implements a WebSocket (RFC 6455) server and provides
    connection establishment (handshaking), management (including
    connection keep-alive), and framing for the SIP and MSRP WebSocket
c180e958
    sub-protocols (RFC 7118 and RFC 7977).
c3958092
 
    The module supports WebSockets (ws) and secure WebSockets (wss)
c180e958
    transports
c3958092
 
 2. How it works
 
    2.1. Initiating a connection
    2.2. SIP message routing
132509a7
    2.3. MSRP message routing
c3958092
 
 2.1. Initiating a connection
 
    A WebSocket connection is initiated with an HTTP GET. The xhttp module
00f108df
    is used to handle this GET and call the Section 5.1, “
    ws_handle_handshake() ” exported function.
c3958092
 
3d5c6699
    event_route[xhttp:request] should perform some validation of the HTTP
00f108df
    headers before calling Section 5.1, “ ws_handle_handshake() ”. The
c3958092
    event_route can also be used to make sure the HTTP GET has the correct
3d5c6699
    URI, perform HTTP authentication on the WebSocket connection, and check
    the Origin header (RFC 6454) to ensure a browser-based SIP UA or MSRP
    client has been downloaded from the correct location.
c3958092
 
    Example 1.1. event_route[xhttp:request]
 ...
03248001
 tcp_accept_no_cl=yes
 ...
c3958092
 loadmodule "sl.so"
 loadmodule "xhttp.so"
132509a7
 loadmodule "msrp.so"  # Only required if using MSRP over WebSockets
c3958092
 loadmodule "websocket.so"
 ...
 event_route[xhttp:request] {
         set_reply_close();
         set_reply_no_connect();
 
a24ce948
         if ($Rp != 80
 #!ifdef WITH_TLS
             && $Rp != 443
 #!endif
         ) {
 
c3958092
                 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") {
 
a24ce948
                 # Validate Host - make sure the client is using the correct
                 # alias for WebSockets
                 if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
c3958092
                         xlog("L_WARN", "Bad host $hdr(Host)\n");
                         xhttp_reply("403", "Forbidden", "", "");
                         exit;
                 }
 
a24ce948
                 # 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;
                 # }
 
c3958092
                 # Optional... perform HTTP authentication
 
                 # ws_handle_handshake() exits (no further configuration file
3cdd5592
                 # processing of the request) when complete in case of failure.
6f928a54
                 if (ws_handle_handshake())
                 {
                         # Optional... cache some information about the
                         # successful connection
                         exit;
                 }
c3958092
         }
 
         xhttp_reply("404", "Not found", "", "");
 }
 ...
 
 2.2. SIP message routing
 
3d5c6699
    SIP over WebSockets uses invalid URIs in routing headers (Contact:,
    Record-Route:, and Via:) because a JavaScript stack running in a
    browser has no way to determine the local address from which the
    WebSocket connection is made. This means that the routing headers
c3958092
    cannot be used for request or response routing in the normal manner.
 
c180e958
    RFC 7118 - The WebSocket Protocol as a Transport for the Session
    Initiation Protocol - states that SIP WebSocket Clients and the SIP
    registrar should implement SIP Outbound (RFC 5626) and Path header
    support (RFC 3327) to enable requests and responses to be correctly
    routed. Kamailio has a module called "Outbound" for this functionality.
3d5c6699
 
    The nathelper module functions (nat_uac_test(), fix_nated_register(),
    add_contact_alias(), and handle_ruri_alias()) and the Kamailio core
    force_rport() can be used to ensure correct routing of SIP WebSocket
c3958092
    requests without using Outbound and Path.
 
    Example 1.2. WebSocket SIP Routing
 ...
 loadmodule "sl.so"
 loadmodule "tm.so"
 ...
 loadmodule "websocket.so"
 ...
 request_route {
 
         # per request initial checks
         route(REQINIT);
 
         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 {
                         if (!add_contact_alias()) {
9af456f2
                                 xlog("L_ERR", "Error aliasing contact <$ct>\n");
c3958092
                                 sl_send_reply("400", "Bad Request");
                                 exit;
                         }
                 }
         }
 
         if (!is_method("REGISTER"))
                 t_on_reply("WS_REPLY");
 ...
 # Handle requests within SIP dialogs
 route[WITHINDLG] {
         if (has_totag()) {
                 # sequential request withing a dialog should
                 # take the path determined by record-routing
                 if (loose_route()) {
                         if ($du == "") {
                                 if (!handle_ruri_alias()) {
                                         xlog("L_ERR", "Bad alias <$ru>\n");
                                         sl_send_reply("400", "Bad Request");
                                         exit;
                                 }
                         }
                         route(RELAY);
                 } else {
                         if ( is_method("ACK") ) {
 ...
 onreply_route[WS_REPLY] {
         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();
         }
 }
 ...
 
132509a7
 2.3. MSRP message routing
 
3d5c6699
    MSRP over WebSocket clients create invalid local URIs for use in Path
    headers (From-Path: and To-Path:) because a JavaScript stack running in
    a browser has no way to determine the local address from which the
    WebSocket connection is made. This is OK because MSRP over WebSocket
    clients MUST use an MSRP relay and it is the MSRP relay's
132509a7
    responsibility to select the correct connection to the client based on
    the MSRP URIs that it has created (and maintains a mapping for).
 
c3958092
 3. Dependencies
 
    3.1. Kamailio Modules
    3.2. External Libraries or Applications
 
 3.1. Kamailio Modules
 
    The following module must be loaded before this module:
      * sl.
2c6ad972
      * tm.
c3958092
 
    The following modules are required to make proper use of this module:
7ebf6aff
      * nathelper or outbound.
c3958092
      * xhttp.
 
3d5c6699
    The following module is required to use the secure WebSocket (wss)
c3958092
    scheme:
      * tls.
 
132509a7
    The following module is required to support MSRP over WebSockets:
      * msrp.
 
c3958092
 3.2. External Libraries or Applications
 
    The following libraries must be installed before running Kamailio with
    this module loaded:
      * OpenSSL.
      * GNU libunistring.
 
 4. Parameters
 
    4.1. keepalive_mechanism (integer)
    4.2. keepalive_timeout (integer)
    4.3. keepalive_processes (integer)
    4.4. keepalive_interval (integer)
    4.5. ping_application_data (string)
132509a7
    4.6. sub_protocols (integer)
3d5c6699
    4.7. cors_mode (integer)
e8f25501
    4.8. verbose_list (int)
20af8da0
    4.9. event_callback (str)
fbfca70e
    4.10. timer_interval (integer)
    4.11. rm_delay_interval (integer)
c3958092
 
 4.1. keepalive_mechanism (integer)
 
    The keep-alive mechanism to use for WebSocket connections.
 
 Note
 
3d5c6699
    If nathelper is only being used for WebSocket connections then
    nathelper NAT pinging is not required. If nathelper is used for
    WebSocket connections and TCP/TLS aliasing/NAT-traversal then WebSocket
    keep-alives are not required.
c3958092
 
      * 0 - no WebSocket keep-alives
      * 1 - Ping WebSocket keep-alives
      * 2 - Pong WebSocket keep-alives
 
    Default value is 1.
 
    Example 1.3. Set keepalive_mechanism parameter
 ...
 modparam("websocket", "keepalive_mechanism", 0)
 ...
 
 4.2. keepalive_timeout (integer)
 
3d5c6699
    The time (in seconds) after which to send a keep-alive on idle
c3958092
    WebSocket connections.
 
    Default value is 180.
 
    Example 1.4. Set keepalive_timeout parameter
 ...
 modparam("websocket", "keepalive_timeout", 30)
 ...
 
 4.3. keepalive_processes (integer)
 
3d5c6699
    The number of processes to start to perform WebSocket connection
c3958092
    keep-alives.
 
    Default value is 1.
 
    Example 1.5. Set keepalive_processes parameter
 ...
 modparam("websocket", "keepalive_processes", 2)
 ...
 
 4.4. keepalive_interval (integer)
 
c180e958
    The number of seconds between each keep-alive process run
c3958092
 
    Default value is 1.
 
    Example 1.6. Set keepalive_interval parameter
 ...
 modparam("websocket", "keepalive_interval", 2)
 ...
 
 4.5. ping_application_data (string)
 
    The application data to use in keep-alive Ping and Pong frames.
 
    Default value is Kamailio Server: header content
 
    Example 1.7. Set ping_application_data parameter
 ...
 modparam("websocket", "ping_application_data", "WebSockets rock")
 ...
 
132509a7
 4.6. sub_protocols (integer)
 
    A bitmap that allows you to control the sub-protocols supported by the
    WebSocket server.
c180e958
      * 1 - sip (RFC 7118)
af8e6703
      * 2 - msrp (RFC 7977) - the msrp module must be loaded before the
        websocket module
132509a7
 
af8e6703
    Default value is 1 when msrp module is not loaded, 3 when msrp module
    is loaded.
132509a7
 
    Example 1.8. Set sub_protocols parameter
 ...
 modparam("websocket", "sub_protocols", 2)
 ...
 
3d5c6699
 4.7. cors_mode (integer)
 
    This parameter lets you set the "Cross-origin resource sharing"
    behaviour of the WebSocket server.
      * 0 - Do not add an "Access-Control-Allow-Origin:" header to the
        response accepting the WebSocket handshake.
      * 1 - Add a "Access-Control-Allow-Origin: *" header to the response
        accepting the WebSocket handshake.
      * 2 - Add a "Access-Control-Allow-Origin:" header containing the same
        body as the "Origin:" header from the request to the response
        accepting the WebSocket handshake. If there is no "Origin:" header
        in the request no header will be added to the response.
 
    Default value is 0.
 
    Example 1.9. Set cors_mode parameter
 ...
 modparam("websocket", "cors_mode", 2)
 ...
 
e8f25501
 4.8. verbose_list (int)
 
    Allows to enable/disable the printing of debug messages when getting
    the list of websocket connections. If enabled, it prints debug messages
    every second for ping operations.
 
    Default value is 0 (disabled).
 
    Example 1.10. Set verbose_list parameter
 ...
 modparam("websocket", "verbose_list", 1)
 ...
 
20af8da0
 4.9. event_callback (str)
 
    The name of the function in the kemi configuration file (embedded
    scripting language such as Lua, Python, ...) to be executed instead of
    event_route[...] blocks specific for websocket module.
 
    The function has one string parameter, the value is the name of the
    event_route block, respectively "websocket:closed".
 
    Default value is 'empty' (no function is executed for events).
 
    Example 1.11. Set event_callback parameter
 ...
 modparam("websocket", "event_callback", "ksr_websocket_event")
 ...
 -- event callback function implemented in Lua
 function ksr_websocket_event(evname)
         KSR.info("===== websocket module triggered event: " .. evname .. "\n");
         return 1;
 end
 ...
 
fbfca70e
 4.10. timer_interval (integer)
 
    The number of seconds between each timer process run
 
    Default value is 1.
 
    Example 1.12. Set timer_intervalparameter
 ...
 modparam("websocket", "timer_interval", 5)
 ...
 
 4.11. rm_delay_interval (integer)
 
    The number of seconds to wait before destroying the websocket
    connection once put in remove state.
 
    Default value is 5.
 
a8395274
    Example 1.13. Set rm_delay_intervalparameter
fbfca70e
 ...
 modparam("websocket", "rm_delay_interval", 2)
 ...
 
c3958092
 5. Functions
 
3d5c6699
    5.1. ws_handle_handshake()
9af456f2
    5.2. ws_close([status, reason[, connection_id]])
c3958092
 
00f108df
 5.1.  ws_handle_handshake()
c3958092
 
3d5c6699
    This function checks an HTTP GET request for the required headers and
    values, and (if successful) upgrades the connection from HTTP to
c3958092
    WebSocket.
 
3d5c6699
    This function can be used from ANY_ROUTE (but will only work in
c3958092
    event_route[xhttp:request]).
 
 Note
 
3d5c6699
    This function returns 0, stopping all further processing of the
3cdd5592
    request, when there is a problem. Otherwise, it returns 1 (or positive
    number) in case of success.
c3958092
 
fbfca70e
    Example 1.14. ws_handle_handshake usage
c3958092
 ...
 ws_handle_handshake();
 ...
 
00f108df
 5.2.  ws_close([status, reason[, connection_id]])
9af456f2
 
    This function closes a WebSocket connection.
 
    The function returns -1 if there is an error and 1 if it succeeds.
 
    The meaning of the parameters is as follows:
      * status - an integer indicating the reason for closure.
      * reason - a string describing the reason for closure.
      * connection_id - the connection to close. If not specified the
        connection the current message arrived on will be closed.
 
 Note
 
    status and reason values SHOULD correspond to the definitions in
    section 7.4 of RFC 6455. If these parameters are not used the defaults
    of "1000" and "Normal closure" will be used.
 
    This function can be used from ANY_ROUTE.
 
fbfca70e
    Example 1.15. ws_close usage
9af456f2
 ...
 ws_close(4000, "Because I say so");
 ...
 
951905da
 6. RPC Commands
c3958092
 
    6.1. ws.dump
    6.2. ws.close
    6.3. ws.ping
    6.4. ws.pong
    6.5. ws.disable
    6.6. ws.enable
 
 6.1. ws.dump
 
    Provides the details of the first 50 WebSocket connections.
 
    Name: ws.dump
 
    Parameters:
00f108df
      * order (optional) - “id_hash”, “used_desc”, or “used_asc”.
c3958092
 
 Note
 
    If no parameter is provided id_hash order is used.
 
951905da
    RPC Command Usage:
 ...
 kamcmd ws.dump used_asc
 ...
c3958092
 
 6.2. ws.close
 
    Starts the close handshake for the specified WebSocket connection.
 
    Name: ws.close
 
    Parameters:
      * id - WebSocket connection ID.
 
951905da
    RPC Command Usage:
 ...
 kamcmd ws.close: 1
 ...
c3958092
 
 6.3. ws.ping
 
    Sends a Ping frame on the specified WebSocket connection.
 
    Name: ws.ping
 
    Parameters:
      * id - WebSocket connection ID.
 
951905da
    RPC Command Usage:
 ...
 kamcmd ws.ping 1
 ...
c3958092
 
 6.4. ws.pong
 
    Sends a Pong frame on the specified WebSocket connection.
 
    Name: ws.pong
 
    Parameters:
      * id - WebSocket connection ID.
 
951905da
    RPC Command Usage:
 ...
 kamcmd ws.pong 1
 ...
c3958092
 
 6.5. ws.disable
 
    Disables WebSockets preventing new connections from being established.
 
    Name: ws.disable
 
    Parameters: none
 
951905da
    RPC Command Usage:
 ...
 kamcmd ws.disable
 ...
c3958092
 
 6.6. ws.enable
 
    Enables WebSockets allowing new connections to be established.
 
 Note
 
    WebSockets are enabled at start-up.
 
    Name: ws.enable
 
    Parameters: none
 
951905da
    RPC Command Format:
 ...
 kamcmd ws.enable
 ...
6f928a54
 
 7. Event routes
 
3d5c6699
    7.1. websocket:closed
6f928a54
 
00f108df
 7.1.  websocket:closed
6f928a54
 
3d5c6699
    When defined, the module calls event_route[websocket:closed] when a
0dc2fa31
    connection closes. The connection may be identified using the $si and
    $sp pseudo-variables.
38053da7
 
fbfca70e
    Example 1.16. event_route[websocket:closed] usage
6f928a54
 ...
 event_route[websocket:closed] {
         xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
 }
 ...
00f108df
 
 8. Exported Pseudo Variables
 
    8.1. $ws_conid
 
 8.1. $ws_conid
 
    Connection id of closed websocket connection. Can only be used in
    websocket:closed event route.
 
fbfca70e
    Example 1.17. $ws_conid usage
00f108df
 ...
 event_route[websocket:closed] {
         xlog("L_INFO", "WebSocket connection with id $ws_conid has closed\n");
 }
 ...