123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- WebSocket Module
- Peter Dunkley
- Crocodile RCS Ltd
- Copyright © 2012-2013 Crocodile RCS Ltd
- __________________________________________________________________
- Table of Contents
- 1. Admin Guide
- 1. Overview
- 2. How it works
- 2.1. Initiating a connection
- 2.2. SIP message routing
- 2.3. MSRP message routing
- 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)
- 4.6. sub_protocols (integer)
- 4.7. cors_mode (integer)
- 5. Functions
- 5.1. ws_handle_handshake()
- 5.2. ws_close([status, reason[, connection_id]])
- 6. MI Commands
- 6.1. ws.dump
- 6.2. ws.close
- 6.3. ws.ping
- 6.4. ws.pong
- 6.5. ws.disable
- 6.6. ws.enable
- 7. Event routes
- 7.1. websocket:closed
- 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
- 1.8. Set sub_protocols parameter
- 1.9. Set cors_mode parameter
- 1.10. ws_handle_handshake usage
- 1.11. ws_close usage
- 1.12. event_route[websocket:closed] usage
- Chapter 1. Admin Guide
- Table of Contents
- 1. Overview
- 2. How it works
- 2.1. Initiating a connection
- 2.2. SIP message routing
- 2.3. MSRP message routing
- 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)
- 4.6. sub_protocols (integer)
- 4.7. cors_mode (integer)
- 5. Functions
- 5.1. ws_handle_handshake()
- 5.2. ws_close([status, reason[, connection_id]])
- 6. MI Commands
- 6.1. ws.dump
- 6.2. ws.close
- 6.3. ws.ping
- 6.4. ws.pong
- 6.5. ws.disable
- 6.6. ws.enable
- 7. Event routes
- 7.1. websocket:closed
- 1. Overview
- 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
- sub-protocols (draft-ietf-sipcore-sip-websocket and
- draft-pd-msrp-websocket).
- The module supports WebSockets (ws) and secure WebSockets (wss)
- 2. How it works
- 2.1. Initiating a connection
- 2.2. SIP message routing
- 2.3. MSRP message routing
- 2.1. Initiating a connection
- A WebSocket connection is initiated with an HTTP GET. The xhttp module
- is used to handle this GET and call the Section 5.1, “
- ws_handle_handshake() ” exported function.
- event_route[xhttp:request] should perform some validation of the HTTP
- headers before calling Section 5.1, “ ws_handle_handshake() ”. The
- event_route can also be used to make sure the HTTP GET has the correct
- 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.
- Example 1.1. event_route[xhttp:request]
- ...
- loadmodule "sl.so"
- loadmodule "xhttp.so"
- loadmodule "msrp.so" # Only required if using MSRP over WebSockets
- loadmodule "websocket.so"
- ...
- event_route[xhttp:request] {
- set_reply_close();
- set_reply_no_connect();
- if ($Rp != 80
- #!ifdef WITH_TLS
- && $Rp != 443
- #!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", "", "");
- }
- ...
- 2.2. SIP message routing
- 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
- cannot be used for request or response routing in the normal manner.
- draft-ietf-sipcore-sip-websocket states that SIP WebSocket Clients and
- the SIP registrar should implement Outbound (RFC 5626) and Path (RFC
- 3327) to enable requests and responses to be correctly routed. However,
- Kamailio does not currently support Outbound and it may not be possible
- to guarantee all SIP WebSocket clients will support Outbound and Path.
- 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
- 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()) {
- xlog("L_ERR", "Error aliasing contact <$ct>\n");
- 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();
- }
- }
- ...
- 2.3. MSRP message routing
- 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
- responsibility to select the correct connection to the client based on
- the MSRP URIs that it has created (and maintains a mapping for).
- 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.
- The following modules are required to make proper use of this module:
- * nathelper or outbound.
- * xhttp.
- The following module is required to use the secure WebSocket (wss)
- scheme:
- * tls.
- The following module is required to support MSRP over WebSockets:
- * msrp.
- 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)
- 4.6. sub_protocols (integer)
- 4.7. cors_mode (integer)
- 4.1. keepalive_mechanism (integer)
- The keep-alive mechanism to use for WebSocket connections.
- Note
- 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.
- * 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)
- The time (in seconds) after which to send a keep-alive on idle
- WebSocket connections.
- Default value is 180.
- Example 1.4. Set keepalive_timeout parameter
- ...
- modparam("websocket", "keepalive_timeout", 30)
- ...
- 4.3. keepalive_processes (integer)
- The number of processes to start to perform WebSocket connection
- keep-alives.
- Default value is 1.
- Example 1.5. Set keepalive_processes parameter
- ...
- modparam("websocket", "keepalive_processes", 2)
- ...
- 4.4. keepalive_interval (integer)
- The number of seconds between each keep-alice process run
- 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")
- ...
- 4.6. sub_protocols (integer)
- A bitmap that allows you to control the sub-protocols supported by the
- WebSocket server.
- * 1 - sip (draft-ietf-sipcore-sip-websocket)
- * 2 - msrp (draft-pd-msrp-websocket) - msrp.so must be loaded before
- websocket.so
- Default value is 1 when msrp.so is not loaded 3 when msrp.so is loaded.
- Example 1.8. Set sub_protocols parameter
- ...
- modparam("websocket", "sub_protocols", 2)
- ...
- 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)
- ...
- 5. Functions
- 5.1. ws_handle_handshake()
- 5.2. ws_close([status, reason[, connection_id]])
- 5.1. ws_handle_handshake()
- This function checks an HTTP GET request for the required headers and
- values, and (if successful) upgrades the connection from HTTP to
- WebSocket.
- This function can be used from ANY_ROUTE (but will only work in
- event_route[xhttp:request]).
- Note
- This function returns 0, stopping all further processing of the
- request, when there is a problem.
- Example 1.10. ws_handle_handshake usage
- ...
- ws_handle_handshake();
- ...
- 5.2. ws_close([status, reason[, connection_id]])
- 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.
- Example 1.11. ws_close usage
- ...
- ws_close(4000, "Because I say so");
- ...
- 6. MI Commands
- 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:
- * order (optional) - “id_hash”, “used_desc”, or “used_asc”.
- Note
- If no parameter is provided id_hash order is used.
- MI FIFO Command Format:
- :ws.dump:fifo_reply
- used_asc
- _empty_line_
- 6.2. ws.close
- Starts the close handshake for the specified WebSocket connection.
- Name: ws.close
- Parameters:
- * id - WebSocket connection ID.
- MI FIFO Command Format:
- :ws.close:fifo_reply
- 1
- _empty_line_
- 6.3. ws.ping
- Sends a Ping frame on the specified WebSocket connection.
- Name: ws.ping
- Parameters:
- * id - WebSocket connection ID.
- MI FIFO Command Format:
- :ws.ping:fifo_reply
- 1
- _empty_line_
- 6.4. ws.pong
- Sends a Pong frame on the specified WebSocket connection.
- Name: ws.pong
- Parameters:
- * id - WebSocket connection ID.
- MI FIFO Command Format:
- :ws.pong:fifo_reply
- 1
- _empty_line_
- 6.5. ws.disable
- Disables WebSockets preventing new connections from being established.
- Name: ws.disable
- Parameters: none
- MI FIFO Command Format:
- :ws.disable:fifo_reply
- _empty_line_
- 6.6. ws.enable
- Enables WebSockets allowing new connections to be established.
- Note
- WebSockets are enabled at start-up.
- Name: ws.enable
- Parameters: none
- MI FIFO Command Format:
- :ws.enable:fifo_reply
- _empty_line_
- 7. Event routes
- 7.1. websocket:closed
- 7.1. websocket:closed
- When defined, the module calls event_route[websocket:closed] when a
- connection closes. The connection may be identified using the the $si
- and $sp pseudo-variables.
- Example 1.12. event_route[websocket:closed] usage
- ...
- event_route[websocket:closed] {
- xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
- }
- ...
|