1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 25392f7a3SLiteSpeed Tech#include <assert.h> 35392f7a3SLiteSpeed Tech#include <inttypes.h> 45392f7a3SLiteSpeed Tech#include <stdlib.h> 55392f7a3SLiteSpeed Tech#include <string.h> 65392f7a3SLiteSpeed Tech#include <stdio.h> 75392f7a3SLiteSpeed Tech#include <sys/queue.h> 85392f7a3SLiteSpeed Tech 95392f7a3SLiteSpeed Tech#include "lsquic.h" 105392f7a3SLiteSpeed Tech#include "lsquic_int_types.h" 115392f7a3SLiteSpeed Tech#include "lsquic_varint.h" 125392f7a3SLiteSpeed Tech#include "lsquic_hq.h" 135392f7a3SLiteSpeed Tech#include "lsquic_hcsi_reader.h" 145392f7a3SLiteSpeed Tech#include "lsquic_hash.h" 155392f7a3SLiteSpeed Tech#include "lsquic_conn.h" 165392f7a3SLiteSpeed Tech 175392f7a3SLiteSpeed Techstruct test 185392f7a3SLiteSpeed Tech{ 195392f7a3SLiteSpeed Tech int lineno; 205392f7a3SLiteSpeed Tech 21fbc6cc04SDmitri Tikhonov enum { 22fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS = 0, 23fbc6cc04SDmitri Tikhonov TEST_NUL_OUT_LEST_FULL = 1 << 0, 24fbc6cc04SDmitri Tikhonov } flags; 25fbc6cc04SDmitri Tikhonov 265392f7a3SLiteSpeed Tech unsigned char input[0x100]; 275392f7a3SLiteSpeed Tech size_t input_sz; 285392f7a3SLiteSpeed Tech 295392f7a3SLiteSpeed Tech int retval; 305392f7a3SLiteSpeed Tech char output[0x1000]; 315392f7a3SLiteSpeed Tech}; 325392f7a3SLiteSpeed Tech 335392f7a3SLiteSpeed Tech 345392f7a3SLiteSpeed Techstatic const struct test tests[] = 355392f7a3SLiteSpeed Tech{ 365392f7a3SLiteSpeed Tech { 375392f7a3SLiteSpeed Tech __LINE__, 38fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 395392f7a3SLiteSpeed Tech { 405392f7a3SLiteSpeed Tech 0x03, 415392f7a3SLiteSpeed Tech 0x04, 425392f7a3SLiteSpeed Tech 0x80, 0x12, 0x34, 0x45, 435392f7a3SLiteSpeed Tech }, 445392f7a3SLiteSpeed Tech 6, 455392f7a3SLiteSpeed Tech 0, 465392f7a3SLiteSpeed Tech "on_cancel_push: 1193029\n", 475392f7a3SLiteSpeed Tech }, 485392f7a3SLiteSpeed Tech 495392f7a3SLiteSpeed Tech { 505392f7a3SLiteSpeed Tech __LINE__, 51fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 525392f7a3SLiteSpeed Tech { 535392f7a3SLiteSpeed Tech HQFT_MAX_PUSH_ID, 545392f7a3SLiteSpeed Tech 0x02, 555392f7a3SLiteSpeed Tech 0x41, 0x23, 565392f7a3SLiteSpeed Tech }, 575392f7a3SLiteSpeed Tech 4, 585392f7a3SLiteSpeed Tech 0, 595392f7a3SLiteSpeed Tech "on_max_push_id: 291\n", 605392f7a3SLiteSpeed Tech }, 615392f7a3SLiteSpeed Tech 625392f7a3SLiteSpeed Tech { 635392f7a3SLiteSpeed Tech __LINE__, 64fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 655392f7a3SLiteSpeed Tech { 665392f7a3SLiteSpeed Tech HQFT_SETTINGS, 675392f7a3SLiteSpeed Tech 0x00, 685392f7a3SLiteSpeed Tech }, 695392f7a3SLiteSpeed Tech 2, 705392f7a3SLiteSpeed Tech 0, 715392f7a3SLiteSpeed Tech "have SETTINGS frame\n", 725392f7a3SLiteSpeed Tech }, 735392f7a3SLiteSpeed Tech 745392f7a3SLiteSpeed Tech { /* Frame contents do not match frame length */ 755392f7a3SLiteSpeed Tech __LINE__, 76fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 775392f7a3SLiteSpeed Tech { 785392f7a3SLiteSpeed Tech HQFT_MAX_PUSH_ID, 795392f7a3SLiteSpeed Tech 0x03, 805392f7a3SLiteSpeed Tech 0x41, 0x23, 815392f7a3SLiteSpeed Tech }, 825392f7a3SLiteSpeed Tech 4, 835392f7a3SLiteSpeed Tech -1, 845392f7a3SLiteSpeed Tech "", 855392f7a3SLiteSpeed Tech }, 865392f7a3SLiteSpeed Tech 875392f7a3SLiteSpeed Tech { 885392f7a3SLiteSpeed Tech __LINE__, 89fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 905392f7a3SLiteSpeed Tech { 915392f7a3SLiteSpeed Tech HQFT_SETTINGS, 925392f7a3SLiteSpeed Tech 13, 935392f7a3SLiteSpeed Tech 0x52, 0x34, 945392f7a3SLiteSpeed Tech 0xC0, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 955392f7a3SLiteSpeed Tech 0x52, 0x35, 965392f7a3SLiteSpeed Tech 0x00, 975392f7a3SLiteSpeed Tech }, 985392f7a3SLiteSpeed Tech 15, 995392f7a3SLiteSpeed Tech 0, 1005392f7a3SLiteSpeed Tech "on_setting: 0x1234=0x12233445566778\n" 1015392f7a3SLiteSpeed Tech "on_setting: 0x1235=0x0\n" 1025392f7a3SLiteSpeed Tech "have SETTINGS frame\n" 1035392f7a3SLiteSpeed Tech , 1045392f7a3SLiteSpeed Tech }, 1055392f7a3SLiteSpeed Tech 106fbc6cc04SDmitri Tikhonov { 107fbc6cc04SDmitri Tikhonov __LINE__, 108fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 109fbc6cc04SDmitri Tikhonov { 110fbc6cc04SDmitri Tikhonov 0x80, 0x0F, 0x07, 0x00, /* HQFT_PRIORITY_UPDATE_STREAM */ 111fbc6cc04SDmitri Tikhonov 7, 112fbc6cc04SDmitri Tikhonov 0x52, 0x34, 113fbc6cc04SDmitri Tikhonov 0x41, 0x42, 0x43, 0x44, 0x45, /* ABCDE */ 114fbc6cc04SDmitri Tikhonov HQFT_MAX_PUSH_ID, 115fbc6cc04SDmitri Tikhonov 0x02, 116fbc6cc04SDmitri Tikhonov 0x41, 0x23, 117fbc6cc04SDmitri Tikhonov }, 118fbc6cc04SDmitri Tikhonov 16, 119fbc6cc04SDmitri Tikhonov 0, 120fbc6cc04SDmitri Tikhonov "on_priority_update: stream=0x1234, [ABCDE]\n" 121fbc6cc04SDmitri Tikhonov "on_max_push_id: 291\n" 122fbc6cc04SDmitri Tikhonov , 123fbc6cc04SDmitri Tikhonov }, 124fbc6cc04SDmitri Tikhonov 125fbc6cc04SDmitri Tikhonov { 126fbc6cc04SDmitri Tikhonov __LINE__, 127fbc6cc04SDmitri Tikhonov TEST_NO_FLAGS, 128fbc6cc04SDmitri Tikhonov { 129fbc6cc04SDmitri Tikhonov 0x80, 0x0F, 0x07, 0x01, /* HQFT_PRIORITY_UPDATE_PUSH */ 130fbc6cc04SDmitri Tikhonov 6, 131fbc6cc04SDmitri Tikhonov 0x08, 132fbc6cc04SDmitri Tikhonov 0x50, 0x51, 0x52, 0x53, 0x54, /* PQRST */ 133fbc6cc04SDmitri Tikhonov }, 134fbc6cc04SDmitri Tikhonov 11, 135fbc6cc04SDmitri Tikhonov 0, 136fbc6cc04SDmitri Tikhonov "on_priority_update: push=0x8, [PQRST]\n" 137fbc6cc04SDmitri Tikhonov , 138fbc6cc04SDmitri Tikhonov }, 139fbc6cc04SDmitri Tikhonov 140fbc6cc04SDmitri Tikhonov { 141fbc6cc04SDmitri Tikhonov __LINE__, 142fbc6cc04SDmitri Tikhonov TEST_NUL_OUT_LEST_FULL, 143fbc6cc04SDmitri Tikhonov { 144fbc6cc04SDmitri Tikhonov 0x80, 0x0F, 0x07, 0x01, /* HQFT_PRIORITY_UPDATE_PUSH */ 145fbc6cc04SDmitri Tikhonov 21, 146fbc6cc04SDmitri Tikhonov 0x08, 147fbc6cc04SDmitri Tikhonov 0x50, 0x51, 0x52, 0x53, 0x54, /* PQRST */ 148fbc6cc04SDmitri Tikhonov 0x50, 0x51, 0x52, 0x53, 0x54, /* PQRST */ 149fbc6cc04SDmitri Tikhonov 0x50, 0x51, 0x52, 0x53, 0x54, /* PQRST */ 150fbc6cc04SDmitri Tikhonov 0x50, 0x51, 0x52, 0x53, 0x54, /* PQRST */ 151fbc6cc04SDmitri Tikhonov }, 152fbc6cc04SDmitri Tikhonov 26, 153fbc6cc04SDmitri Tikhonov 0, 154fbc6cc04SDmitri Tikhonov "on_priority_update: push=0x8, [PQRSTPQRSTPQRSTPQRST]\n" 155fbc6cc04SDmitri Tikhonov , 156fbc6cc04SDmitri Tikhonov }, 157fbc6cc04SDmitri Tikhonov 1585392f7a3SLiteSpeed Tech}; 1595392f7a3SLiteSpeed Tech 1605392f7a3SLiteSpeed Tech 1615392f7a3SLiteSpeed Techstatic void 1625392f7a3SLiteSpeed Techon_cancel_push (void *ctx, uint64_t push_id) 1635392f7a3SLiteSpeed Tech{ 1645392f7a3SLiteSpeed Tech fprintf(ctx, "%s: %"PRIu64"\n", __func__, push_id); 1655392f7a3SLiteSpeed Tech} 1665392f7a3SLiteSpeed Tech 1675392f7a3SLiteSpeed Techstatic void 1685392f7a3SLiteSpeed Techon_max_push_id (void *ctx, uint64_t push_id) 1695392f7a3SLiteSpeed Tech{ 1705392f7a3SLiteSpeed Tech fprintf(ctx, "%s: %"PRIu64"\n", __func__, push_id); 1715392f7a3SLiteSpeed Tech} 1725392f7a3SLiteSpeed Tech 1735392f7a3SLiteSpeed Techstatic void 1745392f7a3SLiteSpeed Techon_settings_frame (void *ctx) 1755392f7a3SLiteSpeed Tech{ 1765392f7a3SLiteSpeed Tech fprintf(ctx, "have SETTINGS frame\n"); 1775392f7a3SLiteSpeed Tech} 1785392f7a3SLiteSpeed Tech 1795392f7a3SLiteSpeed Techstatic void 1805392f7a3SLiteSpeed Techon_setting (void *ctx, uint64_t setting_id, uint64_t value) 1815392f7a3SLiteSpeed Tech{ 1825392f7a3SLiteSpeed Tech fprintf(ctx, "%s: 0x%"PRIX64"=0x%"PRIX64"\n", __func__, setting_id, value); 1835392f7a3SLiteSpeed Tech} 1845392f7a3SLiteSpeed Tech 1855392f7a3SLiteSpeed Techstatic void 1865392f7a3SLiteSpeed Techon_goaway (void *ctx, uint64_t stream_id) 1875392f7a3SLiteSpeed Tech{ 1885392f7a3SLiteSpeed Tech fprintf(ctx, "%s: %"PRIu64"\n", __func__, stream_id); 1895392f7a3SLiteSpeed Tech} 1905392f7a3SLiteSpeed Tech 1915392f7a3SLiteSpeed Techstatic void 19255d69529SGeorge Wangon_frame_error (void *ctx, unsigned code, uint64_t frame_type) 1935392f7a3SLiteSpeed Tech{ 1945392f7a3SLiteSpeed Tech fprintf(ctx, "%s: %"PRIu64"\n", __func__, frame_type); 1955392f7a3SLiteSpeed Tech} 1965392f7a3SLiteSpeed Tech 197fbc6cc04SDmitri Tikhonovstatic void 198fbc6cc04SDmitri Tikhonovon_priority_update (void *ctx, enum hq_frame_type frame_type, 199fbc6cc04SDmitri Tikhonov /* PFV: Priority Field Value */ 200fbc6cc04SDmitri Tikhonov uint64_t id, const char *pfv, size_t pfv_sz) 201fbc6cc04SDmitri Tikhonov{ 202fbc6cc04SDmitri Tikhonov const char *type; 203fbc6cc04SDmitri Tikhonov 204fbc6cc04SDmitri Tikhonov switch (frame_type) 205fbc6cc04SDmitri Tikhonov { 206fbc6cc04SDmitri Tikhonov case HQFT_PRIORITY_UPDATE_STREAM: type = "stream"; break; 207fbc6cc04SDmitri Tikhonov case HQFT_PRIORITY_UPDATE_PUSH: type = "push"; break; 208fbc6cc04SDmitri Tikhonov default: assert(0); return; 209fbc6cc04SDmitri Tikhonov } 210fbc6cc04SDmitri Tikhonov 211fbc6cc04SDmitri Tikhonov fprintf(ctx, "%s: %s=0x%"PRIX64", [%.*s]\n", __func__, type, id, 212fbc6cc04SDmitri Tikhonov (int) pfv_sz, pfv); 213fbc6cc04SDmitri Tikhonov} 214fbc6cc04SDmitri Tikhonov 2155392f7a3SLiteSpeed Techstatic const struct hcsi_callbacks callbacks = 2165392f7a3SLiteSpeed Tech{ 2175392f7a3SLiteSpeed Tech .on_cancel_push = on_cancel_push, 2185392f7a3SLiteSpeed Tech .on_max_push_id = on_max_push_id, 2195392f7a3SLiteSpeed Tech .on_settings_frame = on_settings_frame, 2205392f7a3SLiteSpeed Tech .on_setting = on_setting, 2215392f7a3SLiteSpeed Tech .on_goaway = on_goaway, 22255d69529SGeorge Wang .on_frame_error = on_frame_error, 223fbc6cc04SDmitri Tikhonov .on_priority_update = on_priority_update, 2245392f7a3SLiteSpeed Tech}; 2255392f7a3SLiteSpeed Tech 2265392f7a3SLiteSpeed Tech 2275392f7a3SLiteSpeed Techstatic void 2285392f7a3SLiteSpeed Techabort_error (struct lsquic_conn *conn, int is_app, unsigned error_code, 2295392f7a3SLiteSpeed Tech const char *format, ...) 2305392f7a3SLiteSpeed Tech{ 2315392f7a3SLiteSpeed Tech} 2325392f7a3SLiteSpeed Tech 2335392f7a3SLiteSpeed Tech 2345392f7a3SLiteSpeed Techstatic const struct conn_iface conn_iface = { 2355392f7a3SLiteSpeed Tech .ci_abort_error = abort_error, 2365392f7a3SLiteSpeed Tech}; 2375392f7a3SLiteSpeed Tech 2385392f7a3SLiteSpeed Tech 2395392f7a3SLiteSpeed Techstatic void 2405392f7a3SLiteSpeed Techrun_test (const struct test *test) 2415392f7a3SLiteSpeed Tech{ 2425392f7a3SLiteSpeed Tech struct hcsi_reader reader; 2435392f7a3SLiteSpeed Tech size_t read_sz, out_sz, toread; 2445392f7a3SLiteSpeed Tech FILE *out_f; 2455392f7a3SLiteSpeed Tech char *output; 2465392f7a3SLiteSpeed Tech const unsigned char *p; 2475392f7a3SLiteSpeed Tech int s; 2485392f7a3SLiteSpeed Tech struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0); 2495392f7a3SLiteSpeed Tech lconn.cn_if = &conn_iface; 2505392f7a3SLiteSpeed Tech 251fbc6cc04SDmitri Tikhonov for (read_sz = 1; read_sz <= test->input_sz; ++read_sz) 2525392f7a3SLiteSpeed Tech { 2535392f7a3SLiteSpeed Tech out_f = open_memstream(&output, &out_sz); 2545392f7a3SLiteSpeed Tech lsquic_hcsi_reader_init(&reader, &lconn, &callbacks, out_f); 25555d69529SGeorge Wang reader.hr_flag |= HR_FLAG_RCVD_SETTING; 2565392f7a3SLiteSpeed Tech 2575392f7a3SLiteSpeed Tech p = test->input; 2585392f7a3SLiteSpeed Tech do 2595392f7a3SLiteSpeed Tech { 2605392f7a3SLiteSpeed Tech toread = test->input + test->input_sz - p; 2615392f7a3SLiteSpeed Tech if (toread > read_sz) 2625392f7a3SLiteSpeed Tech toread = read_sz; 2635392f7a3SLiteSpeed Tech s = lsquic_hcsi_reader_feed(&reader, p, toread); 2645392f7a3SLiteSpeed Tech if (s != 0) 2655392f7a3SLiteSpeed Tech break; 2665392f7a3SLiteSpeed Tech p += toread; 2675392f7a3SLiteSpeed Tech } 2685392f7a3SLiteSpeed Tech while (p < test->input + test->input_sz); 2695392f7a3SLiteSpeed Tech 2705392f7a3SLiteSpeed Tech assert(s == test->retval); 2715392f7a3SLiteSpeed Tech 2725392f7a3SLiteSpeed Tech fclose(out_f); 273fbc6cc04SDmitri Tikhonov if (test->retval == 0 && read_sz < test->input_sz 274fbc6cc04SDmitri Tikhonov && (test->flags & TEST_NUL_OUT_LEST_FULL)) 275fbc6cc04SDmitri Tikhonov assert(0 == strcmp(output, "")); 276fbc6cc04SDmitri Tikhonov else 277fbc6cc04SDmitri Tikhonov assert(0 == strcmp(test->output, output)); 2785392f7a3SLiteSpeed Tech free(output); 2795392f7a3SLiteSpeed Tech } 2805392f7a3SLiteSpeed Tech} 2815392f7a3SLiteSpeed Tech 2825392f7a3SLiteSpeed Techint 2835392f7a3SLiteSpeed Techmain (void) 2845392f7a3SLiteSpeed Tech{ 2855392f7a3SLiteSpeed Tech const struct test *test; 2865392f7a3SLiteSpeed Tech struct test coalesced_test; 2875392f7a3SLiteSpeed Tech 2885392f7a3SLiteSpeed Tech for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test) 2895392f7a3SLiteSpeed Tech run_test(test); 2905392f7a3SLiteSpeed Tech 2915392f7a3SLiteSpeed Tech memset(&coalesced_test, 0, sizeof(coalesced_test)); 2925392f7a3SLiteSpeed Tech for (test = tests; test < tests + sizeof(tests) / sizeof(tests[0]); ++test) 293fbc6cc04SDmitri Tikhonov if (test->retval == 0 && !(test->flags & TEST_NUL_OUT_LEST_FULL)) 2945392f7a3SLiteSpeed Tech { 2955392f7a3SLiteSpeed Tech memcpy(coalesced_test.input + coalesced_test.input_sz, 2965392f7a3SLiteSpeed Tech test->input, test->input_sz); 2975392f7a3SLiteSpeed Tech coalesced_test.input_sz += test->input_sz; 2985392f7a3SLiteSpeed Tech strcat(coalesced_test.output, test->output); 2995392f7a3SLiteSpeed Tech } 3005392f7a3SLiteSpeed Tech run_test(&coalesced_test); 3015392f7a3SLiteSpeed Tech 3025392f7a3SLiteSpeed Tech return 0; 3035392f7a3SLiteSpeed Tech} 304