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