lsquic_hcsi_reader.c revision 7d09751d
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <inttypes.h> 4#include <stddef.h> 5#include <stdint.h> 6#include <string.h> 7#include <sys/queue.h> 8 9#include "lsquic.h" 10#include "lsquic_int_types.h" 11#include "lsquic_varint.h" 12#include "lsquic_hq.h" 13#include "lsquic_hash.h" 14#include "lsquic_conn.h" 15#include "lsquic_hcsi_reader.h" 16 17#define LSQUIC_LOGGER_MODULE LSQLM_HCSI_READER 18#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(reader->hr_conn) 19#include "lsquic_logger.h" 20 21#define MIN(a, b) ((a) < (b) ? (a) : (b)) 22 23 24void 25lsquic_hcsi_reader_init (struct hcsi_reader *reader, 26 struct lsquic_conn *conn, const struct hcsi_callbacks *callbacks, 27 void *ctx) 28{ 29 memset(reader, 0, sizeof(*reader)); 30 reader->hr_state = HR_READ_FRAME_BEGIN; 31 reader->hr_conn = conn; 32 reader->hr_cb = callbacks; 33 reader->hr_ctx = ctx; 34 LSQ_DEBUG("initialized"); 35} 36 37 38int 39lsquic_hcsi_reader_feed (struct hcsi_reader *reader, const void *buf, 40 size_t bufsz) 41{ 42 const unsigned char *p = buf; 43 const unsigned char *const end = p + bufsz; 44 45 const unsigned char *orig_p; 46 uint64_t len; 47 int s; 48 49 while (p < end) 50 { 51 switch (reader->hr_state) 52 { 53 case HR_READ_FRAME_BEGIN: 54 reader->hr_u.vint2_state.vr2s_state = 0; 55 reader->hr_state = HR_READ_FRAME_CONTINUE; 56 /* fall-through */ 57 case HR_READ_FRAME_CONTINUE: 58 s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 59 if (s < 0) 60 break; 61 reader->hr_frame_type = reader->hr_u.vint2_state.vr2s_one; 62 reader->hr_frame_length = reader->hr_u.vint2_state.vr2s_two; 63 switch (reader->hr_frame_type) 64 { 65 case HQFT_SETTINGS: 66 if (reader->hr_frame_length) 67 { 68 reader->hr_state = HR_READ_SETTING_BEGIN; 69 reader->hr_nread = 0; 70 } 71 else 72 { 73 reader->hr_cb->on_settings_frame(reader->hr_ctx); 74 reader->hr_state = HR_READ_FRAME_BEGIN; 75 } 76 break; 77 case HQFT_GOAWAY: 78 reader->hr_state = HR_READ_VARINT; 79 break; 80 case HQFT_CANCEL_PUSH: 81 reader->hr_state = HR_READ_VARINT; 82 break; 83 case HQFT_MAX_PUSH_ID: 84 reader->hr_state = HR_READ_VARINT; 85 break; 86 case HQFT_DATA: 87 case HQFT_HEADERS: 88 case HQFT_PUSH_PROMISE: 89 reader->hr_cb->on_unexpected_frame(reader->hr_ctx, 90 reader->hr_frame_type); 91 return -1; 92 default: 93 if (!(reader->hr_frame_type >= 0xB && 94 (reader->hr_frame_type - 0xB) % 0x1F == 0)) 95 LSQ_INFO("unknown frame type 0x%"PRIX64" -- skipping", 96 reader->hr_frame_type); 97 reader->hr_state = HR_SKIPPING; 98 LSQ_DEBUG("unknown frame 0x%"PRIX64": will skip %"PRIu64" bytes", 99 reader->hr_frame_type, reader->hr_frame_length); 100 break; 101 } 102 break; 103 case HR_READ_VARINT: 104 reader->hr_u.vint_state.pos = 0; 105 reader->hr_state = HR_READ_VARINT_CONTINUE; 106 reader->hr_nread = 0; 107 /* fall-through */ 108 case HR_READ_VARINT_CONTINUE: 109 orig_p = p; 110 s = lsquic_varint_read_nb(&p, end, &reader->hr_u.vint_state); 111 reader->hr_nread += p - orig_p; 112 if (0 == s) 113 { 114 if (reader->hr_nread != reader->hr_frame_length) 115 { 116 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 117 HEC_FRAME_ERROR, 118 "Frame length does not match actual payload length"); 119 reader->hr_state = HR_ERROR; 120 return -1; 121 } 122 switch (reader->hr_frame_type) 123 { 124 case HQFT_GOAWAY: 125 reader->hr_cb->on_goaway(reader->hr_ctx, 126 reader->hr_u.vint_state.val); 127 break; 128 case HQFT_CANCEL_PUSH: 129 reader->hr_cb->on_cancel_push(reader->hr_ctx, 130 reader->hr_u.vint_state.val); 131 break; 132 case HQFT_MAX_PUSH_ID: 133 reader->hr_cb->on_max_push_id(reader->hr_ctx, 134 reader->hr_u.vint_state.val); 135 break; 136 default: 137 assert(0); 138 } 139 reader->hr_state = HR_READ_FRAME_BEGIN; 140 break; 141 } 142 else 143 { 144 assert(p == end); 145 return 0; 146 } 147 case HR_SKIPPING: 148 len = MIN((uintptr_t) (end - p), reader->hr_frame_length); 149 p += len; 150 reader->hr_frame_length -= len; 151 if (0 == reader->hr_frame_length) 152 reader->hr_state = HR_READ_FRAME_BEGIN; 153 break; 154 case HR_READ_SETTING_BEGIN: 155 reader->hr_u.vint2_state.vr2s_state = 0; 156 reader->hr_state = HR_READ_SETTING_CONTINUE; 157 /* fall-through */ 158 case HR_READ_SETTING_CONTINUE: 159 orig_p = p; 160 s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 161 reader->hr_nread += p - orig_p; 162 if (reader->hr_nread > reader->hr_frame_length) 163 { 164 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 165 HEC_FRAME_ERROR, "SETTING frame contents too long"); 166 reader->hr_state = HR_ERROR; 167 return -1; 168 } 169 if (s < 0) 170 break; 171 reader->hr_cb->on_setting(reader->hr_ctx, 172 reader->hr_u.vint2_state.vr2s_one, 173 reader->hr_u.vint2_state.vr2s_two); 174 if (reader->hr_nread >= reader->hr_frame_length) 175 { 176 reader->hr_state = HR_READ_FRAME_BEGIN; 177 reader->hr_cb->on_settings_frame(reader->hr_ctx); 178 } 179 else 180 reader->hr_state = HR_READ_SETTING_BEGIN; 181 break; 182 default: 183 assert(0); 184 /* fall-through */ 185 case HR_ERROR: 186 return -1; 187 } 188 } 189 190 return 0; 191} 192