1 /*
2 * Copyright (c) 2014 by Farsight Security, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25 #include <assert.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <fstrm.h>
32
33 #include "libmy/print_string.h"
34
35 /* Placeholder "Content Type" values. */
36 static const uint8_t wharrgarbl[] = "wharr\x00garbl";
37 static const uint8_t wharrgarblv2[] = "wharrgarblv2";
38
39 /*
40 * Valid control frames. These come in two variants, the *_wh suffixed ones that
41 * include the escape sequence and control frame length header which must be
42 * encoded/decoded with the FSTRM_CONTROL_FLAG_WITH_HEADER flag, and the
43 * un-suffixed ones which must be encoded/decoded without the
44 * FSTRM_CONTROL_FLAG_WITH_HEADER flag.
45 */
46
47 static const uint8_t accept_1[] = {
48 /* FSTRM_CONTROL_ACCEPT. */
49 0x00, 0x00, 0x00, 0x01,
50 };
51
52 static const uint8_t accept_1_wh[] = {
53 /* Escape sequence. */
54 0x00, 0x00, 0x00, 0x00,
55
56 /* Control frame length: 4 bytes of control frame payload. */
57 0x00, 0x00, 0x00, 0x04,
58
59 /* FSTRM_CONTROL_ACCEPT. */
60 0x00, 0x00, 0x00, 0x01,
61 };
62
63 static const uint8_t accept_2[] = {
64 /* FSTRM_CONTROL_ACCEPT. */
65 0x00, 0x00, 0x00, 0x01,
66
67 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
68 0x00, 0x00, 0x00, 0x01,
69 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
70 0x00, 0x00, 0x00, 0x0b,
71 /* The CONTENT_TYPE field payload. */
72 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
73 };
74
75 static const uint8_t accept_2_wh[] = {
76 /* Escape sequence. */
77 0x00, 0x00, 0x00, 0x00,
78
79 /* Control frame length: 23 bytes of control frame payload. */
80 0x00, 0x00, 0x00, 0x17,
81
82 /* FSTRM_CONTROL_ACCEPT. */
83 0x00, 0x00, 0x00, 0x01,
84
85 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
86 0x00, 0x00, 0x00, 0x01,
87 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
88 0x00, 0x00, 0x00, 0x0b,
89 /* The CONTENT_TYPE field payload. */
90 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
91 };
92
93 static const uint8_t accept_3[] = {
94 /* FSTRM_CONTROL_ACCEPT. */
95 0x00, 0x00, 0x00, 0x01,
96
97 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
98 0x00, 0x00, 0x00, 0x01,
99 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
100 0x00, 0x00, 0x00, 0x0b,
101 /* The CONTENT_TYPE field payload. */
102 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
103
104 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
105 0x00, 0x00, 0x00, 0x01,
106 /* 0x0c (12 bytes) of CONTENT_TYPE field payload follow. */
107 0x00, 0x00, 0x00, 0x0c,
108 /* The CONTENT_TYPE field payload. */
109 'w', 'h', 'a', 'r', 'r', 'g', 'a', 'r', 'b', 'l', 'v', '2',
110 };
111
112 static const uint8_t accept_3_wh[] = {
113 /* Escape sequence. */
114 0x00, 0x00, 0x00, 0x00,
115
116 /* Control frame length: 43 bytes of control frame payload. */
117 0x00, 0x00, 0x00, 0x2b,
118
119 /* FSTRM_CONTROL_ACCEPT. */
120 0x00, 0x00, 0x00, 0x01,
121
122 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
123 0x00, 0x00, 0x00, 0x01,
124 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
125 0x00, 0x00, 0x00, 0x0b,
126 /* The CONTENT_TYPE field payload. */
127 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
128
129 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
130 0x00, 0x00, 0x00, 0x01,
131 /* 0x0c (12 bytes) of CONTENT_TYPE field payload follow. */
132 0x00, 0x00, 0x00, 0x0c,
133 /* The CONTENT_TYPE field payload. */
134 'w', 'h', 'a', 'r', 'r', 'g', 'a', 'r', 'b', 'l', 'v', '2',
135 };
136
137 static const uint8_t ready_1[] = {
138 /* FSTRM_CONTROL_READY. */
139 0x00, 0x00, 0x00, 0x04,
140
141 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
142 0x00, 0x00, 0x00, 0x01,
143 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
144 0x00, 0x00, 0x00, 0x0b,
145 /* The CONTENT_TYPE field payload. */
146 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
147
148 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
149 0x00, 0x00, 0x00, 0x01,
150 /* 0x0c (12 bytes) of CONTENT_TYPE field payload follow. */
151 0x00, 0x00, 0x00, 0x0c,
152 /* The CONTENT_TYPE field payload. */
153 'w', 'h', 'a', 'r', 'r', 'g', 'a', 'r', 'b', 'l', 'v', '2',
154 };
155
156 static const uint8_t start_1[] = {
157 /* FSTRM_CONTROL_START. */
158 0x00, 0x00, 0x00, 0x02,
159 };
160
161 static const uint8_t start_1_wh[] = {
162 /* Escape sequence. */
163 0x00, 0x00, 0x00, 0x00,
164
165 /* Control frame length: 4 bytes of control frame payload. */
166 0x00, 0x00, 0x00, 0x04,
167
168 /* FSTRM_CONTROL_START. */
169 0x00, 0x00, 0x00, 0x02,
170 };
171
172 static const uint8_t start_2[] = {
173 /* FSTRM_CONTROL_START. */
174 0x00, 0x00, 0x00, 0x02,
175
176 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
177 0x00, 0x00, 0x00, 0x01,
178
179 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
180 0x00, 0x00, 0x00, 0x0b,
181
182 /* The CONTENT_TYPE field payload. */
183 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
184 };
185
186 static const uint8_t start_2_wh[] = {
187 /* Escape sequence. */
188 0x00, 0x00, 0x00, 0x00,
189
190 /* Control frame length: 23 bytes of control frame payload. */
191 0x00, 0x00, 0x00, 0x17,
192
193 /* FSTRM_CONTROL_START. */
194 0x00, 0x00, 0x00, 0x02,
195
196 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
197 0x00, 0x00, 0x00, 0x01,
198
199 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
200 0x00, 0x00, 0x00, 0x0b,
201
202 /* The CONTENT_TYPE field payload. */
203 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l',
204 };
205
206 static const uint8_t stop_1[] = {
207 /* FSTRM_CONTROL_STOP. */
208 0x00, 0x00, 0x00, 0x03,
209 };
210
211 static const uint8_t stop_1_wh[] = {
212 /* Escape sequence. */
213 0x00, 0x00, 0x00, 0x00,
214
215 /* Control frame length: 4 bytes of control frame payload. */
216 0x00, 0x00, 0x00, 0x04,
217
218 /* FSTRM_CONTROL_STOP. */
219 0x00, 0x00, 0x00, 0x03,
220 };
221
222 /*
223 * Structure for encoding parameters and expected results for the above control
224 * tests.
225 */
226 struct control_test {
227 const uint8_t *frame;
228 size_t len_frame;
229 fstrm_control_type type;
230 uint32_t flags;
231 const uint8_t *content_type;
232 size_t len_content_type;
233 fstrm_res match_res;
234 };
235
236 static const struct control_test control_tests[] = {
237 {
238 .frame = accept_1,
239 .len_frame = sizeof(accept_1),
240 .type = FSTRM_CONTROL_ACCEPT,
241 },
242 {
243 .frame = accept_1_wh,
244 .len_frame = sizeof(accept_1_wh),
245 .type = FSTRM_CONTROL_ACCEPT,
246 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
247 },
248 {
249 .frame = accept_2,
250 .len_frame = sizeof(accept_2),
251 .type = FSTRM_CONTROL_ACCEPT,
252 .content_type = wharrgarbl,
253 .len_content_type = sizeof(wharrgarbl) - 1,
254 },
255 {
256 .frame = accept_2_wh,
257 .len_frame = sizeof(accept_2_wh),
258 .type = FSTRM_CONTROL_ACCEPT,
259 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
260 .content_type = wharrgarbl,
261 .len_content_type = sizeof(wharrgarbl) - 1,
262 },
263 {
264 .frame = accept_3,
265 .len_frame = sizeof(accept_3),
266 .type = FSTRM_CONTROL_ACCEPT,
267 .content_type = wharrgarbl,
268 .len_content_type = sizeof(wharrgarbl) - 1,
269 },
270 {
271 .frame = accept_3_wh,
272 .len_frame = sizeof(accept_3_wh),
273 .type = FSTRM_CONTROL_ACCEPT,
274 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
275 .content_type = wharrgarbl,
276 .len_content_type = sizeof(wharrgarbl) - 1,
277 },
278 {
279 .frame = accept_3,
280 .len_frame = sizeof(accept_3),
281 .type = FSTRM_CONTROL_ACCEPT,
282 .content_type = wharrgarblv2,
283 .len_content_type = sizeof(wharrgarblv2) - 1,
284 },
285 {
286 .frame = accept_3_wh,
287 .len_frame = sizeof(accept_3_wh),
288 .type = FSTRM_CONTROL_ACCEPT,
289 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
290 .content_type = wharrgarblv2,
291 .len_content_type = sizeof(wharrgarblv2) - 1,
292 },
293 {
294 .frame = ready_1,
295 .len_frame = sizeof(ready_1),
296 .type = FSTRM_CONTROL_READY,
297 .content_type = wharrgarbl,
298 .len_content_type = sizeof(wharrgarbl) - 1,
299 },
300 {
301 .frame = ready_1,
302 .len_frame = sizeof(ready_1),
303 .type = FSTRM_CONTROL_READY,
304 .content_type = wharrgarblv2,
305 .len_content_type = sizeof(wharrgarblv2) - 1,
306 },
307 {
308 .frame = start_1,
309 .len_frame = sizeof(start_1),
310 .type = FSTRM_CONTROL_START,
311 },
312 {
313 .frame = start_1_wh,
314 .len_frame = sizeof(start_1_wh),
315 .type = FSTRM_CONTROL_START,
316 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
317 },
318 {
319 .frame = start_1,
320 .len_frame = sizeof(start_1),
321 .type = FSTRM_CONTROL_START,
322 .content_type = wharrgarbl,
323 .len_content_type = sizeof(wharrgarbl) - 1,
324 },
325 {
326 .frame = start_1_wh,
327 .len_frame = sizeof(start_1_wh),
328 .type = FSTRM_CONTROL_START,
329 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
330 .content_type = wharrgarbl,
331 .len_content_type = sizeof(wharrgarbl) - 1,
332 },
333 {
334 .frame = start_2,
335 .len_frame = sizeof(start_2),
336 .type = FSTRM_CONTROL_START,
337 .content_type = wharrgarbl,
338 .len_content_type = sizeof(wharrgarbl) - 1,
339 },
340 {
341 .frame = start_2,
342 .len_frame = sizeof(start_2),
343 .type = FSTRM_CONTROL_START,
344 .content_type = wharrgarblv2,
345 .len_content_type = sizeof(wharrgarblv2) - 1,
346 .match_res = fstrm_res_failure,
347 },
348 {
349 .frame = start_2_wh,
350 .len_frame = sizeof(start_2_wh),
351 .type = FSTRM_CONTROL_START,
352 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
353 .content_type = wharrgarbl,
354 .len_content_type = sizeof(wharrgarbl) - 1,
355 },
356 {
357 .frame = stop_1,
358 .len_frame = sizeof(stop_1),
359 .type = FSTRM_CONTROL_STOP,
360 .match_res = fstrm_res_failure,
361 },
362 {
363 .frame = stop_1_wh,
364 .len_frame = sizeof(stop_1_wh),
365 .type = FSTRM_CONTROL_STOP,
366 .flags = FSTRM_CONTROL_FLAG_WITH_HEADER,
367 .match_res = fstrm_res_failure,
368 },
369
370 { .frame = NULL },
371 };
372
373 /* Invalid control frames. */
374
375 static const uint8_t invalid_1[] = { 0xff, };
376
377 static const uint8_t invalid_2[] = { 0xff, 0xff, };
378
379 static const uint8_t invalid_3[] = { 0xff, 0xff, 0xff, };
380
381 static const uint8_t invalid_4[] = { 0xff, 0xff, 0xff, };
382
383 static const uint8_t invalid_5[] = { 0xff, 0xff, 0xff, 0xff, };
384
385 static const uint8_t invalid_6[] = { 0xff, 0xff, 0xff, 0xff, 0xff };
386
387 static const uint8_t invalid_7[] = { 0xab, 0xad, 0x1d, 0xea, };
388
389 static const uint8_t invalid_8[] = {
390 /* FSTRM_CONTROL_START. */
391 0x00, 0x00, 0x00, 0x02,
392
393 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
394 0x00, 0x00, 0x00, 0x01,
395
396 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
397 0x00, 0x00, 0x00, 0x0b,
398
399 /* The CONTENT_TYPE field payload. Only 10 bytes here. Short read! */
400 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b',
401 };
402
403 static const uint8_t invalid_9[] = {
404 /* FSTRM_CONTROL_START. */
405 0x00, 0x00, 0x00, 0x02,
406
407 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
408 0x00, 0x00, 0x00, 0x01,
409
410 /* 0x0b (11 bytes) of CONTENT_TYPE field payload follow. */
411 0x00, 0x00, 0x00, 0x0b,
412
413 /* The CONTENT_TYPE field payload. An extra byte here. */
414 'w', 'h', 'a', 'r', 'r', 0x00, 'g', 'a', 'r', 'b', 'l', 'z',
415 };
416
417 static const uint8_t invalid_10[] = {
418 /* FSTRM_CONTROL_START. */
419 0x00, 0x00, 0x00, 0x02,
420
421 /* Incomplete control field. */
422 0x00,
423 };
424
425 static const uint8_t invalid_11[] = {
426 /* FSTRM_CONTROL_START. */
427 0x00, 0x00, 0x00, 0x02,
428
429 /* Incomplete control field. */
430 0x00, 0x00, 0x00,
431 };
432
433 static const uint8_t invalid_12[] = {
434 /* FSTRM_CONTROL_START. */
435 0x00, 0x00, 0x00, 0x02,
436
437 /* FSTRM_CONTROL_FIELD_CONTENT_TYPE. */
438 0x00, 0x00, 0x00, 0x01,
439
440 /* No CONTENT_TYPE field payload. This is required. */
441 };
442
443 struct bytes {
444 const uint8_t *bytes;
445 size_t len;
446 };
447
448 static const struct bytes invalid[] = {
449 { invalid_1, sizeof(invalid_1), },
450 { invalid_2, sizeof(invalid_2), },
451 { invalid_3, sizeof(invalid_3), },
452 { invalid_4, sizeof(invalid_4), },
453 { invalid_5, sizeof(invalid_5), },
454 { invalid_6, sizeof(invalid_6), },
455 { invalid_7, sizeof(invalid_7), },
456 { invalid_8, sizeof(invalid_8), },
457 { invalid_9, sizeof(invalid_9), },
458 { invalid_10, sizeof(invalid_10), },
459 { invalid_11, sizeof(invalid_11), },
460 { invalid_12, sizeof(invalid_12), },
461 { NULL, 0 },
462 };
463
464 static fstrm_res
match_content_type(struct fstrm_control * c,const uint8_t * content_type,size_t len_content_type)465 match_content_type(struct fstrm_control *c,
466 const uint8_t *content_type,
467 size_t len_content_type)
468 {
469 fstrm_res res;
470
471 res = fstrm_control_match_field_content_type(c, content_type, len_content_type);
472 printf(" Control frame is %scompatible with CONTENT_TYPE (%zd bytes): ",
473 res == fstrm_res_success ? "" : "NOT ",
474 len_content_type);
475 print_string(content_type, len_content_type, stdout);
476 putchar('\n');
477
478 return res;
479 }
480
481 static fstrm_res
decode_control_frame(struct fstrm_control * c,const uint8_t * control_frame,size_t len_control_frame,uint32_t flags)482 decode_control_frame(struct fstrm_control *c,
483 const uint8_t *control_frame,
484 size_t len_control_frame,
485 uint32_t flags)
486 {
487 fstrm_res res;
488 fstrm_control_type type;
489
490 res = fstrm_control_decode(c, control_frame, len_control_frame, flags);
491 if (res == fstrm_res_success) {
492 printf("Successfully decoded frame (%zd bytes):\n ",
493 len_control_frame);
494 print_string(control_frame, len_control_frame, stdout);
495 putchar('\n');
496 } else {
497 printf("Failed to decode frame (%zd bytes):\n ",
498 len_control_frame);
499 print_string(control_frame, len_control_frame, stdout);
500 putchar('\n');
501 return res;
502 }
503
504 res = fstrm_control_get_type(c, &type);
505 if (res != fstrm_res_success) {
506 puts(" fstrm_control_get_type() failed.");
507 return res;
508 }
509 printf(" The control frame is of type %s (0x%08x).\n",
510 fstrm_control_type_to_str(type), type);
511
512 size_t n_ctype;
513 res = fstrm_control_get_num_field_content_type(c, &n_ctype);
514 if (res != fstrm_res_success) {
515 puts(" fstrm_control_get_num_field_content_type() failed.");
516 return res;
517 }
518 for (size_t idx = 0; idx < n_ctype; idx++) {
519 const uint8_t *content_type;
520 size_t len_content_type;
521
522 res = fstrm_control_get_field_content_type(c, idx,
523 &content_type, &len_content_type);
524 if (res == fstrm_res_success) {
525 printf(" The control frame has a CONTENT_TYPE field (%zd bytes): ",
526 len_content_type);
527 print_string(content_type, len_content_type, stdout);
528 putchar('\n');
529 } else if (res == fstrm_res_failure) {
530 puts(" The control frame does not have any CONTENT_TYPE fields.");
531 } else {
532 /* Not reached. */
533 assert(0);
534 }
535 }
536
537 return fstrm_res_success;
538 }
539
540 static void
test_reencode_frame(struct fstrm_control * c,const uint8_t * control_frame,size_t len_control_frame,uint32_t flags)541 test_reencode_frame(struct fstrm_control *c,
542 const uint8_t *control_frame,
543 size_t len_control_frame,
544 uint32_t flags)
545 {
546 printf("Running %s().\n", __func__);
547
548 fstrm_res res;
549 int cmp;
550 size_t len_new_frame = 0, len_new_frame_2 = 0;
551
552 res = fstrm_control_encoded_size(c, &len_new_frame, flags);
553 assert(res == fstrm_res_success);
554 printf("Need %zd bytes for new frame.\n", len_new_frame);
555 assert(len_new_frame <= FSTRM_CONTROL_FRAME_LENGTH_MAX);
556 uint8_t new_frame[len_new_frame];
557
558 len_new_frame_2 = len_new_frame;
559 res = fstrm_control_encode(c, new_frame, &len_new_frame_2, flags);
560 assert(res == fstrm_res_success);
561 printf("Successfully encoded a new frame (%zd bytes):\n ",
562 len_new_frame_2);
563 print_string(new_frame, len_new_frame_2, stdout);
564 putchar('\n');
565 assert(len_new_frame == len_new_frame_2);
566 assert(len_new_frame == len_control_frame);
567
568 cmp = memcmp(control_frame, new_frame, len_control_frame);
569 assert(cmp == 0);
570 puts("New frame is identical to original frame.");
571 }
572
573 static void
test_reencode_frame_static(struct fstrm_control * c,const uint8_t * control_frame,size_t len_control_frame,uint32_t flags)574 test_reencode_frame_static(struct fstrm_control *c,
575 const uint8_t *control_frame,
576 size_t len_control_frame,
577 uint32_t flags)
578 {
579 printf("Running %s().\n", __func__);
580
581 fstrm_res res;
582 int cmp;
583 uint8_t new_frame[FSTRM_CONTROL_FRAME_LENGTH_MAX];
584 size_t len_new_frame = sizeof(new_frame);
585
586 res = fstrm_control_encode(c, new_frame, &len_new_frame, flags);
587 assert(res == fstrm_res_success);
588 assert(len_new_frame <= FSTRM_CONTROL_FRAME_LENGTH_MAX);
589 printf("Successfully encoded a new frame (%zd bytes):\n ", len_new_frame);
590 print_string(new_frame, len_new_frame, stdout);
591 putchar('\n');
592
593 cmp = memcmp(control_frame, new_frame, len_control_frame);
594 assert(cmp == 0);
595 puts("New frame is identical to original frame.");
596 }
597
598 static void
test_control_test(struct fstrm_control * c,const struct control_test * test)599 test_control_test(struct fstrm_control *c, const struct control_test *test)
600 {
601 printf("Running %s().\n", __func__);
602
603 if (test->flags & FSTRM_CONTROL_FLAG_WITH_HEADER)
604 printf("Control frames include escape sequence and control frame length.\n"
605 " (FSTRM_CONTROL_FLAG_WITH_HEADER enabled.)\n");
606
607 fstrm_res res;
608 fstrm_control_type type;
609
610 res = decode_control_frame(c, test->frame, test->len_frame, test->flags);
611 assert(res == fstrm_res_success);
612 res = fstrm_control_get_type(c, &type);
613 assert(res == fstrm_res_success);
614 assert(type == test->type);
615
616 res = match_content_type(c, test->content_type, test->len_content_type);
617 assert(res == test->match_res);
618
619 test_reencode_frame(c, test->frame, test->len_frame, test->flags);
620 test_reencode_frame_static(c, test->frame, test->len_frame, test->flags);
621 }
622
623 static void
test_control_tests(struct fstrm_control * c)624 test_control_tests(struct fstrm_control *c)
625 {
626 printf("Running %s().\n\n", __func__);
627
628 for (const struct control_test *test = &control_tests[0];
629 test->frame != NULL;
630 test++)
631 {
632 test_control_test(c, test);
633 putchar('\n');
634 }
635 }
636
637 static void
test_invalid(struct fstrm_control * c)638 test_invalid(struct fstrm_control *c)
639 {
640 printf("Running %s().\n", __func__);
641
642 for (const struct bytes *test = &invalid[0];
643 test->bytes != NULL;
644 test++)
645 {
646 fstrm_res res;
647 res = decode_control_frame(c, test->bytes, test->len, 0);
648 assert(res != fstrm_res_success);
649 }
650 }
651
652 int
main(void)653 main(void)
654 {
655 struct fstrm_control *c;
656
657 c = fstrm_control_init();
658
659 puts("====> The following tests must succeed. <====");
660 test_control_tests(c);
661
662 puts("====> The following tests must fail. <====");
663 test_invalid(c);
664
665 fstrm_control_destroy(&c);
666
667 return EXIT_SUCCESS;
668 }
669