120Sigor@sysoev.ru 220Sigor@sysoev.ru /* 320Sigor@sysoev.ru * Copyright (C) Igor Sysoev 420Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 520Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 620Sigor@sysoev.ru */ 720Sigor@sysoev.ru 853Sigor@sysoev.ru #include <nxt_router.h> 9115Sigor@sysoev.ru #include <nxt_conf.h> 1020Sigor@sysoev.ru 1120Sigor@sysoev.ru 12115Sigor@sysoev.ru typedef struct { 13*318Smax.romanov@nginx.com nxt_str_t type; 14*318Smax.romanov@nginx.com uint32_t workers; 15*318Smax.romanov@nginx.com nxt_msec_t timeout; 16*318Smax.romanov@nginx.com uint32_t requests; 17*318Smax.romanov@nginx.com nxt_conf_value_t *limits_value; 18133Sigor@sysoev.ru } nxt_router_app_conf_t; 19133Sigor@sysoev.ru 20133Sigor@sysoev.ru 21133Sigor@sysoev.ru typedef struct { 22133Sigor@sysoev.ru nxt_str_t application; 23115Sigor@sysoev.ru } nxt_router_listener_conf_t; 24115Sigor@sysoev.ru 25115Sigor@sysoev.ru 26167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t; 27141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t; 28141Smax.romanov@nginx.com 29141Smax.romanov@nginx.com struct nxt_start_worker_s { 30141Smax.romanov@nginx.com nxt_app_t *app; 31167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 32141Smax.romanov@nginx.com 33141Smax.romanov@nginx.com nxt_work_t work; 34141Smax.romanov@nginx.com }; 35141Smax.romanov@nginx.com 36141Smax.romanov@nginx.com 37*318Smax.romanov@nginx.com typedef struct { 38*318Smax.romanov@nginx.com uint32_t stream; 39*318Smax.romanov@nginx.com nxt_conn_t *conn; 40*318Smax.romanov@nginx.com nxt_port_t *app_port; 41*318Smax.romanov@nginx.com nxt_req_app_link_t *ra; 42*318Smax.romanov@nginx.com 43*318Smax.romanov@nginx.com nxt_queue_link_t link; /* for nxt_conn_t.requests */ 44*318Smax.romanov@nginx.com } nxt_req_conn_link_t; 45*318Smax.romanov@nginx.com 46*318Smax.romanov@nginx.com 47167Smax.romanov@nginx.com struct nxt_req_app_link_s { 48*318Smax.romanov@nginx.com uint32_t stream; 49167Smax.romanov@nginx.com nxt_port_t *app_port; 50*318Smax.romanov@nginx.com nxt_pid_t app_pid; 51167Smax.romanov@nginx.com nxt_port_t *reply_port; 52167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 53167Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 54167Smax.romanov@nginx.com 55167Smax.romanov@nginx.com nxt_queue_link_t link; /* for nxt_app_t.requests */ 56167Smax.romanov@nginx.com 57167Smax.romanov@nginx.com nxt_mp_t *mem_pool; 58167Smax.romanov@nginx.com nxt_work_t work; 59167Smax.romanov@nginx.com }; 60167Smax.romanov@nginx.com 61167Smax.romanov@nginx.com 62198Sigor@sysoev.ru typedef struct { 63198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 64198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 65198Sigor@sysoev.ru } nxt_socket_rpc_t; 66198Sigor@sysoev.ru 67198Sigor@sysoev.ru 68*318Smax.romanov@nginx.com typedef struct { 69*318Smax.romanov@nginx.com nxt_mp_t *mem_pool; 70*318Smax.romanov@nginx.com nxt_port_recv_msg_t msg; 71*318Smax.romanov@nginx.com nxt_work_t work; 72*318Smax.romanov@nginx.com } nxt_remove_pid_msg_t; 73*318Smax.romanov@nginx.com 74*318Smax.romanov@nginx.com 75*318Smax.romanov@nginx.com static void nxt_router_worker_remove_pid_handler(nxt_task_t *task, void *obj, 76*318Smax.romanov@nginx.com void *data); 77*318Smax.romanov@nginx.com static void nxt_router_worker_remove_pid_done(nxt_task_t *task, void *obj, 78*318Smax.romanov@nginx.com void *data); 79*318Smax.romanov@nginx.com 80139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 81198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 82198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 83139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 84139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 85139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 86139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 87193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 8853Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 8953Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 9053Sigor@sysoev.ru 91115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 92115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 93133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 94133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 95133Sigor@sysoev.ru nxt_str_t *name); 96198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 97198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 98198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 99198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 100198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 101198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 10265Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 10365Sigor@sysoev.ru nxt_sockaddr_t *sa); 10453Sigor@sysoev.ru 10553Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 10653Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 10753Sigor@sysoev.ru const nxt_event_interface_t *interface); 108115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 109115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 110115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 111115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 112115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 113115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 114115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 115154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 116154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 117154Sigor@sysoev.ru nxt_work_handler_t handler); 118313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 119313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 120139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 121139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 12253Sigor@sysoev.ru 12353Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 12453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 12553Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 12653Sigor@sysoev.ru nxt_event_engine_t *engine); 127133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 128133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 12953Sigor@sysoev.ru 130315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 131315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 132315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 133315Sigor@sysoev.ru nxt_work_t *jobs); 13453Sigor@sysoev.ru 13553Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 13653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 13753Sigor@sysoev.ru void *data); 13853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 13953Sigor@sysoev.ru void *data); 14053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 14153Sigor@sysoev.ru void *data); 142313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 143313Sigor@sysoev.ru void *data); 14453Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 14553Sigor@sysoev.ru void *data); 14653Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 14753Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 14853Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 14953Sigor@sysoev.ru void *data); 15053Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 15153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 15253Sigor@sysoev.ru 153167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj, 154167Smax.romanov@nginx.com void *data); 155167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app); 156*318Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t stream); 157141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj, 158141Smax.romanov@nginx.com void *data); 159141Smax.romanov@nginx.com 16053Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 16153Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 16253Sigor@sysoev.ru void *data); 163206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, 164206Smax.romanov@nginx.com void *data); 16588Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 16688Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 167141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task, 168167Smax.romanov@nginx.com nxt_req_app_link_t *ra, nxt_port_t *port); 169216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 170216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 171216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 172216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 173216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 174216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 17588Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 17653Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 17753Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 17853Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 17953Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 180*318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 18162Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 18220Sigor@sysoev.ru 183141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 184141Smax.romanov@nginx.com const char* fmt, ...); 185141Smax.romanov@nginx.com 186119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 18720Sigor@sysoev.ru 188216Sigor@sysoev.ru 189216Sigor@sysoev.ru static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = { 190216Sigor@sysoev.ru nxt_python_prepare_msg, 191216Sigor@sysoev.ru nxt_php_prepare_msg, 192216Sigor@sysoev.ru nxt_go_prepare_msg, 193216Sigor@sysoev.ru }; 194216Sigor@sysoev.ru 195216Sigor@sysoev.ru 19620Sigor@sysoev.ru nxt_int_t 197141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 19820Sigor@sysoev.ru { 199141Smax.romanov@nginx.com nxt_int_t ret; 200141Smax.romanov@nginx.com nxt_router_t *router; 201141Smax.romanov@nginx.com nxt_runtime_t *rt; 202141Smax.romanov@nginx.com 203141Smax.romanov@nginx.com rt = task->thread->runtime; 20453Sigor@sysoev.ru 20588Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 20688Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 20788Smax.romanov@nginx.com return ret; 20888Smax.romanov@nginx.com } 20988Smax.romanov@nginx.com 21053Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 21153Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 21253Sigor@sysoev.ru return NXT_ERROR; 21353Sigor@sysoev.ru } 21453Sigor@sysoev.ru 21553Sigor@sysoev.ru nxt_queue_init(&router->engines); 21653Sigor@sysoev.ru nxt_queue_init(&router->sockets); 217133Sigor@sysoev.ru nxt_queue_init(&router->apps); 21853Sigor@sysoev.ru 219119Smax.romanov@nginx.com nxt_router = router; 220119Smax.romanov@nginx.com 221115Sigor@sysoev.ru return NXT_OK; 222115Sigor@sysoev.ru } 223115Sigor@sysoev.ru 224115Sigor@sysoev.ru 225167Smax.romanov@nginx.com static nxt_start_worker_t * 226192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra) 227167Smax.romanov@nginx.com { 228240Sigor@sysoev.ru nxt_port_t *main_port; 229167Smax.romanov@nginx.com nxt_runtime_t *rt; 230167Smax.romanov@nginx.com nxt_start_worker_t *sw; 231167Smax.romanov@nginx.com 232192Smax.romanov@nginx.com sw = nxt_zalloc(sizeof(nxt_start_worker_t)); 233167Smax.romanov@nginx.com 234167Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 235167Smax.romanov@nginx.com return NULL; 236167Smax.romanov@nginx.com } 237167Smax.romanov@nginx.com 238167Smax.romanov@nginx.com sw->app = app; 239167Smax.romanov@nginx.com sw->ra = ra; 240167Smax.romanov@nginx.com 241*318Smax.romanov@nginx.com nxt_debug(task, "sw %p create, stream #%uD, app '%V' %p", sw, 242*318Smax.romanov@nginx.com ra->stream, &app->name, app); 243167Smax.romanov@nginx.com 244167Smax.romanov@nginx.com rt = task->thread->runtime; 245240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 246167Smax.romanov@nginx.com 247167Smax.romanov@nginx.com sw->work.handler = nxt_router_send_sw_request; 248240Sigor@sysoev.ru sw->work.task = &main_port->engine->task; 249167Smax.romanov@nginx.com sw->work.obj = sw; 250167Smax.romanov@nginx.com sw->work.data = task->thread->engine; 251167Smax.romanov@nginx.com sw->work.next = NULL; 252167Smax.romanov@nginx.com 253240Sigor@sysoev.ru if (task->thread->engine != main_port->engine) { 254240Sigor@sysoev.ru nxt_debug(task, "sw %p post send to main engine %p", sw, 255240Sigor@sysoev.ru main_port->engine); 256240Sigor@sysoev.ru 257240Sigor@sysoev.ru nxt_event_engine_post(main_port->engine, &sw->work); 258167Smax.romanov@nginx.com 259167Smax.romanov@nginx.com } else { 260167Smax.romanov@nginx.com nxt_router_send_sw_request(task, sw, sw->work.data); 261167Smax.romanov@nginx.com } 262167Smax.romanov@nginx.com 263167Smax.romanov@nginx.com return sw; 264167Smax.romanov@nginx.com } 265167Smax.romanov@nginx.com 266167Smax.romanov@nginx.com 267192Smax.romanov@nginx.com nxt_inline void 268192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw) 269141Smax.romanov@nginx.com { 270192Smax.romanov@nginx.com nxt_debug(task, "sw %p release", sw); 271192Smax.romanov@nginx.com 272192Smax.romanov@nginx.com nxt_free(sw); 273141Smax.romanov@nginx.com } 274141Smax.romanov@nginx.com 275141Smax.romanov@nginx.com 276*318Smax.romanov@nginx.com nxt_inline void 277*318Smax.romanov@nginx.com nxt_router_rc_unlink(nxt_req_conn_link_t *rc) 278*318Smax.romanov@nginx.com { 279*318Smax.romanov@nginx.com nxt_queue_remove(&rc->link); 280*318Smax.romanov@nginx.com 281*318Smax.romanov@nginx.com if (rc->ra != NULL) { 282*318Smax.romanov@nginx.com rc->ra->rc = NULL; 283*318Smax.romanov@nginx.com rc->ra = NULL; 284*318Smax.romanov@nginx.com } 285*318Smax.romanov@nginx.com 286*318Smax.romanov@nginx.com rc->conn = NULL; 287*318Smax.romanov@nginx.com } 288*318Smax.romanov@nginx.com 289*318Smax.romanov@nginx.com 290167Smax.romanov@nginx.com static nxt_req_app_link_t * 291167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc) 292167Smax.romanov@nginx.com { 293167Smax.romanov@nginx.com nxt_mp_t *mp; 294*318Smax.romanov@nginx.com nxt_event_engine_t *engine; 295167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 296167Smax.romanov@nginx.com 297167Smax.romanov@nginx.com mp = rc->conn->mem_pool; 298*318Smax.romanov@nginx.com engine = task->thread->engine; 299167Smax.romanov@nginx.com 300167Smax.romanov@nginx.com ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t)); 301167Smax.romanov@nginx.com 302167Smax.romanov@nginx.com if (nxt_slow_path(ra == NULL)) { 303167Smax.romanov@nginx.com return NULL; 304167Smax.romanov@nginx.com } 305167Smax.romanov@nginx.com 306*318Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD create", rc->stream); 307167Smax.romanov@nginx.com 308167Smax.romanov@nginx.com nxt_memzero(ra, sizeof(nxt_req_app_link_t)); 309167Smax.romanov@nginx.com 310*318Smax.romanov@nginx.com ra->stream = rc->stream; 311*318Smax.romanov@nginx.com ra->app_pid = -1; 312167Smax.romanov@nginx.com ra->rc = rc; 313*318Smax.romanov@nginx.com rc->ra = ra; 314*318Smax.romanov@nginx.com ra->reply_port = engine->port; 315167Smax.romanov@nginx.com 316167Smax.romanov@nginx.com ra->mem_pool = mp; 317167Smax.romanov@nginx.com 318167Smax.romanov@nginx.com ra->work.handler = NULL; 319*318Smax.romanov@nginx.com ra->work.task = &engine->task; 320167Smax.romanov@nginx.com ra->work.obj = ra; 321*318Smax.romanov@nginx.com ra->work.data = engine; 322167Smax.romanov@nginx.com 323167Smax.romanov@nginx.com return ra; 324167Smax.romanov@nginx.com } 325167Smax.romanov@nginx.com 326167Smax.romanov@nginx.com 327167Smax.romanov@nginx.com static void 328167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data) 329167Smax.romanov@nginx.com { 330*318Smax.romanov@nginx.com nxt_port_t *app_port; 331*318Smax.romanov@nginx.com nxt_req_app_link_t *ra; 332*318Smax.romanov@nginx.com nxt_event_engine_t *engine; 333*318Smax.romanov@nginx.com 334*318Smax.romanov@nginx.com ra = obj; 335*318Smax.romanov@nginx.com engine = data; 336*318Smax.romanov@nginx.com 337*318Smax.romanov@nginx.com if (ra->app_port != NULL) { 338*318Smax.romanov@nginx.com 339*318Smax.romanov@nginx.com app_port = ra->app_port; 340*318Smax.romanov@nginx.com ra->app_port = NULL; 341*318Smax.romanov@nginx.com 342*318Smax.romanov@nginx.com if (task->thread->engine != engine) { 343*318Smax.romanov@nginx.com ra->app_pid = app_port->pid; 344*318Smax.romanov@nginx.com } 345*318Smax.romanov@nginx.com 346*318Smax.romanov@nginx.com nxt_router_app_release_port(task, app_port, app_port->app); 347*318Smax.romanov@nginx.com 348*318Smax.romanov@nginx.com #if 0 349*318Smax.romanov@nginx.com /* Uncomment to hold app port until complete response received. */ 350*318Smax.romanov@nginx.com if (ra->rc != NULL) { 351*318Smax.romanov@nginx.com ra->rc->app_port = ra->app_port; 352*318Smax.romanov@nginx.com 353*318Smax.romanov@nginx.com } else { 354*318Smax.romanov@nginx.com nxt_router_app_release_port(task, ra->app_port, ra->app_port->app); 355*318Smax.romanov@nginx.com } 356*318Smax.romanov@nginx.com #endif 357*318Smax.romanov@nginx.com } 358*318Smax.romanov@nginx.com 359*318Smax.romanov@nginx.com if (task->thread->engine != engine) { 360*318Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_release; 361*318Smax.romanov@nginx.com ra->work.task = &engine->task; 362*318Smax.romanov@nginx.com ra->work.next = NULL; 363*318Smax.romanov@nginx.com 364*318Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD post release to %p", 365*318Smax.romanov@nginx.com ra->stream, engine); 366*318Smax.romanov@nginx.com 367*318Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 368*318Smax.romanov@nginx.com 369*318Smax.romanov@nginx.com return; 370*318Smax.romanov@nginx.com } 371*318Smax.romanov@nginx.com 372*318Smax.romanov@nginx.com if (ra->rc != NULL && ra->app_pid != -1) { 373*318Smax.romanov@nginx.com nxt_port_rpc_ex_set_peer(task, engine->port, ra->rc, ra->app_pid); 374*318Smax.romanov@nginx.com } 375*318Smax.romanov@nginx.com 376*318Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD release", ra->stream); 377*318Smax.romanov@nginx.com 378*318Smax.romanov@nginx.com nxt_mp_release(ra->mem_pool, ra); 379*318Smax.romanov@nginx.com } 380*318Smax.romanov@nginx.com 381*318Smax.romanov@nginx.com 382*318Smax.romanov@nginx.com static void 383*318Smax.romanov@nginx.com nxt_router_ra_abort(nxt_task_t *task, void *obj, void *data) 384*318Smax.romanov@nginx.com { 385*318Smax.romanov@nginx.com nxt_conn_t *c; 386167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 387167Smax.romanov@nginx.com nxt_event_engine_t *engine; 388167Smax.romanov@nginx.com 389167Smax.romanov@nginx.com ra = obj; 390167Smax.romanov@nginx.com engine = data; 391167Smax.romanov@nginx.com 392167Smax.romanov@nginx.com if (task->thread->engine != engine) { 393*318Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_abort; 394167Smax.romanov@nginx.com ra->work.task = &engine->task; 395167Smax.romanov@nginx.com ra->work.next = NULL; 396167Smax.romanov@nginx.com 397*318Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD post abort to %p", ra->stream, engine); 398167Smax.romanov@nginx.com 399167Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 400167Smax.romanov@nginx.com 401167Smax.romanov@nginx.com return; 402167Smax.romanov@nginx.com } 403167Smax.romanov@nginx.com 404*318Smax.romanov@nginx.com nxt_debug(task, "ra stream #%uD abort", ra->stream); 405*318Smax.romanov@nginx.com 406*318Smax.romanov@nginx.com if (ra->rc != NULL) { 407*318Smax.romanov@nginx.com c = ra->rc->conn; 408*318Smax.romanov@nginx.com 409*318Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 410*318Smax.romanov@nginx.com "Failed to start application worker"); 411167Smax.romanov@nginx.com } 412167Smax.romanov@nginx.com 413167Smax.romanov@nginx.com nxt_mp_release(ra->mem_pool, ra); 414167Smax.romanov@nginx.com } 415167Smax.romanov@nginx.com 416167Smax.romanov@nginx.com 417141Smax.romanov@nginx.com void 418141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 419141Smax.romanov@nginx.com { 420141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 421141Smax.romanov@nginx.com 422192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 423141Smax.romanov@nginx.com return; 424141Smax.romanov@nginx.com } 425141Smax.romanov@nginx.com 426192Smax.romanov@nginx.com if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) { 427192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 428141Smax.romanov@nginx.com } 429192Smax.romanov@nginx.com 430192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 431141Smax.romanov@nginx.com } 432141Smax.romanov@nginx.com 433141Smax.romanov@nginx.com 434139Sigor@sysoev.ru void 435139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 436115Sigor@sysoev.ru { 437139Sigor@sysoev.ru size_t dump_size; 438198Sigor@sysoev.ru nxt_int_t ret; 439139Sigor@sysoev.ru nxt_buf_t *b; 440139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 441139Sigor@sysoev.ru 442139Sigor@sysoev.ru b = msg->buf; 443139Sigor@sysoev.ru 444139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 445139Sigor@sysoev.ru 446139Sigor@sysoev.ru if (dump_size > 300) { 447139Sigor@sysoev.ru dump_size = 300; 44853Sigor@sysoev.ru } 44953Sigor@sysoev.ru 450139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 451139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 452139Sigor@sysoev.ru 453139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 454139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 455139Sigor@sysoev.ru return; 45653Sigor@sysoev.ru } 45753Sigor@sysoev.ru 458139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 459139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 460139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 461198Sigor@sysoev.ru msg->port_msg.pid, 462198Sigor@sysoev.ru msg->port_msg.reply_port); 463198Sigor@sysoev.ru 464198Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free); 465198Sigor@sysoev.ru 466198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) { 467198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL); 468198Sigor@sysoev.ru 469198Sigor@sysoev.ru } else { 470198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 471139Sigor@sysoev.ru } 47253Sigor@sysoev.ru } 47353Sigor@sysoev.ru 47453Sigor@sysoev.ru 475192Smax.romanov@nginx.com void 476192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 477192Smax.romanov@nginx.com { 478*318Smax.romanov@nginx.com nxt_mp_t *mp; 479*318Smax.romanov@nginx.com nxt_buf_t *buf; 480*318Smax.romanov@nginx.com nxt_event_engine_t *engine; 481*318Smax.romanov@nginx.com nxt_remove_pid_msg_t *rp; 482*318Smax.romanov@nginx.com 483192Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, msg); 484192Smax.romanov@nginx.com 485192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 486192Smax.romanov@nginx.com return; 487192Smax.romanov@nginx.com } 488192Smax.romanov@nginx.com 489*318Smax.romanov@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 490*318Smax.romanov@nginx.com 491*318Smax.romanov@nginx.com buf = nxt_buf_mem_alloc(mp, nxt_buf_used_size(msg->buf), 0); 492*318Smax.romanov@nginx.com buf->mem.free = nxt_cpymem(buf->mem.free, msg->buf->mem.pos, 493*318Smax.romanov@nginx.com nxt_buf_used_size(msg->buf)); 494*318Smax.romanov@nginx.com 495*318Smax.romanov@nginx.com nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) 496*318Smax.romanov@nginx.com { 497*318Smax.romanov@nginx.com rp = nxt_mp_retain(mp, sizeof(nxt_remove_pid_msg_t)); 498*318Smax.romanov@nginx.com 499*318Smax.romanov@nginx.com rp->mem_pool = mp; 500*318Smax.romanov@nginx.com 501*318Smax.romanov@nginx.com rp->msg.fd = msg->fd; 502*318Smax.romanov@nginx.com rp->msg.buf = buf; 503*318Smax.romanov@nginx.com rp->msg.port = engine->port; 504*318Smax.romanov@nginx.com rp->msg.port_msg = msg->port_msg; 505*318Smax.romanov@nginx.com rp->msg.size = msg->size; 506*318Smax.romanov@nginx.com rp->msg.new_port = NULL; 507*318Smax.romanov@nginx.com 508*318Smax.romanov@nginx.com rp->work.handler = nxt_router_worker_remove_pid_handler; 509*318Smax.romanov@nginx.com rp->work.task = &engine->task; 510*318Smax.romanov@nginx.com rp->work.obj = rp; 511*318Smax.romanov@nginx.com rp->work.data = task->thread->engine; 512*318Smax.romanov@nginx.com rp->work.next = NULL; 513*318Smax.romanov@nginx.com 514*318Smax.romanov@nginx.com nxt_event_engine_post(engine, &rp->work); 515*318Smax.romanov@nginx.com } 516*318Smax.romanov@nginx.com nxt_queue_loop; 517*318Smax.romanov@nginx.com 518192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 519192Smax.romanov@nginx.com 520192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 521192Smax.romanov@nginx.com } 522192Smax.romanov@nginx.com 523192Smax.romanov@nginx.com 524*318Smax.romanov@nginx.com static void 525*318Smax.romanov@nginx.com nxt_router_worker_remove_pid_handler(nxt_task_t *task, void *obj, void *data) 526*318Smax.romanov@nginx.com { 527*318Smax.romanov@nginx.com nxt_event_engine_t *engine; 528*318Smax.romanov@nginx.com nxt_remove_pid_msg_t *rp; 529*318Smax.romanov@nginx.com 530*318Smax.romanov@nginx.com rp = obj; 531*318Smax.romanov@nginx.com 532*318Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, &rp->msg); 533*318Smax.romanov@nginx.com 534*318Smax.romanov@nginx.com engine = rp->work.data; 535*318Smax.romanov@nginx.com 536*318Smax.romanov@nginx.com rp->work.handler = nxt_router_worker_remove_pid_done; 537*318Smax.romanov@nginx.com rp->work.task = &engine->task; 538*318Smax.romanov@nginx.com rp->work.next = NULL; 539*318Smax.romanov@nginx.com 540*318Smax.romanov@nginx.com nxt_event_engine_post(engine, &rp->work); 541*318Smax.romanov@nginx.com } 542*318Smax.romanov@nginx.com 543*318Smax.romanov@nginx.com 544*318Smax.romanov@nginx.com static void 545*318Smax.romanov@nginx.com nxt_router_worker_remove_pid_done(nxt_task_t *task, void *obj, void *data) 546*318Smax.romanov@nginx.com { 547*318Smax.romanov@nginx.com nxt_remove_pid_msg_t *rp; 548*318Smax.romanov@nginx.com 549*318Smax.romanov@nginx.com rp = obj; 550*318Smax.romanov@nginx.com 551*318Smax.romanov@nginx.com nxt_mp_release(rp->mem_pool, rp); 552*318Smax.romanov@nginx.com } 553*318Smax.romanov@nginx.com 554*318Smax.romanov@nginx.com 55553Sigor@sysoev.ru static nxt_router_temp_conf_t * 556139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 55753Sigor@sysoev.ru { 55865Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 55953Sigor@sysoev.ru nxt_router_conf_t *rtcf; 56053Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 56153Sigor@sysoev.ru 56265Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 56353Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 56453Sigor@sysoev.ru return NULL; 56553Sigor@sysoev.ru } 56653Sigor@sysoev.ru 56765Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 56853Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 56953Sigor@sysoev.ru goto fail; 57053Sigor@sysoev.ru } 57153Sigor@sysoev.ru 57253Sigor@sysoev.ru rtcf->mem_pool = mp; 57353Sigor@sysoev.ru 57465Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 57553Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 57653Sigor@sysoev.ru goto fail; 57753Sigor@sysoev.ru } 57853Sigor@sysoev.ru 57965Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 58053Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 58153Sigor@sysoev.ru goto temp_fail; 58253Sigor@sysoev.ru } 58353Sigor@sysoev.ru 58453Sigor@sysoev.ru tmcf->mem_pool = tmp; 58553Sigor@sysoev.ru tmcf->conf = rtcf; 586139Sigor@sysoev.ru tmcf->count = 1; 587139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 58853Sigor@sysoev.ru 58953Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 59053Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 59153Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 59253Sigor@sysoev.ru goto temp_fail; 59353Sigor@sysoev.ru } 59453Sigor@sysoev.ru 59553Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 59653Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 59753Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 59853Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 59953Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 600133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 601133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 60253Sigor@sysoev.ru 60353Sigor@sysoev.ru return tmcf; 60453Sigor@sysoev.ru 60553Sigor@sysoev.ru temp_fail: 60653Sigor@sysoev.ru 60765Sigor@sysoev.ru nxt_mp_destroy(tmp); 60853Sigor@sysoev.ru 60953Sigor@sysoev.ru fail: 61053Sigor@sysoev.ru 61165Sigor@sysoev.ru nxt_mp_destroy(mp); 61253Sigor@sysoev.ru 61353Sigor@sysoev.ru return NULL; 61453Sigor@sysoev.ru } 61553Sigor@sysoev.ru 61653Sigor@sysoev.ru 617198Sigor@sysoev.ru static void 618198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) 619139Sigor@sysoev.ru { 620139Sigor@sysoev.ru nxt_int_t ret; 621139Sigor@sysoev.ru nxt_router_t *router; 622139Sigor@sysoev.ru nxt_runtime_t *rt; 623198Sigor@sysoev.ru nxt_queue_link_t *qlk; 624198Sigor@sysoev.ru nxt_socket_conf_t *skcf; 625198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 626139Sigor@sysoev.ru const nxt_event_interface_t *interface; 627139Sigor@sysoev.ru 628198Sigor@sysoev.ru tmcf = obj; 629198Sigor@sysoev.ru 630198Sigor@sysoev.ru qlk = nxt_queue_first(&tmcf->pending); 631198Sigor@sysoev.ru 632198Sigor@sysoev.ru if (qlk != nxt_queue_tail(&tmcf->pending)) { 633198Sigor@sysoev.ru nxt_queue_remove(qlk); 634198Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 635198Sigor@sysoev.ru 636198Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 637198Sigor@sysoev.ru 638198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(task, tmcf, skcf); 639198Sigor@sysoev.ru 640198Sigor@sysoev.ru return; 641139Sigor@sysoev.ru } 642139Sigor@sysoev.ru 643139Sigor@sysoev.ru rt = task->thread->runtime; 644139Sigor@sysoev.ru 645139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 646139Sigor@sysoev.ru 647198Sigor@sysoev.ru router = tmcf->conf->router; 648198Sigor@sysoev.ru 649139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 650139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 651198Sigor@sysoev.ru goto fail; 652139Sigor@sysoev.ru } 653139Sigor@sysoev.ru 654139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 655139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 656198Sigor@sysoev.ru goto fail; 657139Sigor@sysoev.ru } 658139Sigor@sysoev.ru 659139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 660139Sigor@sysoev.ru 661315Sigor@sysoev.ru nxt_router_engines_post(router, tmcf); 662139Sigor@sysoev.ru 663139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 664139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 665139Sigor@sysoev.ru 666198Sigor@sysoev.ru nxt_router_conf_ready(task, tmcf); 667198Sigor@sysoev.ru 668198Sigor@sysoev.ru return; 669198Sigor@sysoev.ru 670198Sigor@sysoev.ru fail: 671198Sigor@sysoev.ru 672198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 673198Sigor@sysoev.ru 674198Sigor@sysoev.ru return; 675139Sigor@sysoev.ru } 676139Sigor@sysoev.ru 677139Sigor@sysoev.ru 678139Sigor@sysoev.ru static void 679139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 680139Sigor@sysoev.ru { 681153Sigor@sysoev.ru nxt_joint_job_t *job; 682153Sigor@sysoev.ru 683153Sigor@sysoev.ru job = obj; 684153Sigor@sysoev.ru 685198Sigor@sysoev.ru nxt_router_conf_ready(task, job->tmcf); 686139Sigor@sysoev.ru } 687139Sigor@sysoev.ru 688139Sigor@sysoev.ru 689139Sigor@sysoev.ru static void 690198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 691139Sigor@sysoev.ru { 692139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 693139Sigor@sysoev.ru 694139Sigor@sysoev.ru if (--tmcf->count == 0) { 695193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); 696139Sigor@sysoev.ru } 697139Sigor@sysoev.ru } 698139Sigor@sysoev.ru 699139Sigor@sysoev.ru 700139Sigor@sysoev.ru static void 701139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 702139Sigor@sysoev.ru { 703148Sigor@sysoev.ru nxt_socket_t s; 704149Sigor@sysoev.ru nxt_router_t *router; 705148Sigor@sysoev.ru nxt_queue_link_t *qlk; 706148Sigor@sysoev.ru nxt_socket_conf_t *skcf; 707148Sigor@sysoev.ru 708198Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 709198Sigor@sysoev.ru 710148Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->creating); 711148Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->creating); 712148Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 713148Sigor@sysoev.ru { 714148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 715148Sigor@sysoev.ru s = skcf->listen.socket; 716148Sigor@sysoev.ru 717148Sigor@sysoev.ru if (s != -1) { 718148Sigor@sysoev.ru nxt_socket_close(task, s); 719148Sigor@sysoev.ru } 720148Sigor@sysoev.ru 721148Sigor@sysoev.ru nxt_free(skcf->socket); 722148Sigor@sysoev.ru } 723148Sigor@sysoev.ru 724149Sigor@sysoev.ru router = tmcf->conf->router; 725149Sigor@sysoev.ru 726149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->keeping); 727149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->deleting); 728149Sigor@sysoev.ru 729148Sigor@sysoev.ru // TODO: new engines and threads 730148Sigor@sysoev.ru 731139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 732139Sigor@sysoev.ru 733193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); 734139Sigor@sysoev.ru } 735139Sigor@sysoev.ru 736139Sigor@sysoev.ru 737139Sigor@sysoev.ru static void 738139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 739193Smax.romanov@nginx.com nxt_port_msg_type_t type) 740139Sigor@sysoev.ru { 741193Smax.romanov@nginx.com nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); 742139Sigor@sysoev.ru } 743139Sigor@sysoev.ru 744139Sigor@sysoev.ru 745115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 746115Sigor@sysoev.ru { 747133Sigor@sysoev.ru nxt_string("listeners_threads"), 748115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 749115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 750115Sigor@sysoev.ru }, 751115Sigor@sysoev.ru }; 752115Sigor@sysoev.ru 753115Sigor@sysoev.ru 754133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 755115Sigor@sysoev.ru { 756133Sigor@sysoev.ru nxt_string("type"), 757115Sigor@sysoev.ru NXT_CONF_MAP_STR, 758133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 759115Sigor@sysoev.ru }, 760115Sigor@sysoev.ru 761115Sigor@sysoev.ru { 762133Sigor@sysoev.ru nxt_string("workers"), 763115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 764133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 765133Sigor@sysoev.ru }, 766*318Smax.romanov@nginx.com 767*318Smax.romanov@nginx.com { 768*318Smax.romanov@nginx.com nxt_string("limits"), 769*318Smax.romanov@nginx.com NXT_CONF_MAP_PTR, 770*318Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, limits_value), 771*318Smax.romanov@nginx.com }, 772*318Smax.romanov@nginx.com }; 773*318Smax.romanov@nginx.com 774*318Smax.romanov@nginx.com 775*318Smax.romanov@nginx.com static nxt_conf_map_t nxt_router_app_limits_conf[] = { 776*318Smax.romanov@nginx.com { 777*318Smax.romanov@nginx.com nxt_string("timeout"), 778*318Smax.romanov@nginx.com NXT_CONF_MAP_MSEC, 779*318Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, timeout), 780*318Smax.romanov@nginx.com }, 781*318Smax.romanov@nginx.com 782*318Smax.romanov@nginx.com { 783*318Smax.romanov@nginx.com nxt_string("requests"), 784*318Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 785*318Smax.romanov@nginx.com offsetof(nxt_router_app_conf_t, requests), 786*318Smax.romanov@nginx.com }, 787133Sigor@sysoev.ru }; 788133Sigor@sysoev.ru 789133Sigor@sysoev.ru 790133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 791133Sigor@sysoev.ru { 792133Sigor@sysoev.ru nxt_string("application"), 793133Sigor@sysoev.ru NXT_CONF_MAP_STR, 794133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 795115Sigor@sysoev.ru }, 796115Sigor@sysoev.ru }; 797115Sigor@sysoev.ru 798115Sigor@sysoev.ru 799115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 800115Sigor@sysoev.ru { 801115Sigor@sysoev.ru nxt_string("header_buffer_size"), 802115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 803115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 804115Sigor@sysoev.ru }, 805115Sigor@sysoev.ru 806115Sigor@sysoev.ru { 807115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 808115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 809115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 810115Sigor@sysoev.ru }, 811115Sigor@sysoev.ru 812115Sigor@sysoev.ru { 813206Smax.romanov@nginx.com nxt_string("large_header_buffers"), 814206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 815206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, large_header_buffers), 816206Smax.romanov@nginx.com }, 817206Smax.romanov@nginx.com 818206Smax.romanov@nginx.com { 819206Smax.romanov@nginx.com nxt_string("body_buffer_size"), 820206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 821206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_buffer_size), 822206Smax.romanov@nginx.com }, 823206Smax.romanov@nginx.com 824206Smax.romanov@nginx.com { 825206Smax.romanov@nginx.com nxt_string("max_body_size"), 826206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 827206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, max_body_size), 828206Smax.romanov@nginx.com }, 829206Smax.romanov@nginx.com 830206Smax.romanov@nginx.com { 831115Sigor@sysoev.ru nxt_string("header_read_timeout"), 832115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 833115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 834115Sigor@sysoev.ru }, 835206Smax.romanov@nginx.com 836206Smax.romanov@nginx.com { 837206Smax.romanov@nginx.com nxt_string("body_read_timeout"), 838206Smax.romanov@nginx.com NXT_CONF_MAP_MSEC, 839206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_read_timeout), 840206Smax.romanov@nginx.com }, 841115Sigor@sysoev.ru }; 842115Sigor@sysoev.ru 843115Sigor@sysoev.ru 84453Sigor@sysoev.ru static nxt_int_t 845115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 846115Sigor@sysoev.ru u_char *start, u_char *end) 84753Sigor@sysoev.ru { 848133Sigor@sysoev.ru u_char *p; 849133Sigor@sysoev.ru size_t size; 850115Sigor@sysoev.ru nxt_mp_t *mp; 851115Sigor@sysoev.ru uint32_t next; 852115Sigor@sysoev.ru nxt_int_t ret; 853115Sigor@sysoev.ru nxt_str_t name; 854133Sigor@sysoev.ru nxt_app_t *app, *prev; 855133Sigor@sysoev.ru nxt_app_type_t type; 856115Sigor@sysoev.ru nxt_sockaddr_t *sa; 857133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 858133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 859133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 860115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 861216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 862133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 863115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 864115Sigor@sysoev.ru 865115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 866133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 867115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 868115Sigor@sysoev.ru 869208Svbart@nginx.com conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); 870115Sigor@sysoev.ru if (conf == NULL) { 871115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 872115Sigor@sysoev.ru return NXT_ERROR; 873115Sigor@sysoev.ru } 874115Sigor@sysoev.ru 875213Svbart@nginx.com mp = tmcf->conf->mem_pool; 876213Svbart@nginx.com 877213Svbart@nginx.com ret = nxt_conf_map_object(mp, conf, nxt_router_conf, 878136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 879115Sigor@sysoev.ru if (ret != NXT_OK) { 880133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 881115Sigor@sysoev.ru return NXT_ERROR; 882115Sigor@sysoev.ru } 883115Sigor@sysoev.ru 884117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 885117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 886117Sigor@sysoev.ru } 887117Sigor@sysoev.ru 888133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 889133Sigor@sysoev.ru if (applications == NULL) { 890133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 891115Sigor@sysoev.ru return NXT_ERROR; 892115Sigor@sysoev.ru } 893115Sigor@sysoev.ru 894133Sigor@sysoev.ru next = 0; 895133Sigor@sysoev.ru 896133Sigor@sysoev.ru for ( ;; ) { 897133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 898133Sigor@sysoev.ru if (application == NULL) { 899133Sigor@sysoev.ru break; 900133Sigor@sysoev.ru } 901133Sigor@sysoev.ru 902133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 903133Sigor@sysoev.ru 904144Smax.romanov@nginx.com size = nxt_conf_json_length(application, NULL); 905144Smax.romanov@nginx.com 906144Smax.romanov@nginx.com app = nxt_malloc(sizeof(nxt_app_t) + name.length + size); 907133Sigor@sysoev.ru if (app == NULL) { 908133Sigor@sysoev.ru goto fail; 909133Sigor@sysoev.ru } 910133Sigor@sysoev.ru 911144Smax.romanov@nginx.com nxt_memzero(app, sizeof(nxt_app_t)); 912144Smax.romanov@nginx.com 913144Smax.romanov@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 914144Smax.romanov@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); 915133Sigor@sysoev.ru 916133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 917133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 918133Sigor@sysoev.ru 919144Smax.romanov@nginx.com nxt_assert(app->conf.length <= size); 920144Smax.romanov@nginx.com 921133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 922133Sigor@sysoev.ru 923133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 924133Sigor@sysoev.ru 925133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 926133Sigor@sysoev.ru nxt_free(app); 927133Sigor@sysoev.ru 928133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 929133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 930133Sigor@sysoev.ru continue; 931133Sigor@sysoev.ru } 932133Sigor@sysoev.ru 933263Smax.romanov@nginx.com apcf.workers = 1; 934*318Smax.romanov@nginx.com apcf.timeout = 0; 935*318Smax.romanov@nginx.com apcf.requests = 0; 936*318Smax.romanov@nginx.com apcf.limits_value = NULL; 937263Smax.romanov@nginx.com 938213Svbart@nginx.com ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, 939136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 940133Sigor@sysoev.ru if (ret != NXT_OK) { 941133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 942133Sigor@sysoev.ru goto app_fail; 943133Sigor@sysoev.ru } 944115Sigor@sysoev.ru 945*318Smax.romanov@nginx.com if (apcf.limits_value != NULL) { 946*318Smax.romanov@nginx.com 947*318Smax.romanov@nginx.com if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) { 948*318Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "application limits is not object"); 949*318Smax.romanov@nginx.com goto app_fail; 950*318Smax.romanov@nginx.com } 951*318Smax.romanov@nginx.com 952*318Smax.romanov@nginx.com ret = nxt_conf_map_object(mp, apcf.limits_value, 953*318Smax.romanov@nginx.com nxt_router_app_limits_conf, 954*318Smax.romanov@nginx.com nxt_nitems(nxt_router_app_limits_conf), 955*318Smax.romanov@nginx.com &apcf); 956*318Smax.romanov@nginx.com if (ret != NXT_OK) { 957*318Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "application limits map error"); 958*318Smax.romanov@nginx.com goto app_fail; 959*318Smax.romanov@nginx.com } 960*318Smax.romanov@nginx.com } 961*318Smax.romanov@nginx.com 962133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 963133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 964*318Smax.romanov@nginx.com nxt_debug(task, "application timeout: %D", apcf.timeout); 965*318Smax.romanov@nginx.com nxt_debug(task, "application requests: %D", apcf.requests); 966133Sigor@sysoev.ru 967216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); 968216Sigor@sysoev.ru 969216Sigor@sysoev.ru if (lang == NULL) { 970141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 971141Smax.romanov@nginx.com &apcf.type); 972141Smax.romanov@nginx.com goto app_fail; 973141Smax.romanov@nginx.com } 974141Smax.romanov@nginx.com 975216Sigor@sysoev.ru nxt_debug(task, "application language module: \"%s\"", lang->file); 976216Sigor@sysoev.ru 977216Sigor@sysoev.ru type = nxt_app_parse_type(&lang->type); 978216Sigor@sysoev.ru 979216Sigor@sysoev.ru if (type == NXT_APP_UNKNOWN) { 980216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 981216Sigor@sysoev.ru &lang->type); 982216Sigor@sysoev.ru goto app_fail; 983216Sigor@sysoev.ru } 984216Sigor@sysoev.ru 985216Sigor@sysoev.ru if (nxt_app_prepare_msg[type] == NULL) { 986133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 987216Sigor@sysoev.ru &lang->type); 988133Sigor@sysoev.ru goto app_fail; 989133Sigor@sysoev.ru } 990133Sigor@sysoev.ru 991133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 992133Sigor@sysoev.ru if (ret != NXT_OK) { 993133Sigor@sysoev.ru goto app_fail; 994133Sigor@sysoev.ru } 995133Sigor@sysoev.ru 996141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 997141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 998141Smax.romanov@nginx.com 999144Smax.romanov@nginx.com app->name.length = name.length; 1000144Smax.romanov@nginx.com nxt_memcpy(app->name.start, name.start, name.length); 1001144Smax.romanov@nginx.com 1002133Sigor@sysoev.ru app->type = type; 1003133Sigor@sysoev.ru app->max_workers = apcf.workers; 1004*318Smax.romanov@nginx.com app->timeout = apcf.timeout; 1005133Sigor@sysoev.ru app->live = 1; 1006216Sigor@sysoev.ru app->prepare_msg = nxt_app_prepare_msg[type]; 1007133Sigor@sysoev.ru 1008133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 1009133Sigor@sysoev.ru } 1010133Sigor@sysoev.ru 1011133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 1012133Sigor@sysoev.ru #if 0 1013133Sigor@sysoev.ru if (http == NULL) { 1014133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 1015133Sigor@sysoev.ru return NXT_ERROR; 1016133Sigor@sysoev.ru } 1017133Sigor@sysoev.ru #endif 1018133Sigor@sysoev.ru 1019133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 1020115Sigor@sysoev.ru if (listeners == NULL) { 1021133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 1022115Sigor@sysoev.ru return NXT_ERROR; 1023115Sigor@sysoev.ru } 102453Sigor@sysoev.ru 1025133Sigor@sysoev.ru next = 0; 102653Sigor@sysoev.ru 1027115Sigor@sysoev.ru for ( ;; ) { 1028115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 1029115Sigor@sysoev.ru if (listener == NULL) { 1030115Sigor@sysoev.ru break; 1031115Sigor@sysoev.ru } 103253Sigor@sysoev.ru 1033115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 1034115Sigor@sysoev.ru if (sa == NULL) { 1035115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 1036133Sigor@sysoev.ru goto fail; 1037115Sigor@sysoev.ru } 1038115Sigor@sysoev.ru 1039115Sigor@sysoev.ru sa->type = SOCK_STREAM; 1040115Sigor@sysoev.ru 1041115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 1042115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 104353Sigor@sysoev.ru 1044115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 1045115Sigor@sysoev.ru if (skcf == NULL) { 1046133Sigor@sysoev.ru goto fail; 1047115Sigor@sysoev.ru } 104853Sigor@sysoev.ru 1049213Svbart@nginx.com ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, 1050136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 1051115Sigor@sysoev.ru if (ret != NXT_OK) { 1052115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 1053133Sigor@sysoev.ru goto fail; 1054115Sigor@sysoev.ru } 105553Sigor@sysoev.ru 1056133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 1057133Sigor@sysoev.ru 1058133Sigor@sysoev.ru // STUB, default values if http block is not defined. 1059133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 1060133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 1061206Smax.romanov@nginx.com skcf->large_header_buffers = 4; 1062206Smax.romanov@nginx.com skcf->body_buffer_size = 16 * 1024; 1063206Smax.romanov@nginx.com skcf->max_body_size = 2 * 1024 * 1024; 1064133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 1065206Smax.romanov@nginx.com skcf->body_read_timeout = 5000; 106653Sigor@sysoev.ru 1067133Sigor@sysoev.ru if (http != NULL) { 1068213Svbart@nginx.com ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, 1069136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 1070133Sigor@sysoev.ru if (ret != NXT_OK) { 1071133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 1072133Sigor@sysoev.ru goto fail; 1073133Sigor@sysoev.ru } 1074115Sigor@sysoev.ru } 1075115Sigor@sysoev.ru 1076115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 1077115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 1078160Sigor@sysoev.ru skcf->router_conf->count++; 1079133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 1080133Sigor@sysoev.ru &lscf.application); 1081115Sigor@sysoev.ru 1082115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 1083115Sigor@sysoev.ru } 108453Sigor@sysoev.ru 1085198Sigor@sysoev.ru nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf); 1086198Sigor@sysoev.ru 108753Sigor@sysoev.ru return NXT_OK; 1088133Sigor@sysoev.ru 1089133Sigor@sysoev.ru app_fail: 1090133Sigor@sysoev.ru 1091133Sigor@sysoev.ru nxt_free(app); 1092133Sigor@sysoev.ru 1093133Sigor@sysoev.ru fail: 1094133Sigor@sysoev.ru 1095141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1096141Smax.romanov@nginx.com 1097141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 1098133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 1099133Sigor@sysoev.ru nxt_free(app); 1100141Smax.romanov@nginx.com 1101141Smax.romanov@nginx.com } nxt_queue_loop; 1102133Sigor@sysoev.ru 1103133Sigor@sysoev.ru return NXT_ERROR; 1104133Sigor@sysoev.ru } 1105133Sigor@sysoev.ru 1106133Sigor@sysoev.ru 1107133Sigor@sysoev.ru static nxt_app_t * 1108133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 1109133Sigor@sysoev.ru { 1110141Smax.romanov@nginx.com nxt_app_t *app; 1111141Smax.romanov@nginx.com 1112141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 1113133Sigor@sysoev.ru 1114133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 1115133Sigor@sysoev.ru return app; 1116133Sigor@sysoev.ru } 1117141Smax.romanov@nginx.com 1118141Smax.romanov@nginx.com } nxt_queue_loop; 1119133Sigor@sysoev.ru 1120133Sigor@sysoev.ru return NULL; 1121133Sigor@sysoev.ru } 1122133Sigor@sysoev.ru 1123133Sigor@sysoev.ru 1124133Sigor@sysoev.ru static nxt_app_t * 1125133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 1126133Sigor@sysoev.ru { 1127133Sigor@sysoev.ru nxt_app_t *app; 1128133Sigor@sysoev.ru 1129133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 1130133Sigor@sysoev.ru 1131133Sigor@sysoev.ru if (app == NULL) { 1132134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 1133133Sigor@sysoev.ru } 1134133Sigor@sysoev.ru 1135133Sigor@sysoev.ru return app; 113653Sigor@sysoev.ru } 113753Sigor@sysoev.ru 113853Sigor@sysoev.ru 113953Sigor@sysoev.ru static nxt_socket_conf_t * 114065Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 114153Sigor@sysoev.ru { 1142163Smax.romanov@nginx.com nxt_socket_conf_t *skcf; 1143163Smax.romanov@nginx.com 1144163Smax.romanov@nginx.com skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 1145163Smax.romanov@nginx.com if (nxt_slow_path(skcf == NULL)) { 114653Sigor@sysoev.ru return NULL; 114753Sigor@sysoev.ru } 114853Sigor@sysoev.ru 1149163Smax.romanov@nginx.com skcf->sockaddr = sa; 1150163Smax.romanov@nginx.com 1151163Smax.romanov@nginx.com skcf->listen.sockaddr = sa; 1152312Sigor@sysoev.ru 1153312Sigor@sysoev.ru nxt_listen_socket_remote_size(&skcf->listen, sa); 1154163Smax.romanov@nginx.com 1155163Smax.romanov@nginx.com skcf->listen.socket = -1; 1156163Smax.romanov@nginx.com skcf->listen.backlog = NXT_LISTEN_BACKLOG; 1157163Smax.romanov@nginx.com skcf->listen.flags = NXT_NONBLOCK; 1158163Smax.romanov@nginx.com skcf->listen.read_after_accept = 1; 1159163Smax.romanov@nginx.com 1160163Smax.romanov@nginx.com return skcf; 116153Sigor@sysoev.ru } 116253Sigor@sysoev.ru 116353Sigor@sysoev.ru 116453Sigor@sysoev.ru static void 116553Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 116653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 116753Sigor@sysoev.ru { 116853Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 116953Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 117053Sigor@sysoev.ru 117153Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 117253Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 117353Sigor@sysoev.ru nqlk = next) 117453Sigor@sysoev.ru { 117553Sigor@sysoev.ru next = nxt_queue_next(nqlk); 117653Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 117753Sigor@sysoev.ru 117853Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 117953Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 118053Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 118153Sigor@sysoev.ru { 118253Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 118353Sigor@sysoev.ru 1184115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 1185115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 1186115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 1187115Sigor@sysoev.ru 118853Sigor@sysoev.ru nxt_queue_remove(oqlk); 118953Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 119053Sigor@sysoev.ru 119153Sigor@sysoev.ru nxt_queue_remove(nqlk); 119253Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 119353Sigor@sysoev.ru 119453Sigor@sysoev.ru break; 119553Sigor@sysoev.ru } 119653Sigor@sysoev.ru } 119753Sigor@sysoev.ru } 119853Sigor@sysoev.ru 119953Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 1200115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 120153Sigor@sysoev.ru } 120253Sigor@sysoev.ru 120353Sigor@sysoev.ru 1204198Sigor@sysoev.ru static void 1205198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(nxt_task_t *task, 1206198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf) 1207198Sigor@sysoev.ru { 1208198Sigor@sysoev.ru uint32_t stream; 1209198Sigor@sysoev.ru nxt_buf_t *b; 1210198Sigor@sysoev.ru nxt_port_t *main_port, *router_port; 1211198Sigor@sysoev.ru nxt_runtime_t *rt; 1212198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1213198Sigor@sysoev.ru 1214198Sigor@sysoev.ru rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); 1215198Sigor@sysoev.ru if (rpc == NULL) { 1216198Sigor@sysoev.ru goto fail; 1217198Sigor@sysoev.ru } 1218198Sigor@sysoev.ru 1219198Sigor@sysoev.ru rpc->socket_conf = skcf; 1220198Sigor@sysoev.ru rpc->temp_conf = tmcf; 1221198Sigor@sysoev.ru 1222198Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, skcf->sockaddr->sockaddr_size, 0); 1223198Sigor@sysoev.ru if (b == NULL) { 1224198Sigor@sysoev.ru goto fail; 1225198Sigor@sysoev.ru } 1226198Sigor@sysoev.ru 1227198Sigor@sysoev.ru b->mem.free = nxt_cpymem(b->mem.free, skcf->sockaddr, 1228198Sigor@sysoev.ru skcf->sockaddr->sockaddr_size); 1229198Sigor@sysoev.ru 1230198Sigor@sysoev.ru rt = task->thread->runtime; 1231240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1232198Sigor@sysoev.ru router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 1233198Sigor@sysoev.ru 1234198Sigor@sysoev.ru stream = nxt_port_rpc_register_handler(task, router_port, 1235198Sigor@sysoev.ru nxt_router_listen_socket_ready, 1236198Sigor@sysoev.ru nxt_router_listen_socket_error, 1237198Sigor@sysoev.ru main_port->pid, rpc); 1238198Sigor@sysoev.ru if (stream == 0) { 1239198Sigor@sysoev.ru goto fail; 1240198Sigor@sysoev.ru } 1241198Sigor@sysoev.ru 1242198Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, 1243198Sigor@sysoev.ru stream, router_port->id, b); 1244198Sigor@sysoev.ru 1245198Sigor@sysoev.ru return; 1246198Sigor@sysoev.ru 1247198Sigor@sysoev.ru fail: 1248198Sigor@sysoev.ru 1249198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 1250198Sigor@sysoev.ru } 1251198Sigor@sysoev.ru 1252198Sigor@sysoev.ru 1253198Sigor@sysoev.ru static void 1254198Sigor@sysoev.ru nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 1255198Sigor@sysoev.ru void *data) 125653Sigor@sysoev.ru { 1257115Sigor@sysoev.ru nxt_int_t ret; 1258115Sigor@sysoev.ru nxt_socket_t s; 1259198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1260115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 126153Sigor@sysoev.ru 1262198Sigor@sysoev.ru rpc = data; 1263198Sigor@sysoev.ru 1264198Sigor@sysoev.ru s = msg->fd; 1265198Sigor@sysoev.ru 1266198Sigor@sysoev.ru ret = nxt_socket_nonblocking(task, s); 1267198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1268198Sigor@sysoev.ru goto fail; 126953Sigor@sysoev.ru } 127053Sigor@sysoev.ru 1271229Sigor@sysoev.ru nxt_socket_defer_accept(task, s, rpc->socket_conf->sockaddr); 1272198Sigor@sysoev.ru 1273198Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 1274198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1275198Sigor@sysoev.ru goto fail; 1276198Sigor@sysoev.ru } 1277198Sigor@sysoev.ru 1278198Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 1279198Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 1280198Sigor@sysoev.ru goto fail; 1281198Sigor@sysoev.ru } 1282198Sigor@sysoev.ru 1283198Sigor@sysoev.ru rtsk->count = 0; 1284198Sigor@sysoev.ru rtsk->fd = s; 1285198Sigor@sysoev.ru 1286198Sigor@sysoev.ru rpc->socket_conf->listen.socket = s; 1287198Sigor@sysoev.ru rpc->socket_conf->socket = rtsk; 1288198Sigor@sysoev.ru 1289198Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue, 1290198Sigor@sysoev.ru nxt_router_conf_apply, task, rpc->temp_conf, NULL); 1291198Sigor@sysoev.ru 1292198Sigor@sysoev.ru return; 1293148Sigor@sysoev.ru 1294148Sigor@sysoev.ru fail: 1295148Sigor@sysoev.ru 1296148Sigor@sysoev.ru nxt_socket_close(task, s); 1297148Sigor@sysoev.ru 1298198Sigor@sysoev.ru nxt_router_conf_error(task, rpc->temp_conf); 1299198Sigor@sysoev.ru } 1300198Sigor@sysoev.ru 1301198Sigor@sysoev.ru 1302198Sigor@sysoev.ru static void 1303198Sigor@sysoev.ru nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 1304198Sigor@sysoev.ru void *data) 1305198Sigor@sysoev.ru { 1306198Sigor@sysoev.ru u_char *p; 1307198Sigor@sysoev.ru size_t size; 1308198Sigor@sysoev.ru uint8_t error; 1309198Sigor@sysoev.ru nxt_buf_t *in, *out; 1310198Sigor@sysoev.ru nxt_sockaddr_t *sa; 1311198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1312198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 1313198Sigor@sysoev.ru 1314198Sigor@sysoev.ru static nxt_str_t socket_errors[] = { 1315198Sigor@sysoev.ru nxt_string("ListenerSystem"), 1316198Sigor@sysoev.ru nxt_string("ListenerNoIPv6"), 1317198Sigor@sysoev.ru nxt_string("ListenerPort"), 1318198Sigor@sysoev.ru nxt_string("ListenerInUse"), 1319198Sigor@sysoev.ru nxt_string("ListenerNoAddress"), 1320198Sigor@sysoev.ru nxt_string("ListenerNoAccess"), 1321198Sigor@sysoev.ru nxt_string("ListenerPath"), 1322198Sigor@sysoev.ru }; 1323198Sigor@sysoev.ru 1324198Sigor@sysoev.ru rpc = data; 1325198Sigor@sysoev.ru sa = rpc->socket_conf->sockaddr; 1326198Sigor@sysoev.ru 1327198Sigor@sysoev.ru in = msg->buf; 1328198Sigor@sysoev.ru p = in->mem.pos; 1329198Sigor@sysoev.ru 1330198Sigor@sysoev.ru error = *p++; 1331198Sigor@sysoev.ru 1332198Sigor@sysoev.ru size = sizeof("listen socket error: ") - 1 1333198Sigor@sysoev.ru + sizeof("{listener: \"\", code:\"\", message: \"\"}") - 1 1334198Sigor@sysoev.ru + sa->length + socket_errors[error].length + (in->mem.free - p); 1335198Sigor@sysoev.ru 1336198Sigor@sysoev.ru tmcf = rpc->temp_conf; 1337198Sigor@sysoev.ru 1338198Sigor@sysoev.ru out = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 1339198Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) { 1340198Sigor@sysoev.ru return; 1341198Sigor@sysoev.ru } 1342198Sigor@sysoev.ru 1343198Sigor@sysoev.ru out->mem.free = nxt_sprintf(out->mem.free, out->mem.end, 1344198Sigor@sysoev.ru "listen socket error: " 1345198Sigor@sysoev.ru "{listener: \"%*s\", code:\"%V\", message: \"%*s\"}", 1346198Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa), 1347198Sigor@sysoev.ru &socket_errors[error], in->mem.free - p, p); 1348198Sigor@sysoev.ru 1349198Sigor@sysoev.ru nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos); 1350198Sigor@sysoev.ru 1351198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 135253Sigor@sysoev.ru } 135353Sigor@sysoev.ru 135453Sigor@sysoev.ru 135553Sigor@sysoev.ru static nxt_int_t 135653Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 135753Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 135853Sigor@sysoev.ru { 135953Sigor@sysoev.ru nxt_int_t ret; 136053Sigor@sysoev.ru nxt_uint_t n, threads; 136153Sigor@sysoev.ru nxt_queue_link_t *qlk; 136253Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 136353Sigor@sysoev.ru 136453Sigor@sysoev.ru threads = tmcf->conf->threads; 136553Sigor@sysoev.ru 136653Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 136753Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 136853Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 136953Sigor@sysoev.ru return NXT_ERROR; 137053Sigor@sysoev.ru } 137153Sigor@sysoev.ru 137253Sigor@sysoev.ru n = 0; 137353Sigor@sysoev.ru 137453Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 137553Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 137653Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 137753Sigor@sysoev.ru { 137853Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 137953Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 138053Sigor@sysoev.ru return NXT_ERROR; 138153Sigor@sysoev.ru } 138253Sigor@sysoev.ru 1383115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 138453Sigor@sysoev.ru 138553Sigor@sysoev.ru if (n < threads) { 1386315Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_KEEP; 1387115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 138853Sigor@sysoev.ru 138953Sigor@sysoev.ru } else { 1390315Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_DELETE; 1391115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 139253Sigor@sysoev.ru } 139353Sigor@sysoev.ru 139453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 139553Sigor@sysoev.ru return ret; 139653Sigor@sysoev.ru } 139753Sigor@sysoev.ru 139853Sigor@sysoev.ru n++; 139953Sigor@sysoev.ru } 140053Sigor@sysoev.ru 140153Sigor@sysoev.ru tmcf->new_threads = n; 140253Sigor@sysoev.ru 140353Sigor@sysoev.ru while (n < threads) { 140453Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 140553Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 140653Sigor@sysoev.ru return NXT_ERROR; 140753Sigor@sysoev.ru } 140853Sigor@sysoev.ru 1409315Sigor@sysoev.ru recf->action = NXT_ROUTER_ENGINE_ADD; 1410315Sigor@sysoev.ru 141153Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 141253Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 141353Sigor@sysoev.ru return NXT_ERROR; 141453Sigor@sysoev.ru } 141553Sigor@sysoev.ru 1416115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 141753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 141853Sigor@sysoev.ru return ret; 141953Sigor@sysoev.ru } 142053Sigor@sysoev.ru 142153Sigor@sysoev.ru n++; 142253Sigor@sysoev.ru } 142353Sigor@sysoev.ru 142453Sigor@sysoev.ru return NXT_OK; 142553Sigor@sysoev.ru } 142653Sigor@sysoev.ru 142753Sigor@sysoev.ru 142853Sigor@sysoev.ru static nxt_int_t 1429115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 1430115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 143153Sigor@sysoev.ru { 1432115Sigor@sysoev.ru nxt_int_t ret; 1433115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 143453Sigor@sysoev.ru 1435154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 1436154Sigor@sysoev.ru nxt_router_listen_socket_create); 1437115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1438115Sigor@sysoev.ru return ret; 1439115Sigor@sysoev.ru } 1440115Sigor@sysoev.ru 1441154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 1442154Sigor@sysoev.ru nxt_router_listen_socket_create); 144353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 144453Sigor@sysoev.ru return ret; 144553Sigor@sysoev.ru } 144653Sigor@sysoev.ru 1447115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1448115Sigor@sysoev.ru 1449115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1450115Sigor@sysoev.ru 1451115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1452115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 1453115Sigor@sysoev.ru 1454115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1455115Sigor@sysoev.ru 1456115Sigor@sysoev.ru return ret; 145753Sigor@sysoev.ru } 145853Sigor@sysoev.ru 145953Sigor@sysoev.ru 146053Sigor@sysoev.ru static nxt_int_t 1461115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 1462115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 146353Sigor@sysoev.ru { 1464115Sigor@sysoev.ru nxt_int_t ret; 1465115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 146653Sigor@sysoev.ru 1467154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 1468154Sigor@sysoev.ru nxt_router_listen_socket_create); 146953Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 147053Sigor@sysoev.ru return ret; 147153Sigor@sysoev.ru } 147253Sigor@sysoev.ru 1473154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 1474154Sigor@sysoev.ru nxt_router_listen_socket_update); 147553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 147653Sigor@sysoev.ru return ret; 147753Sigor@sysoev.ru } 147853Sigor@sysoev.ru 1479139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 1480115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1481115Sigor@sysoev.ru return ret; 1482115Sigor@sysoev.ru } 1483115Sigor@sysoev.ru 1484115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1485115Sigor@sysoev.ru 1486115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1487115Sigor@sysoev.ru 1488115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1489115Sigor@sysoev.ru 1490115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1491115Sigor@sysoev.ru 1492115Sigor@sysoev.ru return ret; 149353Sigor@sysoev.ru } 149453Sigor@sysoev.ru 149553Sigor@sysoev.ru 149653Sigor@sysoev.ru static nxt_int_t 1497115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 1498115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 149953Sigor@sysoev.ru { 150053Sigor@sysoev.ru nxt_int_t ret; 150153Sigor@sysoev.ru 1502313Sigor@sysoev.ru ret = nxt_router_engine_quit(tmcf, recf); 1503313Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1504313Sigor@sysoev.ru return ret; 1505313Sigor@sysoev.ru } 1506313Sigor@sysoev.ru 1507139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 150853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 150953Sigor@sysoev.ru return ret; 151053Sigor@sysoev.ru } 151153Sigor@sysoev.ru 1512139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 151353Sigor@sysoev.ru } 151453Sigor@sysoev.ru 151553Sigor@sysoev.ru 151653Sigor@sysoev.ru static nxt_int_t 1517154Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 1518154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 151953Sigor@sysoev.ru nxt_work_handler_t handler) 152053Sigor@sysoev.ru { 1521153Sigor@sysoev.ru nxt_joint_job_t *job; 152253Sigor@sysoev.ru nxt_queue_link_t *qlk; 1523155Sigor@sysoev.ru nxt_socket_conf_t *skcf; 152453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 152553Sigor@sysoev.ru 152653Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 152753Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 152853Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 152953Sigor@sysoev.ru { 1530154Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 1531153Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) { 1532139Sigor@sysoev.ru return NXT_ERROR; 1533139Sigor@sysoev.ru } 1534139Sigor@sysoev.ru 1535154Sigor@sysoev.ru job->work.next = recf->jobs; 1536154Sigor@sysoev.ru recf->jobs = &job->work; 1537154Sigor@sysoev.ru 1538153Sigor@sysoev.ru job->task = tmcf->engine->task; 1539153Sigor@sysoev.ru job->work.handler = handler; 1540153Sigor@sysoev.ru job->work.task = &job->task; 1541153Sigor@sysoev.ru job->work.obj = job; 1542153Sigor@sysoev.ru job->tmcf = tmcf; 154353Sigor@sysoev.ru 1544154Sigor@sysoev.ru tmcf->count++; 1545154Sigor@sysoev.ru 1546154Sigor@sysoev.ru joint = nxt_mp_alloc(tmcf->conf->mem_pool, 1547154Sigor@sysoev.ru sizeof(nxt_socket_conf_joint_t)); 154853Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 154953Sigor@sysoev.ru return NXT_ERROR; 155053Sigor@sysoev.ru } 155153Sigor@sysoev.ru 1552153Sigor@sysoev.ru job->work.data = joint; 155353Sigor@sysoev.ru 155453Sigor@sysoev.ru joint->count = 1; 1555155Sigor@sysoev.ru 1556155Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1557155Sigor@sysoev.ru skcf->count++; 1558155Sigor@sysoev.ru joint->socket_conf = skcf; 1559155Sigor@sysoev.ru 156088Smax.romanov@nginx.com joint->engine = recf->engine; 156153Sigor@sysoev.ru } 156253Sigor@sysoev.ru 156320Sigor@sysoev.ru return NXT_OK; 156420Sigor@sysoev.ru } 156520Sigor@sysoev.ru 156620Sigor@sysoev.ru 1567115Sigor@sysoev.ru static void 1568115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 1569115Sigor@sysoev.ru { 1570115Sigor@sysoev.ru nxt_queue_link_t *qlk; 1571115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1572115Sigor@sysoev.ru 1573115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 1574115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 1575115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 1576115Sigor@sysoev.ru { 1577115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1578115Sigor@sysoev.ru skcf->socket->count++; 1579115Sigor@sysoev.ru } 1580115Sigor@sysoev.ru } 1581115Sigor@sysoev.ru 1582115Sigor@sysoev.ru 158320Sigor@sysoev.ru static nxt_int_t 1584313Sigor@sysoev.ru nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 1585313Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 1586313Sigor@sysoev.ru { 1587313Sigor@sysoev.ru nxt_joint_job_t *job; 1588313Sigor@sysoev.ru 1589313Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 1590313Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) { 1591313Sigor@sysoev.ru return NXT_ERROR; 1592313Sigor@sysoev.ru } 1593313Sigor@sysoev.ru 1594313Sigor@sysoev.ru job->work.next = recf->jobs; 1595313Sigor@sysoev.ru recf->jobs = &job->work; 1596313Sigor@sysoev.ru 1597313Sigor@sysoev.ru job->task = tmcf->engine->task; 1598313Sigor@sysoev.ru job->work.handler = nxt_router_worker_thread_quit; 1599313Sigor@sysoev.ru job->work.task = &job->task; 1600313Sigor@sysoev.ru job->work.obj = NULL; 1601313Sigor@sysoev.ru job->work.data = NULL; 1602313Sigor@sysoev.ru job->tmcf = NULL; 1603313Sigor@sysoev.ru 1604313Sigor@sysoev.ru return NXT_OK; 1605313Sigor@sysoev.ru } 1606313Sigor@sysoev.ru 1607313Sigor@sysoev.ru 1608313Sigor@sysoev.ru static nxt_int_t 1609139Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 1610139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 161120Sigor@sysoev.ru { 1612153Sigor@sysoev.ru nxt_joint_job_t *job; 161353Sigor@sysoev.ru nxt_queue_link_t *qlk; 161420Sigor@sysoev.ru 161553Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 161653Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 161753Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 161853Sigor@sysoev.ru { 1619154Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 1620153Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) { 1621139Sigor@sysoev.ru return NXT_ERROR; 1622139Sigor@sysoev.ru } 1623139Sigor@sysoev.ru 1624154Sigor@sysoev.ru job->work.next = recf->jobs; 1625154Sigor@sysoev.ru recf->jobs = &job->work; 1626154Sigor@sysoev.ru 1627153Sigor@sysoev.ru job->task = tmcf->engine->task; 1628153Sigor@sysoev.ru job->work.handler = nxt_router_listen_socket_delete; 1629153Sigor@sysoev.ru job->work.task = &job->task; 1630153Sigor@sysoev.ru job->work.obj = job; 1631153Sigor@sysoev.ru job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1632153Sigor@sysoev.ru job->tmcf = tmcf; 1633154Sigor@sysoev.ru 1634154Sigor@sysoev.ru tmcf->count++; 163520Sigor@sysoev.ru } 163620Sigor@sysoev.ru 163753Sigor@sysoev.ru return NXT_OK; 163853Sigor@sysoev.ru } 163920Sigor@sysoev.ru 164020Sigor@sysoev.ru 164153Sigor@sysoev.ru static nxt_int_t 164253Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 164353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 164453Sigor@sysoev.ru { 164553Sigor@sysoev.ru nxt_int_t ret; 164653Sigor@sysoev.ru nxt_uint_t i, threads; 164753Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 164820Sigor@sysoev.ru 164953Sigor@sysoev.ru recf = tmcf->engines->elts; 165053Sigor@sysoev.ru threads = tmcf->conf->threads; 165120Sigor@sysoev.ru 165253Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 165353Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 165453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 165553Sigor@sysoev.ru return ret; 165653Sigor@sysoev.ru } 165720Sigor@sysoev.ru } 165820Sigor@sysoev.ru 165920Sigor@sysoev.ru return NXT_OK; 166020Sigor@sysoev.ru } 166153Sigor@sysoev.ru 166253Sigor@sysoev.ru 166353Sigor@sysoev.ru static nxt_int_t 166453Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 166553Sigor@sysoev.ru nxt_event_engine_t *engine) 166653Sigor@sysoev.ru { 166753Sigor@sysoev.ru nxt_int_t ret; 166853Sigor@sysoev.ru nxt_thread_link_t *link; 166953Sigor@sysoev.ru nxt_thread_handle_t handle; 167053Sigor@sysoev.ru 167153Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 167253Sigor@sysoev.ru 167353Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 167453Sigor@sysoev.ru return NXT_ERROR; 167553Sigor@sysoev.ru } 167653Sigor@sysoev.ru 167753Sigor@sysoev.ru link->start = nxt_router_thread_start; 167853Sigor@sysoev.ru link->engine = engine; 167953Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 168053Sigor@sysoev.ru link->work.task = task; 168153Sigor@sysoev.ru link->work.data = link; 168253Sigor@sysoev.ru 168353Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 168453Sigor@sysoev.ru 168553Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 168653Sigor@sysoev.ru 168753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 168853Sigor@sysoev.ru nxt_queue_remove(&engine->link); 168953Sigor@sysoev.ru } 169053Sigor@sysoev.ru 169153Sigor@sysoev.ru return ret; 169253Sigor@sysoev.ru } 169353Sigor@sysoev.ru 169453Sigor@sysoev.ru 169553Sigor@sysoev.ru static void 1696133Sigor@sysoev.ru nxt_router_apps_sort(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 1697133Sigor@sysoev.ru { 1698167Smax.romanov@nginx.com nxt_app_t *app; 1699167Smax.romanov@nginx.com nxt_port_t *port; 1700141Smax.romanov@nginx.com 1701141Smax.romanov@nginx.com nxt_queue_each(app, &router->apps, nxt_app_t, link) { 1702133Sigor@sysoev.ru 1703133Sigor@sysoev.ru nxt_queue_remove(&app->link); 1704133Sigor@sysoev.ru 1705167Smax.romanov@nginx.com nxt_thread_log_debug("about to remove app '%V' %p", &app->name, app); 1706167Smax.romanov@nginx.com 1707163Smax.romanov@nginx.com app->live = 0; 1708163Smax.romanov@nginx.com 1709167Smax.romanov@nginx.com if (nxt_router_app_free(NULL, app) != 0) { 1710163Smax.romanov@nginx.com continue; 1711163Smax.romanov@nginx.com } 1712163Smax.romanov@nginx.com 1713167Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 1714167Smax.romanov@nginx.com 1715167Smax.romanov@nginx.com nxt_thread_log_debug("app '%V' %p pending requests found", 1716167Smax.romanov@nginx.com &app->name, app); 1717167Smax.romanov@nginx.com continue; 1718163Smax.romanov@nginx.com } 1719163Smax.romanov@nginx.com 1720167Smax.romanov@nginx.com do { 1721167Smax.romanov@nginx.com port = nxt_router_app_get_port(app, 0); 1722167Smax.romanov@nginx.com if (port == NULL) { 1723167Smax.romanov@nginx.com break; 1724167Smax.romanov@nginx.com } 1725167Smax.romanov@nginx.com 1726167Smax.romanov@nginx.com nxt_thread_log_debug("port %p send quit", port); 1727167Smax.romanov@nginx.com 1728167Smax.romanov@nginx.com nxt_port_socket_write(&port->engine->task, port, 1729167Smax.romanov@nginx.com NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 1730167Smax.romanov@nginx.com } while (1); 1731167Smax.romanov@nginx.com 1732141Smax.romanov@nginx.com } nxt_queue_loop; 1733133Sigor@sysoev.ru 1734133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous); 1735133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps); 1736133Sigor@sysoev.ru } 1737133Sigor@sysoev.ru 1738133Sigor@sysoev.ru 1739133Sigor@sysoev.ru static void 1740315Sigor@sysoev.ru nxt_router_engines_post(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 174153Sigor@sysoev.ru { 174253Sigor@sysoev.ru nxt_uint_t n; 1743315Sigor@sysoev.ru nxt_event_engine_t *engine; 174453Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 174553Sigor@sysoev.ru 174653Sigor@sysoev.ru recf = tmcf->engines->elts; 174753Sigor@sysoev.ru 174853Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 1749315Sigor@sysoev.ru engine = recf->engine; 1750315Sigor@sysoev.ru 1751315Sigor@sysoev.ru switch (recf->action) { 1752315Sigor@sysoev.ru 1753315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_KEEP: 1754315Sigor@sysoev.ru break; 1755315Sigor@sysoev.ru 1756315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_ADD: 1757315Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &engine->link0); 1758315Sigor@sysoev.ru break; 1759315Sigor@sysoev.ru 1760315Sigor@sysoev.ru case NXT_ROUTER_ENGINE_DELETE: 1761315Sigor@sysoev.ru nxt_queue_remove(&engine->link0); 1762315Sigor@sysoev.ru break; 1763315Sigor@sysoev.ru } 1764315Sigor@sysoev.ru 1765316Sigor@sysoev.ru nxt_router_engine_post(engine, recf->jobs); 1766316Sigor@sysoev.ru 176753Sigor@sysoev.ru recf++; 176853Sigor@sysoev.ru } 176953Sigor@sysoev.ru } 177053Sigor@sysoev.ru 177153Sigor@sysoev.ru 177253Sigor@sysoev.ru static void 1773315Sigor@sysoev.ru nxt_router_engine_post(nxt_event_engine_t *engine, nxt_work_t *jobs) 177453Sigor@sysoev.ru { 1775154Sigor@sysoev.ru nxt_work_t *work, *next; 1776154Sigor@sysoev.ru 1777315Sigor@sysoev.ru for (work = jobs; work != NULL; work = next) { 1778154Sigor@sysoev.ru next = work->next; 1779154Sigor@sysoev.ru work->next = NULL; 1780154Sigor@sysoev.ru 1781315Sigor@sysoev.ru nxt_event_engine_post(engine, work); 178253Sigor@sysoev.ru } 178353Sigor@sysoev.ru } 178453Sigor@sysoev.ru 178553Sigor@sysoev.ru 1786119Smax.romanov@nginx.com static nxt_port_handler_t nxt_router_app_port_handlers[] = { 1787192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_QUIT */ 1788192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_NEW_PORT */ 1789192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_CHANGE_FILE */ 1790192Smax.romanov@nginx.com /* TODO: remove mmap_handler from app ports */ 1791192Smax.romanov@nginx.com nxt_port_mmap_handler, /* NXT_PORT_MSG_MMAP */ 1792*318Smax.romanov@nginx.com nxt_port_rpc_handler, /* NXT_PORT_MSG_DATA */ 1793192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_REMOVE_PID */ 1794192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_READY */ 1795192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_START_WORKER */ 1796317Svbart@nginx.com NULL, /* NXT_PORT_MSG_SOCKET */ 1797317Svbart@nginx.com NULL, /* NXT_PORT_MSG_MODULES */ 1798317Svbart@nginx.com NULL, /* NXT_PORT_MSG_CONF_STORE */ 1799190Smax.romanov@nginx.com nxt_port_rpc_handler, 1800190Smax.romanov@nginx.com nxt_port_rpc_handler, 180188Smax.romanov@nginx.com }; 180288Smax.romanov@nginx.com 180388Smax.romanov@nginx.com 180488Smax.romanov@nginx.com static void 180553Sigor@sysoev.ru nxt_router_thread_start(void *data) 180653Sigor@sysoev.ru { 1807141Smax.romanov@nginx.com nxt_int_t ret; 1808141Smax.romanov@nginx.com nxt_port_t *port; 180988Smax.romanov@nginx.com nxt_task_t *task; 181053Sigor@sysoev.ru nxt_thread_t *thread; 181153Sigor@sysoev.ru nxt_thread_link_t *link; 181253Sigor@sysoev.ru nxt_event_engine_t *engine; 181353Sigor@sysoev.ru 181453Sigor@sysoev.ru link = data; 181553Sigor@sysoev.ru engine = link->engine; 181688Smax.romanov@nginx.com task = &engine->task; 181753Sigor@sysoev.ru 181853Sigor@sysoev.ru thread = nxt_thread(); 181953Sigor@sysoev.ru 1820165Smax.romanov@nginx.com nxt_event_engine_thread_adopt(engine); 1821165Smax.romanov@nginx.com 182253Sigor@sysoev.ru /* STUB */ 182353Sigor@sysoev.ru thread->runtime = engine->task.thread->runtime; 182453Sigor@sysoev.ru 182553Sigor@sysoev.ru engine->task.thread = thread; 182653Sigor@sysoev.ru engine->task.log = thread->log; 182753Sigor@sysoev.ru thread->engine = engine; 182863Sigor@sysoev.ru thread->task = &engine->task; 182953Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 183053Sigor@sysoev.ru 183163Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 183253Sigor@sysoev.ru 1833197Smax.romanov@nginx.com port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, 1834197Smax.romanov@nginx.com NXT_PROCESS_ROUTER); 1835141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 1836141Smax.romanov@nginx.com return; 1837141Smax.romanov@nginx.com } 1838141Smax.romanov@nginx.com 1839141Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0); 1840141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 1841163Smax.romanov@nginx.com nxt_mp_release(port->mem_pool, port); 1842141Smax.romanov@nginx.com return; 1843141Smax.romanov@nginx.com } 1844141Smax.romanov@nginx.com 1845141Smax.romanov@nginx.com engine->port = port; 1846141Smax.romanov@nginx.com 1847141Smax.romanov@nginx.com nxt_port_enable(task, port, nxt_router_app_port_handlers); 1848141Smax.romanov@nginx.com 184953Sigor@sysoev.ru nxt_event_engine_start(engine); 185053Sigor@sysoev.ru } 185153Sigor@sysoev.ru 185253Sigor@sysoev.ru 185353Sigor@sysoev.ru static void 185453Sigor@sysoev.ru nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 185553Sigor@sysoev.ru { 1856153Sigor@sysoev.ru nxt_joint_job_t *job; 185753Sigor@sysoev.ru nxt_listen_event_t *listen; 185853Sigor@sysoev.ru nxt_listen_socket_t *ls; 185953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 186053Sigor@sysoev.ru 1861153Sigor@sysoev.ru job = obj; 186253Sigor@sysoev.ru joint = data; 186353Sigor@sysoev.ru 186453Sigor@sysoev.ru ls = &joint->socket_conf->listen; 186553Sigor@sysoev.ru 1866159Sigor@sysoev.ru nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); 1867159Sigor@sysoev.ru 186853Sigor@sysoev.ru listen = nxt_listen_event(task, ls); 186953Sigor@sysoev.ru if (nxt_slow_path(listen == NULL)) { 187053Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 187153Sigor@sysoev.ru return; 187253Sigor@sysoev.ru } 187353Sigor@sysoev.ru 187453Sigor@sysoev.ru listen->socket.data = joint; 1875139Sigor@sysoev.ru 1876153Sigor@sysoev.ru job->work.next = NULL; 1877153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1878153Sigor@sysoev.ru 1879153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 188053Sigor@sysoev.ru } 188153Sigor@sysoev.ru 188253Sigor@sysoev.ru 188353Sigor@sysoev.ru nxt_inline nxt_listen_event_t * 188453Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections, 188553Sigor@sysoev.ru nxt_socket_conf_t *skcf) 188653Sigor@sysoev.ru { 1887115Sigor@sysoev.ru nxt_socket_t fd; 1888115Sigor@sysoev.ru nxt_queue_link_t *qlk; 188953Sigor@sysoev.ru nxt_listen_event_t *listen; 189053Sigor@sysoev.ru 1891115Sigor@sysoev.ru fd = skcf->socket->fd; 189253Sigor@sysoev.ru 1893115Sigor@sysoev.ru for (qlk = nxt_queue_first(listen_connections); 1894115Sigor@sysoev.ru qlk != nxt_queue_tail(listen_connections); 1895115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 189653Sigor@sysoev.ru { 1897115Sigor@sysoev.ru listen = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 189853Sigor@sysoev.ru 1899115Sigor@sysoev.ru if (fd == listen->socket.fd) { 190053Sigor@sysoev.ru return listen; 190153Sigor@sysoev.ru } 190253Sigor@sysoev.ru } 190353Sigor@sysoev.ru 190453Sigor@sysoev.ru return NULL; 190553Sigor@sysoev.ru } 190653Sigor@sysoev.ru 190753Sigor@sysoev.ru 190853Sigor@sysoev.ru static void 190953Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 191053Sigor@sysoev.ru { 1911153Sigor@sysoev.ru nxt_joint_job_t *job; 191253Sigor@sysoev.ru nxt_event_engine_t *engine; 191353Sigor@sysoev.ru nxt_listen_event_t *listen; 191453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old; 191553Sigor@sysoev.ru 1916153Sigor@sysoev.ru job = obj; 191753Sigor@sysoev.ru joint = data; 191853Sigor@sysoev.ru 1919139Sigor@sysoev.ru engine = task->thread->engine; 1920139Sigor@sysoev.ru 1921159Sigor@sysoev.ru nxt_queue_insert_tail(&engine->joints, &joint->link); 1922159Sigor@sysoev.ru 192353Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, 192453Sigor@sysoev.ru joint->socket_conf); 192553Sigor@sysoev.ru 192653Sigor@sysoev.ru old = listen->socket.data; 192753Sigor@sysoev.ru listen->socket.data = joint; 1928177Sigor@sysoev.ru listen->listen = &joint->socket_conf->listen; 192953Sigor@sysoev.ru 1930153Sigor@sysoev.ru job->work.next = NULL; 1931153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1932153Sigor@sysoev.ru 1933153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 1934139Sigor@sysoev.ru 1935181Smax.romanov@nginx.com /* 1936181Smax.romanov@nginx.com * The task is allocated from configuration temporary 1937181Smax.romanov@nginx.com * memory pool so it can be freed after engine post operation. 1938181Smax.romanov@nginx.com */ 1939181Smax.romanov@nginx.com 1940181Smax.romanov@nginx.com nxt_router_conf_release(&engine->task, old); 194153Sigor@sysoev.ru } 194253Sigor@sysoev.ru 194353Sigor@sysoev.ru 194453Sigor@sysoev.ru static void 194553Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 194653Sigor@sysoev.ru { 1947153Sigor@sysoev.ru nxt_joint_job_t *job; 1948153Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1949153Sigor@sysoev.ru nxt_listen_event_t *listen; 1950153Sigor@sysoev.ru nxt_event_engine_t *engine; 1951153Sigor@sysoev.ru 1952153Sigor@sysoev.ru job = obj; 195353Sigor@sysoev.ru skcf = data; 195453Sigor@sysoev.ru 1955139Sigor@sysoev.ru engine = task->thread->engine; 1956139Sigor@sysoev.ru 195753Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, skcf); 195853Sigor@sysoev.ru 195953Sigor@sysoev.ru nxt_fd_event_delete(engine, &listen->socket); 196053Sigor@sysoev.ru 1961163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket delete: %d", engine, 1962163Smax.romanov@nginx.com listen->socket.fd); 1963163Smax.romanov@nginx.com 196453Sigor@sysoev.ru listen->timer.handler = nxt_router_listen_socket_close; 196553Sigor@sysoev.ru listen->timer.work_queue = &engine->fast_work_queue; 196653Sigor@sysoev.ru 196753Sigor@sysoev.ru nxt_timer_add(engine, &listen->timer, 0); 1968139Sigor@sysoev.ru 1969153Sigor@sysoev.ru job->work.next = NULL; 1970153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1971153Sigor@sysoev.ru 1972153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 197353Sigor@sysoev.ru } 197453Sigor@sysoev.ru 197553Sigor@sysoev.ru 197653Sigor@sysoev.ru static void 1977313Sigor@sysoev.ru nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, void *data) 1978313Sigor@sysoev.ru { 1979313Sigor@sysoev.ru nxt_event_engine_t *engine; 1980313Sigor@sysoev.ru 1981313Sigor@sysoev.ru nxt_debug(task, "router worker thread quit"); 1982313Sigor@sysoev.ru 1983313Sigor@sysoev.ru engine = task->thread->engine; 1984313Sigor@sysoev.ru 1985313Sigor@sysoev.ru engine->shutdown = 1; 1986313Sigor@sysoev.ru 1987313Sigor@sysoev.ru if (nxt_queue_is_empty(&engine->joints)) { 1988313Sigor@sysoev.ru nxt_thread_exit(task->thread); 1989313Sigor@sysoev.ru } 1990313Sigor@sysoev.ru } 1991313Sigor@sysoev.ru 1992313Sigor@sysoev.ru 1993313Sigor@sysoev.ru static void 199453Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 199553Sigor@sysoev.ru { 199653Sigor@sysoev.ru nxt_timer_t *timer; 199753Sigor@sysoev.ru nxt_listen_event_t *listen; 199853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 199953Sigor@sysoev.ru 200053Sigor@sysoev.ru timer = obj; 200153Sigor@sysoev.ru listen = nxt_timer_data(timer, nxt_listen_event_t, timer); 200253Sigor@sysoev.ru joint = listen->socket.data; 200353Sigor@sysoev.ru 2004163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, 2005163Smax.romanov@nginx.com listen->socket.fd); 2006163Smax.romanov@nginx.com 200753Sigor@sysoev.ru nxt_queue_remove(&listen->link); 2008123Smax.romanov@nginx.com 2009123Smax.romanov@nginx.com /* 'task' refers to listen->task and we cannot use after nxt_free() */ 2010123Smax.romanov@nginx.com task = &task->thread->engine->task; 2011123Smax.romanov@nginx.com 201253Sigor@sysoev.ru nxt_free(listen); 201353Sigor@sysoev.ru 201453Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 201553Sigor@sysoev.ru } 201653Sigor@sysoev.ru 201753Sigor@sysoev.ru 201853Sigor@sysoev.ru static void 201953Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, 202053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint) 202153Sigor@sysoev.ru { 2022118Sigor@sysoev.ru nxt_socket_conf_t *skcf; 2023115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 202453Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 202553Sigor@sysoev.ru 2026118Sigor@sysoev.ru skcf = joint->socket_conf; 2027118Sigor@sysoev.ru rtsk = skcf->socket; 2028118Sigor@sysoev.ru lock = &skcf->router_conf->router->lock; 202953Sigor@sysoev.ru 203053Sigor@sysoev.ru nxt_thread_spin_lock(lock); 203153Sigor@sysoev.ru 2032163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket release: rtsk->count %D", 2033163Smax.romanov@nginx.com task->thread->engine, rtsk->count); 2034163Smax.romanov@nginx.com 2035115Sigor@sysoev.ru if (--rtsk->count != 0) { 2036115Sigor@sysoev.ru rtsk = NULL; 203753Sigor@sysoev.ru } 203853Sigor@sysoev.ru 203953Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 204053Sigor@sysoev.ru 2041115Sigor@sysoev.ru if (rtsk != NULL) { 2042115Sigor@sysoev.ru nxt_socket_close(task, rtsk->fd); 2043115Sigor@sysoev.ru nxt_free(rtsk); 2044118Sigor@sysoev.ru skcf->socket = NULL; 204553Sigor@sysoev.ru } 204653Sigor@sysoev.ru 204753Sigor@sysoev.ru nxt_router_conf_release(task, joint); 204853Sigor@sysoev.ru } 204953Sigor@sysoev.ru 205053Sigor@sysoev.ru 205153Sigor@sysoev.ru static void 205253Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 205353Sigor@sysoev.ru { 2054156Sigor@sysoev.ru nxt_bool_t exit; 205553Sigor@sysoev.ru nxt_socket_conf_t *skcf; 205653Sigor@sysoev.ru nxt_router_conf_t *rtcf; 2057313Sigor@sysoev.ru nxt_event_engine_t *engine; 205853Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 205953Sigor@sysoev.ru 2060163Smax.romanov@nginx.com nxt_debug(task, "conf joint %p count: %D", joint, joint->count); 206153Sigor@sysoev.ru 206253Sigor@sysoev.ru if (--joint->count != 0) { 206353Sigor@sysoev.ru return; 206453Sigor@sysoev.ru } 206553Sigor@sysoev.ru 206653Sigor@sysoev.ru nxt_queue_remove(&joint->link); 206753Sigor@sysoev.ru 206853Sigor@sysoev.ru skcf = joint->socket_conf; 206953Sigor@sysoev.ru rtcf = skcf->router_conf; 207053Sigor@sysoev.ru lock = &rtcf->router->lock; 207153Sigor@sysoev.ru 207253Sigor@sysoev.ru nxt_thread_spin_lock(lock); 207353Sigor@sysoev.ru 2074163Smax.romanov@nginx.com nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, 2075163Smax.romanov@nginx.com rtcf, rtcf->count); 2076163Smax.romanov@nginx.com 207753Sigor@sysoev.ru if (--skcf->count != 0) { 207853Sigor@sysoev.ru rtcf = NULL; 207953Sigor@sysoev.ru 208053Sigor@sysoev.ru } else { 208153Sigor@sysoev.ru nxt_queue_remove(&skcf->link); 208253Sigor@sysoev.ru 208353Sigor@sysoev.ru if (--rtcf->count != 0) { 208453Sigor@sysoev.ru rtcf = NULL; 208553Sigor@sysoev.ru } 208653Sigor@sysoev.ru } 208753Sigor@sysoev.ru 208853Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 208953Sigor@sysoev.ru 2090141Smax.romanov@nginx.com /* TODO remove engine->port */ 2091141Smax.romanov@nginx.com /* TODO excude from connected ports */ 2092141Smax.romanov@nginx.com 2093156Sigor@sysoev.ru /* The joint content can be used before memory pool destruction. */ 2094313Sigor@sysoev.ru engine = joint->engine; 2095313Sigor@sysoev.ru exit = (engine->shutdown && nxt_queue_is_empty(&engine->joints)); 2096156Sigor@sysoev.ru 209753Sigor@sysoev.ru if (rtcf != NULL) { 2098115Sigor@sysoev.ru nxt_debug(task, "old router conf is destroyed"); 2099131Smax.romanov@nginx.com 2100131Smax.romanov@nginx.com nxt_mp_thread_adopt(rtcf->mem_pool); 2101131Smax.romanov@nginx.com 210265Sigor@sysoev.ru nxt_mp_destroy(rtcf->mem_pool); 210353Sigor@sysoev.ru } 210453Sigor@sysoev.ru 2105156Sigor@sysoev.ru if (exit) { 210653Sigor@sysoev.ru nxt_thread_exit(task->thread); 210753Sigor@sysoev.ru } 210853Sigor@sysoev.ru } 210953Sigor@sysoev.ru 211053Sigor@sysoev.ru 211153Sigor@sysoev.ru static void 211253Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 211353Sigor@sysoev.ru { 2114141Smax.romanov@nginx.com nxt_port_t *port; 211553Sigor@sysoev.ru nxt_thread_link_t *link; 211653Sigor@sysoev.ru nxt_event_engine_t *engine; 211753Sigor@sysoev.ru nxt_thread_handle_t handle; 211853Sigor@sysoev.ru 211958Svbart@nginx.com handle = (nxt_thread_handle_t) obj; 212053Sigor@sysoev.ru link = data; 212153Sigor@sysoev.ru 212253Sigor@sysoev.ru nxt_thread_wait(handle); 212353Sigor@sysoev.ru 212453Sigor@sysoev.ru engine = link->engine; 212553Sigor@sysoev.ru 212653Sigor@sysoev.ru nxt_queue_remove(&engine->link); 212753Sigor@sysoev.ru 2128141Smax.romanov@nginx.com port = engine->port; 2129141Smax.romanov@nginx.com 2130141Smax.romanov@nginx.com // TODO notify all apps 2131141Smax.romanov@nginx.com 2132163Smax.romanov@nginx.com nxt_mp_thread_adopt(port->mem_pool); 2133163Smax.romanov@nginx.com nxt_port_release(port); 2134163Smax.romanov@nginx.com 2135163Smax.romanov@nginx.com nxt_mp_thread_adopt(engine->mem_pool); 213663Sigor@sysoev.ru nxt_mp_destroy(engine->mem_pool); 213753Sigor@sysoev.ru 213853Sigor@sysoev.ru nxt_event_engine_free(engine); 213953Sigor@sysoev.ru 214053Sigor@sysoev.ru nxt_free(link); 214153Sigor@sysoev.ru } 214253Sigor@sysoev.ru 214353Sigor@sysoev.ru 2144206Smax.romanov@nginx.com static const nxt_conn_state_t nxt_router_conn_read_header_state 214553Sigor@sysoev.ru nxt_aligned(64) = 214653Sigor@sysoev.ru { 214753Sigor@sysoev.ru .ready_handler = nxt_router_conn_http_header_parse, 214853Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 214953Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 215053Sigor@sysoev.ru 215153Sigor@sysoev.ru .timer_handler = nxt_router_conn_timeout, 215253Sigor@sysoev.ru .timer_value = nxt_router_conn_timeout_value, 215353Sigor@sysoev.ru .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 215453Sigor@sysoev.ru }; 215553Sigor@sysoev.ru 215653Sigor@sysoev.ru 2157206Smax.romanov@nginx.com static const nxt_conn_state_t nxt_router_conn_read_body_state 2158206Smax.romanov@nginx.com nxt_aligned(64) = 2159206Smax.romanov@nginx.com { 2160206Smax.romanov@nginx.com .ready_handler = nxt_router_conn_http_body_read, 2161206Smax.romanov@nginx.com .close_handler = nxt_router_conn_close, 2162206Smax.romanov@nginx.com .error_handler = nxt_router_conn_error, 2163206Smax.romanov@nginx.com 2164206Smax.romanov@nginx.com .timer_handler = nxt_router_conn_timeout, 2165206Smax.romanov@nginx.com .timer_value = nxt_router_conn_timeout_value, 2166206Smax.romanov@nginx.com .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout), 2167206Smax.romanov@nginx.com .timer_autoreset = 1, 2168206Smax.romanov@nginx.com }; 2169206Smax.romanov@nginx.com 2170206Smax.romanov@nginx.com 217153Sigor@sysoev.ru static void 217253Sigor@sysoev.ru nxt_router_conn_init(nxt_task_t *task, void *obj, void *data) 217353Sigor@sysoev.ru { 217453Sigor@sysoev.ru size_t size; 217562Sigor@sysoev.ru nxt_conn_t *c; 217653Sigor@sysoev.ru nxt_event_engine_t *engine; 217753Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 217853Sigor@sysoev.ru 217953Sigor@sysoev.ru c = obj; 218053Sigor@sysoev.ru joint = data; 218153Sigor@sysoev.ru 218253Sigor@sysoev.ru nxt_debug(task, "router conn init"); 218353Sigor@sysoev.ru 218453Sigor@sysoev.ru joint->count++; 218553Sigor@sysoev.ru 218653Sigor@sysoev.ru size = joint->socket_conf->header_buffer_size; 218753Sigor@sysoev.ru c->read = nxt_buf_mem_alloc(c->mem_pool, size, 0); 218853Sigor@sysoev.ru 218953Sigor@sysoev.ru c->socket.data = NULL; 219053Sigor@sysoev.ru 219153Sigor@sysoev.ru engine = task->thread->engine; 219253Sigor@sysoev.ru c->read_work_queue = &engine->fast_work_queue; 219353Sigor@sysoev.ru c->write_work_queue = &engine->fast_work_queue; 219453Sigor@sysoev.ru 2195206Smax.romanov@nginx.com c->read_state = &nxt_router_conn_read_header_state; 219653Sigor@sysoev.ru 219762Sigor@sysoev.ru nxt_conn_read(engine, c); 219853Sigor@sysoev.ru } 219953Sigor@sysoev.ru 220053Sigor@sysoev.ru 220162Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_write_state 220253Sigor@sysoev.ru nxt_aligned(64) = 220353Sigor@sysoev.ru { 220488Smax.romanov@nginx.com .ready_handler = nxt_router_conn_ready, 220553Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 220653Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 220753Sigor@sysoev.ru }; 220853Sigor@sysoev.ru 220953Sigor@sysoev.ru 221053Sigor@sysoev.ru static void 2211*318Smax.romanov@nginx.com nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2212*318Smax.romanov@nginx.com void *data) 221388Smax.romanov@nginx.com { 221488Smax.romanov@nginx.com size_t dump_size; 2215194Smax.romanov@nginx.com nxt_buf_t *b, *last; 221688Smax.romanov@nginx.com nxt_conn_t *c; 221788Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 221888Smax.romanov@nginx.com 221988Smax.romanov@nginx.com b = msg->buf; 2220*318Smax.romanov@nginx.com rc = data; 222188Smax.romanov@nginx.com 222288Smax.romanov@nginx.com c = rc->conn; 222388Smax.romanov@nginx.com 222488Smax.romanov@nginx.com dump_size = nxt_buf_used_size(b); 222588Smax.romanov@nginx.com 222688Smax.romanov@nginx.com if (dump_size > 300) { 222788Smax.romanov@nginx.com dump_size = 300; 222888Smax.romanov@nginx.com } 222988Smax.romanov@nginx.com 2230119Smax.romanov@nginx.com nxt_debug(task, "%srouter app data (%z): %*s", 223188Smax.romanov@nginx.com msg->port_msg.last ? "last " : "", msg->size, dump_size, 223288Smax.romanov@nginx.com b->mem.pos); 223388Smax.romanov@nginx.com 223488Smax.romanov@nginx.com if (msg->size == 0) { 223588Smax.romanov@nginx.com b = NULL; 223688Smax.romanov@nginx.com } 223788Smax.romanov@nginx.com 223888Smax.romanov@nginx.com if (msg->port_msg.last != 0) { 223988Smax.romanov@nginx.com nxt_debug(task, "router data create last buf"); 224088Smax.romanov@nginx.com 224188Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 224288Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 224388Smax.romanov@nginx.com /* TODO pogorevaTb */ 224488Smax.romanov@nginx.com } 224588Smax.romanov@nginx.com 224688Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 2247167Smax.romanov@nginx.com 2248167Smax.romanov@nginx.com if (rc->app_port != NULL) { 2249167Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 2250167Smax.romanov@nginx.com 2251167Smax.romanov@nginx.com rc->app_port = NULL; 2252167Smax.romanov@nginx.com } 2253206Smax.romanov@nginx.com 2254*318Smax.romanov@nginx.com nxt_router_rc_unlink(rc); 225588Smax.romanov@nginx.com } 225688Smax.romanov@nginx.com 225788Smax.romanov@nginx.com if (b == NULL) { 225888Smax.romanov@nginx.com return; 225988Smax.romanov@nginx.com } 226088Smax.romanov@nginx.com 2261206Smax.romanov@nginx.com if (msg->buf == b) { 2262206Smax.romanov@nginx.com /* Disable instant buffer completion/re-using by port. */ 2263206Smax.romanov@nginx.com msg->buf = NULL; 2264206Smax.romanov@nginx.com } 2265194Smax.romanov@nginx.com 226688Smax.romanov@nginx.com if (c->write == NULL) { 226788Smax.romanov@nginx.com c->write = b; 226888Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 226988Smax.romanov@nginx.com 227088Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 2271277Sigor@sysoev.ru 227288Smax.romanov@nginx.com } else { 227388Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 227488Smax.romanov@nginx.com 227588Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 227688Smax.romanov@nginx.com } 227788Smax.romanov@nginx.com } 227888Smax.romanov@nginx.com 2279277Sigor@sysoev.ru 2280*318Smax.romanov@nginx.com static void 2281*318Smax.romanov@nginx.com nxt_router_response_error_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2282*318Smax.romanov@nginx.com void *data) 2283*318Smax.romanov@nginx.com { 2284*318Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 2285*318Smax.romanov@nginx.com 2286*318Smax.romanov@nginx.com rc = data; 2287*318Smax.romanov@nginx.com 2288*318Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2289*318Smax.romanov@nginx.com "Application terminated unexpectedly"); 2290*318Smax.romanov@nginx.com 2291*318Smax.romanov@nginx.com nxt_router_rc_unlink(rc); 2292*318Smax.romanov@nginx.com } 2293*318Smax.romanov@nginx.com 2294*318Smax.romanov@nginx.com 2295141Smax.romanov@nginx.com nxt_inline const char * 2296141Smax.romanov@nginx.com nxt_router_text_by_code(int code) 2297141Smax.romanov@nginx.com { 2298141Smax.romanov@nginx.com switch (code) { 2299141Smax.romanov@nginx.com case 400: return "Bad request"; 2300141Smax.romanov@nginx.com case 404: return "Not found"; 2301141Smax.romanov@nginx.com case 403: return "Forbidden"; 2302206Smax.romanov@nginx.com case 408: return "Request Timeout"; 2303206Smax.romanov@nginx.com case 411: return "Length Required"; 2304206Smax.romanov@nginx.com case 413: return "Request Entity Too Large"; 2305141Smax.romanov@nginx.com case 500: 2306141Smax.romanov@nginx.com default: return "Internal server error"; 2307141Smax.romanov@nginx.com } 2308141Smax.romanov@nginx.com } 2309141Smax.romanov@nginx.com 2310163Smax.romanov@nginx.com 2311163Smax.romanov@nginx.com static nxt_buf_t * 2312163Smax.romanov@nginx.com nxt_router_get_error_buf(nxt_task_t *task, nxt_mp_t *mp, int code, 2313163Smax.romanov@nginx.com const char* fmt, va_list args) 231488Smax.romanov@nginx.com { 2315163Smax.romanov@nginx.com nxt_buf_t *b, *last; 2316163Smax.romanov@nginx.com const char *msg; 2317163Smax.romanov@nginx.com 2318163Smax.romanov@nginx.com b = nxt_buf_mem_ts_alloc(task, mp, 16384); 2319141Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 2320163Smax.romanov@nginx.com return NULL; 2321141Smax.romanov@nginx.com } 2322141Smax.romanov@nginx.com 2323141Smax.romanov@nginx.com b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, 2324141Smax.romanov@nginx.com "HTTP/1.0 %d %s\r\n" 2325141Smax.romanov@nginx.com "Content-Type: text/plain\r\n" 2326141Smax.romanov@nginx.com "Connection: close\r\n\r\n", 2327141Smax.romanov@nginx.com code, nxt_router_text_by_code(code)); 2328141Smax.romanov@nginx.com 2329141Smax.romanov@nginx.com msg = (const char *) b->mem.free; 2330141Smax.romanov@nginx.com 2331141Smax.romanov@nginx.com b->mem.free = nxt_vsprintf(b->mem.free, b->mem.end, fmt, args); 2332206Smax.romanov@nginx.com b->mem.free[0] = '\0'; 2333141Smax.romanov@nginx.com 2334141Smax.romanov@nginx.com nxt_log_alert(task->log, "error %d: %s", code, msg); 2335141Smax.romanov@nginx.com 2336163Smax.romanov@nginx.com last = nxt_buf_mem_ts_alloc(task, mp, 0); 2337163Smax.romanov@nginx.com 2338141Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 2339163Smax.romanov@nginx.com nxt_mp_release(mp, b); 2340163Smax.romanov@nginx.com return NULL; 2341141Smax.romanov@nginx.com } 2342141Smax.romanov@nginx.com 2343163Smax.romanov@nginx.com nxt_buf_set_sync(last); 2344163Smax.romanov@nginx.com nxt_buf_set_last(last); 2345163Smax.romanov@nginx.com 2346141Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 2347141Smax.romanov@nginx.com 2348163Smax.romanov@nginx.com return b; 2349163Smax.romanov@nginx.com } 2350163Smax.romanov@nginx.com 2351163Smax.romanov@nginx.com 2352163Smax.romanov@nginx.com 2353163Smax.romanov@nginx.com static void 2354163Smax.romanov@nginx.com nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 2355163Smax.romanov@nginx.com const char* fmt, ...) 2356163Smax.romanov@nginx.com { 2357163Smax.romanov@nginx.com va_list args; 2358*318Smax.romanov@nginx.com nxt_mp_t *mp; 2359163Smax.romanov@nginx.com nxt_buf_t *b; 2360163Smax.romanov@nginx.com 2361*318Smax.romanov@nginx.com /* TODO: fix when called from main thread */ 2362*318Smax.romanov@nginx.com /* TODO: fix when called in the middle of response */ 2363*318Smax.romanov@nginx.com 2364*318Smax.romanov@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 2365*318Smax.romanov@nginx.com 2366163Smax.romanov@nginx.com va_start(args, fmt); 2367*318Smax.romanov@nginx.com b = nxt_router_get_error_buf(task, mp, code, fmt, args); 2368163Smax.romanov@nginx.com va_end(args); 2369163Smax.romanov@nginx.com 2370273Smax.romanov@nginx.com if (c->socket.fd == -1) { 2371*318Smax.romanov@nginx.com nxt_mp_release(mp, b->next); 2372*318Smax.romanov@nginx.com nxt_mp_release(mp, b); 2373273Smax.romanov@nginx.com return; 2374273Smax.romanov@nginx.com } 2375273Smax.romanov@nginx.com 2376141Smax.romanov@nginx.com if (c->write == NULL) { 2377141Smax.romanov@nginx.com c->write = b; 2378141Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 2379141Smax.romanov@nginx.com 2380141Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 2381277Sigor@sysoev.ru 2382141Smax.romanov@nginx.com } else { 2383141Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 2384141Smax.romanov@nginx.com 2385141Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 2386141Smax.romanov@nginx.com } 2387141Smax.romanov@nginx.com } 2388141Smax.romanov@nginx.com 2389141Smax.romanov@nginx.com 2390141Smax.romanov@nginx.com static void 2391192Smax.romanov@nginx.com nxt_router_sw_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 2392192Smax.romanov@nginx.com { 2393192Smax.romanov@nginx.com nxt_start_worker_t *sw; 2394192Smax.romanov@nginx.com 2395192Smax.romanov@nginx.com sw = data; 2396192Smax.romanov@nginx.com 2397192Smax.romanov@nginx.com nxt_assert(sw != NULL); 2398192Smax.romanov@nginx.com nxt_assert(sw->app->pending_workers != 0); 2399192Smax.romanov@nginx.com 2400192Smax.romanov@nginx.com msg->new_port->app = sw->app; 2401192Smax.romanov@nginx.com 2402192Smax.romanov@nginx.com sw->app->pending_workers--; 2403192Smax.romanov@nginx.com sw->app->workers++; 2404192Smax.romanov@nginx.com 2405192Smax.romanov@nginx.com nxt_debug(task, "sw %p got port %p", sw, msg->new_port); 2406192Smax.romanov@nginx.com 2407192Smax.romanov@nginx.com nxt_router_app_release_port(task, msg->new_port, sw->app); 2408192Smax.romanov@nginx.com 2409192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2410192Smax.romanov@nginx.com } 2411192Smax.romanov@nginx.com 2412192Smax.romanov@nginx.com 2413192Smax.romanov@nginx.com static void 2414192Smax.romanov@nginx.com nxt_router_sw_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 2415192Smax.romanov@nginx.com { 2416*318Smax.romanov@nginx.com nxt_app_t *app; 2417*318Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2418*318Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2419192Smax.romanov@nginx.com nxt_start_worker_t *sw; 2420192Smax.romanov@nginx.com 2421192Smax.romanov@nginx.com sw = data; 2422192Smax.romanov@nginx.com 2423192Smax.romanov@nginx.com nxt_assert(sw != NULL); 2424*318Smax.romanov@nginx.com nxt_assert(sw->app != NULL); 2425192Smax.romanov@nginx.com nxt_assert(sw->app->pending_workers != 0); 2426192Smax.romanov@nginx.com 2427*318Smax.romanov@nginx.com app = sw->app; 2428*318Smax.romanov@nginx.com 2429192Smax.romanov@nginx.com sw->app->pending_workers--; 2430192Smax.romanov@nginx.com 2431277Sigor@sysoev.ru nxt_debug(task, "sw %p error, failed to start app '%V'", 2432*318Smax.romanov@nginx.com sw, &app->name); 2433*318Smax.romanov@nginx.com 2434*318Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 2435*318Smax.romanov@nginx.com lnk = nxt_queue_last(&app->requests); 2436*318Smax.romanov@nginx.com nxt_queue_remove(lnk); 2437*318Smax.romanov@nginx.com 2438*318Smax.romanov@nginx.com ra = nxt_queue_link_data(lnk, nxt_req_app_link_t, link); 2439*318Smax.romanov@nginx.com 2440*318Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p abort next stream #%uD", 2441*318Smax.romanov@nginx.com &app->name, app, ra->stream); 2442*318Smax.romanov@nginx.com 2443*318Smax.romanov@nginx.com nxt_router_ra_abort(task, ra, ra->work.data); 2444*318Smax.romanov@nginx.com } 2445192Smax.romanov@nginx.com 2446192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2447192Smax.romanov@nginx.com } 2448192Smax.romanov@nginx.com 2449192Smax.romanov@nginx.com 2450192Smax.romanov@nginx.com static void 2451141Smax.romanov@nginx.com nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data) 2452141Smax.romanov@nginx.com { 2453174Sigor@sysoev.ru size_t size; 2454192Smax.romanov@nginx.com uint32_t stream; 2455141Smax.romanov@nginx.com nxt_buf_t *b; 2456141Smax.romanov@nginx.com nxt_app_t *app; 2457274Smax.romanov@nginx.com nxt_port_t *main_port, *router_port, *app_port; 2458141Smax.romanov@nginx.com nxt_runtime_t *rt; 2459141Smax.romanov@nginx.com nxt_start_worker_t *sw; 2460274Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2461141Smax.romanov@nginx.com 2462141Smax.romanov@nginx.com sw = obj; 2463141Smax.romanov@nginx.com app = sw->app; 2464141Smax.romanov@nginx.com 2465274Smax.romanov@nginx.com if (nxt_queue_is_empty(&app->requests)) { 2466274Smax.romanov@nginx.com ra = sw->ra; 2467*318Smax.romanov@nginx.com app_port = nxt_router_app_get_port(app, ra->stream); 2468274Smax.romanov@nginx.com 2469274Smax.romanov@nginx.com if (app_port != NULL) { 2470*318Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p process stream #%uD", 2471*318Smax.romanov@nginx.com &app->name, app, ra->stream); 2472274Smax.romanov@nginx.com 2473274Smax.romanov@nginx.com ra->app_port = app_port; 2474274Smax.romanov@nginx.com 2475274Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, ra, app_port); 2476274Smax.romanov@nginx.com 2477274Smax.romanov@nginx.com nxt_router_ra_release(task, ra, ra->work.data); 2478274Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2479274Smax.romanov@nginx.com 2480274Smax.romanov@nginx.com return; 2481274Smax.romanov@nginx.com } 2482274Smax.romanov@nginx.com } 2483274Smax.romanov@nginx.com 2484167Smax.romanov@nginx.com nxt_queue_insert_tail(&app->requests, &sw->ra->link); 2485167Smax.romanov@nginx.com 2486163Smax.romanov@nginx.com if (app->workers + app->pending_workers >= app->max_workers) { 2487244Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p %uD/%uD running/pending workers, " 2488244Smax.romanov@nginx.com "max_workers (%uD) reached", &app->name, app, 2489244Smax.romanov@nginx.com app->workers, app->pending_workers, app->max_workers); 2490192Smax.romanov@nginx.com 2491192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2492163Smax.romanov@nginx.com 2493163Smax.romanov@nginx.com return; 2494163Smax.romanov@nginx.com } 2495163Smax.romanov@nginx.com 2496163Smax.romanov@nginx.com app->pending_workers++; 2497163Smax.romanov@nginx.com 2498192Smax.romanov@nginx.com nxt_debug(task, "sw %p send", sw); 249988Smax.romanov@nginx.com 2500119Smax.romanov@nginx.com rt = task->thread->runtime; 2501240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2502192Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2503141Smax.romanov@nginx.com 2504174Sigor@sysoev.ru size = app->name.length + 1 + app->conf.length; 2505174Sigor@sysoev.ru 2506240Sigor@sysoev.ru b = nxt_buf_mem_alloc(main_port->mem_pool, size, 0); 2507174Sigor@sysoev.ru 2508174Sigor@sysoev.ru nxt_buf_cpystr(b, &app->name); 2509174Sigor@sysoev.ru *b->mem.free++ = '\0'; 2510141Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 2511141Smax.romanov@nginx.com 2512192Smax.romanov@nginx.com stream = nxt_port_rpc_register_handler(task, router_port, 2513192Smax.romanov@nginx.com nxt_router_sw_ready, 2514192Smax.romanov@nginx.com nxt_router_sw_error, 2515240Sigor@sysoev.ru main_port->pid, sw); 2516240Sigor@sysoev.ru 2517240Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1, 2518192Smax.romanov@nginx.com stream, router_port->id, b); 2519141Smax.romanov@nginx.com } 2520141Smax.romanov@nginx.com 2521141Smax.romanov@nginx.com 2522163Smax.romanov@nginx.com static nxt_bool_t 2523167Smax.romanov@nginx.com nxt_router_app_free(nxt_task_t *task, nxt_app_t *app) 2524163Smax.romanov@nginx.com { 2525192Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2526192Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2527167Smax.romanov@nginx.com 2528167Smax.romanov@nginx.com nxt_thread_log_debug("app '%V' %p state: %d/%uD/%uD/%d", &app->name, app, 2529167Smax.romanov@nginx.com app->live, app->workers, app->pending_workers, 2530167Smax.romanov@nginx.com nxt_queue_is_empty(&app->requests)); 2531167Smax.romanov@nginx.com 2532277Sigor@sysoev.ru if (app->live == 0 2533277Sigor@sysoev.ru && app->workers == 0 2534277Sigor@sysoev.ru && app->pending_workers == 0 2535277Sigor@sysoev.ru && nxt_queue_is_empty(&app->requests)) 2536277Sigor@sysoev.ru { 2537163Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->mutex); 2538163Smax.romanov@nginx.com nxt_free(app); 2539163Smax.romanov@nginx.com 2540163Smax.romanov@nginx.com return 1; 2541163Smax.romanov@nginx.com } 2542163Smax.romanov@nginx.com 2543277Sigor@sysoev.ru if (app->live == 1 2544277Sigor@sysoev.ru && nxt_queue_is_empty(&app->requests) == 0 2545277Sigor@sysoev.ru && app->workers + app->pending_workers < app->max_workers) 2546277Sigor@sysoev.ru { 2547167Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 2548167Smax.romanov@nginx.com nxt_queue_remove(lnk); 2549167Smax.romanov@nginx.com 2550167Smax.romanov@nginx.com ra = nxt_queue_link_data(lnk, nxt_req_app_link_t, link); 2551167Smax.romanov@nginx.com 2552192Smax.romanov@nginx.com nxt_router_sw_create(task, app, ra); 2553167Smax.romanov@nginx.com } 2554167Smax.romanov@nginx.com 2555163Smax.romanov@nginx.com return 0; 2556163Smax.romanov@nginx.com } 2557163Smax.romanov@nginx.com 2558163Smax.romanov@nginx.com 2559141Smax.romanov@nginx.com static nxt_port_t * 2560*318Smax.romanov@nginx.com nxt_router_app_get_port(nxt_app_t *app, uint32_t stream) 2561141Smax.romanov@nginx.com { 2562141Smax.romanov@nginx.com nxt_port_t *port; 2563141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2564141Smax.romanov@nginx.com 2565141Smax.romanov@nginx.com port = NULL; 2566141Smax.romanov@nginx.com 2567141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2568141Smax.romanov@nginx.com 2569141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->ports)) { 2570141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->ports); 2571141Smax.romanov@nginx.com nxt_queue_remove(lnk); 2572141Smax.romanov@nginx.com 2573141Smax.romanov@nginx.com lnk->next = NULL; 2574141Smax.romanov@nginx.com 2575141Smax.romanov@nginx.com port = nxt_queue_link_data(lnk, nxt_port_t, app_link); 2576167Smax.romanov@nginx.com 2577*318Smax.romanov@nginx.com port->app_stream = stream; 2578141Smax.romanov@nginx.com } 2579141Smax.romanov@nginx.com 2580141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2581141Smax.romanov@nginx.com 2582141Smax.romanov@nginx.com return port; 2583141Smax.romanov@nginx.com } 2584141Smax.romanov@nginx.com 2585141Smax.romanov@nginx.com 2586141Smax.romanov@nginx.com static void 2587141Smax.romanov@nginx.com nxt_router_app_release_port(nxt_task_t *task, void *obj, void *data) 2588141Smax.romanov@nginx.com { 2589141Smax.romanov@nginx.com nxt_app_t *app; 2590141Smax.romanov@nginx.com nxt_port_t *port; 2591141Smax.romanov@nginx.com nxt_work_t *work; 2592141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2593167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2594141Smax.romanov@nginx.com 2595141Smax.romanov@nginx.com port = obj; 2596141Smax.romanov@nginx.com app = data; 2597141Smax.romanov@nginx.com 2598141Smax.romanov@nginx.com nxt_assert(app != NULL); 2599141Smax.romanov@nginx.com nxt_assert(app == port->app); 2600141Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 2601141Smax.romanov@nginx.com 2602141Smax.romanov@nginx.com 2603141Smax.romanov@nginx.com if (task->thread->engine != port->engine) { 2604163Smax.romanov@nginx.com work = &port->work; 2605141Smax.romanov@nginx.com 2606141Smax.romanov@nginx.com nxt_debug(task, "post release port to engine %p", port->engine); 2607141Smax.romanov@nginx.com 2608141Smax.romanov@nginx.com work->next = NULL; 2609141Smax.romanov@nginx.com work->handler = nxt_router_app_release_port; 2610166Smax.romanov@nginx.com work->task = &port->engine->task; 2611141Smax.romanov@nginx.com work->obj = port; 2612141Smax.romanov@nginx.com work->data = app; 2613141Smax.romanov@nginx.com 2614141Smax.romanov@nginx.com nxt_event_engine_post(port->engine, work); 2615141Smax.romanov@nginx.com 2616141Smax.romanov@nginx.com return; 2617141Smax.romanov@nginx.com } 2618141Smax.romanov@nginx.com 2619141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 2620141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 2621141Smax.romanov@nginx.com nxt_queue_remove(lnk); 2622141Smax.romanov@nginx.com 2623167Smax.romanov@nginx.com ra = nxt_queue_link_data(lnk, nxt_req_app_link_t, link); 2624167Smax.romanov@nginx.com 2625*318Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p process next stream #%uD", 2626*318Smax.romanov@nginx.com &app->name, app, ra->stream); 2627167Smax.romanov@nginx.com 2628167Smax.romanov@nginx.com ra->app_port = port; 2629*318Smax.romanov@nginx.com port->app_stream = ra->stream; 2630167Smax.romanov@nginx.com 2631167Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, ra, port); 2632167Smax.romanov@nginx.com 2633167Smax.romanov@nginx.com nxt_router_ra_release(task, ra, ra->work.data); 2634141Smax.romanov@nginx.com 2635141Smax.romanov@nginx.com return; 2636141Smax.romanov@nginx.com } 2637141Smax.romanov@nginx.com 2638*318Smax.romanov@nginx.com port->app_stream = 0; 2639167Smax.romanov@nginx.com 2640163Smax.romanov@nginx.com if (port->pair[1] == -1) { 2641167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p port already closed (pid %PI dead?)", 2642167Smax.romanov@nginx.com &app->name, app, port->pid); 2643163Smax.romanov@nginx.com 2644163Smax.romanov@nginx.com app->workers--; 2645167Smax.romanov@nginx.com nxt_router_app_free(task, app); 2646163Smax.romanov@nginx.com 2647163Smax.romanov@nginx.com port->app = NULL; 2648163Smax.romanov@nginx.com 2649163Smax.romanov@nginx.com nxt_port_release(port); 2650163Smax.romanov@nginx.com 2651163Smax.romanov@nginx.com return; 2652163Smax.romanov@nginx.com } 2653163Smax.romanov@nginx.com 2654163Smax.romanov@nginx.com if (!app->live) { 2655167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p is not alive, send QUIT to port", 2656167Smax.romanov@nginx.com &app->name, app); 2657163Smax.romanov@nginx.com 2658163Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, 2659163Smax.romanov@nginx.com -1, 0, 0, NULL); 2660163Smax.romanov@nginx.com 2661163Smax.romanov@nginx.com return; 2662163Smax.romanov@nginx.com } 2663163Smax.romanov@nginx.com 2664167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", 2665167Smax.romanov@nginx.com &app->name, app); 2666141Smax.romanov@nginx.com 2667141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2668141Smax.romanov@nginx.com 2669141Smax.romanov@nginx.com nxt_queue_insert_head(&app->ports, &port->app_link); 2670141Smax.romanov@nginx.com 2671141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2672141Smax.romanov@nginx.com } 2673141Smax.romanov@nginx.com 2674141Smax.romanov@nginx.com 2675163Smax.romanov@nginx.com nxt_bool_t 2676141Smax.romanov@nginx.com nxt_router_app_remove_port(nxt_port_t *port) 2677141Smax.romanov@nginx.com { 2678163Smax.romanov@nginx.com nxt_app_t *app; 2679163Smax.romanov@nginx.com nxt_bool_t busy; 2680141Smax.romanov@nginx.com 2681141Smax.romanov@nginx.com app = port->app; 2682*318Smax.romanov@nginx.com busy = port->app_stream != 0; 2683163Smax.romanov@nginx.com 2684163Smax.romanov@nginx.com if (app == NULL) { 2685167Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, no app", port); 2686167Smax.romanov@nginx.com 2687163Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 2688163Smax.romanov@nginx.com 2689163Smax.romanov@nginx.com return 1; 2690141Smax.romanov@nginx.com } 2691141Smax.romanov@nginx.com 2692141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2693141Smax.romanov@nginx.com 2694163Smax.romanov@nginx.com if (port->app_link.next != NULL) { 2695163Smax.romanov@nginx.com 2696163Smax.romanov@nginx.com nxt_queue_remove(&port->app_link); 2697163Smax.romanov@nginx.com port->app_link.next = NULL; 2698163Smax.romanov@nginx.com 2699163Smax.romanov@nginx.com } 2700141Smax.romanov@nginx.com 2701141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2702163Smax.romanov@nginx.com 2703163Smax.romanov@nginx.com if (busy == 0) { 2704167Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, free, app '%V' %p", port, 2705167Smax.romanov@nginx.com &app->name, app); 2706163Smax.romanov@nginx.com 2707163Smax.romanov@nginx.com app->workers--; 2708167Smax.romanov@nginx.com nxt_router_app_free(&port->engine->task, app); 2709163Smax.romanov@nginx.com 2710163Smax.romanov@nginx.com return 1; 2711163Smax.romanov@nginx.com } 2712163Smax.romanov@nginx.com 2713*318Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, busy, app '%V' %p, " 2714*318Smax.romanov@nginx.com "app stream #%uD", port, &app->name, app, 2715*318Smax.romanov@nginx.com port->app_stream); 2716167Smax.romanov@nginx.com 2717163Smax.romanov@nginx.com return 0; 2718141Smax.romanov@nginx.com } 2719141Smax.romanov@nginx.com 2720141Smax.romanov@nginx.com 2721167Smax.romanov@nginx.com static nxt_int_t 2722167Smax.romanov@nginx.com nxt_router_app_port(nxt_task_t *task, nxt_req_app_link_t *ra) 2723141Smax.romanov@nginx.com { 2724141Smax.romanov@nginx.com nxt_app_t *app; 2725141Smax.romanov@nginx.com nxt_conn_t *c; 2726167Smax.romanov@nginx.com nxt_port_t *port; 2727*318Smax.romanov@nginx.com nxt_event_engine_t *engine; 2728141Smax.romanov@nginx.com nxt_start_worker_t *sw; 2729141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 2730141Smax.romanov@nginx.com 2731141Smax.romanov@nginx.com port = NULL; 2732167Smax.romanov@nginx.com c = ra->rc->conn; 2733141Smax.romanov@nginx.com 2734141Smax.romanov@nginx.com joint = c->listen->socket.data; 2735141Smax.romanov@nginx.com app = joint->socket_conf->application; 2736141Smax.romanov@nginx.com 2737141Smax.romanov@nginx.com if (app == NULL) { 2738167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2739141Smax.romanov@nginx.com "Application is NULL in socket_conf"); 2740141Smax.romanov@nginx.com return NXT_ERROR; 2741141Smax.romanov@nginx.com } 2742141Smax.romanov@nginx.com 2743*318Smax.romanov@nginx.com engine = task->thread->engine; 2744*318Smax.romanov@nginx.com 2745*318Smax.romanov@nginx.com nxt_timer_disable(engine, &c->read_timer); 2746*318Smax.romanov@nginx.com 2747*318Smax.romanov@nginx.com if (app->timeout != 0) { 2748*318Smax.romanov@nginx.com c->read_timer.handler = nxt_router_app_timeout; 2749*318Smax.romanov@nginx.com nxt_timer_add(engine, &c->read_timer, app->timeout); 2750*318Smax.romanov@nginx.com } 2751*318Smax.romanov@nginx.com 2752*318Smax.romanov@nginx.com port = nxt_router_app_get_port(app, ra->stream); 2753141Smax.romanov@nginx.com 2754141Smax.romanov@nginx.com if (port != NULL) { 2755163Smax.romanov@nginx.com nxt_debug(task, "already have port for app '%V'", &app->name); 2756163Smax.romanov@nginx.com 2757167Smax.romanov@nginx.com ra->app_port = port; 2758141Smax.romanov@nginx.com return NXT_OK; 2759141Smax.romanov@nginx.com } 2760141Smax.romanov@nginx.com 2761192Smax.romanov@nginx.com sw = nxt_router_sw_create(task, app, ra); 2762141Smax.romanov@nginx.com 2763141Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 2764167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2765141Smax.romanov@nginx.com "Failed to allocate start worker struct"); 2766141Smax.romanov@nginx.com return NXT_ERROR; 2767141Smax.romanov@nginx.com } 2768141Smax.romanov@nginx.com 2769141Smax.romanov@nginx.com return NXT_AGAIN; 277088Smax.romanov@nginx.com } 277188Smax.romanov@nginx.com 277288Smax.romanov@nginx.com 277388Smax.romanov@nginx.com static void 277453Sigor@sysoev.ru nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, void *data) 277553Sigor@sysoev.ru { 2776206Smax.romanov@nginx.com size_t size; 277753Sigor@sysoev.ru nxt_int_t ret; 2778206Smax.romanov@nginx.com nxt_buf_t *buf; 277962Sigor@sysoev.ru nxt_conn_t *c; 2780268Sigor@sysoev.ru nxt_sockaddr_t *local; 278188Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2782206Smax.romanov@nginx.com nxt_app_request_body_t *b; 278353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 278488Smax.romanov@nginx.com nxt_app_request_header_t *h; 278553Sigor@sysoev.ru 278653Sigor@sysoev.ru c = obj; 278788Smax.romanov@nginx.com ap = data; 2788206Smax.romanov@nginx.com buf = c->read; 2789206Smax.romanov@nginx.com joint = c->listen->socket.data; 279053Sigor@sysoev.ru 279153Sigor@sysoev.ru nxt_debug(task, "router conn http header parse"); 279253Sigor@sysoev.ru 279388Smax.romanov@nginx.com if (ap == NULL) { 2794206Smax.romanov@nginx.com ap = nxt_mp_zalloc(c->mem_pool, sizeof(nxt_app_parse_ctx_t)); 279588Smax.romanov@nginx.com if (nxt_slow_path(ap == NULL)) { 279653Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 279753Sigor@sysoev.ru return; 279853Sigor@sysoev.ru } 279953Sigor@sysoev.ru 280088Smax.romanov@nginx.com ret = nxt_app_http_req_init(task, ap); 280161Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 280261Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 280361Sigor@sysoev.ru return; 280461Sigor@sysoev.ru } 280588Smax.romanov@nginx.com 280688Smax.romanov@nginx.com c->socket.data = ap; 2807113Smax.romanov@nginx.com 2808113Smax.romanov@nginx.com ap->r.remote.start = nxt_sockaddr_address(c->remote); 2809113Smax.romanov@nginx.com ap->r.remote.length = c->remote->address_length; 2810206Smax.romanov@nginx.com 2811268Sigor@sysoev.ru local = joint->socket_conf->sockaddr; 2812268Sigor@sysoev.ru ap->r.local.start = nxt_sockaddr_address(local); 2813268Sigor@sysoev.ru ap->r.local.length = local->address_length; 2814268Sigor@sysoev.ru 2815206Smax.romanov@nginx.com ap->r.header.buf = buf; 281653Sigor@sysoev.ru } 281753Sigor@sysoev.ru 281888Smax.romanov@nginx.com h = &ap->r.header; 2819206Smax.romanov@nginx.com b = &ap->r.body; 2820206Smax.romanov@nginx.com 2821206Smax.romanov@nginx.com ret = nxt_app_http_req_header_parse(task, ap, buf); 2822206Smax.romanov@nginx.com 2823206Smax.romanov@nginx.com nxt_debug(task, "http parse request header: %d", ret); 282453Sigor@sysoev.ru 282553Sigor@sysoev.ru switch (nxt_expect(NXT_DONE, ret)) { 282653Sigor@sysoev.ru 282753Sigor@sysoev.ru case NXT_DONE: 282888Smax.romanov@nginx.com nxt_debug(task, "router request header parsing complete, " 282988Smax.romanov@nginx.com "content length: %O, preread: %uz", 2830206Smax.romanov@nginx.com h->parsed_content_length, nxt_buf_mem_used_size(&buf->mem)); 2831206Smax.romanov@nginx.com 2832206Smax.romanov@nginx.com if (b->done) { 2833206Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 2834206Smax.romanov@nginx.com 2835206Smax.romanov@nginx.com return; 2836206Smax.romanov@nginx.com } 2837206Smax.romanov@nginx.com 2838277Sigor@sysoev.ru if (joint->socket_conf->max_body_size > 0 2839277Sigor@sysoev.ru && (size_t) h->parsed_content_length 2840277Sigor@sysoev.ru > joint->socket_conf->max_body_size) 2841277Sigor@sysoev.ru { 2842206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 413, "Content-Length too big"); 2843206Smax.romanov@nginx.com return; 2844206Smax.romanov@nginx.com } 2845206Smax.romanov@nginx.com 2846206Smax.romanov@nginx.com if (nxt_buf_mem_free_size(&buf->mem) == 0) { 2847206Smax.romanov@nginx.com size = nxt_min(joint->socket_conf->body_buffer_size, 2848206Smax.romanov@nginx.com (size_t) h->parsed_content_length); 2849206Smax.romanov@nginx.com 2850206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2851206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2852206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2853206Smax.romanov@nginx.com "buffer for request body"); 2854206Smax.romanov@nginx.com return; 2855206Smax.romanov@nginx.com } 2856206Smax.romanov@nginx.com 2857206Smax.romanov@nginx.com c->read = buf->next; 2858206Smax.romanov@nginx.com 2859206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 2860206Smax.romanov@nginx.com } 2861206Smax.romanov@nginx.com 2862206Smax.romanov@nginx.com if (b->buf == NULL) { 2863206Smax.romanov@nginx.com b->buf = c->read; 2864206Smax.romanov@nginx.com } 2865206Smax.romanov@nginx.com 2866206Smax.romanov@nginx.com c->read_state = &nxt_router_conn_read_body_state; 2867206Smax.romanov@nginx.com break; 2868206Smax.romanov@nginx.com 2869206Smax.romanov@nginx.com case NXT_ERROR: 2870206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 400, "Request header parse error"); 2871206Smax.romanov@nginx.com return; 2872206Smax.romanov@nginx.com 2873206Smax.romanov@nginx.com default: /* NXT_AGAIN */ 2874206Smax.romanov@nginx.com 2875206Smax.romanov@nginx.com if (c->read->mem.free == c->read->mem.end) { 2876206Smax.romanov@nginx.com size = joint->socket_conf->large_header_buffer_size; 2877206Smax.romanov@nginx.com 2878277Sigor@sysoev.ru if (size <= (size_t) nxt_buf_mem_used_size(&buf->mem) 2879277Sigor@sysoev.ru || ap->r.header.bufs 2880277Sigor@sysoev.ru >= joint->socket_conf->large_header_buffers) 2881277Sigor@sysoev.ru { 2882206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 413, 2883206Smax.romanov@nginx.com "Too long request headers"); 2884206Smax.romanov@nginx.com return; 2885206Smax.romanov@nginx.com } 2886206Smax.romanov@nginx.com 2887206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2888206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2889206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2890206Smax.romanov@nginx.com "Failed to allocate large header " 2891206Smax.romanov@nginx.com "buffer"); 2892206Smax.romanov@nginx.com return; 2893206Smax.romanov@nginx.com } 2894206Smax.romanov@nginx.com 2895206Smax.romanov@nginx.com ap->r.header.bufs++; 2896206Smax.romanov@nginx.com 2897206Smax.romanov@nginx.com size = c->read->mem.free - c->read->mem.pos; 2898206Smax.romanov@nginx.com 2899206Smax.romanov@nginx.com c->read = nxt_buf_cpy(buf->next, c->read->mem.pos, size); 2900206Smax.romanov@nginx.com } 2901206Smax.romanov@nginx.com 2902206Smax.romanov@nginx.com } 2903206Smax.romanov@nginx.com 2904206Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 2905206Smax.romanov@nginx.com } 2906206Smax.romanov@nginx.com 2907206Smax.romanov@nginx.com 2908206Smax.romanov@nginx.com static void 2909206Smax.romanov@nginx.com nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, void *data) 2910206Smax.romanov@nginx.com { 2911206Smax.romanov@nginx.com size_t size; 2912206Smax.romanov@nginx.com nxt_int_t ret; 2913206Smax.romanov@nginx.com nxt_buf_t *buf; 2914206Smax.romanov@nginx.com nxt_conn_t *c; 2915206Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2916206Smax.romanov@nginx.com nxt_app_request_body_t *b; 2917206Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 2918206Smax.romanov@nginx.com nxt_app_request_header_t *h; 2919206Smax.romanov@nginx.com 2920206Smax.romanov@nginx.com c = obj; 2921206Smax.romanov@nginx.com ap = data; 2922206Smax.romanov@nginx.com buf = c->read; 2923206Smax.romanov@nginx.com 2924206Smax.romanov@nginx.com nxt_debug(task, "router conn http body read"); 2925206Smax.romanov@nginx.com 2926206Smax.romanov@nginx.com nxt_assert(ap != NULL); 2927206Smax.romanov@nginx.com 2928206Smax.romanov@nginx.com b = &ap->r.body; 2929206Smax.romanov@nginx.com h = &ap->r.header; 2930206Smax.romanov@nginx.com 2931206Smax.romanov@nginx.com ret = nxt_app_http_req_body_read(task, ap, buf); 2932206Smax.romanov@nginx.com 2933206Smax.romanov@nginx.com nxt_debug(task, "http read request body: %d", ret); 2934206Smax.romanov@nginx.com 2935206Smax.romanov@nginx.com switch (nxt_expect(NXT_DONE, ret)) { 2936206Smax.romanov@nginx.com 2937206Smax.romanov@nginx.com case NXT_DONE: 293888Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 293988Smax.romanov@nginx.com return; 294053Sigor@sysoev.ru 294153Sigor@sysoev.ru case NXT_ERROR: 2942206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Read body error"); 294353Sigor@sysoev.ru return; 294453Sigor@sysoev.ru 294553Sigor@sysoev.ru default: /* NXT_AGAIN */ 294653Sigor@sysoev.ru 2947206Smax.romanov@nginx.com if (nxt_buf_mem_free_size(&buf->mem) == 0) { 2948206Smax.romanov@nginx.com joint = c->listen->socket.data; 2949206Smax.romanov@nginx.com 2950206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 2951206Smax.romanov@nginx.com 2952206Smax.romanov@nginx.com size = nxt_min(joint->socket_conf->body_buffer_size, 2953206Smax.romanov@nginx.com (size_t) h->parsed_content_length - b->preread_size); 2954206Smax.romanov@nginx.com 2955206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2956206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2957206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2958206Smax.romanov@nginx.com "buffer for request body"); 2959206Smax.romanov@nginx.com return; 296088Smax.romanov@nginx.com } 2961206Smax.romanov@nginx.com 2962206Smax.romanov@nginx.com c->read = buf->next; 296388Smax.romanov@nginx.com } 296488Smax.romanov@nginx.com 2965206Smax.romanov@nginx.com nxt_debug(task, "router request body read again, rest: %uz", 2966206Smax.romanov@nginx.com h->parsed_content_length - b->preread_size); 296788Smax.romanov@nginx.com } 296888Smax.romanov@nginx.com 296988Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 297088Smax.romanov@nginx.com } 297188Smax.romanov@nginx.com 297288Smax.romanov@nginx.com 297388Smax.romanov@nginx.com static void 297488Smax.romanov@nginx.com nxt_router_process_http_request(nxt_task_t *task, nxt_conn_t *c, 297588Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap) 297688Smax.romanov@nginx.com { 2977167Smax.romanov@nginx.com nxt_mp_t *port_mp; 2978122Smax.romanov@nginx.com nxt_int_t res; 2979167Smax.romanov@nginx.com nxt_port_t *port; 298088Smax.romanov@nginx.com nxt_event_engine_t *engine; 2981167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 298288Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 298388Smax.romanov@nginx.com 298488Smax.romanov@nginx.com engine = task->thread->engine; 298588Smax.romanov@nginx.com 2986*318Smax.romanov@nginx.com rc = nxt_port_rpc_register_handler_ex(task, engine->port, 2987*318Smax.romanov@nginx.com nxt_router_response_ready_handler, 2988*318Smax.romanov@nginx.com nxt_router_response_error_handler, 2989*318Smax.romanov@nginx.com sizeof(nxt_req_conn_link_t)); 2990122Smax.romanov@nginx.com 299188Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 2992141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2993141Smax.romanov@nginx.com "req->conn link"); 2994141Smax.romanov@nginx.com 2995141Smax.romanov@nginx.com return; 299688Smax.romanov@nginx.com } 299788Smax.romanov@nginx.com 2998*318Smax.romanov@nginx.com rc->stream = nxt_port_rpc_ex_stream(rc); 2999*318Smax.romanov@nginx.com rc->conn = c; 3000*318Smax.romanov@nginx.com 3001*318Smax.romanov@nginx.com nxt_queue_insert_tail(&c->requests, &rc->link); 3002*318Smax.romanov@nginx.com 3003*318Smax.romanov@nginx.com nxt_debug(task, "stream #%uD linked to conn %p at engine %p", 3004*318Smax.romanov@nginx.com rc->stream, c, engine); 300553Sigor@sysoev.ru 3006273Smax.romanov@nginx.com c->socket.data = NULL; 3007167Smax.romanov@nginx.com 3008167Smax.romanov@nginx.com ra = nxt_router_ra_create(task, rc); 3009167Smax.romanov@nginx.com 3010167Smax.romanov@nginx.com ra->ap = ap; 3011167Smax.romanov@nginx.com 3012167Smax.romanov@nginx.com res = nxt_router_app_port(task, ra); 3013141Smax.romanov@nginx.com 3014141Smax.romanov@nginx.com if (res != NXT_OK) { 3015141Smax.romanov@nginx.com return; 3016141Smax.romanov@nginx.com } 3017141Smax.romanov@nginx.com 3018167Smax.romanov@nginx.com port = ra->app_port; 3019141Smax.romanov@nginx.com 3020141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 3021*318Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Application port not found"); 3022141Smax.romanov@nginx.com return; 3023141Smax.romanov@nginx.com } 3024141Smax.romanov@nginx.com 3025*318Smax.romanov@nginx.com nxt_port_rpc_ex_set_peer(task, engine->port, rc, port->pid); 3026*318Smax.romanov@nginx.com 3027122Smax.romanov@nginx.com port_mp = port->mem_pool; 3028167Smax.romanov@nginx.com port->mem_pool = c->mem_pool; 3029167Smax.romanov@nginx.com 3030167Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, ra, port); 3031167Smax.romanov@nginx.com 3032167Smax.romanov@nginx.com port->mem_pool = port_mp; 3033167Smax.romanov@nginx.com 3034167Smax.romanov@nginx.com nxt_router_ra_release(task, ra, ra->work.data); 3035167Smax.romanov@nginx.com } 3036167Smax.romanov@nginx.com 3037167Smax.romanov@nginx.com 3038167Smax.romanov@nginx.com static void 3039167Smax.romanov@nginx.com nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_app_link_t *ra, 3040167Smax.romanov@nginx.com nxt_port_t *port) 3041167Smax.romanov@nginx.com { 3042167Smax.romanov@nginx.com nxt_int_t res; 3043167Smax.romanov@nginx.com nxt_port_t *c_port, *reply_port; 3044167Smax.romanov@nginx.com nxt_conn_t *c; 3045167Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 3046167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 3047167Smax.romanov@nginx.com 3048*318Smax.romanov@nginx.com /* TODO: it is unsafe to use ra->rc and ra->rc->conn in main thread */ 3049*318Smax.romanov@nginx.com 3050*318Smax.romanov@nginx.com nxt_assert(ra->rc != NULL); 3051*318Smax.romanov@nginx.com 3052167Smax.romanov@nginx.com reply_port = ra->reply_port; 3053167Smax.romanov@nginx.com ap = ra->ap; 3054167Smax.romanov@nginx.com c = ra->rc->conn; 3055141Smax.romanov@nginx.com 3056141Smax.romanov@nginx.com c_port = nxt_process_connected_port_find(port->process, reply_port->pid, 3057141Smax.romanov@nginx.com reply_port->id); 3058141Smax.romanov@nginx.com if (nxt_slow_path(c_port != reply_port)) { 3059141Smax.romanov@nginx.com res = nxt_port_send_port(task, port, reply_port, 0); 3060122Smax.romanov@nginx.com 3061122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 3062167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 3063141Smax.romanov@nginx.com "Failed to send reply port to application"); 3064167Smax.romanov@nginx.com return; 3065122Smax.romanov@nginx.com } 3066122Smax.romanov@nginx.com 3067141Smax.romanov@nginx.com nxt_process_connected_port_add(port->process, reply_port); 306888Smax.romanov@nginx.com } 306988Smax.romanov@nginx.com 307088Smax.romanov@nginx.com wmsg.port = port; 307188Smax.romanov@nginx.com wmsg.write = NULL; 307288Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 3073*318Smax.romanov@nginx.com wmsg.stream = ra->stream; 3074167Smax.romanov@nginx.com 3075216Sigor@sysoev.ru res = port->app->prepare_msg(task, &ap->r, &wmsg); 3076122Smax.romanov@nginx.com 3077122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 3078167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 3079141Smax.romanov@nginx.com "Failed to prepare message for application"); 3080167Smax.romanov@nginx.com return; 3081122Smax.romanov@nginx.com } 308288Smax.romanov@nginx.com 308388Smax.romanov@nginx.com nxt_debug(task, "about to send %d bytes buffer to worker port %d", 308488Smax.romanov@nginx.com nxt_buf_used_size(wmsg.write), 308588Smax.romanov@nginx.com wmsg.port->socket.fd); 308688Smax.romanov@nginx.com 3087122Smax.romanov@nginx.com res = nxt_port_socket_write(task, wmsg.port, NXT_PORT_MSG_DATA, 3088*318Smax.romanov@nginx.com -1, ra->stream, reply_port->id, wmsg.write); 3089122Smax.romanov@nginx.com 3090122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 3091167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 3092141Smax.romanov@nginx.com "Failed to send message to application"); 3093167Smax.romanov@nginx.com return; 3094122Smax.romanov@nginx.com } 309553Sigor@sysoev.ru } 309653Sigor@sysoev.ru 309753Sigor@sysoev.ru 3098216Sigor@sysoev.ru static nxt_int_t 3099216Sigor@sysoev.ru nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 3100216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg) 3101216Sigor@sysoev.ru { 3102216Sigor@sysoev.ru nxt_int_t rc; 3103216Sigor@sysoev.ru nxt_buf_t *b; 3104216Sigor@sysoev.ru nxt_http_field_t *field; 3105216Sigor@sysoev.ru nxt_app_request_header_t *h; 3106216Sigor@sysoev.ru 3107216Sigor@sysoev.ru static const nxt_str_t prefix = nxt_string("HTTP_"); 3108216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 3109216Sigor@sysoev.ru 3110216Sigor@sysoev.ru h = &r->header; 3111216Sigor@sysoev.ru 3112216Sigor@sysoev.ru #define RC(S) \ 3113216Sigor@sysoev.ru do { \ 3114216Sigor@sysoev.ru rc = (S); \ 3115216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 3116216Sigor@sysoev.ru goto fail; \ 3117216Sigor@sysoev.ru } \ 3118216Sigor@sysoev.ru } while(0) 3119216Sigor@sysoev.ru 3120216Sigor@sysoev.ru #define NXT_WRITE(N) \ 3121216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 3122216Sigor@sysoev.ru 3123216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 3124216Sigor@sysoev.ru 3125216Sigor@sysoev.ru NXT_WRITE(&h->method); 3126216Sigor@sysoev.ru NXT_WRITE(&h->target); 3127277Sigor@sysoev.ru 3128216Sigor@sysoev.ru if (h->path.start == h->target.start) { 3129216Sigor@sysoev.ru NXT_WRITE(&eof); 3130277Sigor@sysoev.ru 3131216Sigor@sysoev.ru } else { 3132216Sigor@sysoev.ru NXT_WRITE(&h->path); 3133216Sigor@sysoev.ru } 3134216Sigor@sysoev.ru 3135216Sigor@sysoev.ru if (h->query.start != NULL) { 3136216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 3137216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 3138216Sigor@sysoev.ru } else { 3139216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 3140216Sigor@sysoev.ru } 3141216Sigor@sysoev.ru 3142216Sigor@sysoev.ru NXT_WRITE(&h->version); 3143216Sigor@sysoev.ru 3144216Sigor@sysoev.ru NXT_WRITE(&r->remote); 3145268Sigor@sysoev.ru NXT_WRITE(&r->local); 3146216Sigor@sysoev.ru 3147216Sigor@sysoev.ru NXT_WRITE(&h->host); 3148216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 3149216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 3150216Sigor@sysoev.ru 3151216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 3152216Sigor@sysoev.ru RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, 3153216Sigor@sysoev.ru &prefix, &field->name)); 3154216Sigor@sysoev.ru NXT_WRITE(&field->value); 3155216Sigor@sysoev.ru 3156216Sigor@sysoev.ru } nxt_list_loop; 3157216Sigor@sysoev.ru 3158216Sigor@sysoev.ru /* end-of-headers mark */ 3159216Sigor@sysoev.ru NXT_WRITE(&eof); 3160216Sigor@sysoev.ru 3161216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 3162216Sigor@sysoev.ru 3163216Sigor@sysoev.ru for(b = r->body.buf; b != NULL; b = b->next) { 3164216Sigor@sysoev.ru RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 3165216Sigor@sysoev.ru nxt_buf_mem_used_size(&b->mem))); 3166216Sigor@sysoev.ru } 3167216Sigor@sysoev.ru 3168216Sigor@sysoev.ru #undef NXT_WRITE 3169216Sigor@sysoev.ru #undef RC 3170216Sigor@sysoev.ru 3171216Sigor@sysoev.ru return NXT_OK; 3172216Sigor@sysoev.ru 3173216Sigor@sysoev.ru fail: 3174216Sigor@sysoev.ru 3175216Sigor@sysoev.ru return NXT_ERROR; 3176216Sigor@sysoev.ru } 3177216Sigor@sysoev.ru 3178216Sigor@sysoev.ru 3179216Sigor@sysoev.ru static nxt_int_t 3180216Sigor@sysoev.ru nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 3181216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg) 3182216Sigor@sysoev.ru { 3183216Sigor@sysoev.ru nxt_int_t rc; 3184216Sigor@sysoev.ru nxt_buf_t *b; 3185305Smax.romanov@nginx.com nxt_bool_t method_is_post; 3186216Sigor@sysoev.ru nxt_http_field_t *field; 3187216Sigor@sysoev.ru nxt_app_request_header_t *h; 3188216Sigor@sysoev.ru 3189216Sigor@sysoev.ru static const nxt_str_t prefix = nxt_string("HTTP_"); 3190216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 3191216Sigor@sysoev.ru 3192216Sigor@sysoev.ru h = &r->header; 3193216Sigor@sysoev.ru 3194216Sigor@sysoev.ru #define RC(S) \ 3195216Sigor@sysoev.ru do { \ 3196216Sigor@sysoev.ru rc = (S); \ 3197216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 3198216Sigor@sysoev.ru goto fail; \ 3199216Sigor@sysoev.ru } \ 3200216Sigor@sysoev.ru } while(0) 3201216Sigor@sysoev.ru 3202216Sigor@sysoev.ru #define NXT_WRITE(N) \ 3203216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 3204216Sigor@sysoev.ru 3205216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 3206216Sigor@sysoev.ru 3207216Sigor@sysoev.ru NXT_WRITE(&h->method); 3208216Sigor@sysoev.ru NXT_WRITE(&h->target); 3209277Sigor@sysoev.ru 3210216Sigor@sysoev.ru if (h->path.start == h->target.start) { 3211216Sigor@sysoev.ru NXT_WRITE(&eof); 3212277Sigor@sysoev.ru 3213216Sigor@sysoev.ru } else { 3214216Sigor@sysoev.ru NXT_WRITE(&h->path); 3215216Sigor@sysoev.ru } 3216216Sigor@sysoev.ru 3217216Sigor@sysoev.ru if (h->query.start != NULL) { 3218216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 3219216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 3220216Sigor@sysoev.ru } else { 3221216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 3222216Sigor@sysoev.ru } 3223216Sigor@sysoev.ru 3224216Sigor@sysoev.ru NXT_WRITE(&h->version); 3225216Sigor@sysoev.ru 3226216Sigor@sysoev.ru // PHP_SELF 3227216Sigor@sysoev.ru // SCRIPT_NAME 3228216Sigor@sysoev.ru // SCRIPT_FILENAME 3229216Sigor@sysoev.ru // DOCUMENT_ROOT 3230216Sigor@sysoev.ru 3231216Sigor@sysoev.ru NXT_WRITE(&r->remote); 3232268Sigor@sysoev.ru NXT_WRITE(&r->local); 3233216Sigor@sysoev.ru 3234216Sigor@sysoev.ru NXT_WRITE(&h->host); 3235216Sigor@sysoev.ru NXT_WRITE(&h->cookie); 3236216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 3237216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 3238216Sigor@sysoev.ru 3239216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length)); 3240305Smax.romanov@nginx.com RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 3241305Smax.romanov@nginx.com 3242305Smax.romanov@nginx.com method_is_post = h->method.length == 4 && 3243305Smax.romanov@nginx.com h->method.start[0] == 'P' && 3244305Smax.romanov@nginx.com h->method.start[1] == 'O' && 3245305Smax.romanov@nginx.com h->method.start[2] == 'S' && 3246305Smax.romanov@nginx.com h->method.start[3] == 'T'; 3247305Smax.romanov@nginx.com 3248305Smax.romanov@nginx.com if (method_is_post) { 3249305Smax.romanov@nginx.com for(b = r->body.buf; b != NULL; b = b->next) { 3250305Smax.romanov@nginx.com RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 3251305Smax.romanov@nginx.com nxt_buf_mem_used_size(&b->mem))); 3252305Smax.romanov@nginx.com } 3253305Smax.romanov@nginx.com } 3254216Sigor@sysoev.ru 3255216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 3256216Sigor@sysoev.ru RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, 3257216Sigor@sysoev.ru &prefix, &field->name)); 3258216Sigor@sysoev.ru NXT_WRITE(&field->value); 3259216Sigor@sysoev.ru 3260216Sigor@sysoev.ru } nxt_list_loop; 3261216Sigor@sysoev.ru 3262216Sigor@sysoev.ru /* end-of-headers mark */ 3263216Sigor@sysoev.ru NXT_WRITE(&eof); 3264216Sigor@sysoev.ru 3265305Smax.romanov@nginx.com if (!method_is_post) { 3266305Smax.romanov@nginx.com for(b = r->body.buf; b != NULL; b = b->next) { 3267305Smax.romanov@nginx.com RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 3268305Smax.romanov@nginx.com nxt_buf_mem_used_size(&b->mem))); 3269305Smax.romanov@nginx.com } 3270216Sigor@sysoev.ru } 3271216Sigor@sysoev.ru 3272216Sigor@sysoev.ru #undef NXT_WRITE 3273216Sigor@sysoev.ru #undef RC 3274216Sigor@sysoev.ru 3275216Sigor@sysoev.ru return NXT_OK; 3276216Sigor@sysoev.ru 3277216Sigor@sysoev.ru fail: 3278216Sigor@sysoev.ru 3279216Sigor@sysoev.ru return NXT_ERROR; 3280216Sigor@sysoev.ru } 3281216Sigor@sysoev.ru 3282216Sigor@sysoev.ru 3283216Sigor@sysoev.ru static nxt_int_t 3284216Sigor@sysoev.ru nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, nxt_app_wmsg_t *wmsg) 3285216Sigor@sysoev.ru { 3286216Sigor@sysoev.ru nxt_int_t rc; 3287216Sigor@sysoev.ru nxt_buf_t *b; 3288216Sigor@sysoev.ru nxt_http_field_t *field; 3289216Sigor@sysoev.ru nxt_app_request_header_t *h; 3290216Sigor@sysoev.ru 3291216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 3292216Sigor@sysoev.ru 3293216Sigor@sysoev.ru h = &r->header; 3294216Sigor@sysoev.ru 3295216Sigor@sysoev.ru #define RC(S) \ 3296216Sigor@sysoev.ru do { \ 3297216Sigor@sysoev.ru rc = (S); \ 3298216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 3299216Sigor@sysoev.ru goto fail; \ 3300216Sigor@sysoev.ru } \ 3301216Sigor@sysoev.ru } while(0) 3302216Sigor@sysoev.ru 3303216Sigor@sysoev.ru #define NXT_WRITE(N) \ 3304216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 3305216Sigor@sysoev.ru 3306216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 3307216Sigor@sysoev.ru 3308216Sigor@sysoev.ru NXT_WRITE(&h->method); 3309216Sigor@sysoev.ru NXT_WRITE(&h->target); 3310277Sigor@sysoev.ru 3311216Sigor@sysoev.ru if (h->path.start == h->target.start) { 3312216Sigor@sysoev.ru NXT_WRITE(&eof); 3313277Sigor@sysoev.ru 3314216Sigor@sysoev.ru } else { 3315216Sigor@sysoev.ru NXT_WRITE(&h->path); 3316216Sigor@sysoev.ru } 3317216Sigor@sysoev.ru 3318216Sigor@sysoev.ru if (h->query.start != NULL) { 3319216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 3320216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 3321216Sigor@sysoev.ru } else { 3322216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 3323216Sigor@sysoev.ru } 3324216Sigor@sysoev.ru 3325216Sigor@sysoev.ru NXT_WRITE(&h->version); 3326253Smax.romanov@nginx.com NXT_WRITE(&r->remote); 3327216Sigor@sysoev.ru 3328216Sigor@sysoev.ru NXT_WRITE(&h->host); 3329216Sigor@sysoev.ru NXT_WRITE(&h->cookie); 3330216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 3331216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 3332216Sigor@sysoev.ru 3333216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length)); 3334216Sigor@sysoev.ru 3335216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 3336216Sigor@sysoev.ru NXT_WRITE(&field->name); 3337216Sigor@sysoev.ru NXT_WRITE(&field->value); 3338216Sigor@sysoev.ru 3339216Sigor@sysoev.ru } nxt_list_loop; 3340216Sigor@sysoev.ru 3341216Sigor@sysoev.ru /* end-of-headers mark */ 3342216Sigor@sysoev.ru NXT_WRITE(&eof); 3343216Sigor@sysoev.ru 3344216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 3345216Sigor@sysoev.ru 3346216Sigor@sysoev.ru for(b = r->body.buf; b != NULL; b = b->next) { 3347216Sigor@sysoev.ru RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 3348216Sigor@sysoev.ru nxt_buf_mem_used_size(&b->mem))); 3349216Sigor@sysoev.ru } 3350216Sigor@sysoev.ru 3351216Sigor@sysoev.ru #undef NXT_WRITE 3352216Sigor@sysoev.ru #undef RC 3353216Sigor@sysoev.ru 3354216Sigor@sysoev.ru return NXT_OK; 3355216Sigor@sysoev.ru 3356216Sigor@sysoev.ru fail: 3357216Sigor@sysoev.ru 3358216Sigor@sysoev.ru return NXT_ERROR; 3359216Sigor@sysoev.ru } 3360216Sigor@sysoev.ru 3361216Sigor@sysoev.ru 336262Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_close_state 336353Sigor@sysoev.ru nxt_aligned(64) = 336453Sigor@sysoev.ru { 336553Sigor@sysoev.ru .ready_handler = nxt_router_conn_free, 336653Sigor@sysoev.ru }; 336753Sigor@sysoev.ru 336853Sigor@sysoev.ru 336953Sigor@sysoev.ru static void 337088Smax.romanov@nginx.com nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data) 337188Smax.romanov@nginx.com { 337288Smax.romanov@nginx.com nxt_buf_t *b; 337388Smax.romanov@nginx.com nxt_bool_t last; 337488Smax.romanov@nginx.com nxt_conn_t *c; 337588Smax.romanov@nginx.com nxt_work_queue_t *wq; 337688Smax.romanov@nginx.com 337788Smax.romanov@nginx.com nxt_debug(task, "router conn ready %p", obj); 337888Smax.romanov@nginx.com 337988Smax.romanov@nginx.com c = obj; 338088Smax.romanov@nginx.com b = c->write; 338188Smax.romanov@nginx.com 338288Smax.romanov@nginx.com wq = &task->thread->engine->fast_work_queue; 338388Smax.romanov@nginx.com 338488Smax.romanov@nginx.com last = 0; 338588Smax.romanov@nginx.com 338688Smax.romanov@nginx.com while (b != NULL) { 338788Smax.romanov@nginx.com if (!nxt_buf_is_sync(b)) { 338888Smax.romanov@nginx.com if (nxt_buf_used_size(b) > 0) { 338988Smax.romanov@nginx.com break; 339088Smax.romanov@nginx.com } 339188Smax.romanov@nginx.com } 339288Smax.romanov@nginx.com 339388Smax.romanov@nginx.com if (nxt_buf_is_last(b)) { 339488Smax.romanov@nginx.com last = 1; 339588Smax.romanov@nginx.com } 339688Smax.romanov@nginx.com 339788Smax.romanov@nginx.com nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); 339888Smax.romanov@nginx.com 339988Smax.romanov@nginx.com b = b->next; 340088Smax.romanov@nginx.com } 340188Smax.romanov@nginx.com 340288Smax.romanov@nginx.com c->write = b; 340388Smax.romanov@nginx.com 340488Smax.romanov@nginx.com if (b != NULL) { 340588Smax.romanov@nginx.com nxt_debug(task, "router conn %p has more data to write", obj); 340688Smax.romanov@nginx.com 340788Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 3408277Sigor@sysoev.ru 340988Smax.romanov@nginx.com } else { 341088Smax.romanov@nginx.com nxt_debug(task, "router conn %p no more data to write, last = %d", obj, 341188Smax.romanov@nginx.com last); 341288Smax.romanov@nginx.com 341388Smax.romanov@nginx.com if (last != 0) { 341488Smax.romanov@nginx.com nxt_debug(task, "enqueue router conn close %p (ready handler)", c); 341588Smax.romanov@nginx.com 341688Smax.romanov@nginx.com nxt_work_queue_add(wq, nxt_router_conn_close, task, c, 341788Smax.romanov@nginx.com c->socket.data); 341888Smax.romanov@nginx.com } 341988Smax.romanov@nginx.com } 342088Smax.romanov@nginx.com } 342188Smax.romanov@nginx.com 342288Smax.romanov@nginx.com 342388Smax.romanov@nginx.com static void 342453Sigor@sysoev.ru nxt_router_conn_close(nxt_task_t *task, void *obj, void *data) 342553Sigor@sysoev.ru { 342662Sigor@sysoev.ru nxt_conn_t *c; 342753Sigor@sysoev.ru 342853Sigor@sysoev.ru c = obj; 342953Sigor@sysoev.ru 343053Sigor@sysoev.ru nxt_debug(task, "router conn close"); 343153Sigor@sysoev.ru 343253Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 343353Sigor@sysoev.ru 343462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 343553Sigor@sysoev.ru } 343653Sigor@sysoev.ru 343753Sigor@sysoev.ru 343853Sigor@sysoev.ru static void 3439164Smax.romanov@nginx.com nxt_router_conn_mp_cleanup(nxt_task_t *task, void *obj, void *data) 3440164Smax.romanov@nginx.com { 3441164Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 3442164Smax.romanov@nginx.com 3443164Smax.romanov@nginx.com joint = obj; 3444164Smax.romanov@nginx.com 3445164Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 3446164Smax.romanov@nginx.com } 3447164Smax.romanov@nginx.com 3448164Smax.romanov@nginx.com 3449164Smax.romanov@nginx.com static void 345053Sigor@sysoev.ru nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) 345153Sigor@sysoev.ru { 345262Sigor@sysoev.ru nxt_conn_t *c; 345388Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 345453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 345553Sigor@sysoev.ru 345653Sigor@sysoev.ru c = obj; 345753Sigor@sysoev.ru 345853Sigor@sysoev.ru nxt_debug(task, "router conn close done"); 345953Sigor@sysoev.ru 346088Smax.romanov@nginx.com nxt_queue_each(rc, &c->requests, nxt_req_conn_link_t, link) { 346188Smax.romanov@nginx.com 3462*318Smax.romanov@nginx.com nxt_debug(task, "conn %p close, stream #%uD", c, rc->stream); 346388Smax.romanov@nginx.com 3464141Smax.romanov@nginx.com if (rc->app_port != NULL) { 3465141Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 3466141Smax.romanov@nginx.com 3467141Smax.romanov@nginx.com rc->app_port = NULL; 3468141Smax.romanov@nginx.com } 3469141Smax.romanov@nginx.com 3470*318Smax.romanov@nginx.com nxt_router_rc_unlink(rc); 3471*318Smax.romanov@nginx.com 3472*318Smax.romanov@nginx.com nxt_port_rpc_cancel(task, task->thread->engine->port, rc->stream); 347388Smax.romanov@nginx.com 347488Smax.romanov@nginx.com } nxt_queue_loop; 347588Smax.romanov@nginx.com 3476122Smax.romanov@nginx.com nxt_queue_remove(&c->link); 3477122Smax.romanov@nginx.com 3478131Smax.romanov@nginx.com joint = c->listen->socket.data; 3479131Smax.romanov@nginx.com 3480131Smax.romanov@nginx.com task = &task->thread->engine->task; 3481131Smax.romanov@nginx.com 3482164Smax.romanov@nginx.com nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup, task, joint, NULL); 3483164Smax.romanov@nginx.com 3484164Smax.romanov@nginx.com nxt_mp_release(c->mem_pool, c); 348553Sigor@sysoev.ru } 348653Sigor@sysoev.ru 348753Sigor@sysoev.ru 348853Sigor@sysoev.ru static void 348953Sigor@sysoev.ru nxt_router_conn_error(nxt_task_t *task, void *obj, void *data) 349053Sigor@sysoev.ru { 349162Sigor@sysoev.ru nxt_conn_t *c; 349253Sigor@sysoev.ru 349353Sigor@sysoev.ru c = obj; 349453Sigor@sysoev.ru 349553Sigor@sysoev.ru nxt_debug(task, "router conn error"); 349653Sigor@sysoev.ru 3497273Smax.romanov@nginx.com if (c->socket.fd != -1) { 3498273Smax.romanov@nginx.com c->write_state = &nxt_router_conn_close_state; 3499273Smax.romanov@nginx.com 3500273Smax.romanov@nginx.com nxt_conn_close(task->thread->engine, c); 3501273Smax.romanov@nginx.com } 350253Sigor@sysoev.ru } 350353Sigor@sysoev.ru 350453Sigor@sysoev.ru 350553Sigor@sysoev.ru static void 350653Sigor@sysoev.ru nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) 350753Sigor@sysoev.ru { 350862Sigor@sysoev.ru nxt_conn_t *c; 350962Sigor@sysoev.ru nxt_timer_t *timer; 351053Sigor@sysoev.ru 351153Sigor@sysoev.ru timer = obj; 351253Sigor@sysoev.ru 351353Sigor@sysoev.ru nxt_debug(task, "router conn timeout"); 351453Sigor@sysoev.ru 351562Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 351653Sigor@sysoev.ru 3517206Smax.romanov@nginx.com if (c->read_state == &nxt_router_conn_read_header_state) { 3518206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 408, "Read header timeout"); 3519206Smax.romanov@nginx.com 3520206Smax.romanov@nginx.com } else { 3521206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 408, "Read body timeout"); 3522206Smax.romanov@nginx.com } 352353Sigor@sysoev.ru } 352453Sigor@sysoev.ru 352553Sigor@sysoev.ru 3526*318Smax.romanov@nginx.com static void 3527*318Smax.romanov@nginx.com nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data) 3528*318Smax.romanov@nginx.com { 3529*318Smax.romanov@nginx.com nxt_conn_t *c; 3530*318Smax.romanov@nginx.com nxt_timer_t *timer; 3531*318Smax.romanov@nginx.com 3532*318Smax.romanov@nginx.com timer = obj; 3533*318Smax.romanov@nginx.com 3534*318Smax.romanov@nginx.com nxt_debug(task, "router app timeout"); 3535*318Smax.romanov@nginx.com 3536*318Smax.romanov@nginx.com c = nxt_read_timer_conn(timer); 3537*318Smax.romanov@nginx.com 3538*318Smax.romanov@nginx.com nxt_router_gen_error(task, c, 408, "Application timeout"); 3539*318Smax.romanov@nginx.com } 3540*318Smax.romanov@nginx.com 3541*318Smax.romanov@nginx.com 354253Sigor@sysoev.ru static nxt_msec_t 354362Sigor@sysoev.ru nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 354453Sigor@sysoev.ru { 354553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 354653Sigor@sysoev.ru 354753Sigor@sysoev.ru joint = c->listen->socket.data; 354853Sigor@sysoev.ru 354953Sigor@sysoev.ru return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 355053Sigor@sysoev.ru } 3551