wslay_event.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  1. /*
  2. * Wslay - The WebSocket Library
  3. *
  4. * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "wslay_event.h"
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <stdio.h>
  29. #include "wslay_frame.h"
  30. #include "wslay_net.h"
  31. #include "wslay_macro.h"
  32. /* Start of utf8 dfa */
  33. /* Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  34. * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
  35. *
  36. * Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  37. *
  38. * Permission is hereby granted, free of charge, to any person
  39. * obtaining a copy of this software and associated documentation
  40. * files (the "Software"), to deal in the Software without
  41. * restriction, including without limitation the rights to use, copy,
  42. * modify, merge, publish, distribute, sublicense, and/or sell copies
  43. * of the Software, and to permit persons to whom the Software is
  44. * furnished to do so, subject to the following conditions:
  45. *
  46. * The above copyright notice and this permission notice shall be
  47. * included in all copies or substantial portions of the Software.
  48. *
  49. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  50. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  51. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  52. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  53. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  54. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  55. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  56. * SOFTWARE.
  57. */
  58. #define UTF8_ACCEPT 0
  59. #define UTF8_REJECT 12
  60. /* clang-format off */
  61. static const uint8_t utf8d[] = {
  62. /*
  63. * The first part of the table maps bytes to character classes that
  64. * to reduce the size of the transition table and create bitmasks.
  65. */
  66. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  67. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  68. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  69. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  70. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
  71. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  72. 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  73. 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
  74. /*
  75. * The second part is a transition table that maps a combination
  76. * of a state of the automaton and a character class to a state.
  77. */
  78. 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
  79. 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
  80. 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
  81. 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
  82. 12,36,12,12,12,12,12,12,12,12,12,12,
  83. };
  84. /* clang-format on */
  85. static uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte) {
  86. uint32_t type = utf8d[byte];
  87. *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6)
  88. : (0xff >> type) & (byte);
  89. *state = utf8d[256 + *state + type];
  90. return *state;
  91. }
  92. /* End of utf8 dfa */
  93. static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len,
  94. int flags, void *user_data) {
  95. struct wslay_event_frame_user_data *e =
  96. (struct wslay_event_frame_user_data *)user_data;
  97. return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data);
  98. }
  99. static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len,
  100. int flags, void *user_data) {
  101. struct wslay_event_frame_user_data *e =
  102. (struct wslay_event_frame_user_data *)user_data;
  103. return e->ctx->callbacks.send_callback(e->ctx, data, len, flags,
  104. e->user_data);
  105. }
  106. static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len,
  107. void *user_data) {
  108. struct wslay_event_frame_user_data *e =
  109. (struct wslay_event_frame_user_data *)user_data;
  110. return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data);
  111. }
  112. static int wslay_event_byte_chunk_init(struct wslay_event_byte_chunk **chunk,
  113. size_t len) {
  114. *chunk = malloc(sizeof(struct wslay_event_byte_chunk) + len);
  115. if (*chunk == NULL) {
  116. return WSLAY_ERR_NOMEM;
  117. }
  118. memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk));
  119. if (len) {
  120. (*chunk)->data = (uint8_t *)(*chunk) + sizeof(**chunk);
  121. (*chunk)->data_length = len;
  122. }
  123. return 0;
  124. }
  125. static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) {
  126. free(c);
  127. }
  128. static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c,
  129. size_t off, const uint8_t *data,
  130. size_t data_length) {
  131. memcpy(c->data + off, data, data_length);
  132. }
  133. static void wslay_event_imsg_set(struct wslay_event_imsg *m, uint8_t fin,
  134. uint8_t rsv, uint8_t opcode) {
  135. m->fin = fin;
  136. m->rsv = rsv;
  137. m->opcode = opcode;
  138. m->msg_length = 0;
  139. }
  140. static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) {
  141. while (!wslay_queue_empty(&m->chunks)) {
  142. struct wslay_event_byte_chunk *chunk = wslay_struct_of(
  143. wslay_queue_top(&m->chunks), struct wslay_event_byte_chunk, qe);
  144. wslay_queue_pop(&m->chunks);
  145. wslay_event_byte_chunk_free(chunk);
  146. }
  147. }
  148. static void wslay_event_imsg_reset(struct wslay_event_imsg *m) {
  149. m->opcode = 0xffu;
  150. m->utf8state = UTF8_ACCEPT;
  151. wslay_event_imsg_chunks_free(m);
  152. }
  153. static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m,
  154. size_t len) {
  155. if (len == 0) {
  156. return 0;
  157. } else {
  158. int r;
  159. struct wslay_event_byte_chunk *chunk;
  160. if ((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) {
  161. return r;
  162. }
  163. wslay_queue_push(&m->chunks, &chunk->qe);
  164. m->msg_length += len;
  165. return 0;
  166. }
  167. }
  168. static int wslay_event_omsg_non_fragmented_init(struct wslay_event_omsg **m,
  169. uint8_t opcode, uint8_t rsv,
  170. const uint8_t *msg,
  171. size_t msg_length) {
  172. *m = malloc(sizeof(struct wslay_event_omsg) + msg_length);
  173. if (!*m) {
  174. return WSLAY_ERR_NOMEM;
  175. }
  176. memset(*m, 0, sizeof(struct wslay_event_omsg));
  177. (*m)->fin = 1;
  178. (*m)->opcode = opcode;
  179. (*m)->rsv = rsv;
  180. (*m)->type = WSLAY_NON_FRAGMENTED;
  181. if (msg_length) {
  182. (*m)->data = (uint8_t *)(*m) + sizeof(**m);
  183. memcpy((*m)->data, msg, msg_length);
  184. (*m)->data_length = msg_length;
  185. }
  186. return 0;
  187. }
  188. static int wslay_event_omsg_fragmented_init(
  189. struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv,
  190. const union wslay_event_msg_source source,
  191. wslay_event_fragmented_msg_callback read_callback) {
  192. *m = calloc(1, sizeof(struct wslay_event_omsg));
  193. if (!*m) {
  194. return WSLAY_ERR_NOMEM;
  195. }
  196. (*m)->opcode = opcode;
  197. (*m)->rsv = rsv;
  198. (*m)->type = WSLAY_FRAGMENTED;
  199. (*m)->source = source;
  200. (*m)->read_callback = read_callback;
  201. return 0;
  202. }
  203. static void wslay_event_omsg_free(struct wslay_event_omsg *m) { free(m); }
  204. static uint8_t *wslay_event_flatten_queue(struct wslay_queue *queue,
  205. size_t len) {
  206. if (len == 0) {
  207. return NULL;
  208. } else {
  209. size_t off = 0;
  210. uint8_t *buf = malloc(len);
  211. if (!buf) {
  212. return NULL;
  213. }
  214. while (!wslay_queue_empty(queue)) {
  215. struct wslay_event_byte_chunk *chunk = wslay_struct_of(
  216. wslay_queue_top(queue), struct wslay_event_byte_chunk, qe);
  217. wslay_queue_pop(queue);
  218. memcpy(buf + off, chunk->data, chunk->data_length);
  219. off += chunk->data_length;
  220. wslay_event_byte_chunk_free(chunk);
  221. assert(off <= len);
  222. }
  223. assert(len == off);
  224. return buf;
  225. }
  226. }
  227. static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) {
  228. return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0;
  229. }
  230. int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code,
  231. const uint8_t *reason, size_t reason_length) {
  232. if (!wslay_event_is_msg_queueable(ctx)) {
  233. return WSLAY_ERR_NO_MORE_MSG;
  234. } else if (reason_length > 123) {
  235. return WSLAY_ERR_INVALID_ARGUMENT;
  236. } else {
  237. uint8_t msg[128];
  238. size_t msg_length;
  239. struct wslay_event_msg arg;
  240. uint16_t ncode;
  241. int r;
  242. if (status_code == 0) {
  243. msg_length = 0;
  244. } else {
  245. ncode = htons(status_code);
  246. memcpy(msg, &ncode, 2);
  247. if (reason_length) {
  248. memcpy(msg + 2, reason, reason_length);
  249. }
  250. msg_length = reason_length + 2;
  251. }
  252. arg.opcode = WSLAY_CONNECTION_CLOSE;
  253. arg.msg = msg;
  254. arg.msg_length = msg_length;
  255. r = wslay_event_queue_msg(ctx, &arg);
  256. if (r == 0) {
  257. ctx->close_status |= WSLAY_CLOSE_QUEUED;
  258. }
  259. return r;
  260. }
  261. }
  262. static int wslay_event_queue_close_wrapper(wslay_event_context_ptr ctx,
  263. uint16_t status_code,
  264. const uint8_t *reason,
  265. size_t reason_length) {
  266. int r;
  267. ctx->read_enabled = 0;
  268. if ((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) &&
  269. r != WSLAY_ERR_NO_MORE_MSG) {
  270. return r;
  271. }
  272. return 0;
  273. }
  274. static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx,
  275. uint8_t rsv) {
  276. return ((rsv & ~ctx->allowed_rsv_bits) == 0);
  277. }
  278. int wslay_event_queue_msg(wslay_event_context_ptr ctx,
  279. const struct wslay_event_msg *arg) {
  280. return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE);
  281. }
  282. int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx,
  283. const struct wslay_event_msg *arg, uint8_t rsv) {
  284. int r;
  285. struct wslay_event_omsg *omsg;
  286. if (!wslay_event_is_msg_queueable(ctx)) {
  287. return WSLAY_ERR_NO_MORE_MSG;
  288. }
  289. /* RSV1 is not allowed for control frames */
  290. if ((wslay_is_ctrl_frame(arg->opcode) &&
  291. (arg->msg_length > 125 || wslay_get_rsv1(rsv))) ||
  292. !wslay_event_verify_rsv_bits(ctx, rsv)) {
  293. return WSLAY_ERR_INVALID_ARGUMENT;
  294. }
  295. if ((r = wslay_event_omsg_non_fragmented_init(
  296. &omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) {
  297. return r;
  298. }
  299. if (wslay_is_ctrl_frame(arg->opcode)) {
  300. wslay_queue_push(&ctx->send_ctrl_queue, &omsg->qe);
  301. } else {
  302. wslay_queue_push(&ctx->send_queue, &omsg->qe);
  303. }
  304. ++ctx->queued_msg_count;
  305. ctx->queued_msg_length += arg->msg_length;
  306. return 0;
  307. }
  308. int wslay_event_queue_fragmented_msg(
  309. wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) {
  310. return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE);
  311. }
  312. int wslay_event_queue_fragmented_msg_ex(
  313. wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg,
  314. uint8_t rsv) {
  315. int r;
  316. struct wslay_event_omsg *omsg;
  317. if (!wslay_event_is_msg_queueable(ctx)) {
  318. return WSLAY_ERR_NO_MORE_MSG;
  319. }
  320. if (wslay_is_ctrl_frame(arg->opcode) ||
  321. !wslay_event_verify_rsv_bits(ctx, rsv)) {
  322. return WSLAY_ERR_INVALID_ARGUMENT;
  323. }
  324. if ((r = wslay_event_omsg_fragmented_init(
  325. &omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) {
  326. return r;
  327. }
  328. wslay_queue_push(&ctx->send_queue, &omsg->qe);
  329. ++ctx->queued_msg_count;
  330. return 0;
  331. }
  332. void wslay_event_config_set_callbacks(
  333. wslay_event_context_ptr ctx,
  334. const struct wslay_event_callbacks *callbacks) {
  335. ctx->callbacks = *callbacks;
  336. }
  337. static int
  338. wslay_event_context_init(wslay_event_context_ptr *ctx,
  339. const struct wslay_event_callbacks *callbacks,
  340. void *user_data) {
  341. int i, r;
  342. struct wslay_frame_callbacks frame_callbacks = {
  343. wslay_event_frame_send_callback, wslay_event_frame_recv_callback,
  344. wslay_event_frame_genmask_callback};
  345. *ctx = calloc(1, sizeof(struct wslay_event_context));
  346. if (!*ctx) {
  347. return WSLAY_ERR_NOMEM;
  348. }
  349. wslay_event_config_set_callbacks(*ctx, callbacks);
  350. (*ctx)->user_data = user_data;
  351. (*ctx)->frame_user_data.ctx = *ctx;
  352. (*ctx)->frame_user_data.user_data = user_data;
  353. if ((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks,
  354. &(*ctx)->frame_user_data)) != 0) {
  355. wslay_event_context_free(*ctx);
  356. return r;
  357. }
  358. (*ctx)->read_enabled = (*ctx)->write_enabled = 1;
  359. wslay_queue_init(&(*ctx)->send_queue);
  360. wslay_queue_init(&(*ctx)->send_ctrl_queue);
  361. (*ctx)->queued_msg_count = 0;
  362. (*ctx)->queued_msg_length = 0;
  363. for (i = 0; i < 2; ++i) {
  364. wslay_queue_init(&(*ctx)->imsgs[i].chunks);
  365. wslay_event_imsg_reset(&(*ctx)->imsgs[i]);
  366. }
  367. (*ctx)->imsg = &(*ctx)->imsgs[0];
  368. (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf;
  369. (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE;
  370. (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE;
  371. (*ctx)->max_recv_msg_length = (1u << 31) - 1;
  372. return 0;
  373. }
  374. int wslay_event_context_server_init(
  375. wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks,
  376. void *user_data) {
  377. int r;
  378. if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) {
  379. return r;
  380. }
  381. (*ctx)->server = 1;
  382. return 0;
  383. }
  384. int wslay_event_context_client_init(
  385. wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks,
  386. void *user_data) {
  387. int r;
  388. if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) {
  389. return r;
  390. }
  391. (*ctx)->server = 0;
  392. return 0;
  393. }
  394. void wslay_event_context_free(wslay_event_context_ptr ctx) {
  395. int i;
  396. if (!ctx) {
  397. return;
  398. }
  399. for (i = 0; i < 2; ++i) {
  400. wslay_event_imsg_chunks_free(&ctx->imsgs[i]);
  401. wslay_queue_deinit(&ctx->imsgs[i].chunks);
  402. }
  403. while (!wslay_queue_empty(&ctx->send_queue)) {
  404. struct wslay_event_omsg *omsg = wslay_struct_of(
  405. wslay_queue_top(&ctx->send_queue), struct wslay_event_omsg, qe);
  406. wslay_queue_pop(&ctx->send_queue);
  407. wslay_event_omsg_free(omsg);
  408. }
  409. wslay_queue_deinit(&ctx->send_queue);
  410. while (!wslay_queue_empty(&ctx->send_ctrl_queue)) {
  411. struct wslay_event_omsg *omsg = wslay_struct_of(
  412. wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe);
  413. wslay_queue_pop(&ctx->send_ctrl_queue);
  414. wslay_event_omsg_free(omsg);
  415. }
  416. wslay_queue_deinit(&ctx->send_ctrl_queue);
  417. wslay_frame_context_free(ctx->frame_ctx);
  418. wslay_event_omsg_free(ctx->omsg);
  419. free(ctx);
  420. }
  421. static void wslay_event_call_on_frame_recv_start_callback(
  422. wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) {
  423. if (ctx->callbacks.on_frame_recv_start_callback) {
  424. struct wslay_event_on_frame_recv_start_arg arg;
  425. arg.fin = iocb->fin;
  426. arg.rsv = iocb->rsv;
  427. arg.opcode = iocb->opcode;
  428. arg.payload_length = iocb->payload_length;
  429. ctx->callbacks.on_frame_recv_start_callback(ctx, &arg, ctx->user_data);
  430. }
  431. }
  432. static void wslay_event_call_on_frame_recv_chunk_callback(
  433. wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) {
  434. if (ctx->callbacks.on_frame_recv_chunk_callback) {
  435. struct wslay_event_on_frame_recv_chunk_arg arg;
  436. arg.data = iocb->data;
  437. arg.data_length = iocb->data_length;
  438. ctx->callbacks.on_frame_recv_chunk_callback(ctx, &arg, ctx->user_data);
  439. }
  440. }
  441. static void
  442. wslay_event_call_on_frame_recv_end_callback(wslay_event_context_ptr ctx) {
  443. if (ctx->callbacks.on_frame_recv_end_callback) {
  444. ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data);
  445. }
  446. }
  447. static int wslay_event_is_valid_status_code(uint16_t status_code) {
  448. return (1000 <= status_code && status_code <= 1011 && status_code != 1004 &&
  449. status_code != 1005 && status_code != 1006) ||
  450. (3000 <= status_code && status_code <= 4999);
  451. }
  452. static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) {
  453. return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0;
  454. }
  455. int wslay_event_recv(wslay_event_context_ptr ctx) {
  456. struct wslay_frame_iocb iocb;
  457. ssize_t r;
  458. while (ctx->read_enabled) {
  459. memset(&iocb, 0, sizeof(iocb));
  460. r = wslay_frame_recv(ctx->frame_ctx, &iocb);
  461. if (r >= 0) {
  462. int new_frame = 0;
  463. /* RSV1 is not allowed on control and continuation frames */
  464. if ((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) ||
  465. (wslay_get_rsv1(iocb.rsv) &&
  466. (wslay_is_ctrl_frame(iocb.opcode) ||
  467. iocb.opcode == WSLAY_CONTINUATION_FRAME)) ||
  468. (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) {
  469. if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR,
  470. NULL, 0)) != 0) {
  471. return (int)r;
  472. }
  473. break;
  474. }
  475. if (ctx->imsg->opcode == 0xffu) {
  476. if (iocb.opcode == WSLAY_TEXT_FRAME ||
  477. iocb.opcode == WSLAY_BINARY_FRAME ||
  478. iocb.opcode == WSLAY_CONNECTION_CLOSE ||
  479. iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) {
  480. wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
  481. new_frame = 1;
  482. } else {
  483. if ((r = wslay_event_queue_close_wrapper(
  484. ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
  485. return (int)r;
  486. }
  487. break;
  488. }
  489. } else if (ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) {
  490. if (iocb.opcode == WSLAY_CONTINUATION_FRAME) {
  491. ctx->imsg->fin = iocb.fin;
  492. } else if (iocb.opcode == WSLAY_CONNECTION_CLOSE ||
  493. iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) {
  494. ctx->imsg = &ctx->imsgs[1];
  495. wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode);
  496. } else {
  497. if ((r = wslay_event_queue_close_wrapper(
  498. ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
  499. return (int)r;
  500. }
  501. break;
  502. }
  503. new_frame = 1;
  504. }
  505. if (new_frame) {
  506. if (ctx->imsg->msg_length + iocb.payload_length >
  507. ctx->max_recv_msg_length) {
  508. if ((r = wslay_event_queue_close_wrapper(
  509. ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) {
  510. return (int)r;
  511. }
  512. break;
  513. }
  514. ctx->ipayloadlen = iocb.payload_length;
  515. wslay_event_call_on_frame_recv_start_callback(ctx, &iocb);
  516. if (!wslay_event_config_get_no_buffering(ctx) ||
  517. wslay_is_ctrl_frame(iocb.opcode)) {
  518. if ((r = wslay_event_imsg_append_chunk(ctx->imsg,
  519. iocb.payload_length)) != 0) {
  520. ctx->read_enabled = 0;
  521. return (int)r;
  522. }
  523. }
  524. }
  525. /* If RSV1 bit is set then it is too early for utf-8 validation */
  526. if ((!wslay_get_rsv1(ctx->imsg->rsv) &&
  527. ctx->imsg->opcode == WSLAY_TEXT_FRAME) ||
  528. ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
  529. size_t i;
  530. if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
  531. i = 2;
  532. } else {
  533. i = 0;
  534. }
  535. for (; i < iocb.data_length; ++i) {
  536. uint32_t codep;
  537. if (decode(&ctx->imsg->utf8state, &codep, iocb.data[i]) ==
  538. UTF8_REJECT) {
  539. if ((r = wslay_event_queue_close_wrapper(
  540. ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) !=
  541. 0) {
  542. return (int)r;
  543. }
  544. break;
  545. }
  546. }
  547. }
  548. if (ctx->imsg->utf8state == UTF8_REJECT) {
  549. break;
  550. }
  551. wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb);
  552. if (iocb.data_length > 0) {
  553. if (!wslay_event_config_get_no_buffering(ctx) ||
  554. wslay_is_ctrl_frame(iocb.opcode)) {
  555. struct wslay_event_byte_chunk *chunk;
  556. chunk = wslay_struct_of(wslay_queue_tail(&ctx->imsg->chunks),
  557. struct wslay_event_byte_chunk, qe);
  558. wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, iocb.data,
  559. iocb.data_length);
  560. }
  561. ctx->ipayloadoff += iocb.data_length;
  562. }
  563. if (ctx->ipayloadoff == ctx->ipayloadlen) {
  564. if (ctx->imsg->fin &&
  565. (ctx->imsg->opcode == WSLAY_TEXT_FRAME ||
  566. ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) &&
  567. ctx->imsg->utf8state != UTF8_ACCEPT) {
  568. if ((r = wslay_event_queue_close_wrapper(
  569. ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) {
  570. return (int)r;
  571. }
  572. break;
  573. }
  574. wslay_event_call_on_frame_recv_end_callback(ctx);
  575. if (ctx->imsg->fin) {
  576. if (ctx->callbacks.on_msg_recv_callback ||
  577. ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE ||
  578. ctx->imsg->opcode == WSLAY_PING) {
  579. struct wslay_event_on_msg_recv_arg arg;
  580. uint16_t status_code = 0;
  581. uint8_t *msg = NULL;
  582. size_t msg_length = 0;
  583. if (!wslay_event_config_get_no_buffering(ctx) ||
  584. wslay_is_ctrl_frame(iocb.opcode)) {
  585. msg = wslay_event_flatten_queue(&ctx->imsg->chunks,
  586. ctx->imsg->msg_length);
  587. if (ctx->imsg->msg_length && !msg) {
  588. ctx->read_enabled = 0;
  589. return WSLAY_ERR_NOMEM;
  590. }
  591. msg_length = ctx->imsg->msg_length;
  592. }
  593. if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
  594. const uint8_t *reason;
  595. size_t reason_length;
  596. if (ctx->imsg->msg_length >= 2) {
  597. memcpy(&status_code, msg, 2);
  598. status_code = ntohs(status_code);
  599. if (!wslay_event_is_valid_status_code(status_code)) {
  600. free(msg);
  601. if ((r = wslay_event_queue_close_wrapper(
  602. ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
  603. return (int)r;
  604. }
  605. break;
  606. }
  607. reason = msg + 2;
  608. reason_length = ctx->imsg->msg_length - 2;
  609. } else {
  610. reason = NULL;
  611. reason_length = 0;
  612. }
  613. ctx->close_status |= WSLAY_CLOSE_RECEIVED;
  614. ctx->status_code_recv =
  615. status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
  616. if ((r = wslay_event_queue_close_wrapper(ctx, status_code, reason,
  617. reason_length)) != 0) {
  618. free(msg);
  619. return (int)r;
  620. }
  621. } else if (ctx->imsg->opcode == WSLAY_PING) {
  622. struct wslay_event_msg pong_arg;
  623. pong_arg.opcode = WSLAY_PONG;
  624. pong_arg.msg = msg;
  625. pong_arg.msg_length = ctx->imsg->msg_length;
  626. if ((r = wslay_event_queue_msg(ctx, &pong_arg)) &&
  627. r != WSLAY_ERR_NO_MORE_MSG) {
  628. ctx->read_enabled = 0;
  629. free(msg);
  630. return (int)r;
  631. }
  632. }
  633. if (ctx->callbacks.on_msg_recv_callback) {
  634. arg.rsv = ctx->imsg->rsv;
  635. arg.opcode = ctx->imsg->opcode;
  636. arg.msg = msg;
  637. arg.msg_length = msg_length;
  638. arg.status_code = status_code;
  639. ctx->error = 0;
  640. ctx->callbacks.on_msg_recv_callback(ctx, &arg, ctx->user_data);
  641. }
  642. free(msg);
  643. }
  644. wslay_event_imsg_reset(ctx->imsg);
  645. if (ctx->imsg == &ctx->imsgs[1]) {
  646. ctx->imsg = &ctx->imsgs[0];
  647. }
  648. }
  649. ctx->ipayloadlen = ctx->ipayloadoff = 0;
  650. }
  651. } else {
  652. if (r != WSLAY_ERR_WANT_READ ||
  653. (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
  654. if ((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) {
  655. return (int)r;
  656. }
  657. return WSLAY_ERR_CALLBACK_FAILURE;
  658. }
  659. break;
  660. }
  661. }
  662. return 0;
  663. }
  664. static void
  665. wslay_event_on_non_fragmented_msg_popped(wslay_event_context_ptr ctx) {
  666. ctx->omsg->fin = 1;
  667. ctx->opayloadlen = ctx->omsg->data_length;
  668. ctx->opayloadoff = 0;
  669. }
  670. static struct wslay_event_omsg *
  671. wslay_event_send_ctrl_queue_pop(wslay_event_context_ptr ctx) {
  672. /*
  673. * If Close control frame is queued, we don't send any control frame
  674. * other than Close.
  675. */
  676. if (ctx->close_status & WSLAY_CLOSE_QUEUED) {
  677. while (!wslay_queue_empty(&ctx->send_ctrl_queue)) {
  678. struct wslay_event_omsg *msg = wslay_struct_of(
  679. wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe);
  680. wslay_queue_pop(&ctx->send_ctrl_queue);
  681. if (msg->opcode == WSLAY_CONNECTION_CLOSE) {
  682. return msg;
  683. } else {
  684. wslay_event_omsg_free(msg);
  685. }
  686. }
  687. return NULL;
  688. } else {
  689. struct wslay_event_omsg *msg = wslay_struct_of(
  690. wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe);
  691. wslay_queue_pop(&ctx->send_ctrl_queue);
  692. return msg;
  693. }
  694. }
  695. int wslay_event_send(wslay_event_context_ptr ctx) {
  696. struct wslay_frame_iocb iocb;
  697. ssize_t r;
  698. while (ctx->write_enabled &&
  699. (!wslay_queue_empty(&ctx->send_queue) ||
  700. !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) {
  701. if (!ctx->omsg) {
  702. if (wslay_queue_empty(&ctx->send_ctrl_queue)) {
  703. ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue),
  704. struct wslay_event_omsg, qe);
  705. wslay_queue_pop(&ctx->send_queue);
  706. } else {
  707. ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
  708. if (ctx->omsg == NULL) {
  709. break;
  710. }
  711. }
  712. if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
  713. wslay_event_on_non_fragmented_msg_popped(ctx);
  714. }
  715. } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) &&
  716. ctx->frame_ctx->ostate == PREP_HEADER &&
  717. !wslay_queue_empty(&ctx->send_ctrl_queue)) {
  718. wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe);
  719. ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
  720. if (ctx->omsg == NULL) {
  721. break;
  722. }
  723. /* ctrl message has WSLAY_NON_FRAGMENTED */
  724. wslay_event_on_non_fragmented_msg_popped(ctx);
  725. }
  726. if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
  727. memset(&iocb, 0, sizeof(iocb));
  728. iocb.fin = 1;
  729. iocb.opcode = ctx->omsg->opcode;
  730. iocb.rsv = ctx->omsg->rsv;
  731. iocb.mask = ctx->server ^ 1;
  732. iocb.data = ctx->omsg->data;
  733. iocb.data_length = ctx->opayloadlen;
  734. if (ctx->opayloadoff) {
  735. iocb.data += ctx->opayloadoff;
  736. iocb.data_length -= ctx->opayloadoff;
  737. }
  738. iocb.payload_length = ctx->opayloadlen;
  739. r = wslay_frame_send(ctx->frame_ctx, &iocb);
  740. if (r >= 0) {
  741. ctx->opayloadoff += (uint64_t)r;
  742. if (ctx->opayloadoff == ctx->opayloadlen) {
  743. --ctx->queued_msg_count;
  744. ctx->queued_msg_length -= ctx->omsg->data_length;
  745. if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) {
  746. uint16_t status_code = 0;
  747. ctx->write_enabled = 0;
  748. ctx->close_status |= WSLAY_CLOSE_SENT;
  749. if (ctx->omsg->data_length >= 2) {
  750. memcpy(&status_code, ctx->omsg->data, 2);
  751. status_code = ntohs(status_code);
  752. }
  753. ctx->status_code_sent =
  754. status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
  755. }
  756. wslay_event_omsg_free(ctx->omsg);
  757. ctx->omsg = NULL;
  758. } else {
  759. break;
  760. }
  761. } else {
  762. if (r != WSLAY_ERR_WANT_WRITE ||
  763. (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
  764. ctx->write_enabled = 0;
  765. return WSLAY_ERR_CALLBACK_FAILURE;
  766. }
  767. break;
  768. }
  769. } else {
  770. if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) {
  771. int eof = 0;
  772. r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf),
  773. &ctx->omsg->source, &eof, ctx->user_data);
  774. if (r == 0 && eof == 0) {
  775. break;
  776. } else if (r < 0) {
  777. ctx->write_enabled = 0;
  778. return WSLAY_ERR_CALLBACK_FAILURE;
  779. }
  780. ctx->obuflimit = ctx->obuf + r;
  781. if (eof) {
  782. ctx->omsg->fin = 1;
  783. }
  784. ctx->opayloadlen = (uint64_t)r;
  785. ctx->opayloadoff = 0;
  786. }
  787. memset(&iocb, 0, sizeof(iocb));
  788. iocb.fin = ctx->omsg->fin;
  789. iocb.opcode = ctx->omsg->opcode;
  790. iocb.rsv = ctx->omsg->rsv;
  791. iocb.mask = ctx->server ? 0 : 1;
  792. iocb.data = ctx->obufmark;
  793. iocb.data_length = (size_t)(ctx->obuflimit - ctx->obufmark);
  794. iocb.payload_length = ctx->opayloadlen;
  795. r = wslay_frame_send(ctx->frame_ctx, &iocb);
  796. if (r >= 0) {
  797. ctx->obufmark += r;
  798. if (ctx->obufmark == ctx->obuflimit) {
  799. ctx->obufmark = ctx->obuflimit = ctx->obuf;
  800. if (ctx->omsg->fin) {
  801. --ctx->queued_msg_count;
  802. wslay_event_omsg_free(ctx->omsg);
  803. ctx->omsg = NULL;
  804. } else {
  805. ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME;
  806. /* RSV1 is not set on continuation frames */
  807. ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT);
  808. }
  809. } else {
  810. break;
  811. }
  812. } else {
  813. if (r != WSLAY_ERR_WANT_WRITE ||
  814. (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) {
  815. ctx->write_enabled = 0;
  816. return WSLAY_ERR_CALLBACK_FAILURE;
  817. }
  818. break;
  819. }
  820. }
  821. }
  822. return 0;
  823. }
  824. ssize_t wslay_event_write(wslay_event_context_ptr ctx, uint8_t *buf,
  825. size_t buflen) {
  826. struct wslay_frame_iocb iocb;
  827. ssize_t r;
  828. uint8_t *buf_last = buf;
  829. size_t wpayloadlen;
  830. while (ctx->write_enabled &&
  831. (!wslay_queue_empty(&ctx->send_queue) ||
  832. !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) {
  833. if (!ctx->omsg) {
  834. if (wslay_queue_empty(&ctx->send_ctrl_queue)) {
  835. ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue),
  836. struct wslay_event_omsg, qe);
  837. wslay_queue_pop(&ctx->send_queue);
  838. } else {
  839. ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
  840. if (ctx->omsg == NULL) {
  841. break;
  842. }
  843. }
  844. if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
  845. wslay_event_on_non_fragmented_msg_popped(ctx);
  846. }
  847. } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) &&
  848. ctx->frame_ctx->ostate == PREP_HEADER &&
  849. !wslay_queue_empty(&ctx->send_ctrl_queue)) {
  850. wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe);
  851. ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx);
  852. if (ctx->omsg == NULL) {
  853. break;
  854. }
  855. /* ctrl message has WSLAY_NON_FRAGMENTED */
  856. wslay_event_on_non_fragmented_msg_popped(ctx);
  857. }
  858. if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) {
  859. memset(&iocb, 0, sizeof(iocb));
  860. iocb.fin = 1;
  861. iocb.opcode = ctx->omsg->opcode;
  862. iocb.rsv = ctx->omsg->rsv;
  863. iocb.mask = ctx->server ^ 1;
  864. iocb.data = ctx->omsg->data;
  865. iocb.data_length = ctx->opayloadlen;
  866. if (ctx->opayloadoff) {
  867. iocb.data += ctx->opayloadoff;
  868. iocb.data_length -= ctx->opayloadoff;
  869. }
  870. iocb.payload_length = ctx->opayloadlen;
  871. r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen,
  872. &wpayloadlen);
  873. if (r > 0) {
  874. assert((size_t)r <= buflen);
  875. buf_last += r;
  876. buflen -= (size_t)r;
  877. ctx->opayloadoff += wpayloadlen;
  878. if (ctx->opayloadoff == ctx->opayloadlen) {
  879. --ctx->queued_msg_count;
  880. ctx->queued_msg_length -= ctx->omsg->data_length;
  881. if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) {
  882. uint16_t status_code = 0;
  883. ctx->write_enabled = 0;
  884. ctx->close_status |= WSLAY_CLOSE_SENT;
  885. if (ctx->omsg->data_length >= 2) {
  886. memcpy(&status_code, ctx->omsg->data, 2);
  887. status_code = ntohs(status_code);
  888. }
  889. ctx->status_code_sent =
  890. status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code;
  891. }
  892. wslay_event_omsg_free(ctx->omsg);
  893. ctx->omsg = NULL;
  894. } else {
  895. break;
  896. }
  897. } else if (r == 0) {
  898. return buf_last - buf;
  899. } else {
  900. return WSLAY_ERR_CALLBACK_FAILURE;
  901. }
  902. } else {
  903. if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) {
  904. int eof = 0;
  905. r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf),
  906. &ctx->omsg->source, &eof, ctx->user_data);
  907. if (r == 0 && eof == 0) {
  908. break;
  909. } else if (r < 0) {
  910. ctx->write_enabled = 0;
  911. return WSLAY_ERR_CALLBACK_FAILURE;
  912. }
  913. ctx->obuflimit = ctx->obuf + r;
  914. if (eof) {
  915. ctx->omsg->fin = 1;
  916. }
  917. ctx->opayloadlen = (uint64_t)r;
  918. ctx->opayloadoff = 0;
  919. }
  920. memset(&iocb, 0, sizeof(iocb));
  921. iocb.fin = ctx->omsg->fin;
  922. iocb.opcode = ctx->omsg->opcode;
  923. iocb.rsv = ctx->omsg->rsv;
  924. iocb.mask = ctx->server ? 0 : 1;
  925. iocb.data = ctx->obufmark;
  926. iocb.data_length = (size_t)(ctx->obuflimit - ctx->obufmark);
  927. iocb.payload_length = ctx->opayloadlen;
  928. r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen,
  929. &wpayloadlen);
  930. if (r > 0) {
  931. assert((size_t)r <= buflen);
  932. buf_last += r;
  933. buflen -= (size_t)r;
  934. ctx->obufmark += wpayloadlen;
  935. if (ctx->obufmark == ctx->obuflimit) {
  936. ctx->obufmark = ctx->obuflimit = ctx->obuf;
  937. if (ctx->omsg->fin) {
  938. --ctx->queued_msg_count;
  939. wslay_event_omsg_free(ctx->omsg);
  940. ctx->omsg = NULL;
  941. } else {
  942. ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME;
  943. /* RSV1 is not set on continuation frames */
  944. ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT);
  945. }
  946. } else {
  947. break;
  948. }
  949. } else if (r == 0) {
  950. return buf_last - buf;
  951. } else {
  952. return WSLAY_ERR_CALLBACK_FAILURE;
  953. }
  954. }
  955. }
  956. return buf_last - buf;
  957. }
  958. void wslay_event_set_error(wslay_event_context_ptr ctx, int val) {
  959. ctx->error = val;
  960. }
  961. int wslay_event_want_read(wslay_event_context_ptr ctx) {
  962. return ctx->read_enabled;
  963. }
  964. int wslay_event_want_write(wslay_event_context_ptr ctx) {
  965. return ctx->write_enabled &&
  966. (!wslay_queue_empty(&ctx->send_queue) ||
  967. !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg);
  968. }
  969. void wslay_event_shutdown_read(wslay_event_context_ptr ctx) {
  970. ctx->read_enabled = 0;
  971. }
  972. void wslay_event_shutdown_write(wslay_event_context_ptr ctx) {
  973. ctx->write_enabled = 0;
  974. }
  975. int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) {
  976. return ctx->read_enabled;
  977. }
  978. int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) {
  979. return ctx->write_enabled;
  980. }
  981. int wslay_event_get_close_received(wslay_event_context_ptr ctx) {
  982. return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0;
  983. }
  984. int wslay_event_get_close_sent(wslay_event_context_ptr ctx) {
  985. return (ctx->close_status & WSLAY_CLOSE_SENT) > 0;
  986. }
  987. void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx,
  988. uint8_t rsv) {
  989. /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */
  990. ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT;
  991. }
  992. void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) {
  993. if (val) {
  994. ctx->config |= WSLAY_CONFIG_NO_BUFFERING;
  995. } else {
  996. ctx->config &= (uint32_t)~WSLAY_CONFIG_NO_BUFFERING;
  997. }
  998. }
  999. void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx,
  1000. uint64_t val) {
  1001. ctx->max_recv_msg_length = val;
  1002. }
  1003. uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) {
  1004. return ctx->status_code_recv;
  1005. }
  1006. uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) {
  1007. return ctx->status_code_sent;
  1008. }
  1009. size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) {
  1010. return ctx->queued_msg_count;
  1011. }
  1012. size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) {
  1013. return ctx->queued_msg_length;
  1014. }