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