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