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