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