1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_router.h> 8 #include <nxt_http.h> 9 #include <nxt_upstream.h> 10 #include <nxt_h1proto.h> 11 #include <nxt_websocket.h> 12 #include <nxt_websocket_header.h> 13 14 15 /* 16 * nxt_http_conn_ and nxt_h1p_conn_ prefixes are used for connection handlers. 17 * nxt_h1p_idle_ prefix is used for idle connection handlers. 18 * nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods. 19 */ 20 21 #if (NXT_TLS) 22 static ssize_t nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c); 23 static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data); 24 #endif 25 static ssize_t nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c); 26 static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data); 27 static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data); 28 static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, 29 void *data); 30 static nxt_int_t nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, 31 nxt_http_request_t *r); 32 static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, 33 nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf); 34 static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, 35 uintptr_t data); 36 static nxt_int_t nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, 37 uintptr_t data); 38 static nxt_int_t nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, 39 uintptr_t data); 40 static nxt_int_t nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, 41 uintptr_t data); 42 static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, 43 uintptr_t data); 44 static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r); 45 static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, 46 void *data); 47 static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r); 48 static void nxt_h1p_request_header_send(nxt_task_t *task, 49 nxt_http_request_t *r, nxt_work_handler_t body_handler, void *data); 50 static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, 51 nxt_buf_t *out); 52 static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, 53 nxt_buf_t *out); 54 static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, 55 nxt_http_proto_t proto); 56 static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 57 nxt_buf_t *last); 58 static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data); 59 static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, 60 void *data); 61 static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, 62 void *data); 63 nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p, 64 nxt_http_request_t *r); 65 static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 66 nxt_socket_conf_joint_t *joint); 67 static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data); 68 static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data); 69 static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data); 70 static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data); 71 static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, 72 nxt_conn_t *c); 73 static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data); 74 static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data); 75 static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c); 76 static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data); 77 static void nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, 78 void *data); 79 static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, 80 void *data); 81 static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c, 82 uintptr_t data); 83 static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c); 84 static void nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c); 85 static void nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data); 86 static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data); 87 static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data); 88 89 static void nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer); 90 static void nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data); 91 static void nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data); 92 static void nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer); 93 static void nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data); 94 static void nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer); 95 static ssize_t nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c); 96 static void nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, 97 void *data); 98 static nxt_int_t nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, 99 nxt_buf_mem_t *bm); 100 static void nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer); 101 static void nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data); 102 static void nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, nxt_buf_t *out); 103 static void nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data); 104 static void nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data); 105 static void nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data); 106 static void nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data); 107 static nxt_msec_t nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data); 108 static void nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer); 109 static void nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data); 110 static nxt_int_t nxt_h1p_peer_transfer_encoding(void *ctx, 111 nxt_http_field_t *field, uintptr_t data); 112 113 #if (NXT_TLS) 114 static const nxt_conn_state_t nxt_http_idle_state; 115 static const nxt_conn_state_t nxt_h1p_shutdown_state; 116 #endif 117 static const nxt_conn_state_t nxt_h1p_idle_state; 118 static const nxt_conn_state_t nxt_h1p_header_parse_state; 119 static const nxt_conn_state_t nxt_h1p_read_body_state; 120 static const nxt_conn_state_t nxt_h1p_request_send_state; 121 static const nxt_conn_state_t nxt_h1p_timeout_response_state; 122 static const nxt_conn_state_t nxt_h1p_keepalive_state; 123 static const nxt_conn_state_t nxt_h1p_close_state; 124 static const nxt_conn_state_t nxt_h1p_peer_connect_state; 125 static const nxt_conn_state_t nxt_h1p_peer_header_send_state; 126 static const nxt_conn_state_t nxt_h1p_peer_header_body_send_state; 127 static const nxt_conn_state_t nxt_h1p_peer_header_read_state; 128 static const nxt_conn_state_t nxt_h1p_peer_header_read_timer_state; 129 static const nxt_conn_state_t nxt_h1p_peer_read_state; 130 static const nxt_conn_state_t nxt_h1p_peer_close_state; 131 132 133 const nxt_http_proto_table_t nxt_http_proto[3] = { 134 /* NXT_HTTP_PROTO_H1 */ 135 { 136 .body_read = nxt_h1p_request_body_read, 137 .local_addr = nxt_h1p_request_local_addr, 138 .header_send = nxt_h1p_request_header_send, 139 .send = nxt_h1p_request_send, 140 .body_bytes_sent = nxt_h1p_request_body_bytes_sent, 141 .discard = nxt_h1p_request_discard, 142 .close = nxt_h1p_request_close, 143 144 .peer_connect = nxt_h1p_peer_connect, 145 .peer_header_send = nxt_h1p_peer_header_send, 146 .peer_header_read = nxt_h1p_peer_header_read, 147 .peer_read = nxt_h1p_peer_read, 148 .peer_close = nxt_h1p_peer_close, 149 150 .ws_frame_start = nxt_h1p_websocket_frame_start, 151 }, 152 /* NXT_HTTP_PROTO_H2 */ 153 /* NXT_HTTP_PROTO_DEVNULL */ 154 }; 155 156 157 static nxt_lvlhsh_t nxt_h1p_fields_hash; 158 159 static nxt_http_field_proc_t nxt_h1p_fields[] = { 160 { nxt_string("Connection"), &nxt_h1p_connection, 0 }, 161 { nxt_string("Upgrade"), &nxt_h1p_upgrade, 0 }, 162 { nxt_string("Sec-WebSocket-Key"), &nxt_h1p_websocket_key, 0 }, 163 { nxt_string("Sec-WebSocket-Version"), 164 &nxt_h1p_websocket_version, 0 }, 165 { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 }, 166 167 { nxt_string("Host"), &nxt_http_request_host, 0 }, 168 { nxt_string("Cookie"), &nxt_http_request_field, 169 offsetof(nxt_http_request_t, cookie) }, 170 { nxt_string("Referer"), &nxt_http_request_field, 171 offsetof(nxt_http_request_t, referer) }, 172 { nxt_string("User-Agent"), &nxt_http_request_field, 173 offsetof(nxt_http_request_t, user_agent) }, 174 { nxt_string("Content-Type"), &nxt_http_request_field, 175 offsetof(nxt_http_request_t, content_type) }, 176 { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, 177 }; 178 179 180 static nxt_lvlhsh_t nxt_h1p_peer_fields_hash; 181 182 static nxt_http_field_proc_t nxt_h1p_peer_fields[] = { 183 { nxt_string("Connection"), &nxt_http_proxy_skip, 0 }, 184 { nxt_string("Transfer-Encoding"), &nxt_h1p_peer_transfer_encoding, 0 }, 185 { nxt_string("Server"), &nxt_http_proxy_skip, 0 }, 186 { nxt_string("Date"), &nxt_http_proxy_date, 0 }, 187 { nxt_string("Content-Length"), &nxt_http_proxy_content_length, 0 }, 188 }; 189 190 191 nxt_int_t 192 nxt_h1p_init(nxt_task_t *task) 193 { 194 nxt_int_t ret; 195 196 ret = nxt_http_fields_hash(&nxt_h1p_fields_hash, 197 nxt_h1p_fields, nxt_nitems(nxt_h1p_fields)); 198 199 if (nxt_fast_path(ret == NXT_OK)) { 200 ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash, 201 nxt_h1p_peer_fields, 202 nxt_nitems(nxt_h1p_peer_fields)); 203 } 204 205 return ret; 206 } 207 208 209 void 210 nxt_http_conn_init(nxt_task_t *task, void *obj, void *data) 211 { 212 nxt_conn_t *c; 213 nxt_socket_conf_t *skcf; 214 nxt_event_engine_t *engine; 215 nxt_listen_event_t *lev; 216 nxt_socket_conf_joint_t *joint; 217 218 c = obj; 219 lev = data; 220 221 nxt_debug(task, "http conn init"); 222 223 joint = lev->socket.data; 224 skcf = joint->socket_conf; 225 c->local = skcf->sockaddr; 226 227 engine = task->thread->engine; 228 c->read_work_queue = &engine->fast_work_queue; 229 c->write_work_queue = &engine->fast_work_queue; 230 231 c->read_state = &nxt_h1p_idle_state; 232 233 #if (NXT_TLS) 234 if (skcf->tls != NULL) { 235 c->read_state = &nxt_http_idle_state; 236 } 237 #endif 238 239 nxt_conn_read(engine, c); 240 } 241 242 243 #if (NXT_TLS) 244 245 static const nxt_conn_state_t nxt_http_idle_state 246 nxt_aligned(64) = 247 { 248 .ready_handler = nxt_http_conn_test, 249 .close_handler = nxt_h1p_conn_close, 250 .error_handler = nxt_h1p_conn_error, 251 252 .io_read_handler = nxt_http_idle_io_read_handler, 253 254 .timer_handler = nxt_h1p_idle_timeout, 255 .timer_value = nxt_h1p_conn_timer_value, 256 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 257 }; 258 259 260 static ssize_t 261 nxt_http_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) 262 { 263 size_t size; 264 ssize_t n; 265 nxt_buf_t *b; 266 nxt_socket_conf_joint_t *joint; 267 268 joint = c->listen->socket.data; 269 270 if (nxt_slow_path(joint == NULL)) { 271 /* 272 * Listening socket had been closed while 273 * connection was in keep-alive state. 274 */ 275 c->read_state = &nxt_h1p_idle_close_state; 276 return 0; 277 } 278 279 size = joint->socket_conf->header_buffer_size; 280 281 b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); 282 if (nxt_slow_path(b == NULL)) { 283 c->socket.error = NXT_ENOMEM; 284 return NXT_ERROR; 285 } 286 287 /* 288 * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP. 289 * 11 bytes are enough to log supported SSLv3/TLS version. 290 * 16 bytes are just for more optimized kernel copy-out operation. 291 */ 292 n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK); 293 294 if (n > 0) { 295 c->read = b; 296 297 } else { 298 c->read = NULL; 299 nxt_event_engine_buf_mem_free(task->thread->engine, b); 300 } 301 302 return n; 303 } 304 305 306 static void 307 nxt_http_conn_test(nxt_task_t *task, void *obj, void *data) 308 { 309 u_char *p; 310 nxt_buf_t *b; 311 nxt_conn_t *c; 312 nxt_tls_conf_t *tls; 313 nxt_event_engine_t *engine; 314 nxt_socket_conf_joint_t *joint; 315 316 c = obj; 317 318 nxt_debug(task, "h1p conn https test"); 319 320 engine = task->thread->engine; 321 b = c->read; 322 p = b->mem.pos; 323 324 c->read_state = &nxt_h1p_idle_state; 325 326 if (p[0] != 0x16) { 327 b->mem.free = b->mem.pos; 328 329 nxt_conn_read(engine, c); 330 return; 331 } 332 333 /* SSLv3/TLS ClientHello message. */ 334 335 #if (NXT_DEBUG) 336 if (nxt_buf_mem_used_size(&b->mem) >= 11) { 337 u_char major, minor; 338 const char *protocol; 339 340 major = p[9]; 341 minor = p[10]; 342 343 if (major == 3) { 344 if (minor == 0) { 345 protocol = "SSLv"; 346 347 } else { 348 protocol = "TLSv"; 349 major -= 2; 350 minor -= 1; 351 } 352 353 nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor); 354 } 355 } 356 #endif 357 358 c->read = NULL; 359 nxt_event_engine_buf_mem_free(engine, b); 360 361 joint = c->listen->socket.data; 362 363 if (nxt_slow_path(joint == NULL)) { 364 /* 365 * Listening socket had been closed while 366 * connection was in keep-alive state. 367 */ 368 nxt_h1p_closing(task, c); 369 return; 370 } 371 372 tls = joint->socket_conf->tls; 373 374 tls->conn_init(task, tls, c); 375 } 376 377 #endif 378 379 380 static const nxt_conn_state_t nxt_h1p_idle_state 381 nxt_aligned(64) = 382 { 383 .ready_handler = nxt_h1p_conn_proto_init, 384 .close_handler = nxt_h1p_conn_close, 385 .error_handler = nxt_h1p_conn_error, 386 387 .io_read_handler = nxt_h1p_idle_io_read_handler, 388 389 .timer_handler = nxt_h1p_idle_timeout, 390 .timer_value = nxt_h1p_conn_timer_value, 391 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 392 .timer_autoreset = 1, 393 }; 394 395 396 static ssize_t 397 nxt_h1p_idle_io_read_handler(nxt_task_t *task, nxt_conn_t *c) 398 { 399 size_t size; 400 ssize_t n; 401 nxt_buf_t *b; 402 nxt_socket_conf_joint_t *joint; 403 404 joint = c->listen->socket.data; 405 406 if (nxt_slow_path(joint == NULL)) { 407 /* 408 * Listening socket had been closed while 409 * connection was in keep-alive state. 410 */ 411 c->read_state = &nxt_h1p_idle_close_state; 412 return 0; 413 } 414 415 b = c->read; 416 417 if (b == NULL) { 418 size = joint->socket_conf->header_buffer_size; 419 420 b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); 421 if (nxt_slow_path(b == NULL)) { 422 c->socket.error = NXT_ENOMEM; 423 return NXT_ERROR; 424 } 425 } 426 427 n = c->io->recvbuf(c, b); 428 429 if (n > 0) { 430 c->read = b; 431 432 } else { 433 c->read = NULL; 434 nxt_event_engine_buf_mem_free(task->thread->engine, b); 435 } 436 437 return n; 438 } 439 440 441 static void 442 nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data) 443 { 444 nxt_conn_t *c; 445 nxt_h1proto_t *h1p; 446 447 c = obj; 448 449 nxt_debug(task, "h1p conn proto init"); 450 451 h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t)); 452 if (nxt_slow_path(h1p == NULL)) { 453 nxt_h1p_closing(task, c); 454 return; 455 } 456 457 c->socket.data = h1p; 458 h1p->conn = c; 459 460 nxt_h1p_conn_request_init(task, c, h1p); 461 } 462 463 464 static void 465 nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) 466 { 467 nxt_int_t ret; 468 nxt_conn_t *c; 469 nxt_h1proto_t *h1p; 470 nxt_http_request_t *r; 471 nxt_socket_conf_joint_t *joint; 472 473 c = obj; 474 h1p = data; 475 476 nxt_debug(task, "h1p conn request init"); 477 478 nxt_queue_remove(&c->link); 479 480 r = nxt_http_request_create(task); 481 482 if (nxt_fast_path(r != NULL)) { 483 h1p->request = r; 484 r->proto.h1 = h1p; 485 486 /* r->protocol = NXT_HTTP_PROTO_H1 is done by zeroing. */ 487 r->remote = c->remote; 488 489 #if (NXT_TLS) 490 r->tls = c->u.tls; 491 #endif 492 493 r->task = c->task; 494 task = &r->task; 495 c->socket.task = task; 496 c->read_timer.task = task; 497 c->write_timer.task = task; 498 499 ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); 500 501 if (nxt_fast_path(ret == NXT_OK)) { 502 joint = c->listen->socket.data; 503 joint->count++; 504 505 r->conf = joint; 506 507 if (c->local == NULL) { 508 c->local = joint->socket_conf->sockaddr; 509 } 510 511 nxt_h1p_conn_request_header_parse(task, c, h1p); 512 return; 513 } 514 515 /* 516 * The request is very incomplete here, 517 * so "internal server error" useless here. 518 */ 519 nxt_mp_release(r->mem_pool); 520 } 521 522 nxt_h1p_closing(task, c); 523 } 524 525 526 static const nxt_conn_state_t nxt_h1p_header_parse_state 527 nxt_aligned(64) = 528 { 529 .ready_handler = nxt_h1p_conn_request_header_parse, 530 .close_handler = nxt_h1p_conn_request_error, 531 .error_handler = nxt_h1p_conn_request_error, 532 533 .timer_handler = nxt_h1p_conn_request_timeout, 534 .timer_value = nxt_h1p_conn_request_timer_value, 535 .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 536 }; 537 538 539 static void 540 nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, void *data) 541 { 542 nxt_int_t ret; 543 nxt_conn_t *c; 544 nxt_h1proto_t *h1p; 545 nxt_http_status_t status; 546 nxt_http_request_t *r; 547 548 c = obj; 549 h1p = data; 550 551 nxt_debug(task, "h1p conn header parse"); 552 553 ret = nxt_http_parse_request(&h1p->parser, &c->read->mem); 554 555 ret = nxt_expect(NXT_DONE, ret); 556 557 if (ret != NXT_AGAIN) { 558 nxt_timer_disable(task->thread->engine, &c->read_timer); 559 } 560 561 r = h1p->request; 562 563 switch (ret) { 564 565 case NXT_DONE: 566 /* 567 * By default the keepalive mode is disabled in HTTP/1.0 and 568 * enabled in HTTP/1.1. The mode can be overridden later by 569 * the "Connection" field processed in nxt_h1p_connection(). 570 */ 571 h1p->keepalive = (h1p->parser.version.s.minor != '0'); 572 573 ret = nxt_h1p_header_process(task, h1p, r); 574 575 if (nxt_fast_path(ret == NXT_OK)) { 576 577 #if (NXT_TLS) 578 if (c->u.tls == NULL && r->conf->socket_conf->tls != NULL) { 579 status = NXT_HTTP_TO_HTTPS; 580 goto error; 581 } 582 #endif 583 584 r->state->ready_handler(task, r, NULL); 585 return; 586 } 587 588 status = ret; 589 goto error; 590 591 case NXT_AGAIN: 592 status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf); 593 594 if (nxt_fast_path(status == NXT_OK)) { 595 c->read_state = &nxt_h1p_header_parse_state; 596 597 nxt_conn_read(task->thread->engine, c); 598 return; 599 } 600 601 break; 602 603 case NXT_HTTP_PARSE_INVALID: 604 status = NXT_HTTP_BAD_REQUEST; 605 break; 606 607 case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: 608 status = NXT_HTTP_VERSION_NOT_SUPPORTED; 609 break; 610 611 case NXT_HTTP_PARSE_TOO_LARGE_FIELD: 612 status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 613 break; 614 615 default: 616 case NXT_ERROR: 617 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 618 break; 619 } 620 621 (void) nxt_h1p_header_process(task, h1p, r); 622 623 error: 624 625 h1p->keepalive = 0; 626 627 nxt_http_request_error(task, r, status); 628 } 629 630 631 static nxt_int_t 632 nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, 633 nxt_http_request_t *r) 634 { 635 u_char *m; 636 nxt_int_t ret; 637 638 r->target.start = h1p->parser.target_start; 639 r->target.length = h1p->parser.target_end - h1p->parser.target_start; 640 641 if (h1p->parser.version.ui64 != 0) { 642 r->version.start = h1p->parser.version.str; 643 r->version.length = sizeof(h1p->parser.version.str); 644 } 645 646 r->method = &h1p->parser.method; 647 r->path = &h1p->parser.path; 648 r->args = &h1p->parser.args; 649 650 r->fields = h1p->parser.fields; 651 652 ret = nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r); 653 if (nxt_slow_path(ret != NXT_OK)) { 654 return ret; 655 } 656 657 if (h1p->connection_upgrade && h1p->upgrade_websocket) { 658 m = h1p->parser.method.start; 659 660 if (nxt_slow_path(h1p->parser.method.length != 3 661 || m[0] != 'G' 662 || m[1] != 'E' 663 || m[2] != 'T')) 664 { 665 nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad method"); 666 667 return NXT_HTTP_BAD_REQUEST; 668 } 669 670 if (nxt_slow_path(h1p->parser.version.s.minor != '1')) { 671 nxt_log(task, NXT_LOG_INFO, "h1p upgrade: bad protocol version"); 672 673 return NXT_HTTP_BAD_REQUEST; 674 } 675 676 if (nxt_slow_path(h1p->websocket_key == NULL)) { 677 nxt_log(task, NXT_LOG_INFO, 678 "h1p upgrade: bad or absent websocket key"); 679 680 return NXT_HTTP_BAD_REQUEST; 681 } 682 683 if (nxt_slow_path(h1p->websocket_version_ok == 0)) { 684 nxt_log(task, NXT_LOG_INFO, 685 "h1p upgrade: bad or absent websocket version"); 686 687 return NXT_HTTP_UPGRADE_REQUIRED; 688 } 689 690 r->websocket_handshake = 1; 691 } 692 693 return ret; 694 } 695 696 697 static nxt_int_t 698 nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c, 699 nxt_socket_conf_t *skcf) 700 { 701 size_t size, used; 702 nxt_buf_t *in, *b; 703 704 in = c->read; 705 706 if (nxt_buf_mem_free_size(&in->mem) == 0) { 707 size = skcf->large_header_buffer_size; 708 used = nxt_buf_mem_used_size(&in->mem); 709 710 if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { 711 return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 712 } 713 714 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 715 if (nxt_slow_path(b == NULL)) { 716 return NXT_HTTP_INTERNAL_SERVER_ERROR; 717 } 718 719 b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); 720 721 in->next = h1p->buffers; 722 h1p->buffers = in; 723 h1p->nbuffers++; 724 725 c->read = b; 726 } 727 728 return NXT_OK; 729 } 730 731 732 static nxt_int_t 733 nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data) 734 { 735 nxt_http_request_t *r; 736 737 r = ctx; 738 field->hopbyhop = 1; 739 740 if (field->value_length == 5 741 && nxt_memcasecmp(field->value, "close", 5) == 0) 742 { 743 r->proto.h1->keepalive = 0; 744 745 } else if (field->value_length == 10 746 && nxt_memcasecmp(field->value, "keep-alive", 10) == 0) 747 { 748 r->proto.h1->keepalive = 1; 749 750 } else if (field->value_length == 7 751 && nxt_memcasecmp(field->value, "upgrade", 7) == 0) 752 { 753 r->proto.h1->connection_upgrade = 1; 754 } 755 756 return NXT_OK; 757 } 758 759 760 static nxt_int_t 761 nxt_h1p_upgrade(void *ctx, nxt_http_field_t *field, uintptr_t data) 762 { 763 nxt_http_request_t *r; 764 765 r = ctx; 766 767 if (field->value_length == 9 768 && nxt_memcasecmp(field->value, "websocket", 9) == 0) 769 { 770 r->proto.h1->upgrade_websocket = 1; 771 } 772 773 return NXT_OK; 774 } 775 776 777 static nxt_int_t 778 nxt_h1p_websocket_key(void *ctx, nxt_http_field_t *field, uintptr_t data) 779 { 780 nxt_http_request_t *r; 781 782 r = ctx; 783 784 if (field->value_length == 24) { 785 r->proto.h1->websocket_key = field; 786 } 787 788 return NXT_OK; 789 } 790 791 792 static nxt_int_t 793 nxt_h1p_websocket_version(void *ctx, nxt_http_field_t *field, uintptr_t data) 794 { 795 nxt_http_request_t *r; 796 797 r = ctx; 798 799 if (field->value_length == 2 800 && field->value[0] == '1' && field->value[1] == '3') 801 { 802 r->proto.h1->websocket_version_ok = 1; 803 } 804 805 return NXT_OK; 806 } 807 808 809 static nxt_int_t 810 nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) 811 { 812 nxt_http_te_t te; 813 nxt_http_request_t *r; 814 815 r = ctx; 816 field->skip = 1; 817 field->hopbyhop = 1; 818 819 if (field->value_length == 7 820 && nxt_memcmp(field->value, "chunked", 7) == 0) 821 { 822 te = NXT_HTTP_TE_CHUNKED; 823 824 } else { 825 te = NXT_HTTP_TE_UNSUPPORTED; 826 } 827 828 r->proto.h1->transfer_encoding = te; 829 830 return NXT_OK; 831 } 832 833 834 static void 835 nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r) 836 { 837 size_t size, body_length, body_buffer_size, body_rest; 838 ssize_t res; 839 nxt_str_t *tmp_path, tmp_name; 840 nxt_buf_t *in, *b; 841 nxt_conn_t *c; 842 nxt_h1proto_t *h1p; 843 nxt_http_status_t status; 844 845 static const nxt_str_t tmp_name_pattern = nxt_string("/req-XXXXXXXX"); 846 847 h1p = r->proto.h1; 848 849 nxt_debug(task, "h1p request body read %O te:%d", 850 r->content_length_n, h1p->transfer_encoding); 851 852 switch (h1p->transfer_encoding) { 853 854 case NXT_HTTP_TE_CHUNKED: 855 status = NXT_HTTP_LENGTH_REQUIRED; 856 goto error; 857 858 case NXT_HTTP_TE_UNSUPPORTED: 859 status = NXT_HTTP_NOT_IMPLEMENTED; 860 goto error; 861 862 default: 863 case NXT_HTTP_TE_NONE: 864 break; 865 } 866 867 if (r->content_length_n == -1 || r->content_length_n == 0) { 868 goto ready; 869 } 870 871 body_length = (size_t) r->content_length_n; 872 873 body_buffer_size = nxt_min(r->conf->socket_conf->body_buffer_size, 874 body_length); 875 876 if (body_length > body_buffer_size) { 877 tmp_path = &r->conf->socket_conf->body_temp_path; 878 879 tmp_name.length = tmp_path->length + tmp_name_pattern.length; 880 881 b = nxt_buf_file_alloc(r->mem_pool, 882 body_buffer_size + sizeof(nxt_file_t) 883 + tmp_name.length + 1, 0); 884 885 } else { 886 /* This initialization required for CentOS 6, gcc 4.4.7. */ 887 tmp_path = NULL; 888 tmp_name.length = 0; 889 890 b = nxt_buf_mem_alloc(r->mem_pool, body_buffer_size, 0); 891 } 892 893 if (nxt_slow_path(b == NULL)) { 894 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 895 goto error; 896 } 897 898 r->body = b; 899 900 if (body_length > body_buffer_size) { 901 tmp_name.start = nxt_pointer_to(b->mem.start, sizeof(nxt_file_t)); 902 903 memcpy(tmp_name.start, tmp_path->start, tmp_path->length); 904 memcpy(tmp_name.start + tmp_path->length, tmp_name_pattern.start, 905 tmp_name_pattern.length); 906 tmp_name.start[tmp_name.length] = '\0'; 907 908 b->file = (nxt_file_t *) b->mem.start; 909 nxt_memzero(b->file, sizeof(nxt_file_t)); 910 b->file->fd = -1; 911 b->file->size = body_length; 912 913 b->mem.start += sizeof(nxt_file_t) + tmp_name.length + 1; 914 b->mem.pos = b->mem.start; 915 b->mem.free = b->mem.start; 916 917 b->file->fd = mkstemp((char *) tmp_name.start); 918 if (nxt_slow_path(b->file->fd == -1)) { 919 nxt_alert(task, "mkstemp(%s) failed %E", tmp_name.start, nxt_errno); 920 921 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 922 goto error; 923 } 924 925 nxt_debug(task, "create body tmp file \"%V\", %d", 926 &tmp_name, b->file->fd); 927 928 unlink((char *) tmp_name.start); 929 } 930 931 body_rest = body_length; 932 933 in = h1p->conn->read; 934 935 size = nxt_buf_mem_used_size(&in->mem); 936 937 if (size != 0) { 938 size = nxt_min(size, body_length); 939 940 if (nxt_buf_is_file(b)) { 941 res = nxt_fd_write(b->file->fd, in->mem.pos, size); 942 if (nxt_slow_path(res < (ssize_t) size)) { 943 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 944 goto error; 945 } 946 947 b->file_end += size; 948 949 } else { 950 size = nxt_min(body_buffer_size, size); 951 b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size); 952 body_buffer_size -= size; 953 } 954 955 in->mem.pos += size; 956 body_rest -= size; 957 } 958 959 nxt_debug(task, "h1p body rest: %uz", body_rest); 960 961 if (body_rest != 0) { 962 in->next = h1p->buffers; 963 h1p->buffers = in; 964 h1p->nbuffers++; 965 966 c = h1p->conn; 967 c->read = b; 968 c->read_state = &nxt_h1p_read_body_state; 969 970 nxt_conn_read(task->thread->engine, c); 971 return; 972 } 973 974 if (nxt_buf_is_file(b)) { 975 b->mem.start = NULL; 976 b->mem.end = NULL; 977 b->mem.pos = NULL; 978 b->mem.free = NULL; 979 } 980 981 ready: 982 983 r->state->ready_handler(task, r, NULL); 984 985 return; 986 987 error: 988 989 h1p->keepalive = 0; 990 991 nxt_http_request_error(task, r, status); 992 } 993 994 995 static const nxt_conn_state_t nxt_h1p_read_body_state 996 nxt_aligned(64) = 997 { 998 .ready_handler = nxt_h1p_conn_request_body_read, 999 .close_handler = nxt_h1p_conn_request_error, 1000 .error_handler = nxt_h1p_conn_request_error, 1001 1002 .timer_handler = nxt_h1p_conn_request_timeout, 1003 .timer_value = nxt_h1p_conn_request_timer_value, 1004 .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout), 1005 .timer_autoreset = 1, 1006 }; 1007 1008 1009 static void 1010 nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data) 1011 { 1012 size_t size, body_rest; 1013 ssize_t res; 1014 nxt_buf_t *b; 1015 nxt_conn_t *c; 1016 nxt_h1proto_t *h1p; 1017 nxt_http_request_t *r; 1018 nxt_event_engine_t *engine; 1019 1020 c = obj; 1021 h1p = data; 1022 1023 nxt_debug(task, "h1p conn request body read"); 1024 1025 r = h1p->request; 1026 1027 engine = task->thread->engine; 1028 1029 b = c->read; 1030 1031 if (nxt_buf_is_file(b)) { 1032 body_rest = b->file->size - b->file_end; 1033 1034 size = nxt_buf_mem_used_size(&b->mem); 1035 size = nxt_min(size, body_rest); 1036 1037 res = nxt_fd_write(b->file->fd, b->mem.pos, size); 1038 if (nxt_slow_path(res < (ssize_t) size)) { 1039 nxt_h1p_request_error(task, h1p, r); 1040 return; 1041 } 1042 1043 b->file_end += size; 1044 body_rest -= res; 1045 1046 b->mem.pos += size; 1047 1048 if (b->mem.pos == b->mem.free) { 1049 if (body_rest >= (size_t) nxt_buf_mem_size(&b->mem)) { 1050 b->mem.free = b->mem.start; 1051 1052 } else { 1053 /* This required to avoid reading next request. */ 1054 b->mem.free = b->mem.end - body_rest; 1055 } 1056 1057 b->mem.pos = b->mem.free; 1058 } 1059 1060 } else { 1061 body_rest = nxt_buf_mem_free_size(&c->read->mem); 1062 } 1063 1064 nxt_debug(task, "h1p body rest: %uz", body_rest); 1065 1066 if (body_rest != 0) { 1067 nxt_conn_read(engine, c); 1068 1069 } else { 1070 if (nxt_buf_is_file(b)) { 1071 b->mem.start = NULL; 1072 b->mem.end = NULL; 1073 b->mem.pos = NULL; 1074 b->mem.free = NULL; 1075 } 1076 1077 c->read = NULL; 1078 1079 r->state->ready_handler(task, r, NULL); 1080 } 1081 } 1082 1083 1084 static void 1085 nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r) 1086 { 1087 r->local = nxt_conn_local_addr(task, r->proto.h1->conn); 1088 } 1089 1090 1091 #define NXT_HTTP_LAST_INFORMATIONAL \ 1092 (NXT_HTTP_CONTINUE + nxt_nitems(nxt_http_informational) - 1) 1093 1094 static const nxt_str_t nxt_http_informational[] = { 1095 nxt_string("HTTP/1.1 100 Continue\r\n"), 1096 nxt_string("HTTP/1.1 101 Switching Protocols\r\n"), 1097 }; 1098 1099 1100 #define NXT_HTTP_LAST_SUCCESS \ 1101 (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1) 1102 1103 static const nxt_str_t nxt_http_success[] = { 1104 nxt_string("HTTP/1.1 200 OK\r\n"), 1105 nxt_string("HTTP/1.1 201 Created\r\n"), 1106 nxt_string("HTTP/1.1 202 Accepted\r\n"), 1107 nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"), 1108 nxt_string("HTTP/1.1 204 No Content\r\n"), 1109 nxt_string("HTTP/1.1 205 Reset Content\r\n"), 1110 nxt_string("HTTP/1.1 206 Partial Content\r\n"), 1111 }; 1112 1113 1114 #define NXT_HTTP_LAST_REDIRECTION \ 1115 (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1) 1116 1117 static const nxt_str_t nxt_http_redirection[] = { 1118 nxt_string("HTTP/1.1 300 Multiple Choices\r\n"), 1119 nxt_string("HTTP/1.1 301 Moved Permanently\r\n"), 1120 nxt_string("HTTP/1.1 302 Found\r\n"), 1121 nxt_string("HTTP/1.1 303 See Other\r\n"), 1122 nxt_string("HTTP/1.1 304 Not Modified\r\n"), 1123 nxt_string("HTTP/1.1 307 Temporary Redirect\r\n"), 1124 nxt_string("HTTP/1.1 308 Permanent Redirect\r\n"), 1125 }; 1126 1127 1128 #define NXT_HTTP_LAST_CLIENT_ERROR \ 1129 (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1) 1130 1131 static const nxt_str_t nxt_http_client_error[] = { 1132 nxt_string("HTTP/1.1 400 Bad Request\r\n"), 1133 nxt_string("HTTP/1.1 401 Unauthorized\r\n"), 1134 nxt_string("HTTP/1.1 402 Payment Required\r\n"), 1135 nxt_string("HTTP/1.1 403 Forbidden\r\n"), 1136 nxt_string("HTTP/1.1 404 Not Found\r\n"), 1137 nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"), 1138 nxt_string("HTTP/1.1 406 Not Acceptable\r\n"), 1139 nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"), 1140 nxt_string("HTTP/1.1 408 Request Timeout\r\n"), 1141 nxt_string("HTTP/1.1 409 Conflict\r\n"), 1142 nxt_string("HTTP/1.1 410 Gone\r\n"), 1143 nxt_string("HTTP/1.1 411 Length Required\r\n"), 1144 nxt_string("HTTP/1.1 412 Precondition Failed\r\n"), 1145 nxt_string("HTTP/1.1 413 Payload Too Large\r\n"), 1146 nxt_string("HTTP/1.1 414 URI Too Long\r\n"), 1147 nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"), 1148 nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"), 1149 nxt_string("HTTP/1.1 417 Expectation Failed\r\n"), 1150 nxt_string("HTTP/1.1 418\r\n"), 1151 nxt_string("HTTP/1.1 419\r\n"), 1152 nxt_string("HTTP/1.1 420\r\n"), 1153 nxt_string("HTTP/1.1 421\r\n"), 1154 nxt_string("HTTP/1.1 422\r\n"), 1155 nxt_string("HTTP/1.1 423\r\n"), 1156 nxt_string("HTTP/1.1 424\r\n"), 1157 nxt_string("HTTP/1.1 425\r\n"), 1158 nxt_string("HTTP/1.1 426 Upgrade Required\r\n"), 1159 nxt_string("HTTP/1.1 427\r\n"), 1160 nxt_string("HTTP/1.1 428\r\n"), 1161 nxt_string("HTTP/1.1 429\r\n"), 1162 nxt_string("HTTP/1.1 430\r\n"), 1163 nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"), 1164 }; 1165 1166 1167 #define NXT_HTTP_LAST_NGINX_ERROR \ 1168 (NXT_HTTP_TO_HTTPS + nxt_nitems(nxt_http_nginx_error) - 1) 1169 1170 static const nxt_str_t nxt_http_nginx_error[] = { 1171 nxt_string("HTTP/1.1 400 " 1172 "The plain HTTP request was sent to HTTPS port\r\n"), 1173 }; 1174 1175 1176 #define NXT_HTTP_LAST_SERVER_ERROR \ 1177 (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1) 1178 1179 static const nxt_str_t nxt_http_server_error[] = { 1180 nxt_string("HTTP/1.1 500 Internal Server Error\r\n"), 1181 nxt_string("HTTP/1.1 501 Not Implemented\r\n"), 1182 nxt_string("HTTP/1.1 502 Bad Gateway\r\n"), 1183 nxt_string("HTTP/1.1 503 Service Unavailable\r\n"), 1184 nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"), 1185 nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"), 1186 }; 1187 1188 1189 #define UNKNOWN_STATUS_LENGTH nxt_length("HTTP/1.1 65536\r\n") 1190 1191 static void 1192 nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r, 1193 nxt_work_handler_t body_handler, void *data) 1194 { 1195 u_char *p; 1196 size_t size; 1197 nxt_buf_t *header; 1198 nxt_str_t unknown_status; 1199 nxt_int_t conn; 1200 nxt_uint_t n; 1201 nxt_bool_t http11; 1202 nxt_conn_t *c; 1203 nxt_h1proto_t *h1p; 1204 const nxt_str_t *status; 1205 nxt_http_field_t *field; 1206 u_char buf[UNKNOWN_STATUS_LENGTH]; 1207 1208 static const char chunked[] = "Transfer-Encoding: chunked\r\n"; 1209 static const char websocket_version[] = "Sec-WebSocket-Version: 13\r\n"; 1210 1211 static const nxt_str_t connection[3] = { 1212 nxt_string("Connection: close\r\n"), 1213 nxt_string("Connection: keep-alive\r\n"), 1214 nxt_string("Upgrade: websocket\r\n" 1215 "Connection: Upgrade\r\n" 1216 "Sec-WebSocket-Accept: "), 1217 }; 1218 1219 nxt_debug(task, "h1p request header send"); 1220 1221 r->header_sent = 1; 1222 h1p = r->proto.h1; 1223 n = r->status; 1224 1225 if (n >= NXT_HTTP_CONTINUE && n <= NXT_HTTP_LAST_INFORMATIONAL) { 1226 status = &nxt_http_informational[n - NXT_HTTP_CONTINUE]; 1227 1228 } else if (n >= NXT_HTTP_OK && n <= NXT_HTTP_LAST_SUCCESS) { 1229 status = &nxt_http_success[n - NXT_HTTP_OK]; 1230 1231 } else if (n >= NXT_HTTP_MULTIPLE_CHOICES 1232 && n <= NXT_HTTP_LAST_REDIRECTION) 1233 { 1234 status = &nxt_http_redirection[n - NXT_HTTP_MULTIPLE_CHOICES]; 1235 1236 } else if (n >= NXT_HTTP_BAD_REQUEST && n <= NXT_HTTP_LAST_CLIENT_ERROR) { 1237 status = &nxt_http_client_error[n - NXT_HTTP_BAD_REQUEST]; 1238 1239 } else if (n >= NXT_HTTP_TO_HTTPS && n <= NXT_HTTP_LAST_NGINX_ERROR) { 1240 status = &nxt_http_nginx_error[n - NXT_HTTP_TO_HTTPS]; 1241 1242 } else if (n >= NXT_HTTP_INTERNAL_SERVER_ERROR 1243 && n <= NXT_HTTP_LAST_SERVER_ERROR) 1244 { 1245 status = &nxt_http_server_error[n - NXT_HTTP_INTERNAL_SERVER_ERROR]; 1246 1247 } else { 1248 p = nxt_sprintf(buf, buf + UNKNOWN_STATUS_LENGTH, 1249 "HTTP/1.1 %03d\r\n", n); 1250 1251 unknown_status.length = p - buf; 1252 unknown_status.start = buf; 1253 status = &unknown_status; 1254 } 1255 1256 size = status->length; 1257 /* Trailing CRLF at the end of header. */ 1258 size += nxt_length("\r\n"); 1259 1260 conn = -1; 1261 1262 if (r->websocket_handshake && n == NXT_HTTP_SWITCHING_PROTOCOLS) { 1263 h1p->websocket = 1; 1264 h1p->keepalive = 0; 1265 conn = 2; 1266 size += NXT_WEBSOCKET_ACCEPT_SIZE + 2; 1267 1268 } else { 1269 http11 = (h1p->parser.version.s.minor != '0'); 1270 1271 if (r->resp.content_length == NULL || r->resp.content_length->skip) { 1272 1273 if (http11) { 1274 if (n != NXT_HTTP_NOT_MODIFIED 1275 && n != NXT_HTTP_NO_CONTENT 1276 && body_handler != NULL 1277 && !h1p->websocket) 1278 { 1279 h1p->chunked = 1; 1280 size += nxt_length(chunked); 1281 /* Trailing CRLF will be added by the first chunk header. */ 1282 size -= nxt_length("\r\n"); 1283 } 1284 1285 } else { 1286 h1p->keepalive = 0; 1287 } 1288 } 1289 1290 if (http11 ^ h1p->keepalive) { 1291 conn = h1p->keepalive; 1292 } 1293 } 1294 1295 if (conn >= 0) { 1296 size += connection[conn].length; 1297 } 1298 1299 nxt_list_each(field, r->resp.fields) { 1300 1301 if (!field->skip) { 1302 size += field->name_length + field->value_length; 1303 size += nxt_length(": \r\n"); 1304 } 1305 1306 } nxt_list_loop; 1307 1308 if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { 1309 size += nxt_length(websocket_version); 1310 } 1311 1312 header = nxt_http_buf_mem(task, r, size); 1313 if (nxt_slow_path(header == NULL)) { 1314 nxt_h1p_request_error(task, h1p, r); 1315 return; 1316 } 1317 1318 p = nxt_cpymem(header->mem.free, status->start, status->length); 1319 1320 nxt_list_each(field, r->resp.fields) { 1321 1322 if (!field->skip) { 1323 p = nxt_cpymem(p, field->name, field->name_length); 1324 *p++ = ':'; *p++ = ' '; 1325 p = nxt_cpymem(p, field->value, field->value_length); 1326 *p++ = '\r'; *p++ = '\n'; 1327 } 1328 1329 } nxt_list_loop; 1330 1331 if (conn >= 0) { 1332 p = nxt_cpymem(p, connection[conn].start, connection[conn].length); 1333 } 1334 1335 if (h1p->websocket) { 1336 nxt_websocket_accept(p, h1p->websocket_key->value); 1337 p += NXT_WEBSOCKET_ACCEPT_SIZE; 1338 1339 *p++ = '\r'; *p++ = '\n'; 1340 } 1341 1342 if (nxt_slow_path(n == NXT_HTTP_UPGRADE_REQUIRED)) { 1343 p = nxt_cpymem(p, websocket_version, nxt_length(websocket_version)); 1344 } 1345 1346 if (h1p->chunked) { 1347 p = nxt_cpymem(p, chunked, nxt_length(chunked)); 1348 /* Trailing CRLF will be added by the first chunk header. */ 1349 1350 } else { 1351 *p++ = '\r'; *p++ = '\n'; 1352 } 1353 1354 header->mem.free = p; 1355 1356 h1p->header_size = nxt_buf_mem_used_size(&header->mem); 1357 1358 c = h1p->conn; 1359 1360 c->write = header; 1361 h1p->conn_write_tail = &header->next; 1362 c->write_state = &nxt_h1p_request_send_state; 1363 1364 if (body_handler != NULL) { 1365 /* 1366 * The body handler will run before c->io->write() handler, 1367 * because the latter was inqueued by nxt_conn_write() 1368 * in engine->write_work_queue. 1369 */ 1370 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 1371 body_handler, task, r, data); 1372 1373 } else { 1374 header->next = nxt_http_buf_last(r); 1375 } 1376 1377 nxt_conn_write(task->thread->engine, c); 1378 1379 if (h1p->websocket) { 1380 nxt_h1p_websocket_first_frame_start(task, r, c->read); 1381 } 1382 } 1383 1384 1385 void 1386 nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_bool_t all) 1387 { 1388 size_t size; 1389 nxt_buf_t *b, *in, *next; 1390 nxt_conn_t *c; 1391 1392 nxt_debug(task, "h1p complete buffers"); 1393 1394 b = h1p->buffers; 1395 c = h1p->conn; 1396 in = c->read; 1397 1398 if (b != NULL) { 1399 if (in == NULL) { 1400 /* A request with large body. */ 1401 in = b; 1402 c->read = in; 1403 1404 b = in->next; 1405 in->next = NULL; 1406 } 1407 1408 while (b != NULL) { 1409 next = b->next; 1410 b->next = NULL; 1411 1412 b->completion_handler(task, b, b->parent); 1413 1414 b = next; 1415 } 1416 1417 h1p->buffers = NULL; 1418 h1p->nbuffers = 0; 1419 } 1420 1421 if (in != NULL) { 1422 size = nxt_buf_mem_used_size(&in->mem); 1423 1424 if (size == 0 || all) { 1425 in->completion_handler(task, in, in->parent); 1426 1427 c->read = NULL; 1428 } 1429 } 1430 } 1431 1432 1433 static const nxt_conn_state_t nxt_h1p_request_send_state 1434 nxt_aligned(64) = 1435 { 1436 .ready_handler = nxt_h1p_conn_sent, 1437 .error_handler = nxt_h1p_conn_request_error, 1438 1439 .timer_handler = nxt_h1p_conn_request_send_timeout, 1440 .timer_value = nxt_h1p_conn_request_timer_value, 1441 .timer_data = offsetof(nxt_socket_conf_t, send_timeout), 1442 .timer_autoreset = 1, 1443 }; 1444 1445 1446 static void 1447 nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out) 1448 { 1449 nxt_conn_t *c; 1450 nxt_h1proto_t *h1p; 1451 1452 nxt_debug(task, "h1p request send"); 1453 1454 h1p = r->proto.h1; 1455 c = h1p->conn; 1456 1457 if (h1p->chunked) { 1458 out = nxt_h1p_chunk_create(task, r, out); 1459 if (nxt_slow_path(out == NULL)) { 1460 nxt_h1p_request_error(task, h1p, r); 1461 return; 1462 } 1463 } 1464 1465 if (c->write == NULL) { 1466 c->write = out; 1467 c->write_state = &nxt_h1p_request_send_state; 1468 1469 nxt_conn_write(task->thread->engine, c); 1470 1471 } else { 1472 *h1p->conn_write_tail = out; 1473 } 1474 1475 while (out->next != NULL) { 1476 out = out->next; 1477 } 1478 1479 h1p->conn_write_tail = &out->next; 1480 } 1481 1482 1483 static nxt_buf_t * 1484 nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out) 1485 { 1486 nxt_off_t size; 1487 nxt_buf_t *b, **prev, *header, *tail; 1488 1489 const size_t chunk_size = 2 * nxt_length("\r\n") + NXT_OFF_T_HEXLEN; 1490 static const char tail_chunk[] = "\r\n0\r\n\r\n"; 1491 1492 size = 0; 1493 prev = &out; 1494 1495 for (b = out; b != NULL; b = b->next) { 1496 1497 if (nxt_buf_is_last(b)) { 1498 tail = nxt_http_buf_mem(task, r, sizeof(tail_chunk)); 1499 if (nxt_slow_path(tail == NULL)) { 1500 return NULL; 1501 } 1502 1503 *prev = tail; 1504 tail->next = b; 1505 /* 1506 * The tail_chunk size with trailing zero is 8 bytes, so 1507 * memcpy may be inlined with just single 8 byte move operation. 1508 */ 1509 nxt_memcpy(tail->mem.free, tail_chunk, sizeof(tail_chunk)); 1510 tail->mem.free += nxt_length(tail_chunk); 1511 1512 break; 1513 } 1514 1515 size += nxt_buf_used_size(b); 1516 prev = &b->next; 1517 } 1518 1519 if (size == 0) { 1520 return out; 1521 } 1522 1523 header = nxt_http_buf_mem(task, r, chunk_size); 1524 if (nxt_slow_path(header == NULL)) { 1525 return NULL; 1526 } 1527 1528 header->next = out; 1529 header->mem.free = nxt_sprintf(header->mem.free, header->mem.end, 1530 "\r\n%xO\r\n", size); 1531 return header; 1532 } 1533 1534 1535 static nxt_off_t 1536 nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto) 1537 { 1538 nxt_off_t sent; 1539 nxt_h1proto_t *h1p; 1540 1541 h1p = proto.h1; 1542 1543 sent = h1p->conn->sent - h1p->header_size; 1544 1545 return (sent > 0) ? sent : 0; 1546 } 1547 1548 1549 static void 1550 nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 1551 nxt_buf_t *last) 1552 { 1553 nxt_buf_t *b; 1554 nxt_conn_t *c; 1555 nxt_h1proto_t *h1p; 1556 nxt_work_queue_t *wq; 1557 1558 nxt_debug(task, "h1p request discard"); 1559 1560 h1p = r->proto.h1; 1561 h1p->keepalive = 0; 1562 1563 c = h1p->conn; 1564 b = c->write; 1565 c->write = NULL; 1566 1567 wq = &task->thread->engine->fast_work_queue; 1568 1569 nxt_sendbuf_drain(task, wq, b); 1570 nxt_sendbuf_drain(task, wq, last); 1571 } 1572 1573 1574 static void 1575 nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data) 1576 { 1577 nxt_h1proto_t *h1p; 1578 nxt_http_request_t *r; 1579 1580 h1p = data; 1581 1582 nxt_debug(task, "h1p conn request error"); 1583 1584 r = h1p->request; 1585 1586 if (nxt_slow_path(r == NULL)) { 1587 nxt_h1p_shutdown(task, h1p->conn); 1588 return; 1589 } 1590 1591 if (r->fields == NULL) { 1592 (void) nxt_h1p_header_process(task, h1p, r); 1593 } 1594 1595 if (r->status == 0) { 1596 r->status = NXT_HTTP_BAD_REQUEST; 1597 } 1598 1599 nxt_h1p_request_error(task, h1p, r); 1600 } 1601 1602 1603 static void 1604 nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data) 1605 { 1606 nxt_conn_t *c; 1607 nxt_timer_t *timer; 1608 nxt_h1proto_t *h1p; 1609 nxt_http_request_t *r; 1610 1611 timer = obj; 1612 1613 nxt_debug(task, "h1p conn request timeout"); 1614 1615 c = nxt_read_timer_conn(timer); 1616 c->block_read = 1; 1617 /* 1618 * Disable SO_LINGER off during socket closing 1619 * to send "408 Request Timeout" error response. 1620 */ 1621 c->socket.timedout = 0; 1622 1623 h1p = c->socket.data; 1624 h1p->keepalive = 0; 1625 r = h1p->request; 1626 1627 if (r->fields == NULL) { 1628 (void) nxt_h1p_header_process(task, h1p, r); 1629 } 1630 1631 nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT); 1632 } 1633 1634 1635 static void 1636 nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data) 1637 { 1638 nxt_conn_t *c; 1639 nxt_timer_t *timer; 1640 nxt_h1proto_t *h1p; 1641 1642 timer = obj; 1643 1644 nxt_debug(task, "h1p conn request send timeout"); 1645 1646 c = nxt_write_timer_conn(timer); 1647 c->block_write = 1; 1648 h1p = c->socket.data; 1649 1650 nxt_h1p_request_error(task, h1p, h1p->request); 1651 } 1652 1653 1654 nxt_msec_t 1655 nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data) 1656 { 1657 nxt_h1proto_t *h1p; 1658 1659 h1p = c->socket.data; 1660 1661 return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data); 1662 } 1663 1664 1665 nxt_inline void 1666 nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p, 1667 nxt_http_request_t *r) 1668 { 1669 h1p->keepalive = 0; 1670 1671 r->state->error_handler(task, r, h1p); 1672 } 1673 1674 1675 static void 1676 nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 1677 nxt_socket_conf_joint_t *joint) 1678 { 1679 nxt_conn_t *c; 1680 nxt_h1proto_t *h1p; 1681 1682 nxt_debug(task, "h1p request close"); 1683 1684 h1p = proto.h1; 1685 h1p->keepalive &= !h1p->request->inconsistent; 1686 h1p->request = NULL; 1687 1688 nxt_router_conf_release(task, joint); 1689 1690 c = h1p->conn; 1691 task = &c->task; 1692 c->socket.task = task; 1693 c->read_timer.task = task; 1694 c->write_timer.task = task; 1695 1696 if (h1p->keepalive) { 1697 nxt_h1p_keepalive(task, h1p, c); 1698 1699 } else { 1700 nxt_h1p_shutdown(task, c); 1701 } 1702 } 1703 1704 1705 static void 1706 nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data) 1707 { 1708 nxt_conn_t *c; 1709 nxt_event_engine_t *engine; 1710 1711 c = obj; 1712 1713 nxt_debug(task, "h1p conn sent"); 1714 1715 engine = task->thread->engine; 1716 1717 c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); 1718 1719 if (c->write != NULL) { 1720 nxt_conn_write(engine, c); 1721 } 1722 } 1723 1724 1725 static void 1726 nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) 1727 { 1728 nxt_conn_t *c; 1729 1730 c = obj; 1731 1732 nxt_debug(task, "h1p conn close"); 1733 1734 nxt_queue_remove(&c->link); 1735 1736 nxt_h1p_shutdown(task, c); 1737 } 1738 1739 1740 static void 1741 nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) 1742 { 1743 nxt_conn_t *c; 1744 1745 c = obj; 1746 1747 nxt_debug(task, "h1p conn error"); 1748 1749 nxt_queue_remove(&c->link); 1750 1751 nxt_h1p_shutdown(task, c); 1752 } 1753 1754 1755 static nxt_msec_t 1756 nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data) 1757 { 1758 nxt_socket_conf_joint_t *joint; 1759 1760 joint = c->listen->socket.data; 1761 1762 if (nxt_fast_path(joint != NULL)) { 1763 return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 1764 } 1765 1766 /* 1767 * Listening socket had been closed while 1768 * connection was in keep-alive state. 1769 */ 1770 return 1; 1771 } 1772 1773 1774 static void 1775 nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) 1776 { 1777 size_t size; 1778 nxt_buf_t *in; 1779 nxt_event_engine_t *engine; 1780 1781 nxt_debug(task, "h1p keepalive"); 1782 1783 if (!c->tcp_nodelay) { 1784 nxt_conn_tcp_nodelay_on(task, c); 1785 } 1786 1787 nxt_h1p_complete_buffers(task, h1p, 0); 1788 1789 in = c->read; 1790 1791 nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); 1792 1793 c->sent = 0; 1794 1795 engine = task->thread->engine; 1796 nxt_queue_insert_head(&engine->idle_connections, &c->link); 1797 1798 if (in == NULL) { 1799 c->read_state = &nxt_h1p_keepalive_state; 1800 1801 nxt_conn_read(engine, c); 1802 1803 } else { 1804 size = nxt_buf_mem_used_size(&in->mem); 1805 1806 nxt_debug(task, "h1p pipelining"); 1807 1808 nxt_memmove(in->mem.start, in->mem.pos, size); 1809 1810 in->mem.pos = in->mem.start; 1811 in->mem.free = in->mem.start + size; 1812 1813 nxt_h1p_conn_request_init(task, c, c->socket.data); 1814 } 1815 } 1816 1817 1818 static const nxt_conn_state_t nxt_h1p_keepalive_state 1819 nxt_aligned(64) = 1820 { 1821 .ready_handler = nxt_h1p_conn_request_init, 1822 .close_handler = nxt_h1p_conn_close, 1823 .error_handler = nxt_h1p_conn_error, 1824 1825 .io_read_handler = nxt_h1p_idle_io_read_handler, 1826 1827 .timer_handler = nxt_h1p_idle_timeout, 1828 .timer_value = nxt_h1p_conn_timer_value, 1829 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 1830 .timer_autoreset = 1, 1831 }; 1832 1833 1834 const nxt_conn_state_t nxt_h1p_idle_close_state 1835 nxt_aligned(64) = 1836 { 1837 .close_handler = nxt_h1p_idle_close, 1838 }; 1839 1840 1841 static void 1842 nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) 1843 { 1844 nxt_conn_t *c; 1845 1846 c = obj; 1847 1848 nxt_debug(task, "h1p idle close"); 1849 1850 nxt_queue_remove(&c->link); 1851 1852 nxt_h1p_idle_response(task, c); 1853 } 1854 1855 1856 static void 1857 nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) 1858 { 1859 nxt_conn_t *c; 1860 nxt_timer_t *timer; 1861 1862 timer = obj; 1863 1864 nxt_debug(task, "h1p idle timeout"); 1865 1866 c = nxt_read_timer_conn(timer); 1867 c->block_read = 1; 1868 1869 nxt_queue_remove(&c->link); 1870 1871 nxt_h1p_idle_response(task, c); 1872 } 1873 1874 1875 #define NXT_H1P_IDLE_TIMEOUT \ 1876 "HTTP/1.1 408 Request Timeout\r\n" \ 1877 "Server: " NXT_SERVER "\r\n" \ 1878 "Connection: close\r\n" \ 1879 "Content-Length: 0\r\n" \ 1880 "Date: " 1881 1882 1883 static void 1884 nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c) 1885 { 1886 u_char *p; 1887 size_t size; 1888 nxt_buf_t *out, *last; 1889 1890 size = nxt_length(NXT_H1P_IDLE_TIMEOUT) 1891 + nxt_http_date_cache.size 1892 + nxt_length("\r\n\r\n"); 1893 1894 out = nxt_buf_mem_alloc(c->mem_pool, size, 0); 1895 if (nxt_slow_path(out == NULL)) { 1896 goto fail; 1897 } 1898 1899 p = nxt_cpymem(out->mem.free, NXT_H1P_IDLE_TIMEOUT, 1900 nxt_length(NXT_H1P_IDLE_TIMEOUT)); 1901 1902 p = nxt_thread_time_string(task->thread, &nxt_http_date_cache, p); 1903 1904 out->mem.free = nxt_cpymem(p, "\r\n\r\n", 4); 1905 1906 last = nxt_mp_zget(c->mem_pool, NXT_BUF_SYNC_SIZE); 1907 if (nxt_slow_path(last == NULL)) { 1908 goto fail; 1909 } 1910 1911 out->next = last; 1912 nxt_buf_set_sync(last); 1913 nxt_buf_set_last(last); 1914 1915 last->completion_handler = nxt_h1p_idle_response_sent; 1916 last->parent = c; 1917 1918 c->write = out; 1919 c->write_state = &nxt_h1p_timeout_response_state; 1920 1921 nxt_conn_write(task->thread->engine, c); 1922 return; 1923 1924 fail: 1925 1926 nxt_h1p_shutdown(task, c); 1927 } 1928 1929 1930 static const nxt_conn_state_t nxt_h1p_timeout_response_state 1931 nxt_aligned(64) = 1932 { 1933 .ready_handler = nxt_h1p_conn_sent, 1934 .error_handler = nxt_h1p_idle_response_error, 1935 1936 .timer_handler = nxt_h1p_idle_response_timeout, 1937 .timer_value = nxt_h1p_idle_response_timer_value, 1938 }; 1939 1940 1941 static void 1942 nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data) 1943 { 1944 nxt_conn_t *c; 1945 1946 c = data; 1947 1948 nxt_debug(task, "h1p idle timeout response sent"); 1949 1950 nxt_h1p_shutdown(task, c); 1951 } 1952 1953 1954 static void 1955 nxt_h1p_idle_response_error(nxt_task_t *task, void *obj, void *data) 1956 { 1957 nxt_conn_t *c; 1958 1959 c = obj; 1960 1961 nxt_debug(task, "h1p response error"); 1962 1963 nxt_h1p_shutdown(task, c); 1964 } 1965 1966 1967 static void 1968 nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data) 1969 { 1970 nxt_conn_t *c; 1971 nxt_timer_t *timer; 1972 1973 timer = obj; 1974 1975 nxt_debug(task, "h1p idle timeout response timeout"); 1976 1977 c = nxt_read_timer_conn(timer); 1978 c->block_write = 1; 1979 1980 nxt_h1p_shutdown(task, c); 1981 } 1982 1983 1984 static nxt_msec_t 1985 nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data) 1986 { 1987 return 10 * 1000; 1988 } 1989 1990 1991 static void 1992 nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c) 1993 { 1994 nxt_timer_t *timer; 1995 nxt_h1proto_t *h1p; 1996 1997 nxt_debug(task, "h1p shutdown"); 1998 1999 h1p = c->socket.data; 2000 2001 if (h1p != NULL) { 2002 nxt_h1p_complete_buffers(task, h1p, 1); 2003 2004 if (nxt_slow_path(h1p->websocket_timer != NULL)) { 2005 timer = &h1p->websocket_timer->timer; 2006 2007 if (timer->handler != nxt_h1p_conn_ws_shutdown) { 2008 timer->handler = nxt_h1p_conn_ws_shutdown; 2009 nxt_timer_add(task->thread->engine, timer, 0); 2010 2011 } else { 2012 nxt_debug(task, "h1p already scheduled ws shutdown"); 2013 } 2014 2015 return; 2016 } 2017 } 2018 2019 nxt_h1p_closing(task, c); 2020 } 2021 2022 2023 static void 2024 nxt_h1p_conn_ws_shutdown(nxt_task_t *task, void *obj, void *data) 2025 { 2026 nxt_timer_t *timer; 2027 nxt_h1p_websocket_timer_t *ws_timer; 2028 2029 nxt_debug(task, "h1p conn ws shutdown"); 2030 2031 timer = obj; 2032 ws_timer = nxt_timer_data(timer, nxt_h1p_websocket_timer_t, timer); 2033 2034 nxt_h1p_closing(task, ws_timer->h1p->conn); 2035 } 2036 2037 2038 static void 2039 nxt_h1p_closing(nxt_task_t *task, nxt_conn_t *c) 2040 { 2041 nxt_debug(task, "h1p closing"); 2042 2043 c->socket.data = NULL; 2044 2045 #if (NXT_TLS) 2046 2047 if (c->u.tls != NULL) { 2048 c->write_state = &nxt_h1p_shutdown_state; 2049 2050 c->io->shutdown(task, c, NULL); 2051 return; 2052 } 2053 2054 #endif 2055 2056 nxt_h1p_conn_closing(task, c, NULL); 2057 } 2058 2059 2060 #if (NXT_TLS) 2061 2062 static const nxt_conn_state_t nxt_h1p_shutdown_state 2063 nxt_aligned(64) = 2064 { 2065 .ready_handler = nxt_h1p_conn_closing, 2066 .close_handler = nxt_h1p_conn_closing, 2067 .error_handler = nxt_h1p_conn_closing, 2068 }; 2069 2070 #endif 2071 2072 2073 static void 2074 nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data) 2075 { 2076 nxt_conn_t *c; 2077 2078 c = obj; 2079 2080 nxt_debug(task, "h1p conn closing"); 2081 2082 c->write_state = &nxt_h1p_close_state; 2083 2084 nxt_conn_close(task->thread->engine, c); 2085 } 2086 2087 2088 static const nxt_conn_state_t nxt_h1p_close_state 2089 nxt_aligned(64) = 2090 { 2091 .ready_handler = nxt_h1p_conn_free, 2092 }; 2093 2094 2095 static void 2096 nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data) 2097 { 2098 nxt_conn_t *c; 2099 nxt_listen_event_t *lev; 2100 nxt_event_engine_t *engine; 2101 2102 c = obj; 2103 2104 nxt_debug(task, "h1p conn free"); 2105 2106 engine = task->thread->engine; 2107 2108 nxt_sockaddr_cache_free(engine, c); 2109 2110 lev = c->listen; 2111 2112 nxt_conn_free(task, c); 2113 2114 nxt_router_listen_event_release(&engine->task, lev, NULL); 2115 } 2116 2117 2118 static void 2119 nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer) 2120 { 2121 nxt_mp_t *mp; 2122 nxt_int_t ret; 2123 nxt_conn_t *c, *client; 2124 nxt_h1proto_t *h1p; 2125 nxt_fd_event_t *socket; 2126 nxt_work_queue_t *wq; 2127 nxt_http_request_t *r; 2128 2129 nxt_debug(task, "h1p peer connect"); 2130 2131 peer->status = NXT_HTTP_UNSET; 2132 r = peer->request; 2133 2134 mp = nxt_mp_create(1024, 128, 256, 32); 2135 2136 if (nxt_slow_path(mp == NULL)) { 2137 goto fail; 2138 } 2139 2140 h1p = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t)); 2141 if (nxt_slow_path(h1p == NULL)) { 2142 goto fail; 2143 } 2144 2145 ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); 2146 if (nxt_slow_path(ret != NXT_OK)) { 2147 goto fail; 2148 } 2149 2150 c = nxt_conn_create(mp, task); 2151 if (nxt_slow_path(c == NULL)) { 2152 goto fail; 2153 } 2154 2155 c->mem_pool = mp; 2156 h1p->conn = c; 2157 2158 peer->proto.h1 = h1p; 2159 h1p->request = r; 2160 2161 c->socket.data = peer; 2162 c->remote = peer->server->sockaddr; 2163 2164 c->socket.write_ready = 1; 2165 c->write_state = &nxt_h1p_peer_connect_state; 2166 2167 /* 2168 * TODO: queues should be implemented via client proto interface. 2169 */ 2170 client = r->proto.h1->conn; 2171 2172 socket = &client->socket; 2173 wq = socket->read_work_queue; 2174 c->read_work_queue = wq; 2175 c->socket.read_work_queue = wq; 2176 c->read_timer.work_queue = wq; 2177 2178 wq = socket->write_work_queue; 2179 c->write_work_queue = wq; 2180 c->socket.write_work_queue = wq; 2181 c->write_timer.work_queue = wq; 2182 /* TODO END */ 2183 2184 nxt_conn_connect(task->thread->engine, c); 2185 2186 return; 2187 2188 fail: 2189 2190 peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; 2191 2192 r->state->error_handler(task, r, peer); 2193 } 2194 2195 2196 static const nxt_conn_state_t nxt_h1p_peer_connect_state 2197 nxt_aligned(64) = 2198 { 2199 .ready_handler = nxt_h1p_peer_connected, 2200 .close_handler = nxt_h1p_peer_refused, 2201 .error_handler = nxt_h1p_peer_error, 2202 2203 .timer_handler = nxt_h1p_peer_send_timeout, 2204 .timer_value = nxt_h1p_peer_timer_value, 2205 .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), 2206 }; 2207 2208 2209 static void 2210 nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data) 2211 { 2212 nxt_http_peer_t *peer; 2213 nxt_http_request_t *r; 2214 2215 peer = data; 2216 2217 nxt_debug(task, "h1p peer connected"); 2218 2219 r = peer->request; 2220 r->state->ready_handler(task, r, peer); 2221 } 2222 2223 2224 static void 2225 nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data) 2226 { 2227 nxt_http_peer_t *peer; 2228 nxt_http_request_t *r; 2229 2230 peer = data; 2231 2232 nxt_debug(task, "h1p peer refused"); 2233 2234 //peer->status = NXT_HTTP_SERVICE_UNAVAILABLE; 2235 peer->status = NXT_HTTP_BAD_GATEWAY; 2236 2237 r = peer->request; 2238 r->state->error_handler(task, r, peer); 2239 } 2240 2241 2242 static void 2243 nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) 2244 { 2245 u_char *p; 2246 size_t size; 2247 nxt_buf_t *header, *body; 2248 nxt_conn_t *c; 2249 nxt_http_field_t *field; 2250 nxt_http_request_t *r; 2251 2252 nxt_debug(task, "h1p peer header send"); 2253 2254 r = peer->request; 2255 2256 size = r->method->length + sizeof(" ") + r->target.length 2257 + sizeof(" HTTP/1.1\r\n") 2258 + sizeof("Connection: close\r\n") 2259 + sizeof("\r\n"); 2260 2261 nxt_list_each(field, r->fields) { 2262 2263 if (!field->hopbyhop) { 2264 size += field->name_length + field->value_length; 2265 size += nxt_length(": \r\n"); 2266 } 2267 2268 } nxt_list_loop; 2269 2270 header = nxt_http_buf_mem(task, r, size); 2271 if (nxt_slow_path(header == NULL)) { 2272 r->state->error_handler(task, r, peer); 2273 return; 2274 } 2275 2276 p = header->mem.free; 2277 2278 p = nxt_cpymem(p, r->method->start, r->method->length); 2279 *p++ = ' '; 2280 p = nxt_cpymem(p, r->target.start, r->target.length); 2281 p = nxt_cpymem(p, " HTTP/1.1\r\n", 11); 2282 p = nxt_cpymem(p, "Connection: close\r\n", 19); 2283 2284 nxt_list_each(field, r->fields) { 2285 2286 if (!field->hopbyhop) { 2287 p = nxt_cpymem(p, field->name, field->name_length); 2288 *p++ = ':'; *p++ = ' '; 2289 p = nxt_cpymem(p, field->value, field->value_length); 2290 *p++ = '\r'; *p++ = '\n'; 2291 } 2292 2293 } nxt_list_loop; 2294 2295 *p++ = '\r'; *p++ = '\n'; 2296 header->mem.free = p; 2297 size = p - header->mem.pos; 2298 2299 c = peer->proto.h1->conn; 2300 c->write = header; 2301 c->write_state = &nxt_h1p_peer_header_send_state; 2302 2303 if (r->body != NULL) { 2304 if (nxt_buf_is_file(r->body)) { 2305 body = nxt_buf_file_alloc(r->mem_pool, 0, 0); 2306 2307 } else { 2308 body = nxt_buf_mem_alloc(r->mem_pool, 0, 0); 2309 } 2310 2311 if (nxt_slow_path(body == NULL)) { 2312 r->state->error_handler(task, r, peer); 2313 return; 2314 } 2315 2316 header->next = body; 2317 2318 if (nxt_buf_is_file(r->body)) { 2319 body->file = r->body->file; 2320 body->file_end = r->body->file_end; 2321 2322 } else { 2323 body->mem = r->body->mem; 2324 } 2325 2326 size += nxt_buf_used_size(body); 2327 2328 // nxt_mp_retain(r->mem_pool); 2329 } 2330 2331 if (size > 16384) { 2332 /* Use proxy_send_timeout instead of proxy_timeout. */ 2333 c->write_state = &nxt_h1p_peer_header_body_send_state; 2334 } 2335 2336 nxt_conn_write(task->thread->engine, c); 2337 } 2338 2339 2340 static const nxt_conn_state_t nxt_h1p_peer_header_send_state 2341 nxt_aligned(64) = 2342 { 2343 .ready_handler = nxt_h1p_peer_header_sent, 2344 .error_handler = nxt_h1p_peer_error, 2345 2346 .timer_handler = nxt_h1p_peer_send_timeout, 2347 .timer_value = nxt_h1p_peer_timer_value, 2348 .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), 2349 }; 2350 2351 2352 static const nxt_conn_state_t nxt_h1p_peer_header_body_send_state 2353 nxt_aligned(64) = 2354 { 2355 .ready_handler = nxt_h1p_peer_header_sent, 2356 .error_handler = nxt_h1p_peer_error, 2357 2358 .timer_handler = nxt_h1p_peer_send_timeout, 2359 .timer_value = nxt_h1p_peer_timer_value, 2360 .timer_data = offsetof(nxt_socket_conf_t, proxy_send_timeout), 2361 .timer_autoreset = 1, 2362 }; 2363 2364 2365 static void 2366 nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data) 2367 { 2368 nxt_conn_t *c; 2369 nxt_http_peer_t *peer; 2370 nxt_http_request_t *r; 2371 nxt_event_engine_t *engine; 2372 2373 c = obj; 2374 peer = data; 2375 2376 nxt_debug(task, "h1p peer header sent"); 2377 2378 engine = task->thread->engine; 2379 2380 c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); 2381 2382 if (c->write != NULL) { 2383 nxt_conn_write(engine, c); 2384 return; 2385 } 2386 2387 r = peer->request; 2388 r->state->ready_handler(task, r, peer); 2389 } 2390 2391 2392 static void 2393 nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer) 2394 { 2395 nxt_conn_t *c; 2396 2397 nxt_debug(task, "h1p peer header read"); 2398 2399 c = peer->proto.h1->conn; 2400 2401 if (c->write_timer.enabled) { 2402 c->read_state = &nxt_h1p_peer_header_read_state; 2403 2404 } else { 2405 c->read_state = &nxt_h1p_peer_header_read_timer_state; 2406 } 2407 2408 nxt_conn_read(task->thread->engine, c); 2409 } 2410 2411 2412 static const nxt_conn_state_t nxt_h1p_peer_header_read_state 2413 nxt_aligned(64) = 2414 { 2415 .ready_handler = nxt_h1p_peer_header_read_done, 2416 .close_handler = nxt_h1p_peer_closed, 2417 .error_handler = nxt_h1p_peer_error, 2418 2419 .io_read_handler = nxt_h1p_peer_io_read_handler, 2420 }; 2421 2422 2423 static const nxt_conn_state_t nxt_h1p_peer_header_read_timer_state 2424 nxt_aligned(64) = 2425 { 2426 .ready_handler = nxt_h1p_peer_header_read_done, 2427 .close_handler = nxt_h1p_peer_closed, 2428 .error_handler = nxt_h1p_peer_error, 2429 2430 .io_read_handler = nxt_h1p_peer_io_read_handler, 2431 2432 .timer_handler = nxt_h1p_peer_read_timeout, 2433 .timer_value = nxt_h1p_peer_timer_value, 2434 .timer_data = offsetof(nxt_socket_conf_t, proxy_timeout), 2435 }; 2436 2437 2438 static ssize_t 2439 nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c) 2440 { 2441 size_t size; 2442 ssize_t n; 2443 nxt_buf_t *b; 2444 nxt_http_peer_t *peer; 2445 nxt_socket_conf_t *skcf; 2446 nxt_http_request_t *r; 2447 2448 peer = c->socket.data; 2449 r = peer->request; 2450 b = c->read; 2451 2452 if (b == NULL) { 2453 skcf = r->conf->socket_conf; 2454 2455 size = (peer->header_received) ? skcf->proxy_buffer_size 2456 : skcf->proxy_header_buffer_size; 2457 2458 nxt_debug(task, "h1p peer io read: %z", size); 2459 2460 b = nxt_http_proxy_buf_mem_alloc(task, r, size); 2461 if (nxt_slow_path(b == NULL)) { 2462 c->socket.error = NXT_ENOMEM; 2463 return NXT_ERROR; 2464 } 2465 } 2466 2467 n = c->io->recvbuf(c, b); 2468 2469 if (n > 0) { 2470 c->read = b; 2471 2472 } else { 2473 c->read = NULL; 2474 nxt_http_proxy_buf_mem_free(task, r, b); 2475 } 2476 2477 return n; 2478 } 2479 2480 2481 static void 2482 nxt_h1p_peer_header_read_done(nxt_task_t *task, void *obj, void *data) 2483 { 2484 nxt_int_t ret; 2485 nxt_buf_t *b; 2486 nxt_conn_t *c; 2487 nxt_h1proto_t *h1p; 2488 nxt_http_peer_t *peer; 2489 nxt_http_request_t *r; 2490 nxt_event_engine_t *engine; 2491 2492 c = obj; 2493 peer = data; 2494 2495 nxt_debug(task, "h1p peer header read done"); 2496 2497 b = c->read; 2498 2499 ret = nxt_h1p_peer_header_parse(peer, &b->mem); 2500 2501 r = peer->request; 2502 2503 ret = nxt_expect(NXT_DONE, ret); 2504 2505 if (ret != NXT_AGAIN) { 2506 engine = task->thread->engine; 2507 nxt_timer_disable(engine, &c->write_timer); 2508 nxt_timer_disable(engine, &c->read_timer); 2509 } 2510 2511 switch (ret) { 2512 2513 case NXT_DONE: 2514 peer->fields = peer->proto.h1->parser.fields; 2515 2516 ret = nxt_http_fields_process(peer->fields, 2517 &nxt_h1p_peer_fields_hash, r); 2518 if (nxt_slow_path(ret != NXT_OK)) { 2519 peer->status = NXT_HTTP_INTERNAL_SERVER_ERROR; 2520 break; 2521 } 2522 2523 c->read = NULL; 2524 2525 peer->header_received = 1; 2526 2527 h1p = peer->proto.h1; 2528 2529 if (h1p->chunked) { 2530 if (r->resp.content_length != NULL) { 2531 peer->status = NXT_HTTP_BAD_GATEWAY; 2532 break; 2533 } 2534 2535 h1p->chunked_parse.mem_pool = c->mem_pool; 2536 2537 } else if (r->resp.content_length_n > 0) { 2538 h1p->remainder = r->resp.content_length_n; 2539 } 2540 2541 if (nxt_buf_mem_used_size(&b->mem) != 0) { 2542 nxt_h1p_peer_body_process(task, peer, b); 2543 return; 2544 } 2545 2546 r->state->ready_handler(task, r, peer); 2547 return; 2548 2549 case NXT_AGAIN: 2550 if (nxt_buf_mem_free_size(&b->mem) != 0) { 2551 nxt_conn_read(task->thread->engine, c); 2552 return; 2553 } 2554 2555 /* Fall through. */ 2556 2557 default: 2558 case NXT_ERROR: 2559 case NXT_HTTP_PARSE_INVALID: 2560 case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: 2561 case NXT_HTTP_PARSE_TOO_LARGE_FIELD: 2562 peer->status = NXT_HTTP_BAD_GATEWAY; 2563 break; 2564 } 2565 2566 nxt_http_proxy_buf_mem_free(task, r, b); 2567 2568 r->state->error_handler(task, r, peer); 2569 } 2570 2571 2572 static nxt_int_t 2573 nxt_h1p_peer_header_parse(nxt_http_peer_t *peer, nxt_buf_mem_t *bm) 2574 { 2575 u_char *p; 2576 size_t length; 2577 nxt_int_t status; 2578 2579 if (peer->status < 0) { 2580 length = nxt_buf_mem_used_size(bm); 2581 2582 if (nxt_slow_path(length < 12)) { 2583 return NXT_AGAIN; 2584 } 2585 2586 p = bm->pos; 2587 2588 if (nxt_slow_path(nxt_memcmp(p, "HTTP/1.", 7) != 0 2589 || (p[7] != '0' && p[7] != '1'))) 2590 { 2591 return NXT_ERROR; 2592 } 2593 2594 status = nxt_int_parse(&p[9], 3); 2595 2596 if (nxt_slow_path(status < 0)) { 2597 return NXT_ERROR; 2598 } 2599 2600 p += 12; 2601 length -= 12; 2602 2603 p = nxt_memchr(p, '\n', length); 2604 2605 if (nxt_slow_path(p == NULL)) { 2606 return NXT_AGAIN; 2607 } 2608 2609 bm->pos = p + 1; 2610 peer->status = status; 2611 } 2612 2613 return nxt_http_parse_fields(&peer->proto.h1->parser, bm); 2614 } 2615 2616 2617 static void 2618 nxt_h1p_peer_read(nxt_task_t *task, nxt_http_peer_t *peer) 2619 { 2620 nxt_conn_t *c; 2621 2622 nxt_debug(task, "h1p peer read"); 2623 2624 c = peer->proto.h1->conn; 2625 c->read_state = &nxt_h1p_peer_read_state; 2626 2627 nxt_conn_read(task->thread->engine, c); 2628 } 2629 2630 2631 static const nxt_conn_state_t nxt_h1p_peer_read_state 2632 nxt_aligned(64) = 2633 { 2634 .ready_handler = nxt_h1p_peer_read_done, 2635 .close_handler = nxt_h1p_peer_closed, 2636 .error_handler = nxt_h1p_peer_error, 2637 2638 .io_read_handler = nxt_h1p_peer_io_read_handler, 2639 2640 .timer_handler = nxt_h1p_peer_read_timeout, 2641 .timer_value = nxt_h1p_peer_timer_value, 2642 .timer_data = offsetof(nxt_socket_conf_t, proxy_read_timeout), 2643 .timer_autoreset = 1, 2644 }; 2645 2646 2647 static void 2648 nxt_h1p_peer_read_done(nxt_task_t *task, void *obj, void *data) 2649 { 2650 nxt_buf_t *out; 2651 nxt_conn_t *c; 2652 nxt_http_peer_t *peer; 2653 2654 c = obj; 2655 peer = data; 2656 2657 nxt_debug(task, "h1p peer read done"); 2658 2659 out = c->read; 2660 c->read = NULL; 2661 2662 nxt_h1p_peer_body_process(task, peer, out); 2663 } 2664 2665 2666 static void 2667 nxt_h1p_peer_body_process(nxt_task_t *task, nxt_http_peer_t *peer, 2668 nxt_buf_t *out) 2669 { 2670 size_t length; 2671 nxt_h1proto_t *h1p; 2672 nxt_http_request_t *r; 2673 2674 h1p = peer->proto.h1; 2675 2676 if (h1p->chunked) { 2677 out = nxt_http_chunk_parse(task, &h1p->chunked_parse, out); 2678 2679 if (h1p->chunked_parse.chunk_error || h1p->chunked_parse.error) { 2680 peer->status = NXT_HTTP_BAD_GATEWAY; 2681 r = peer->request; 2682 r->state->error_handler(task, r, peer); 2683 return; 2684 } 2685 2686 if (h1p->chunked_parse.last) { 2687 nxt_buf_chain_add(&out, nxt_http_buf_last(peer->request)); 2688 peer->closed = 1; 2689 } 2690 2691 } else if (h1p->remainder > 0) { 2692 length = nxt_buf_chain_length(out); 2693 h1p->remainder -= length; 2694 } 2695 2696 peer->body = out; 2697 2698 r = peer->request; 2699 r->state->ready_handler(task, r, peer); 2700 } 2701 2702 2703 static void 2704 nxt_h1p_peer_closed(nxt_task_t *task, void *obj, void *data) 2705 { 2706 nxt_http_peer_t *peer; 2707 nxt_http_request_t *r; 2708 2709 peer = data; 2710 2711 nxt_debug(task, "h1p peer closed"); 2712 2713 r = peer->request; 2714 2715 if (peer->header_received) { 2716 peer->body = nxt_http_buf_last(r); 2717 peer->closed = 1; 2718 r->inconsistent = (peer->proto.h1->remainder != 0); 2719 2720 r->state->ready_handler(task, r, peer); 2721 2722 } else { 2723 peer->status = NXT_HTTP_BAD_GATEWAY; 2724 2725 r->state->error_handler(task, r, peer); 2726 } 2727 } 2728 2729 2730 static void 2731 nxt_h1p_peer_error(nxt_task_t *task, void *obj, void *data) 2732 { 2733 nxt_http_peer_t *peer; 2734 nxt_http_request_t *r; 2735 2736 peer = data; 2737 2738 nxt_debug(task, "h1p peer error"); 2739 2740 peer->status = NXT_HTTP_BAD_GATEWAY; 2741 2742 r = peer->request; 2743 r->state->error_handler(task, r, peer); 2744 } 2745 2746 2747 static void 2748 nxt_h1p_peer_send_timeout(nxt_task_t *task, void *obj, void *data) 2749 { 2750 nxt_conn_t *c; 2751 nxt_timer_t *timer; 2752 nxt_http_peer_t *peer; 2753 nxt_http_request_t *r; 2754 2755 timer = obj; 2756 2757 nxt_debug(task, "h1p peer send timeout"); 2758 2759 c = nxt_write_timer_conn(timer); 2760 c->block_write = 1; 2761 c->block_read = 1; 2762 2763 peer = c->socket.data; 2764 peer->status = NXT_HTTP_GATEWAY_TIMEOUT; 2765 2766 r = peer->request; 2767 r->state->error_handler(task, r, peer); 2768 } 2769 2770 2771 static void 2772 nxt_h1p_peer_read_timeout(nxt_task_t *task, void *obj, void *data) 2773 { 2774 nxt_conn_t *c; 2775 nxt_timer_t *timer; 2776 nxt_http_peer_t *peer; 2777 nxt_http_request_t *r; 2778 2779 timer = obj; 2780 2781 nxt_debug(task, "h1p peer read timeout"); 2782 2783 c = nxt_read_timer_conn(timer); 2784 c->block_write = 1; 2785 c->block_read = 1; 2786 2787 peer = c->socket.data; 2788 peer->status = NXT_HTTP_GATEWAY_TIMEOUT; 2789 2790 r = peer->request; 2791 r->state->error_handler(task, r, peer); 2792 } 2793 2794 2795 static nxt_msec_t 2796 nxt_h1p_peer_timer_value(nxt_conn_t *c, uintptr_t data) 2797 { 2798 nxt_http_peer_t *peer; 2799 2800 peer = c->socket.data; 2801 2802 return nxt_value_at(nxt_msec_t, peer->request->conf->socket_conf, data); 2803 } 2804 2805 2806 static void 2807 nxt_h1p_peer_close(nxt_task_t *task, nxt_http_peer_t *peer) 2808 { 2809 nxt_conn_t *c; 2810 2811 nxt_debug(task, "h1p peer close"); 2812 2813 peer->closed = 1; 2814 2815 c = peer->proto.h1->conn; 2816 task = &c->task; 2817 c->socket.task = task; 2818 c->read_timer.task = task; 2819 c->write_timer.task = task; 2820 2821 if (c->socket.fd != -1) { 2822 c->write_state = &nxt_h1p_peer_close_state; 2823 2824 nxt_conn_close(task->thread->engine, c); 2825 2826 } else { 2827 nxt_h1p_peer_free(task, c, NULL); 2828 } 2829 } 2830 2831 2832 static const nxt_conn_state_t nxt_h1p_peer_close_state 2833 nxt_aligned(64) = 2834 { 2835 .ready_handler = nxt_h1p_peer_free, 2836 }; 2837 2838 2839 static void 2840 nxt_h1p_peer_free(nxt_task_t *task, void *obj, void *data) 2841 { 2842 nxt_conn_t *c; 2843 2844 c = obj; 2845 2846 nxt_debug(task, "h1p peer free"); 2847 2848 nxt_conn_free(task, c); 2849 } 2850 2851 2852 static nxt_int_t 2853 nxt_h1p_peer_transfer_encoding(void *ctx, nxt_http_field_t *field, 2854 uintptr_t data) 2855 { 2856 nxt_http_request_t *r; 2857 2858 r = ctx; 2859 field->skip = 1; 2860 2861 if (field->value_length == 7 2862 && nxt_memcmp(field->value, "chunked", 7) == 0) 2863 { 2864 r->peer->proto.h1->chunked = 1; 2865 } 2866 2867 return NXT_OK; 2868 } 2869