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> 10774Svbart@nginx.com #if (NXT_TLS) 11774Svbart@nginx.com #include <nxt_cert.h> 12774Svbart@nginx.com #endif 13431Sigor@sysoev.ru #include <nxt_http.h> 14743Smax.romanov@nginx.com #include <nxt_port_memory_int.h> 15743Smax.romanov@nginx.com #include <nxt_unit_request.h> 16743Smax.romanov@nginx.com #include <nxt_unit_response.h> 171131Smax.romanov@nginx.com #include <nxt_router_request.h> 18*1555Smax.romanov@nginx.com #include <nxt_app_queue.h> 19*1555Smax.romanov@nginx.com #include <nxt_port_queue.h> 2020Sigor@sysoev.ru 21115Sigor@sysoev.ru typedef struct { 22318Smax.romanov@nginx.com nxt_str_t type; 23507Smax.romanov@nginx.com uint32_t processes; 24507Smax.romanov@nginx.com uint32_t max_processes; 25507Smax.romanov@nginx.com uint32_t spare_processes; 26318Smax.romanov@nginx.com nxt_msec_t timeout; 27427Smax.romanov@nginx.com nxt_msec_t res_timeout; 28507Smax.romanov@nginx.com nxt_msec_t idle_timeout; 29318Smax.romanov@nginx.com uint32_t requests; 30318Smax.romanov@nginx.com nxt_conf_value_t *limits_value; 31507Smax.romanov@nginx.com nxt_conf_value_t *processes_value; 321473Svbart@nginx.com nxt_conf_value_t *targets_value; 33133Sigor@sysoev.ru } nxt_router_app_conf_t; 34133Sigor@sysoev.ru 35133Sigor@sysoev.ru 36133Sigor@sysoev.ru typedef struct { 37964Sigor@sysoev.ru nxt_str_t pass; 38964Sigor@sysoev.ru nxt_str_t application; 39115Sigor@sysoev.ru } nxt_router_listener_conf_t; 40115Sigor@sysoev.ru 41115Sigor@sysoev.ru 42774Svbart@nginx.com #if (NXT_TLS) 43774Svbart@nginx.com 44774Svbart@nginx.com typedef struct { 45774Svbart@nginx.com nxt_str_t name; 46774Svbart@nginx.com nxt_socket_conf_t *conf; 47774Svbart@nginx.com 48774Svbart@nginx.com nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ 49774Svbart@nginx.com } nxt_router_tlssock_t; 50774Svbart@nginx.com 51774Svbart@nginx.com #endif 52774Svbart@nginx.com 53774Svbart@nginx.com 54198Sigor@sysoev.ru typedef struct { 55198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 56198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 57198Sigor@sysoev.ru } nxt_socket_rpc_t; 58198Sigor@sysoev.ru 59198Sigor@sysoev.ru 60507Smax.romanov@nginx.com typedef struct { 61507Smax.romanov@nginx.com nxt_app_t *app; 62507Smax.romanov@nginx.com nxt_router_temp_conf_t *temp_conf; 63507Smax.romanov@nginx.com } nxt_app_rpc_t; 64507Smax.romanov@nginx.com 65507Smax.romanov@nginx.com 661488St.nateldemoura@f5.com static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, 671488St.nateldemoura@f5.com nxt_mp_t *mp); 681488St.nateldemoura@f5.com static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data); 69662Smax.romanov@nginx.com static void nxt_router_greet_controller(nxt_task_t *task, 70662Smax.romanov@nginx.com nxt_port_t *controller_port); 71662Smax.romanov@nginx.com 72507Smax.romanov@nginx.com static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); 73425Smax.romanov@nginx.com 741552Smax.romanov@nginx.com static void nxt_router_new_port_handler(nxt_task_t *task, 751552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 761552Smax.romanov@nginx.com static void nxt_router_conf_data_handler(nxt_task_t *task, 771552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 781552Smax.romanov@nginx.com static void nxt_router_remove_pid_handler(nxt_task_t *task, 791552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 801552Smax.romanov@nginx.com static void nxt_router_access_log_reopen_handler(nxt_task_t *task, 811552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 821552Smax.romanov@nginx.com 83139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 84198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 85198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 86139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 87139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 88139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 89139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 90193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 9153Sigor@sysoev.ru 92115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 93115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 941183Svbart@nginx.com static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, 951183Svbart@nginx.com nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); 96133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 97*1555Smax.romanov@nginx.com static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, 98*1555Smax.romanov@nginx.com nxt_port_t *port); 99*1555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, 100*1555Smax.romanov@nginx.com nxt_port_t *port); 101*1555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, 102*1555Smax.romanov@nginx.com nxt_port_t *port, nxt_fd_t fd); 103198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 104198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 105198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 106198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 107198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 108198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 109774Svbart@nginx.com #if (NXT_TLS) 110774Svbart@nginx.com static void nxt_router_tls_rpc_create(nxt_task_t *task, 111774Svbart@nginx.com nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls); 112774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task, 113774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 114774Svbart@nginx.com #endif 115507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task, 116507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 117507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task, 118507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 119507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task, 120507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 121359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 122359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 123359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 124359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 12553Sigor@sysoev.ru 12653Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 12753Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 12853Sigor@sysoev.ru const nxt_event_interface_t *interface); 129115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 130115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 131115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 132115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 133115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 134115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 135154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 136154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 137154Sigor@sysoev.ru nxt_work_handler_t handler); 138313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 139313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 140139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 141139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 14253Sigor@sysoev.ru 14353Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 14453Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 14553Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 14653Sigor@sysoev.ru nxt_event_engine_t *engine); 147343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 148133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 14953Sigor@sysoev.ru 150315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 151315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 152315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 153315Sigor@sysoev.ru nxt_work_t *jobs); 15453Sigor@sysoev.ru 15553Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 1561545Smax.romanov@nginx.com static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, 1571545Smax.romanov@nginx.com void *data); 15853Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 15953Sigor@sysoev.ru void *data); 16053Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 16153Sigor@sysoev.ru void *data); 16253Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 16353Sigor@sysoev.ru void *data); 164313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 165313Sigor@sysoev.ru void *data); 16653Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 16753Sigor@sysoev.ru void *data); 16853Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 16953Sigor@sysoev.ru void *data); 1701547Smax.romanov@nginx.com static void nxt_router_req_headers_ack_handler(nxt_task_t *task, 1711547Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); 172359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 173359Sigor@sysoev.ru nxt_socket_conf_t *skcf); 17453Sigor@sysoev.ru 175630Svbart@nginx.com static void nxt_router_access_log_writer(nxt_task_t *task, 176630Svbart@nginx.com nxt_http_request_t *r, nxt_router_access_log_t *access_log); 177630Svbart@nginx.com static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 178630Svbart@nginx.com struct tm *tm, size_t size, const char *format); 179630Svbart@nginx.com static void nxt_router_access_log_open(nxt_task_t *task, 180630Svbart@nginx.com nxt_router_temp_conf_t *tmcf); 181630Svbart@nginx.com static void nxt_router_access_log_ready(nxt_task_t *task, 182630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 183630Svbart@nginx.com static void nxt_router_access_log_error(nxt_task_t *task, 184630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 185630Svbart@nginx.com static void nxt_router_access_log_release(nxt_task_t *task, 186630Svbart@nginx.com nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 187651Svbart@nginx.com static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 188651Svbart@nginx.com void *data); 189631Svbart@nginx.com static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 190631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 191631Svbart@nginx.com static void nxt_router_access_log_reopen_error(nxt_task_t *task, 192631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 193630Svbart@nginx.com 194343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task, 195343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 1961547Smax.romanov@nginx.com static nxt_int_t nxt_router_app_shared_port_send(nxt_task_t *task, 1971547Smax.romanov@nginx.com nxt_port_t *app_port); 198343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task, 199343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 200343Smax.romanov@nginx.com 201753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 2021123Smax.romanov@nginx.com 203343Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 2041123Smax.romanov@nginx.com nxt_apr_action_t action); 2051547Smax.romanov@nginx.com static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 2061547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2071547Smax.romanov@nginx.com static void nxt_router_http_request_done(nxt_task_t *task, void *obj, 2081547Smax.romanov@nginx.com void *data); 209141Smax.romanov@nginx.com 210425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task, 2111547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2121007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 2131547Smax.romanov@nginx.com nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); 214510Salexander.borisov@nginx.com 215318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 216507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 217507Smax.romanov@nginx.com void *data); 218507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 219507Smax.romanov@nginx.com void *data); 220753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 221507Smax.romanov@nginx.com void *data); 222753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 223431Sigor@sysoev.ru 224431Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_state; 225431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 226141Smax.romanov@nginx.com 227753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task, 228753Smax.romanov@nginx.com nxt_app_joint_t *app_joint, int i); 229753Smax.romanov@nginx.com 2301547Smax.romanov@nginx.com static void nxt_router_http_request_release_post(nxt_task_t *task, 2311007Salexander.borisov@nginx.com nxt_http_request_t *r); 2321007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 2331007Salexander.borisov@nginx.com void *data); 2341321Smax.romanov@nginx.com static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 2351545Smax.romanov@nginx.com static void nxt_router_get_port_handler(nxt_task_t *task, 2361545Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2371546Smax.romanov@nginx.com static void nxt_router_get_mmap_handler(nxt_task_t *task, 2381546Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2391007Salexander.borisov@nginx.com 2401149Smax.romanov@nginx.com extern const nxt_http_request_state_t nxt_http_websocket; 2411131Smax.romanov@nginx.com 242119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 24320Sigor@sysoev.ru 244743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_"); 245743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string(""); 246743Smax.romanov@nginx.com 247743Smax.romanov@nginx.com static const nxt_str_t *nxt_app_msg_prefix[] = { 248804Svbart@nginx.com &empty_prefix, 249743Smax.romanov@nginx.com &http_prefix, 250743Smax.romanov@nginx.com &http_prefix, 251743Smax.romanov@nginx.com &http_prefix, 252743Smax.romanov@nginx.com &http_prefix, 253977Smax.romanov@gmail.com &empty_prefix, 254216Sigor@sysoev.ru }; 255216Sigor@sysoev.ru 256216Sigor@sysoev.ru 2571488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_router_process_port_handlers = { 2581488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 259662Smax.romanov@nginx.com .new_port = nxt_router_new_port_handler, 2601545Smax.romanov@nginx.com .get_port = nxt_router_get_port_handler, 261662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 262662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 2631546Smax.romanov@nginx.com .get_mmap = nxt_router_get_mmap_handler, 264662Smax.romanov@nginx.com .data = nxt_router_conf_data_handler, 265662Smax.romanov@nginx.com .remove_pid = nxt_router_remove_pid_handler, 266662Smax.romanov@nginx.com .access_log = nxt_router_access_log_reopen_handler, 267662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 268662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 2691321Smax.romanov@nginx.com .oosm = nxt_router_oosm_handler, 270662Smax.romanov@nginx.com }; 271662Smax.romanov@nginx.com 272662Smax.romanov@nginx.com 2731488St.nateldemoura@f5.com const nxt_process_init_t nxt_router_process = { 2741488St.nateldemoura@f5.com .name = "router", 2751488St.nateldemoura@f5.com .type = NXT_PROCESS_ROUTER, 2761488St.nateldemoura@f5.com .prefork = nxt_router_prefork, 2771488St.nateldemoura@f5.com .restart = 1, 2781488St.nateldemoura@f5.com .setup = nxt_process_core_setup, 2791488St.nateldemoura@f5.com .start = nxt_router_start, 2801488St.nateldemoura@f5.com .port_handlers = &nxt_router_process_port_handlers, 2811488St.nateldemoura@f5.com .signals = nxt_process_signals, 2821488St.nateldemoura@f5.com }; 2831488St.nateldemoura@f5.com 2841488St.nateldemoura@f5.com 2851509Sigor@sysoev.ru /* Queues of nxt_socket_conf_t */ 2861509Sigor@sysoev.ru nxt_queue_t creating_sockets; 2871509Sigor@sysoev.ru nxt_queue_t pending_sockets; 2881509Sigor@sysoev.ru nxt_queue_t updating_sockets; 2891509Sigor@sysoev.ru nxt_queue_t keeping_sockets; 2901509Sigor@sysoev.ru nxt_queue_t deleting_sockets; 2911509Sigor@sysoev.ru 2921509Sigor@sysoev.ru 2931488St.nateldemoura@f5.com static nxt_int_t 2941488St.nateldemoura@f5.com nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 2951488St.nateldemoura@f5.com { 2961488St.nateldemoura@f5.com nxt_runtime_stop_app_processes(task, task->thread->runtime); 2971488St.nateldemoura@f5.com 2981488St.nateldemoura@f5.com return NXT_OK; 2991488St.nateldemoura@f5.com } 3001488St.nateldemoura@f5.com 3011488St.nateldemoura@f5.com 3021488St.nateldemoura@f5.com static nxt_int_t 3031488St.nateldemoura@f5.com nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) 30420Sigor@sysoev.ru { 305141Smax.romanov@nginx.com nxt_int_t ret; 306662Smax.romanov@nginx.com nxt_port_t *controller_port; 307141Smax.romanov@nginx.com nxt_router_t *router; 308141Smax.romanov@nginx.com nxt_runtime_t *rt; 309141Smax.romanov@nginx.com 310141Smax.romanov@nginx.com rt = task->thread->runtime; 31153Sigor@sysoev.ru 3121488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "router started"); 3131488St.nateldemoura@f5.com 314771Sigor@sysoev.ru #if (NXT_TLS) 315771Sigor@sysoev.ru rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 316771Sigor@sysoev.ru if (nxt_slow_path(rt->tls == NULL)) { 317771Sigor@sysoev.ru return NXT_ERROR; 318771Sigor@sysoev.ru } 319771Sigor@sysoev.ru 320771Sigor@sysoev.ru ret = rt->tls->library_init(task); 321771Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 322771Sigor@sysoev.ru return ret; 323771Sigor@sysoev.ru } 324771Sigor@sysoev.ru #endif 325771Sigor@sysoev.ru 3261459Smax.romanov@nginx.com ret = nxt_http_init(task); 32788Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 32888Smax.romanov@nginx.com return ret; 32988Smax.romanov@nginx.com } 33088Smax.romanov@nginx.com 33153Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 33253Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 33353Sigor@sysoev.ru return NXT_ERROR; 33453Sigor@sysoev.ru } 33553Sigor@sysoev.ru 33653Sigor@sysoev.ru nxt_queue_init(&router->engines); 33753Sigor@sysoev.ru nxt_queue_init(&router->sockets); 338133Sigor@sysoev.ru nxt_queue_init(&router->apps); 33953Sigor@sysoev.ru 340119Smax.romanov@nginx.com nxt_router = router; 341119Smax.romanov@nginx.com 342662Smax.romanov@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 343662Smax.romanov@nginx.com if (controller_port != NULL) { 344662Smax.romanov@nginx.com nxt_router_greet_controller(task, controller_port); 345662Smax.romanov@nginx.com } 346662Smax.romanov@nginx.com 347115Sigor@sysoev.ru return NXT_OK; 348115Sigor@sysoev.ru } 349115Sigor@sysoev.ru 350115Sigor@sysoev.ru 351343Smax.romanov@nginx.com static void 352662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 353662Smax.romanov@nginx.com { 354662Smax.romanov@nginx.com nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 355662Smax.romanov@nginx.com -1, 0, 0, NULL); 356662Smax.romanov@nginx.com } 357662Smax.romanov@nginx.com 358662Smax.romanov@nginx.com 359662Smax.romanov@nginx.com static void 360507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 361507Smax.romanov@nginx.com void *data) 362167Smax.romanov@nginx.com { 363343Smax.romanov@nginx.com size_t size; 364343Smax.romanov@nginx.com uint32_t stream; 365430Sigor@sysoev.ru nxt_mp_t *mp; 366648Svbart@nginx.com nxt_int_t ret; 367343Smax.romanov@nginx.com nxt_app_t *app; 368343Smax.romanov@nginx.com nxt_buf_t *b; 369343Smax.romanov@nginx.com nxt_port_t *main_port; 370343Smax.romanov@nginx.com nxt_runtime_t *rt; 371343Smax.romanov@nginx.com 372343Smax.romanov@nginx.com app = data; 373167Smax.romanov@nginx.com 374167Smax.romanov@nginx.com rt = task->thread->runtime; 375240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 376167Smax.romanov@nginx.com 377507Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p start process", &app->name, app); 378343Smax.romanov@nginx.com 379343Smax.romanov@nginx.com size = app->name.length + 1 + app->conf.length; 380343Smax.romanov@nginx.com 381343Smax.romanov@nginx.com b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size); 382343Smax.romanov@nginx.com 383343Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 384343Smax.romanov@nginx.com goto failed; 385167Smax.romanov@nginx.com } 386167Smax.romanov@nginx.com 387343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->name); 388343Smax.romanov@nginx.com *b->mem.free++ = '\0'; 389343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 390343Smax.romanov@nginx.com 391753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, 1); 392753Smax.romanov@nginx.com 393343Smax.romanov@nginx.com stream = nxt_port_rpc_register_handler(task, port, 394343Smax.romanov@nginx.com nxt_router_app_port_ready, 395343Smax.romanov@nginx.com nxt_router_app_port_error, 396753Smax.romanov@nginx.com -1, app->joint); 397343Smax.romanov@nginx.com 398343Smax.romanov@nginx.com if (nxt_slow_path(stream == 0)) { 399753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, -1); 400753Smax.romanov@nginx.com 401343Smax.romanov@nginx.com goto failed; 402343Smax.romanov@nginx.com } 403343Smax.romanov@nginx.com 4041488St.nateldemoura@f5.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS, 4051488St.nateldemoura@f5.com -1, stream, port->id, b); 406648Svbart@nginx.com 407648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 408648Svbart@nginx.com nxt_port_rpc_cancel(task, port, stream); 409753Smax.romanov@nginx.com 410753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, -1); 411753Smax.romanov@nginx.com 412648Svbart@nginx.com goto failed; 413648Svbart@nginx.com } 414343Smax.romanov@nginx.com 415753Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 416753Smax.romanov@nginx.com 417343Smax.romanov@nginx.com return; 418343Smax.romanov@nginx.com 419343Smax.romanov@nginx.com failed: 420343Smax.romanov@nginx.com 421648Svbart@nginx.com if (b != NULL) { 422648Svbart@nginx.com mp = b->data; 423648Svbart@nginx.com nxt_mp_free(mp, b); 424648Svbart@nginx.com nxt_mp_release(mp); 425648Svbart@nginx.com } 426648Svbart@nginx.com 427343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 428343Smax.romanov@nginx.com 429507Smax.romanov@nginx.com app->pending_processes--; 430343Smax.romanov@nginx.com 431343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 432343Smax.romanov@nginx.com 433343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 434167Smax.romanov@nginx.com } 435167Smax.romanov@nginx.com 436167Smax.romanov@nginx.com 437753Smax.romanov@nginx.com static void 438753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 439753Smax.romanov@nginx.com { 440753Smax.romanov@nginx.com app_joint->use_count += i; 441753Smax.romanov@nginx.com 442753Smax.romanov@nginx.com if (app_joint->use_count == 0) { 443753Smax.romanov@nginx.com nxt_assert(app_joint->app == NULL); 444753Smax.romanov@nginx.com 445753Smax.romanov@nginx.com nxt_free(app_joint); 446753Smax.romanov@nginx.com } 447753Smax.romanov@nginx.com } 448753Smax.romanov@nginx.com 449753Smax.romanov@nginx.com 450343Smax.romanov@nginx.com static nxt_int_t 451507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 452141Smax.romanov@nginx.com { 453343Smax.romanov@nginx.com nxt_int_t res; 454343Smax.romanov@nginx.com nxt_port_t *router_port; 455343Smax.romanov@nginx.com nxt_runtime_t *rt; 456343Smax.romanov@nginx.com 4571549Smax.romanov@nginx.com nxt_debug(task, "app '%V' start process", &app->name); 4581549Smax.romanov@nginx.com 459343Smax.romanov@nginx.com rt = task->thread->runtime; 460343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 461343Smax.romanov@nginx.com 462343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1); 463343Smax.romanov@nginx.com 464507Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 465343Smax.romanov@nginx.com app); 466343Smax.romanov@nginx.com 467343Smax.romanov@nginx.com if (res == NXT_OK) { 468343Smax.romanov@nginx.com return res; 469318Smax.romanov@nginx.com } 470318Smax.romanov@nginx.com 471343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 472343Smax.romanov@nginx.com 473507Smax.romanov@nginx.com app->pending_processes--; 474343Smax.romanov@nginx.com 475343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 476343Smax.romanov@nginx.com 477343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 478343Smax.romanov@nginx.com 479343Smax.romanov@nginx.com return NXT_ERROR; 480318Smax.romanov@nginx.com } 481318Smax.romanov@nginx.com 482318Smax.romanov@nginx.com 483423Smax.romanov@nginx.com nxt_inline nxt_bool_t 484*1555Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) 485423Smax.romanov@nginx.com { 486*1555Smax.romanov@nginx.com nxt_buf_t *b, *next; 487*1555Smax.romanov@nginx.com nxt_bool_t cancelled; 488*1555Smax.romanov@nginx.com nxt_msg_info_t *msg_info; 489*1555Smax.romanov@nginx.com 490*1555Smax.romanov@nginx.com msg_info = &req_rpc_data->msg_info; 491423Smax.romanov@nginx.com 492423Smax.romanov@nginx.com if (msg_info->buf == NULL) { 493423Smax.romanov@nginx.com return 0; 494423Smax.romanov@nginx.com } 495423Smax.romanov@nginx.com 496*1555Smax.romanov@nginx.com cancelled = nxt_app_queue_cancel(req_rpc_data->app->shared_port->queue, 497*1555Smax.romanov@nginx.com msg_info->tracking_cookie, 498*1555Smax.romanov@nginx.com req_rpc_data->stream); 499423Smax.romanov@nginx.com 500423Smax.romanov@nginx.com if (cancelled) { 501*1555Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router", 502*1555Smax.romanov@nginx.com req_rpc_data->stream); 503423Smax.romanov@nginx.com } 504423Smax.romanov@nginx.com 505423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) { 506423Smax.romanov@nginx.com next = b->next; 5071269Sigor@sysoev.ru b->next = NULL; 508423Smax.romanov@nginx.com 509423Smax.romanov@nginx.com b->completion_handler = msg_info->completion_handler; 510423Smax.romanov@nginx.com 511423Smax.romanov@nginx.com if (b->is_port_mmap_sent) { 512423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0; 513423Smax.romanov@nginx.com b->completion_handler(task, b, b->parent); 514423Smax.romanov@nginx.com } 515423Smax.romanov@nginx.com } 516423Smax.romanov@nginx.com 517423Smax.romanov@nginx.com msg_info->buf = NULL; 518423Smax.romanov@nginx.com 519423Smax.romanov@nginx.com return cancelled; 520423Smax.romanov@nginx.com } 521423Smax.romanov@nginx.com 522423Smax.romanov@nginx.com 523425Smax.romanov@nginx.com nxt_inline nxt_bool_t 524425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk) 525425Smax.romanov@nginx.com { 526425Smax.romanov@nginx.com if (lnk->next != NULL) { 527425Smax.romanov@nginx.com nxt_queue_remove(lnk); 528425Smax.romanov@nginx.com 529425Smax.romanov@nginx.com lnk->next = NULL; 530425Smax.romanov@nginx.com 531425Smax.romanov@nginx.com return 1; 532425Smax.romanov@nginx.com } 533425Smax.romanov@nginx.com 534425Smax.romanov@nginx.com return 0; 535425Smax.romanov@nginx.com } 536425Smax.romanov@nginx.com 537425Smax.romanov@nginx.com 538343Smax.romanov@nginx.com nxt_inline void 5391123Smax.romanov@nginx.com nxt_request_rpc_data_unlink(nxt_task_t *task, 5401123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data) 541343Smax.romanov@nginx.com { 5421547Smax.romanov@nginx.com nxt_http_request_t *r; 5431547Smax.romanov@nginx.com 544*1555Smax.romanov@nginx.com nxt_router_msg_cancel(task, req_rpc_data); 5451123Smax.romanov@nginx.com 5461123Smax.romanov@nginx.com if (req_rpc_data->app_port != NULL) { 5471123Smax.romanov@nginx.com nxt_router_app_port_release(task, req_rpc_data->app_port, 5481123Smax.romanov@nginx.com req_rpc_data->apr_action); 5491123Smax.romanov@nginx.com 5501123Smax.romanov@nginx.com req_rpc_data->app_port = NULL; 5511123Smax.romanov@nginx.com } 5521123Smax.romanov@nginx.com 5531123Smax.romanov@nginx.com if (req_rpc_data->app != NULL) { 5541123Smax.romanov@nginx.com nxt_router_app_use(task, req_rpc_data->app, -1); 5551123Smax.romanov@nginx.com 5561123Smax.romanov@nginx.com req_rpc_data->app = NULL; 5571123Smax.romanov@nginx.com } 5581123Smax.romanov@nginx.com 5591547Smax.romanov@nginx.com r = req_rpc_data->request; 5601547Smax.romanov@nginx.com 5611547Smax.romanov@nginx.com if (r != NULL) { 5621547Smax.romanov@nginx.com r->timer_data = NULL; 5631547Smax.romanov@nginx.com 5641547Smax.romanov@nginx.com nxt_router_http_request_release_post(task, r); 5651547Smax.romanov@nginx.com 5661547Smax.romanov@nginx.com r->req_rpc_data = NULL; 5671123Smax.romanov@nginx.com req_rpc_data->request = NULL; 568346Smax.romanov@nginx.com } 5691547Smax.romanov@nginx.com 5701547Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1) { 5711547Smax.romanov@nginx.com nxt_fd_close(req_rpc_data->msg_info.body_fd); 5721547Smax.romanov@nginx.com 5731547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1; 5741547Smax.romanov@nginx.com } 5751547Smax.romanov@nginx.com 5761547Smax.romanov@nginx.com if (req_rpc_data->rpc_cancel) { 5771547Smax.romanov@nginx.com req_rpc_data->rpc_cancel = 0; 5781547Smax.romanov@nginx.com 5791547Smax.romanov@nginx.com nxt_port_rpc_cancel(task, task->thread->engine->port, 5801547Smax.romanov@nginx.com req_rpc_data->stream); 5811547Smax.romanov@nginx.com } 582343Smax.romanov@nginx.com } 583343Smax.romanov@nginx.com 584343Smax.romanov@nginx.com 5851552Smax.romanov@nginx.com static void 586141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 587141Smax.romanov@nginx.com { 588*1555Smax.romanov@nginx.com nxt_int_t res; 5891547Smax.romanov@nginx.com nxt_app_t *app; 5901547Smax.romanov@nginx.com nxt_port_t *port, *main_app_port; 5911547Smax.romanov@nginx.com nxt_runtime_t *rt; 5921547Smax.romanov@nginx.com 593141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 594141Smax.romanov@nginx.com 5951547Smax.romanov@nginx.com port = msg->u.new_port; 5961547Smax.romanov@nginx.com 5971547Smax.romanov@nginx.com if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { 598662Smax.romanov@nginx.com nxt_router_greet_controller(task, msg->u.new_port); 599662Smax.romanov@nginx.com } 600662Smax.romanov@nginx.com 6011547Smax.romanov@nginx.com if (port == NULL || port->type != NXT_PROCESS_APP) { 6021547Smax.romanov@nginx.com 6031547Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 6041547Smax.romanov@nginx.com return; 6051547Smax.romanov@nginx.com } 6061547Smax.romanov@nginx.com 6071547Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 608*1555Smax.romanov@nginx.com 609*1555Smax.romanov@nginx.com } else { 610*1555Smax.romanov@nginx.com if (msg->fd2 != -1) { 611*1555Smax.romanov@nginx.com res = nxt_router_port_queue_map(task, port, msg->fd2); 612*1555Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 613*1555Smax.romanov@nginx.com return; 614*1555Smax.romanov@nginx.com } 615*1555Smax.romanov@nginx.com 616*1555Smax.romanov@nginx.com nxt_fd_close(msg->fd2); 617*1555Smax.romanov@nginx.com msg->fd2 = -1; 618*1555Smax.romanov@nginx.com } 6191547Smax.romanov@nginx.com } 6201547Smax.romanov@nginx.com 6211547Smax.romanov@nginx.com if (msg->port_msg.stream != 0) { 6221547Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 623141Smax.romanov@nginx.com return; 624141Smax.romanov@nginx.com } 625141Smax.romanov@nginx.com 6261547Smax.romanov@nginx.com /* 6271547Smax.romanov@nginx.com * Port with "id == 0" is application 'main' port and it always 6281547Smax.romanov@nginx.com * should come with non-zero stream. 6291547Smax.romanov@nginx.com */ 6301547Smax.romanov@nginx.com nxt_assert(port->id != 0); 6311547Smax.romanov@nginx.com 6321547Smax.romanov@nginx.com /* Find 'main' app port and get app reference. */ 6331547Smax.romanov@nginx.com rt = task->thread->runtime; 6341547Smax.romanov@nginx.com 6351547Smax.romanov@nginx.com /* 6361547Smax.romanov@nginx.com * It is safe to access 'runtime->ports' hash because 'NEW_PORT' 6371547Smax.romanov@nginx.com * sent to main port (with id == 0) and processed in main thread. 6381547Smax.romanov@nginx.com */ 6391547Smax.romanov@nginx.com main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); 6401547Smax.romanov@nginx.com nxt_assert(main_app_port != NULL); 6411547Smax.romanov@nginx.com 6421547Smax.romanov@nginx.com app = main_app_port->app; 6431547Smax.romanov@nginx.com nxt_assert(app != NULL); 6441547Smax.romanov@nginx.com 6451547Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 6461547Smax.romanov@nginx.com 6471547Smax.romanov@nginx.com /* TODO here should be find-and-add code because there can be 6481547Smax.romanov@nginx.com port waiters in port_hash */ 6491547Smax.romanov@nginx.com nxt_port_hash_add(&app->port_hash, port); 6501547Smax.romanov@nginx.com app->port_hash_count++; 6511547Smax.romanov@nginx.com 6521547Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 6531547Smax.romanov@nginx.com 6541547Smax.romanov@nginx.com port->app = app; 6551547Smax.romanov@nginx.com port->main_app_port = main_app_port; 656141Smax.romanov@nginx.com } 657141Smax.romanov@nginx.com 658141Smax.romanov@nginx.com 6591552Smax.romanov@nginx.com static void 660139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 661115Sigor@sysoev.ru { 6621526Smax.romanov@nginx.com void *p; 6631526Smax.romanov@nginx.com size_t size; 664198Sigor@sysoev.ru nxt_int_t ret; 665139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 666139Sigor@sysoev.ru 667139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 668139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 669139Sigor@sysoev.ru return; 67053Sigor@sysoev.ru } 67153Sigor@sysoev.ru 6721526Smax.romanov@nginx.com if (nxt_slow_path(msg->fd == -1)) { 6731526Smax.romanov@nginx.com nxt_alert(task, "conf_data_handler: invalid file shm fd"); 6741526Smax.romanov@nginx.com return; 6751526Smax.romanov@nginx.com } 6761526Smax.romanov@nginx.com 6771526Smax.romanov@nginx.com if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { 6781526Smax.romanov@nginx.com nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)", 6791526Smax.romanov@nginx.com (int) nxt_buf_mem_used_size(&msg->buf->mem)); 6801526Smax.romanov@nginx.com 6811526Smax.romanov@nginx.com nxt_fd_close(msg->fd); 6821526Smax.romanov@nginx.com msg->fd = -1; 6831526Smax.romanov@nginx.com 6841526Smax.romanov@nginx.com return; 6851526Smax.romanov@nginx.com } 6861526Smax.romanov@nginx.com 6871526Smax.romanov@nginx.com nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); 6881526Smax.romanov@nginx.com 6891526Smax.romanov@nginx.com p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd, 0); 6901526Smax.romanov@nginx.com 6911526Smax.romanov@nginx.com nxt_fd_close(msg->fd); 6921526Smax.romanov@nginx.com msg->fd = -1; 6931526Smax.romanov@nginx.com 6941526Smax.romanov@nginx.com if (nxt_slow_path(p == MAP_FAILED)) { 6951526Smax.romanov@nginx.com return; 6961526Smax.romanov@nginx.com } 6971526Smax.romanov@nginx.com 6981526Smax.romanov@nginx.com nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p); 699423Smax.romanov@nginx.com 700591Sigor@sysoev.ru tmcf->router_conf->router = nxt_router; 701139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 702139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 703198Sigor@sysoev.ru msg->port_msg.pid, 704198Sigor@sysoev.ru msg->port_msg.reply_port); 705198Sigor@sysoev.ru 706779Smax.romanov@nginx.com if (nxt_slow_path(tmcf->port == NULL)) { 707779Smax.romanov@nginx.com nxt_alert(task, "reply port not found"); 708779Smax.romanov@nginx.com 7091526Smax.romanov@nginx.com goto fail; 710779Smax.romanov@nginx.com } 711779Smax.romanov@nginx.com 712779Smax.romanov@nginx.com nxt_port_use(task, tmcf->port, 1); 713779Smax.romanov@nginx.com 7141526Smax.romanov@nginx.com ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size)); 715198Sigor@sysoev.ru 716198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) { 717198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL); 718198Sigor@sysoev.ru 719198Sigor@sysoev.ru } else { 720198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 721139Sigor@sysoev.ru } 7221526Smax.romanov@nginx.com 7231526Smax.romanov@nginx.com fail: 7241526