lsquic_hcsi_reader.c revision 7d09751d
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 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 uint64_t len; 475392f7a3SLiteSpeed Tech int s; 485392f7a3SLiteSpeed Tech 495392f7a3SLiteSpeed Tech while (p < end) 505392f7a3SLiteSpeed Tech { 515392f7a3SLiteSpeed Tech switch (reader->hr_state) 525392f7a3SLiteSpeed Tech { 535392f7a3SLiteSpeed Tech case HR_READ_FRAME_BEGIN: 545392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_state = 0; 555392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_CONTINUE; 565392f7a3SLiteSpeed Tech /* fall-through */ 575392f7a3SLiteSpeed Tech case HR_READ_FRAME_CONTINUE: 585392f7a3SLiteSpeed Tech s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 595392f7a3SLiteSpeed Tech if (s < 0) 605392f7a3SLiteSpeed Tech break; 615392f7a3SLiteSpeed Tech reader->hr_frame_type = reader->hr_u.vint2_state.vr2s_one; 625392f7a3SLiteSpeed Tech reader->hr_frame_length = reader->hr_u.vint2_state.vr2s_two; 635392f7a3SLiteSpeed Tech switch (reader->hr_frame_type) 645392f7a3SLiteSpeed Tech { 655392f7a3SLiteSpeed Tech case HQFT_SETTINGS: 665392f7a3SLiteSpeed Tech if (reader->hr_frame_length) 675392f7a3SLiteSpeed Tech { 685392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_BEGIN; 695392f7a3SLiteSpeed Tech reader->hr_nread = 0; 705392f7a3SLiteSpeed Tech } 715392f7a3SLiteSpeed Tech else 725392f7a3SLiteSpeed Tech { 735392f7a3SLiteSpeed Tech reader->hr_cb->on_settings_frame(reader->hr_ctx); 745392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 755392f7a3SLiteSpeed Tech } 765392f7a3SLiteSpeed Tech break; 775392f7a3SLiteSpeed Tech case HQFT_GOAWAY: 785392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 795392f7a3SLiteSpeed Tech break; 805392f7a3SLiteSpeed Tech case HQFT_CANCEL_PUSH: 815392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 825392f7a3SLiteSpeed Tech break; 835392f7a3SLiteSpeed Tech case HQFT_MAX_PUSH_ID: 845392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT; 855392f7a3SLiteSpeed Tech break; 865392f7a3SLiteSpeed Tech case HQFT_DATA: 875392f7a3SLiteSpeed Tech case HQFT_HEADERS: 885392f7a3SLiteSpeed Tech case HQFT_PUSH_PROMISE: 895392f7a3SLiteSpeed Tech reader->hr_cb->on_unexpected_frame(reader->hr_ctx, 905392f7a3SLiteSpeed Tech reader->hr_frame_type); 915392f7a3SLiteSpeed Tech return -1; 925392f7a3SLiteSpeed Tech default: 935392f7a3SLiteSpeed Tech if (!(reader->hr_frame_type >= 0xB && 945392f7a3SLiteSpeed Tech (reader->hr_frame_type - 0xB) % 0x1F == 0)) 955392f7a3SLiteSpeed Tech LSQ_INFO("unknown frame type 0x%"PRIX64" -- skipping", 965392f7a3SLiteSpeed Tech reader->hr_frame_type); 975392f7a3SLiteSpeed Tech reader->hr_state = HR_SKIPPING; 985392f7a3SLiteSpeed Tech LSQ_DEBUG("unknown frame 0x%"PRIX64": will skip %"PRIu64" bytes", 995392f7a3SLiteSpeed Tech reader->hr_frame_type, reader->hr_frame_length); 1005392f7a3SLiteSpeed Tech break; 1015392f7a3SLiteSpeed Tech } 1025392f7a3SLiteSpeed Tech break; 1035392f7a3SLiteSpeed Tech case HR_READ_VARINT: 1045392f7a3SLiteSpeed Tech reader->hr_u.vint_state.pos = 0; 1055392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_VARINT_CONTINUE; 1065392f7a3SLiteSpeed Tech reader->hr_nread = 0; 1075392f7a3SLiteSpeed Tech /* fall-through */ 1085392f7a3SLiteSpeed Tech case HR_READ_VARINT_CONTINUE: 1095392f7a3SLiteSpeed Tech orig_p = p; 1105392f7a3SLiteSpeed Tech s = lsquic_varint_read_nb(&p, end, &reader->hr_u.vint_state); 1115392f7a3SLiteSpeed Tech reader->hr_nread += p - orig_p; 1125392f7a3SLiteSpeed Tech if (0 == s) 1135392f7a3SLiteSpeed Tech { 1145392f7a3SLiteSpeed Tech if (reader->hr_nread != reader->hr_frame_length) 1155392f7a3SLiteSpeed Tech { 1165392f7a3SLiteSpeed Tech reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 11792f6e17bSDmitri Tikhonov HEC_FRAME_ERROR, 1185392f7a3SLiteSpeed Tech "Frame length does not match actual payload length"); 1195392f7a3SLiteSpeed Tech reader->hr_state = HR_ERROR; 1205392f7a3SLiteSpeed Tech return -1; 1215392f7a3SLiteSpeed Tech } 1225392f7a3SLiteSpeed Tech switch (reader->hr_frame_type) 1235392f7a3SLiteSpeed Tech { 1245392f7a3SLiteSpeed Tech case HQFT_GOAWAY: 1255392f7a3SLiteSpeed Tech reader->hr_cb->on_goaway(reader->hr_ctx, 1265392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1275392f7a3SLiteSpeed Tech break; 1285392f7a3SLiteSpeed Tech case HQFT_CANCEL_PUSH: 1295392f7a3SLiteSpeed Tech reader->hr_cb->on_cancel_push(reader->hr_ctx, 1305392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1315392f7a3SLiteSpeed Tech break; 1325392f7a3SLiteSpeed Tech case HQFT_MAX_PUSH_ID: 1335392f7a3SLiteSpeed Tech reader->hr_cb->on_max_push_id(reader->hr_ctx, 1345392f7a3SLiteSpeed Tech reader->hr_u.vint_state.val); 1355392f7a3SLiteSpeed Tech break; 1365392f7a3SLiteSpeed Tech default: 1375392f7a3SLiteSpeed Tech assert(0); 1385392f7a3SLiteSpeed Tech } 1395392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1405392f7a3SLiteSpeed Tech break; 1415392f7a3SLiteSpeed Tech } 1425392f7a3SLiteSpeed Tech else 1435392f7a3SLiteSpeed Tech { 1445392f7a3SLiteSpeed Tech assert(p == end); 1455392f7a3SLiteSpeed Tech return 0; 1465392f7a3SLiteSpeed Tech } 1475392f7a3SLiteSpeed Tech case HR_SKIPPING: 1485392f7a3SLiteSpeed Tech len = MIN((uintptr_t) (end - p), reader->hr_frame_length); 1495392f7a3SLiteSpeed Tech p += len; 1505392f7a3SLiteSpeed Tech reader->hr_frame_length -= len; 1515392f7a3SLiteSpeed Tech if (0 == reader->hr_frame_length) 1525392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1535392f7a3SLiteSpeed Tech break; 1545392f7a3SLiteSpeed Tech case HR_READ_SETTING_BEGIN: 1555392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_state = 0; 1565392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_CONTINUE; 1575392f7a3SLiteSpeed Tech /* fall-through */ 1585392f7a3SLiteSpeed Tech case HR_READ_SETTING_CONTINUE: 1595392f7a3SLiteSpeed Tech orig_p = p; 1605392f7a3SLiteSpeed Tech s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 1615392f7a3SLiteSpeed Tech reader->hr_nread += p - orig_p; 1625392f7a3SLiteSpeed Tech if (reader->hr_nread > reader->hr_frame_length) 1635392f7a3SLiteSpeed Tech { 1645392f7a3SLiteSpeed Tech reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 16592f6e17bSDmitri Tikhonov HEC_FRAME_ERROR, "SETTING frame contents too long"); 1665392f7a3SLiteSpeed Tech reader->hr_state = HR_ERROR; 1675392f7a3SLiteSpeed Tech return -1; 1685392f7a3SLiteSpeed Tech } 1695392f7a3SLiteSpeed Tech if (s < 0) 1705392f7a3SLiteSpeed Tech break; 1715392f7a3SLiteSpeed Tech reader->hr_cb->on_setting(reader->hr_ctx, 1725392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_one, 1735392f7a3SLiteSpeed Tech reader->hr_u.vint2_state.vr2s_two); 1745392f7a3SLiteSpeed Tech if (reader->hr_nread >= reader->hr_frame_length) 1755392f7a3SLiteSpeed Tech { 1765392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_FRAME_BEGIN; 1775392f7a3SLiteSpeed Tech reader->hr_cb->on_settings_frame(reader->hr_ctx); 1785392f7a3SLiteSpeed Tech } 1795392f7a3SLiteSpeed Tech else 1805392f7a3SLiteSpeed Tech reader->hr_state = HR_READ_SETTING_BEGIN; 1815392f7a3SLiteSpeed Tech break; 1825392f7a3SLiteSpeed Tech default: 1835392f7a3SLiteSpeed Tech assert(0); 1845392f7a3SLiteSpeed Tech /* fall-through */ 1855392f7a3SLiteSpeed Tech case HR_ERROR: 1865392f7a3SLiteSpeed Tech return -1; 1875392f7a3SLiteSpeed Tech } 1885392f7a3SLiteSpeed Tech } 1895392f7a3SLiteSpeed Tech 1905392f7a3SLiteSpeed Tech return 0; 1915392f7a3SLiteSpeed Tech} 192