lsquic_hcsi_reader.c revision fbc6cc04
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 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 if (!(reader->hr_frame_type >= 0xB && 99 (reader->hr_frame_type - 0xB) % 0x1F == 0)) 100 LSQ_INFO("unknown frame type 0x%"PRIX64" -- skipping", 101 reader->hr_frame_type); 102 reader->hr_state = HR_SKIPPING; 103 LSQ_DEBUG("unknown frame 0x%"PRIX64": will skip %"PRIu64" bytes", 104 reader->hr_frame_type, reader->hr_frame_length); 105 break; 106 } 107 break; 108 case HR_READ_VARINT: 109 reader->hr_u.vint_state.pos = 0; 110 reader->hr_state = HR_READ_VARINT_CONTINUE; 111 reader->hr_nread = 0; 112 /* fall-through */ 113 case HR_READ_VARINT_CONTINUE: 114 orig_p = p; 115 s = lsquic_varint_read_nb(&p, end, &reader->hr_u.vint_state); 116 reader->hr_nread += p - orig_p; 117 if (0 == s) 118 { 119 switch (reader->hr_frame_type) 120 { 121 case HQFT_GOAWAY: 122 case HQFT_CANCEL_PUSH: 123 case HQFT_MAX_PUSH_ID: 124 if (reader->hr_nread != reader->hr_frame_length) 125 { 126 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 127 HEC_FRAME_ERROR, 128 "Frame length does not match actual payload length"); 129 reader->hr_state = HR_ERROR; 130 return -1; 131 } 132 break; 133 } 134 switch (reader->hr_frame_type) 135 { 136 case HQFT_GOAWAY: 137 reader->hr_cb->on_goaway(reader->hr_ctx, 138 reader->hr_u.vint_state.val); 139 break; 140 case HQFT_CANCEL_PUSH: 141 reader->hr_cb->on_cancel_push(reader->hr_ctx, 142 reader->hr_u.vint_state.val); 143 break; 144 case HQFT_MAX_PUSH_ID: 145 reader->hr_cb->on_max_push_id(reader->hr_ctx, 146 reader->hr_u.vint_state.val); 147 break; 148 case HQFT_PRIORITY_UPDATE_PUSH: 149 case HQFT_PRIORITY_UPDATE_STREAM: 150 len = reader->hr_frame_length - reader->hr_nread; 151 if (len <= (uintptr_t) (end - p)) 152 { 153 reader->hr_cb->on_priority_update(reader->hr_ctx, 154 reader->hr_frame_type, reader->hr_u.vint_state.val, 155 (char *) p, len); 156 p += len; 157 } 158 else if (len <= sizeof(reader->hr_u.prio_state.buf)) 159 { 160 reader->hr_frame_length = len; 161 reader->hr_nread = 0; 162 reader->hr_state = HR_READ_PRIORITY_UPDATE; 163 goto continue_reading; 164 } 165 else 166 { 167 p += len; 168 /* 16 bytes is more than enough for a PRIORITY_UPDATE 169 * frame, anything larger than that is unreasonable. 170 */ 171 if (reader->hr_frame_length 172 > sizeof(reader->hr_u.prio_state.buf)) 173 LSQ_INFO("skip PRIORITY_UPDATE frame that's too " 174 "long (%"PRIu64" bytes)", len); 175 } 176 break; 177 default: 178 assert(0); 179 } 180 reader->hr_state = HR_READ_FRAME_BEGIN; 181 break; 182 } 183 else 184 { 185 assert(p == end); 186 return 0; 187 } 188 case HR_SKIPPING: 189 len = MIN((uintptr_t) (end - p), reader->hr_frame_length); 190 p += len; 191 reader->hr_frame_length -= len; 192 if (0 == reader->hr_frame_length) 193 reader->hr_state = HR_READ_FRAME_BEGIN; 194 break; 195 case HR_READ_SETTING_BEGIN: 196 reader->hr_u.vint2_state.vr2s_state = 0; 197 reader->hr_state = HR_READ_SETTING_CONTINUE; 198 /* fall-through */ 199 case HR_READ_SETTING_CONTINUE: 200 orig_p = p; 201 s = lsquic_varint_read_two(&p, end, &reader->hr_u.vint2_state); 202 reader->hr_nread += p - orig_p; 203 if (reader->hr_nread > reader->hr_frame_length) 204 { 205 reader->hr_conn->cn_if->ci_abort_error(reader->hr_conn, 1, 206 HEC_FRAME_ERROR, "SETTING frame contents too long"); 207 reader->hr_state = HR_ERROR; 208 return -1; 209 } 210 if (s < 0) 211 break; 212 reader->hr_cb->on_setting(reader->hr_ctx, 213 reader->hr_u.vint2_state.vr2s_one, 214 reader->hr_u.vint2_state.vr2s_two); 215 if (reader->hr_nread >= reader->hr_frame_length) 216 { 217 reader->hr_state = HR_READ_FRAME_BEGIN; 218 reader->hr_cb->on_settings_frame(reader->hr_ctx); 219 } 220 else 221 reader->hr_state = HR_READ_SETTING_BEGIN; 222 break; 223 case HR_READ_PRIORITY_UPDATE: 224 len = MIN((uintptr_t) (end - p), 225 reader->hr_frame_length - reader->hr_nread); 226 memcpy(reader->hr_u.prio_state.buf + reader->hr_nread, p, len); 227 reader->hr_nread += len; 228 p += len; 229 if (reader->hr_frame_length == reader->hr_nread) 230 { 231 reader->hr_cb->on_priority_update(reader->hr_ctx, 232 reader->hr_frame_type, reader->hr_u.vint_state.val, 233 reader->hr_u.prio_state.buf, reader->hr_frame_length); 234 reader->hr_state = HR_READ_FRAME_BEGIN; 235 } 236 break; 237 default: 238 assert(0); 239 /* fall-through */ 240 case HR_ERROR: 241 return -1; 242 } 243 } 244 245 return 0; 246} 247