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); 1111936So.canty@f5.com static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task, 1121936So.canty@f5.com nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf, 1131936So.canty@f5.com nxt_conf_value_t *conf); 1141563Svbart@nginx.com 115133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 1161563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 1171563Svbart@nginx.com static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, 1181563Svbart@nginx.com nxt_app_t *app); 1191563Svbart@nginx.com static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, 1201563Svbart@nginx.com nxt_str_t *name); 1211563Svbart@nginx.com static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, 1221563Svbart@nginx.com int i); 1231563Svbart@nginx.com 1241555Smax.romanov@nginx.com static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, 1251555Smax.romanov@nginx.com nxt_port_t *port); 1261555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, 1271555Smax.romanov@nginx.com nxt_port_t *port); 1281555Smax.romanov@nginx.com static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, 1291555Smax.romanov@nginx.com nxt_port_t *port, nxt_fd_t fd); 130198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 131198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 132198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 133198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 134198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 135198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 136774Svbart@nginx.com #if (NXT_TLS) 137774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task, 138774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 1391828Sa.suvorov@f5.com static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 1401920Sa.suvorov@f5.com nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init, 1411920Sa.suvorov@f5.com nxt_bool_t last); 142774Svbart@nginx.com #endif 143507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task, 144507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 145507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task, 146507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 147507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task, 148507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 149359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 150359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 151359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 152359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 15353Sigor@sysoev.ru 15453Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 15553Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 15653Sigor@sysoev.ru const nxt_event_interface_t *interface); 157115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 158115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 159115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 160115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 161115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 162115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 163154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 164154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 165154Sigor@sysoev.ru nxt_work_handler_t handler); 166313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 167313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 168139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 169139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 17053Sigor@sysoev.ru 17153Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 17253Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 17353Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 17453Sigor@sysoev.ru nxt_event_engine_t *engine); 175343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 176133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 17753Sigor@sysoev.ru 178315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 179315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 180315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 181315Sigor@sysoev.ru nxt_work_t *jobs); 18253Sigor@sysoev.ru 18353Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 1841545Smax.romanov@nginx.com static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, 1851545Smax.romanov@nginx.com void *data); 18653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 18753Sigor@sysoev.ru void *data); 18853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 18953Sigor@sysoev.ru void *data); 19053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 19153Sigor@sysoev.ru void *data); 192313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 193313Sigor@sysoev.ru void *data); 19453Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 19553Sigor@sysoev.ru void *data); 19653Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 19753Sigor@sysoev.ru void *data); 1981547Smax.romanov@nginx.com static void nxt_router_req_headers_ack_handler(nxt_task_t *task, 1991547Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); 200359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 201359Sigor@sysoev.ru nxt_socket_conf_t *skcf); 20253Sigor@sysoev.ru 203630Svbart@nginx.com static void nxt_router_access_log_writer(nxt_task_t *task, 204630Svbart@nginx.com nxt_http_request_t *r, nxt_router_access_log_t *access_log); 205630Svbart@nginx.com static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 206630Svbart@nginx.com struct tm *tm, size_t size, const char *format); 207630Svbart@nginx.com static void nxt_router_access_log_open(nxt_task_t *task, 208630Svbart@nginx.com nxt_router_temp_conf_t *tmcf); 209630Svbart@nginx.com static void nxt_router_access_log_ready(nxt_task_t *task, 210630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 211630Svbart@nginx.com static void nxt_router_access_log_error(nxt_task_t *task, 212630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 213630Svbart@nginx.com static void nxt_router_access_log_release(nxt_task_t *task, 214630Svbart@nginx.com nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 215651Svbart@nginx.com static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 216651Svbart@nginx.com void *data); 217631Svbart@nginx.com static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 218631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 219631Svbart@nginx.com static void nxt_router_access_log_reopen_error(nxt_task_t *task, 220631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 221630Svbart@nginx.com 222343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task, 223343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 224343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task, 225343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 226343Smax.romanov@nginx.com 2271563Svbart@nginx.com static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i); 228753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 2291123Smax.romanov@nginx.com 2301978Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_app_t *app, 2311978Smax.romanov@nginx.com nxt_port_t *port, nxt_apr_action_t action); 2321547Smax.romanov@nginx.com static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 2331547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2341561Smax.romanov@nginx.com static void nxt_router_http_request_error(nxt_task_t *task, void *obj, 2351561Smax.romanov@nginx.com void *data); 2361547Smax.romanov@nginx.com static void nxt_router_http_request_done(nxt_task_t *task, void *obj, 2371547Smax.romanov@nginx.com void *data); 238141Smax.romanov@nginx.com 239425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task, 2401547Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data); 2411007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 2421547Smax.romanov@nginx.com nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); 243510Salexander.borisov@nginx.com 244318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 245507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 246507Smax.romanov@nginx.com void *data); 247507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 248507Smax.romanov@nginx.com void *data); 249753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 250507Smax.romanov@nginx.com void *data); 251753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 252431Sigor@sysoev.ru 253431Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_state; 254431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 255141Smax.romanov@nginx.com 256753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task, 257753Smax.romanov@nginx.com nxt_app_joint_t *app_joint, int i); 258753Smax.romanov@nginx.com 2591547Smax.romanov@nginx.com static void nxt_router_http_request_release_post(nxt_task_t *task, 2601007Salexander.borisov@nginx.com nxt_http_request_t *r); 2611007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 2621007Salexander.borisov@nginx.com void *data); 2631321Smax.romanov@nginx.com static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 2641545Smax.romanov@nginx.com static void nxt_router_get_port_handler(nxt_task_t *task, 2651545Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2661546Smax.romanov@nginx.com static void nxt_router_get_mmap_handler(nxt_task_t *task, 2671546Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 2681007Salexander.borisov@nginx.com 2691149Smax.romanov@nginx.com extern const nxt_http_request_state_t nxt_http_websocket; 2701131Smax.romanov@nginx.com 271119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 27220Sigor@sysoev.ru 273743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_"); 274743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string(""); 275743Smax.romanov@nginx.com 276743Smax.romanov@nginx.com static const nxt_str_t *nxt_app_msg_prefix[] = { 277804Svbart@nginx.com &empty_prefix, 2781594Smax.romanov@nginx.com &empty_prefix, 279743Smax.romanov@nginx.com &http_prefix, 280743Smax.romanov@nginx.com &http_prefix, 281743Smax.romanov@nginx.com &http_prefix, 282977Smax.romanov@gmail.com &empty_prefix, 283216Sigor@sysoev.ru }; 284216Sigor@sysoev.ru 285216Sigor@sysoev.ru 2861488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_router_process_port_handlers = { 2871488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 288662Smax.romanov@nginx.com .new_port = nxt_router_new_port_handler, 2891545Smax.romanov@nginx.com .get_port = nxt_router_get_port_handler, 290662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 291662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 2921546Smax.romanov@nginx.com .get_mmap = nxt_router_get_mmap_handler, 293662Smax.romanov@nginx.com .data = nxt_router_conf_data_handler, 2941926Smax.romanov@nginx.com .app_restart = nxt_router_app_restart_handler, 295662Smax.romanov@nginx.com .remove_pid = nxt_router_remove_pid_handler, 296662Smax.romanov@nginx.com .access_log = nxt_router_access_log_reopen_handler, 297662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 298662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 2991321Smax.romanov@nginx.com .oosm = nxt_router_oosm_handler, 300662Smax.romanov@nginx.com }; 301662Smax.romanov@nginx.com 302662Smax.romanov@nginx.com 3031488St.nateldemoura@f5.com const nxt_process_init_t nxt_router_process = { 3041488St.nateldemoura@f5.com .name = "router", 3051488St.nateldemoura@f5.com .type = NXT_PROCESS_ROUTER, 3061488St.nateldemoura@f5.com .prefork = nxt_router_prefork, 3071488St.nateldemoura@f5.com .restart = 1, 3081488St.nateldemoura@f5.com .setup = nxt_process_core_setup, 3091488St.nateldemoura@f5.com .start = nxt_router_start, 3101488St.nateldemoura@f5.com .port_handlers = &nxt_router_process_port_handlers, 3111488St.nateldemoura@f5.com .signals = nxt_process_signals, 3121488St.nateldemoura@f5.com }; 3131488St.nateldemoura@f5.com 3141488St.nateldemoura@f5.com 3151509Sigor@sysoev.ru /* Queues of nxt_socket_conf_t */ 3161509Sigor@sysoev.ru nxt_queue_t creating_sockets; 3171509Sigor@sysoev.ru nxt_queue_t pending_sockets; 3181509Sigor@sysoev.ru nxt_queue_t updating_sockets; 3191509Sigor@sysoev.ru nxt_queue_t keeping_sockets; 3201509Sigor@sysoev.ru nxt_queue_t deleting_sockets; 3211509Sigor@sysoev.ru 3221509Sigor@sysoev.ru 3231488St.nateldemoura@f5.com static nxt_int_t 3241488St.nateldemoura@f5.com nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 3251488St.nateldemoura@f5.com { 3261488St.nateldemoura@f5.com nxt_runtime_stop_app_processes(task, task->thread->runtime); 3271488St.nateldemoura@f5.com 3281488St.nateldemoura@f5.com return NXT_OK; 3291488St.nateldemoura@f5.com } 3301488St.nateldemoura@f5.com 3311488St.nateldemoura@f5.com 3321488St.nateldemoura@f5.com static nxt_int_t 3331488St.nateldemoura@f5.com nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) 33420Sigor@sysoev.ru { 335141Smax.romanov@nginx.com nxt_int_t ret; 336662Smax.romanov@nginx.com nxt_port_t *controller_port; 337141Smax.romanov@nginx.com nxt_router_t *router; 338141Smax.romanov@nginx.com nxt_runtime_t *rt; 339141Smax.romanov@nginx.com 340141Smax.romanov@nginx.com rt = task->thread->runtime; 34153Sigor@sysoev.ru 3421488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "router started"); 3431488St.nateldemoura@f5.com 344771Sigor@sysoev.ru #if (NXT_TLS) 345771Sigor@sysoev.ru rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 346771Sigor@sysoev.ru if (nxt_slow_path(rt->tls == NULL)) { 347771Sigor@sysoev.ru return NXT_ERROR; 348771Sigor@sysoev.ru } 349771Sigor@sysoev.ru 350771Sigor@sysoev.ru ret = rt->tls->library_init(task); 351771Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 352771Sigor@sysoev.ru return ret; 353771Sigor@sysoev.ru } 354771Sigor@sysoev.ru #endif 355771Sigor@sysoev.ru 3561459Smax.romanov@nginx.com ret = nxt_http_init(task); 35788Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 35888Smax.romanov@nginx.com return ret; 35988Smax.romanov@nginx.com } 36088Smax.romanov@nginx.com 36153Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 36253Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 36353Sigor@sysoev.ru return NXT_ERROR; 36453Sigor@sysoev.ru } 36553Sigor@sysoev.ru 36653Sigor@sysoev.ru nxt_queue_init(&router->engines); 36753Sigor@sysoev.ru nxt_queue_init(&router->sockets); 368133Sigor@sysoev.ru nxt_queue_init(&router->apps); 36953Sigor@sysoev.ru 370119Smax.romanov@nginx.com nxt_router = router; 371119Smax.romanov@nginx.com 372662Smax.romanov@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 373662Smax.romanov@nginx.com if (controller_port != NULL) { 374662Smax.romanov@nginx.com nxt_router_greet_controller(task, controller_port); 375662Smax.romanov@nginx.com } 376662Smax.romanov@nginx.com 377115Sigor@sysoev.ru return NXT_OK; 378115Sigor@sysoev.ru } 379115Sigor@sysoev.ru 380115Sigor@sysoev.ru 381343Smax.romanov@nginx.com static void 382662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 383662Smax.romanov@nginx.com { 384662Smax.romanov@nginx.com nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 385662Smax.romanov@nginx.com -1, 0, 0, NULL); 386662Smax.romanov@nginx.com } 387662Smax.romanov@nginx.com 388662Smax.romanov@nginx.com 389662Smax.romanov@nginx.com static void 390507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 391507Smax.romanov@nginx.com void *data) 392167Smax.romanov@nginx.com { 3931926Smax.romanov@nginx.com size_t size; 3941926Smax.romanov@nginx.com uint32_t stream; 395*2014Smax.romanov@nginx.com nxt_fd_t port_fd, queue_fd; 3961926Smax.romanov@nginx.com nxt_int_t ret; 3971926Smax.romanov@nginx.com nxt_app_t *app; 3981926Smax.romanov@nginx.com nxt_buf_t *b; 3991998St.nateldemoura@f5.com nxt_port_t *dport; 4001926Smax.romanov@nginx.com nxt_runtime_t *rt; 4011926Smax.romanov@nginx.com nxt_app_joint_rpc_t *app_joint_rpc; 402343Smax.romanov@nginx.com 403343Smax.romanov@nginx.com app = data; 404167Smax.romanov@nginx.com 4051998St.nateldemoura@f5.com nxt_thread_mutex_lock(&app->mutex); 4061998St.nateldemoura@f5.com 4071998St.nateldemoura@f5.com dport = app->proto_port; 4081998St.nateldemoura@f5.com 4091998St.nateldemoura@f5.com nxt_thread_mutex_unlock(&app->mutex); 4101998St.nateldemoura@f5.com 4111998St.nateldemoura@f5.com if (dport != NULL) { 4121998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start process", &app->name, app); 4131998St.nateldemoura@f5.com 4141998St.nateldemoura@f5.com b = NULL; 415*2014Smax.romanov@nginx.com port_fd = -1; 416*2014Smax.romanov@nginx.com queue_fd = -1; 4171998St.nateldemoura@f5.com 4181998St.nateldemoura@f5.com } else { 4191998St.nateldemoura@f5.com if (app->proto_port_requests > 0) { 4201998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p wait for prototype process", 4211998St.nateldemoura@f5.com &app->name, app); 4221998St.nateldemoura@f5.com 4231998St.nateldemoura@f5.com app->proto_port_requests++; 4241998St.nateldemoura@f5.com 4251998St.nateldemoura@f5.com goto skip; 4261998St.nateldemoura@f5.com } 4271998St.nateldemoura@f5.com 4281998St.nateldemoura@f5.com nxt_debug(task, "app '%V' %p start prototype process", &app->name, app); 4291998St.nateldemoura@f5.com 4301998St.nateldemoura@f5.com rt = task->thread->runtime; 4311998St.nateldemoura@f5.com dport = rt->port_by_type[NXT_PROCESS_MAIN]; 4321998St.nateldemoura@f5.com 4331998St.nateldemoura@f5.com size = app->name.length + 1 + app->conf.length; 4341998St.nateldemoura@f5.com 4351998St.nateldemoura@f5.com b = nxt_buf_mem_alloc(task->thread->engine->mem_pool, size, 0); 4361998St.nateldemoura@f5.com if (nxt_slow_path(b == NULL)) { 4371998St.nateldemoura@f5.com goto failed; 4381998St.nateldemoura@f5.com } 4391998St.nateldemoura@f5.com 4401998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->name); 4411998St.nateldemoura@f5.com *b->mem.free++ = '\0'; 4421998St.nateldemoura@f5.com nxt_buf_cpystr(b, &app->conf); 443*2014Smax.romanov@nginx.com 444*2014Smax.romanov@nginx.com port_fd = app->shared_port->pair[0]; 445*2014Smax.romanov@nginx.com queue_fd = app->shared_port->queue_fd; 4461998St.nateldemoura@f5.com } 447343Smax.romanov@nginx.com 4481926Smax.romanov@nginx.com app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port, 4491926Smax.romanov@nginx.com nxt_router_app_port_ready, 4501926Smax.romanov@nginx.com nxt_router_app_port_error, 4511926Smax.romanov@nginx.com sizeof(nxt_app_joint_rpc_t)); 4521926Smax.romanov@nginx.com if (nxt_slow_path(app_joint_rpc == NULL)) { 453343Smax.romanov@nginx.com goto failed; 454343Smax.romanov@nginx.com } 455343Smax.romanov@nginx.com 4561926Smax.romanov@nginx.com stream = nxt_port_rpc_ex_stream(app_joint_rpc); 4571926Smax.romanov@nginx.com 458*2014Smax.romanov@nginx.com ret = nxt_port_socket_write2(task, dport, NXT_PORT_MSG_START_PROCESS, 459*2014Smax.romanov@nginx.com port_fd, queue_fd, stream, port->id, b); 460648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 461648Svbart@nginx.com nxt_port_rpc_cancel(task, port, stream); 462753Smax.romanov@nginx.com 463648Svbart@nginx.com goto failed; 464648Svbart@nginx.com } 465343Smax.romanov@nginx.com 4661926Smax.romanov@nginx.com app_joint_rpc->app_joint = app->joint; 4671926Smax.romanov@nginx.com app_joint_rpc->generation = app->generation; 4681998St.nateldemoura@f5.com app_joint_rpc->proto = (b != NULL); 4691998St.nateldemoura@f5.com 4701998St.nateldemoura@f5.com if (b != NULL) { 4711998St.nateldemoura@f5.com app->proto_port_requests++; 4721998St.nateldemoura@f5.com 4731998St.nateldemoura@f5.com b = NULL; 4741998St.nateldemoura@f5.com } 4751926Smax.romanov@nginx.com 4761926Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, 1); 4771926Smax.romanov@nginx.com 478343Smax.romanov@nginx.com failed: 479343Smax.romanov@nginx.com 480648Svbart@nginx.com if (b != NULL) { 4811998St.nateldemoura@f5.com nxt_mp_free(b->data, b); 4821998St.nateldemoura@f5.com } 4831998St.nateldemoura@f5.com 4841998St.nateldemoura@f5.com skip: 485343Smax.romanov@nginx.com 486343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 487167Smax.romanov@nginx.com } 488167Smax.romanov@nginx.com 489167Smax.romanov@nginx.com 490753Smax.romanov@nginx.com static void 491753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 492753Smax.romanov@nginx.com { 493753Smax.romanov@nginx.com app_joint->use_count += i; 494753Smax.romanov@nginx.com 495753Smax.romanov@nginx.com if (app_joint->use_count == 0) { 496753Smax.romanov@nginx.com nxt_assert(app_joint->app == NULL); 497753Smax.romanov@nginx.com 498753Smax.romanov@nginx.com nxt_free(app_joint); 499753Smax.romanov@nginx.com } 500753Smax.romanov@nginx.com } 501753Smax.romanov@nginx.com 502753Smax.romanov@nginx.com 503343Smax.romanov@nginx.com static nxt_int_t 504507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 505141Smax.romanov@nginx.com { 506343Smax.romanov@nginx.com nxt_int_t res; 507343Smax.romanov@nginx.com nxt_port_t *router_port; 508343Smax.romanov@nginx.com nxt_runtime_t *rt; 509343Smax.romanov@nginx.com 5101549Smax.romanov@nginx.com nxt_debug(task, "app '%V' start process", &app->name); 5111549Smax.romanov@nginx.com 512343Smax.romanov@nginx.com rt = task->thread->runtime; 513343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 514343Smax.romanov@nginx.com 515343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1); 516343Smax.romanov@nginx.com 517507Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 518343Smax.romanov@nginx.com app); 519343Smax.romanov@nginx.com 520343Smax.romanov@nginx.com if (res == NXT_OK) { 521343Smax.romanov@nginx.com return res; 522318Smax.romanov@nginx.com } 523318Smax.romanov@nginx.com 524343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 525343Smax.romanov@nginx.com 526507Smax.romanov@nginx.com app->pending_processes--; 527343Smax.romanov@nginx.com 528343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 529343Smax.romanov@nginx.com 530343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 531343Smax.romanov@nginx.com 532343Smax.romanov@nginx.com return NXT_ERROR; 533318Smax.romanov@nginx.com } 534318Smax.romanov@nginx.com 535318Smax.romanov@nginx.com 536423Smax.romanov@nginx.com nxt_inline nxt_bool_t 5371555Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) 538423Smax.romanov@nginx.com { 5391555Smax.romanov@nginx.com nxt_buf_t *b, *next; 5401555Smax.romanov@nginx.com nxt_bool_t cancelled; 5411926Smax.romanov@nginx.com nxt_port_t *app_port; 5421555Smax.romanov@nginx.com nxt_msg_info_t *msg_info; 5431555Smax.romanov@nginx.com 5441555Smax.romanov@nginx.com msg_info = &req_rpc_data->msg_info; 545423Smax.romanov@nginx.com 546423Smax.romanov@nginx.com if (msg_info->buf == NULL) { 547423Smax.romanov@nginx.com return 0; 548423Smax.romanov@nginx.com } 549423Smax.romanov@nginx.com 5501926Smax.romanov@nginx.com app_port = req_rpc_data->app_port; 5511926Smax.romanov@nginx.com 5521926Smax.romanov@nginx.com if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) { 5531926Smax.romanov@nginx.com cancelled = nxt_app_queue_cancel(app_port->queue, 5541926Smax.romanov@nginx.com msg_info->tracking_cookie, 5551926Smax.romanov@nginx.com req_rpc_data->stream); 5561926Smax.romanov@nginx.com 5571926Smax.romanov@nginx.com if (cancelled) { 5581926Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router", 5591926Smax.romanov@nginx.com req_rpc_data->stream); 5601926Smax.romanov@nginx.com } 5611926Smax.romanov@nginx.com 5621926Smax.romanov@nginx.com } else { 5631926Smax.romanov@nginx.com cancelled = 0; 564423Smax.romanov@nginx.com } 565423Smax.romanov@nginx.com 566423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) { 567423Smax.romanov@nginx.com next = b->next; 5681269Sigor@sysoev.ru b->next = NULL; 569423Smax.romanov@nginx.com 570423Smax.romanov@nginx.com if (b->is_port_mmap_sent) { 571423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0; 572423Smax.romanov@nginx.com } 5731829Smax.romanov@nginx.com 5741829Smax.romanov@nginx.com b->completion_handler(task, b, b->parent); 575423Smax.romanov@nginx.com } 576423Smax.romanov@nginx.com 577423Smax.romanov@nginx.com msg_info->buf = NULL; 578423Smax.romanov@nginx.com 579423Smax.romanov@nginx.com return cancelled; 580423Smax.romanov@nginx.com } 581423Smax.romanov@nginx.com 582423Smax.romanov@nginx.com 583425Smax.romanov@nginx.com nxt_inline nxt_bool_t 584425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk) 585425Smax.romanov@nginx.com { 586425Smax.romanov@nginx.com if (lnk->next != NULL) { 587425Smax.romanov@nginx.com nxt_queue_remove(lnk); 588425Smax.romanov@nginx.com 589425Smax.romanov@nginx.com lnk->next = NULL; 590425Smax.romanov@nginx.com 591425Smax.romanov@nginx.com return 1; 592425Smax.romanov@nginx.com } 593425Smax.romanov@nginx.com 594425Smax.romanov@nginx.com return 0; 595425Smax.romanov@nginx.com } 596425Smax.romanov@nginx.com 597425Smax.romanov@nginx.com 598343Smax.romanov@nginx.com nxt_inline void 5991123Smax.romanov@nginx.com nxt_request_rpc_data_unlink(nxt_task_t *task, 6001123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data) 601343Smax.romanov@nginx.com { 6021561Smax.romanov@nginx.com nxt_app_t *app; 6031561Smax.romanov@nginx.com nxt_bool_t unlinked; 6041547Smax.romanov@nginx.com nxt_http_request_t *r; 6051547Smax.romanov@nginx.com 6061555Smax.romanov@nginx.com nxt_router_msg_cancel(task, req_rpc_data); 6071123Smax.romanov@nginx.com 6081978Smax.romanov@nginx.com app = req_rpc_data->app; 6091978Smax.romanov@nginx.com 6101123Smax.romanov@nginx.com if (req_rpc_data->app_port != NULL) { 6111978Smax.romanov@nginx.com nxt_router_app_port_release(task, app, req_rpc_data->app_port, 6121123Smax.romanov@nginx.com req_rpc_data->apr_action); 6131123Smax.romanov@nginx.com 6141123Smax.romanov@nginx.com req_rpc_data->app_port = NULL; 6151123Smax.romanov@nginx.com } 6161123Smax.romanov@nginx.com 6171547Smax.romanov@nginx.com r = req_rpc_data->request; 6181547Smax.romanov@nginx.com 6191547Smax.romanov@nginx.com if (r != NULL) { 6201547Smax.romanov@nginx.com r->timer_data = NULL; 6211547Smax.romanov@nginx.com 6221547Smax.romanov@nginx.com nxt_router_http_request_release_post(task, r); 6231547Smax.romanov@nginx.com 6241547Smax.romanov@nginx.com r->req_rpc_data = NULL; 6251123Smax.romanov@nginx.com req_rpc_data->request = NULL; 6261561Smax.romanov@nginx.com 6271561Smax.romanov@nginx.com if (app != NULL) { 6281561Smax.romanov@nginx.com unlinked = 0; 6291561Smax.romanov@nginx.com 6301561Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 6311561Smax.romanov@nginx.com 6321561Smax.romanov@nginx.com if (r->app_link.next != NULL) { 6331561Smax.romanov@nginx.com nxt_queue_remove(&r->app_link); 6341561Smax.romanov@nginx.com r->app_link.next = NULL; 6351561Smax.romanov@nginx.com 6361561Smax.romanov@nginx.com unlinked = 1; 6371561Smax.romanov@nginx.com } 6381561Smax.romanov@nginx.com 6391561Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 6401561Smax.romanov@nginx.com 6411561Smax.romanov@nginx.com if (unlinked) { 6421561Smax.romanov@nginx.com nxt_mp_release(r->mem_pool); 6431561Smax.romanov@nginx.com } 6441561Smax.romanov@nginx.com } 6451561Smax.romanov@nginx.com } 6461561Smax.romanov@nginx.com 6471561Smax.romanov@nginx.com if (app != NULL) { 6481561Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 6491561Smax.romanov@nginx.com 6501561Smax.romanov@nginx.com req_rpc_data->app = NULL; 651346Smax.romanov@nginx.com } 6521547Smax.romanov@nginx.com 6531547Smax.romanov@nginx.com if (req_rpc_data->msg_info.body_fd != -1) { 6541547Smax.romanov@nginx.com nxt_fd_close(req_rpc_data->msg_info.body_fd); 6551547Smax.romanov@nginx.com 6561547Smax.romanov@nginx.com req_rpc_data->msg_info.body_fd = -1; 6571547Smax.romanov@nginx.com } 6581547Smax.romanov@nginx.com 6591547Smax.romanov@nginx.com if (req_rpc_data->rpc_cancel) { 6601547Smax.romanov@nginx.com req_rpc_data->rpc_cancel = 0; 6611547Smax.romanov@nginx.com 6621547Smax.romanov@nginx.com nxt_port_rpc_cancel(task, task->thread->engine->port, 6631547Smax.romanov@nginx.com req_rpc_data->stream); 6641547Smax.romanov@nginx.com } 665343Smax.romanov@nginx.com } 666343Smax.romanov@nginx.com 667343Smax.romanov@nginx.com 6681552Smax.romanov@nginx.com static void 669141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 670141Smax.romanov@nginx.com { 6711555Smax.romanov@nginx.com nxt_int_t res; 6721547Smax.romanov@nginx.com nxt_app_t *app; 6731547Smax.romanov@nginx.com nxt_port_t *port, *main_app_port; 6741547Smax.romanov@nginx.com nxt_runtime_t *rt; 6751547Smax.romanov@nginx.com 676141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 677141Smax.romanov@nginx.com 6781547Smax.romanov@nginx.com port = msg->u.new_port; 6791547Smax.romanov@nginx.com 6801547Smax.romanov@nginx.com if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { 681662Smax.romanov@nginx.com nxt_router_greet_controller(task, msg->u.new_port); 682662Smax.romanov@nginx.com } 683662Smax.romanov@nginx.com 6841998St.nateldemoura@f5.com if (port != NULL && port->type == NXT_PROCESS_PROTOTYPE) { 6851998St.nateldemoura@f5.com nxt_port_rpc_handler(task, msg); 6861998St.nateldemoura@f5.com 6871998St.nateldemoura@f5.com return; 6881998St.nateldemoura@f5.com } 6891998St.nateldemoura@f5.com 6901547Smax.romanov@nginx.com if (port == NULL || port->type != NXT_PROCESS_APP) { 6911547Smax.romanov@nginx.com 6921547Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 6931547Smax.romanov@nginx.com return; 6941547Smax.romanov@nginx.com } 6951547Smax.romanov@nginx.com 6961547Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 6971555Smax.romanov@nginx.com 6981555Smax.romanov@nginx.com } else { 6991558Smax.romanov@nginx.com if (msg->fd[1] != -1) { 7001558Smax.romanov@nginx.com res = nxt_router_port_queue_map(task, port, msg->fd[1]); 7011555Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 7021555Smax.romanov@nginx.com return; 7031555Smax.romanov@nginx.com } 7041555Smax.romanov@nginx.com 7051558Smax.romanov@nginx.com nxt_fd_close(msg->fd[1]); 7061558Smax.romanov@nginx.com msg->fd[1] = -1; 7071555Smax.romanov@nginx.com } 7081547Smax.romanov@nginx.com } 7091547Smax.romanov@nginx.com 7101547Smax.romanov@nginx.com if (msg->port_msg.stream != 0) { 7111547Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 712141Smax.romanov@nginx.com return; 713141Smax.romanov@nginx.com } 714141Smax.romanov@nginx.com 7151998St.nateldemoura@f5.com nxt_debug(task, "new port id %d (%d)", port->id, port->type); 7161998St.nateldemoura@f5.com 7171547Smax.romanov@nginx.com /* 7181547Smax.romanov@nginx.com * Port with "id == 0" is application 'main' port and it always 7191547Smax.romanov@nginx.com * should come with non-zero stream. 7201547Smax.romanov@nginx.com */ 7211547Smax.romanov@nginx.com nxt_assert(port->id != 0); 7221547Smax.romanov@nginx.com 7231547Smax.romanov@nginx.com /* Find 'main' app port and get app reference. */ 7241547Smax.romanov@nginx.com rt = task->thread->runtime; 7251547Smax.romanov@nginx.com 7261547Smax.romanov@nginx.com /* 7271547Smax.romanov@nginx.com * It is safe to access 'runtime->ports' hash because 'NEW_PORT' 7281547Smax.romanov@nginx.com * sent to main port (with id == 0) and processed in main thread. 7291547Smax.romanov@nginx.com */ 7301547Smax.romanov@nginx.com main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); 7311547Smax.romanov@nginx.com nxt_assert(main_app_port != NULL); 7321547Smax.romanov@nginx.com 7331547Smax.romanov@nginx.com app = main_app_port->app; 7341915Smax.romanov@nginx.com 7351915Smax.romanov@nginx.com if (nxt_fast_path(app != NULL)) { 7361915Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 737