websocket_admin.xml 20 KB

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