wslay_frame_test.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  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_frame_test.h"
  26. #include <assert.h>
  27. #include <CUnit/CUnit.h>
  28. #include "wslay_frame.h"
  29. void test_wslay_frame_context_init(void) {
  30. wslay_frame_context_ptr ctx;
  31. struct wslay_frame_callbacks callbacks;
  32. int user_data;
  33. CU_ASSERT_FALSE(wslay_frame_context_init(&ctx, &callbacks, &user_data));
  34. wslay_frame_context_free(ctx);
  35. }
  36. struct scripted_data_feed {
  37. uint8_t data[8192];
  38. uint8_t *datamark;
  39. uint8_t *datalimit;
  40. size_t feedseq[8192];
  41. size_t seqidx;
  42. };
  43. static void scripted_data_feed_init(struct scripted_data_feed *df,
  44. uint8_t *data, size_t data_length) {
  45. memset(df, 0, sizeof(struct scripted_data_feed));
  46. if (data_length) {
  47. memcpy(df->data, data, data_length);
  48. }
  49. df->datamark = df->data;
  50. df->datalimit = df->data + data_length;
  51. df->feedseq[0] = data_length;
  52. }
  53. static ssize_t scripted_recv_callback(uint8_t *data, size_t len, int flags,
  54. void *user_data) {
  55. struct scripted_data_feed *df = (struct scripted_data_feed *)user_data;
  56. size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
  57. memcpy(data, df->datamark, wlen);
  58. df->datamark += wlen;
  59. if (wlen <= len) {
  60. ++df->seqidx;
  61. } else {
  62. df->feedseq[df->seqidx] -= wlen;
  63. }
  64. return wlen;
  65. }
  66. static ssize_t scripted_send_callback(const uint8_t *data, size_t len,
  67. int flags, void *user_data) {
  68. struct scripted_data_feed *df = (struct scripted_data_feed *)user_data;
  69. size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
  70. memcpy(df->datamark, data, wlen);
  71. df->datamark += wlen;
  72. if (wlen <= len) {
  73. ++df->seqidx;
  74. } else {
  75. df->feedseq[df->seqidx] -= wlen;
  76. }
  77. return wlen;
  78. }
  79. void test_wslay_frame_recv(void) {
  80. wslay_frame_context_ptr ctx;
  81. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  82. struct scripted_data_feed df;
  83. struct wslay_frame_iocb iocb;
  84. /* Masked text frame containing "Hello" */
  85. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  86. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  87. scripted_data_feed_init(&df, msg, sizeof(msg));
  88. wslay_frame_context_init(&ctx, &callbacks, &df);
  89. CU_ASSERT(5 == wslay_frame_recv(ctx, &iocb));
  90. CU_ASSERT_EQUAL(1, iocb.fin);
  91. CU_ASSERT_EQUAL(0, iocb.rsv);
  92. CU_ASSERT_EQUAL(0x1, iocb.opcode);
  93. CU_ASSERT_EQUAL(5, iocb.payload_length);
  94. CU_ASSERT_EQUAL(1, iocb.mask);
  95. CU_ASSERT_EQUAL(5, iocb.data_length);
  96. CU_ASSERT(memcmp("Hello", iocb.data, iocb.data_length) == 0);
  97. wslay_frame_context_free(ctx);
  98. }
  99. void test_wslay_frame_recv_1byte(void) {
  100. wslay_frame_context_ptr ctx;
  101. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  102. struct scripted_data_feed df;
  103. struct wslay_frame_iocb iocb;
  104. size_t i;
  105. /* Masked text frame containing "Hello" */
  106. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  107. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  108. scripted_data_feed_init(&df, msg, sizeof(msg));
  109. for (i = 0; i < sizeof(msg); ++i) {
  110. df.feedseq[i] = 1;
  111. }
  112. wslay_frame_context_init(&ctx, &callbacks, &df);
  113. for (i = 0; i < 4; ++i) {
  114. CU_ASSERT(WSLAY_ERR_WANT_READ == wslay_frame_recv(ctx, &iocb));
  115. }
  116. for (i = 0; i < 5; ++i) {
  117. CU_ASSERT(1 == wslay_frame_recv(ctx, &iocb));
  118. CU_ASSERT_EQUAL(1, iocb.fin);
  119. CU_ASSERT_EQUAL(0, iocb.rsv);
  120. CU_ASSERT_EQUAL(0x1, iocb.opcode);
  121. CU_ASSERT_EQUAL(5, iocb.payload_length);
  122. CU_ASSERT_EQUAL(1, iocb.mask);
  123. CU_ASSERT_EQUAL(1, iocb.data_length);
  124. CU_ASSERT_EQUAL(msg[6 + i] ^ msg[2 + i % 4], iocb.data[0]);
  125. }
  126. CU_ASSERT(WSLAY_ERR_WANT_READ == wslay_frame_recv(ctx, &iocb));
  127. wslay_frame_context_free(ctx);
  128. }
  129. void test_wslay_frame_recv_fragmented(void) {
  130. wslay_frame_context_ptr ctx;
  131. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  132. struct scripted_data_feed df;
  133. struct wslay_frame_iocb iocb;
  134. /* Unmasked message */
  135. uint8_t msg[] = {0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */
  136. 0x80, 0x02, 0x6c, 0x6f}; /* "lo" */
  137. scripted_data_feed_init(&df, msg, sizeof(msg));
  138. df.feedseq[0] = 5;
  139. df.feedseq[1] = 4;
  140. wslay_frame_context_init(&ctx, &callbacks, &df);
  141. CU_ASSERT(3 == wslay_frame_recv(ctx, &iocb));
  142. CU_ASSERT_EQUAL(0, iocb.fin);
  143. CU_ASSERT_EQUAL(0, iocb.rsv);
  144. CU_ASSERT_EQUAL(WSLAY_TEXT_FRAME, iocb.opcode);
  145. CU_ASSERT_EQUAL(3, iocb.payload_length);
  146. CU_ASSERT_EQUAL(0, iocb.mask);
  147. CU_ASSERT_EQUAL(3, iocb.data_length);
  148. CU_ASSERT(memcmp("Hel", iocb.data, iocb.data_length) == 0);
  149. CU_ASSERT(2 == wslay_frame_recv(ctx, &iocb));
  150. CU_ASSERT_EQUAL(1, iocb.fin);
  151. CU_ASSERT_EQUAL(0, iocb.rsv);
  152. CU_ASSERT_EQUAL(WSLAY_CONTINUATION_FRAME, iocb.opcode);
  153. CU_ASSERT_EQUAL(2, iocb.payload_length);
  154. CU_ASSERT_EQUAL(0, iocb.mask);
  155. CU_ASSERT_EQUAL(2, iocb.data_length);
  156. CU_ASSERT(memcmp("lo", iocb.data, iocb.data_length) == 0);
  157. wslay_frame_context_free(ctx);
  158. }
  159. void test_wslay_frame_recv_interleaved_ctrl_frame(void) {
  160. wslay_frame_context_ptr ctx;
  161. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  162. struct scripted_data_feed df;
  163. struct wslay_frame_iocb iocb;
  164. /* Unmasked message */
  165. uint8_t msg[] = {0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */
  166. /* ping with "Hello" */
  167. 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80, 0x02, 0x6c,
  168. 0x6f}; /* "lo" */
  169. scripted_data_feed_init(&df, msg, sizeof(msg));
  170. df.feedseq[0] = 5;
  171. df.feedseq[1] = 7, df.feedseq[2] = 4;
  172. wslay_frame_context_init(&ctx, &callbacks, &df);
  173. CU_ASSERT(3 == wslay_frame_recv(ctx, &iocb));
  174. CU_ASSERT_EQUAL(0, iocb.fin);
  175. CU_ASSERT_EQUAL(0, iocb.rsv);
  176. CU_ASSERT_EQUAL(WSLAY_TEXT_FRAME, iocb.opcode);
  177. CU_ASSERT_EQUAL(3, iocb.payload_length);
  178. CU_ASSERT_EQUAL(0, iocb.mask);
  179. CU_ASSERT_EQUAL(3, iocb.data_length);
  180. CU_ASSERT(memcmp("Hel", iocb.data, iocb.data_length) == 0);
  181. CU_ASSERT(5 == wslay_frame_recv(ctx, &iocb));
  182. CU_ASSERT_EQUAL(1, iocb.fin);
  183. CU_ASSERT_EQUAL(0, iocb.rsv);
  184. CU_ASSERT_EQUAL(WSLAY_PING, iocb.opcode);
  185. CU_ASSERT_EQUAL(5, iocb.payload_length);
  186. CU_ASSERT_EQUAL(0, iocb.mask);
  187. CU_ASSERT_EQUAL(5, iocb.data_length);
  188. CU_ASSERT(memcmp("Hello", iocb.data, iocb.data_length) == 0);
  189. CU_ASSERT(2 == wslay_frame_recv(ctx, &iocb));
  190. CU_ASSERT_EQUAL(1, iocb.fin);
  191. CU_ASSERT_EQUAL(0, iocb.rsv);
  192. CU_ASSERT_EQUAL(WSLAY_CONTINUATION_FRAME, iocb.opcode);
  193. CU_ASSERT_EQUAL(2, iocb.payload_length);
  194. CU_ASSERT_EQUAL(0, iocb.mask);
  195. CU_ASSERT_EQUAL(2, iocb.data_length);
  196. CU_ASSERT(memcmp("lo", iocb.data, iocb.data_length) == 0);
  197. wslay_frame_context_free(ctx);
  198. }
  199. void test_wslay_frame_recv_zero_payloadlen(void) {
  200. wslay_frame_context_ptr ctx;
  201. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  202. struct scripted_data_feed df;
  203. struct wslay_frame_iocb iocb;
  204. /* Unmasked message */
  205. uint8_t msg[] = {0x81, 0x00}; /* "" */
  206. scripted_data_feed_init(&df, msg, sizeof(msg));
  207. df.feedseq[0] = 2;
  208. wslay_frame_context_init(&ctx, &callbacks, &df);
  209. CU_ASSERT(0 == wslay_frame_recv(ctx, &iocb));
  210. CU_ASSERT_EQUAL(1, iocb.fin);
  211. CU_ASSERT_EQUAL(0, iocb.rsv);
  212. CU_ASSERT_EQUAL(WSLAY_TEXT_FRAME, iocb.opcode);
  213. CU_ASSERT_EQUAL(0, iocb.payload_length);
  214. CU_ASSERT_EQUAL(0, iocb.mask);
  215. CU_ASSERT_EQUAL(0, iocb.data_length);
  216. wslay_frame_context_free(ctx);
  217. }
  218. void test_wslay_frame_recv_too_large_payload(void) {
  219. wslay_frame_context_ptr ctx;
  220. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  221. struct scripted_data_feed df;
  222. struct wslay_frame_iocb iocb;
  223. uint8_t msg[] = {0x81, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  224. scripted_data_feed_init(&df, msg, sizeof(msg));
  225. df.feedseq[0] = sizeof(msg);
  226. wslay_frame_context_init(&ctx, &callbacks, &df);
  227. CU_ASSERT_EQUAL(WSLAY_ERR_PROTO, wslay_frame_recv(ctx, &iocb));
  228. wslay_frame_context_free(ctx);
  229. }
  230. void test_wslay_frame_recv_ctrl_frame_too_large_payload(void) {
  231. wslay_frame_context_ptr ctx;
  232. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  233. struct scripted_data_feed df;
  234. struct wslay_frame_iocb iocb;
  235. uint8_t msg[] = {0x88, 0x7e};
  236. scripted_data_feed_init(&df, msg, sizeof(msg));
  237. df.feedseq[0] = sizeof(msg);
  238. wslay_frame_context_init(&ctx, &callbacks, &df);
  239. CU_ASSERT_EQUAL(WSLAY_ERR_PROTO, wslay_frame_recv(ctx, &iocb));
  240. wslay_frame_context_free(ctx);
  241. }
  242. void test_wslay_frame_recv_minimum_ext_payload16(void) {
  243. wslay_frame_context_ptr ctx;
  244. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  245. struct scripted_data_feed df;
  246. struct wslay_frame_iocb iocb;
  247. uint8_t msg[] = {0x81, 0x7e, 0x00, 0x7d};
  248. scripted_data_feed_init(&df, msg, sizeof(msg));
  249. df.feedseq[0] = sizeof(msg);
  250. wslay_frame_context_init(&ctx, &callbacks, &df);
  251. CU_ASSERT_EQUAL(WSLAY_ERR_PROTO, wslay_frame_recv(ctx, &iocb));
  252. wslay_frame_context_free(ctx);
  253. }
  254. void test_wslay_frame_recv_minimum_ext_payload64(void) {
  255. wslay_frame_context_ptr ctx;
  256. struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL};
  257. struct scripted_data_feed df;
  258. struct wslay_frame_iocb iocb;
  259. uint8_t msg[] = {0x81, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff};
  260. scripted_data_feed_init(&df, msg, sizeof(msg));
  261. df.feedseq[0] = sizeof(msg);
  262. wslay_frame_context_init(&ctx, &callbacks, &df);
  263. CU_ASSERT_EQUAL(WSLAY_ERR_PROTO, wslay_frame_recv(ctx, &iocb));
  264. wslay_frame_context_free(ctx);
  265. }
  266. struct accumulator {
  267. uint8_t buf[4096];
  268. size_t length;
  269. };
  270. static ssize_t accumulator_send_callback(const uint8_t *buf, size_t len,
  271. int flags, void *user_data) {
  272. struct accumulator *acc = (struct accumulator *)user_data;
  273. assert(acc->length + len < sizeof(acc->buf));
  274. memcpy(acc->buf + acc->length, buf, len);
  275. acc->length += len;
  276. return len;
  277. }
  278. static int static_genmask_callback(uint8_t *buf, size_t len, void *user_data) {
  279. static const uint8_t makskey[] = {0x37u, 0xfau, 0x21u, 0x3du};
  280. memcpy(buf, makskey, 4);
  281. return 0;
  282. }
  283. void test_wslay_frame_send(void) {
  284. wslay_frame_context_ptr ctx;
  285. struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL,
  286. static_genmask_callback};
  287. struct accumulator acc;
  288. struct wslay_frame_iocb iocb;
  289. /* Masked text frame containing "Hello" */
  290. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  291. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  292. wslay_frame_context_init(&ctx, &callbacks, &acc);
  293. memset(&iocb, 0, sizeof(iocb));
  294. acc.length = 0;
  295. iocb.fin = 1;
  296. iocb.opcode = WSLAY_TEXT_FRAME;
  297. iocb.mask = 1;
  298. iocb.payload_length = 5;
  299. iocb.data = (const uint8_t *)"Hello";
  300. iocb.data_length = 5;
  301. CU_ASSERT(5 == wslay_frame_send(ctx, &iocb));
  302. CU_ASSERT_EQUAL(sizeof(msg), acc.length);
  303. CU_ASSERT(memcmp(msg, acc.buf, sizeof(msg)) == 0);
  304. wslay_frame_context_free(ctx);
  305. }
  306. void test_wslay_frame_send_fragmented(void) {
  307. wslay_frame_context_ptr ctx;
  308. struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL,
  309. static_genmask_callback};
  310. struct accumulator acc;
  311. struct wslay_frame_iocb iocb;
  312. /* Unmasked message */
  313. uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; /* "Hel" */
  314. uint8_t msg2[] = {0x80, 0x02, 0x6c, 0x6f}; /* "lo" */
  315. wslay_frame_context_init(&ctx, &callbacks, &acc);
  316. memset(&iocb, 0, sizeof(iocb));
  317. acc.length = 0;
  318. iocb.fin = 0;
  319. iocb.opcode = WSLAY_TEXT_FRAME;
  320. iocb.mask = 0;
  321. iocb.payload_length = 3;
  322. iocb.data = (const uint8_t *)"Hel";
  323. iocb.data_length = 3;
  324. CU_ASSERT(3 == wslay_frame_send(ctx, &iocb));
  325. CU_ASSERT_EQUAL(sizeof(msg1), acc.length);
  326. CU_ASSERT(memcmp(msg1, acc.buf, sizeof(msg1)) == 0);
  327. acc.length = 0;
  328. iocb.fin = 1;
  329. iocb.opcode = WSLAY_CONTINUATION_FRAME;
  330. iocb.payload_length = 2;
  331. iocb.data = (const uint8_t *)"lo";
  332. iocb.data_length = 2;
  333. CU_ASSERT(2 == wslay_frame_send(ctx, &iocb));
  334. CU_ASSERT_EQUAL(sizeof(msg2), acc.length);
  335. CU_ASSERT(memcmp(msg2, acc.buf, sizeof(msg2)) == 0);
  336. wslay_frame_context_free(ctx);
  337. }
  338. void test_wslay_frame_send_interleaved_ctrl_frame(void) {
  339. wslay_frame_context_ptr ctx;
  340. struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL,
  341. static_genmask_callback};
  342. struct accumulator acc;
  343. struct wslay_frame_iocb iocb;
  344. /* Unmasked message */
  345. /* text with "Hel", with fin = 0 */
  346. uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c};
  347. /* ping with "Hello" */
  348. uint8_t msg2[] = {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f};
  349. /* text with "lo", continuation frame for msg1, with fin = 1 */
  350. uint8_t msg3[] = {0x80, 0x02, 0x6c, 0x6f};
  351. wslay_frame_context_init(&ctx, &callbacks, &acc);
  352. memset(&iocb, 0, sizeof(iocb));
  353. acc.length = 0;
  354. iocb.fin = 0;
  355. iocb.opcode = WSLAY_TEXT_FRAME;
  356. iocb.mask = 0;
  357. iocb.payload_length = 3;
  358. iocb.data = (const uint8_t *)"Hel";
  359. iocb.data_length = 3;
  360. CU_ASSERT(3 == wslay_frame_send(ctx, &iocb));
  361. CU_ASSERT_EQUAL(sizeof(msg1), acc.length);
  362. CU_ASSERT(memcmp(msg1, acc.buf, sizeof(msg1)) == 0);
  363. acc.length = 0;
  364. iocb.fin = 1;
  365. iocb.opcode = WSLAY_PING;
  366. iocb.payload_length = 5;
  367. iocb.data = (const uint8_t *)"Hello";
  368. iocb.data_length = 5;
  369. CU_ASSERT(5 == wslay_frame_send(ctx, &iocb));
  370. CU_ASSERT_EQUAL(sizeof(msg2), acc.length);
  371. CU_ASSERT(memcmp(msg2, acc.buf, sizeof(msg2)) == 0);
  372. acc.length = 0;
  373. iocb.fin = 1;
  374. iocb.opcode = WSLAY_CONTINUATION_FRAME;
  375. iocb.payload_length = 2;
  376. iocb.data = (const uint8_t *)"lo";
  377. iocb.data_length = 2;
  378. CU_ASSERT(2 == wslay_frame_send(ctx, &iocb));
  379. CU_ASSERT_EQUAL(sizeof(msg3), acc.length);
  380. CU_ASSERT(memcmp(msg3, acc.buf, sizeof(msg3)) == 0);
  381. wslay_frame_context_free(ctx);
  382. }
  383. void test_wslay_frame_send_1byte_masked(void) {
  384. wslay_frame_context_ptr ctx;
  385. struct wslay_frame_callbacks callbacks = {scripted_send_callback, NULL,
  386. static_genmask_callback};
  387. struct wslay_frame_iocb iocb;
  388. /* Masked text frame containing "Hello" */
  389. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  390. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  391. uint8_t hello[] = "Hello";
  392. struct scripted_data_feed df;
  393. size_t i;
  394. scripted_data_feed_init(&df, NULL, 0);
  395. for (i = 0; i < sizeof(msg); ++i) {
  396. df.feedseq[i] = 1;
  397. }
  398. wslay_frame_context_init(&ctx, &callbacks, &df);
  399. memset(&iocb, 0, sizeof(iocb));
  400. iocb.fin = 1;
  401. iocb.opcode = WSLAY_TEXT_FRAME;
  402. iocb.mask = 1;
  403. iocb.payload_length = 5;
  404. iocb.data = hello;
  405. iocb.data_length = sizeof(hello) - 1;
  406. for (i = 0; i < 5; ++i) {
  407. CU_ASSERT_EQUAL(WSLAY_ERR_WANT_WRITE, wslay_frame_send(ctx, &iocb));
  408. }
  409. CU_ASSERT_EQUAL(5, wslay_frame_send(ctx, &iocb));
  410. wslay_frame_context_free(ctx);
  411. }
  412. void test_wslay_frame_send_zero_payloadlen(void) {
  413. wslay_frame_context_ptr ctx;
  414. struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL,
  415. static_genmask_callback};
  416. struct accumulator acc;
  417. struct wslay_frame_iocb iocb;
  418. /* Unmasked message */
  419. uint8_t msg[] = {0x81, 0x00}; /* "" */
  420. acc.length = 0;
  421. wslay_frame_context_init(&ctx, &callbacks, &acc);
  422. memset(&iocb, 0, sizeof(iocb));
  423. iocb.fin = 1;
  424. iocb.opcode = WSLAY_TEXT_FRAME;
  425. iocb.mask = 0;
  426. iocb.payload_length = 0;
  427. iocb.data_length = 0;
  428. CU_ASSERT(0 == wslay_frame_send(ctx, &iocb));
  429. CU_ASSERT_EQUAL(sizeof(msg), acc.length);
  430. CU_ASSERT(memcmp(msg, acc.buf, sizeof(msg)) == 0);
  431. wslay_frame_context_free(ctx);
  432. }
  433. void test_wslay_frame_send_too_large_payload(void) {
  434. wslay_frame_context_ptr ctx;
  435. struct wslay_frame_callbacks callbacks;
  436. struct wslay_frame_iocb iocb;
  437. wslay_frame_context_init(&ctx, &callbacks, NULL);
  438. memset(&iocb, 0, sizeof(iocb));
  439. iocb.fin = 1;
  440. iocb.opcode = WSLAY_TEXT_FRAME;
  441. iocb.mask = 0;
  442. iocb.payload_length = UINT64_MAX;
  443. CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, wslay_frame_send(ctx, &iocb));
  444. wslay_frame_context_free(ctx);
  445. }
  446. void test_wslay_frame_send_ctrl_frame_too_large_payload(void) {
  447. wslay_frame_context_ptr ctx;
  448. struct wslay_frame_callbacks callbacks;
  449. struct wslay_frame_iocb iocb;
  450. wslay_frame_context_init(&ctx, &callbacks, NULL);
  451. memset(&iocb, 0, sizeof(iocb));
  452. iocb.fin = 1;
  453. iocb.opcode = WSLAY_PING;
  454. iocb.mask = 0;
  455. iocb.payload_length = 1024;
  456. CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, wslay_frame_send(ctx, &iocb));
  457. wslay_frame_context_free(ctx);
  458. }
  459. void test_wslay_frame_write(void) {
  460. wslay_frame_context_ptr ctx;
  461. struct wslay_frame_callbacks callbacks = {NULL, NULL,
  462. static_genmask_callback};
  463. struct wslay_frame_iocb iocb;
  464. /* Masked text frame containing "Hello" */
  465. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  466. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  467. uint8_t buf[1024];
  468. size_t wpayloadlen;
  469. wslay_frame_context_init(&ctx, &callbacks, NULL);
  470. memset(&iocb, 0, sizeof(iocb));
  471. iocb.fin = 1;
  472. iocb.opcode = WSLAY_TEXT_FRAME;
  473. iocb.mask = 1;
  474. iocb.payload_length = 5;
  475. iocb.data = (const uint8_t *)"Hello";
  476. iocb.data_length = 5;
  477. CU_ASSERT(11 ==
  478. wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  479. CU_ASSERT(iocb.data_length == wpayloadlen);
  480. CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0);
  481. wslay_frame_context_free(ctx);
  482. }
  483. void test_wslay_frame_write_fragmented(void) {
  484. wslay_frame_context_ptr ctx;
  485. struct wslay_frame_callbacks callbacks = {NULL, NULL,
  486. static_genmask_callback};
  487. struct wslay_frame_iocb iocb;
  488. /* Unmasked message */
  489. uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; /* "Hel" */
  490. uint8_t msg2[] = {0x80, 0x02, 0x6c, 0x6f}; /* "lo" */
  491. uint8_t buf[1024];
  492. size_t wpayloadlen;
  493. wslay_frame_context_init(&ctx, &callbacks, NULL);
  494. memset(&iocb, 0, sizeof(iocb));
  495. iocb.fin = 0;
  496. iocb.opcode = WSLAY_TEXT_FRAME;
  497. iocb.mask = 0;
  498. iocb.payload_length = 3;
  499. iocb.data = (const uint8_t *)"Hel";
  500. iocb.data_length = 3;
  501. CU_ASSERT(5 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  502. CU_ASSERT(3 == wpayloadlen);
  503. CU_ASSERT(memcmp(msg1, buf, sizeof(msg1)) == 0);
  504. iocb.fin = 1;
  505. iocb.opcode = WSLAY_CONTINUATION_FRAME;
  506. iocb.payload_length = 2;
  507. iocb.data = (const uint8_t *)"lo";
  508. iocb.data_length = 2;
  509. CU_ASSERT(4 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  510. CU_ASSERT(2 == wpayloadlen);
  511. CU_ASSERT(memcmp(msg2, buf, sizeof(msg2)) == 0);
  512. wslay_frame_context_free(ctx);
  513. }
  514. void test_wslay_frame_write_interleaved_ctrl_frame(void) {
  515. wslay_frame_context_ptr ctx;
  516. struct wslay_frame_callbacks callbacks = {NULL, NULL,
  517. static_genmask_callback};
  518. struct wslay_frame_iocb iocb;
  519. /* Unmasked message */
  520. /* text with "Hel", with fin = 0 */
  521. uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c};
  522. /* ping with "Hello" */
  523. uint8_t msg2[] = {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f};
  524. /* text with "lo", continuation frame for msg1, with fin = 1 */
  525. uint8_t msg3[] = {0x80, 0x02, 0x6c, 0x6f};
  526. uint8_t buf[1024];
  527. size_t wpayloadlen;
  528. wslay_frame_context_init(&ctx, &callbacks, NULL);
  529. memset(&iocb, 0, sizeof(iocb));
  530. iocb.fin = 0;
  531. iocb.opcode = WSLAY_TEXT_FRAME;
  532. iocb.mask = 0;
  533. iocb.payload_length = 3;
  534. iocb.data = (const uint8_t *)"Hel";
  535. iocb.data_length = 3;
  536. CU_ASSERT(5 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  537. CU_ASSERT(3 == wpayloadlen);
  538. CU_ASSERT(memcmp(msg1, buf, sizeof(msg1)) == 0);
  539. iocb.fin = 1;
  540. iocb.opcode = WSLAY_PING;
  541. iocb.payload_length = 5;
  542. iocb.data = (const uint8_t *)"Hello";
  543. iocb.data_length = 5;
  544. CU_ASSERT(7 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  545. CU_ASSERT(5 == wpayloadlen);
  546. CU_ASSERT(memcmp(msg2, buf, sizeof(msg2)) == 0);
  547. iocb.fin = 1;
  548. iocb.opcode = WSLAY_CONTINUATION_FRAME;
  549. iocb.payload_length = 2;
  550. iocb.data = (const uint8_t *)"lo";
  551. iocb.data_length = 2;
  552. CU_ASSERT(4 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  553. CU_ASSERT(2 == wpayloadlen);
  554. CU_ASSERT(memcmp(msg3, buf, sizeof(msg3)) == 0);
  555. wslay_frame_context_free(ctx);
  556. }
  557. void test_wslay_frame_write_1byte_masked(void) {
  558. wslay_frame_context_ptr ctx;
  559. struct wslay_frame_callbacks callbacks = {NULL, NULL,
  560. static_genmask_callback};
  561. struct wslay_frame_iocb iocb;
  562. /* Masked text frame containing "Hello" */
  563. uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du,
  564. 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u};
  565. uint8_t hello[] = "Hello";
  566. size_t i;
  567. uint8_t buf[1024];
  568. size_t wpayloadlen;
  569. wslay_frame_context_init(&ctx, &callbacks, NULL);
  570. memset(&iocb, 0, sizeof(iocb));
  571. iocb.fin = 1;
  572. iocb.opcode = WSLAY_TEXT_FRAME;
  573. iocb.mask = 1;
  574. iocb.payload_length = 5;
  575. iocb.data = hello;
  576. iocb.data_length = sizeof(hello) - 1;
  577. CU_ASSERT_EQUAL(6, wslay_frame_write(ctx, &iocb, buf, 6, &wpayloadlen));
  578. CU_ASSERT(0 == wpayloadlen);
  579. for (i = 0; i < 5; ++i) {
  580. CU_ASSERT_EQUAL(
  581. 1, wslay_frame_write(ctx, &iocb, buf + 6 + i, 1, &wpayloadlen));
  582. CU_ASSERT(1 == wpayloadlen);
  583. ++iocb.data;
  584. --iocb.data_length;
  585. }
  586. CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0);
  587. wslay_frame_context_free(ctx);
  588. }
  589. void test_wslay_frame_write_zero_payloadlen(void) {
  590. wslay_frame_context_ptr ctx;
  591. struct wslay_frame_callbacks callbacks = {NULL, NULL,
  592. static_genmask_callback};
  593. struct wslay_frame_iocb iocb;
  594. /* Unmasked message */
  595. uint8_t msg[] = {0x81, 0x00}; /* "" */
  596. uint8_t buf[1024];
  597. size_t wpayloadlen;
  598. wslay_frame_context_init(&ctx, &callbacks, NULL);
  599. memset(&iocb, 0, sizeof(iocb));
  600. iocb.fin = 1;
  601. iocb.opcode = WSLAY_TEXT_FRAME;
  602. iocb.mask = 0;
  603. iocb.payload_length = 0;
  604. iocb.data_length = 0;
  605. CU_ASSERT(2 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  606. CU_ASSERT(0 == wpayloadlen);
  607. CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0);
  608. wslay_frame_context_free(ctx);
  609. }
  610. void test_wslay_frame_write_too_large_payload(void) {
  611. wslay_frame_context_ptr ctx;
  612. struct wslay_frame_callbacks callbacks;
  613. struct wslay_frame_iocb iocb;
  614. uint8_t buf[1024];
  615. size_t wpayloadlen;
  616. wslay_frame_context_init(&ctx, &callbacks, NULL);
  617. memset(&iocb, 0, sizeof(iocb));
  618. iocb.fin = 1;
  619. iocb.opcode = WSLAY_TEXT_FRAME;
  620. iocb.mask = 0;
  621. iocb.payload_length = UINT64_MAX;
  622. CU_ASSERT_EQUAL(
  623. WSLAY_ERR_INVALID_ARGUMENT,
  624. wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  625. wslay_frame_context_free(ctx);
  626. }
  627. void test_wslay_frame_write_ctrl_frame_too_large_payload(void) {
  628. wslay_frame_context_ptr ctx;
  629. struct wslay_frame_callbacks callbacks;
  630. struct wslay_frame_iocb iocb;
  631. uint8_t buf[1024];
  632. size_t wpayloadlen;
  633. wslay_frame_context_init(&ctx, &callbacks, NULL);
  634. memset(&iocb, 0, sizeof(iocb));
  635. iocb.fin = 1;
  636. iocb.opcode = WSLAY_PING;
  637. iocb.mask = 0;
  638. iocb.payload_length = 1024;
  639. CU_ASSERT_EQUAL(
  640. WSLAY_ERR_INVALID_ARGUMENT,
  641. wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen));
  642. wslay_frame_context_free(ctx);
  643. }