764f1ce42899644b7061e33e43f21202fcd43bd1
[sip-router] / src / modules / websocket / README
1 WebSocket Module
2
3 Peter Dunkley
4
5    Crocodile RCS Ltd
6
7    Copyright © 2012-2013 Crocodile RCS Ltd
8      __________________________________________________________________
9
10    Table of Contents
11
12    1. Admin Guide
13
14         1. Overview
15         2. How it works
16
17               2.1. Initiating a connection
18               2.2. SIP message routing
19               2.3. MSRP message routing
20
21         3. Dependencies
22
23               3.1. Kamailio Modules
24               3.2. External Libraries or Applications
25
26         4. Parameters
27
28               4.1. keepalive_mechanism (integer)
29               4.2. keepalive_timeout (integer)
30               4.3. keepalive_processes (integer)
31               4.4. keepalive_interval (integer)
32               4.5. ping_application_data (string)
33               4.6. sub_protocols (integer)
34               4.7. cors_mode (integer)
35
36         5. Functions
37
38               5.1. ws_handle_handshake()
39               5.2. ws_close([status, reason[, connection_id]])
40
41         6. RPC Commands
42
43               6.1. ws.dump
44               6.2. ws.close
45               6.3. ws.ping
46               6.4. ws.pong
47               6.5. ws.disable
48               6.6. ws.enable
49
50         7. Event routes
51
52               7.1. websocket:closed
53
54         8. Exported Pseudo Variables
55
56               8.1. $ws_conid
57
58    List of Examples
59
60    1.1. event_route[xhttp:request]
61    1.2. WebSocket SIP Routing
62    1.3. Set keepalive_mechanism parameter
63    1.4. Set keepalive_timeout parameter
64    1.5. Set keepalive_processes parameter
65    1.6. Set keepalive_interval parameter
66    1.7. Set ping_application_data parameter
67    1.8. Set sub_protocols parameter
68    1.9. Set cors_mode parameter
69    1.10. ws_handle_handshake usage
70    1.11. ws_close usage
71    1.12. event_route[websocket:closed] usage
72    1.13. $ws_conid usage
73
74 Chapter 1. Admin Guide
75
76    Table of Contents
77
78    1. Overview
79    2. How it works
80
81         2.1. Initiating a connection
82         2.2. SIP message routing
83         2.3. MSRP message routing
84
85    3. Dependencies
86
87         3.1. Kamailio Modules
88         3.2. External Libraries or Applications
89
90    4. Parameters
91
92         4.1. keepalive_mechanism (integer)
93         4.2. keepalive_timeout (integer)
94         4.3. keepalive_processes (integer)
95         4.4. keepalive_interval (integer)
96         4.5. ping_application_data (string)
97         4.6. sub_protocols (integer)
98         4.7. cors_mode (integer)
99
100    5. Functions
101
102         5.1. ws_handle_handshake()
103         5.2. ws_close([status, reason[, connection_id]])
104
105    6. RPC Commands
106
107         6.1. ws.dump
108         6.2. ws.close
109         6.3. ws.ping
110         6.4. ws.pong
111         6.5. ws.disable
112         6.6. ws.enable
113
114    7. Event routes
115
116         7.1. websocket:closed
117
118    8. Exported Pseudo Variables
119
120         8.1. $ws_conid
121
122 1. Overview
123
124    This module implements a WebSocket (RFC 6455) server and provides
125    connection establishment (handshaking), management (including
126    connection keep-alive), and framing for the SIP and MSRP WebSocket
127    sub-protocols (RFC 7118 and RFC 7977).
128
129    The module supports WebSockets (ws) and secure WebSockets (wss)
130    transports
131
132 2. How it works
133
134    2.1. Initiating a connection
135    2.2. SIP message routing
136    2.3. MSRP message routing
137
138 2.1. Initiating a connection
139
140    A WebSocket connection is initiated with an HTTP GET. The xhttp module
141    is used to handle this GET and call the Section 5.1, “
142    ws_handle_handshake() ” exported function.
143
144    event_route[xhttp:request] should perform some validation of the HTTP
145    headers before calling Section 5.1, “ ws_handle_handshake() ”. The
146    event_route can also be used to make sure the HTTP GET has the correct
147    URI, perform HTTP authentication on the WebSocket connection, and check
148    the Origin header (RFC 6454) to ensure a browser-based SIP UA or MSRP
149    client has been downloaded from the correct location.
150
151    Example 1.1. event_route[xhttp:request]
152 ...
153 loadmodule "sl.so"
154 loadmodule "xhttp.so"
155 loadmodule "msrp.so"  # Only required if using MSRP over WebSockets
156 loadmodule "websocket.so"
157 ...
158 event_route[xhttp:request] {
159         set_reply_close();
160         set_reply_no_connect();
161
162         if ($Rp != 80
163 #!ifdef WITH_TLS
164             && $Rp != 443
165 #!endif
166         ) {
167
168                 xlog("L_WARN", "HTTP request received on $Rp\n");
169                 xhttp_reply("403", "Forbidden", "", "");
170                 exit;
171         }
172
173         xlog("L_DBG", "HTTP Request Received\n");
174
175         if ($hdr(Upgrade)=~"websocket"
176                         && $hdr(Connection)=~"Upgrade"
177                         && $rm=~"GET") {
178
179                 # Validate Host - make sure the client is using the correct
180                 # alias for WebSockets
181                 if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
182                         xlog("L_WARN", "Bad host $hdr(Host)\n");
183                         xhttp_reply("403", "Forbidden", "", "");
184                         exit;
185                 }
186
187                 # Optional... validate Origin - make sure the client is from an
188                 # authorised website.  For example,
189                 #
190                 # if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
191                 #     && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
192                 #       xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
193                 #       xhttp_reply("403", "Forbidden", "", "");
194                 #       exit;
195                 # }
196
197                 # Optional... perform HTTP authentication
198
199                 # ws_handle_handshake() exits (no further configuration file
200                 # processing of the request) when complete.
201                 if (ws_handle_handshake())
202                 {
203                         # Optional... cache some information about the
204                         # successful connection
205                         exit;
206                 }
207         }
208
209         xhttp_reply("404", "Not found", "", "");
210 }
211 ...
212
213 2.2. SIP message routing
214
215    SIP over WebSockets uses invalid URIs in routing headers (Contact:,
216    Record-Route:, and Via:) because a JavaScript stack running in a
217    browser has no way to determine the local address from which the
218    WebSocket connection is made. This means that the routing headers
219    cannot be used for request or response routing in the normal manner.
220
221    RFC 7118 - The WebSocket Protocol as a Transport for the Session
222    Initiation Protocol - states that SIP WebSocket Clients and the SIP
223    registrar should implement SIP Outbound (RFC 5626) and Path header
224    support (RFC 3327) to enable requests and responses to be correctly
225    routed. Kamailio has a module called "Outbound" for this functionality.
226
227    The nathelper module functions (nat_uac_test(), fix_nated_register(),
228    add_contact_alias(), and handle_ruri_alias()) and the Kamailio core
229    force_rport() can be used to ensure correct routing of SIP WebSocket
230    requests without using Outbound and Path.
231
232    Example 1.2. WebSocket SIP Routing
233 ...
234 loadmodule "sl.so"
235 loadmodule "tm.so"
236 ...
237 loadmodule "websocket.so"
238 ...
239 request_route {
240
241         # per request initial checks
242         route(REQINIT);
243
244         if (nat_uac_test(64)) {
245                 # Do NAT traversal stuff for requests from a WebSocket
246                 # connection - even if it is not behind a NAT!
247                 # This won't be needed in the future if Kamailio and the
248                 # WebSocket client support Outbound and Path.
249                 force_rport();
250                 if (is_method("REGISTER"))
251                         fix_nated_register();
252                 else {
253                         if (!add_contact_alias()) {
254                                 xlog("L_ERR", "Error aliasing contact <$ct>\n");
255                                 sl_send_reply("400", "Bad Request");
256                                 exit;
257                         }
258                 }
259         }
260
261         if (!is_method("REGISTER"))
262                 t_on_reply("WS_REPLY");
263 ...
264 # Handle requests within SIP dialogs
265 route[WITHINDLG] {
266         if (has_totag()) {
267                 # sequential request withing a dialog should
268                 # take the path determined by record-routing
269                 if (loose_route()) {
270                         if ($du == "") {
271                                 if (!handle_ruri_alias()) {
272                                         xlog("L_ERR", "Bad alias <$ru>\n");
273                                         sl_send_reply("400", "Bad Request");
274                                         exit;
275                                 }
276                         }
277                         route(RELAY);
278                 } else {
279                         if ( is_method("ACK") ) {
280 ...
281 onreply_route[WS_REPLY] {
282         if (nat_uac_test(64)) {
283                 # Do NAT traversal stuff for replies to a WebSocket connection
284                 # - even if it is not behind a NAT!
285                 # This won't be needed in the future if Kamailio and the
286                 # WebSocket client support Outbound and Path.
287                 add_contact_alias();
288         }
289 }
290 ...
291
292 2.3. MSRP message routing
293
294    MSRP over WebSocket clients create invalid local URIs for use in Path
295    headers (From-Path: and To-Path:) because a JavaScript stack running in
296    a browser has no way to determine the local address from which the
297    WebSocket connection is made. This is OK because MSRP over WebSocket
298    clients MUST use an MSRP relay and it is the MSRP relay's
299    responsibility to select the correct connection to the client based on
300    the MSRP URIs that it has created (and maintains a mapping for).
301
302 3. Dependencies
303
304    3.1. Kamailio Modules
305    3.2. External Libraries or Applications
306
307 3.1. Kamailio Modules
308
309    The following module must be loaded before this module:
310      * sl.
311      * tm.
312
313    The following modules are required to make proper use of this module:
314      * nathelper or outbound.
315      * xhttp.
316
317    The following module is required to use the secure WebSocket (wss)
318    scheme:
319      * tls.
320
321    The following module is required to support MSRP over WebSockets:
322      * msrp.
323
324 3.2. External Libraries or Applications
325
326    The following libraries must be installed before running Kamailio with
327    this module loaded:
328      * OpenSSL.
329      * GNU libunistring.
330
331 4. Parameters
332
333    4.1. keepalive_mechanism (integer)
334    4.2. keepalive_timeout (integer)
335    4.3. keepalive_processes (integer)
336    4.4. keepalive_interval (integer)
337    4.5. ping_application_data (string)
338    4.6. sub_protocols (integer)
339    4.7. cors_mode (integer)
340
341 4.1. keepalive_mechanism (integer)
342
343    The keep-alive mechanism to use for WebSocket connections.
344
345 Note
346
347    If nathelper is only being used for WebSocket connections then
348    nathelper NAT pinging is not required. If nathelper is used for
349    WebSocket connections and TCP/TLS aliasing/NAT-traversal then WebSocket
350    keep-alives are not required.
351
352      * 0 - no WebSocket keep-alives
353      * 1 - Ping WebSocket keep-alives
354      * 2 - Pong WebSocket keep-alives
355
356    Default value is 1.
357
358    Example 1.3. Set keepalive_mechanism parameter
359 ...
360 modparam("websocket", "keepalive_mechanism", 0)
361 ...
362
363 4.2. keepalive_timeout (integer)
364
365    The time (in seconds) after which to send a keep-alive on idle
366    WebSocket connections.
367
368    Default value is 180.
369
370    Example 1.4. Set keepalive_timeout parameter
371 ...
372 modparam("websocket", "keepalive_timeout", 30)
373 ...
374
375 4.3. keepalive_processes (integer)
376
377    The number of processes to start to perform WebSocket connection
378    keep-alives.
379
380    Default value is 1.
381
382    Example 1.5. Set keepalive_processes parameter
383 ...
384 modparam("websocket", "keepalive_processes", 2)
385 ...
386
387 4.4. keepalive_interval (integer)
388
389    The number of seconds between each keep-alive process run
390
391    Default value is 1.
392
393    Example 1.6. Set keepalive_interval parameter
394 ...
395 modparam("websocket", "keepalive_interval", 2)
396 ...
397
398 4.5. ping_application_data (string)
399
400    The application data to use in keep-alive Ping and Pong frames.
401
402    Default value is Kamailio Server: header content
403
404    Example 1.7. Set ping_application_data parameter
405 ...
406 modparam("websocket", "ping_application_data", "WebSockets rock")
407 ...
408
409 4.6. sub_protocols (integer)
410
411    A bitmap that allows you to control the sub-protocols supported by the
412    WebSocket server.
413      * 1 - sip (RFC 7118)
414      * 2 - msrp (RFC 7977) - msrp.so must be loaded before websocket.so
415
416    Default value is 1 when msrp.so is not loaded 3 when msrp.so is loaded.
417
418    Example 1.8. Set sub_protocols parameter
419 ...
420 modparam("websocket", "sub_protocols", 2)
421 ...
422
423 4.7. cors_mode (integer)
424
425    This parameter lets you set the "Cross-origin resource sharing"
426    behaviour of the WebSocket server.
427      * 0 - Do not add an "Access-Control-Allow-Origin:" header to the
428        response accepting the WebSocket handshake.
429      * 1 - Add a "Access-Control-Allow-Origin: *" header to the response
430        accepting the WebSocket handshake.
431      * 2 - Add a "Access-Control-Allow-Origin:" header containing the same
432        body as the "Origin:" header from the request to the response
433        accepting the WebSocket handshake. If there is no "Origin:" header
434        in the request no header will be added to the response.
435
436    Default value is 0.
437
438    Example 1.9. Set cors_mode parameter
439 ...
440 modparam("websocket", "cors_mode", 2)
441 ...
442
443 5. Functions
444
445    5.1. ws_handle_handshake()
446    5.2. ws_close([status, reason[, connection_id]])
447
448 5.1.  ws_handle_handshake()
449
450    This function checks an HTTP GET request for the required headers and
451    values, and (if successful) upgrades the connection from HTTP to
452    WebSocket.
453
454    This function can be used from ANY_ROUTE (but will only work in
455    event_route[xhttp:request]).
456
457 Note
458
459    This function returns 0, stopping all further processing of the
460    request, when there is a problem.
461
462    Example 1.10. ws_handle_handshake usage
463 ...
464 ws_handle_handshake();
465 ...
466
467 5.2.  ws_close([status, reason[, connection_id]])
468
469    This function closes a WebSocket connection.
470
471    The function returns -1 if there is an error and 1 if it succeeds.
472
473    The meaning of the parameters is as follows:
474      * status - an integer indicating the reason for closure.
475      * reason - a string describing the reason for closure.
476      * connection_id - the connection to close. If not specified the
477        connection the current message arrived on will be closed.
478
479 Note
480
481    status and reason values SHOULD correspond to the definitions in
482    section 7.4 of RFC 6455. If these parameters are not used the defaults
483    of "1000" and "Normal closure" will be used.
484
485    This function can be used from ANY_ROUTE.
486
487    Example 1.11. ws_close usage
488 ...
489 ws_close(4000, "Because I say so");
490 ...
491
492 6. RPC Commands
493
494    6.1. ws.dump
495    6.2. ws.close
496    6.3. ws.ping
497    6.4. ws.pong
498    6.5. ws.disable
499    6.6. ws.enable
500
501 6.1. ws.dump
502
503    Provides the details of the first 50 WebSocket connections.
504
505    Name: ws.dump
506
507    Parameters:
508      * order (optional) - “id_hash”, “used_desc”, or “used_asc”.
509
510 Note
511
512    If no parameter is provided id_hash order is used.
513
514    RPC Command Usage:
515 ...
516 kamcmd ws.dump used_asc
517 ...
518
519 6.2. ws.close
520
521    Starts the close handshake for the specified WebSocket connection.
522
523    Name: ws.close
524
525    Parameters:
526      * id - WebSocket connection ID.
527
528    RPC Command Usage:
529 ...
530 kamcmd ws.close: 1
531 ...
532
533 6.3. ws.ping
534
535    Sends a Ping frame on the specified WebSocket connection.
536
537    Name: ws.ping
538
539    Parameters:
540      * id - WebSocket connection ID.
541
542    RPC Command Usage:
543 ...
544 kamcmd ws.ping 1
545 ...
546
547 6.4. ws.pong
548
549    Sends a Pong frame on the specified WebSocket connection.
550
551    Name: ws.pong
552
553    Parameters:
554      * id - WebSocket connection ID.
555
556    RPC Command Usage:
557 ...
558 kamcmd ws.pong 1
559 ...
560
561 6.5. ws.disable
562
563    Disables WebSockets preventing new connections from being established.
564
565    Name: ws.disable
566
567    Parameters: none
568
569    RPC Command Usage:
570 ...
571 kamcmd ws.disable
572 ...
573
574 6.6. ws.enable
575
576    Enables WebSockets allowing new connections to be established.
577
578 Note
579
580    WebSockets are enabled at start-up.
581
582    Name: ws.enable
583
584    Parameters: none
585
586    RPC Command Format:
587 ...
588 kamcmd ws.enable
589 ...
590
591 7. Event routes
592
593    7.1. websocket:closed
594
595 7.1.  websocket:closed
596
597    When defined, the module calls event_route[websocket:closed] when a
598    connection closes. The connection may be identified using the the $si
599    and $sp pseudo-variables.
600
601    Example 1.12. event_route[websocket:closed] usage
602 ...
603 event_route[websocket:closed] {
604         xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
605 }
606 ...
607
608 8. Exported Pseudo Variables
609
610    8.1. $ws_conid
611
612 8.1. $ws_conid
613
614    Connection id of closed websocket connection. Can only be used in
615    websocket:closed event route.
616
617    Example 1.13. $ws_conid usage
618 ...
619 event_route[websocket:closed] {
620         xlog("L_INFO", "WebSocket connection with id $ws_conid has closed\n");
621 }
622 ...