wslay_event_test.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  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_test.h"
  26. #include <assert.h>
  27. #include <CUnit/CUnit.h>
  28. #include "wslay_event.h"
  29. struct scripted_data_feed {
  30. uint8_t data[8192];
  31. uint8_t *datamark;
  32. uint8_t *datalimit;
  33. size_t feedseq[8192];
  34. size_t seqidx;
  35. };
  36. struct accumulator {
  37. uint8_t buf[4096];
  38. size_t length;
  39. };
  40. struct my_user_data {
  41. struct scripted_data_feed *df;
  42. struct accumulator *acc;
  43. };
  44. static void scripted_data_feed_init(struct scripted_data_feed *df,
  45. const uint8_t *data, size_t data_length) {
  46. memset(df, 0, sizeof(struct scripted_data_feed));
  47. if (data_length) {
  48. memcpy(df->data, data, data_length);
  49. }
  50. df->datamark = df->data;
  51. df->datalimit = df->data + data_length;
  52. df->feedseq[0] = data_length;
  53. }
  54. static ssize_t
  55. scripted_read_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len,
  56. const union wslay_event_msg_source *source, int *eof,
  57. void *user_data) {
  58. struct scripted_data_feed *df = (struct scripted_data_feed *)source->data;
  59. size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
  60. memcpy(data, df->datamark, wlen);
  61. df->datamark += wlen;
  62. if (wlen <= len) {
  63. ++df->seqidx;
  64. } else {
  65. df->feedseq[df->seqidx] -= wlen;
  66. }
  67. if (df->datamark == df->datalimit) {
  68. *eof = 1;
  69. }
  70. return wlen;
  71. }
  72. static ssize_t scripted_recv_callback(wslay_event_context_ptr ctx,
  73. uint8_t *data, size_t len, int flags,
  74. void *user_data) {
  75. struct scripted_data_feed *df = ((struct my_user_data *)user_data)->df;
  76. size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
  77. memcpy(data, df->datamark, wlen);
  78. df->datamark += wlen;
  79. if (wlen <= len) {
  80. ++df->seqidx;
  81. } else {
  82. df->feedseq[df->seqidx] -= wlen;
  83. }
  84. return wlen;
  85. }
  86. static ssize_t accumulator_send_callback(wslay_event_context_ptr ctx,
  87. const uint8_t *buf, size_t len,
  88. int flags, void *user_data) {
  89. struct accumulator *acc = ((struct my_user_data *)user_data)->acc;
  90. assert(acc->length + len < sizeof(acc->buf));
  91. memcpy(acc->buf + acc->length, buf, len);
  92. acc->length += len;
  93. return len;
  94. }
  95. static ssize_t one_accumulator_send_callback(wslay_event_context_ptr ctx,
  96. const uint8_t *buf, size_t len,
  97. int flags, void *user_data) {
  98. struct accumulator *acc = ((struct my_user_data *)user_data)->acc;
  99. assert(len > 0);
  100. memcpy(acc->buf + acc->length, buf, 1);
  101. acc->length += 1;
  102. return 1;
  103. }
  104. static ssize_t fail_recv_callback(wslay_event_context_ptr ctx, uint8_t *data,
  105. size_t len, int flags, void *user_data) {
  106. wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
  107. return -1;
  108. }
  109. static ssize_t fail_send_callback(wslay_event_context_ptr ctx,
  110. const uint8_t *buf, size_t len, int flags,
  111. void *user_data) {
  112. wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
  113. return -1;
  114. }
  115. void test_wslay_event_send_fragmented_msg(void) {
  116. wslay_event_context_ptr ctx;
  117. struct wslay_event_callbacks callbacks;
  118. struct my_user_data ud;
  119. struct accumulator acc;
  120. const char msg[] = "Hello";
  121. struct scripted_data_feed df;
  122. struct wslay_event_fragmented_msg arg;
  123. const uint8_t ans[] = {0x01, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f};
  124. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  125. df.feedseq[0] = 3;
  126. df.feedseq[1] = 2;
  127. memset(&callbacks, 0, sizeof(callbacks));
  128. callbacks.send_callback = accumulator_send_callback;
  129. memset(&acc, 0, sizeof(acc));
  130. ud.acc = &acc;
  131. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  132. memset(&arg, 0, sizeof(arg));
  133. arg.opcode = WSLAY_TEXT_FRAME;
  134. arg.source.data = &df;
  135. arg.read_callback = scripted_read_callback;
  136. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  137. CU_ASSERT(0 == wslay_event_send(ctx));
  138. CU_ASSERT_EQUAL(9, acc.length);
  139. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  140. wslay_event_context_free(ctx);
  141. }
  142. void test_wslay_event_send_fragmented_msg_empty_data(void) {
  143. wslay_event_context_ptr ctx;
  144. struct wslay_event_callbacks callbacks;
  145. struct my_user_data ud;
  146. struct accumulator acc;
  147. struct scripted_data_feed df;
  148. struct wslay_event_fragmented_msg arg;
  149. const uint8_t ans[] = {0x81, 0x00};
  150. scripted_data_feed_init(&df, NULL, 0);
  151. memset(&callbacks, 0, sizeof(callbacks));
  152. callbacks.send_callback = accumulator_send_callback;
  153. memset(&acc, 0, sizeof(acc));
  154. ud.acc = &acc;
  155. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  156. memset(&arg, 0, sizeof(arg));
  157. arg.opcode = WSLAY_TEXT_FRAME;
  158. arg.source.data = &df;
  159. arg.read_callback = scripted_read_callback;
  160. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  161. CU_ASSERT(0 == wslay_event_send(ctx));
  162. CU_ASSERT_EQUAL(2, acc.length);
  163. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  164. wslay_event_context_free(ctx);
  165. }
  166. void test_wslay_event_send_fragmented_msg_with_ctrl(void) {
  167. int i;
  168. wslay_event_context_ptr ctx;
  169. struct wslay_event_callbacks callbacks;
  170. struct my_user_data ud;
  171. struct accumulator acc;
  172. const char msg[] = "Hello";
  173. struct scripted_data_feed df;
  174. struct wslay_event_fragmented_msg arg;
  175. struct wslay_event_msg ctrl_arg;
  176. const uint8_t ans[] = {
  177. 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */
  178. 0x89, 0x00, /* unmasked ping */
  179. 0x80, 0x02, 0x6c, 0x6f /* "lo" */
  180. };
  181. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  182. df.feedseq[0] = 3;
  183. df.feedseq[1] = 2;
  184. memset(&callbacks, 0, sizeof(callbacks));
  185. callbacks.send_callback = one_accumulator_send_callback;
  186. memset(&acc, 0, sizeof(acc));
  187. ud.acc = &acc;
  188. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  189. memset(&arg, 0, sizeof(arg));
  190. arg.opcode = WSLAY_TEXT_FRAME;
  191. arg.source.data = &df;
  192. arg.read_callback = scripted_read_callback;
  193. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  194. CU_ASSERT(1 == wslay_event_get_queued_msg_count(ctx));
  195. CU_ASSERT(0 == wslay_event_get_queued_msg_length(ctx));
  196. CU_ASSERT(0 == wslay_event_send(ctx));
  197. memset(&ctrl_arg, 0, sizeof(ctrl_arg));
  198. ctrl_arg.opcode = WSLAY_PING;
  199. ctrl_arg.msg_length = 0;
  200. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &ctrl_arg));
  201. CU_ASSERT(2 == wslay_event_get_queued_msg_count(ctx));
  202. for (i = 0; i < 10; ++i) {
  203. CU_ASSERT(0 == wslay_event_send(ctx));
  204. }
  205. CU_ASSERT(0 == wslay_event_get_queued_msg_count(ctx));
  206. CU_ASSERT(11 == acc.length);
  207. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  208. wslay_event_context_free(ctx);
  209. }
  210. void test_wslay_event_send_fragmented_msg_with_rsv1(void) {
  211. wslay_event_context_ptr ctx;
  212. struct wslay_event_callbacks callbacks;
  213. struct my_user_data ud;
  214. struct accumulator acc;
  215. const char msg[] = "Hello";
  216. struct scripted_data_feed df;
  217. struct wslay_event_fragmented_msg arg;
  218. const uint8_t ans[] = {0x41, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f};
  219. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  220. df.feedseq[0] = 3;
  221. df.feedseq[1] = 2;
  222. memset(&callbacks, 0, sizeof(callbacks));
  223. callbacks.send_callback = accumulator_send_callback;
  224. memset(&acc, 0, sizeof(acc));
  225. ud.acc = &acc;
  226. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  227. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  228. memset(&arg, 0, sizeof(arg));
  229. arg.opcode = WSLAY_TEXT_FRAME;
  230. arg.source.data = &df;
  231. arg.read_callback = scripted_read_callback;
  232. CU_ASSERT(0 ==
  233. wslay_event_queue_fragmented_msg_ex(ctx, &arg, WSLAY_RSV1_BIT));
  234. CU_ASSERT(0 == wslay_event_send(ctx));
  235. CU_ASSERT_EQUAL(9, acc.length);
  236. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  237. wslay_event_context_free(ctx);
  238. }
  239. void test_wslay_event_send_msg_with_rsv1(void) {
  240. wslay_event_context_ptr ctx;
  241. struct wslay_event_callbacks callbacks;
  242. struct my_user_data ud;
  243. struct accumulator acc;
  244. const char msg[] = "Hello";
  245. struct wslay_event_msg arg;
  246. const uint8_t ans[] = {
  247. 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  248. };
  249. memset(&callbacks, 0, sizeof(callbacks));
  250. callbacks.send_callback = accumulator_send_callback;
  251. memset(&acc, 0, sizeof(acc));
  252. ud.acc = &acc;
  253. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  254. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  255. memset(&arg, 0, sizeof(arg));
  256. arg.opcode = WSLAY_TEXT_FRAME;
  257. arg.msg = (const uint8_t *)msg;
  258. arg.msg_length = 5;
  259. CU_ASSERT(0 == wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT));
  260. CU_ASSERT(0 == wslay_event_send(ctx));
  261. CU_ASSERT(7 == acc.length);
  262. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  263. wslay_event_context_free(ctx);
  264. }
  265. void test_wslay_event_send_ctrl_msg_first(void) {
  266. wslay_event_context_ptr ctx;
  267. struct wslay_event_callbacks callbacks;
  268. struct my_user_data ud;
  269. struct accumulator acc;
  270. const char msg[] = "Hello";
  271. struct wslay_event_msg arg;
  272. const uint8_t ans[] = {
  273. 0x89, 0x00, /* unmasked ping */
  274. 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  275. };
  276. memset(&callbacks, 0, sizeof(callbacks));
  277. callbacks.send_callback = accumulator_send_callback;
  278. memset(&acc, 0, sizeof(acc));
  279. ud.acc = &acc;
  280. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  281. memset(&arg, 0, sizeof(arg));
  282. arg.opcode = WSLAY_PING;
  283. arg.msg_length = 0;
  284. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg));
  285. arg.opcode = WSLAY_TEXT_FRAME;
  286. arg.msg = (const uint8_t *)msg;
  287. arg.msg_length = 5;
  288. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg));
  289. CU_ASSERT(0 == wslay_event_send(ctx));
  290. CU_ASSERT(9 == acc.length);
  291. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  292. wslay_event_context_free(ctx);
  293. }
  294. void test_wslay_event_send_ctrl_msg_with_rsv1(void) {
  295. wslay_event_context_ptr ctx;
  296. struct wslay_event_callbacks callbacks;
  297. struct wslay_event_msg arg;
  298. memset(&callbacks, 0, sizeof(callbacks));
  299. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  300. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  301. memset(&arg, 0, sizeof(arg));
  302. arg.opcode = WSLAY_PING;
  303. arg.msg_length = 0;
  304. CU_ASSERT(WSLAY_ERR_INVALID_ARGUMENT ==
  305. wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT));
  306. wslay_event_context_free(ctx);
  307. }
  308. void test_wslay_event_queue_close(void) {
  309. wslay_event_context_ptr ctx;
  310. struct wslay_event_callbacks callbacks;
  311. struct my_user_data ud;
  312. struct accumulator acc;
  313. const char msg[] = "H";
  314. const uint8_t ans[] = {
  315. 0x88, 0x03, 0x03, 0xf1, 0x48 /* "H" */
  316. };
  317. memset(&callbacks, 0, sizeof(callbacks));
  318. callbacks.send_callback = accumulator_send_callback;
  319. memset(&acc, 0, sizeof(acc));
  320. ud.acc = &acc;
  321. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  322. CU_ASSERT(0 == wslay_event_queue_close(ctx, WSLAY_CODE_MESSAGE_TOO_BIG,
  323. (const uint8_t *)msg, 1));
  324. CU_ASSERT(0 == wslay_event_send(ctx));
  325. CU_ASSERT(5 == acc.length);
  326. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  327. CU_ASSERT(1 == wslay_event_get_close_sent(ctx));
  328. wslay_event_context_free(ctx);
  329. }
  330. void test_wslay_event_queue_close_without_code(void) {
  331. wslay_event_context_ptr ctx;
  332. struct wslay_event_callbacks callbacks;
  333. struct my_user_data ud;
  334. struct accumulator acc;
  335. const uint8_t ans[] = {0x88, 0x00};
  336. struct wslay_event_msg ping = {WSLAY_PING, NULL, 0};
  337. memset(&callbacks, 0, sizeof(callbacks));
  338. callbacks.send_callback = accumulator_send_callback;
  339. memset(&acc, 0, sizeof(acc));
  340. ud.acc = &acc;
  341. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  342. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &ping));
  343. /* See that ping is not sent because close frame is queued */
  344. CU_ASSERT(0 == wslay_event_queue_close(ctx, 0, NULL, 0));
  345. CU_ASSERT(0 == wslay_event_send(ctx));
  346. CU_ASSERT(2 == acc.length);
  347. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  348. CU_ASSERT(1 == wslay_event_get_close_sent(ctx));
  349. CU_ASSERT(WSLAY_CODE_NO_STATUS_RCVD == wslay_event_get_status_code_sent(ctx));
  350. wslay_event_context_free(ctx);
  351. }
  352. void test_wslay_event_recv_close_without_code(void) {
  353. wslay_event_context_ptr ctx;
  354. struct wslay_event_callbacks callbacks;
  355. struct my_user_data ud;
  356. const uint8_t msg[] = {0x88u, 0x00};
  357. struct scripted_data_feed df;
  358. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  359. memset(&callbacks, 0, sizeof(callbacks));
  360. callbacks.recv_callback = scripted_recv_callback;
  361. ud.df = &df;
  362. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  363. CU_ASSERT(0 == wslay_event_recv(ctx));
  364. CU_ASSERT(1 == wslay_event_get_close_received(ctx));
  365. CU_ASSERT(WSLAY_CODE_NO_STATUS_RCVD ==
  366. wslay_event_get_status_code_received(ctx));
  367. wslay_event_context_free(ctx);
  368. }
  369. void test_wslay_event_reply_close(void) {
  370. wslay_event_context_ptr ctx;
  371. struct wslay_event_callbacks callbacks;
  372. struct my_user_data ud;
  373. struct accumulator acc;
  374. /* Masked close frame with code = 1009, reason = "Hello" */
  375. const uint8_t msg[] = {
  376. 0x88u, 0x87u, 0x00u, 0x00u, 0x00u, 0x00u, 0x03, 0xf1, /* 1009 */
  377. 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  378. };
  379. const uint8_t ans[] = {
  380. 0x88u, 0x07u, 0x03, 0xf1, /* 1009 */
  381. 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  382. };
  383. struct scripted_data_feed df;
  384. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  385. memset(&callbacks, 0, sizeof(callbacks));
  386. callbacks.send_callback = accumulator_send_callback;
  387. callbacks.recv_callback = scripted_recv_callback;
  388. memset(&acc, 0, sizeof(acc));
  389. ud.df = &df;
  390. ud.acc = &acc;
  391. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  392. CU_ASSERT(0 == wslay_event_recv(ctx));
  393. CU_ASSERT(1 == wslay_event_get_queued_msg_count(ctx));
  394. /* 7 bytes = 2 bytes status code + "Hello" */
  395. CU_ASSERT(7 == wslay_event_get_queued_msg_length(ctx));
  396. CU_ASSERT(1 == wslay_event_get_close_received(ctx));
  397. CU_ASSERT(WSLAY_CODE_MESSAGE_TOO_BIG ==
  398. wslay_event_get_status_code_received(ctx));
  399. CU_ASSERT(WSLAY_CODE_ABNORMAL_CLOSURE ==
  400. wslay_event_get_status_code_sent(ctx));
  401. CU_ASSERT(0 == wslay_event_send(ctx));
  402. CU_ASSERT(0 == wslay_event_get_queued_msg_count(ctx));
  403. CU_ASSERT(0 == wslay_event_get_queued_msg_length(ctx));
  404. CU_ASSERT(9 == acc.length);
  405. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  406. CU_ASSERT(1 == wslay_event_get_close_sent(ctx));
  407. CU_ASSERT(WSLAY_CODE_MESSAGE_TOO_BIG ==
  408. wslay_event_get_status_code_received(ctx));
  409. CU_ASSERT(WSLAY_CODE_MESSAGE_TOO_BIG ==
  410. wslay_event_get_status_code_sent(ctx));
  411. wslay_event_context_free(ctx);
  412. }
  413. void test_wslay_event_no_more_msg(void) {
  414. wslay_event_context_ptr ctx;
  415. struct wslay_event_callbacks callbacks;
  416. memset(&callbacks, 0, sizeof(callbacks));
  417. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  418. CU_ASSERT(0 == wslay_event_queue_close(ctx, 0, NULL, 0));
  419. CU_ASSERT(WSLAY_ERR_NO_MORE_MSG == wslay_event_queue_close(ctx, 0, NULL, 0));
  420. wslay_event_context_free(ctx);
  421. }
  422. void test_wslay_event_callback_failure(void) {
  423. wslay_event_context_ptr ctx;
  424. struct wslay_event_callbacks callbacks;
  425. memset(&callbacks, 0, sizeof(callbacks));
  426. callbacks.recv_callback = fail_recv_callback;
  427. callbacks.send_callback = fail_send_callback;
  428. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  429. CU_ASSERT(WSLAY_ERR_CALLBACK_FAILURE == wslay_event_recv(ctx));
  430. /* close control frame is in queue */
  431. CU_ASSERT(WSLAY_ERR_CALLBACK_FAILURE == wslay_event_send(ctx));
  432. wslay_event_context_free(ctx);
  433. }
  434. static void no_buffering_callback(wslay_event_context_ptr ctx,
  435. const struct wslay_event_on_msg_recv_arg *arg,
  436. void *user_data) {
  437. if (arg->opcode == WSLAY_PING) {
  438. CU_ASSERT(3 == arg->msg_length);
  439. CU_ASSERT(0 == memcmp("Foo", arg->msg, arg->msg_length));
  440. } else {
  441. CU_ASSERT(WSLAY_TEXT_FRAME == arg->opcode);
  442. CU_ASSERT(0 == arg->msg_length);
  443. }
  444. }
  445. void test_wslay_event_no_buffering(void) {
  446. wslay_event_context_ptr ctx;
  447. struct wslay_event_callbacks callbacks;
  448. struct my_user_data ud;
  449. const uint8_t msg[] = {
  450. 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */
  451. 0x89, 0x03, 0x46, 0x6f, 0x6f, /* ping with "Foo" */
  452. 0x80, 0x02, 0x6c, 0x6f, /* "lo" */
  453. };
  454. struct scripted_data_feed df;
  455. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  456. memset(&callbacks, 0, sizeof(callbacks));
  457. ud.df = &df;
  458. callbacks.recv_callback = scripted_recv_callback;
  459. callbacks.on_msg_recv_callback = no_buffering_callback;
  460. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  461. wslay_event_config_set_no_buffering(ctx, 1);
  462. CU_ASSERT(0 == wslay_event_recv(ctx));
  463. /* pong must be queued */
  464. CU_ASSERT(wslay_event_want_write(ctx));
  465. wslay_event_context_free(ctx);
  466. }
  467. static void
  468. text_rsv1_on_msg_recv_callback(wslay_event_context_ptr ctx,
  469. const struct wslay_event_on_msg_recv_arg *arg,
  470. void *user_data) {
  471. CU_ASSERT(WSLAY_TEXT_FRAME == arg->opcode);
  472. CU_ASSERT(WSLAY_RSV1_BIT == arg->rsv);
  473. }
  474. void test_wslay_event_recv_text_frame_with_rsv1(void) {
  475. wslay_event_context_ptr ctx;
  476. struct wslay_event_callbacks callbacks;
  477. struct my_user_data ud;
  478. const uint8_t msg[] = {
  479. 0xc1, 0x07, 0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00 // "Hello" pm-deflate
  480. };
  481. const uint8_t fragmented[] = {
  482. 0x41, 0x03, 0xf2, 0x48, 0xcd, // First fragment
  483. 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00 // Second fragment, RSV1 bit off
  484. };
  485. const uint8_t bad_fragment[] = {
  486. 0x41, 0x03, 0xf2, 0x48, 0xcd, 0xc0,
  487. 0x04, 0xc9, 0xc9, 0x07, 0x00 // RSV1 bit on
  488. };
  489. const uint8_t pingmsg[] = {
  490. 0xc9, 0x03, 0x46, 0x6f, 0x6f /* ping with "Foo" */
  491. };
  492. struct scripted_data_feed df;
  493. /* Message marked with RSV1 should skip UTF-8 validation */
  494. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  495. memset(&callbacks, 0, sizeof(callbacks));
  496. ud.df = &df;
  497. callbacks.recv_callback = scripted_recv_callback;
  498. callbacks.on_msg_recv_callback = text_rsv1_on_msg_recv_callback;
  499. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  500. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  501. CU_ASSERT(0 == wslay_event_recv(ctx));
  502. CU_ASSERT(0 == wslay_event_want_write(ctx));
  503. wslay_event_context_free(ctx);
  504. /* UTF-8 validation is skipped for continuation frames if the
  505. * initial frame was marked with RSV1 bit */
  506. scripted_data_feed_init(&df, (const uint8_t *)fragmented, sizeof(fragmented));
  507. memset(&callbacks, 0, sizeof(callbacks));
  508. ud.df = &df;
  509. callbacks.recv_callback = scripted_recv_callback;
  510. callbacks.on_msg_recv_callback = text_rsv1_on_msg_recv_callback;
  511. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  512. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  513. CU_ASSERT(0 == wslay_event_recv(ctx));
  514. CU_ASSERT(0 == wslay_event_want_write(ctx));
  515. wslay_event_context_free(ctx);
  516. /* disallow RSV1 */
  517. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  518. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  519. CU_ASSERT(0 == wslay_event_recv(ctx));
  520. /* Close frame must be queued */
  521. CU_ASSERT(wslay_event_want_write(ctx));
  522. wslay_event_context_free(ctx);
  523. /* RSV1 is not allowed in continuation frame */
  524. scripted_data_feed_init(&df, (const uint8_t *)bad_fragment,
  525. sizeof(bad_fragment));
  526. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  527. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  528. CU_ASSERT(0 == wslay_event_recv(ctx));
  529. /* Close frame must be queued */
  530. CU_ASSERT(wslay_event_want_write(ctx));
  531. wslay_event_context_free(ctx);
  532. /* RSV1 is not allowed in ping frame */
  533. scripted_data_feed_init(&df, (const uint8_t *)pingmsg, sizeof(pingmsg));
  534. wslay_event_context_client_init(&ctx, &callbacks, &ud);
  535. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  536. CU_ASSERT(0 == wslay_event_recv(ctx));
  537. /* Close frame must be queued */
  538. CU_ASSERT(wslay_event_want_write(ctx));
  539. wslay_event_context_free(ctx);
  540. }
  541. void test_wslay_event_frame_too_big(void) {
  542. wslay_event_context_ptr ctx;
  543. struct wslay_event_callbacks callbacks;
  544. struct my_user_data ud;
  545. struct accumulator acc;
  546. /* Masked text frame */
  547. const uint8_t msg[] = {
  548. 0x81, 0x85, 0x00, 0x00, 0x00, 0x00,
  549. 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  550. };
  551. const uint8_t ans[] = {
  552. 0x88, 0x02, 0x03, 0xf1 /* 1009 */
  553. };
  554. struct scripted_data_feed df;
  555. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  556. memset(&callbacks, 0, sizeof(callbacks));
  557. callbacks.send_callback = accumulator_send_callback;
  558. callbacks.recv_callback = scripted_recv_callback;
  559. memset(&acc, 0, sizeof(acc));
  560. ud.df = &df;
  561. ud.acc = &acc;
  562. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  563. wslay_event_config_set_max_recv_msg_length(ctx, 4);
  564. CU_ASSERT(0 == wslay_event_recv(ctx));
  565. CU_ASSERT(0 == wslay_event_send(ctx));
  566. CU_ASSERT(4 == acc.length);
  567. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  568. CU_ASSERT(1 == wslay_event_get_close_sent(ctx));
  569. CU_ASSERT(WSLAY_CODE_MESSAGE_TOO_BIG ==
  570. wslay_event_get_status_code_sent(ctx));
  571. wslay_event_context_free(ctx);
  572. }
  573. void test_wslay_event_message_too_big(void) {
  574. wslay_event_context_ptr ctx;
  575. struct wslay_event_callbacks callbacks;
  576. struct my_user_data ud;
  577. struct accumulator acc;
  578. /* Masked text 2 frames */
  579. const uint8_t msg[] = {
  580. 0x01, 0x85, 0x00, 0x00, 0x00, 0x00,
  581. 0x48, 0x65, 0x6c, 0x6c, 0x6f, /* "Hello" */
  582. 0x80, 0x85, 0x00, 0x00, 0x00, 0x00,
  583. 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  584. };
  585. const uint8_t ans[] = {
  586. 0x88, 0x02, 0x03, 0xf1 /* 1009 */
  587. };
  588. struct scripted_data_feed df;
  589. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg));
  590. memset(&callbacks, 0, sizeof(callbacks));
  591. callbacks.send_callback = accumulator_send_callback;
  592. callbacks.recv_callback = scripted_recv_callback;
  593. memset(&acc, 0, sizeof(acc));
  594. ud.df = &df;
  595. ud.acc = &acc;
  596. wslay_event_context_server_init(&ctx, &callbacks, &ud);
  597. wslay_event_config_set_max_recv_msg_length(ctx, 9);
  598. CU_ASSERT(0 == wslay_event_recv(ctx));
  599. CU_ASSERT(0 == wslay_event_send(ctx));
  600. CU_ASSERT(4 == acc.length);
  601. CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length));
  602. CU_ASSERT(1 == wslay_event_get_close_sent(ctx));
  603. CU_ASSERT(WSLAY_CODE_MESSAGE_TOO_BIG ==
  604. wslay_event_get_status_code_sent(ctx));
  605. wslay_event_context_free(ctx);
  606. }
  607. void test_wslay_event_config_set_allowed_rsv_bits(void) {
  608. wslay_event_context_ptr ctx;
  609. struct wslay_event_callbacks callbacks;
  610. memset(&callbacks, 0, sizeof(callbacks));
  611. CU_ASSERT(0 == wslay_event_context_server_init(&ctx, &callbacks, NULL));
  612. CU_ASSERT(WSLAY_RSV_NONE == ctx->allowed_rsv_bits);
  613. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  614. CU_ASSERT(WSLAY_RSV1_BIT == ctx->allowed_rsv_bits);
  615. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT | WSLAY_RSV2_BIT |
  616. WSLAY_RSV3_BIT);
  617. CU_ASSERT(WSLAY_RSV1_BIT == ctx->allowed_rsv_bits);
  618. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV2_BIT | WSLAY_RSV3_BIT);
  619. CU_ASSERT(WSLAY_RSV_NONE == ctx->allowed_rsv_bits);
  620. wslay_event_context_free(ctx);
  621. }
  622. void test_wslay_event_write_fragmented_msg(void) {
  623. wslay_event_context_ptr ctx;
  624. struct wslay_event_callbacks callbacks;
  625. const char msg[] = "Hello";
  626. struct scripted_data_feed df;
  627. struct wslay_event_fragmented_msg arg;
  628. const uint8_t ans[] = {0x01, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f};
  629. uint8_t buf[1024];
  630. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  631. df.feedseq[0] = 3;
  632. df.feedseq[1] = 2;
  633. memset(&callbacks, 0, sizeof(callbacks));
  634. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  635. memset(&arg, 0, sizeof(arg));
  636. arg.opcode = WSLAY_TEXT_FRAME;
  637. arg.source.data = &df;
  638. arg.read_callback = scripted_read_callback;
  639. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  640. CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf)));
  641. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  642. wslay_event_context_free(ctx);
  643. }
  644. void test_wslay_event_write_fragmented_msg_empty_data(void) {
  645. wslay_event_context_ptr ctx;
  646. struct wslay_event_callbacks callbacks;
  647. struct scripted_data_feed df;
  648. struct wslay_event_fragmented_msg arg;
  649. const uint8_t ans[] = {0x81, 0x00};
  650. uint8_t buf[1024];
  651. scripted_data_feed_init(&df, NULL, 0);
  652. memset(&callbacks, 0, sizeof(callbacks));
  653. callbacks.send_callback = accumulator_send_callback;
  654. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  655. memset(&arg, 0, sizeof(arg));
  656. arg.opcode = WSLAY_TEXT_FRAME;
  657. arg.source.data = &df;
  658. arg.read_callback = scripted_read_callback;
  659. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  660. CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf)));
  661. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  662. wslay_event_context_free(ctx);
  663. }
  664. void test_wslay_event_write_fragmented_msg_with_ctrl(void) {
  665. wslay_event_context_ptr ctx;
  666. struct wslay_event_callbacks callbacks;
  667. const char msg[] = "Hello";
  668. struct scripted_data_feed df;
  669. struct wslay_event_fragmented_msg arg;
  670. struct wslay_event_msg ctrl_arg;
  671. const uint8_t ans[] = {
  672. 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */
  673. 0x89, 0x00, /* unmasked ping */
  674. 0x80, 0x02, 0x6c, 0x6f /* "lo" */
  675. };
  676. uint8_t buf[1024];
  677. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  678. df.feedseq[0] = 3;
  679. df.feedseq[1] = 2;
  680. memset(&callbacks, 0, sizeof(callbacks));
  681. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  682. memset(&arg, 0, sizeof(arg));
  683. arg.opcode = WSLAY_TEXT_FRAME;
  684. arg.source.data = &df;
  685. arg.read_callback = scripted_read_callback;
  686. CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg));
  687. CU_ASSERT(1 == wslay_event_get_queued_msg_count(ctx));
  688. CU_ASSERT(0 == wslay_event_get_queued_msg_length(ctx));
  689. CU_ASSERT(4 == wslay_event_write(ctx, buf, 4));
  690. memset(&ctrl_arg, 0, sizeof(ctrl_arg));
  691. ctrl_arg.opcode = WSLAY_PING;
  692. ctrl_arg.msg_length = 0;
  693. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &ctrl_arg));
  694. CU_ASSERT(2 == wslay_event_get_queued_msg_count(ctx));
  695. CU_ASSERT(7 == wslay_event_write(ctx, buf + 4, sizeof(buf) - 4));
  696. CU_ASSERT(0 == wslay_event_get_queued_msg_count(ctx));
  697. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  698. wslay_event_context_free(ctx);
  699. }
  700. void test_wslay_event_write_fragmented_msg_with_rsv1(void) {
  701. wslay_event_context_ptr ctx;
  702. struct wslay_event_callbacks callbacks;
  703. const char msg[] = "Hello";
  704. struct scripted_data_feed df;
  705. struct wslay_event_fragmented_msg arg;
  706. const uint8_t ans[] = {0x41, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f};
  707. uint8_t buf[1024];
  708. scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1);
  709. df.feedseq[0] = 3;
  710. df.feedseq[1] = 2;
  711. memset(&callbacks, 0, sizeof(callbacks));
  712. callbacks.send_callback = accumulator_send_callback;
  713. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  714. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  715. memset(&arg, 0, sizeof(arg));
  716. arg.opcode = WSLAY_TEXT_FRAME;
  717. arg.source.data = &df;
  718. arg.read_callback = scripted_read_callback;
  719. CU_ASSERT(0 ==
  720. wslay_event_queue_fragmented_msg_ex(ctx, &arg, WSLAY_RSV1_BIT));
  721. CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf)));
  722. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  723. wslay_event_context_free(ctx);
  724. }
  725. void test_wslay_event_write_msg_with_rsv1(void) {
  726. wslay_event_context_ptr ctx;
  727. struct wslay_event_callbacks callbacks;
  728. const char msg[] = "Hello";
  729. struct wslay_event_msg arg;
  730. const uint8_t ans[] = {
  731. 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  732. };
  733. uint8_t buf[1024];
  734. memset(&callbacks, 0, sizeof(callbacks));
  735. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  736. wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT);
  737. memset(&arg, 0, sizeof(arg));
  738. arg.opcode = WSLAY_TEXT_FRAME;
  739. arg.msg = (const uint8_t *)msg;
  740. arg.msg_length = 5;
  741. CU_ASSERT(0 == wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT));
  742. CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf)));
  743. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  744. wslay_event_context_free(ctx);
  745. }
  746. void test_wslay_event_write_ctrl_msg_first(void) {
  747. wslay_event_context_ptr ctx;
  748. struct wslay_event_callbacks callbacks;
  749. const char msg[] = "Hello";
  750. struct wslay_event_msg arg;
  751. const uint8_t ans[] = {
  752. 0x89, 0x00, /* unmasked ping */
  753. 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */
  754. };
  755. uint8_t buf[1024];
  756. memset(&callbacks, 0, sizeof(callbacks));
  757. wslay_event_context_server_init(&ctx, &callbacks, NULL);
  758. memset(&arg, 0, sizeof(arg));
  759. arg.opcode = WSLAY_PING;
  760. arg.msg_length = 0;
  761. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg));
  762. arg.opcode = WSLAY_TEXT_FRAME;
  763. arg.msg = (const uint8_t *)msg;
  764. arg.msg_length = 5;
  765. CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg));
  766. CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf)));
  767. CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans)));
  768. wslay_event_context_free(ctx);
  769. }