1/* Copyright (c) 2017 - 2022 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 continue_reading: 50 while (p < end) 51 { 52 switch (reader->hr_state) 53 { 54 case HR_READ_FRAME_BEGIN: 55 reader->hr_u.vint2_state.vr2s_state = 0; 56 reader->hr_state = HR_READ_FRAME_CONTINUE; 57 /* fall-through */ 58 case HR_READ_FRAME_CONTINUE: 59 s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 60 if (s < 0) 61 break; 62 reader->hr_frame_type = reader->hr_u.vint2_state.vr2s_one; 63 reader->hr_frame_length = reader->hr_u.vint2_state.vr2s_two; 64 65 if (!(reader->hr_flag & HR_FLAG_RCVD_SETTING) 66 && reader->hr_frame_type != HQFT_SETTINGS) 67 { 68 reader->hr_cb->on_frame_error(reader->hr_ctx, 69 HEC_MISSING_SETTINGS, reader->hr_frame_type); 70 return -1; 71 } 72 73 switch (reader->hr_frame_type) 74 { 75 case HQFT_SETTINGS: 76 reader->hr_flag |= HR_FLAG_RCVD_SETTING; 77 if (reader->hr_frame_length) 78 { 79 reader->hr_state = HR_READ_SETTING_BEGIN; 80 reader->hr_nread = 0; 81 } 82 else 83 { 84 reader->hr_cb->on_settings_frame(reader->hr_ctx); 85 reader->hr_state = HR_READ_FRAME_BEGIN; 86 } 87 break; 88 case HQFT_GOAWAY: 89 reader->hr_state = HR_READ_VARINT; 90 break; 91 case HQFT_CANCEL_PUSH: 92 reader->hr_state = HR_READ_VARINT; 93 break; 94 case HQFT_MAX_PUSH_ID: 95 reader->hr_state = HR_READ_VARINT; 96 break; 97 case HQFT_PRIORITY_UPDATE_PUSH: 98 case HQFT_PRIORITY_UPDATE_STREAM: 99 reader->hr_state = HR_READ_VARINT; 100 break; 101 case HQFT_DATA: 102 case HQFT_HEADERS: 103 case HQFT_PUSH_PROMISE: 104 reader->hr_cb->on_frame_error(reader->hr_ctx, 105 HEC_FRAME_UNEXPECTED, reader->hr_frame_type); 106 return -1; 107 default: 108 { 109 /* From [draft-ietf-quic-http-31] Section 7.2.8: 110 " Frame types of the format "0x1f * N + 0x21" for non-negative 111 " integer values of N are reserved to exercise the requirement 112 " that unknown types be ignored 113 */ 114 enum lsq_log_level L; 115 if (!(reader->hr_frame_type >= 0x21 && 116 (reader->hr_frame_type - 0x21) % 0x1F == 0)) 117 /* Non-grease: log with higher level: */ 118 L = LSQ_LOG_INFO; 119 else 120 L = LSQ_LOG_DEBUG; 121 LSQ_LOG(L, "unknown frame type 0x%"PRIX64": will skip " 122 "%"PRIu64" bytes", reader->hr_frame_type, 123 reader->hr_frame_length); 124 reader->hr_state = HR_SKIPPING; 125 break; 126 } 127 } 128 break; 129 case HR_READ_VARINT: 130 reader->hr_u.vint_state.pos = 0; 131 reader->hr_state = HR_READ_VARINT_CONTINUE; 132 reader->hr_nread = 0; 133 /* fall-through */ 134 case HR_READ_VARINT_CONTINUE: 135 orig_p = p; 136 s = lsquic_varint_read_nb(&p, end, &reader->hr_u.vint_state); 137 reader->hr_nread += p - orig_p; 138 if (0 == s) 139 { 140 switch (reader->hr_frame_type) 141 { 142 case HQFT_GOAWAY: 143 case HQFT_CANCEL_PUSH: 144 case HQFT_MAX_PUSH_ID: 145 if (reader->hr_nread != reader->hr_frame_length) 146 { 147 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 148 HEC_FRAME_ERROR, 149 "Frame length does not match actual payload length"); 150 reader->hr_state = HR_ERROR; 151 return -1; 152 } 153 break; 154 } 155 switch (reader->hr_frame_type) 156 { 157 case HQFT_GOAWAY: 158 reader->hr_cb->on_goaway(reader->hr_ctx, 159 reader->hr_u.vint_state.val); 160 break; 161 case HQFT_CANCEL_PUSH: 162 reader->hr_cb->on_cancel_push(reader->hr_ctx, 163 reader->hr_u.vint_state.val); 164 break; 165 case HQFT_MAX_PUSH_ID: 166 reader->hr_cb->on_max_push_id(reader->hr_ctx, 167 reader->hr_u.vint_state.val); 168 break; 169 case HQFT_PRIORITY_UPDATE_PUSH: 170 case HQFT_PRIORITY_UPDATE_STREAM: 171 len = reader->hr_frame_length - reader->hr_nread; 172 if (len <= (uintptr_t) (end - p)) 173 { 174 reader->hr_cb->on_priority_update(reader->hr_ctx, 175 reader->hr_frame_type, reader->hr_u.vint_state.val, 176 (char *) p, len); 177 p += len; 178 } 179 else if (len <= sizeof(reader->hr_u.prio_state.buf)) 180 { 181 reader->hr_frame_length = len; 182 reader->hr_nread = 0; 183 reader->hr_state = HR_READ_PRIORITY_UPDATE; 184 goto continue_reading; 185 } 186 else 187 { 188 p += len; 189 /* 16 bytes is more than enough for a PRIORITY_UPDATE 190 * frame, anything larger than that is unreasonable. 191 */ 192 if (reader->hr_frame_length 193 > sizeof(reader->hr_u.prio_state.buf)) 194 LSQ_INFO("skip PRIORITY_UPDATE frame that's too " 195 "long (%"PRIu64" bytes)", len); 196 } 197 break; 198 default: 199 assert(0); 200 } 201 reader->hr_state = HR_READ_FRAME_BEGIN; 202 break; 203 } 204 else 205 { 206 assert(p == end); 207 return 0; 208 } 209 case HR_SKIPPING: 210 len = MIN((uintptr_t) (end - p), reader->hr_frame_length); 211 p += len; 212 reader->hr_frame_length -= len; 213 if (0 == reader->hr_frame_length) 214 reader->hr_state = HR_READ_FRAME_BEGIN; 215 break; 216 case HR_READ_SETTING_BEGIN: 217 reader->hr_u.vint2_state.vr2s_state = 0; 218 reader->hr_state = HR_READ_SETTING_CONTINUE; 219 /* fall-through */ 220 case HR_READ_SETTING_CONTINUE: 221 orig_p = p; 222 s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 223 reader->hr_nread += p - orig_p; 224 if (reader->hr_nread > reader->hr_frame_length) 225 { 226 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 227 HEC_FRAME_ERROR, "SETTING frame contents too long"); 228 reader->hr_state = HR_ERROR; 229 return -1; 230 } 231 if (s < 0) 232 break; 233 reader->hr_cb->on_setting(reader->hr_ctx, 234 reader->hr_u.vint2_state.vr2s_one, 235 reader->hr_u.vint2_state.vr2s_two); 236 if (reader->hr_nread >= reader->hr_frame_length) 237 { 238 reader->hr_state = HR_READ_FRAME_BEGIN; 239 reader->hr_cb->on_settings_frame(reader->hr_ctx); 240 } 241 else 242 reader->hr_state = HR_READ_SETTING_BEGIN; 243 break; 244 case HR_READ_PRIORITY_UPDATE: 245 len = MIN((uintptr_t) (end - p), 246 reader->hr_frame_length - reader->hr_nread); 247 memcpy(reader->hr_u.prio_state.buf + reader->hr_nread, p, len); 248 reader->hr_nread += len; 249 p += len; 250 if (reader->hr_frame_length == reader->hr_nread) 251 { 252 reader->hr_cb->on_priority_update(reader->hr_ctx, 253 reader->hr_frame_type, reader->hr_u.vint_state.val, 254 reader->hr_u.prio_state.buf, reader->hr_frame_length); 255 reader->hr_state = HR_READ_FRAME_BEGIN; 256 } 257 break; 258 default: 259 assert(0); 260 /* fall-through */ 261 case HR_ERROR: 262 return -1; 263 } 264 } 265 266 return 0; 267} 268