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