1 /* 2 * h2 - HTTP/2 protocol layer 3 * 4 * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved 5 * License: BSD 3-clause (same as lighttpd) 6 */ 7 #include "first.h" 8 #include "h2.h" 9 10 #include <arpa/inet.h> /* htonl() */ 11 #include <stdint.h> /* INT32_MAX INT32_MIN */ 12 #include <stdlib.h> 13 #include <string.h> 14 15 #include "base.h" 16 #include "buffer.h" 17 #include "chunk.h" 18 #include "fdevent.h" /* FDEVENT_STREAM_REQUEST_BUFMIN */ 19 #include "http_header.h" 20 #include "log.h" 21 #include "request.h" 22 23 24 static request_st * h2_init_stream (request_st * const h2r, connection * const con); 25 26 27 static void 28 h2_send_settings_ack (connection * const con) 29 { 30 static const uint8_t settings_ack[] = { 31 /* SETTINGS w/ ACK */ 32 0x00, 0x00, 0x00 /* frame length */ 33 ,H2_FTYPE_SETTINGS /* frame type */ 34 ,H2_FLAG_ACK /* frame flags */ 35 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */ 36 }; 37 38 chunkqueue_append_mem(con->write_queue, 39 (const char *)settings_ack, sizeof(settings_ack)); 40 } 41 42 43 __attribute_cold__ 44 static void 45 h2_send_rst_stream_id (uint32_t h2id, connection * const con, const request_h2error_t e) 46 { 47 union { 48 uint8_t c[16]; 49 uint32_t u[4]; /*(alignment)*/ 50 } rst_stream = { { /*(big-endian numbers)*/ 51 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 52 /* RST_STREAM */ 53 ,0x00, 0x00, 0x04 /* frame length */ 54 ,H2_FTYPE_RST_STREAM /* frame type */ 55 ,0x00 /* frame flags */ 56 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 57 ,0x00, 0x00, 0x00, 0x00 /* error code; (fill in below) */ 58 } }; 59 60 rst_stream.u[2] = htonl(h2id); 61 rst_stream.u[3] = htonl(e); 62 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/ 63 (const char *)rst_stream.c+3, sizeof(rst_stream)-3); 64 } 65 66 67 __attribute_cold__ 68 static void 69 h2_send_rst_stream (request_st * const r, connection * const con, const request_h2error_t e) 70 { 71 r->h2state = H2_STATE_CLOSED; 72 h2_send_rst_stream_id(r->h2id, con, e); 73 } 74 75 76 __attribute_cold__ 77 static void 78 h2_send_goaway_rst_stream (connection * const con) 79 { 80 h2con * const h2c = con->h2; 81 const int sent_goaway = h2c->sent_goaway; 82 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 83 request_st * const r = h2c->r[i]; 84 if (r->h2state == H2_STATE_CLOSED) continue; 85 /*(XXX: might consider always sending RST_STREAM)*/ 86 if (!sent_goaway) 87 r->h2state = H2_STATE_CLOSED; 88 else /*(also sets r->h2state = H2_STATE_CLOSED)*/ 89 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 90 } 91 } 92 93 94 void 95 h2_send_goaway (connection * const con, const request_h2error_t e) 96 { 97 /* future: RFC 7540 Section 6.8 notes that server initiating graceful 98 * connection shutdown SHOULD send GOAWAY with stream id 2^31-1 and a 99 * NO_ERROR code, and later send another GOAWAY with an updated last 100 * stream identifier. (This is not done here, but doing so would be 101 * friendlier to clients that send streaming requests which the client 102 * is unable to retry.) */ 103 104 if (e != H2_E_NO_ERROR) 105 h2_send_goaway_rst_stream(con); 106 /*XXX: else should send RST_STREAM w/ CANCEL for any active PUSH_PROMISE */ 107 108 h2con * const h2c = con->h2; 109 if (h2c->sent_goaway && (h2c->sent_goaway > 0 || e == H2_E_NO_ERROR)) 110 return; 111 h2c->sent_goaway = (e == H2_E_NO_ERROR) ? -1 : (int32_t)e; 112 113 union { 114 uint8_t c[20]; 115 uint32_t u[5]; /*(alignment)*/ 116 } goaway = { { /*(big-endian numbers)*/ 117 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 118 /* GOAWAY */ 119 ,0x00, 0x00, 0x08 /* frame length */ 120 ,H2_FTYPE_GOAWAY /* frame type */ 121 ,0x00 /* frame flags */ 122 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */ 123 ,0x00, 0x00, 0x00, 0x00 /* last-stream-id (fill in below) */ 124 ,0x00, 0x00, 0x00, 0x00 /* error code (fill in below) */ 125 /* additional debug data (*); (optional) 126 * adjust frame length if any additional 127 * debug data is sent */ 128 } }; 129 130 goaway.u[3] = htonl(h2c->h2_cid); /* last-stream-id */ 131 goaway.u[4] = htonl(e); 132 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/ 133 (const char *)goaway.c+3, sizeof(goaway)-3); 134 } 135 136 137 __attribute_cold__ 138 static void 139 h2_send_goaway_e (connection * const con, const request_h2error_t e) 140 { 141 h2_send_goaway(con, e); 142 } 143 144 145 static int 146 h2_recv_goaway (connection * const con, const uint8_t * const s, uint32_t len) 147 { 148 /*(s must be entire GOAWAY frame and len the frame length field)*/ 149 /*assert(s[3] == H2_FTYPE_GOAWAY);*/ 150 UNUSED(len); 151 if ((s[5] & ~0x80) | s[6] | s[7] | s[8]) { /*(GOAWAY stream id must be 0)*/ 152 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 153 return 0; 154 } 155 const uint32_t e = (s[13]<< 24) | (s[14]<< 16) | (s[15]<< 8) | s[16]; 156 #if 0 157 /* XXX: debug: could log error code sent by peer */ 158 #endif 159 #if 0 160 /* XXX: debug: could log additional debug info (if any) sent by peer */ 161 if (len > 8) { 162 } 163 #endif 164 #if 0 165 /* XXX: could validate/use Last-Stream-ID sent by peer */ 166 const uint32_t last_id = (s[9] << 24) | (s[10]<< 16) | (s[11]<< 8) | s[12]; 167 #endif 168 169 /* send PROTOCOL_ERROR back to peer if peer sent an error code 170 * (i.e. not NO_ERROR) in order to terminate connection more quickly */ 171 h2_send_goaway(con, e==H2_E_NO_ERROR ? H2_E_NO_ERROR : H2_E_PROTOCOL_ERROR); 172 h2con * const h2c = con->h2; 173 if (0 == h2c->rused) return 0; 174 return 1; 175 } 176 177 178 static void 179 h2_recv_rst_stream (connection * const con, const uint8_t * const s, const uint32_t len) 180 { 181 /*(s must be entire RST_STREAM frame and len the frame length field)*/ 182 /*assert(s[3] == H2_FTYPE_RST_STREAM);*/ 183 if (4 != len) { /*(RST_STREAM frame length must be 4)*/ 184 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 185 return; 186 } 187 const uint32_t id = 188 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 189 if (0 == id) { /*(RST_STREAM id must not be 0)*/ 190 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 191 return; 192 } 193 h2con * const h2c = con->h2; 194 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 195 request_st * const r = h2c->r[i]; 196 if (r->h2id != id) continue; 197 if (r->h2state == H2_STATE_IDLE) { 198 /*(RST_STREAM must not be for stream in "idle" state)*/ 199 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 200 return; 201 } 202 /* XXX: ? add debug trace including error code from RST_STREAM ? */ 203 r->h2state = H2_STATE_CLOSED; 204 return; 205 } 206 /* unknown/inactive stream id 207 * XXX: how should we handle RST_STREAM for unknown/inactive stream id? 208 * (stream id may have been closed recently and server forgot about it, 209 * but client (peer) sent RST_STREAM prior to receiving stream end from 210 * server)*/ 211 #if 0 212 if (h2c->sent_goaway && h2c->h2_cid < id) return; 213 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 214 #else 215 if (h2c->h2_cid < id) { 216 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 217 return; 218 } 219 #endif 220 } 221 222 223 static void 224 h2_recv_ping (connection * const con, uint8_t * const s, const uint32_t len) 225 { 226 #if 0 227 union { 228 uint8_t c[20]; 229 uint32_t u[5]; /*(alignment)*/ 230 } ping = { { /*(big-endian numbers)*/ 231 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 232 /* PING */ 233 ,0x00, 0x00, 0x08 /* frame length */ 234 ,H2_FTYPE_PING /* frame type */ 235 ,H2_FLAG_ACK /* frame flags */ 236 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */ 237 ,0x00, 0x00, 0x00, 0x00 /* opaque (fill in below) */ 238 ,0x00, 0x00, 0x00, 0x00 239 } }; 240 #endif 241 242 /*(s must be entire PING frame and len the frame length field)*/ 243 /*assert(s[3] == H2_FTYPE_PING);*/ 244 if (8 != len) { /*(PING frame length must be 8)*/ 245 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 246 return; 247 } 248 s[5] &= ~0x80; /* reserved bit must be ignored */ 249 if (s[5] | s[6] | s[7] | s[8]) { /*(PING stream id must be 0)*/ 250 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 251 return; 252 } 253 if (s[4] & H2_FLAG_ACK) /*(ignore; unexpected if we did not send PING)*/ 254 return; 255 /* reflect PING back to peer with frame flag ACK */ 256 /* (9 byte frame header plus 8 byte PING payload = 17 bytes)*/ 257 s[4] = H2_FLAG_ACK; 258 chunkqueue_append_mem(con->write_queue, (const char *)s, 17); 259 } 260 261 262 static void 263 h2_recv_priority (connection * const con, const uint8_t * const s, const uint32_t len) 264 { 265 /*(s must be entire PRIORITY frame and len the frame length field)*/ 266 /*assert(s[3] == H2_FTYPE_PRIORITY);*/ 267 if (5 != len) { /*(PRIORITY frame length must be 5)*/ 268 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 269 return; 270 } 271 const uint32_t id = 272 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 273 if (0 == id) { /*(PRIORITY id must not be 0)*/ 274 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 275 return; 276 } 277 const uint32_t prio = 278 ((s[9] << 24) | (s[10] << 16) | (s[11] << 8) | s[12]) & ~0x80000000u; 279 #if 0 280 uint32_t exclusive_dependency = (s[9] & 0x80) ? 1 : 0; 281 uint32_t weight = s[13]; 282 #endif 283 h2con * const h2c = con->h2; 284 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 285 request_st * const r = h2c->r[i]; 286 if (r->h2id != id) continue; 287 /* XXX: TODO: update priority info */ 288 if (prio == id) { 289 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 290 return; 291 } 292 return; 293 } 294 /* XXX: TODO: update priority info for unknown/inactive stream */ 295 /*if (h2c->sent_goaway && h2c->h2_cid < id) return;*/ 296 if (prio == id) { 297 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR); 298 return; 299 } 300 } 301 302 303 static void 304 h2_recv_window_update (connection * const con, const uint8_t * const s, const uint32_t len) 305 { 306 /*(s must be entire WINDOW_UPDATE frame and len the frame length field)*/ 307 /*assert(s[3] == H2_FTYPE_WINDOW_UPDATE);*/ 308 if (4 != len) { /*(WINDOW_UPDATE frame length must be 4)*/ 309 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 310 return; 311 } 312 const uint32_t id = 313 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 314 const int32_t v = 315 (int32_t)(((s[9] << 24)|(s[10] << 16)|(s[11] << 8)|s[12]) & ~0x80000000); 316 request_st *r = NULL; 317 if (0 == id) 318 r = &con->request; 319 else { 320 h2con * const h2c = con->h2; 321 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 322 request_st * const rr = h2c->r[i]; 323 if (rr->h2id != id) continue; 324 r = rr; 325 break; 326 } 327 /* peer should not send WINDOW_UPDATE for an inactive stream, 328 * but RFC 7540 does not explicitly call this out. On the other hand, 329 * since there may be a temporary mismatch in stream state between 330 * peers, ignore window update if stream id is unknown/inactive. 331 * Also, it is not an error if GOAWAY sent and h2c->h2_cid < id */ 332 if (NULL == r) { 333 if (h2c->h2_cid < id && 0 == h2c->sent_goaway) 334 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 335 #if 0 336 /*(needed for h2spec if testing with response < 16k+1 over TLS 337 * or response <= socket send buffer size over cleartext, due to 338 * completing response too quickly for the test frame sequence) */ 339 if (v == 0) /* h2spec: 6.9-2 (after we retired id 1) */ 340 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR); 341 if (v == INT32_MAX)/* h2spec: 6.9.1-3 (after we retired id 1) */ 342 h2_send_rst_stream_id(id, con, H2_E_FLOW_CONTROL_ERROR); 343 #endif 344 return; 345 } 346 /* MUST NOT be treated as error if stream is in closed state; ignore */ 347 if (r->h2state == H2_STATE_CLOSED 348 || r->h2state == H2_STATE_HALF_CLOSED_LOCAL) return; 349 } 350 if (0 == v || r->h2_swin > INT32_MAX - v) { 351 request_h2error_t e = (0 == v) 352 ? H2_E_PROTOCOL_ERROR 353 : H2_E_FLOW_CONTROL_ERROR; 354 if (0 == id) 355 h2_send_goaway_e(con, e); 356 else 357 h2_send_rst_stream(r, con, e); 358 return; 359 } 360 r->h2_swin += v; 361 } 362 363 364 static void 365 h2_send_window_update (connection * const con, uint32_t h2id, const uint32_t len) 366 { 367 if (0 == len) return; 368 union { 369 uint8_t c[16]; 370 uint32_t u[4]; /*(alignment)*/ 371 } window_upd = { { /*(big-endian numbers)*/ 372 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 373 /* WINDOW_UPDATE */ 374 ,0x00, 0x00, 0x04 /* frame length */ 375 ,H2_FTYPE_WINDOW_UPDATE /* frame type */ 376 ,0x00 /* frame flags */ 377 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 378 ,0x00, 0x00, 0x00, 0x00 /* window update increase (fill in below) */ 379 } }; 380 381 window_upd.u[2] = htonl(h2id); 382 window_upd.u[3] = htonl(len); 383 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align padding)*/ 384 (const char *)window_upd.c+3, sizeof(window_upd)-3); 385 } 386 387 388 static void 389 h2_parse_frame_settings (connection * const con, const uint8_t *s, uint32_t len) 390 { 391 /*(s and len must be SETTINGS frame payload)*/ 392 /*(caller must validate frame len, frame type == 0x04, frame id == 0)*/ 393 h2con * const h2c = con->h2; 394 for (; len >= 6; len -= 6, s += 6) { 395 uint32_t v = (s[2] << 24) | (s[3] << 16) | (s[4] << 8) | s[5]; 396 switch (((s[0] << 8) | s[1])) { 397 case H2_SETTINGS_HEADER_TABLE_SIZE: 398 /* encoder may use any table size <= value sent by peer */ 399 /* For simple compliance with RFC and constrained memory use, 400 * choose to not increase table size beyond the default 4096, 401 * but allow smaller sizes to be set and then reset up to 4096, 402 * e.g. set to 0 to evict all dynamic table entries, 403 * and then set to 4096 to restore dynamic table use */ 404 if (v > 4096) v = 4096; 405 if (v == h2c->s_header_table_size) break; 406 h2c->s_header_table_size = v; 407 /* FIXME: TODO: configure HPACK encoder */ 408 break; 409 case H2_SETTINGS_ENABLE_PUSH: 410 if ((v|1) != 1) { /*(v == 0 || v == 1)*/ 411 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 412 return; 413 } 414 h2c->s_enable_push = v; 415 break; 416 case H2_SETTINGS_MAX_CONCURRENT_STREAMS: 417 h2c->s_max_concurrent_streams = v; 418 break; 419 case H2_SETTINGS_INITIAL_WINDOW_SIZE: 420 if (v > INT32_MAX) { /*(2^31 - 1)*/ 421 h2_send_goaway_e(con, H2_E_FLOW_CONTROL_ERROR); 422 return; 423 } 424 else if (h2c->rused) { /*(update existing streams)*/ 425 /*(underflow is ok; unsigned integer math)*/ 426 /*(h2c->s_initial_window_size is >= 0)*/ 427 int32_t diff = 428 (int32_t)((uint32_t)v - (uint32_t)h2c->s_initial_window_size); 429 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 430 request_st * const r = h2c->r[i]; 431 const int32_t swin = r->h2_swin; 432 if (r->h2state == H2_STATE_HALF_CLOSED_LOCAL 433 || r->h2state == H2_STATE_CLOSED) continue; 434 if (diff >= 0 435 ? swin > INT32_MAX - diff 436 : swin < INT32_MIN - diff) { 437 h2_send_rst_stream(r, con, H2_E_FLOW_CONTROL_ERROR); 438 continue; 439 } 440 r->h2_swin += diff; 441 } 442 } 443 h2c->s_initial_window_size = (int32_t)v; 444 break; 445 case H2_SETTINGS_MAX_FRAME_SIZE: 446 if (v < 16384 || v > 16777215) { /*[(2^14),(2^24-1)]*/ 447 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 448 return; 449 } 450 h2c->s_max_frame_size = v; 451 break; 452 case H2_SETTINGS_MAX_HEADER_LIST_SIZE: 453 h2c->s_max_header_list_size = v; 454 break; 455 default: 456 break; 457 } 458 } 459 460 if (len) { 461 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 462 return; 463 } 464 465 /* caller must send SETTINGS frame with ACK flag, 466 * if appropriate, and if h2c->sent_goaway is not set 467 * (Do not send ACK for Upgrade: h2c and HTTP2-Settings header) */ 468 } 469 470 471 static void 472 h2_recv_settings (connection * const con, const uint8_t * const s, const uint32_t len) 473 { 474 /*(s must be entire SETTINGS frame, len must be the frame length field)*/ 475 /*assert(s[3] == H2_FTYPE_SETTINGS);*/ 476 if ((s[5] & ~0x80) | s[6] | s[7] | s[8]) {/*(SETTINGS stream id must be 0)*/ 477 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 478 return; 479 } 480 481 h2con * const h2c = con->h2; 482 if (!(s[4] & H2_FLAG_ACK)) { 483 h2_parse_frame_settings(con, s+9, len); 484 if (h2c->sent_goaway <= 0) 485 h2_send_settings_ack(con); 486 } 487 else { 488 /* lighttpd currently sends SETTINGS in server preface, and not again, 489 * so this does not have to handle another SETTINGS frame being sent 490 * before receiving an ACK from prior SETTINGS frame. (If it does, 491 * then we will need some sort of counter.) */ 492 if (0 != len) 493 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 494 else if (h2c->sent_settings) 495 h2c->sent_settings = 0; 496 else /* SETTINGS with ACK for SETTINGS frame we did not send */ 497 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 498 } 499 } 500 501 502 static int 503 h2_recv_end_data (request_st * const r, connection * const con, const uint32_t alen) 504 { 505 chunkqueue * const reqbody_queue = r->reqbody_queue; 506 r->h2state = (r->h2state == H2_STATE_OPEN) 507 ? H2_STATE_HALF_CLOSED_REMOTE 508 : H2_STATE_CLOSED; 509 if (r->reqbody_length == -1) 510 r->reqbody_length = reqbody_queue->bytes_in + (off_t)alen; 511 else if (r->reqbody_length != reqbody_queue->bytes_in + (off_t)alen) { 512 if (0 == reqbody_queue->bytes_out) { 513 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 514 return 0; 515 } /* else let reqbody streaming consumer handle truncated reqbody */ 516 } 517 518 return 1; 519 } 520 521 522 static int 523 h2_recv_data (connection * const con, const uint8_t * const s, const uint32_t len) 524 { 525 /*(s must be entire DATA frame, len must be the frame length field)*/ 526 /*assert(s[3] == H2_FTYPE_DATA);*/ 527 528 /* future: consider string refs rather than copying DATA from chunkqueue 529 * or try to consume entire chunk, or to split chunks with less copying */ 530 531 h2con * const h2c = con->h2; 532 const uint32_t id = 533 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 534 if (0 == id || h2c->h2_cid < id) { /*(RST_STREAM id must not be 0)*/ 535 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 536 return 0; 537 } 538 539 uint32_t alen = len; /* actual data len, minus padding */ 540 uint32_t pad = 0; 541 if (s[4] & H2_FLAG_PADDED) { 542 pad = s[9]; 543 if (pad >= len) { 544 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 545 return 0; 546 } 547 alen -= (1 + pad); 548 } 549 550 request_st * const h2r = &con->request; 551 if (h2r->h2_rwin <= 0 && 0 != alen) { /*(always proceed if 0 == alen)*/ 552 /*(connection_state_machine_h2() must ensure con is rescheduled, 553 * when backends consume data if con->read_queue is not empty, 554 * whether or not con->fd has data to read from the network)*/ 555 /*(leave frame in cq to be re-read later)*/ 556 return 0; 557 } 558 /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/ 559 /*(not worried about underflow while 560 * SETTINGS_MAX_FRAME_SIZE is small (e.g. 16k or 32k) and 561 * SETTINGS_MAX_CONCURRENT_STREAMS is small (h2c->r[8]))*/ 562 /*h2r->h2_rwin -= (int32_t)len;*//* update connection recv window (below) */ 563 564 request_st *r = NULL; 565 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 566 request_st * const rr = h2c->r[i]; 567 if (rr->h2id != id) continue; 568 r = rr; 569 break; 570 } 571 chunkqueue * const cq = con->read_queue; 572 if (NULL == r) { 573 /* XXX: TODO: might need to keep a list of recently retired streams 574 * for a few seconds so that if we send RST_STREAM, then we ignore 575 * further DATA and do not send connection error, though recv windows 576 * still must be updated. */ 577 if (h2c->h2_cid < id || (!h2c->sent_goaway && 0 != alen)) 578 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 579 chunkqueue_mark_written(cq, 9+len); 580 return 0; 581 } 582 583 if (r->h2state == H2_STATE_CLOSED 584 || r->h2state == H2_STATE_HALF_CLOSED_REMOTE) { 585 h2_send_rst_stream_id(id, con, H2_E_STREAM_CLOSED); 586 chunkqueue_mark_written(cq, 9+len); 587 h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/ 588 return 1; 589 } 590 591 if (r->h2_rwin <= 0 && 0 != alen) {/*(always proceed if 0==alen)*/ 592 if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN) { 593 /*(connection_state_machine_h2() must ensure con is rescheduled, 594 * when backends consume data if con->read_queue is not empty, 595 * whether or not con->fd has data to read from the network)*/ 596 /*(leave frame in cq to be re-read later)*/ 597 return 0; 598 } 599 } 600 /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/ 601 /*(undeflow will not occur (with reasonable SETTINGS_MAX_FRAME_SIZE used) 602 * since windows updated elsewhere and data is streamed to temp files if 603 * not FDEVENT_STREAM_REQUEST_BUFMIN)*/ 604 /*r->h2_rwin -= (int32_t)len;*/ 605 h2_send_window_update(con, r->h2id, len); /*(r->h2_rwin)*/ 606 h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/ 607 608 chunkqueue * const dst = r->reqbody_queue; 609 610 if (r->reqbody_length >= 0 && r->reqbody_length < dst->bytes_in + alen) { 611 /* data exceeds Content-Length specified (client mistake) */ 612 #if 0 /* truncate */ 613 alen = r->reqbody_length - dst->bytes_in; 614 /*(END_STREAM may follow in 0-length DATA frame or HEADERS (trailers))*/ 615 #else /* reject */ 616 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 617 chunkqueue_mark_written(cq, 9+len); 618 return 1; 619 #endif 620 } 621 622 /*(accounting for mod_accesslog and mod_rrdtool)*/ 623 chunkqueue * const rq = r->read_queue; 624 rq->bytes_in += (off_t)alen; 625 rq->bytes_out += (off_t)alen; 626 627 /* r->conf.max_request_size is in kBytes */ 628 const off_t max_request_size = (off_t)r->conf.max_request_size << 10; 629 if (0 != max_request_size 630 && dst->bytes_in + (off_t)alen > max_request_size) { 631 if (0 == r->http_status) { 632 r->http_status = 413; /* Payload Too Large */ 633 log_error(r->conf.errh, __FILE__, __LINE__, 634 "request-size too long: %lld -> 413", 635 (long long) (dst->bytes_in + (off_t)alen)); 636 } 637 chunkqueue_mark_written(cq, 9+len); 638 return 1; 639 } 640 641 if ((s[4] & H2_FLAG_END_STREAM) && !h2_recv_end_data(r, con, alen)) { 642 chunkqueue_mark_written(cq, 9+len); 643 return 1; 644 } 645 646 chunkqueue_mark_written(cq, 9 + ((s[4] & H2_FLAG_PADDED) ? 1 : 0)); 647 648 #if 0 649 if (pad) { 650 /* XXX: future optimization: if data is at end of chunk, then adjust 651 * size of chunk by reducing c->mem->used to avoid copying chunk 652 * when it is split (below) since the split would be due to padding 653 * (also adjust cq->bytes_out)*/ 654 /*(might quickly check 9+len == cqlen if cqlen passed in as param)*/ 655 /*(then check if cq->last contains all of padding, or leave alone)*/ 656 /*(if handled here, then set pad = 0 here)*/ 657 } 658 #endif 659 660 /*(similar decision logic to that in http_chunk_uses_tempfile())*/ 661 const chunk * const c = dst->last; 662 if ((c && c->type == FILE_CHUNK && c->file.is_temp) 663 || dst->bytes_in - dst->bytes_out + alen > 65536) { 664 log_error_st * const errh = r->conf.errh; 665 if (0 != chunkqueue_steal_with_tempfiles(dst, cq, (off_t)alen, errh)) { 666 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR); 667 return 0; 668 } 669 } 670 else 671 chunkqueue_steal(dst, cq, (off_t)alen); 672 673 if (pad) 674 chunkqueue_mark_written(cq, pad); 675 return 1; 676 } 677 678 679 __attribute_cold__ 680 static uint32_t 681 h2_frame_cq_compact (chunkqueue * const cq, uint32_t len) 682 { 683 /*(marked cold since most frames not expect to cross chunk boundary)*/ 684 685 /*(must be guaranteed by caller)*/ 686 /*assert(chunkqueue_length(cq) >= len);*/ 687 /*assert(cq->first != cq->last);*//*(multiple chunks)*/ 688 /* caller must guarantee that chunks in chunkqueue are all MEM_CHUNK */ 689 690 /* move data to beginning of buffer if offset is large or data is short */ 691 chunk *c = cq->first; 692 uint32_t mlen = buffer_string_length(c->mem); 693 if (mlen < c->offset) { 694 memmove(c->mem->ptr, c->mem->ptr + c->offset, mlen); 695 buffer_string_set_length(c->mem, mlen); 696 c->offset = 0; 697 } 698 699 /* combine first mem chunk with next non-empty mem chunks up to len 700 * (loop if next chunk is empty) */ 701 /* (modified from connection_handle_read_post_cq_compact()) */ 702 uint32_t clen = mlen; 703 do { 704 buffer * const mem = c->next->mem; 705 const off_t offset = c->next->offset; 706 mlen = buffer_string_length(mem) - (uint32_t)offset; 707 force_assert(c->type == MEM_CHUNK); 708 force_assert(c->next->type == MEM_CHUNK); 709 if (mlen > clen - len) { 710 mlen = clen - len; 711 buffer_append_string_len(c->mem, mem->ptr+offset, mlen); 712 c->next->offset += mlen; 713 return len; 714 } 715 716 buffer_append_string_len(c->mem, mem->ptr+offset, mlen); 717 clen += mlen; 718 /*(swap first and second chunk, then remove first chunk)*/ 719 c->next->offset = c->offset; 720 c->next->mem = c->mem; 721 c->mem = mem; 722 c->offset = offset + (off_t)mlen; 723 chunkqueue_remove_finished_chunks(cq); 724 } while ((c = cq->first)); /*(need to re-read cq->first)*/ 725 return clen; 726 } 727 728 729 __attribute_cold__ 730 static uint32_t 731 h2_recv_continuation (uint32_t n, uint32_t clen, const off_t cqlen, chunkqueue * const cq, connection * const con) 732 { 733 chunk *c = cq->first; 734 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset); 735 uint32_t m = n; 736 uint32_t flags; 737 h2con * const h2c = con->h2; 738 const uint32_t fsize = h2c->s_max_frame_size; 739 const uint32_t id = 740 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 741 do { 742 if (cqlen < n+9) return n+9; /* incomplete frame; go on */ 743 if (clen < n+9) { 744 clen = h2_frame_cq_compact(cq, n+9); 745 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 746 s = (uint8_t *)(c->mem->ptr + c->offset); 747 } 748 if (s[n+3] != H2_FTYPE_CONTINUATION) { 749 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 750 return 0; 751 } 752 flags = s[n+4]; 753 const uint32_t flen = (s[n+0]<<16)|(s[n+1]<<8)|s[n+2]; 754 if (id != (uint32_t)((s[n+5]<<24)|(s[n+6]<<16)|(s[n+7]<<8)|s[n+8])) { 755 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 756 return 0; 757 } 758 if (flen > fsize) { 759 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 760 return 0; 761 } 762 n += 9+flen; 763 if (n >= 65536) { /*(very oversized for hpack)*/ 764 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 765 return 0; 766 } 767 if (clen < n) { 768 clen = h2_frame_cq_compact(cq, n); 769 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 770 s = (uint8_t *)(c->mem->ptr + c->offset); 771 } 772 } while (!(flags & H2_FLAG_END_HEADERS)); 773 774 /* If some CONTINUATION frames were concatenated to earlier frames while 775 * processing above, but END_HEADERS were not received, then the next time 776 * data was read, initial frame size might exceed SETTINGS_MAX_FRAME_SIZE. 777 * (This describes the current lighttpd implementation in h2_parse_frames()) 778 * While a flag could be set and checked to avoid this, such situations of 779 * large HEADERS (and CONTINUATION) across multiple network reads is 780 * expected to be rare. Reparse and concatenate below. 781 * 782 * Aside: why would the authors of RFC 7540 go through the trouble of 783 * creating a CONTINUATION frame that must be special-cased when use of 784 * CONTINUATION is so restricted e.g. no other intervening frames and 785 * that HEADERS and PUSH_PROMISE HPACK must be parsed as a single block? 786 * IMHO, it would have been simpler to avoid CONTINUATION entirely, and have 787 * a special-case for HEADERS and PUSH_PROMISE to be allowed to exceed 788 * SETTINGS_MAX_FRAME_SIZE with implementations providing a different limit. 789 * While intermediates would not know such a limit of origin servers, 790 * there could have been a reasonable default set with a different SETTINGS 791 * parameter aimed just at HEADERS and PUSH_PROMISE. The parameter 792 * SETTINGS_MAX_HEADER_LIST_SIZE could even have been (re)used, had it been 793 * given a reasonable initial value instead of "unlimited", since HPACK 794 * encoded headers are smaller than the HPACK decoded headers to which the 795 * limit SETTINGS_MAX_HEADER_LIST_SIZE applies. */ 796 797 n = m; /* reset n to beginning of first CONTINUATION frame */ 798 799 /* Eliminate padding from first frame (HEADERS or PUSH_PROMISE) if PADDED */ 800 if (s[4] & H2_FLAG_PADDED) { 801 const uint32_t plen = s[9]; 802 /* validate padding */ 803 const uint32_t flen = (s[0]<<16)|(s[1]<<8)|s[2]; 804 if (flen < 1 + plen + ((s[n+4] & H2_FLAG_PRIORITY) ? 5 : 0)) { 805 /* Padding that exceeds the size remaining for the header block 806 * fragment MUST be treated as a PROTOCOL_ERROR. */ 807 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 808 return 0; 809 } 810 /* set padding to 0 since we will overwrite padding in merge below */ 811 /* (alternatively, could memmove() 9 bytes of frame header over the 812 * pad length octet, remove PADDED flag, add 1 to c->offset, 813 * add 1 to s, subtract 1 from clen and substract 1 from cqlen, 814 * substract 1 from n) */ 815 s[9] = 0; 816 /* set offset to beginning of padding at end of first frame */ 817 m -= plen; 818 } 819 820 do { 821 const uint32_t flen = (s[n+0]<<16)|(s[n+1]<<8)|s[n+2]; 822 flags = s[n+4]; 823 memmove(s+m, s+n+9, flen); 824 m += flen; 825 n += 9+flen; 826 } while (!(flags & H2_FLAG_END_HEADERS)); 827 /* overwrite frame size */ 828 m -= 9; /*(temporarily remove frame header from len)*/ 829 s[0] = (m >> 16) & 0xFF; 830 s[1] = (m >> 8) & 0xFF; 831 s[2] = (m ) & 0xFF; 832 m += 9; 833 /* adjust chunk c->mem */ 834 if (n < clen) { /*(additional frames after CONTINUATION)*/ 835 memmove(s+m, s+n, clen-n); 836 n = m + (clen-n); 837 } 838 else 839 n = m; 840 buffer_string_set_length(c->mem, n + (uint32_t)c->offset); 841 842 return m; 843 } 844 845 846 __attribute_cold__ 847 static request_st * 848 h2_recv_trailers_r (connection * const con, h2con * const h2c, const uint32_t id, const uint32_t flags) 849 { 850 /* rant: RFC 7230 HTTP/1.1 trailer-part would have been much simpler 851 * to support in RFC 7540 HTTP/2 as a distinct frame type rather than 852 * HEADERS. As trailers are not known at the time the request is made, 853 * reuse of such trailers is limited and so a theoretical TRAILERS frame 854 * could have been implemented without HPACK encoding, and would have 855 * been more straightforward to implement than overloading and having to 856 * handle multiple cases for HEADERS. TRAILERS support could then also 857 * be optional, like in HTTP/1.1 */ 858 request_st *r = NULL; 859 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 860 request_st * const rr = h2c->r[i]; 861 if (rr->h2id != id) continue; 862 r = rr; 863 break; 864 } 865 if (NULL == r) { 866 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 867 return NULL; 868 } 869 if (r->h2state != H2_STATE_OPEN 870 && r->h2state != H2_STATE_HALF_CLOSED_LOCAL) { 871 h2_send_rst_stream(r, con, H2_E_STREAM_CLOSED); 872 return NULL; 873 } 874 /* RFC 7540 is not explicit in restricting HEADERS (trailers) following 875 * (optional) DATA frames, but in following HTTP/1.1, we limit to single 876 * (optional) HEADERS (+ CONTINUATIONs) after (optional) DATA frame(s) 877 * and require that the HEADERS frame set END_STREAM flag. */ 878 if (!(flags & H2_FLAG_END_STREAM)) { 879 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 880 return NULL; 881 } 882 883 return h2_recv_end_data(r, con, 0) ? r : NULL; 884 } 885 886 887 /* prototype if HPACK-decoded HEADERS reconstituted 888 * into HTTP/1.1 request format in r->read_queue */ 889 890 /* Note: similar to connection_handle_read_state(), except operates on single 891 * buf since HTTP/2 headers delivered in a single buffer and are complete or err 892 */ 893 __attribute_noinline__ 894 static void 895 h2_parse_request_headers (request_st * const r, char * const hdrs, const uint32_t header_len) 896 { 897 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */ 898 hoff[0] = 1; /* number of lines */ 899 hoff[1] = 0; /* base offset for all lines */ 900 /*hoff[2] = ...;*/ /* offset from base for 2nd line */ 901 r->rqst_header_len = http_header_parse_hoff(hdrs, header_len, hoff); 902 if (0 == r->rqst_header_len || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1) { 903 /* error if headers incomplete or too many header fields */ 904 r->http_status = 431; /* Request Header Fields Too Large */ 905 log_error(r->conf.errh, __FILE__, __LINE__, 906 "oversized request-header -> sending Status 431"); 907 return; 908 } 909 if (r->conf.log_request_header) 910 log_error(r->conf.errh, __FILE__, __LINE__, 911 "fd: %d request-len: %d\n%.*s", r->con->fd, 912 (int)r->rqst_header_len, (int)r->rqst_header_len, hdrs); 913 http_request_headers_process(r, hdrs, hoff, r->con->proto_default_port); 914 } 915 916 917 static void 918 h2_parse_request (request_st * const r) 919 { 920 chunk * const c = r->read_queue->first; 921 r->rqst_header_len = buffer_string_length(c->mem) - (uint32_t)c->offset; 922 h2_parse_request_headers(r, c->mem->ptr + c->offset, r->rqst_header_len); 923 chunkqueue_mark_written(r->read_queue, r->rqst_header_len); 924 925 if (0 != r->http_status) { 926 if (431 == r->http_status) /*(e.g. too many header lines)*/ 927 log_error(r->conf.errh, __FILE__, __LINE__, 928 "oversized request-header -> sending Status 431"); 929 } 930 931 /* ignore Upgrade if using HTTP/2 */ 932 if (r->rqst_htags & HTTP_HEADER_UPGRADE) { 933 http_header_request_unset(r, HTTP_HEADER_UPGRADE, 934 CONST_STR_LEN("upgrade")); 935 buffer * const connhdr = 936 http_header_request_get(r, HTTP_HEADER_CONNECTION, 937 CONST_STR_LEN("connection")); 938 if (connhdr) 939 http_header_remove_token(connhdr, CONST_STR_LEN("upgrade")); 940 } 941 /* XXX: should filter out other hop-by-hop connection headers, too */ 942 } 943 944 945 static int 946 h2_parse_headers_frame (connection * const con, const unsigned char *psrc, const uint32_t plen, request_st * const restrict r, const int trailers) 947 { 948 uint32_t hlen = 0; 949 950 951 952 /* XXX: TODO: HPACK decode frame; fill in (request_st *r) */ 953 954 955 956 #if 1 957 /* terminate reconstituted HTTP/1.1 request 958 * (along with HTTP/2 pseudo-headers) */ 959 chunkqueue_append_mem(r->read_queue, CONST_STR_LEN("\r\n")); 960 if (r->read_queue->first->next) { 961 hlen += 2; 962 h2_frame_cq_compact(r->read_queue, hlen); 963 } 964 h2_parse_request(r); 965 #else 966 /* future: adjust counts if bypassing HTTP/1.x compatibility 967 * (avoiding reconsitituting HTTP/1.1 request in r->read_queue) */ 968 r->rqst_header_len += hlen; 969 /*(accounting for mod_accesslog and mod_rrdtool)*/ 970 chunkqueue * const rq = r->read_queue; 971 rq->bytes_in += (off_t)hlen; 972 rq->bytes_out += (off_t)hlen; 973 #endif 974 975 return 1; 976 } 977 978 979 static int 980 h2_recv_headers (connection * const con, uint8_t * const s, uint32_t flen) 981 { 982 request_st *r = NULL; 983 h2con * const h2c = con->h2; 984 const uint32_t id = 985 ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u; 986 if (0 == id) { /* HEADERS, PUSH_PROMISE stream id must != 0 */ 987 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 988 return 0; 989 } 990 if (!(id & 1)) { /* stream id from client must be odd */ 991 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 992 return 0; 993 } 994 995 request_st * const h2r = &con->request; 996 int trailers = 0; 997 998 if (id > h2c->h2_cid) { 999 if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r)) { 1000 if (0 == h2c->sent_settings) { /*(see h2_recv_settings() comments)*/ 1001 /* too many active streams; refuse new stream */ 1002 h2c->h2_cid = id; 1003 h2_send_rst_stream_id(id, con, H2_E_REFUSED_STREAM); 1004 return 1; 1005 } 1006 else { 1007 /* alternative: stop processing frames and defer processing this 1008 * HEADERS frame until num active streams drops below limit. 1009 * lighttpd sends SETTINGS_MAX_CONCURRENT_STREAMS <limit> with 1010 * server Connection Preface, so a well-behaved client will 1011 * adjust after it sends its initial requests. 1012 * (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)*/ 1013 return -1; 1014 } 1015 } 1016 /* Note: MUST process HPACK decode even if already sent GOAWAY. 1017 * This is necessary since there may be active streams not in 1018 * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly 1019 * receiving DATA and, more relevantly, still might receive HEADERS 1020 * frame with trailers, for which the decoder state is required. 1021 * XXX: future might try to reduce other processing done if sent 1022 * GOAWAY, e.g. might avoid allocating (request_st *r) */ 1023 r = h2_init_stream(h2r, con); 1024 r->h2id = id; 1025 r->h2state = (s[4] & H2_FLAG_END_STREAM) 1026 ? H2_STATE_HALF_CLOSED_REMOTE 1027 : H2_STATE_OPEN; 1028 /* Note: timestamps here are updated only after receipt of entire header 1029 * (HEADERS frame might have been sent in multiple packets 1030 * and CONTINUATION frames may have been sent in multiple packets) 1031 * (affects high precision timestamp, if enabled) 1032 * (large sets of headers are not typical, and even when they do 1033 * occur, they will typically be sent within the same second) 1034 * (future: might keep high precision timestamp in h2con when first 1035 * packet of HEADERS or PUSH_PROMISE is received, and clear that 1036 * timestamp when frame + CONTINUATION(s) are complete (so that 1037 * re-read of initial frame does not overwrite the timestamp)) 1038 */ 1039 r->start_ts = log_epoch_secs; 1040 if (r->conf.high_precision_timestamps) 1041 log_clock_gettime_realtime(&r->start_hp); 1042 } 1043 else { 1044 r = h2_recv_trailers_r(con, h2c, id, s[4]); /* (cold code path) */ 1045 if (NULL == r) 1046 return (h2c->sent_goaway > 0) ? 0 : 1; 1047 trailers = 1; 1048 } 1049 1050 const unsigned char *psrc = s + 9; 1051 uint32_t alen = flen; 1052 if (s[4] & H2_FLAG_PADDED) { 1053 ++psrc; 1054 const uint32_t pad = s[9]; 1055 if (flen < 1 + pad + ((s[4] & H2_FLAG_PRIORITY) ? 5 : 0)) { 1056 /* Padding that exceeds the size remaining for the header block 1057 * fragment MUST be treated as a PROTOCOL_ERROR. */ 1058 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 1059 h2_retire_stream(r, con); 1060 return 0; 1061 } 1062 alen -= (1 + pad); /*(alen is adjusted for PRIORITY below)*/ 1063 } 1064 if (s[4] & H2_FLAG_PRIORITY) { 1065 /* XXX: TODO: handle PRIORITY (prio fields start at *psrc) */ 1066 const uint32_t prio = 1067 ((psrc[0]<<24)|(psrc[1]<<16)|(psrc[2]<<8)|psrc[3]) & ~0x80000000u; 1068 if (prio == id) { 1069 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 1070 h2_retire_stream(r, con); 1071 return 1; 1072 } 1073 #if 0 1074 uint32_t exclusive_dependency = (psrc[0] & 0x80) ? 1 : 0; 1075 uint32_t weight = psrc[4]; 1076 #endif 1077 psrc += 5; 1078 alen -= 5; 1079 } 1080 1081 if (!h2_parse_headers_frame(con, psrc, alen, r, trailers)) 1082 return 0; 1083 1084 #if 0 /*(handled in h2_parse_frames() as a connection error)*/ 1085 if (s[3] == H2_FTYPE_PUSH_PROMISE) { 1086 /* Had to process HPACK to keep HPACK tables sync'd with peer but now 1087 * discard the request if PUSH_PROMISE, since not expected, as this code 1088 * is running as a server, not as a client. 1089 * XXX: future might try to reduce other processing done if 1090 * discarding, e.g. might avoid allocating (request_st *r) */ 1091 /* rant: PUSH_PROMISE could have been a flag on HEADERS frame 1092 * instead of an independent frame type */ 1093 r->http_status = 0; 1094 h2_retire_stream(r, con); 1095 } 1096 #endif 1097 1098 if (!h2c->sent_goaway) { 1099 h2c->h2_cid = id; 1100 if (!(r->rqst_htags & HTTP_HEADER_CONTENT_LENGTH)) 1101 r->reqbody_length = (s[4] & H2_FLAG_END_STREAM) ? 0 : -1; 1102 #if 0 1103 else if (r->reqbody_length > 0 && (s[4] & H2_FLAG_END_STREAM)) { 1104 /*(handled in connection_handle_read_post_state())*/ 1105 /* XXX: TODO if (r->conf.log_request_header_on_error) */ 1106 r->http_status = 400; /* Bad Request */ 1107 } 1108 #endif 1109 1110 /* RFC 7540 Section 8. HTTP Message Exchanges 1111 * 8.1.2.6. Malformed Requests and Responses 1112 * For malformed requests, a server MAY send an HTTP 1113 * response prior to closing or resetting the stream. 1114 * However, h2spec expects stream PROTOCOL_ERROR. 1115 * (This is unfortunate, since we would rather send 1116 * 400 Bad Request which tells client *do not* retry 1117 * the bad request without modification) 1118 * https://github.com/summerwind/h2spec/issues/120 1119 * https://github.com/summerwind/h2spec/issues/121 1120 * https://github.com/summerwind/h2spec/issues/122 1121 */ 1122 #if 0 1123 if (400 == r->http_status) { 1124 h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR); 1125 h2_retire_stream(r, con); 1126 } 1127 #endif 1128 } 1129 else if (h2c->h2_cid < id) { 1130 /* Had to process HPACK to keep HPACK tables sync'd with peer 1131 * but now discard the request if id is after id sent in GOAWAY. 1132 * XXX: future might try to reduce other processing done if 1133 * discarding, e.g. might avoid allocating (request_st *r) */ 1134 r->http_status = 0; 1135 h2_retire_stream(r, con); 1136 } 1137 1138 return 1; 1139 } 1140 1141 1142 int 1143 h2_parse_frames (connection * const con) 1144 { 1145 /* read and process HTTP/2 frames from socket */ 1146 h2con * const h2c = con->h2; 1147 chunkqueue * const cq = con->read_queue; 1148 /* initial max frame size is the minimum: 16k 1149 * (lighttpd does not currently increase max frame size) 1150 * (lighttpd does not currently decrease max frame size) 1151 * (XXX: If SETTINGS_MAX_FRAME_SIZE were increased and then decreased, 1152 * should accept the larger frame size until SETTINGS is ACK'd) */ 1153 const uint32_t fsize = h2c->s_max_frame_size; 1154 for (off_t cqlen = chunkqueue_length(cq); cqlen >= 9; ) { 1155 chunk *c = cq->first; 1156 /*assert(c->type == MEM_CHUNK);*/ 1157 /* copy data if frame header crosses chunk boundary 1158 * future: be more efficient than blind full chunk copy */ 1159 uint32_t clen = buffer_string_length(c->mem) - c->offset; 1160 if (clen < 9) { 1161 clen = h2_frame_cq_compact(cq, 9); 1162 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1163 } 1164 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset); 1165 uint32_t flen = (s[0] << 16) | (s[1] << 8) | s[2]; 1166 if (flen > fsize) { 1167 h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR); 1168 return 0; 1169 } 1170 1171 /*(handle PUSH_PROMISE as connection error further below)*/ 1172 /*if (s[3] == H2_FTYPE_HEADERS || s[3] == H2_FTYPE_PUSH_PROMISE)*/ 1173 1174 if (s[3] == H2_FTYPE_HEADERS) { 1175 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */ 1176 if (clen < 9+flen) { 1177 clen = h2_frame_cq_compact(cq, 9+flen); 1178 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1179 s = (uint8_t *)(c->mem->ptr + c->offset); 1180 } 1181 1182 if (!(s[4] & H2_FLAG_END_HEADERS)) { 1183 /* collect CONTINUATION frames (cold code path) */ 1184 /* note: h2_recv_continuation() return value is overloaded 1185 * and the resulting clen is 9+flen of *concatenated* frames */ 1186 clen = h2_recv_continuation(9+flen, clen, cqlen, cq, con); 1187 if (0 == clen) return 0; 1188 if (cqlen < clen) return 1; /* incomplete frames; go on */ 1189 c = cq->first; /*(reload after h2_recv_continuation())*/ 1190 s = (uint8_t *)(c->mem->ptr + c->offset); 1191 /* frame size was also updated and might (legitimately) 1192 * exceed SETTINGS_MAX_FRAME_SIZE, so do not test fsize again */ 1193 flen = (s[0]<<16)|(s[1]<<8)|s[2]; 1194 /* recalculate after CONTINUATION removed */ 1195 cqlen = chunkqueue_length(cq); 1196 } 1197 1198 int rc = h2_recv_headers(con, s, flen); 1199 cqlen -= (9+flen); 1200 if (rc >= 0) 1201 chunkqueue_mark_written(cq, 9+flen); 1202 if (rc <= 0) 1203 return 0; 1204 con->read_idle_ts = log_epoch_secs; 1205 } 1206 else if (s[3] == H2_FTYPE_DATA) { 1207 /* future: might try to stream data for incomplete frames, 1208 * but that would require keeping additional state for partially 1209 * read frames, including cleaning up if errors occur. 1210 * Since well-behaved clients do not intentionally send partial 1211 * frames, and try to resend if socket buffers are full, this is 1212 * probably not a big concern in practice. */ 1213 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */ 1214 con->read_idle_ts = log_epoch_secs; 1215 /*(h2_recv_data() must consume frame from cq or else return 0)*/ 1216 if (!h2_recv_data(con, s, flen)) 1217 return 0; 1218 cqlen -= (9+flen); 1219 } 1220 else { 1221 /* frame types below are expected to be small 1222 * most frame types below have fixed (small) size 1223 * 4 bytes - WINDOW_UPDATE 1224 * 5 bytes - PRIORITY 1225 * 8 bytes - PING 1226 * 4 bytes - RST_STREAM 1227 * some are variable size 1228 * SETTINGS (6 * #settings; 6 defined in RFC 7540 Section 6.5) 1229 * GOAWAY (8 + optional additional debug data (variable)) 1230 * XXX: might add sanity check for a max flen here, 1231 * before waiting to read partial frame 1232 * (fsize limit is still enforced above for all frames) 1233 */ 1234 if (cqlen < 9+flen) return 1; /* incomplete frame; go on */ 1235 if (clen < 9+flen) { 1236 clen = h2_frame_cq_compact(cq, 9+flen); 1237 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1238 s = (uint8_t *)(c->mem->ptr + c->offset); 1239 } 1240 switch (s[3]) { /* frame type */ 1241 case H2_FTYPE_WINDOW_UPDATE: 1242 h2_recv_window_update(con, s, flen); 1243 break; 1244 case H2_FTYPE_PRIORITY: 1245 h2_recv_priority(con, s, flen); 1246 break; 1247 case H2_FTYPE_SETTINGS: 1248 h2_recv_settings(con, s, flen); 1249 break; 1250 case H2_FTYPE_PING: 1251 h2_recv_ping(con, s, flen); 1252 break; 1253 case H2_FTYPE_RST_STREAM: 1254 h2_recv_rst_stream(con, s, flen); 1255 break; 1256 case H2_FTYPE_GOAWAY: 1257 if (!h2_recv_goaway(con, s, flen)) return 0; 1258 break; 1259 case H2_FTYPE_PUSH_PROMISE: /*not expected from client*/ 1260 case H2_FTYPE_CONTINUATION: /*handled with HEADERS*/ 1261 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 1262 return 0; 1263 default: /* ignore unknown frame types */ 1264 break; 1265 } 1266 cqlen -= (9+flen); 1267 chunkqueue_mark_written(cq, 9+flen); 1268 } 1269 1270 if (h2c->sent_goaway > 0) return 0; 1271 } 1272 1273 return 1; 1274 } 1275 1276 1277 int 1278 h2_want_read (connection * const con) 1279 { 1280 chunkqueue * const cq = con->read_queue; 1281 if (chunkqueue_is_empty(cq)) return 1; 1282 1283 /* check for partial frame */ 1284 const off_t cqlen = cq->bytes_in - cq->bytes_out; /*chunkqueue_length(cq);*/ 1285 if (cqlen < 9) return 1; 1286 chunk *c = cq->first; 1287 uint32_t clen = buffer_string_length(c->mem) - c->offset; 1288 if (clen < 9) { 1289 clen = h2_frame_cq_compact(cq, 9); 1290 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1291 } 1292 uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset); 1293 uint32_t flen = (s[0] << 16) | (s[1] << 8) | s[2]; 1294 if (clen < 9+flen) return 1; 1295 1296 /* check if not HEADERS, or if HEADERS has END_HEADERS flag */ 1297 if (s[3] != H2_FTYPE_HEADERS || (s[4] & H2_FLAG_END_HEADERS)) 1298 return 0; 1299 1300 /* check for partial CONTINUATION frames */ 1301 for (uint32_t n = 9+flen; cqlen >= n+9; n += 9+flen) { 1302 if (clen < n+9) { 1303 clen = h2_frame_cq_compact(cq, n+9); 1304 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1305 s = (uint8_t *)(c->mem->ptr + c->offset); 1306 } 1307 flen = (s[n+0] << 16) | (s[n+1] << 8) | s[n+2]; 1308 if (cqlen < n+9+flen) return 1; /* incomplete frame; go on */ 1309 if (s[4] & H2_FLAG_END_HEADERS) return 0; 1310 } 1311 1312 return 1; 1313 } 1314 1315 1316 static int 1317 h2_recv_client_connection_preface (connection * const con) 1318 { 1319 /* check if the client Connection Preface (24 bytes) has been received 1320 * (initial SETTINGS frame should immediately follow, but is not checked) */ 1321 chunkqueue * const cq = con->read_queue; 1322 if (chunkqueue_length(cq) < 24) { 1323 chunk * const c = cq->first; 1324 if (c && buffer_string_length(c->mem) - c->offset >= 4) { 1325 const char * const s = c->mem->ptr + c->offset; 1326 if (s[0]!='P'||s[1]!='R'||s[2]!='I'||s[3]!=' ') { 1327 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 1328 return 1; /* error; done receiving connection preface */ 1329 } 1330 } 1331 return 0; /*(not ready yet)*/ 1332 } 1333 1334 static const char h2preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; 1335 chunk *c = cq->first; 1336 const uint32_t clen = buffer_string_length(c->mem) - c->offset; 1337 if (clen < 24) h2_frame_cq_compact(cq, 24); 1338 c = cq->first; /*(reload after h2_frame_cq_compact())*/ 1339 const uint8_t * const s = (uint8_t *)(c->mem->ptr + c->offset); 1340 if (0 == memcmp(s, h2preface, 24)) /* sizeof(h2preface)-1) */ 1341 chunkqueue_mark_written(cq, 24); 1342 else 1343 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR); 1344 return 1; /* done receiving connection preface (even if error occurred) */ 1345 } 1346 1347 1348 __attribute_cold__ 1349 static int 1350 h2_read_client_connection_preface (struct connection * const con, chunkqueue * const cq, off_t max_bytes) 1351 { 1352 /* temporary con->network_read() filter until connection preface received */ 1353 1354 /*(alternatively, func ptr could be saved in an element in (h2con *))*/ 1355 void ** const hctx = con->plugin_ctx+0; /*(0 idx used for h2)*/ 1356 int(* const network_read)(struct connection *, chunkqueue *, off_t) = 1357 (int(*)(struct connection *, chunkqueue *, off_t))(uintptr_t)(*hctx); 1358 if (max_bytes < 24) max_bytes = 24; /*(should not happen)*/ 1359 int rc = (network_read)(con, cq, max_bytes); 1360 if (NULL == con->h2) return rc; /*(unexpected; already cleaned up)*/ 1361 if (-1 != rc && h2_recv_client_connection_preface(con)) { 1362 con->network_read = network_read; 1363 *hctx = NULL; 1364 /*(intentionally update timestamp only after reading preface complete)*/ 1365 con->read_idle_ts = log_epoch_secs; 1366 } 1367 return rc; 1368 } 1369 1370 1371 void 1372 h2_init_con (request_st * const restrict h2r, connection * const restrict con, const buffer * const restrict http2_settings) 1373 { 1374 h2con * const h2c = calloc(1, sizeof(h2con)); 1375 force_assert(h2c); 1376 con->h2 = h2c; 1377 con->read_idle_ts = log_epoch_secs; 1378 con->keep_alive_idle = h2r->conf.max_keep_alive_idle; 1379 1380 h2r->h2_rwin = 65535; /* h2 connection recv window */ 1381 h2r->h2_swin = 65535; /* h2 connection send window */ 1382 /* settings sent from peer */ /* initial values */ 1383 h2c->s_header_table_size = 4096; /* SETTINGS_HEADER_TABLE_SIZE */ 1384 h2c->s_enable_push = 1; /* SETTINGS_ENABLE_PUSH */ 1385 h2c->s_max_concurrent_streams= ~0u; /* SETTINGS_MAX_CONCURRENT_STREAMS */ 1386 h2c->s_initial_window_size = 65535; /* SETTINGS_INITIAL_WINDOW_SIZE */ 1387 h2c->s_max_frame_size = 16384; /* SETTINGS_MAX_FRAME_SIZE */ 1388 h2c->s_max_header_list_size = ~0u; /* SETTINGS_MAX_HEADER_LIST_SIZE */ 1389 h2c->sent_settings = log_epoch_secs; /*(send SETTINGS below)*/ 1390 1391 if (http2_settings) /*(if Upgrade: h2c)*/ 1392 h2_parse_frame_settings(con, (uint8_t *)CONST_BUF_LEN(http2_settings)); 1393 1394 static const uint8_t h2settings[] = { /*(big-endian numbers)*/ 1395 /* SETTINGS */ 1396 0x00, 0x00, 0x0c /* frame length */ /* 6 * 2 for two settings */ 1397 ,H2_FTYPE_SETTINGS /* frame type */ 1398 ,0x00 /* frame flags */ 1399 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */ 1400 ,0x00, H2_SETTINGS_MAX_CONCURRENT_STREAMS 1401 ,0x00, 0x00, 0x00, 0x08 /* 8 */ 1402 #if 0 /* ? explicitly disable dynamic table ? (and adjust frame length) */ 1403 /* If this is sent, must wait until peer sends SETTINGS with ACK 1404 * before disabling dynamic table in HPACK decoder */ 1405 ,0x00, H2_SETTINGS_HEADER_TABLE_SIZE 1406 ,0x00, 0x00, 0x00, 0x00 /* 0 */ 1407 #endif 1408 #if 0 /* ? explicitly disable push ? (and adjust frame length) */ 1409 ,0x00, H2_SETTINGS_ENABLE_PUSH 1410 ,0x00, 0x00, 0x00, 0x00 /* 0 */ 1411 #endif 1412 #if 0 /* ? increase from default (65535) ? (and adjust frame length) */ 1413 ,0x00, H2_SETTINGS_INITIAL_WINDOW_SIZE 1414 ,0x00, 0x02, 0x00, 0x00 /* 131072 */ 1415 #endif 1416 #if 0 /* ? increase from default (16384) ? (and adjust frame length) */ 1417 ,0x00, H2_SETTINGS_MAX_FRAME_SIZE 1418 ,0x00, 0x00, 0x80, 0x00 /* 32768 */ 1419 #endif 1420 ,0x00, H2_SETTINGS_MAX_HEADER_LIST_SIZE 1421 ,0x00, 0x00, 0xFF, 0xFF /* 65535 */ 1422 1423 #if 0 1424 /* WINDOW_UPDATE */ 1425 ,0x00, 0x00, 0x04 /* frame length */ 1426 ,H2_FTYPE_WINDOW_UPDATE /* frame type */ 1427 ,0x00 /* frame flags */ 1428 ,0x00, 0x00, 0x00, 0x00 /* stream identifier */ 1429 ,0x00, 0x01, 0x00, 0x01 /* 65537 */ /* increase connection rwin to 128k */ 1430 #endif 1431 }; 1432 1433 /*h2r->h2_rwin += 65537;*//*(enable if WINDOWS_UPDATE is sent above)*/ 1434 chunkqueue_append_mem(con->write_queue, 1435 (const char *)h2settings, sizeof(h2settings)); 1436 1437 if (!h2_recv_client_connection_preface(con)) { 1438 /*(alternatively, func ptr could be saved in an element in (h2con *))*/ 1439 con->plugin_ctx[0] = (void *)(uintptr_t)con->network_read; 1440 con->network_read = h2_read_client_connection_preface; 1441 /* note: no steps taken to reset con->network_read() on error 1442 * as con->network_read() is always set in connection_accepted() */ 1443 } 1444 1445 buffer_string_prepare_copy(h2r->tmp_buf, 65535); 1446 } 1447 1448 1449 static void 1450 h2_send_hpack (request_st * const r, connection * const con, const char *data, uint32_t dlen, const uint32_t flags) 1451 { 1452 union { 1453 uint8_t c[12]; 1454 uint32_t u[3]; /*(alignment)*/ 1455 } headers = { { /*(big-endian numbers)*/ 1456 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 1457 /* HEADERS */ 1458 ,0x00, 0x00, 0x00 /* frame length (fill in below) */ 1459 ,H2_FTYPE_HEADERS /* frame type */ 1460 ,(uint8_t)flags /* frame flags (e.g. END_STREAM for trailers) */ 1461 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 1462 } }; 1463 1464 headers.u[2] = htonl(r->h2id); 1465 1466 /* similar to h2_send_data(), but unlike DATA frames there is a HEADERS 1467 * frame potentially followed by CONTINUATION frame(s) here, and the final 1468 * HEADERS or CONTINUATION frame here has END_HEADERS flag set. 1469 * For trailers, END_STREAM flag is set on HEADERS frame. */ 1470 1471 /*(approximate space needed for frames (header + payload) 1472 * with slight over-estimate of 16 bytes per frame header (> 9) 1473 * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger) 1474 * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes 1475 * per frame can be appoximated with (dlen>>10) + 9)*/ 1476 buffer * const b = 1477 chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9); 1478 char * restrict ptr = b->ptr; 1479 h2con * const h2c = con->h2; 1480 const uint32_t fsize = h2c->s_max_frame_size; 1481 do { 1482 const uint32_t len = dlen < fsize ? dlen : fsize; 1483 headers.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/ 1484 headers.c[4] = (len >> 8) & 0xFF; 1485 headers.c[5] = (len ) & 0xFF; 1486 if (len == dlen) 1487 headers.c[7] |= H2_FLAG_END_HEADERS; 1488 #if 0 1489 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/ 1490 (const char *)headers.c+3, sizeof(headers)-3); 1491 chunkqueue_append_mem(con->write_queue, data, len); 1492 #else 1493 memcpy(ptr, headers.c+3, sizeof(headers)-3); 1494 memcpy(ptr+sizeof(headers)-3, data, len); 1495 ptr += len + sizeof(headers)-3; 1496 #endif 1497 data += len; 1498 dlen -= len; 1499 /*(include H2_FLAG_END_STREAM in HEADERS frame, not CONTINUATION)*/ 1500 headers.c[6] = H2_FTYPE_CONTINUATION; /*(if additional frames needed)*/ 1501 headers.c[7] = 0x00; /*(off +3 to skip over align pad)*/ 1502 } while (dlen); 1503 buffer_string_set_length(b, (uint32_t)(ptr - b->ptr)); 1504 chunkqueue_append_buffer_commit(con->write_queue); 1505 } 1506 1507 1508 __attribute_noinline__ 1509 static void 1510 h2_send_headers_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen, uint32_t flags) 1511 { 1512 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */ 1513 hoff[0] = 1; /* number of lines */ 1514 hoff[1] = 0; /* base offset for all lines */ 1515 /*hoff[2] = ...;*/ /* offset from base for 2nd line */ 1516 uint32_t rc = http_header_parse_hoff(hdrs, hlen, hoff); 1517 if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1 1518 || 1 == hoff[0]) { /*(initial blank line (should not happen))*/ 1519 /* error if headers incomplete or too many header fields */ 1520 log_error(r->conf.errh, __FILE__, __LINE__, 1521 "oversized response-header"); 1522 hoff[0] = 1; 1523 hoff[1] = 0; 1524 http_header_parse_hoff(CONST_STR_LEN(":status: 500\r\n\r\n"), hoff); 1525 } 1526 1527 /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/ 1528 buffer * const tb = r->tmp_buf; 1529 force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/ 1530 1531 /* FIXME: TODO: hpack-encode headers */ 1532 uint32_t dlen = 0; /* TODO: hpack-encoded len */ 1533 char *data = tb->ptr; /* TODO: hpack-encoded data */ 1534 1535 h2_send_hpack(r, con, tb->ptr, dlen, flags); 1536 } 1537 1538 1539 void 1540 h2_send_100_continue (request_st * const r, connection * const con) 1541 { 1542 /* place frame directly in con->write_queue for accounting to be part of 1543 * HTTP/2 protocol overhead, and not part of response header or body len */ 1544 /* 100 Continue is small and will always fit in SETTING_MAX_FRAME_SIZE; 1545 * i.e. there will not be any CONTINUATION frames here */ 1546 1547 /* XXX: need to update hpack dynamic table, 1548 * or else could hard-code header block fragment 1549 * { 0x48, 0x03, 0x31, 0x30, 0x30 } 1550 */ 1551 1552 h2_send_headers_block(r, con, CONST_STR_LEN(":status: 100\r\n\r\n"), 0); 1553 } 1554 1555 1556 static void 1557 h2_send_end_stream_data (request_st * const r, connection * const con); 1558 1559 __attribute_cold__ 1560 __attribute_noinline__ 1561 static void 1562 h2_send_end_stream_trailers (request_st * const r, connection * const con, const buffer * const trailers) 1563 { 1564 /*(trailers are merged into response headers if trailers are received before 1565 * sending response headers to client. However, if streaming response, then 1566 * trailers might need handling here)*/ 1567 1568 /* parse and lowercase field-names in trailers */ 1569 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */ 1570 hoff[0] = 1; /* number of lines */ 1571 hoff[1] = 0; /* base offset for all lines */ 1572 /*hoff[2] = ...;*/ /* offset from base for 2nd line */ 1573 uint32_t rc = http_header_parse_hoff(CONST_BUF_LEN(trailers), hoff); 1574 if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1 1575 || 1 == hoff[0]) { /*(initial blank line (should not happen))*/ 1576 /* skip trailers if incomplete, too many fields, or too long (> 64k-1)*/ 1577 h2_send_end_stream_data(r, con); 1578 return; 1579 } 1580 1581 char * const ptr = trailers->ptr; 1582 for (int i = 1; i < hoff[0]; ++i) { 1583 char *k = ptr + ((i > 1) ? hoff[i] : 0); 1584 if (*k == ':') { 1585 /*(pseudo-header should not appear in trailers)*/ 1586 h2_send_end_stream_data(r, con); 1587 return; 1588 } 1589 const char * const colon = memchr(k, ':', ptr+hoff[i+1]-k); 1590 if (NULL == colon) continue; 1591 do { 1592 if (*k >= 'A' && *k <= 'Z') *k |= 0x20; 1593 } while (++k != colon); 1594 } 1595 1596 h2_send_headers_block(r, con, CONST_BUF_LEN(trailers), H2_FLAG_END_STREAM); 1597 } 1598 1599 1600 void 1601 h2_send_cqheaders (request_st * const r, connection * const con) 1602 { 1603 /*(assumes HTTP/1.1 response headers have been prepended as first chunk) 1604 *(future: if r->write_queue is bypassed for headers, adjust 1605 * r->write_queue bytes counts (bytes_in, bytes_out) with header len)*/ 1606 /* note: expects field-names are lowercased (http_response_write_header())*/ 1607 chunk * const c = r->write_queue->first; 1608 const uint32_t len = buffer_string_length(c->mem) - (uint32_t)c->offset; 1609 uint32_t flags = (r->resp_body_finished && NULL == c->next) 1610 ? H2_FLAG_END_STREAM 1611 : 0; 1612 h2_send_headers_block(r, con, c->mem->ptr + c->offset, len, flags); 1613 chunkqueue_mark_written(r->write_queue, len); 1614 } 1615 1616 1617 #if 0 1618 1619 void 1620 h2_send_data (request_st * const r, connection * const con, const char *data, uint32_t dlen) 1621 { 1622 /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */ 1623 1624 union { 1625 uint8_t c[12]; 1626 uint32_t u[3]; /*(alignment)*/ 1627 } dataframe = { { /*(big-endian numbers)*/ 1628 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 1629 /* DATA */ 1630 ,0x00, 0x00, 0x00 /* frame length (fill in below) */ 1631 ,H2_FTYPE_DATA /* frame type */ 1632 ,0x00 /* frame flags */ 1633 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 1634 } }; 1635 1636 dataframe.u[2] = htonl(r->h2id); 1637 1638 /* XXX: does not provide an optimization to send final set of data with 1639 * END_STREAM flag; see h2_send_end_stream_data() to end stream */ 1640 1641 /* adjust stream and connection windows */ 1642 /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */ 1643 request_st * const h2r = &con->request; 1644 if (r->h2_swin < 0) return; 1645 if (h2r->h2_swin < 0) return; 1646 if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin; 1647 if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin; 1648 if (0 == dlen) return; 1649 r->h2_swin -= (int32_t)dlen; 1650 h2r->h2_swin -= (int32_t)dlen; 1651 1652 /* XXX: future: should have an interface which processes chunkqueue 1653 * and takes string refs to mmap FILE_CHUNK to avoid extra copying 1654 * since the result is likely to be consumed by TLS modules */ 1655 1656 /*(approximate space needed for frames (header + payload) 1657 * with slight over-estimate of 16 bytes per frame header (> 9) 1658 * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger) 1659 * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes 1660 * per frame can be appoximated with (dlen>>10) + 9)*/ 1661 buffer * const b = 1662 chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9); 1663 char * restrict ptr = b->ptr; 1664 h2con * const h2c = con->h2; 1665 const uint32_t fsize = h2c->s_max_frame_size; 1666 do { 1667 const uint32_t len = dlen < fsize ? dlen : fsize; 1668 dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/ 1669 dataframe.c[4] = (len >> 8) & 0xFF; 1670 dataframe.c[5] = (len ) & 0xFF; 1671 #if 0 1672 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/ 1673 (const char *)dataframe.c+3, sizeof(dataframe)-3); 1674 chunkqueue_append_mem(con->write_queue, data, len); 1675 #else 1676 memcpy(ptr, dataframe.c+3, sizeof(dataframe)-3); 1677 memcpy(ptr+sizeof(dataframe)-3, data, len); 1678 ptr += len + sizeof(dataframe)-3; 1679 #endif 1680 data += len; 1681 dlen -= len; 1682 } while (dlen); 1683 buffer_string_set_length(b, (uint32_t)(ptr - b->ptr)); 1684 chunkqueue_append_buffer_commit(con->write_queue); 1685 } 1686 1687 #endif 1688 1689 1690 void 1691 h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const cq, uint32_t dlen) 1692 { 1693 /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */ 1694 1695 union { 1696 uint8_t c[12]; 1697 uint32_t u[3]; /*(alignment)*/ 1698 } dataframe = { { /*(big-endian numbers)*/ 1699 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 1700 /* DATA */ 1701 ,0x00, 0x00, 0x00 /* frame length (fill in below) */ 1702 ,H2_FTYPE_DATA /* frame type */ 1703 ,0x00 /* frame flags */ 1704 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 1705 } }; 1706 1707 dataframe.u[2] = htonl(r->h2id); 1708 1709 /* XXX: does not provide an optimization to send final set of data with 1710 * END_STREAM flag; see h2_send_end_stream_data() to end stream */ 1711 1712 /* adjust stream and connection windows */ 1713 /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */ 1714 request_st * const h2r = &con->request; 1715 if (r->h2_swin < 0) return; 1716 if (h2r->h2_swin < 0) return; 1717 if ((int32_t)dlen > r->h2_swin) dlen = (uint32_t)r->h2_swin; 1718 if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin; 1719 if (0 == dlen) return; 1720 r->h2_swin -= (int32_t)dlen; 1721 h2r->h2_swin -= (int32_t)dlen; 1722 1723 /* XXX: future: should have an interface which processes chunkqueue 1724 * and takes string refs to mmap FILE_CHUNK to avoid extra copying 1725 * since the result is likely to be consumed by TLS modules */ 1726 1727 h2con * const h2c = con->h2; 1728 const uint32_t fsize = h2c->s_max_frame_size; 1729 do { 1730 const uint32_t len = dlen < fsize ? dlen : fsize; 1731 dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/ 1732 dataframe.c[4] = (len >> 8) & 0xFF; 1733 dataframe.c[5] = (len ) & 0xFF; 1734 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/ 1735 (const char *)dataframe.c+3, sizeof(dataframe)-3); 1736 chunkqueue_steal(con->write_queue, cq, (off_t)dlen); 1737 dlen -= len; 1738 } while (dlen); 1739 } 1740 1741 1742 static void 1743 h2_send_end_stream_data (request_st * const r, connection * const con) 1744 { 1745 union { 1746 uint8_t c[12]; 1747 uint32_t u[3]; /*(alignment)*/ 1748 } dataframe = { { /*(big-endian numbers)*/ 1749 0x00, 0x00, 0x00 /* padding for alignment; do not send */ 1750 /* DATA */ 1751 ,0x00, 0x00, 0x00 /* frame length */ 1752 ,H2_FTYPE_DATA /* frame type */ 1753 ,H2_FLAG_END_STREAM /* frame flags */ 1754 ,0x00, 0x00, 0x00, 0x00 /* stream identifier (fill in below) */ 1755 } }; 1756 1757 dataframe.u[2] = htonl(r->h2id); 1758 r->h2state = H2_STATE_CLOSED; 1759 /*(ignore window updates when sending 0-length DATA frame with END_STREAM)*/ 1760 chunkqueue_append_mem(con->write_queue, /*(+3 to skip over align pad)*/ 1761 (const char *)dataframe.c+3, sizeof(dataframe)-3); 1762 } 1763 1764 1765 void 1766 h2_send_end_stream (request_st * const r, connection * const con) 1767 { 1768 if (r->state != CON_STATE_ERROR && r->resp_body_finished) { 1769 /* CON_STATE_RESPONSE_END */ 1770 if (r->gw_dechunk && r->gw_dechunk->done 1771 && !buffer_is_empty(&r->gw_dechunk->b)) 1772 h2_send_end_stream_trailers(r, con, &r->gw_dechunk->b); 1773 else 1774 h2_send_end_stream_data(r, con); 1775 } 1776 else { /* CON_STATE_ERROR */ 1777 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR); 1778 } 1779 } 1780 1781 1782 /* 1783 * (XXX: might move below to separate file) 1784 */ 1785 #include "base64.h" 1786 #include "chunk.h" 1787 #include "plugin.h" 1788 #include "plugin_config.h" 1789 #include "reqpool.h" 1790 1791 1792 static request_st * 1793 h2_init_stream (request_st * const h2r, connection * const con) 1794 { 1795 h2con * const h2c = con->h2; 1796 ++con->request_count; 1797 force_assert(h2c->rused < sizeof(h2c->r)/sizeof(*h2c->r)); 1798 /* initialize stream as subrequest (request_st *) */ 1799 request_st * const r = calloc(1, sizeof(request_st)); 1800 force_assert(r); 1801 /* XXX: TODO: assign default priority, etc. 1802 * Perhaps store stream id and priority in separate table */ 1803 h2c->r[h2c->rused++] = r; 1804 server * const srv = con->srv; 1805 request_init(r, con, srv); 1806 r->h2_rwin = h2c->s_initial_window_size; 1807 r->h2_swin = h2c->s_initial_window_size; 1808 r->http_version = HTTP_VERSION_2; 1809 1810 /* copy config state from h2r */ 1811 const uint32_t used = srv->config_context->used; 1812 r->conditional_is_valid = h2r->conditional_is_valid; 1813 memcpy(r->cond_cache, h2r->cond_cache, used * sizeof(cond_cache_t)); 1814 #ifdef HAVE_PCRE_H 1815 if (used > 1) /*(save 128b per con if no conditions)*/ 1816 memcpy(r->cond_match, h2r->cond_match, used * sizeof(cond_match_t)); 1817 #endif 1818 r->server_name = h2r->server_name; 1819 memcpy(&r->conf, &h2r->conf, sizeof(request_config)); 1820 1821 /* stream id must be assigned by caller */ 1822 return r; 1823 } 1824 1825 1826 static void 1827 h2_release_stream (request_st * const r, connection * const con) 1828 { 1829 if (r->http_status) { 1830 /* (see comment in connection_handle_response_end_state()) */ 1831 plugins_call_handle_request_done(r); 1832 1833 #if 0 1834 /* (fuzzy accounting for mod_accesslog, mod_rrdtool to avoid 1835 * double counting, but HTTP/2 framing and HPACK-encoded headers in 1836 * con->read_queue and con->write_queue are not equivalent to the 1837 * HPACK-decoded headers and request and response bodies in stream 1838 * r->read_queue and r->write_queue) */ 1839 /* DISABLED since mismatches invalidate the relationship between 1840 * con->bytes_in and con->bytes_out */ 1841 con->read_queue->bytes_in -= r->read_queue->bytes_in; 1842 con->write_queue->bytes_out -= r->write_queue->bytes_out; 1843 #else 1844 UNUSED(con); 1845 #endif 1846 } 1847 1848 request_reset(r); 1849 /* future: might keep a pool of reusable (request_st *) */ 1850 request_free(r); 1851 free(r); 1852 } 1853 1854 1855 void 1856 h2_retire_stream (request_st *r, connection * const con) 1857 { 1858 if (r == NULL) return; /*(should not happen)*/ 1859 h2con * const h2c = con->h2; 1860 request_st ** const ar = h2c->r; 1861 for (uint32_t i = 0, j = 0, rused = h2c->rused; i < rused; ++i) { 1862 if (ar[i] != r) 1863 ar[j++] = ar[i]; 1864 else { 1865 h2_release_stream(r, con); 1866 r = NULL; 1867 } 1868 } 1869 if (r == NULL) /* found */ 1870 h2c->r[--h2c->rused] = NULL; 1871 /*else ... should not happen*/ 1872 } 1873 1874 1875 void 1876 h2_retire_con (request_st * const h2r, connection * const con) 1877 { 1878 h2con * const h2c = con->h2; 1879 if (NULL == h2c) return; 1880 1881 if (h2r->state != CON_STATE_ERROR) { /*(CON_STATE_RESPONSE_END)*/ 1882 h2_send_goaway(con, H2_E_NO_ERROR); 1883 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 1884 /*(unexpected if CON_STATE_RESPONSE_END)*/ 1885 request_st * const r = h2c->r[i]; 1886 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR); 1887 h2_release_stream(r, con); 1888 } 1889 if (!chunkqueue_is_empty(con->write_queue)) { 1890 /* similar to connection_handle_write() but without error checks, 1891 * without MAX_WRITE_LIMIT, and without connection throttling */ 1892 /*h2r->conf.bytes_per_second = 0;*/ /* disable rate limit */ 1893 /*h2r->conf.global_bytes_per_second = 0;*/ /* disable rate limit */ 1894 /*con->traffic_limit_reached = 0;*/ 1895 chunkqueue * const cq = con->write_queue; 1896 const off_t len = chunkqueue_length(cq); 1897 off_t written = cq->bytes_out; 1898 con->network_write(con, cq, len); 1899 /*(optional accounting)*/ 1900 written = cq->bytes_out - written; 1901 con->bytes_written += written; 1902 con->bytes_written_cur_second += written; 1903 if (h2r->conf.global_bytes_per_second_cnt_ptr) 1904 *(h2r->conf.global_bytes_per_second_cnt_ptr) += written; 1905 } 1906 } 1907 else { /* CON_STATE_ERROR */ 1908 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) { 1909 request_st * const r = h2c->r[i]; 1910 h2_release_stream(r, con); 1911 } 1912 /* XXX: perhaps attempt to send GOAWAY? Not when CON_STATE_ERROR */ 1913 } 1914 1915 con->h2 = NULL; 1916 1917 /* future: might keep a pool of reusable (h2con *) */ 1918 free(h2c); 1919 } 1920 1921 1922 static void 1923 h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings) 1924 { 1925 /* status: (h2r->state == CON_STATE_REQUEST_END) for Upgrade: h2c */ 1926 1927 /* HTTP/1.1 101 Switching Protocols 1928 * Connection: Upgrade 1929 * Upgrade: h2c 1930 */ 1931 #if 1 1932 static const char switch_proto[] = "HTTP/1.1 101 Switching Protocols\r\n" 1933 "Connection: Upgrade\r\n" 1934 "Upgrade: h2c\r\n\r\n"; 1935 chunkqueue_append_mem(h2r->write_queue, 1936 CONST_STR_LEN(switch_proto)); 1937 h2r->resp_header_len = sizeof(switch_proto)-1; 1938 #else 1939 h2r->http_status = 101; 1940 http_header_response_set(h2r, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"), 1941 CONST_STR_LEN("h2c")); 1942 http_response_write_header(h2r); 1943 http_response_reset(h2r); 1944 h2r->http_status = 0; 1945 #endif 1946 1947 connection * const con = h2r->con; 1948 h2_init_con(h2r, con, http2_settings); 1949 if (con->h2->sent_goaway) return; 1950 1951 con->h2->h2_cid = 1; /* stream id 1 is assigned to h2c upgrade */ 1952 1953 /* copy request state from &con->request to subrequest r 1954 * XXX: would be nice if there were a cleaner way to do this 1955 * (This is fragile and must be kept in-sync with request_st in request.h)*/ 1956 1957 request_st * const r = h2_init_stream(h2r, con); 1958 /*(undo double-count; already incremented in CON_STATE_REQUEST_START)*/ 1959 --con->request_count; 1960 r->state = h2r->state; /* CON_STATE_REQUEST_END */ 1961 r->http_status = 0; 1962 r->http_method = h2r->http_method; 1963 r->h2state = H2_STATE_HALF_CLOSED_REMOTE; 1964 r->h2id = 1; 1965 r->rqst_htags = h2r->rqst_htags; 1966 h2r->rqst_htags = 0; 1967 r->rqst_header_len = h2r->rqst_header_len; 1968 h2r->rqst_header_len = 0; 1969 r->rqst_headers = h2r->rqst_headers; /* copy struct */ 1970 memset(&h2r->rqst_headers, 0, sizeof(array)); 1971 r->uri = h2r->uri; /* copy struct */ 1972 #if 0 1973 r->physical = h2r->physical; /* copy struct */ 1974 r->env = h2r->env; /* copy struct */ 1975 #endif 1976 memset(&h2r->rqst_headers, 0, sizeof(array)); 1977 memset(&h2r->uri, 0, sizeof(request_uri)); 1978 #if 0 1979 memset(&h2r->physical, 0, sizeof(physical)); 1980 memset(&h2r->env, 0, sizeof(array)); 1981 #endif 1982 #if 0 /* expect empty request body */ 1983 r->reqbody_length = h2r->reqbody_length; /* currently always 0 */ 1984 r->te_chunked = h2r->te_chunked; /* must be 0 */ 1985 swap(r->reqbody_queue, h2r->reqbody_queue); /*currently always empty queue*/ 1986 #endif 1987 r->http_host = h2r->http_host; 1988 h2r->http_host = NULL; 1989 #if 0 1990 r->server_name = h2r->server_name; 1991 h2r->server_name = NULL; 1992 #endif 1993 r->target = h2r->target; /* copy struct */ 1994 r->target_orig = h2r->target_orig; /* copy struct */ 1995 #if 0 1996 r->pathinfo = h2r->pathinfo; /* copy struct */ 1997 r->server_name_buf = h2r->server_name_buf; /* copy struct */ 1998 #endif 1999 memset(&h2r->target, 0, sizeof(buffer)); 2000 memset(&h2r->target_orig, 0, sizeof(buffer)); 2001 #if 0 2002 memset(&h2r->pathinfo, 0, sizeof(buffer)); 2003 memset(&h2r->server_name_buf, 0, sizeof(buffer)); 2004 #endif 2005 #if 0 2006 /* skip copying response structures, other state not yet modified in h2r */ 2007 /* r write_queue and read_queue are intentionally separate from h2r */ 2008 /* r->gw_dechunk must be NULL for HTTP/2 */ 2009 /* bytes_written_ckpt and bytes_read_ckpt are for HTTP/1.1 */ 2010 /* error handlers have not yet been set */ 2011 #endif 2012 #if 0 2013 r->loops_per_request = h2r->loops_per_request; 2014 r->async_callback = h2r->async_callback; 2015 #endif 2016 r->keep_alive = h2r->keep_alive; 2017 r->tmp_buf = h2r->tmp_buf; /* shared; same as srv->tmp_buf */ 2018 r->start_hp = h2r->start_hp; /* copy struct */ 2019 r->start_ts = h2r->start_ts; 2020 2021 /* Note: HTTP/1.1 101 Switching Protocols is not immediately written to 2022 * the network here. As this is called from cleartext Upgrade: h2c, 2023 * we choose to delay sending the status until the beginning of the response 2024 * to the HTTP/1.1 request which included Upgrade: h2c */ 2025 } 2026 2027 2028 int 2029 h2_check_con_upgrade_h2c (request_st * const r) 2030 { 2031 /* RFC7540 3.2 Starting HTTP/2 for "http" URIs */ 2032 2033 buffer *http_connection, *http2_settings; 2034 buffer *upgrade = http_header_request_get(r, HTTP_HEADER_UPGRADE, 2035 CONST_STR_LEN("Upgrade")); 2036 if (NULL == upgrade) return 0; 2037 http_connection = http_header_request_get(r, HTTP_HEADER_CONNECTION, 2038 CONST_STR_LEN("Connection")); 2039 if (NULL == http_connection) { 2040 http_header_request_unset(r, HTTP_HEADER_UPGRADE, 2041 CONST_STR_LEN("Upgrade")); 2042 return 0; 2043 } 2044 if (r->http_version != HTTP_VERSION_1_1) { 2045 http_header_request_unset(r, HTTP_HEADER_UPGRADE, 2046 CONST_STR_LEN("Upgrade")); 2047 http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade")); 2048 return 0; 2049 } 2050 2051 if (!http_header_str_contains_token(CONST_BUF_LEN(upgrade), 2052 CONST_STR_LEN("h2c"))) 2053 return 0; 2054 2055 http2_settings = http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS, 2056 CONST_STR_LEN("HTTP2-Settings")); 2057 if (NULL != http2_settings) { 2058 if (0 == r->reqbody_length) { 2059 buffer * const b = r->tmp_buf; 2060 buffer_clear(b); 2061 if (r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/ 2062 && 2063 http_header_str_contains_token(CONST_BUF_LEN(http_connection), 2064 CONST_STR_LEN("HTTP2-Settings")) 2065 && buffer_append_base64_decode(b, CONST_BUF_LEN(http2_settings), 2066 BASE64_URL)) { 2067 h2_con_upgrade_h2c(r, b); 2068 r->http_version = HTTP_VERSION_2; 2069 } /* else ignore if invalid base64 */ 2070 } 2071 else { 2072 /* ignore Upgrade: h2c if request body present since we do not 2073 * (currently) handle request body before transition to h2c */ 2074 /* RFC7540 3.2 Requests that contain a payload body MUST be sent 2075 * in their entirety before the client can send HTTP/2 frames. */ 2076 } 2077 http_header_request_unset(r, HTTP_HEADER_HTTP2_SETTINGS, 2078 CONST_STR_LEN("HTTP2-Settings")); 2079 http_header_remove_token(http_connection, CONST_STR_LEN("HTTP2-Settings")); 2080 } /* else ignore Upgrade: h2c; HTTP2-Settings required for Upgrade: h2c */ 2081 http_header_request_unset(r, HTTP_HEADER_UPGRADE, 2082 CONST_STR_LEN("Upgrade")); 2083 http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade")); 2084 return (r->http_version == HTTP_VERSION_2); 2085 } 2086