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> 1720Sigor@sysoev.ru 1820Sigor@sysoev.ru 19115Sigor@sysoev.ru typedef struct { 20318Smax.romanov@nginx.com nxt_str_t type; 21507Smax.romanov@nginx.com uint32_t processes; 22507Smax.romanov@nginx.com uint32_t max_processes; 23507Smax.romanov@nginx.com uint32_t spare_processes; 24318Smax.romanov@nginx.com nxt_msec_t timeout; 25427Smax.romanov@nginx.com nxt_msec_t res_timeout; 26507Smax.romanov@nginx.com nxt_msec_t idle_timeout; 27318Smax.romanov@nginx.com uint32_t requests; 28318Smax.romanov@nginx.com nxt_conf_value_t *limits_value; 29507Smax.romanov@nginx.com nxt_conf_value_t *processes_value; 30133Sigor@sysoev.ru } nxt_router_app_conf_t; 31133Sigor@sysoev.ru 32133Sigor@sysoev.ru 33133Sigor@sysoev.ru typedef struct { 34964Sigor@sysoev.ru nxt_str_t pass; 35964Sigor@sysoev.ru nxt_str_t application; 36115Sigor@sysoev.ru } nxt_router_listener_conf_t; 37115Sigor@sysoev.ru 38115Sigor@sysoev.ru 39774Svbart@nginx.com #if (NXT_TLS) 40774Svbart@nginx.com 41774Svbart@nginx.com typedef struct { 42774Svbart@nginx.com nxt_str_t name; 43774Svbart@nginx.com nxt_socket_conf_t *conf; 44774Svbart@nginx.com 45774Svbart@nginx.com nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ 46774Svbart@nginx.com } nxt_router_tlssock_t; 47774Svbart@nginx.com 48774Svbart@nginx.com #endif 49774Svbart@nginx.com 50774Svbart@nginx.com 51423Smax.romanov@nginx.com typedef struct nxt_msg_info_s { 52423Smax.romanov@nginx.com nxt_buf_t *buf; 53423Smax.romanov@nginx.com nxt_port_mmap_tracking_t tracking; 54423Smax.romanov@nginx.com nxt_work_handler_t completion_handler; 55423Smax.romanov@nginx.com } nxt_msg_info_t; 56423Smax.romanov@nginx.com 57423Smax.romanov@nginx.com 58*1123Smax.romanov@nginx.com typedef struct nxt_request_app_link_s nxt_request_app_link_t; 59*1123Smax.romanov@nginx.com 60*1123Smax.romanov@nginx.com 61*1123Smax.romanov@nginx.com typedef enum { 62*1123Smax.romanov@nginx.com NXT_APR_NEW_PORT, 63*1123Smax.romanov@nginx.com NXT_APR_REQUEST_FAILED, 64*1123Smax.romanov@nginx.com NXT_APR_GOT_RESPONSE, 65*1123Smax.romanov@nginx.com NXT_APR_CLOSE, 66*1123Smax.romanov@nginx.com } nxt_apr_action_t; 67141Smax.romanov@nginx.com 68141Smax.romanov@nginx.com 69318Smax.romanov@nginx.com typedef struct { 70*1123Smax.romanov@nginx.com uint32_t stream; 71*1123Smax.romanov@nginx.com nxt_app_t *app; 72*1123Smax.romanov@nginx.com 73*1123Smax.romanov@nginx.com nxt_port_t *app_port; 74*1123Smax.romanov@nginx.com nxt_apr_action_t apr_action; 75*1123Smax.romanov@nginx.com 76*1123Smax.romanov@nginx.com nxt_http_request_t *request; 77*1123Smax.romanov@nginx.com nxt_msg_info_t msg_info; 78*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link; 79*1123Smax.romanov@nginx.com } nxt_request_rpc_data_t; 80*1123Smax.romanov@nginx.com 81*1123Smax.romanov@nginx.com 82*1123Smax.romanov@nginx.com struct nxt_request_app_link_s { 83*1123Smax.romanov@nginx.com uint32_t stream; 84*1123Smax.romanov@nginx.com nxt_atomic_t use_count; 85*1123Smax.romanov@nginx.com 86*1123Smax.romanov@nginx.com nxt_port_t *app_port; 87*1123Smax.romanov@nginx.com nxt_apr_action_t apr_action; 88*1123Smax.romanov@nginx.com 89*1123Smax.romanov@nginx.com nxt_port_t *reply_port; 90*1123Smax.romanov@nginx.com nxt_http_request_t *request; 91*1123Smax.romanov@nginx.com nxt_msg_info_t msg_info; 92*1123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data; 93*1123Smax.romanov@nginx.com 94*1123Smax.romanov@nginx.com nxt_nsec_t res_time; 95*1123Smax.romanov@nginx.com 96*1123Smax.romanov@nginx.com nxt_queue_link_t link_app_requests; /* for nxt_app_t.requests */ 97*1123Smax.romanov@nginx.com /* for nxt_port_t.pending_requests */ 98*1123Smax.romanov@nginx.com nxt_queue_link_t link_port_pending; 99*1123Smax.romanov@nginx.com nxt_queue_link_t link_app_pending; /* for nxt_app_t.pending */ 100*1123Smax.romanov@nginx.com 101*1123Smax.romanov@nginx.com nxt_mp_t *mem_pool; 102*1123Smax.romanov@nginx.com nxt_work_t work; 103*1123Smax.romanov@nginx.com 104*1123Smax.romanov@nginx.com int err_code; 105*1123Smax.romanov@nginx.com const char *err_str; 106167Smax.romanov@nginx.com }; 107167Smax.romanov@nginx.com 108167Smax.romanov@nginx.com 109198Sigor@sysoev.ru typedef struct { 110198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 111198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 112198Sigor@sysoev.ru } nxt_socket_rpc_t; 113198Sigor@sysoev.ru 114198Sigor@sysoev.ru 115507Smax.romanov@nginx.com typedef struct { 116507Smax.romanov@nginx.com nxt_app_t *app; 117507Smax.romanov@nginx.com nxt_router_temp_conf_t *temp_conf; 118507Smax.romanov@nginx.com } nxt_app_rpc_t; 119507Smax.romanov@nginx.com 120507Smax.romanov@nginx.com 121427Smax.romanov@nginx.com struct nxt_port_select_state_s { 122*1123Smax.romanov@nginx.com nxt_app_t *app; 123*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link; 124*1123Smax.romanov@nginx.com 125*1123Smax.romanov@nginx.com nxt_port_t *failed_port; 126*1123Smax.romanov@nginx.com int failed_port_use_delta; 127*1123Smax.romanov@nginx.com 128*1123Smax.romanov@nginx.com uint8_t start_process; /* 1 bit */ 129*1123Smax.romanov@nginx.com nxt_request_app_link_t *shared_ra; 130*1123Smax.romanov@nginx.com nxt_port_t *port; 131427Smax.romanov@nginx.com }; 132427Smax.romanov@nginx.com 133427Smax.romanov@nginx.com typedef struct nxt_port_select_state_s nxt_port_select_state_t; 134427Smax.romanov@nginx.com 135662Smax.romanov@nginx.com static void nxt_router_greet_controller(nxt_task_t *task, 136662Smax.romanov@nginx.com nxt_port_t *controller_port); 137662Smax.romanov@nginx.com 138427Smax.romanov@nginx.com static void nxt_router_port_select(nxt_task_t *task, 139427Smax.romanov@nginx.com nxt_port_select_state_t *state); 140427Smax.romanov@nginx.com 141427Smax.romanov@nginx.com static nxt_int_t nxt_router_port_post_select(nxt_task_t *task, 142427Smax.romanov@nginx.com nxt_port_select_state_t *state); 143427Smax.romanov@nginx.com 144507Smax.romanov@nginx.com static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); 145*1123Smax.romanov@nginx.com static void nxt_request_app_link_update_peer(nxt_task_t *task, 146*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link); 147*1123Smax.romanov@nginx.com 148343Smax.romanov@nginx.com 149425Smax.romanov@nginx.com nxt_inline void 150*1123Smax.romanov@nginx.com nxt_request_app_link_inc_use(nxt_request_app_link_t *req_app_link) 151425Smax.romanov@nginx.com { 152*1123Smax.romanov@nginx.com nxt_atomic_fetch_add(&req_app_link->use_count, 1); 153425Smax.romanov@nginx.com } 154425Smax.romanov@nginx.com 155425Smax.romanov@nginx.com nxt_inline void 156*1123Smax.romanov@nginx.com nxt_request_app_link_dec_use(nxt_request_app_link_t *req_app_link) 157425Smax.romanov@nginx.com { 158538Svbart@nginx.com #if (NXT_DEBUG) 159425Smax.romanov@nginx.com int c; 160425Smax.romanov@nginx.com 161*1123Smax.romanov@nginx.com c = nxt_atomic_fetch_add(&req_app_link->use_count, -1); 162425Smax.romanov@nginx.com 163425Smax.romanov@nginx.com nxt_assert(c > 1); 164538Svbart@nginx.com #else 165*1123Smax.romanov@nginx.com (void) nxt_atomic_fetch_add(&req_app_link->use_count, -1); 166538Svbart@nginx.com #endif 167425Smax.romanov@nginx.com } 168425Smax.romanov@nginx.com 169*1123Smax.romanov@nginx.com static void nxt_request_app_link_use(nxt_task_t *task, 170*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link, int i); 171425Smax.romanov@nginx.com 172139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 173198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 174198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 175139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 176139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 177139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 178139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 179193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 18053Sigor@sysoev.ru 181115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 182115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 183133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 184198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 185198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 186198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 187198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 188198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 189198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 190774Svbart@nginx.com #if (NXT_TLS) 191774Svbart@nginx.com static void nxt_router_tls_rpc_create(nxt_task_t *task, 192774Svbart@nginx.com nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls); 193774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task, 194774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 195774Svbart@nginx.com #endif 196507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task, 197507Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 198507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task, 199507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 200507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task, 201507Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 202359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 203359Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 204359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 205359Sigor@sysoev.ru nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 20653Sigor@sysoev.ru 20753Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 20853Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 20953Sigor@sysoev.ru const nxt_event_interface_t *interface); 210115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 211115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 212115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 213115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 214115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 215115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 216154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 217154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 218154Sigor@sysoev.ru nxt_work_handler_t handler); 219313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 220313Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 221139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 222139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 22353Sigor@sysoev.ru 22453Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 22553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 22653Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 22753Sigor@sysoev.ru nxt_event_engine_t *engine); 228343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 229133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 23053Sigor@sysoev.ru 231315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router, 232315Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 233315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine, 234315Sigor@sysoev.ru nxt_work_t *jobs); 23553Sigor@sysoev.ru 23653Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 23753Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 23853Sigor@sysoev.ru void *data); 23953Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 24053Sigor@sysoev.ru void *data); 24153Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 24253Sigor@sysoev.ru void *data); 243313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 244313Sigor@sysoev.ru void *data); 24553Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 24653Sigor@sysoev.ru void *data); 24753Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 24853Sigor@sysoev.ru void *data); 249359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 250359Sigor@sysoev.ru nxt_socket_conf_t *skcf); 25153Sigor@sysoev.ru 252630Svbart@nginx.com static void nxt_router_access_log_writer(nxt_task_t *task, 253630Svbart@nginx.com nxt_http_request_t *r, nxt_router_access_log_t *access_log); 254630Svbart@nginx.com static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 255630Svbart@nginx.com struct tm *tm, size_t size, const char *format); 256630Svbart@nginx.com static void nxt_router_access_log_open(nxt_task_t *task, 257630Svbart@nginx.com nxt_router_temp_conf_t *tmcf); 258630Svbart@nginx.com static void nxt_router_access_log_ready(nxt_task_t *task, 259630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 260630Svbart@nginx.com static void nxt_router_access_log_error(nxt_task_t *task, 261630Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 262630Svbart@nginx.com static void nxt_router_access_log_release(nxt_task_t *task, 263630Svbart@nginx.com nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 264651Svbart@nginx.com static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 265651Svbart@nginx.com void *data); 266631Svbart@nginx.com static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 267631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 268631Svbart@nginx.com static void nxt_router_access_log_reopen_error(nxt_task_t *task, 269631Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 270630Svbart@nginx.com 271343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task, 272343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 273343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task, 274343Smax.romanov@nginx.com nxt_port_recv_msg_t *msg, void *data); 275343Smax.romanov@nginx.com 276753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 277*1123Smax.romanov@nginx.com 278343Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 279*1123Smax.romanov@nginx.com nxt_apr_action_t action); 280427Smax.romanov@nginx.com static nxt_int_t nxt_router_app_port(nxt_task_t *task, nxt_app_t *app, 281*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link); 282141Smax.romanov@nginx.com 283425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task, 284*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link); 2851007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 2861007Salexander.borisov@nginx.com nxt_http_request_t *r, nxt_port_t *port, const nxt_str_t *prefix); 287510Salexander.borisov@nginx.com 288318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 289507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 290507Smax.romanov@nginx.com void *data); 291507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 292507Smax.romanov@nginx.com void *data); 293753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 294507Smax.romanov@nginx.com void *data); 295753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 296431Sigor@sysoev.ru 297431Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_request_send_state; 298431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 299141Smax.romanov@nginx.com 300753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task, 301753Smax.romanov@nginx.com nxt_app_joint_t *app_joint, int i); 302753Smax.romanov@nginx.com 3031007Salexander.borisov@nginx.com static nxt_int_t nxt_router_http_request_done(nxt_task_t *task, 3041007Salexander.borisov@nginx.com nxt_http_request_t *r); 3051007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 3061007Salexander.borisov@nginx.com void *data); 3071007Salexander.borisov@nginx.com 308119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 30920Sigor@sysoev.ru 310743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_"); 311743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string(""); 312743Smax.romanov@nginx.com 313743Smax.romanov@nginx.com static const nxt_str_t *nxt_app_msg_prefix[] = { 314804Svbart@nginx.com &empty_prefix, 315743Smax.romanov@nginx.com &http_prefix, 316743Smax.romanov@nginx.com &http_prefix, 317743Smax.romanov@nginx.com &http_prefix, 318743Smax.romanov@nginx.com &http_prefix, 319977Smax.romanov@gmail.com &empty_prefix, 320216Sigor@sysoev.ru }; 321216Sigor@sysoev.ru 322216Sigor@sysoev.ru 323662Smax.romanov@nginx.com nxt_port_handlers_t nxt_router_process_port_handlers = { 324662Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 325662Smax.romanov@nginx.com .new_port = nxt_router_new_port_handler, 326662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 327662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 328662Smax.romanov@nginx.com .data = nxt_router_conf_data_handler, 329662Smax.romanov@nginx.com .remove_pid = nxt_router_remove_pid_handler, 330662Smax.romanov@nginx.com .access_log = nxt_router_access_log_reopen_handler, 331662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 332662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 333662Smax.romanov@nginx.com }; 334662Smax.romanov@nginx.com 335662Smax.romanov@nginx.com 33620Sigor@sysoev.ru nxt_int_t 337141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 33820Sigor@sysoev.ru { 339141Smax.romanov@nginx.com nxt_int_t ret; 340662Smax.romanov@nginx.com nxt_port_t *controller_port; 341141Smax.romanov@nginx.com nxt_router_t *router; 342141Smax.romanov@nginx.com nxt_runtime_t *rt; 343141Smax.romanov@nginx.com 344141Smax.romanov@nginx.com rt = task->thread->runtime; 34553Sigor@sysoev.ru 346771Sigor@sysoev.ru #if (NXT_TLS) 347771Sigor@sysoev.ru rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 348771Sigor@sysoev.ru if (nxt_slow_path(rt->tls == NULL)) { 349771Sigor@sysoev.ru return NXT_ERROR; 350771Sigor@sysoev.ru } 351771Sigor@sysoev.ru 352771Sigor@sysoev.ru ret = rt->tls->library_init(task); 353771Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 354771Sigor@sysoev.ru return ret; 355771Sigor@sysoev.ru } 356771Sigor@sysoev.ru #endif 357771Sigor@sysoev.ru 358431Sigor@sysoev.ru ret = nxt_http_init(task, rt); 35988Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 36088Smax.romanov@nginx.com return ret; 36188Smax.romanov@nginx.com } 36288Smax.romanov@nginx.com 36353Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 36453Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 36553Sigor@sysoev.ru return NXT_ERROR; 36653Sigor@sysoev.ru } 36753Sigor@sysoev.ru 36853Sigor@sysoev.ru nxt_queue_init(&router->engines); 36953Sigor@sysoev.ru nxt_queue_init(&router->sockets); 370133Sigor@sysoev.ru nxt_queue_init(&router->apps); 37153Sigor@sysoev.ru 372119Smax.romanov@nginx.com nxt_router = router; 373119Smax.romanov@nginx.com 374662Smax.romanov@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 375662Smax.romanov@nginx.com if (controller_port != NULL) { 376662Smax.romanov@nginx.com nxt_router_greet_controller(task, controller_port); 377662Smax.romanov@nginx.com } 378662Smax.romanov@nginx.com 379115Sigor@sysoev.ru return NXT_OK; 380115Sigor@sysoev.ru } 381115Sigor@sysoev.ru 382115Sigor@sysoev.ru 383343Smax.romanov@nginx.com static void 384662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 385662Smax.romanov@nginx.com { 386662Smax.romanov@nginx.com nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 387662Smax.romanov@nginx.com -1, 0, 0, NULL); 388662Smax.romanov@nginx.com } 389662Smax.romanov@nginx.com 390662Smax.romanov@nginx.com 391662Smax.romanov@nginx.com static void 392507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 393507Smax.romanov@nginx.com void *data) 394167Smax.romanov@nginx.com { 395343Smax.romanov@nginx.com size_t size; 396343Smax.romanov@nginx.com uint32_t stream; 397430Sigor@sysoev.ru nxt_mp_t *mp; 398648Svbart@nginx.com nxt_int_t ret; 399343Smax.romanov@nginx.com nxt_app_t *app; 400343Smax.romanov@nginx.com nxt_buf_t *b; 401343Smax.romanov@nginx.com nxt_port_t *main_port; 402343Smax.romanov@nginx.com nxt_runtime_t *rt; 403343Smax.romanov@nginx.com 404343Smax.romanov@nginx.com app = data; 405167Smax.romanov@nginx.com 406167Smax.romanov@nginx.com rt = task->thread->runtime; 407240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 408167Smax.romanov@nginx.com 409507Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p start process", &app->name, app); 410343Smax.romanov@nginx.com 411343Smax.romanov@nginx.com size = app->name.length + 1 + app->conf.length; 412343Smax.romanov@nginx.com 413343Smax.romanov@nginx.com b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size); 414343Smax.romanov@nginx.com 415343Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 416343Smax.romanov@nginx.com goto failed; 417167Smax.romanov@nginx.com } 418167Smax.romanov@nginx.com 419343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->name); 420343Smax.romanov@nginx.com *b->mem.free++ = '\0'; 421343Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 422343Smax.romanov@nginx.com 423753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, 1); 424753Smax.romanov@nginx.com 425343Smax.romanov@nginx.com stream = nxt_port_rpc_register_handler(task, port, 426343Smax.romanov@nginx.com nxt_router_app_port_ready, 427343Smax.romanov@nginx.com nxt_router_app_port_error, 428753Smax.romanov@nginx.com -1, app->joint); 429343Smax.romanov@nginx.com 430343Smax.romanov@nginx.com if (nxt_slow_path(stream == 0)) { 431753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, -1); 432753Smax.romanov@nginx.com 433343Smax.romanov@nginx.com goto failed; 434343Smax.romanov@nginx.com } 435343Smax.romanov@nginx.com 436648Svbart@nginx.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1, 437648Svbart@nginx.com stream, port->id, b); 438648Svbart@nginx.com 439648Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 440648Svbart@nginx.com nxt_port_rpc_cancel(task, port, stream); 441753Smax.romanov@nginx.com 442753Smax.romanov@nginx.com nxt_router_app_joint_use(task, app->joint, -1); 443753Smax.romanov@nginx.com 444648Svbart@nginx.com goto failed; 445648Svbart@nginx.com } 446343Smax.romanov@nginx.com 447753Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 448753Smax.romanov@nginx.com 449343Smax.romanov@nginx.com return; 450343Smax.romanov@nginx.com 451343Smax.romanov@nginx.com failed: 452343Smax.romanov@nginx.com 453648Svbart@nginx.com if (b != NULL) { 454648Svbart@nginx.com mp = b->data; 455648Svbart@nginx.com nxt_mp_free(mp, b); 456648Svbart@nginx.com nxt_mp_release(mp); 457648Svbart@nginx.com } 458648Svbart@nginx.com 459343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 460343Smax.romanov@nginx.com 461507Smax.romanov@nginx.com app->pending_processes--; 462343Smax.romanov@nginx.com 463343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 464343Smax.romanov@nginx.com 465343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 466167Smax.romanov@nginx.com } 467167Smax.romanov@nginx.com 468167Smax.romanov@nginx.com 469753Smax.romanov@nginx.com static void 470753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 471753Smax.romanov@nginx.com { 472753Smax.romanov@nginx.com app_joint->use_count += i; 473753Smax.romanov@nginx.com 474753Smax.romanov@nginx.com if (app_joint->use_count == 0) { 475753Smax.romanov@nginx.com nxt_assert(app_joint->app == NULL); 476753Smax.romanov@nginx.com 477753Smax.romanov@nginx.com nxt_free(app_joint); 478753Smax.romanov@nginx.com } 479753Smax.romanov@nginx.com } 480753Smax.romanov@nginx.com 481753Smax.romanov@nginx.com 482343Smax.romanov@nginx.com static nxt_int_t 483507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 484141Smax.romanov@nginx.com { 485343Smax.romanov@nginx.com nxt_int_t res; 486343Smax.romanov@nginx.com nxt_port_t *router_port; 487343Smax.romanov@nginx.com nxt_runtime_t *rt; 488343Smax.romanov@nginx.com 489343Smax.romanov@nginx.com rt = task->thread->runtime; 490343Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 491343Smax.romanov@nginx.com 492343Smax.romanov@nginx.com nxt_router_app_use(task, app, 1); 493343Smax.romanov@nginx.com 494507Smax.romanov@nginx.com res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 495343Smax.romanov@nginx.com app); 496343Smax.romanov@nginx.com 497343Smax.romanov@nginx.com if (res == NXT_OK) { 498343Smax.romanov@nginx.com return res; 499318Smax.romanov@nginx.com } 500318Smax.romanov@nginx.com 501343Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 502343Smax.romanov@nginx.com 503507Smax.romanov@nginx.com app->pending_processes--; 504343Smax.romanov@nginx.com 505343Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 506343Smax.romanov@nginx.com 507343Smax.romanov@nginx.com nxt_router_app_use(task, app, -1); 508343Smax.romanov@nginx.com 509343Smax.romanov@nginx.com return NXT_ERROR; 510318Smax.romanov@nginx.com } 511318Smax.romanov@nginx.com 512318Smax.romanov@nginx.com 513351Smax.romanov@nginx.com nxt_inline void 514*1123Smax.romanov@nginx.com nxt_request_app_link_init(nxt_task_t *task, 515*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link, nxt_request_rpc_data_t *req_rpc_data) 516167Smax.romanov@nginx.com { 517318Smax.romanov@nginx.com nxt_event_engine_t *engine; 518351Smax.romanov@nginx.com 519318Smax.romanov@nginx.com engine = task->thread->engine; 520167Smax.romanov@nginx.com 521*1123Smax.romanov@nginx.com nxt_memzero(req_app_link, sizeof(nxt_request_app_link_t)); 522*1123Smax.romanov@nginx.com 523*1123Smax.romanov@nginx.com req_app_link->stream = req_rpc_data->stream; 524*1123Smax.romanov@nginx.com req_app_link->use_count = 1; 525*1123Smax.romanov@nginx.com req_app_link->req_rpc_data = req_rpc_data; 526*1123Smax.romanov@nginx.com req_rpc_data->req_app_link = req_app_link; 527*1123Smax.romanov@nginx.com req_app_link->reply_port = engine->port; 528*1123Smax.romanov@nginx.com req_app_link->request = req_rpc_data->request; 529*1123Smax.romanov@nginx.com req_app_link->apr_action = NXT_APR_GOT_RESPONSE; 530*1123Smax.romanov@nginx.com 531*1123Smax.romanov@nginx.com req_app_link->work.handler = NULL; 532*1123Smax.romanov@nginx.com req_app_link->work.task = &engine->task; 533*1123Smax.romanov@nginx.com req_app_link->work.obj = req_app_link; 534*1123Smax.romanov@nginx.com req_app_link->work.data = engine; 535351Smax.romanov@nginx.com } 536351Smax.romanov@nginx.com 537351Smax.romanov@nginx.com 538*1123Smax.romanov@nginx.com nxt_inline nxt_request_app_link_t * 539*1123Smax.romanov@nginx.com nxt_request_app_link_alloc(nxt_task_t *task, 540*1123Smax.romanov@nginx.com nxt_request_app_link_t *ra_src, nxt_request_rpc_data_t *req_rpc_data) 541351Smax.romanov@nginx.com { 542*1123Smax.romanov@nginx.com nxt_mp_t *mp; 543*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link; 544*1123Smax.romanov@nginx.com 545*1123Smax.romanov@nginx.com if (ra_src != NULL && ra_src->mem_pool != NULL) { 546425Smax.romanov@nginx.com return ra_src; 547425Smax.romanov@nginx.com } 548425Smax.romanov@nginx.com 549*1123Smax.romanov@nginx.com mp = req_rpc_data->request->mem_pool; 550*1123Smax.romanov@nginx.com 551*1123Smax.romanov@nginx.com req_app_link = nxt_mp_alloc(mp, sizeof(nxt_request_app_link_t)); 552*1123Smax.romanov@nginx.com 553*1123Smax.romanov@nginx.com if (nxt_slow_path(req_app_link == NULL)) { 554*1123Smax.romanov@nginx.com 555*1123Smax.romanov@nginx.com req_rpc_data->req_app_link = NULL; 556*1123Smax.romanov@nginx.com 557*1123Smax.romanov@nginx.com if (ra_src != NULL) { 558*1123Smax.romanov@nginx.com ra_src->req_rpc_data = NULL; 559*1123Smax.romanov@nginx.com } 560351Smax.romanov@nginx.com 561351Smax.romanov@nginx.com return NULL; 562351Smax.romanov@nginx.com } 563351Smax.romanov@nginx.com 564430Sigor@sysoev.ru nxt_mp_retain(mp); 565430Sigor@sysoev.ru 566*1123Smax.romanov@nginx.com nxt_request_app_link_init(task, req_app_link, req_rpc_data); 567*1123Smax.romanov@nginx.com 568*1123Smax.romanov@nginx.com req_app_link->mem_pool = mp; 569*1123Smax.romanov@nginx.com 570*1123Smax.romanov@nginx.com return req_app_link; 571167Smax.romanov@nginx.com } 572167Smax.romanov@nginx.com 573167Smax.romanov@nginx.com 574423Smax.romanov@nginx.com nxt_inline nxt_bool_t 575423Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_msg_info_t *msg_info, 576423Smax.romanov@nginx.com uint32_t stream) 577423Smax.romanov@nginx.com { 578423Smax.romanov@nginx.com nxt_buf_t *b, *next; 579423Smax.romanov@nginx.com nxt_bool_t cancelled; 580423Smax.romanov@nginx.com 581423Smax.romanov@nginx.com if (msg_info->buf == NULL) { 582423Smax.romanov@nginx.com return 0; 583423Smax.romanov@nginx.com } 584423Smax.romanov@nginx.com 585423Smax.romanov@nginx.com cancelled = nxt_port_mmap_tracking_cancel(task, &msg_info->tracking, 586423Smax.romanov@nginx.com stream); 587423Smax.romanov@nginx.com 588423Smax.romanov@nginx.com if (cancelled) { 589423Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: cancelled by router", stream); 590423Smax.romanov@nginx.com } 591423Smax.romanov@nginx.com 592423Smax.romanov@nginx.com for (b = msg_info->buf; b != NULL; b = next) { 593423Smax.romanov@nginx.com next = b->next; 594423Smax.romanov@nginx.com 595423Smax.romanov@nginx.com b->completion_handler = msg_info->completion_handler; 596423Smax.romanov@nginx.com 597423Smax.romanov@nginx.com if (b->is_port_mmap_sent) { 598423Smax.romanov@nginx.com b->is_port_mmap_sent = cancelled == 0; 599423Smax.romanov@nginx.com b->completion_handler(task, b, b->parent); 600423Smax.romanov@nginx.com } 601423Smax.romanov@nginx.com } 602423Smax.romanov@nginx.com 603423Smax.romanov@nginx.com msg_info->buf = NULL; 604423Smax.romanov@nginx.com 605423Smax.romanov@nginx.com return cancelled; 606423Smax.romanov@nginx.com } 607423Smax.romanov@nginx.com 608423Smax.romanov@nginx.com 609167Smax.romanov@nginx.com static void 610*1123Smax.romanov@nginx.com nxt_request_app_link_update_peer_handler(nxt_task_t *task, void *obj, 611*1123Smax.romanov@nginx.com void *data) 612*1123Smax.romanov@nginx.com { 613*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link; 614*1123Smax.romanov@nginx.com 615*1123Smax.romanov@nginx.com req_app_link = obj; 616*1123Smax.romanov@nginx.com 617*1123Smax.romanov@nginx.com nxt_request_app_link_update_peer(task, req_app_link); 618*1123Smax.romanov@nginx.com 619*1123Smax.romanov@nginx.com nxt_request_app_link_use(task, req_app_link, -1); 620*1123Smax.romanov@nginx.com } 621425Smax.romanov@nginx.com 622425Smax.romanov@nginx.com 623425Smax.romanov@nginx.com static void 624*1123Smax.romanov@nginx.com nxt_request_app_link_update_peer(nxt_task_t *task, 625*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link) 626167Smax.romanov@nginx.com { 627*1123Smax.romanov@nginx.com nxt_event_engine_t *engine; 628*1123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data; 629*1123Smax.romanov@nginx.com 630*1123Smax.romanov@nginx.com engine = req_app_link->work.data; 631*1123Smax.romanov@nginx.com 632*1123Smax.romanov@nginx.com if (task->thread->engine != engine) { 633*1123Smax.romanov@nginx.com nxt_request_app_link_inc_use(req_app_link); 634*1123Smax.romanov@nginx.com 635*1123Smax.romanov@nginx.com req_app_link->work.handler = nxt_request_app_link_update_peer_handler; 636*1123Smax.romanov@nginx.com req_app_link->work.task = &engine->task; 637*1123Smax.romanov@nginx.com req_app_link->work.next = NULL; 638*1123Smax.romanov@nginx.com 639*1123Smax.romanov@nginx.com nxt_debug(task, "req_app_link stream #%uD post update peer to %p", 640*1123Smax.romanov@nginx.com req_app_link->stream, engine); 641*1123Smax.romanov@nginx.com 642*1123Smax.romanov@nginx.com nxt_event_engine_post(engine, &req_app_link->work); 643*1123Smax.romanov@nginx.com 644*1123Smax.romanov@nginx.com return; 645*1123Smax.romanov@nginx.com } 646*1123Smax.romanov@nginx.com 647*1123Smax.romanov@nginx.com nxt_debug(task, "req_app_link stream #%uD update peer", 648*1123Smax.romanov@nginx.com req_app_link->stream); 649*1123Smax.romanov@nginx.com 650*1123Smax.romanov@nginx.com req_rpc_data = req_app_link->req_rpc_data; 651*1123Smax.romanov@nginx.com 652*1123Smax.romanov@nginx.com if (req_rpc_data != NULL && req_app_link->app_port != NULL) { 653*1123Smax.romanov@nginx.com nxt_port_rpc_ex_set_peer(task, engine->port, req_rpc_data, 654*1123Smax.romanov@nginx.com req_app_link->app_port->pid); 655*1123Smax.romanov@nginx.com } 656*1123Smax.romanov@nginx.com 657*1123Smax.romanov@nginx.com nxt_request_app_link_use(task, req_app_link, -1); 658425Smax.romanov@nginx.com } 659425Smax.romanov@nginx.com 660425Smax.romanov@nginx.com 661425Smax.romanov@nginx.com static void 662*1123Smax.romanov@nginx.com nxt_request_app_link_release(nxt_task_t *task, 663*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link) 664425Smax.romanov@nginx.com { 665431Sigor@sysoev.ru nxt_mp_t *mp; 666*1123Smax.romanov@nginx.com nxt_request_rpc_data_t *req_rpc_data; 667*1123Smax.romanov@nginx.com 668*1123Smax.romanov@nginx.com nxt_assert(task->thread->engine == req_app_link->work.data); 669*1123Smax.romanov@nginx.com nxt_assert(req_app_link->use_count == 0); 670*1123Smax.romanov@nginx.com 671*1123Smax.romanov@nginx.com nxt_debug(task, "req_app_link stream #%uD release", req_app_link->stream); 672*1123Smax.romanov@nginx.com 673*1123Smax.romanov@nginx.com req_rpc_data = req_app_link->req_rpc_data; 674*1123Smax.romanov@nginx.com 675*1123Smax.romanov@nginx.com if (req_rpc_data != NULL) { 676*1123Smax.romanov@nginx.com if (nxt_slow_path(req_app_link->err_code != 0)) { 677*1123Smax.romanov@nginx.com nxt_http_request_error(task, req_rpc_data->request, 678*1123Smax.romanov@nginx.com req_app_link->err_code); 679423Smax.romanov@nginx.com 680423Smax.romanov@nginx.com } else { 681*1123Smax.romanov@nginx.com req_rpc_data->app_port = req_app_link->app_port; 682*1123Smax.romanov@nginx.com req_rpc_data->apr_action = req_app_link->apr_action; 683*1123Smax.romanov@nginx.com req_rpc_data->msg_info = req_app_link->msg_info; 684*1123Smax.romanov@nginx.com 685*1123Smax.romanov@nginx.com if (req_rpc_data->app->timeout != 0) { 686*1123Smax.romanov@nginx.com req_rpc_data->request->timer.handler = nxt_router_app_timeout; 687*1123Smax.romanov@nginx.com req_rpc_data->request->timer_data = req_rpc_data; 688*1123Smax.romanov@nginx.com nxt_timer_add(task->thread->engine, 689*1123Smax.romanov@nginx.com &req_rpc_data->request->timer, 690*1123Smax.romanov@nginx.com req_rpc_data->app->timeout); 691425Smax.romanov@nginx.com } 692425Smax.romanov@nginx.com 693*1123Smax.romanov@nginx.com req_app_link->app_port = NULL; 694*1123Smax.romanov@nginx.com req_app_link->msg_info.buf = NULL; 695423Smax.romanov@nginx.com } 696343Smax.romanov@nginx.com 697*1123Smax.romanov@nginx.com req_rpc_data->req_app_link = NULL; 698*1123Smax.romanov@nginx.com req_app_link->req_rpc_data = NULL; 699*1123Smax.romanov@nginx.com } 700*1123Smax.romanov@nginx.com 701*1123Smax.romanov@nginx.com if (req_app_link->app_port != NULL) { 702*1123Smax.romanov@nginx.com nxt_router_app_port_release(task, req_app_link->app_port, 703*1123Smax.romanov@nginx.com req_app_link->apr_action); 704*1123Smax.romanov@nginx.com 705*1123Smax.romanov@nginx.com req_app_link->app_port = NULL; 706*1123Smax.romanov@nginx.com } 707*1123Smax.romanov@nginx.com 708*1123Smax.romanov@nginx.com nxt_router_msg_cancel(task, &req_app_link->msg_info, req_app_link->stream); 709*1123Smax.romanov@nginx.com 710*1123Smax.romanov@nginx.com mp = req_app_link->mem_pool; 711430Sigor@sysoev.ru 712430Sigor@sysoev.ru if (mp != NULL) { 713*1123Smax.romanov@nginx.com nxt_mp_free(mp, req_app_link); 714430Sigor@sysoev.ru nxt_mp_release(mp); 715351Smax.romanov@nginx.com } 716167Smax.romanov@nginx.com } 717167Smax.romanov@nginx.com 718167Smax.romanov@nginx.com 719425Smax.romanov@nginx.com static void 720*1123Smax.romanov@nginx.com nxt_request_app_link_release_handler(nxt_task_t *task, void *obj, void *data) 721425Smax.romanov@nginx.com { 722*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link; 723*1123Smax.romanov@nginx.com 724*1123Smax.romanov@nginx.com req_app_link = obj; 725*1123Smax.romanov@nginx.com 726*1123Smax.romanov@nginx.com nxt_assert(req_app_link->work.data == data); 727*1123Smax.romanov@nginx.com 728*1123Smax.romanov@nginx.com nxt_atomic_fetch_add(&req_app_link->use_count, -1); 729*1123Smax.romanov@nginx.com 730*1123Smax.romanov@nginx.com nxt_request_app_link_release(task, req_app_link); 731425Smax.romanov@nginx.com } 732425Smax.romanov@nginx.com 733425Smax.romanov@nginx.com 734425Smax.romanov@nginx.com static void 735*1123Smax.romanov@nginx.com nxt_request_app_link_use(nxt_task_t *task, nxt_request_app_link_t *req_app_link, 736*1123Smax.romanov@nginx.com int i) 737425Smax.romanov@nginx.com { 738425Smax.romanov@nginx.com int c; 739425Smax.romanov@nginx.com nxt_event_engine_t *engine; 740425Smax.romanov@nginx.com 741*1123Smax.romanov@nginx.com c = nxt_atomic_fetch_add(&req_app_link->use_count, i); 742425Smax.romanov@nginx.com 743425Smax.romanov@nginx.com if (i < 0 && c == -i) { 744*1123Smax.romanov@nginx.com engine = req_app_link->work.data; 745425Smax.romanov@nginx.com 746425Smax.romanov@nginx.com if (task->thread->engine == engine) { 747*1123Smax.romanov@nginx.com nxt_request_app_link_release(task, req_app_link); 748425Smax.romanov@nginx.com 749425Smax.romanov@nginx.com return; 750425Smax.romanov@nginx.com } 751425Smax.romanov@nginx.com 752*1123Smax.romanov@nginx.com nxt_request_app_link_inc_use(req_app_link); 753*1123Smax.romanov@nginx.com 754*1123Smax.romanov@nginx.com req_app_link->work.handler = nxt_request_app_link_release_handler; 755*1123Smax.romanov@nginx.com req_app_link->work.task = &engine->task; 756*1123Smax.romanov@nginx.com req_app_link->work.next = NULL; 757*1123Smax.romanov@nginx.com 758*1123Smax.romanov@nginx.com nxt_debug(task, "req_app_link stream #%uD post release to %p", 759*1123Smax.romanov@nginx.com req_app_link->stream, engine); 760*1123Smax.romanov@nginx.com 761*1123Smax.romanov@nginx.com nxt_event_engine_post(engine, &req_app_link->work); 762425Smax.romanov@nginx.com } 763425Smax.romanov@nginx.com } 764425Smax.romanov@nginx.com 765425Smax.romanov@nginx.com 766423Smax.romanov@nginx.com nxt_inline void 767*1123Smax.romanov@nginx.com nxt_request_app_link_error(nxt_request_app_link_t *req_app_link, int code, 768*1123Smax.romanov@nginx.com const char *str) 769345Smax.romanov@nginx.com { 770*1123Smax.romanov@nginx.com req_app_link->app_port = NULL; 771*1123Smax.romanov@nginx.com req_app_link->err_code = code; 772*1123Smax.romanov@nginx.com req_app_link->err_str = str; 773345Smax.romanov@nginx.com } 774345Smax.romanov@nginx.com 775345Smax.romanov@nginx.com 776427Smax.romanov@nginx.com nxt_inline void 777*1123Smax.romanov@nginx.com nxt_request_app_link_pending(nxt_task_t *task, nxt_app_t *app, 778*1123Smax.romanov@nginx.com nxt_request_app_link_t *req_app_link) 779427Smax.romanov@nginx.com { 780*1123Smax.romanov@nginx.com nxt_queue_insert_tail(&req_app_link->app_port->pending_requests, 781*1123Smax.romanov@nginx.com &req_app_link->link_port_pending); 782*1123Smax.romanov@nginx.com nxt_queue_insert_tail(&app->pending, &req_app_link->link_app_pending); 783*1123Smax.romanov@nginx.com 784