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> 181555Smax.romanov@nginx.com #include <nxt_app_queue.h> 191555Smax.romanov@nginx.com #include <nxt_port_queue.h> 2020Sigor@sysoev.ru 211926Smax.romanov@nginx.com #define NXT_SHARED_PORT_ID 0xFFFFu 221926Smax.romanov@nginx.com 23115Sigor@sysoev.ru typedef struct { 24318Smax.romanov@nginx.com nxt_str_t type; 25507Smax.romanov@nginx.com uint32_t processes; 26507Smax.romanov@nginx.com uint32_t max_processes; 27507Smax.romanov@nginx.com uint32_t spare_processes; 28318Smax.romanov@nginx.com nxt_msec_t timeout; 29507Smax.romanov@nginx.com nxt_msec_t idle_timeout; 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 { 451885Sa.suvorov@f5.com nxt_str_t name; 461885Sa.suvorov@f5.com nxt_socket_conf_t *socket_conf; 471885Sa.suvorov@f5.com nxt_router_temp_conf_t *temp_conf; 481920Sa.suvorov@f5.com nxt_tls_init_t *tls_init; 491885Sa.suvorov@f5.com nxt_bool_t last; 50774Svbart@nginx.com 511920Sa.suvorov@f5.com nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ 52774Svbart@nginx.com } nxt_router_tlssock_t; 53774Svbart@nginx.com 54774Svbart@nginx.com #endif 55774Svbart@nginx.com 56774Svbart@nginx.com 57198Sigor@sysoev.ru typedef struct { 581828Sa.suvorov@f5.com nxt_str_t *name; 59198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 60198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 611828Sa.suvorov@f5.com nxt_bool_t last; 62198Sigor@sysoev.ru } nxt_socket_rpc_t; 63198Sigor@sysoev.ru 64198Sigor@sysoev.ru 65507Smax.romanov@nginx.com typedef struct { 66507Smax.romanov@nginx.com nxt_app_t *app; 67507Smax.romanov@nginx.com nxt_router_temp_conf_t *temp_conf; 681998St.nateldemoura@f5.com uint8_t proto; /* 1 bit */ 69507Smax.romanov@nginx.com } nxt_app_rpc_t; 70507Smax.romanov@nginx.com 71507Smax.romanov@nginx.com 721926Smax.romanov@nginx.com typedef struct { 731926Smax.romanov@nginx.com nxt_app_joint_t *app_joint; 741926Smax.romanov@nginx.com uint32_t generation; 751998St.nateldemoura@f5.com uint8_t proto; /* 1 bit */ 761926Smax.romanov@nginx.com } nxt_app_joint_rpc_t; 771926Smax.romanov@nginx.com 781926Smax.romanov@nginx.com 791488St.nateldemoura@f5.com static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, 801488St.nateldemoura@f5.com nxt_mp_t *mp); 811488St.nateldemoura@f5.com static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data); 82662Smax.romanov@nginx.com static void nxt_router_greet_controller(nxt_task_t *task, 83662Smax.romanov@nginx.com nxt_port_t *controller_port); 84662Smax.romanov@nginx.com 85507Smax.romanov@nginx.com static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); 86425Smax.romanov@nginx.com 871552Smax.romanov@nginx.com static void nxt_router_new_port_handler(nxt_task_t *task, 881552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 891552Smax.romanov@nginx.com static void nxt_router_conf_data_handler(nxt_task_t *task, 901552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 911926Smax.romanov@nginx.com static void nxt_router_app_restart_handler(nxt_task_t *task, 921926Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 931552Smax.romanov@nginx.com static void nxt_router_remove_pid_handler(nxt_task_t *task, 941552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 951552Smax.romanov@nginx.com static void nxt_router_access_log_reopen_handler(nxt_task_t *task, 961552Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 971552Smax.romanov@nginx.com 98139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 99198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 100198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 101139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 102139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 103139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 104139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 105193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 10653Sigor@sysoev.ru 107115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 108115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 1091183Svbart@nginx.com static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, 1101183Svbart@nginx.com nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); 111*2133Sz.hong@f5.com static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task, 112*2133Sz.hong@f5.com nxt_mp_t *mp, nxt_conf_value_t *conf); 113*2133Sz.hong@f5.com static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp, 114*2133Sz.hong@f5.com nxt_conf_value_t *conf, nxt_http_forward_header_t *fh); 1151563Svbart@nginx.com 116133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 1171563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 1181563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, 1191563Svbart@nginx.com nxt_app_t *app); 1201563Svbart@nginx.com static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, 1211563Svbart@nginx.com nxt_str_t *name); 1221563Svbart@nginx.com static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, 1231563Svbart@nginx.com int i); 1241563Svbart@nginx.com 1251555Smax.romanov@nginx.com static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, 1261555Smax.romanov@nginx.com nxt_port_t *port); 1271555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, 1281555Smax.romanov@nginx.com nxt_port_t *port); 1291555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, 1301555Smax.romanov@nginx.com nxt_port_t *port, nxt_fd_t fd); 131198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 132198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 133198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 134198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 135198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 136198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 137774Svbart@nginx.com #if (NXT_TLS) 138774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task, 139774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 1401828Sa.suvorov@f5.com static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 1411920Sa.suvorov@f5.com nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init, 1421920Sa.suvorov@f5.com nxt_bool_t last); 143774Svbart@nginx.com #endif 144507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task, 145507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 146507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task, 147507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 148507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task, 149507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 150359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 151359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 152359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 153359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 15453Sigor@sysoev.ru 15553Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 15653Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 15753Sigor@sysoev.ru const nxt_event_interface_t *interface); 158115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 159115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 160115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 161115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 162115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 163115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 164154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 165154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 166154Sigor@sysoev.ru nxt_work_handler_t handler); 167313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 168313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 169139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 170139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 17153Sigor@sysoev.ru 17253Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 17353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 17453Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 17553Sigor@sysoev.ru nxt_event_engine_t *engine); 176343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 177133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 17853Sigor@sysoev.ru 179315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 180315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 181315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 182315Sigor@sysoev.ru nxt_work_t *jobs); 18353Sigor@sysoev.ru 18453Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 1851545Smax.romanov@nginx.com static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, 1861545Smax.romanov@nginx.com void *data); 18753Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 18853Sigor@sysoev.ru void *data); 18953Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 19053Sigor@sysoev.ru void *data); 19153Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 19253Sigor@sysoev.ru void *data); 193313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 194313Sigor@sysoev.ru void *data); 19553Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 19653Sigor@sysoev.ru void *data); 19753Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 19853Sigor@sysoev.ru void *data); 1991547Smax.romanov@nginx.com static void nxt_router_req_headers_ack_handler(nxt_task_t *task, 2001547Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); 201359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 202359Sigor@sysoev.ru nxt_socket_conf_t *skcf); 20353Sigor@sysoev.ru 204630Svbart@nginx.com static void nxt_router_access_log_writer(nxt_task_t *task, 205630Svbart@nginx.com nxt_http_request_t *r, nxt_router_access_log_t *access_log); 206630Svbart@nginx.com static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 207630Svbart@nginx.com struct tm *tm, size_t size, const char *format); 208630Svbart@nginx.com static void nxt_router_access_log_open(nxt_task_t *task, 209630Svbart@nginx.com nxt_router_temp_conf_t *tmcf); 210630Svbart@nginx.com static void nxt_router_access_log_ready(nxt_task_t *task, 211630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 212630Svbart@nginx.com static void nxt_router_access_log_error(nxt_task_t *task, 213630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 2142033SN/A static void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, 2152033SN/A nxt_router_access_log_t *access_log); 216630Svbart@nginx.com static void nxt_router_access_log_release(nxt_task_t *task, 217630Svbart@nginx.com nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 218651Svbart@nginx.com static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 219651Svbart@nginx.com void *data); 220631Svbart@nginx.com static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 221631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 222631Svbart@nginx.com static void nxt_router_access_log_reopen_error(nxt_task_t *task, 223631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 224630Svbart@nginx.com 225343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task, 226343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 227343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task, 228343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 229343Smax.romanov@nginx.com 2301563Svbart@nginx.com static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i); 231753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 2321123Smax.romanov@nginx.com 2331978Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, 2341978Smax.romanov@nginx.com nxt_port_t *port, nxt_apr_action_t action); 2351547Smax.romanov@nginx.com static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 2361547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2371561Smax.romanov@nginx.com static void nxt_router_http_request_error(nxt_task_t *task, void *obj, 2381561Smax.romanov@nginx.com void *data); 2391547Smax.romanov@nginx.com static void nxt_router_http_request_done(nxt_task_t *task, void *obj, 2401547Smax.romanov@nginx.com void *data); 241141Smax.romanov@nginx.com 242425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task, 2431547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2441007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 2451547Smax.romanov@nginx.com nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); 246510Salexander.borisov@nginx.com 247318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 248507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 249507Smax.romanov@nginx.com void *data); 250507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 251507Smax.romanov@nginx.com void *data); 252753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 253507Smax.romanov@nginx.com void *data); 254753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 255431Sigor@sysoev.ru 256431Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_state; 257431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 258141Smax.romanov@nginx.com 259753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task, 260753Smax.romanov@nginx.com nxt_app_joint_t *app_joint, int i); 261753Smax.romanov@nginx.com 2621547Smax.romanov@nginx.com static void nxt_router_http_request_release_post(nxt_task_t *task, 2631007Salexander.borisov@nginx.com nxt_http_request_t *r); 2641007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 2651007Salexander.borisov@nginx.com void *data); 2661321Smax.romanov@nginx.com static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 2671545Smax.romanov@nginx.com static void nxt_router_get_port_handler(nxt_task_t *task, 2681545Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2691546Smax.romanov@nginx.com static void nxt_router_get_mmap_handler(nxt_task_t *task, 2701546Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2711007Salexander.borisov@nginx.com 2721149Smax.romanov@nginx.com extern const nxt_http_request_state_t nxt_http_websocket; 2731131Smax.romanov@nginx.com 274119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 27520Sigor@sysoev.ru 276743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_"); 277743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string(""); 278743Smax.romanov@nginx.com 279743Smax.romanov@nginx.com static const nxt_str_t *nxt_app_msg_prefix[] = { 280804Svbart@nginx.com &empty_prefix, 2811594Smax.romanov@nginx.com &empty_prefix, 282743Smax.romanov@nginx.com &http_prefix, 283743Smax.romanov@nginx.com &http_prefix, 284743Smax.romanov@nginx.com &http_prefix, 285977Smax.romanov@gmail.com &empty_prefix, 286216Sigor@sysoev.ru }; 287216Sigor@sysoev.ru 288216Sigor@sysoev.ru 2891488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_router_process_port_handlers = { 2901488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 291662Smax.romanov@nginx.com .new_port = nxt_router_new_port_handler, 2921545Smax.romanov@nginx.com .get_port = nxt_router_get_port_handler, 293662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 294662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 2951546Smax.romanov@nginx.com .get_mmap = nxt_router_get_mmap_handler, 296662Smax.romanov@nginx.com .data = nxt_router_conf_data_handler, 2971926Smax.romanov@nginx.com .app_restart = nxt_router_app_restart_handler, 298662Smax.romanov@nginx.com .remove_pid = nxt_router_remove_pid_handler, 299662Smax.romanov@nginx.com .access_log = nxt_router_access_log_reopen_handler, 300662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 301662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 3021321Smax.romanov@nginx.com .oosm = nxt_router_oosm_handler, 303662Smax.romanov@nginx.com }; 304662Smax.romanov@nginx.com 305662Smax.romanov@nginx.com 3061488St.nateldemoura@f5.com const nxt_process_init_t nxt_router_process = { 3071488St.nateldemoura@f5.com .name = "router", 3081488St.nateldemoura@f5.com .type = NXT_PROCESS_ROUTER, 3091488St.nateldemoura@f5.com .prefork = nxt_router_prefork, 3101488St.nateldemoura@f5.com .restart = 1, 3111488St.nateldemoura@f5.com .setup = nxt_process_core_setup, 3121488St.nateldemoura@f5.com .start = nxt_router_start, 3131488St.nateldemoura@f5.com .port_handlers = &nxt_router_process_port_handlers, 3141488St.nateldemoura@f5.com .signals = nxt_process_signals, 3151488St.nateldemoura@f5.com }; 3161488St.nateldemoura@f5.com 3171488St.nateldemoura@f5.com 3181509Sigor@sysoev.ru /* Queues of nxt_socket_conf_t */ 3191509Sigor@sysoev.ru nxt_queue_t creating_sockets; 3201509Sigor@sysoev.ru nxt_queue_t pending_sockets; 3211509Sigor@sysoev.ru nxt_queue_t updating_sockets; 3221509Sigor@sysoev.ru nxt_queue_t keeping_sockets; 3231509Sigor@sysoev.ru nxt_queue_t deleting_sockets; 3241509Sigor@sysoev.ru 3251509Sigor@sysoev.ru 3261488St.nateldemoura@f5.com static nxt_int_t 3271488St.nateldemoura@f5.com nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 3281488St.nateldemoura@f5.com { 3291488St.nateldemoura@f5.com nxt_runtime_stop_app_processes(task, task->thread->runtime); 3301488St.nateldemoura@f5.com 3311488St.nateldemoura@f5.com return NXT_OK; 3321488St.nateldemoura@f5.com } 3331488St.nateldemoura@f5.com 3341488St.nateldemoura@f5.com 3351488St.nateldemoura@f5.com static nxt_int_t 3361488St.nateldemoura@f5.com nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) 33720Sigor@sysoev.ru { 338141Smax.romanov@nginx.com nxt_int_t ret; 339662Smax.romanov@nginx.com nxt_port_t *controller_port; 340141Smax.romanov@nginx.com nxt_router_t *router; 341141Smax.romanov@nginx.com nxt_runtime_t *rt; 342141Smax.romanov@nginx.com 343141Smax.romanov@nginx.com rt = task->thread->runtime; 34453Sigor@sysoev.ru 3451488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "router started"); 3461488St.nateldemoura@f5.com 347771Sigor@sysoev.ru #if (NXT_TLS) 348771Sigor@sysoev.ru rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 349771Sigor@sysoev.ru if (nxt_slow_path(rt->tls == NULL)) { 350771Sigor@sysoev.ru return NXT_ERROR; 351771Sigor@sysoev.ru } 352771Sigor@sysoev.ru 353771Sigor@sysoev.ru ret = rt->tls->library_init(task); 354771Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 355771Sigor@sysoev.ru return ret; 356771Sigor@sysoev.ru } 357771Sigor@sysoev.ru #endif 358771Sigor@sysoev.ru 3591459Smax.romanov@nginx.com ret = nxt_http_init(task); 36088Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 36188Smax.romanov@nginx.com return ret; 36288Smax.romanov@nginx.com } 36388Smax.romanov@nginx.com 36453Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 36553Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 36653Sigor@sysoev.ru return NXT_ERROR; 36753Sigor@sysoev.ru } 36853Sigor@sysoev.ru 36953Sigor@sysoev.ru nxt_queue_init(&router->engines); 37053Sigor@sysoev.ru nxt_queue_init(&router->sockets); 371133Sigor@sysoev.ru nxt_queue_init(&router->apps); 37253Sigor@sysoev.ru 373119Smax.romanov@nginx.com nxt_router = router; 374119Smax.romanov@nginx.com 375662Smax.romanov@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 376662Smax.romanov@nginx.com if (controller_port != NULL) { 377662Smax.romanov@nginx.com nxt_router_greet_controller(task, controller_port); 378662Smax.romanov@nginx.com } 379662Smax.romanov@nginx.com 380115Sigor@sysoev.ru return NXT_OK; 381115Sigor@sysoev.ru } 382115Sigor@sysoev.ru 383115Sigor@sysoev.ru 384343Smax.romanov@nginx.com static void 385662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 386662Smax.romanov@nginx.com { 387662Smax.romanov@nginx.com nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 388662Smax.romanov@nginx.com -1, 0, 0, NULL); 389662Smax.romanov@nginx.com } 390662Smax.romanov@nginx.com 391662Smax.romanov@nginx.com 392662Smax.romanov@nginx.com static void 393507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 394507Smax.romanov@nginx.com void *data) 395167Smax.romanov@nginx.com { 3961926Smax.romanov@nginx.com size_t size; 3971926Smax.romanov@nginx.com uint32_t stream; 3982014Smax.romanov@nginx.com nxt_fd_t port_fd, queue_fd; 3991926Smax.romanov@nginx.com nxt_int_t ret; 4001926Smax.romanov@nginx.com nxt_app_t *app; 4011926Smax.romanov@nginx.com nxt_buf_t *b; 4021998St.nateldemoura@f5.com nxt_port_t *dport; 4031926Smax.romanov@nginx.com nxt_runtime_t *rt; 4041926Smax.romanov@nginx.com nxt_app_joint_rpc_t *app_joint_rpc; 405343Smax.romanov@nginx.com 406343Smax.romanov@nginx.com app = data; 407167Smax.romanov@nginx.com 4081998St.nateldemoura@f5.com nxt_thread_mutex_lock(&app->mutex); 4091998St.nateldemoura@f5.com 4101998St.nateldemoura@f5.com dport = app->proto_port; 4111998St.nateldemoura@f5.com 4121998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex); 4131998St.nateldemoura@f5.com 4141998St.nateldemoura@f5.com if (dport != NULL) { 4151998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start process", &app->name, app); 4161998St.nateldemoura@f5.com 4171998St.nateldemoura@f5.com b = NULL; 4182014Smax.romanov@nginx.com port_fd = -1; 4192014Smax.romanov@nginx.com queue_fd = -1; 4201998St.nateldemoura@f5.com 4211998St.nateldemoura@f5.com } else { 4221998St.nateldemoura@f5.com if (app->proto_port_requests > 0) { 4231998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p wait for prototype process", 4241998St.nateldemoura@f5.com &app->name, app); 4251998St.nateldemoura@f5.com 4261998St.nateldemoura@f5.com app->proto_port_requests++; 4271998St.nateldemoura@f5.com 4281998St.nateldemoura@f5.com goto skip; 4291998St.nateldemoura@f5.com } 4301998St.nateldemoura@f5.com 4311998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start prototype process", &app->name, app); 4321998St.nateldemoura@f5.com 4331998St.nateldemoura@f5.com rt = task->thread->runtime; 4341998St.nateldemoura@f5.com dport = rt->port_by_type[NXT_PROCESS_MAIN]; 4351998St.nateldemoura@f5.com 4361998St.nateldemoura@f5.com size = app->name.length + 1 + app->conf.length; 4371998St.nateldemoura@f5.com 4381998St.nateldemoura@f5.com b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); 4391998St.nateldemoura@f5.com if (nxt_slow_path(b == NULL)) { 4401998St.nateldemoura@f5.com goto failed; 4411998St.nateldemoura@f5.com } 4421998St.nateldemoura@f5.com 4431998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->name); 4441998St.nateldemoura@f5.com *b->mem.free++ = '\0'; 4451998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->conf); 4462014Smax.romanov@nginx.com 4472014Smax.romanov@nginx.com port_fd = app->shared_port->pair[0]; 4482014Smax.romanov@nginx.com queue_fd = app->shared_port->queue_fd; 4491998St.nateldemoura@f5.com } 450343Smax.romanov@nginx.com 4511926Smax.romanov@nginx.com app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port, 4521926Smax.romanov@nginx.com nxt_router_app_port_ready, 4531926Smax.romanov@nginx.com nxt_router_app_port_error, 4541926Smax.romanov@nginx.com sizeof(nxt_app_joint_rpc_t)); 4551926Smax.romanov@nginx.com if (nxt_slow_path(app_joint_rpc == NULL)) { 456343Smax.romanov@nginx.com goto failed; 457343Smax.romanov@nginx.com } 458343Smax.romanov@nginx.com 4591926Smax.romanov@nginx.com stream = nxt_port_rpc_ex_stream(app_joint_rpc); 4601926Smax.romanov@nginx.com 4612014Smax.romanov@nginx.com ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, 4622014Smax.romanov@nginx.com port_fd, queue_fd, stream, port->id, b); 463648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 464648Svbart@nginx.com nxt_port_rpc_cancel(task, port, stream); 465753Smax.romanov@nginx.com 466648Svbart@nginx.com goto failed; 467648Svbart@nginx.com } 468343Smax.romanov@nginx.com 4691926Smax.romanov@nginx.com app_joint_rpc->app_joint = app->joint; 4701926Smax.romanov@nginx.com app_joint_rpc->generation = app->generation; 4711998St.nateldemoura@f5.com app_joint_rpc->proto = (b != NULL); 4721998St.nateldemoura@f5.com 4731998St.nateldemoura@f5.com if (b != NULL) { 4741998St.nateldemoura@f5.com app->proto_port_requests++; 4751998St.nateldemoura@f5.com 4761998St.nateldemoura@f5.com b = NULL; 4771998St.nateldemoura@f5.com } 4781926Smax.romanov@nginx.com 4791926Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, 1); 4801926Smax.romanov@nginx.com 481343Smax.romanov@nginx.com failed: 482343Smax.romanov@nginx.com 483648Svbart@nginx.com if (b != NULL) { 4841998St.nateldemoura@f5.com nxt_mp_free(b->data, b); 4851998St.nateldemoura@f5.com } 4861998St.nateldemoura@f5.com 4871998St.nateldemoura@f5.com skip: 488343Smax.romanov@nginx.com 489343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 490167Smax.romanov@nginx.com } 491167Smax.romanov@nginx.com 492167Smax.romanov@nginx.com 493753Smax.romanov@nginx.com static void 494753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 495753Smax.romanov@nginx.com { 496753Smax.romanov@nginx.com app_joint->use_count += i; 497753Smax.romanov@nginx.com 498753Smax.romanov@nginx.com if (app_joint->use_count == 0) { 499753Smax.romanov@nginx.com nxt_assert(app_joint->app == NULL); 500753Smax.romanov@nginx.com 501753Smax.romanov@nginx.com nxt_free(app_joint); 502753Smax.romanov@nginx.com } 503753Smax.romanov@nginx.com } 504753Smax.romanov@nginx.com 505753Smax.romanov@nginx.com 506343Smax.romanov@nginx.com static nxt_int_t 507507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 508141Smax.romanov@nginx.com { 509343Smax.romanov@nginx.com nxt_int_t res; 510343Smax.romanov@nginx.com nxt_port_t *router_port; 511343Smax.romanov@nginx.com nxt_runtime_t *rt; 512343Smax.romanov@nginx.com 5131549Smax.romanov@nginx.com nxt_debug(task, "app '%V' start process", &app->name); 5141549Smax.romanov@nginx.com 515343Smax.romanov@nginx.com rt = task->thread->runtime; 516343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 517343Smax.romanov@nginx.com 518343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1); 519343Smax.romanov@nginx.com 520507Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 521343Smax.romanov@nginx.com app); 522343Smax.romanov@nginx.com 523343Smax.romanov@nginx.com if (res == NXT_OK) { 524343Smax.romanov@nginx.com return res; 525318Smax.romanov@nginx.com } 526318Smax.romanov@nginx.com 527343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 528343Smax.romanov@nginx.com 529507Smax.romanov@nginx.com app->pending_processes--; 530343Smax.romanov@nginx.com 531343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 532343Smax.romanov@nginx.com 533343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 534343Smax.romanov@nginx.com 535343Smax.romanov@nginx.com return NXT_ERROR; 536318Smax.romanov@nginx.com } 537318Smax.romanov@nginx.com 538318Smax.romanov@nginx.com 539423Smax.romanov@nginx.com nxt_inline nxt_bool_t 5401555Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) 541423Smax.romanov@nginx.com { 5421555Smax.romanov@nginx.com nxt_buf_t *b, *next; 5431555Smax.romanov@nginx.com nxt_bool_t cancelled; 5441926Smax.romanov@nginx.com nxt_port_t *app_port; 5451555Smax.romanov@nginx.com nxt_msg_info_t *msg_info; 5461555Smax.romanov@nginx.com 5471555Smax.romanov@nginx.com msg_info = &req_rpc_data->msg_info; 548423Smax.romanov@nginx.com 549423Smax.romanov@nginx.com if (msg_info->buf == NULL) { 550423Smax.romanov@nginx.com return 0; 551423Smax.romanov@nginx.com } 552423Smax.romanov@nginx.com 5531926Smax.romanov@nginx.com app_port = req_rpc_data->app_port; 5541926Smax.romanov@nginx.com 5551926Smax.romanov@nginx.com if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) { 5561926Smax.romanov@nginx.com cancelled = nxt_app_queue_cancel(app_port->queue, 5571926Smax.romanov@nginx.com msg_info->tracking_cookie, 5581926Smax.romanov@nginx.com req_rpc_data->stream); 5591926Smax.romanov@nginx.com 5601926Smax.romanov@nginx.com if (cancelled) { 5611926Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router", 5621926Smax.romanov@nginx.com req_rpc_data->stream); 5631926Smax.romanov@nginx.com } 5641926Smax.romanov@nginx.com 5651926Smax.romanov@nginx.com } else { 5661926Smax.romanov@nginx.com cancelled = 0; 567423Smax.romanov@nginx.com } 568423Smax.romanov@nginx.com 569423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) { 570423Smax.romanov@nginx.com next = b->next; 5711269Sigor@sysoev.ru b->next = NULL; 572423Smax.romanov@nginx.com 573423Smax.romanov@nginx.com if (b->is_port_mmap_sent) { 574423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0; 575423Smax.romanov@nginx.com } 5761829Smax.romanov@nginx.com 5771829Smax.romanov@nginx.com b->completion_handler(task, b, b->parent); 578423Smax.romanov@nginx.com } 579423Smax.romanov@nginx.com 580423Smax.romanov@nginx.com msg_info->buf = NULL; 581423Smax.romanov@nginx.com 582423Smax.romanov@nginx.com return cancelled; 583423Smax.romanov@nginx.com } 584423Smax.romanov@nginx.com 585423Smax.romanov@nginx.com 586425Smax.romanov@nginx.com nxt_inline nxt_bool_t 587425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk) 588425Smax.romanov@nginx.com { 589425Smax.romanov@nginx.com if (lnk->next != NULL) { 590425Smax.romanov@nginx.com nxt_queue_remove(lnk); 591425Smax.romanov@nginx.com 592425Smax.romanov@nginx.com lnk->next = NULL; 593425Smax.romanov@nginx.com 594425Smax.romanov@nginx.com return 1; 595425Smax.romanov@nginx.com } 596425Smax.romanov@nginx.com 597425Smax.romanov@nginx.com return 0; 598425Smax.romanov@nginx.com } 599425Smax.romanov@nginx.com 600425Smax.romanov@nginx.com 601343Smax.romanov@nginx.com nxt_inline void 6021123Smax.romanov@nginx.com nxt_request_rpc_data_unlink(nxt_task_t *task, 6031123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data) 604343Smax.romanov@nginx.com { 6051561Smax.romanov@nginx.com nxt_app_t *app; 6061561Smax.romanov@nginx.com nxt_bool_t unlinked; 6071547Smax.romanov@nginx.com nxt_http_request_t *r; 6081547Smax.romanov@nginx.com 6091555Smax.romanov@nginx.com nxt_router_msg_cancel(task, req_rpc_data); 6101123Smax.romanov@nginx.com 6111978Smax.romanov@nginx.com app = req_rpc_data->app; 6121978Smax.romanov@nginx.com 6131123Smax.romanov@nginx.com if (req_rpc_data->app_port != NULL) { 6141978Smax.romanov@nginx.com nxt_router_app_port_release(task, app, req_rpc_data->app_port, 6151123Smax.romanov@nginx.com req_rpc_data->apr_action); 6161123Smax.romanov@nginx.com 6171123Smax.romanov@nginx.com req_rpc_data->app_port = NULL; 6181123Smax.romanov@nginx.com } 6191123Smax.romanov@nginx.com 6201547Smax.romanov@nginx.com r = req_rpc_data->request; 6211547Smax.romanov@nginx.com 6221547Smax.romanov@nginx.com if (r != NULL) { 6231547Smax.romanov@nginx.com r->timer_data = NULL; 6241547Smax.romanov@nginx.com 6251547Smax.romanov@nginx.com nxt_router_http_request_release_post(task, r); 6261547Smax.romanov@nginx.com 6271547Smax.romanov@nginx.com r->req_rpc_data = NULL; 6281123Smax.romanov@nginx.com req_rpc_data->request = NULL; 6291561Smax.romanov@nginx.com 6301561Smax.romanov@nginx.com if (app != NULL) { 6311561Smax.romanov@nginx.com unlinked = 0; 6321561Smax.romanov@nginx.com 6331561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 6341561Smax.romanov@nginx.com 6351561Smax.romanov@nginx.com if (r->app_link.next != NULL) { 6361561Smax.romanov@nginx.com nxt_queue_remove(&r->app_link); 6371561Smax.romanov@nginx.com r->app_link.next = NULL; 6381561Smax.romanov@nginx.com 6391561Smax.romanov@nginx.com unlinked = 1; 6401561Smax.romanov@nginx.com } 6411561Smax.romanov@nginx.com 6421561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 6431561Smax.romanov@nginx.com 6441561Smax.romanov@nginx.com if (unlinked) { 6451561Smax.romanov@nginx.com nxt_mp_release(r->mem_pool); 6461561Smax.romanov@nginx.com } 6471561Smax.romanov@nginx.com } 6481561Smax.romanov@nginx.com } 6491561Smax.romanov@nginx.com 6501561Smax.romanov@nginx.com if (app != NULL) { 6511561Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 6521561Smax.romanov@nginx.com 6531561Smax.romanov@nginx.com req_rpc_data->app = NULL; 654346Smax.romanov@nginx.com } 6551547Smax.romanov@nginx.com 6561547Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1) { 6571547Smax.romanov@nginx.com nxt_fd_close(req_rpc_data->msg_info.body_fd); 6581547Smax.romanov@nginx.com 6591547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1; 6601547Smax.romanov@nginx.com } 6611547Smax.romanov@nginx.com 6621547Smax.romanov@nginx.com if (req_rpc_data->rpc_cancel) { 6631547Smax.romanov@nginx.com req_rpc_data->rpc_cancel = 0; 6641547Smax.romanov@nginx.com 6651547Smax.romanov@nginx.com nxt_port_rpc_cancel(task, task->thread->engine->port, 6661547Smax.romanov@nginx.com req_rpc_data->stream); 6671547Smax.romanov@nginx.com } 668343Smax.romanov@nginx.com } 669343Smax.romanov@nginx.com 670343Smax.romanov@nginx.com 6711552Smax.romanov@nginx.com static void 672141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 673141Smax.romanov@nginx.com { 6741555Smax.romanov@nginx.com nxt_int_t res; 6751547Smax.romanov@nginx.com nxt_app_t *app; 6761547Smax.romanov@nginx.com nxt_port_t *port, *main_app_port; 6771547Smax.romanov@nginx.com nxt_runtime_t *rt; 6781547Smax.romanov@nginx.com 679141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 680141Smax.romanov@nginx.com 6811547Smax.romanov@nginx.com port = msg->u.new_port; 6821547Smax.romanov@nginx.com 6831547Smax.romanov@nginx.com if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { 684662Smax.romanov@nginx.com nxt_router_greet_controller(task, msg->u.new_port); 685662Smax.romanov@nginx.com } 686662Smax.romanov@nginx.com 6871998St.nateldemoura@f5.com if (port != NULL && port->type == NXT_PROCESS_PROTOTYPE) { 6881998St.nateldemoura@f5.com nxt_port_rpc_handler(task, msg); 6891998St.nateldemoura@f5.com 6901998St.nateldemoura@f5.com return; 6911998St.nateldemoura@f5.com } 6921998St.nateldemoura@f5.com 6931547Smax.romanov@nginx.com if (port == NULL || port->type != NXT_PROCESS_APP) { 6941547Smax.romanov@nginx.com 6951547Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 6961547Smax.romanov@nginx.com return; 6971547Smax.romanov@nginx.com } 6981547Smax.romanov@nginx.com 6991547Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 7001555Smax.romanov@nginx.com 7011555Smax.romanov@nginx.com } else { 7021558Smax.romanov@nginx.com if (msg->fd[1] != -1) { 7031558Smax.romanov@nginx.com res = nxt_router_port_queue_map(task, port, msg->fd[1]); 7041555Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 7051555Smax.romanov@nginx.com return; 7061555Smax.romanov@nginx.com } 7071555Smax.romanov@nginx.com 7081558Smax.romanov@nginx.com nxt_fd_close(msg->fd[1]); 7091558Smax.romanov@nginx.com msg->fd[1] = -1; 7101555Smax.romanov@nginx.com } 7111547Smax.romanov@nginx.com } 7121547Smax.romanov@nginx.com 7131547Smax.romanov@nginx.com if (msg->port_msg.stream != 0) { 7141547Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 715141Smax.romanov@nginx.com return; 716141Smax.romanov@nginx.com } 717141Smax.romanov@nginx.com 7181998St.nateldemoura@f5.com nxt_debug(task, "new port id %d (%d)", port->id, port->type); 7191998St.nateldemoura@f5.com 7201547Smax.romanov@nginx.com /* 7211547Smax.romanov@nginx.com * Port with "id == 0" is application 'main' port and it always 7221547Smax.romanov@nginx.com * should come with non-zero stream. 7231547Smax.romanov@nginx.com */ 7241547Smax.romanov@nginx.com nxt_assert(port->id != 0); 7251547Smax.romanov@nginx.com 7261547Smax.romanov@nginx.com /* Find 'main' app port and get app reference. */ 7271547Smax.romanov@nginx.com rt = task->thread->runtime; 7281547Smax.romanov@nginx.com 7291547Smax.romanov@nginx.com /* 7301547Smax.romanov@nginx.com * It is safe to access 'runtime->ports' hash because 'NEW_PORT' 7311547Smax.romanov@nginx.com * sent to main port (with id == 0) and processed in main thread. 7321547Smax.romanov@nginx.com */ 7331547Smax.romanov@nginx.com main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); 7341547Smax.romanov@nginx.com nxt_assert(main_app_port != NULL); 7351547Smax.romanov@nginx.com 7361547Smax.romanov@nginx.com app = main_app_port->app; 7371915Smax.romanov@nginx.com 7381915Smax.romanov@nginx.com if (nxt_fast_path(app != NULL)) { 7391915Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 7401915Smax.romanov@nginx.com 7411915Smax.romanov@nginx.com /* TODO here should be find-and-add code because there can be 7421915Smax.romanov@nginx.com port waiters in port_hash */ 7431915Smax.romanov@nginx.com nxt_port_hash_add(&app->port_hash, port); 7441915Smax.romanov@nginx.com app->port_hash_count++; 7451915Smax.romanov@nginx.com 7461915Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 7471915Smax.romanov@nginx.com 7481915Smax.romanov@nginx.com port->