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