ws_frame.c 20 KB

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