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