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