ws_frame.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. /*
  2. * Copyright (C) 2012-2013 Crocodile RCS Ltd
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. *
  20. * Exception: permission to copy, modify, propagate, and distribute a work
  21. * formed by combining OpenSSL toolkit software and the code in this file,
  22. * such as linking with software components and libraries released under
  23. * OpenSSL project license.
  24. *
  25. */
  26. #include <limits.h>
  27. #ifdef EMBEDDED_UTF8_DECODE
  28. #include "utf8_decode.h"
  29. #else
  30. #include <unistr.h>
  31. #endif
  32. #include "../../events.h"
  33. #include "../../receive.h"
  34. #include "../../stats.h"
  35. #include "../../str.h"
  36. #include "../../tcp_conn.h"
  37. #include "../../tcp_read.h"
  38. #include "../../tcp_server.h"
  39. #include "../../lib/kcore/kstats_wrapper.h"
  40. #include "../../lib/kmi/tree.h"
  41. #include "../../mem/mem.h"
  42. #include "ws_conn.h"
  43. #include "ws_frame.h"
  44. #include "ws_mod.h"
  45. #include "ws_handshake.h"
  46. #include "config.h"
  47. /* 0 1 2 3
  48. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  49. +-+-+-+-+-------+-+-------------+-------------------------------+
  50. |F|R|R|R| opcode|M| Payload len | Extended payload length |
  51. |I|S|S|S| (4) |A| (7) | (16/64) |
  52. |N|V|V|V| |S| | (if payload len==126/127) |
  53. | |1|2|3| |K| | |
  54. +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
  55. | Extended payload length continued, if payload len == 127 |
  56. + - - - - - - - - - - - - - - - +-------------------------------+
  57. | |Masking-key, if MASK set to 1 |
  58. +-------------------------------+-------------------------------+
  59. | Masking-key (continued) | Payload Data |
  60. +-------------------------------- - - - - - - - - - - - - - - - +
  61. : Payload Data continued ... :
  62. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  63. | Payload Data continued ... |
  64. +---------------------------------------------------------------+ */
  65. typedef struct {
  66. unsigned int fin;
  67. unsigned int rsv1;
  68. unsigned int rsv2;
  69. unsigned int rsv3;
  70. unsigned int opcode;
  71. unsigned int mask;
  72. unsigned int payload_len;
  73. unsigned char masking_key[4];
  74. char *payload_data;
  75. ws_connection_t *wsc;
  76. } ws_frame_t;
  77. typedef enum
  78. {
  79. CONN_CLOSE_DO = 0,
  80. CONN_CLOSE_DONT
  81. } conn_close_t;
  82. #define BYTE0_MASK_FIN (0x80)
  83. #define BYTE0_MASK_RSV1 (0x40)
  84. #define BYTE0_MASK_RSV2 (0x20)
  85. #define BYTE0_MASK_RSV3 (0x10)
  86. #define BYTE0_MASK_OPCODE (0x0F)
  87. #define BYTE1_MASK_MASK (0x80)
  88. #define BYTE1_MASK_PAYLOAD_LEN (0x7F)
  89. #define OPCODE_CONTINUATION (0x0)
  90. #define OPCODE_TEXT_FRAME (0x1)
  91. #define OPCODE_BINARY_FRAME (0x2)
  92. /* 0x3 - 0x7 are reserved for further non-control frames */
  93. #define OPCODE_CLOSE (0x8)
  94. #define OPCODE_PING (0x9)
  95. #define OPCODE_PONG (0xa)
  96. /* 0xb - 0xf are reserved for further control frames */
  97. int ws_keepalive_mechanism = DEFAULT_KEEPALIVE_MECHANISM;
  98. str ws_ping_application_data = STR_NULL;
  99. stat_var *ws_failed_connections;
  100. stat_var *ws_local_closed_connections;
  101. stat_var *ws_received_frames;
  102. stat_var *ws_remote_closed_connections;
  103. stat_var *ws_transmitted_frames;
  104. stat_var *ws_sip_failed_connections;
  105. stat_var *ws_sip_local_closed_connections;
  106. stat_var *ws_sip_received_frames;
  107. stat_var *ws_sip_remote_closed_connections;
  108. stat_var *ws_sip_transmitted_frames;
  109. stat_var *ws_msrp_failed_connections;
  110. stat_var *ws_msrp_local_closed_connections;
  111. stat_var *ws_msrp_received_frames;
  112. stat_var *ws_msrp_remote_closed_connections;
  113. stat_var *ws_msrp_transmitted_frames;
  114. /* WebSocket status text */
  115. static str str_status_normal_closure = str_init("Normal closure");
  116. static str str_status_protocol_error = str_init("Protocol error");
  117. static str str_status_unsupported_opcode = str_init("Unsupported opcode");
  118. static str str_status_message_too_big = str_init("Message too big");
  119. /* MI command status text */
  120. static str str_status_empty_param = str_init("Empty connection ID parameter");
  121. static str str_status_too_many_params = str_init("Too many parameters");
  122. static str str_status_bad_param = str_init("Bad connection ID parameter");
  123. static str str_status_error_closing = str_init("Error closing connection");
  124. static str str_status_error_sending = str_init("Error sending frame");
  125. static str str_status_string_error = str_init("Error converting string to int");
  126. static int encode_and_send_ws_frame(ws_frame_t *frame, conn_close_t conn_close)
  127. {
  128. int pos = 0, extended_length;
  129. unsigned int frame_length;
  130. char *send_buf;
  131. struct tcp_connection *con;
  132. struct dest_info dst;
  133. union sockaddr_union *from = NULL;
  134. union sockaddr_union local_addr;
  135. int sub_proto;
  136. LM_DBG("encoding WebSocket frame\n");
  137. if (frame->wsc->state != WS_S_OPEN)
  138. {
  139. LM_WARN("sending on closing connection\n");
  140. return -1;
  141. }
  142. wsconn_update(frame->wsc);
  143. /* Validate the first byte */
  144. if (!frame->fin)
  145. {
  146. LM_ERR("WebSocket fragmentation not supported in the sip "
  147. "sub-protocol\n");
  148. return -1;
  149. }
  150. if (frame->rsv1 || frame->rsv2 || frame->rsv3)
  151. {
  152. LM_ERR("WebSocket reserved fields with non-zero values\n");
  153. return -1;
  154. }
  155. sub_proto = frame->wsc->sub_protocol;
  156. switch(frame->opcode)
  157. {
  158. case OPCODE_TEXT_FRAME:
  159. case OPCODE_BINARY_FRAME:
  160. LM_DBG("supported non-control frame: 0x%x\n",
  161. (unsigned char) frame->opcode);
  162. break;
  163. case OPCODE_CLOSE:
  164. case OPCODE_PING:
  165. case OPCODE_PONG:
  166. LM_DBG("supported control frame: 0x%x\n",
  167. (unsigned char) frame->opcode);
  168. break;
  169. default:
  170. LM_ERR("unsupported opcode: 0x%x\n",
  171. (unsigned char) frame->opcode);
  172. return -1;
  173. }
  174. /* validate the second byte */
  175. if (frame->mask)
  176. {
  177. LM_ERR("this is a server - all messages sent will be "
  178. "unmasked\n");
  179. return -1;
  180. }
  181. if (frame->payload_len < 126) extended_length = 0;
  182. else if (frame->payload_len <= USHRT_MAX ) extended_length = 2;
  183. else if (frame->payload_len <= UINT_MAX) extended_length = 4;
  184. else
  185. {
  186. LM_ERR("Kamailio only supports WebSocket frames with payload "
  187. "<= %u\n", UINT_MAX);
  188. return -1;
  189. }
  190. /* Allocate send buffer and build frame */
  191. frame_length = frame->payload_len + extended_length + 2;
  192. if ((send_buf = pkg_malloc(sizeof(unsigned char) * frame_length))
  193. == NULL)
  194. {
  195. LM_ERR("allocating send buffer from pkg memory\n");
  196. return -1;
  197. }
  198. memset(send_buf, 0, sizeof(unsigned char) * frame_length);
  199. send_buf[pos++] = 0x80 | (frame->opcode & 0xff);
  200. if (extended_length == 0)
  201. send_buf[pos++] = (frame->payload_len & 0xff);
  202. else if (extended_length == 2)
  203. {
  204. send_buf[pos++] = 126;
  205. send_buf[pos++] = (frame->payload_len & 0xff00) >> 8;
  206. send_buf[pos++] = (frame->payload_len & 0x00ff) >> 0;
  207. }
  208. else
  209. {
  210. send_buf[pos++] = 127;
  211. send_buf[pos++] = (frame->payload_len & 0xff000000) >> 24;
  212. send_buf[pos++] = (frame->payload_len & 0x00ff0000) >> 16;
  213. send_buf[pos++] = (frame->payload_len & 0x0000ff00) >> 8;
  214. send_buf[pos++] = (frame->payload_len & 0x000000ff) >> 0;
  215. }
  216. memcpy(&send_buf[pos], frame->payload_data, frame->payload_len);
  217. if ((con = tcpconn_get(frame->wsc->id, 0, 0, 0, 0)) == NULL)
  218. {
  219. LM_WARN("TCP/TLS connection get failed\n");
  220. pkg_free(send_buf);
  221. if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
  222. LM_ERR("removing WebSocket connection\n");
  223. return -1;
  224. }
  225. init_dst_from_rcv(&dst, &con->rcv);
  226. if (conn_close == CONN_CLOSE_DO)
  227. {
  228. dst.send_flags.f |= SND_F_CON_CLOSE;
  229. if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
  230. {
  231. LM_ERR("removing WebSocket connection\n");
  232. tcpconn_put(con);
  233. pkg_free(send_buf);
  234. return -1;
  235. }
  236. }
  237. if (dst.proto == PROTO_WS)
  238. {
  239. if (unlikely(tcp_disable))
  240. {
  241. STATS_TX_DROPS;
  242. LM_WARN("TCP disabled\n");
  243. pkg_free(send_buf);
  244. tcpconn_put(con);
  245. return -1;
  246. }
  247. }
  248. #ifdef USE_TLS
  249. else if (dst.proto == PROTO_WSS)
  250. {
  251. if (unlikely(tls_disable))
  252. {
  253. STATS_TX_DROPS;
  254. LM_WARN("TLS disabled\n");
  255. pkg_free(send_buf);
  256. tcpconn_put(con);
  257. return -1;
  258. }
  259. }
  260. #endif /* USE_TLS */
  261. if (unlikely((dst.send_flags.f & SND_F_FORCE_SOCKET)
  262. && dst.send_sock))
  263. {
  264. local_addr = dst.send_sock->su;
  265. su_setport(&local_addr, 0);
  266. from = &local_addr;
  267. }
  268. /* Regardless of what has been set before _always_ use existing
  269. connections for WebSockets. This is required because a WebSocket
  270. server (which Kamailio is) CANNOT create connections. */
  271. dst.send_flags.f |= SND_F_FORCE_CON_REUSE;
  272. if (tcp_send(&dst, from, send_buf, frame_length) < 0)
  273. {
  274. STATS_TX_DROPS;
  275. LM_ERR("sending WebSocket frame\n");
  276. pkg_free(send_buf);
  277. update_stat(ws_failed_connections, 1);
  278. if (sub_proto == SUB_PROTOCOL_SIP)
  279. update_stat(ws_sip_failed_connections, 1);
  280. else if (sub_proto == SUB_PROTOCOL_MSRP)
  281. update_stat(ws_msrp_failed_connections, 1);
  282. if (wsconn_rm(frame->wsc, WSCONN_EVENTROUTE_YES) < 0)
  283. LM_ERR("removing WebSocket connection\n");
  284. tcpconn_put(con);
  285. return -1;
  286. }
  287. update_stat(ws_transmitted_frames, 1);
  288. switch (frame->opcode)
  289. {
  290. case OPCODE_TEXT_FRAME:
  291. case OPCODE_BINARY_FRAME:
  292. if (frame->wsc->sub_protocol == SUB_PROTOCOL_SIP)
  293. update_stat(ws_sip_transmitted_frames, 1);
  294. else if (frame->wsc->sub_protocol == SUB_PROTOCOL_MSRP)
  295. update_stat(ws_msrp_transmitted_frames, 1);
  296. }
  297. pkg_free(send_buf);
  298. tcpconn_put(con);
  299. return 0;
  300. }
  301. static int close_connection(ws_connection_t **p_wsc, ws_close_type_t type,
  302. short int status, str reason)
  303. {
  304. char *data;
  305. ws_frame_t frame;
  306. ws_connection_t * wsc = NULL;
  307. int sub_proto = -1;
  308. if (!p_wsc || !(*p_wsc))
  309. {
  310. LM_ERR("Invalid parameters\n");
  311. return -1;
  312. }
  313. wsc = *p_wsc;
  314. if (wsc->state == WS_S_OPEN)
  315. {
  316. data = pkg_malloc(sizeof(char) * (reason.len + 2));
  317. if (data == NULL)
  318. {
  319. LM_ERR("allocating pkg memory\n");
  320. return -1;
  321. }
  322. data[0] = (status & 0xff00) >> 8;
  323. data[1] = (status & 0x00ff) >> 0;
  324. memcpy(&data[2], reason.s, reason.len);
  325. memset(&frame, 0, sizeof(frame));
  326. frame.fin = 1;
  327. frame.opcode = OPCODE_CLOSE;
  328. frame.payload_len = reason.len + 2;
  329. frame.payload_data = data;
  330. frame.wsc = wsc;
  331. sub_proto = wsc->sub_protocol;
  332. if (encode_and_send_ws_frame(&frame,
  333. type ==
  334. REMOTE_CLOSE ? CONN_CLOSE_DO : CONN_CLOSE_DONT) < 0)
  335. {
  336. LM_ERR("sending WebSocket close\n");
  337. pkg_free(data);
  338. return -1;
  339. }
  340. pkg_free(data);
  341. if (type == LOCAL_CLOSE)
  342. {
  343. frame.wsc->state = WS_S_CLOSING;
  344. update_stat(ws_local_closed_connections, 1);
  345. if (frame.wsc->sub_protocol == SUB_PROTOCOL_SIP)
  346. update_stat(ws_sip_local_closed_connections, 1);
  347. else if (frame.wsc->sub_protocol == SUB_PROTOCOL_MSRP)
  348. update_stat(ws_msrp_local_closed_connections,
  349. 1);
  350. }
  351. else
  352. {
  353. update_stat(ws_remote_closed_connections, 1);
  354. if (sub_proto == SUB_PROTOCOL_SIP)
  355. update_stat(ws_sip_remote_closed_connections,
  356. 1);
  357. else if (sub_proto == SUB_PROTOCOL_MSRP)
  358. update_stat(ws_msrp_remote_closed_connections,
  359. 1);
  360. }
  361. }
  362. else /* if (frame->wsc->state == WS_S_CLOSING) */
  363. {
  364. wsconn_close_now(wsc);
  365. }
  366. return 0;
  367. }
  368. static int decode_and_validate_ws_frame(ws_frame_t *frame,
  369. tcp_event_info_t *tcpinfo,
  370. short *err_code, str *err_text)
  371. {
  372. unsigned int i, len = tcpinfo->len;
  373. int mask_start, j;
  374. char *buf = tcpinfo->buf;
  375. LM_DBG("decoding WebSocket frame\n");
  376. wsconn_update(frame->wsc);
  377. /* Decode and validate first 9 bits */
  378. if (len < 2)
  379. {
  380. LM_WARN("message is too short\n");
  381. *err_code = 1002;
  382. *err_text = str_status_protocol_error;
  383. return -1;
  384. }
  385. frame->fin = (buf[0] & 0xff) & BYTE0_MASK_FIN;
  386. frame->rsv1 = (buf[0] & 0xff) & BYTE0_MASK_RSV1;
  387. frame->rsv2 = (buf[0] & 0xff) & BYTE0_MASK_RSV2;
  388. frame->rsv3 = (buf[0] & 0xff) & BYTE0_MASK_RSV3;
  389. frame->opcode = (buf[0] & 0xff) & BYTE0_MASK_OPCODE;
  390. frame->mask = (buf[1] & 0xff) & BYTE1_MASK_MASK;
  391. if (!frame->fin)
  392. {
  393. LM_WARN("WebSocket fragmentation not supported in the sip "
  394. "sub-protocol\n");
  395. *err_code = 1002;
  396. *err_text = str_status_protocol_error;
  397. return -1;
  398. }
  399. if (frame->rsv1 || frame->rsv2 || frame->rsv3)
  400. {
  401. LM_WARN("WebSocket reserved fields with non-zero values\n");
  402. *err_code = 1002;
  403. *err_text = str_status_protocol_error;
  404. return -1;
  405. }
  406. switch(frame->opcode)
  407. {
  408. case OPCODE_TEXT_FRAME:
  409. case OPCODE_BINARY_FRAME:
  410. LM_DBG("supported non-control frame: 0x%x\n",
  411. (unsigned char) frame->opcode);
  412. break;
  413. case OPCODE_CLOSE:
  414. case OPCODE_PING:
  415. case OPCODE_PONG:
  416. LM_DBG("supported control frame: 0x%x\n",
  417. (unsigned char) frame->opcode);
  418. break;
  419. default:
  420. LM_WARN("unsupported opcode: 0x%x\n",
  421. (unsigned char) frame->opcode);
  422. *err_code = 1008;
  423. *err_text = str_status_unsupported_opcode;
  424. return -1;
  425. }
  426. if (!frame->mask)
  427. {
  428. LM_WARN("this is a server - all received messages must be "
  429. "masked\n");
  430. *err_code = 1002;
  431. *err_text = str_status_protocol_error;
  432. return -1;
  433. }
  434. /* Decode and validate length */
  435. frame->payload_len = (buf[1] & 0xff) & BYTE1_MASK_PAYLOAD_LEN;
  436. if (frame->payload_len == 126)
  437. {
  438. if (len < 4)
  439. {
  440. LM_WARN("message is too short\n");
  441. *err_code = 1002;
  442. *err_text = str_status_protocol_error;
  443. return -1;
  444. }
  445. mask_start = 4;
  446. frame->payload_len = ((buf[2] & 0xff) << 8)
  447. | ((buf[3] & 0xff) << 0);
  448. }
  449. else if (frame->payload_len == 127)
  450. {
  451. if (len < 10)
  452. {
  453. LM_WARN("message is too short\n");
  454. *err_code = 1002;
  455. *err_text = str_status_protocol_error;
  456. return -1;
  457. }
  458. mask_start = 10;
  459. if ((buf[2] & 0xff) != 0 || (buf[3] & 0xff) != 0
  460. || (buf[4] & 0xff) != 0 || (buf[5] & 0xff) != 0)
  461. {
  462. LM_WARN("message is too long\n");
  463. *err_code = 1009;
  464. *err_text = str_status_message_too_big;
  465. return -1;
  466. }
  467. /* Only decoding the last four bytes of the length...
  468. This limits the size of WebSocket messages that can be
  469. handled to 2^32 = which should be plenty for SIP! */
  470. frame->payload_len = ((buf[6] & 0xff) << 24)
  471. | ((buf[7] & 0xff) << 16)
  472. | ((buf[8] & 0xff) << 8)
  473. | ((buf[9] & 0xff) << 0);
  474. }
  475. else
  476. mask_start = 2;
  477. /* Decode mask */
  478. frame->masking_key[0] = (buf[mask_start + 0] & 0xff);
  479. frame->masking_key[1] = (buf[mask_start + 1] & 0xff);
  480. frame->masking_key[2] = (buf[mask_start + 2] & 0xff);
  481. frame->masking_key[3] = (buf[mask_start + 3] & 0xff);
  482. /* Decode and unmask payload */
  483. if ((unsigned long long)len != (unsigned long long)frame->payload_len
  484. + mask_start + 4)
  485. {
  486. LM_WARN("message not complete frame size %u but received %u\n",
  487. frame->payload_len + mask_start + 4, len);
  488. *err_code = 1002;
  489. *err_text = str_status_protocol_error;
  490. return -1;
  491. }
  492. frame->payload_data = &buf[mask_start + 4];
  493. for (i = 0; i < frame->payload_len; i++)
  494. {
  495. j = i % 4;
  496. frame->payload_data[i]
  497. = frame->payload_data[i] ^ frame->masking_key[j];
  498. }
  499. LM_DBG("Rx (decoded): %.*s\n",
  500. (int) frame->payload_len, frame->payload_data);
  501. return frame->opcode;
  502. }
  503. static int handle_close(ws_frame_t *frame)
  504. {
  505. unsigned short code = 0;
  506. str reason = {0, 0};
  507. if (frame->payload_len >= 2)
  508. code = ((frame->payload_data[0] & 0xff) << 8)
  509. | ((frame->payload_data[1] & 0xff) << 0);
  510. if (frame->payload_len > 2)
  511. {
  512. reason.s = &frame->payload_data[2];
  513. reason.len = frame->payload_len - 2;
  514. }
  515. LM_DBG("Rx Close: %hu %.*s\n", code, reason.len, reason.s);
  516. if (close_connection(&frame->wsc,
  517. frame->wsc->state == WS_S_OPEN ? REMOTE_CLOSE : LOCAL_CLOSE,
  518. 1000, str_status_normal_closure) < 0)
  519. {
  520. LM_ERR("closing connection\n");
  521. return -1;
  522. }
  523. return 0;
  524. }
  525. static int handle_ping(ws_frame_t *frame)
  526. {
  527. LM_DBG("Rx Ping: %.*s\n", frame->payload_len, frame->payload_data);
  528. frame->opcode = OPCODE_PONG;
  529. frame->mask = 0;
  530. if (encode_and_send_ws_frame(frame, CONN_CLOSE_DONT) < 0)
  531. {
  532. LM_ERR("sending Pong\n");
  533. return -1;
  534. }
  535. return 0;
  536. }
  537. static int handle_pong(ws_frame_t *frame)
  538. {
  539. LM_DBG("Rx Pong: %.*s\n", frame->payload_len, frame->payload_data);
  540. if (strncmp(frame->payload_data, ws_ping_application_data.s,
  541. ws_ping_application_data.len) == 0)
  542. frame->wsc->awaiting_pong = 0;
  543. return 0;
  544. }
  545. int ws_frame_receive(void *data)
  546. {
  547. ws_frame_t frame;
  548. tcp_event_info_t *tcpinfo = (tcp_event_info_t *) data;
  549. int opcode = -1;
  550. int ret = 0;
  551. short err_code = 0;
  552. str err_text = {NULL, 0};
  553. update_stat(ws_received_frames, 1);
  554. if (tcpinfo == NULL || tcpinfo->buf == NULL || tcpinfo->len <= 0)
  555. {
  556. LM_WARN("received bad frame\n");
  557. return -1;
  558. }
  559. /* wsc refcnt++ */
  560. frame.wsc = wsconn_get(tcpinfo->con->id);
  561. if (frame.wsc == NULL)
  562. {
  563. LM_ERR("WebSocket connection not found\n");
  564. return -1;
  565. }
  566. opcode = decode_and_validate_ws_frame(&frame, tcpinfo, &err_code, &err_text);
  567. if (opcode < 0)
  568. {
  569. if (close_connection(&frame.wsc, LOCAL_CLOSE, err_code, err_text) < 0)
  570. LM_ERR("closing connection\n");
  571. wsconn_put(frame.wsc);
  572. return -1;
  573. }
  574. switch(opcode)
  575. {
  576. case OPCODE_TEXT_FRAME:
  577. case OPCODE_BINARY_FRAME:
  578. if (likely(frame.wsc->sub_protocol == SUB_PROTOCOL_SIP))
  579. {
  580. LM_DBG("Rx SIP message:\n%.*s\n", frame.payload_len,
  581. frame.payload_data);
  582. update_stat(ws_sip_received_frames, 1);
  583. wsconn_put(frame.wsc);
  584. return receive_msg(frame.payload_data,
  585. frame.payload_len,
  586. tcpinfo->rcv);
  587. }
  588. else if (frame.wsc->sub_protocol == SUB_PROTOCOL_MSRP)
  589. {
  590. LM_DBG("Rx MSRP frame:\n%.*s\n", frame.payload_len,
  591. frame.payload_data);
  592. update_stat(ws_msrp_received_frames, 1);
  593. if (likely(sr_event_enabled(SREV_TCP_MSRP_FRAME)))
  594. {
  595. tcp_event_info_t tev;
  596. memset(&tev, 0, sizeof(tcp_event_info_t));
  597. tev.type = SREV_TCP_MSRP_FRAME;
  598. tev.buf = frame.payload_data;
  599. tev.len = frame.payload_len;
  600. tev.rcv = tcpinfo->rcv;
  601. tev.con = tcpinfo->con;
  602. wsconn_put(frame.wsc);
  603. return sr_event_exec(SREV_TCP_MSRP_FRAME,
  604. (void *) &tev);
  605. }
  606. else
  607. {
  608. LM_ERR("no callback registered for MSRP\n");
  609. wsconn_put(frame.wsc);
  610. return -1;
  611. }
  612. }
  613. case OPCODE_CLOSE:
  614. ret = handle_close(&frame);
  615. if (frame.wsc) wsconn_put(frame.wsc);
  616. return ret;
  617. case OPCODE_PING:
  618. ret = handle_ping(&frame);
  619. if (frame.wsc) wsconn_put(frame.wsc);
  620. return ret;
  621. case OPCODE_PONG:
  622. ret = handle_pong(&frame);
  623. if (frame.wsc) wsconn_put(frame.wsc);
  624. return ret;
  625. default:
  626. LM_WARN("received bad frame\n");
  627. wsconn_put(frame.wsc);
  628. return -1;
  629. }
  630. /* how can we get here ? */
  631. wsconn_put(frame.wsc);
  632. return 0;
  633. }
  634. int ws_frame_transmit(void *data)
  635. {
  636. ws_event_info_t *wsev = (ws_event_info_t *) data;
  637. ws_frame_t frame;
  638. memset(&frame, 0, sizeof(frame));
  639. frame.fin = 1;
  640. /* Can't be sure whether this message is UTF-8 or not so check to see
  641. if it "might" be UTF-8 and send as binary if it definitely isn't */
  642. #ifdef EMBEDDED_UTF8_DECODE
  643. frame.opcode = IsUTF8((uint8_t *) wsev->buf, wsev->len) ?
  644. OPCODE_TEXT_FRAME : OPCODE_BINARY_FRAME;
  645. #else
  646. frame.opcode = (u8_check((uint8_t *) wsev->buf, wsev->len) == NULL) ?
  647. OPCODE_TEXT_FRAME : OPCODE_BINARY_FRAME;
  648. #endif
  649. frame.payload_len = wsev->len;
  650. frame.payload_data = wsev->buf;
  651. frame.wsc = wsconn_get(wsev->id);
  652. if (frame.wsc == NULL)
  653. {
  654. LM_ERR("WebSocket outbound connection not found\n");
  655. return -1;
  656. }
  657. LM_DBG("Tx message:\n%.*s\n", frame.payload_len,
  658. frame.payload_data);
  659. if (encode_and_send_ws_frame(&frame, CONN_CLOSE_DONT) < 0)
  660. {
  661. LM_ERR("sending message\n");
  662. wsconn_put(frame.wsc);
  663. return -1;
  664. }
  665. wsconn_put(frame.wsc);
  666. return 0;
  667. }
  668. static int ping_pong(ws_connection_t *wsc, int opcode)
  669. {
  670. ws_frame_t frame;
  671. memset(&frame, 0, sizeof(frame));
  672. frame.fin = 1;
  673. frame.opcode = opcode;
  674. frame.payload_len = ws_ping_application_data.len;
  675. frame.payload_data = ws_ping_application_data.s;
  676. frame.wsc = wsc;
  677. if (encode_and_send_ws_frame(&frame, CONN_CLOSE_DONT) < 0)
  678. {
  679. LM_ERR("sending keepalive\n");
  680. return -1;
  681. }
  682. if (opcode == OPCODE_PING)
  683. wsc->awaiting_pong = 1;
  684. return 0;
  685. }
  686. struct mi_root *ws_mi_close(struct mi_root *cmd, void *param)
  687. {
  688. unsigned int id;
  689. struct mi_node *node = NULL;
  690. ws_connection_t *wsc;
  691. node = cmd->node.kids;
  692. if (node == NULL)
  693. {
  694. LM_WARN("no connection ID parameter\n");
  695. return init_mi_tree(400, str_status_empty_param.s,
  696. str_status_empty_param.len);
  697. }
  698. if (node->value.s == NULL || node->value.len == 0)
  699. {
  700. LM_WARN("empty connection ID parameter\n");
  701. return init_mi_tree(400, str_status_empty_param.s,
  702. str_status_empty_param.len);
  703. }
  704. if (str2int(&node->value, &id) < 0)
  705. {
  706. LM_ERR("converting string to int\n");
  707. return init_mi_tree(400, str_status_string_error.s,
  708. str_status_string_error.len);
  709. }
  710. if (node->next != NULL)
  711. {
  712. LM_WARN("too many parameters\n");
  713. return init_mi_tree(400, str_status_too_many_params.s,
  714. str_status_too_many_params.len);
  715. }
  716. if ((wsc = wsconn_get(id)) == NULL)
  717. {
  718. LM_WARN("bad connection ID parameter\n");
  719. return init_mi_tree(400, str_status_bad_param.s,
  720. str_status_bad_param.len);
  721. }
  722. int ret = close_connection(&wsc, LOCAL_CLOSE, 1000, str_status_normal_closure);
  723. wsconn_put(wsc);
  724. if (ret < 0)
  725. {
  726. LM_WARN("closing connection\n");
  727. return init_mi_tree(500, str_status_error_closing.s,
  728. str_status_error_closing.len);
  729. }
  730. return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  731. }
  732. static struct mi_root *mi_ping_pong(struct mi_root *cmd, void *param,
  733. int opcode)
  734. {
  735. unsigned int id;
  736. struct mi_node *node = NULL;
  737. ws_connection_t *wsc;
  738. node = cmd->node.kids;
  739. if (node == NULL)
  740. {
  741. LM_WARN("no connection ID parameter\n");
  742. return init_mi_tree(400, str_status_empty_param.s,
  743. str_status_empty_param.len);
  744. }
  745. if (node->value.s == NULL || node->value.len == 0)
  746. {
  747. LM_WARN("empty connection ID parameter\n");
  748. return init_mi_tree(400, str_status_empty_param.s,
  749. str_status_empty_param.len);
  750. }
  751. if (str2int(&node->value, &id) < 0)
  752. {
  753. LM_ERR("converting string to int\n");
  754. return init_mi_tree(400, str_status_string_error.s,
  755. str_status_string_error.len);
  756. }
  757. if (node->next != NULL)
  758. {
  759. LM_WARN("too many parameters\n");
  760. return init_mi_tree(400, str_status_too_many_params.s,
  761. str_status_too_many_params.len);
  762. }
  763. if ((wsc = wsconn_get(id)) == NULL)
  764. {
  765. LM_WARN("bad connection ID parameter\n");
  766. return init_mi_tree(400, str_status_bad_param.s,
  767. str_status_bad_param.len);
  768. }
  769. int ret = ping_pong(wsc, opcode);
  770. wsconn_put(wsc);
  771. if (ret < 0)
  772. {
  773. LM_WARN("sending %s\n", OPCODE_PING ? "Ping" : "Pong");
  774. return init_mi_tree(500, str_status_error_sending.s,
  775. str_status_error_sending.len);
  776. }
  777. return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  778. }
  779. struct mi_root *ws_mi_ping(struct mi_root *cmd, void *param)
  780. {
  781. return mi_ping_pong(cmd, param, OPCODE_PING);
  782. }
  783. struct mi_root *ws_mi_pong(struct mi_root *cmd, void *param)
  784. {
  785. return mi_ping_pong(cmd, param, OPCODE_PONG);
  786. }
  787. void ws_keepalive(unsigned int ticks, void *param)
  788. {
  789. int check_time = (int) time(NULL)
  790. - cfg_get(websocket, ws_cfg, keepalive_timeout);
  791. ws_connection_t **list = NULL,
  792. **list_head = NULL;
  793. ws_connection_t *wsc = NULL;
  794. /* get an array of pointer to all ws connection */
  795. list_head = wsconn_get_list();
  796. if (!list_head)
  797. return;
  798. list = list_head;
  799. wsc = *list_head;
  800. while (wsc && wsc->last_used < check_time)
  801. {
  802. if (wsc->state == WS_S_CLOSING || wsc->awaiting_pong)
  803. {
  804. LM_WARN("forcibly closing connection\n");
  805. wsconn_close_now(wsc);
  806. }
  807. else
  808. {
  809. int opcode = (ws_keepalive_mechanism == KEEPALIVE_MECHANISM_PING)
  810. ? OPCODE_PING
  811. : OPCODE_PONG;
  812. ping_pong(wsc, opcode);
  813. }
  814. wsc = *(++list);
  815. }
  816. wsconn_put_list(list_head);
  817. }
  818. int ws_close(sip_msg_t *msg)
  819. {
  820. ws_connection_t *wsc;
  821. int ret;
  822. if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) == NULL) {
  823. LM_ERR("failed to retrieve WebSocket connection\n");
  824. return -1;
  825. }
  826. ret = (close_connection(&wsc, LOCAL_CLOSE, 1000,
  827. str_status_normal_closure) == 0) ? 1: 0;
  828. wsconn_put(wsc);
  829. return ret;
  830. }
  831. int ws_close2(sip_msg_t *msg, char *_status, char *_reason)
  832. {
  833. int status;
  834. str reason;
  835. ws_connection_t *wsc;
  836. int ret;
  837. if (get_int_fparam(&status, msg, (fparam_t *) _status) < 0) {
  838. LM_ERR("failed to get status code\n");
  839. return -1;
  840. }
  841. if (get_str_fparam(&reason, msg, (fparam_t *) _reason) < 0) {
  842. LM_ERR("failed to get reason string\n");
  843. return -1;
  844. }
  845. if ((wsc = wsconn_get(msg->rcv.proto_reserved1)) == NULL) {
  846. LM_ERR("failed to retrieve WebSocket connection\n");
  847. return -1;
  848. }
  849. ret = (close_connection(&wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
  850. wsconn_put(wsc);
  851. return ret;
  852. }
  853. int ws_close3(sip_msg_t *msg, char *_status, char *_reason, char *_con)
  854. {
  855. int status;
  856. str reason;
  857. int con;
  858. ws_connection_t *wsc;
  859. int ret;
  860. if (get_int_fparam(&status, msg, (fparam_t *) _status) < 0) {
  861. LM_ERR("failed to get status code\n");
  862. return -1;
  863. }
  864. if (get_str_fparam(&reason, msg, (fparam_t *) _reason) < 0) {
  865. LM_ERR("failed to get reason string\n");
  866. return -1;
  867. }
  868. if (get_int_fparam(&con, msg, (fparam_t *) _con) < 0) {
  869. LM_ERR("failed to get connection ID\n");
  870. return -1;
  871. }
  872. if ((wsc = wsconn_get(con)) == NULL) {
  873. LM_ERR("failed to retrieve WebSocket connection\n");
  874. return -1;
  875. }
  876. ret = (close_connection(&wsc, LOCAL_CLOSE, status, reason) == 0) ? 1: 0;
  877. wsconn_put(wsc);
  878. return ret;
  879. }