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