lsquic_hcsi_reader.c revision 5392f7a3
15392f7a3SLiteSpeed Tech/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 25392f7a3SLiteSpeed Tech#include <assert.h> 35392f7a3SLiteSpeed Tech#include <inttypes.h> 45392f7a3SLiteSpeed Tech#include <stddef.h> 55392f7a3SLiteSpeed Tech#include <stdint.h> 65392f7a3SLiteSpeed Tech#include <string.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_hash.h" 145392f7a3SLiteSpeed Tech#include "lsquic_conn.h" 155392f7a3SLiteSpeed Tech#include "lsquic_hcsi_reader.h" 165392f7a3SLiteSpeed Tech 175392f7a3SLiteSpeed Tech#define LSQUIC_LOGGER_MODULE LSQLM_HCSI_READER 185392f7a3SLiteSpeed Tech#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(reader->hr_conn) 195392f7a3SLiteSpeed Tech#include "lsquic_logger.h" 205392f7a3SLiteSpeed Tech 215392f7a3SLiteSpeed Tech#define MIN(a, b) ((a) < (b) ? (a) : (b)) 225392f7a3SLiteSpeed Tech 235392f7a3SLiteSpeed Tech 245392f7a3SLiteSpeed Techvoid 255392f7a3SLiteSpeed Techlsquic_hcsi_reader_init (struct hcsi_reader *reader, 265392f7a3SLiteSpeed Tech struct lsquic_conn *conn, const struct hcsi_callbacks *callbacks, 275392f7a3SLiteSpeed Tech void *ctx) 285392f7a3SLiteSpeed Tech{ 295392f7a3SLiteSpeed Tech memset(reader, 0, sizeof(*reader)); 305392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 315392f7a3SLiteSpeed Tech reader->hr_conn = conn; 325392f7a3SLiteSpeed Tech reader->hr_cb = callbacks; 335392f7a3SLiteSpeed Tech reader->hr_ctx = ctx; 345392f7a3SLiteSpeed Tech LSQ_DEBUG("initialized"); 355392f7a3SLiteSpeed Tech} 365392f7a3SLiteSpeed Tech 375392f7a3SLiteSpeed Tech 385392f7a3SLiteSpeed Techint 395392f7a3SLiteSpeed Techlsquic_hcsi_reader_feed (struct hcsi_reader *reader, const void *buf, 405392f7a3SLiteSpeed Tech size_t bufsz) 415392f7a3SLiteSpeed Tech{ 425392f7a3SLiteSpeed Tech const unsigned char *p = buf; 435392f7a3SLiteSpeed Tech const unsigned char *const end = p + bufsz; 445392f7a3SLiteSpeed Tech 455392f7a3SLiteSpeed Tech const unsigned char *orig_p; 465392f7a3SLiteSpeed Tech enum h3_prio_frame_read_status prio_status; 475392f7a3SLiteSpeed Tech uint64_t len; 485392f7a3SLiteSpeed Tech int s; 495392f7a3SLiteSpeed Tech 505392f7a3SLiteSpeed Tech while (p < end) 515392f7a3SLiteSpeed Tech { 525392f7a3SLiteSpeed Tech switch (reader->hr_state) 535392f7a3SLiteSpeed Tech { 545392f7a3SLiteSpeed Tech case HR_READ_FRAME_BEGIN: 555392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_state = 0; 565392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_CONTINUE; 575392f7a3SLiteSpeed Tech /* fall-through */ 585392f7a3SLiteSpeed Tech case HR_READ_FRAME_CONTINUE: 595392f7a3SLiteSpeed Tech s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 605392f7a3SLiteSpeed Tech if (s < 0) 615392f7a3SLiteSpeed Tech break; 625392f7a3SLiteSpeed Tech reader->hr_frame_type = reader->hr_u.vint2_state.vr2s_one; 635392f7a3SLiteSpeed Tech reader->hr_frame_length = reader->hr_u.vint2_state.vr2s_two; 645392f7a3SLiteSpeed Tech switch (reader->hr_frame_type) 655392f7a3SLiteSpeed Tech { 665392f7a3SLiteSpeed Tech case HQFT_SETTINGS: 675392f7a3SLiteSpeed Tech if (reader->hr_frame_length) 685392f7a3SLiteSpeed Tech { 695392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_BEGIN; 705392f7a3SLiteSpeed Tech reader->hr_nread = 0; 715392f7a3SLiteSpeed Tech } 725392f7a3SLiteSpeed Tech else 735392f7a3SLiteSpeed Tech { 745392f7a3SLiteSpeed Tech reader->hr_cb->on_settings_frame(reader->hr_ctx); 755392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 765392f7a3SLiteSpeed Tech } 775392f7a3SLiteSpeed Tech break; 785392f7a3SLiteSpeed Tech case HQFT_PRIORITY: 795392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_PRIORITY_BEGIN; 805392f7a3SLiteSpeed Tech break; 815392f7a3SLiteSpeed Tech case HQFT_GOAWAY: 825392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 835392f7a3SLiteSpeed Tech break; 845392f7a3SLiteSpeed Tech case HQFT_CANCEL_PUSH: 855392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 865392f7a3SLiteSpeed Tech break; 875392f7a3SLiteSpeed Tech case HQFT_MAX_PUSH_ID: 885392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 895392f7a3SLiteSpeed Tech break; 905392f7a3SLiteSpeed Tech case HQFT_DATA: 915392f7a3SLiteSpeed Tech case HQFT_HEADERS: 925392f7a3SLiteSpeed Tech case HQFT_PUSH_PROMISE: 935392f7a3SLiteSpeed Tech reader->hr_cb->on_unexpected_frame(reader->hr_ctx, 945392f7a3SLiteSpeed Tech reader->hr_frame_type); 955392f7a3SLiteSpeed Tech return -1; 965392f7a3SLiteSpeed Tech default: 975392f7a3SLiteSpeed Tech if (!(reader->hr_frame_type >= 0xB && 985392f7a3SLiteSpeed Tech (reader->hr_frame_type - 0xB) % 0x1F == 0)) 995392f7a3SLiteSpeed Tech LSQ_INFO("unknown frame type 0x%"PRIX64" -- skipping", 1005392f7a3SLiteSpeed Tech reader->hr_frame_type); 1015392f7a3SLiteSpeed Tech reader->hr_state = HR_SKIPPING; 1025392f7a3SLiteSpeed Tech LSQ_DEBUG("unknown frame 0x%"PRIX64": will skip %"PRIu64" bytes", 1035392f7a3SLiteSpeed Tech reader->hr_frame_type, reader->hr_frame_length); 1045392f7a3SLiteSpeed Tech break; 1055392f7a3SLiteSpeed Tech } 1065392f7a3SLiteSpeed Tech break; 1075392f7a3SLiteSpeed Tech case HR_READ_VARINT: 1085392f7a3SLiteSpeed Tech reader->hr_u.vint_state.pos = 0; 1095392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT_CONTINUE; 1105392f7a3SLiteSpeed Tech reader->hr_nread = 0; 1115392f7a3SLiteSpeed Tech /* fall-through */ 1125392f7a3SLiteSpeed Tech case HR_READ_VARINT_CONTINUE: 1135392f7a3SLiteSpeed Tech orig_p = p; 1145392f7a3SLiteSpeed Tech s = lsquic_varint_read_nb(&p, end, &reader->hr_u.vint_state); 1155392f7a3SLiteSpeed Tech reader->hr_nread += p - orig_p; 1165392f7a3SLiteSpeed Tech if (0 == s) 1175392f7a3SLiteSpeed Tech { 1185392f7a3SLiteSpeed Tech if (reader->hr_nread != reader->hr_frame_length) 1195392f7a3SLiteSpeed Tech { 1205392f7a3SLiteSpeed Tech reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 1215392f7a3SLiteSpeed Tech HEC_MALFORMED_FRAME + reader->hr_frame_type, 1225392f7a3SLiteSpeed Tech "Frame length does not match actual payload length"); 1235392f7a3SLiteSpeed Tech reader->hr_state = HR_ERROR; 1245392f7a3SLiteSpeed Tech return -1; 1255392f7a3SLiteSpeed Tech } 1265392f7a3SLiteSpeed Tech switch (reader->hr_frame_type) 1275392f7a3SLiteSpeed Tech { 1285392f7a3SLiteSpeed Tech case HQFT_GOAWAY: 1295392f7a3SLiteSpeed Tech reader->hr_cb->on_goaway(reader->hr_ctx, 1305392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1315392f7a3SLiteSpeed Tech break; 1325392f7a3SLiteSpeed Tech case HQFT_CANCEL_PUSH: 1335392f7a3SLiteSpeed Tech reader->hr_cb->on_cancel_push(reader->hr_ctx, 1345392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1355392f7a3SLiteSpeed Tech break; 1365392f7a3SLiteSpeed Tech case HQFT_MAX_PUSH_ID: 1375392f7a3SLiteSpeed Tech reader->hr_cb->on_max_push_id(reader->hr_ctx, 1385392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1395392f7a3SLiteSpeed Tech break; 1405392f7a3SLiteSpeed Tech default: 1415392f7a3SLiteSpeed Tech assert(0); 1425392f7a3SLiteSpeed Tech } 1435392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1445392f7a3SLiteSpeed Tech break; 1455392f7a3SLiteSpeed Tech } 1465392f7a3SLiteSpeed Tech else 1475392f7a3SLiteSpeed Tech { 1485392f7a3SLiteSpeed Tech assert(p == end); 1495392f7a3SLiteSpeed Tech return 0; 1505392f7a3SLiteSpeed Tech } 1515392f7a3SLiteSpeed Tech case HR_SKIPPING: 1525392f7a3SLiteSpeed Tech len = MIN((uintptr_t) (end - p), reader->hr_frame_length); 1535392f7a3SLiteSpeed Tech p += len; 1545392f7a3SLiteSpeed Tech reader->hr_frame_length -= len; 1555392f7a3SLiteSpeed Tech if (0 == reader->hr_frame_length) 1565392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1575392f7a3SLiteSpeed Tech break; 1585392f7a3SLiteSpeed Tech case HR_READ_SETTING_BEGIN: 1595392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_state = 0; 1605392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_CONTINUE; 1615392f7a3SLiteSpeed Tech /* fall-through */ 1625392f7a3SLiteSpeed Tech case HR_READ_SETTING_CONTINUE: 1635392f7a3SLiteSpeed Tech orig_p = p; 1645392f7a3SLiteSpeed Tech s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 1655392f7a3SLiteSpeed Tech reader->hr_nread += p - orig_p; 1665392f7a3SLiteSpeed Tech if (reader->hr_nread > reader->hr_frame_length) 1675392f7a3SLiteSpeed Tech { 1685392f7a3SLiteSpeed Tech reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 1695392f7a3SLiteSpeed Tech HEC_MALFORMED_FRAME + HQFT_SETTINGS, 1705392f7a3SLiteSpeed Tech "SETTING frame contents too long"); 1715392f7a3SLiteSpeed Tech reader->hr_state = HR_ERROR; 1725392f7a3SLiteSpeed Tech return -1; 1735392f7a3SLiteSpeed Tech } 1745392f7a3SLiteSpeed Tech if (s < 0) 1755392f7a3SLiteSpeed Tech break; 1765392f7a3SLiteSpeed Tech reader->hr_cb->on_setting(reader->hr_ctx, 1775392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_one, 1785392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_two); 1795392f7a3SLiteSpeed Tech if (reader->hr_nread >= reader->hr_frame_length) 1805392f7a3SLiteSpeed Tech { 1815392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1825392f7a3SLiteSpeed Tech reader->hr_cb->on_settings_frame(reader->hr_ctx); 1835392f7a3SLiteSpeed Tech } 1845392f7a3SLiteSpeed Tech else 1855392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_BEGIN; 1865392f7a3SLiteSpeed Tech break; 1875392f7a3SLiteSpeed Tech case HR_READ_PRIORITY_BEGIN: 1885392f7a3SLiteSpeed Tech reader->hr_u.prio.h3pfrs_state = 0; 1895392f7a3SLiteSpeed Tech reader->hr_nread = 0; 1905392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_PRIORITY_CONTINUE; 1915392f7a3SLiteSpeed Tech /* fall-through */ 1925392f7a3SLiteSpeed Tech case HR_READ_PRIORITY_CONTINUE: 1935392f7a3SLiteSpeed Tech orig_p = p; 1945392f7a3SLiteSpeed Tech prio_status = lsquic_h3_prio_frame_read(&p, end - p, 1955392f7a3SLiteSpeed Tech &reader->hr_u.prio); 1965392f7a3SLiteSpeed Tech reader->hr_nread += p - orig_p; 1975392f7a3SLiteSpeed Tech if (prio_status == H3PFR_STATUS_DONE) 1985392f7a3SLiteSpeed Tech { 1995392f7a3SLiteSpeed Tech if (reader->hr_nread != reader->hr_frame_length) 2005392f7a3SLiteSpeed Tech { 2015392f7a3SLiteSpeed Tech reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 2025392f7a3SLiteSpeed Tech HEC_MALFORMED_FRAME + HQFT_PRIORITY, "PRIORITY frame " 2035392f7a3SLiteSpeed Tech "contents size does not match frame length"); 2045392f7a3SLiteSpeed Tech reader->hr_state = HR_ERROR; 2055392f7a3SLiteSpeed Tech return -1; 2065392f7a3SLiteSpeed Tech } 2075392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 2085392f7a3SLiteSpeed Tech reader->hr_cb->on_priority(reader->hr_ctx, 2095392f7a3SLiteSpeed Tech &reader->hr_u.prio.h3pfrs_prio); 2105392f7a3SLiteSpeed Tech } 2115392f7a3SLiteSpeed Tech break; 2125392f7a3SLiteSpeed Tech default: 2135392f7a3SLiteSpeed Tech assert(0); 2145392f7a3SLiteSpeed Tech /* fall-through */ 2155392f7a3SLiteSpeed Tech case HR_ERROR: 2165392f7a3SLiteSpeed Tech return -1; 2175392f7a3SLiteSpeed Tech } 2185392f7a3SLiteSpeed Tech } 2195392f7a3SLiteSpeed Tech 2205392f7a3SLiteSpeed Tech return 0; 2215392f7a3SLiteSpeed Tech} 222