1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) Valentin V. Bartenev 5 * Copyright (C) NGINX, Inc. 6 */ 7 8#include <nxt_router.h> 9#include <nxt_conf.h> 10#if (NXT_TLS) 11#include <nxt_cert.h> 12#endif 13#include <nxt_http.h> 14#include <nxt_port_memory_int.h> 15#include <nxt_unit_request.h> 16#include <nxt_unit_response.h> 17#include <nxt_router_request.h> 18#include <nxt_app_queue.h> 19#include <nxt_port_queue.h> 20
| 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) Valentin V. Bartenev 5 * Copyright (C) NGINX, Inc. 6 */ 7 8#include <nxt_router.h> 9#include <nxt_conf.h> 10#if (NXT_TLS) 11#include <nxt_cert.h> 12#endif 13#include <nxt_http.h> 14#include <nxt_port_memory_int.h> 15#include <nxt_unit_request.h> 16#include <nxt_unit_response.h> 17#include <nxt_router_request.h> 18#include <nxt_app_queue.h> 19#include <nxt_port_queue.h> 20
|
| 21#define NXT_SHARED_PORT_ID 0xFFFFu 22
|
21typedef struct { 22 nxt_str_t type; 23 uint32_t processes; 24 uint32_t max_processes; 25 uint32_t spare_processes; 26 nxt_msec_t timeout; 27 nxt_msec_t idle_timeout; 28 uint32_t requests; 29 nxt_conf_value_t *limits_value; 30 nxt_conf_value_t *processes_value; 31 nxt_conf_value_t *targets_value; 32} nxt_router_app_conf_t; 33 34 35typedef struct { 36 nxt_str_t pass; 37 nxt_str_t application; 38} nxt_router_listener_conf_t; 39 40 41#if (NXT_TLS) 42 43typedef struct { 44 nxt_str_t name; 45 nxt_socket_conf_t *socket_conf; 46 nxt_router_temp_conf_t *temp_conf; 47 nxt_tls_init_t *tls_init; 48 nxt_bool_t last; 49 50 nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ 51} nxt_router_tlssock_t; 52 53#endif 54 55 56typedef struct { 57 nxt_str_t *name; 58 nxt_socket_conf_t *socket_conf; 59 nxt_router_temp_conf_t *temp_conf; 60 nxt_bool_t last; 61} nxt_socket_rpc_t; 62 63 64typedef struct { 65 nxt_app_t *app; 66 nxt_router_temp_conf_t *temp_conf; 67} nxt_app_rpc_t; 68 69
| 23typedef struct { 24 nxt_str_t type; 25 uint32_t processes; 26 uint32_t max_processes; 27 uint32_t spare_processes; 28 nxt_msec_t timeout; 29 nxt_msec_t idle_timeout; 30 uint32_t requests; 31 nxt_conf_value_t *limits_value; 32 nxt_conf_value_t *processes_value; 33 nxt_conf_value_t *targets_value; 34} nxt_router_app_conf_t; 35 36 37typedef struct { 38 nxt_str_t pass; 39 nxt_str_t application; 40} nxt_router_listener_conf_t; 41 42 43#if (NXT_TLS) 44 45typedef struct { 46 nxt_str_t name; 47 nxt_socket_conf_t *socket_conf; 48 nxt_router_temp_conf_t *temp_conf; 49 nxt_tls_init_t *tls_init; 50 nxt_bool_t last; 51 52 nxt_queue_link_t link; /* for nxt_socket_conf_t.tls */ 53} nxt_router_tlssock_t; 54 55#endif 56 57 58typedef struct { 59 nxt_str_t *name; 60 nxt_socket_conf_t *socket_conf; 61 nxt_router_temp_conf_t *temp_conf; 62 nxt_bool_t last; 63} nxt_socket_rpc_t; 64 65 66typedef struct { 67 nxt_app_t *app; 68 nxt_router_temp_conf_t *temp_conf; 69} nxt_app_rpc_t; 70 71
|
| 72typedef struct { 73 nxt_app_joint_t *app_joint; 74 uint32_t generation; 75} nxt_app_joint_rpc_t; 76 77
|
70static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, 71 nxt_mp_t *mp); 72static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data); 73static void nxt_router_greet_controller(nxt_task_t *task, 74 nxt_port_t *controller_port); 75 76static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); 77 78static void nxt_router_new_port_handler(nxt_task_t *task, 79 nxt_port_recv_msg_t *msg); 80static void nxt_router_conf_data_handler(nxt_task_t *task, 81 nxt_port_recv_msg_t *msg);
| 78static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, 79 nxt_mp_t *mp); 80static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data); 81static void nxt_router_greet_controller(nxt_task_t *task, 82 nxt_port_t *controller_port); 83 84static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app); 85 86static void nxt_router_new_port_handler(nxt_task_t *task, 87 nxt_port_recv_msg_t *msg); 88static void nxt_router_conf_data_handler(nxt_task_t *task, 89 nxt_port_recv_msg_t *msg);
|
| 90static void nxt_router_app_restart_handler(nxt_task_t *task, 91 nxt_port_recv_msg_t *msg);
|
82static void nxt_router_remove_pid_handler(nxt_task_t *task, 83 nxt_port_recv_msg_t *msg); 84static void nxt_router_access_log_reopen_handler(nxt_task_t *task, 85 nxt_port_recv_msg_t *msg); 86 87static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 88static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 89static void nxt_router_conf_ready(nxt_task_t *task, 90 nxt_router_temp_conf_t *tmcf); 91static void nxt_router_conf_error(nxt_task_t *task, 92 nxt_router_temp_conf_t *tmcf); 93static void nxt_router_conf_send(nxt_task_t *task, 94 nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 95 96static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 97 nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 98static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, 99 nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); 100 101static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 102static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 103static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, 104 nxt_app_t *app); 105static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, 106 nxt_str_t *name); 107static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, 108 int i); 109 110static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, 111 nxt_port_t *port); 112static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, 113 nxt_port_t *port); 114static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, 115 nxt_port_t *port, nxt_fd_t fd); 116static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 117 nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 118static void nxt_router_listen_socket_ready(nxt_task_t *task, 119 nxt_port_recv_msg_t *msg, void *data); 120static void nxt_router_listen_socket_error(nxt_task_t *task, 121 nxt_port_recv_msg_t *msg, void *data); 122#if (NXT_TLS) 123static void nxt_router_tls_rpc_handler(nxt_task_t *task, 124 nxt_port_recv_msg_t *msg, void *data); 125static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 126 nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init, 127 nxt_bool_t last); 128#endif 129static void nxt_router_app_rpc_create(nxt_task_t *task, 130 nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 131static void nxt_router_app_prefork_ready(nxt_task_t *task, 132 nxt_port_recv_msg_t *msg, void *data); 133static void nxt_router_app_prefork_error(nxt_task_t *task, 134 nxt_port_recv_msg_t *msg, void *data); 135static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 136 nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 137static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 138 nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 139 140static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 141 nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 142 const nxt_event_interface_t *interface); 143static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 144 nxt_router_engine_conf_t *recf); 145static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 146 nxt_router_engine_conf_t *recf); 147static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 148 nxt_router_engine_conf_t *recf); 149static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 150 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 151 nxt_work_handler_t handler); 152static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 153 nxt_router_engine_conf_t *recf); 154static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 155 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 156 157static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 158 nxt_router_temp_conf_t *tmcf); 159static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 160 nxt_event_engine_t *engine); 161static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 162 nxt_router_temp_conf_t *tmcf); 163 164static void nxt_router_engines_post(nxt_router_t *router, 165 nxt_router_temp_conf_t *tmcf); 166static void nxt_router_engine_post(nxt_event_engine_t *engine, 167 nxt_work_t *jobs); 168 169static void nxt_router_thread_start(void *data); 170static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, 171 void *data); 172static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 173 void *data); 174static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 175 void *data); 176static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 177 void *data); 178static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 179 void *data); 180static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 181 void *data); 182static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 183 void *data); 184static void nxt_router_req_headers_ack_handler(nxt_task_t *task, 185 nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); 186static void nxt_router_listen_socket_release(nxt_task_t *task, 187 nxt_socket_conf_t *skcf); 188 189static void nxt_router_access_log_writer(nxt_task_t *task, 190 nxt_http_request_t *r, nxt_router_access_log_t *access_log); 191static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 192 struct tm *tm, size_t size, const char *format); 193static void nxt_router_access_log_open(nxt_task_t *task, 194 nxt_router_temp_conf_t *tmcf); 195static void nxt_router_access_log_ready(nxt_task_t *task, 196 nxt_port_recv_msg_t *msg, void *data); 197static void nxt_router_access_log_error(nxt_task_t *task, 198 nxt_port_recv_msg_t *msg, void *data); 199static void nxt_router_access_log_release(nxt_task_t *task, 200 nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 201static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 202 void *data); 203static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 204 nxt_port_recv_msg_t *msg, void *data); 205static void nxt_router_access_log_reopen_error(nxt_task_t *task, 206 nxt_port_recv_msg_t *msg, void *data); 207 208static void nxt_router_app_port_ready(nxt_task_t *task, 209 nxt_port_recv_msg_t *msg, void *data); 210static nxt_int_t nxt_router_app_shared_port_send(nxt_task_t *task, 211 nxt_port_t *app_port); 212static void nxt_router_app_port_error(nxt_task_t *task, 213 nxt_port_recv_msg_t *msg, void *data); 214 215static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i); 216static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 217 218static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 219 nxt_apr_action_t action); 220static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 221 nxt_request_rpc_data_t *req_rpc_data); 222static void nxt_router_http_request_error(nxt_task_t *task, void *obj, 223 void *data); 224static void nxt_router_http_request_done(nxt_task_t *task, void *obj, 225 void *data); 226 227static void nxt_router_dummy_buf_completion(nxt_task_t *task, void *obj, 228 void *data); 229static void nxt_router_app_prepare_request(nxt_task_t *task, 230 nxt_request_rpc_data_t *req_rpc_data); 231static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 232 nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); 233 234static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 235static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 236 void *data); 237static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 238 void *data); 239static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 240 void *data); 241static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 242 243static const nxt_http_request_state_t nxt_http_request_send_state; 244static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 245 246static void nxt_router_app_joint_use(nxt_task_t *task, 247 nxt_app_joint_t *app_joint, int i); 248 249static void nxt_router_http_request_release_post(nxt_task_t *task, 250 nxt_http_request_t *r); 251static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 252 void *data); 253static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 254static void nxt_router_get_port_handler(nxt_task_t *task, 255 nxt_port_recv_msg_t *msg); 256static void nxt_router_get_mmap_handler(nxt_task_t *task, 257 nxt_port_recv_msg_t *msg); 258 259extern const nxt_http_request_state_t nxt_http_websocket; 260 261static nxt_router_t *nxt_router; 262 263static const nxt_str_t http_prefix = nxt_string("HTTP_"); 264static const nxt_str_t empty_prefix = nxt_string(""); 265 266static const nxt_str_t *nxt_app_msg_prefix[] = { 267 &empty_prefix, 268 &empty_prefix, 269 &http_prefix, 270 &http_prefix, 271 &http_prefix, 272 &empty_prefix, 273}; 274 275 276static const nxt_port_handlers_t nxt_router_process_port_handlers = { 277 .quit = nxt_signal_quit_handler, 278 .new_port = nxt_router_new_port_handler, 279 .get_port = nxt_router_get_port_handler, 280 .change_file = nxt_port_change_log_file_handler, 281 .mmap = nxt_port_mmap_handler, 282 .get_mmap = nxt_router_get_mmap_handler, 283 .data = nxt_router_conf_data_handler,
| 92static void nxt_router_remove_pid_handler(nxt_task_t *task, 93 nxt_port_recv_msg_t *msg); 94static void nxt_router_access_log_reopen_handler(nxt_task_t *task, 95 nxt_port_recv_msg_t *msg); 96 97static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 98static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 99static void nxt_router_conf_ready(nxt_task_t *task, 100 nxt_router_temp_conf_t *tmcf); 101static void nxt_router_conf_error(nxt_task_t *task, 102 nxt_router_temp_conf_t *tmcf); 103static void nxt_router_conf_send(nxt_task_t *task, 104 nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 105 106static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 107 nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 108static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, 109 nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); 110 111static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 112static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 113static nxt_int_t nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, 114 nxt_app_t *app); 115static nxt_app_t *nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, 116 nxt_str_t *name); 117static void nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, 118 int i); 119 120static nxt_int_t nxt_router_app_queue_init(nxt_task_t *task, 121 nxt_port_t *port); 122static nxt_int_t nxt_router_port_queue_init(nxt_task_t *task, 123 nxt_port_t *port); 124static nxt_int_t nxt_router_port_queue_map(nxt_task_t *task, 125 nxt_port_t *port, nxt_fd_t fd); 126static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 127 nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 128static void nxt_router_listen_socket_ready(nxt_task_t *task, 129 nxt_port_recv_msg_t *msg, void *data); 130static void nxt_router_listen_socket_error(nxt_task_t *task, 131 nxt_port_recv_msg_t *msg, void *data); 132#if (NXT_TLS) 133static void nxt_router_tls_rpc_handler(nxt_task_t *task, 134 nxt_port_recv_msg_t *msg, void *data); 135static nxt_int_t nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 136 nxt_conf_value_t *value, nxt_socket_conf_t *skcf, nxt_tls_init_t *tls_init, 137 nxt_bool_t last); 138#endif 139static void nxt_router_app_rpc_create(nxt_task_t *task, 140 nxt_router_temp_conf_t *tmcf, nxt_app_t *app); 141static void nxt_router_app_prefork_ready(nxt_task_t *task, 142 nxt_port_recv_msg_t *msg, void *data); 143static void nxt_router_app_prefork_error(nxt_task_t *task, 144 nxt_port_recv_msg_t *msg, void *data); 145static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 146 nxt_router_temp_conf_t *tmcf, nxt_str_t *name); 147static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 148 nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa); 149 150static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 151 nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 152 const nxt_event_interface_t *interface); 153static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 154 nxt_router_engine_conf_t *recf); 155static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 156 nxt_router_engine_conf_t *recf); 157static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 158 nxt_router_engine_conf_t *recf); 159static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 160 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 161 nxt_work_handler_t handler); 162static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 163 nxt_router_engine_conf_t *recf); 164static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 165 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 166 167static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 168 nxt_router_temp_conf_t *tmcf); 169static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 170 nxt_event_engine_t *engine); 171static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 172 nxt_router_temp_conf_t *tmcf); 173 174static void nxt_router_engines_post(nxt_router_t *router, 175 nxt_router_temp_conf_t *tmcf); 176static void nxt_router_engine_post(nxt_event_engine_t *engine, 177 nxt_work_t *jobs); 178 179static void nxt_router_thread_start(void *data); 180static void nxt_router_rt_add_port(nxt_task_t *task, void *obj, 181 void *data); 182static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 183 void *data); 184static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 185 void *data); 186static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 187 void *data); 188static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, 189 void *data); 190static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 191 void *data); 192static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 193 void *data); 194static void nxt_router_req_headers_ack_handler(nxt_task_t *task, 195 nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data); 196static void nxt_router_listen_socket_release(nxt_task_t *task, 197 nxt_socket_conf_t *skcf); 198 199static void nxt_router_access_log_writer(nxt_task_t *task, 200 nxt_http_request_t *r, nxt_router_access_log_t *access_log); 201static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, 202 struct tm *tm, size_t size, const char *format); 203static void nxt_router_access_log_open(nxt_task_t *task, 204 nxt_router_temp_conf_t *tmcf); 205static void nxt_router_access_log_ready(nxt_task_t *task, 206 nxt_port_recv_msg_t *msg, void *data); 207static void nxt_router_access_log_error(nxt_task_t *task, 208 nxt_port_recv_msg_t *msg, void *data); 209static void nxt_router_access_log_release(nxt_task_t *task, 210 nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); 211static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, 212 void *data); 213static void nxt_router_access_log_reopen_ready(nxt_task_t *task, 214 nxt_port_recv_msg_t *msg, void *data); 215static void nxt_router_access_log_reopen_error(nxt_task_t *task, 216 nxt_port_recv_msg_t *msg, void *data); 217 218static void nxt_router_app_port_ready(nxt_task_t *task, 219 nxt_port_recv_msg_t *msg, void *data); 220static nxt_int_t nxt_router_app_shared_port_send(nxt_task_t *task, 221 nxt_port_t *app_port); 222static void nxt_router_app_port_error(nxt_task_t *task, 223 nxt_port_recv_msg_t *msg, void *data); 224 225static void nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i); 226static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app); 227 228static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 229 nxt_apr_action_t action); 230static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 231 nxt_request_rpc_data_t *req_rpc_data); 232static void nxt_router_http_request_error(nxt_task_t *task, void *obj, 233 void *data); 234static void nxt_router_http_request_done(nxt_task_t *task, void *obj, 235 void *data); 236 237static void nxt_router_dummy_buf_completion(nxt_task_t *task, void *obj, 238 void *data); 239static void nxt_router_app_prepare_request(nxt_task_t *task, 240 nxt_request_rpc_data_t *req_rpc_data); 241static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task, 242 nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix); 243 244static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data); 245static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, 246 void *data); 247static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, 248 void *data); 249static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, 250 void *data); 251static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data); 252 253static const nxt_http_request_state_t nxt_http_request_send_state; 254static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data); 255 256static void nxt_router_app_joint_use(nxt_task_t *task, 257 nxt_app_joint_t *app_joint, int i); 258 259static void nxt_router_http_request_release_post(nxt_task_t *task, 260 nxt_http_request_t *r); 261static void nxt_router_http_request_release(nxt_task_t *task, void *obj, 262 void *data); 263static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 264static void nxt_router_get_port_handler(nxt_task_t *task, 265 nxt_port_recv_msg_t *msg); 266static void nxt_router_get_mmap_handler(nxt_task_t *task, 267 nxt_port_recv_msg_t *msg); 268 269extern const nxt_http_request_state_t nxt_http_websocket; 270 271static nxt_router_t *nxt_router; 272 273static const nxt_str_t http_prefix = nxt_string("HTTP_"); 274static const nxt_str_t empty_prefix = nxt_string(""); 275 276static const nxt_str_t *nxt_app_msg_prefix[] = { 277 &empty_prefix, 278 &empty_prefix, 279 &http_prefix, 280 &http_prefix, 281 &http_prefix, 282 &empty_prefix, 283}; 284 285 286static const nxt_port_handlers_t nxt_router_process_port_handlers = { 287 .quit = nxt_signal_quit_handler, 288 .new_port = nxt_router_new_port_handler, 289 .get_port = nxt_router_get_port_handler, 290 .change_file = nxt_port_change_log_file_handler, 291 .mmap = nxt_port_mmap_handler, 292 .get_mmap = nxt_router_get_mmap_handler, 293 .data = nxt_router_conf_data_handler,
|
| 294 .app_restart = nxt_router_app_restart_handler,
|
284 .remove_pid = nxt_router_remove_pid_handler, 285 .access_log = nxt_router_access_log_reopen_handler, 286 .rpc_ready = nxt_port_rpc_handler, 287 .rpc_error = nxt_port_rpc_handler, 288 .oosm = nxt_router_oosm_handler, 289}; 290 291 292const nxt_process_init_t nxt_router_process = { 293 .name = "router", 294 .type = NXT_PROCESS_ROUTER, 295 .prefork = nxt_router_prefork, 296 .restart = 1, 297 .setup = nxt_process_core_setup, 298 .start = nxt_router_start, 299 .port_handlers = &nxt_router_process_port_handlers, 300 .signals = nxt_process_signals, 301}; 302 303 304/* Queues of nxt_socket_conf_t */ 305nxt_queue_t creating_sockets; 306nxt_queue_t pending_sockets; 307nxt_queue_t updating_sockets; 308nxt_queue_t keeping_sockets; 309nxt_queue_t deleting_sockets; 310 311 312static nxt_int_t 313nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 314{ 315 nxt_runtime_stop_app_processes(task, task->thread->runtime); 316 317 return NXT_OK; 318} 319 320 321static nxt_int_t 322nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) 323{ 324 nxt_int_t ret; 325 nxt_port_t *controller_port; 326 nxt_router_t *router; 327 nxt_runtime_t *rt; 328 329 rt = task->thread->runtime; 330 331 nxt_log(task, NXT_LOG_INFO, "router started"); 332 333#if (NXT_TLS) 334 rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 335 if (nxt_slow_path(rt->tls == NULL)) { 336 return NXT_ERROR; 337 } 338 339 ret = rt->tls->library_init(task); 340 if (nxt_slow_path(ret != NXT_OK)) { 341 return ret; 342 } 343#endif 344 345 ret = nxt_http_init(task); 346 if (nxt_slow_path(ret != NXT_OK)) { 347 return ret; 348 } 349 350 router = nxt_zalloc(sizeof(nxt_router_t)); 351 if (nxt_slow_path(router == NULL)) { 352 return NXT_ERROR; 353 } 354 355 nxt_queue_init(&router->engines); 356 nxt_queue_init(&router->sockets); 357 nxt_queue_init(&router->apps); 358 359 nxt_router = router; 360 361 controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 362 if (controller_port != NULL) { 363 nxt_router_greet_controller(task, controller_port); 364 } 365 366 return NXT_OK; 367} 368 369 370static void 371nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 372{ 373 nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 374 -1, 0, 0, NULL); 375} 376 377 378static void 379nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 380 void *data) 381{
| 295 .remove_pid = nxt_router_remove_pid_handler, 296 .access_log = nxt_router_access_log_reopen_handler, 297 .rpc_ready = nxt_port_rpc_handler, 298 .rpc_error = nxt_port_rpc_handler, 299 .oosm = nxt_router_oosm_handler, 300}; 301 302 303const nxt_process_init_t nxt_router_process = { 304 .name = "router", 305 .type = NXT_PROCESS_ROUTER, 306 .prefork = nxt_router_prefork, 307 .restart = 1, 308 .setup = nxt_process_core_setup, 309 .start = nxt_router_start, 310 .port_handlers = &nxt_router_process_port_handlers, 311 .signals = nxt_process_signals, 312}; 313 314 315/* Queues of nxt_socket_conf_t */ 316nxt_queue_t creating_sockets; 317nxt_queue_t pending_sockets; 318nxt_queue_t updating_sockets; 319nxt_queue_t keeping_sockets; 320nxt_queue_t deleting_sockets; 321 322 323static nxt_int_t 324nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 325{ 326 nxt_runtime_stop_app_processes(task, task->thread->runtime); 327 328 return NXT_OK; 329} 330 331 332static nxt_int_t 333nxt_router_start(nxt_task_t *task, nxt_process_data_t *data) 334{ 335 nxt_int_t ret; 336 nxt_port_t *controller_port; 337 nxt_router_t *router; 338 nxt_runtime_t *rt; 339 340 rt = task->thread->runtime; 341 342 nxt_log(task, NXT_LOG_INFO, "router started"); 343 344#if (NXT_TLS) 345 rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL"); 346 if (nxt_slow_path(rt->tls == NULL)) { 347 return NXT_ERROR; 348 } 349 350 ret = rt->tls->library_init(task); 351 if (nxt_slow_path(ret != NXT_OK)) { 352 return ret; 353 } 354#endif 355 356 ret = nxt_http_init(task); 357 if (nxt_slow_path(ret != NXT_OK)) { 358 return ret; 359 } 360 361 router = nxt_zalloc(sizeof(nxt_router_t)); 362 if (nxt_slow_path(router == NULL)) { 363 return NXT_ERROR; 364 } 365 366 nxt_queue_init(&router->engines); 367 nxt_queue_init(&router->sockets); 368 nxt_queue_init(&router->apps); 369 370 nxt_router = router; 371 372 controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 373 if (controller_port != NULL) { 374 nxt_router_greet_controller(task, controller_port); 375 } 376 377 return NXT_OK; 378} 379 380 381static void 382nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port) 383{ 384 nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY, 385 -1, 0, 0, NULL); 386} 387 388 389static void 390nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port, 391 void *data) 392{
|
382 size_t size; 383 uint32_t stream; 384 nxt_mp_t *mp; 385 nxt_int_t ret; 386 nxt_app_t *app; 387 nxt_buf_t *b; 388 nxt_port_t *main_port; 389 nxt_runtime_t *rt;
| 393 size_t size; 394 uint32_t stream; 395 nxt_mp_t *mp; 396 nxt_int_t ret; 397 nxt_app_t *app; 398 nxt_buf_t *b; 399 nxt_port_t *main_port; 400 nxt_runtime_t *rt; 401 nxt_app_joint_rpc_t *app_joint_rpc;
|
390 391 app = data; 392 393 rt = task->thread->runtime; 394 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 395 396 nxt_debug(task, "app '%V' %p start process", &app->name, app); 397 398 size = app->name.length + 1 + app->conf.length; 399 400 b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size); 401 402 if (nxt_slow_path(b == NULL)) { 403 goto failed; 404 } 405 406 nxt_buf_cpystr(b, &app->name); 407 *b->mem.free++ = '\0'; 408 nxt_buf_cpystr(b, &app->conf); 409
| 402 403 app = data; 404 405 rt = task->thread->runtime; 406 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 407 408 nxt_debug(task, "app '%V' %p start process", &app->name, app); 409 410 size = app->name.length + 1 + app->conf.length; 411 412 b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size); 413 414 if (nxt_slow_path(b == NULL)) { 415 goto failed; 416 } 417 418 nxt_buf_cpystr(b, &app->name); 419 *b->mem.free++ = '\0'; 420 nxt_buf_cpystr(b, &app->conf); 421
|
410 nxt_router_app_joint_use(task, app->joint, 1); 411 412 stream = nxt_port_rpc_register_handler(task, port, 413 nxt_router_app_port_ready, 414 nxt_router_app_port_error, 415 -1, app->joint); 416 417 if (nxt_slow_path(stream == 0)) { 418 nxt_router_app_joint_use(task, app->joint, -1); 419
| 422 app_joint_rpc = nxt_port_rpc_register_handler_ex(task, port, 423 nxt_router_app_port_ready, 424 nxt_router_app_port_error, 425 sizeof(nxt_app_joint_rpc_t)); 426 if (nxt_slow_path(app_joint_rpc == NULL)) {
|
420 goto failed; 421 } 422
| 427 goto failed; 428 } 429
|
| 430 stream = nxt_port_rpc_ex_stream(app_joint_rpc); 431
|
423 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS, 424 -1, stream, port->id, b);
| 432 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS, 433 -1, stream, port->id, b);
|
425
| |
426 if (nxt_slow_path(ret != NXT_OK)) { 427 nxt_port_rpc_cancel(task, port, stream); 428
| 434 if (nxt_slow_path(ret != NXT_OK)) { 435 nxt_port_rpc_cancel(task, port, stream); 436
|
429 nxt_router_app_joint_use(task, app->joint, -1); 430
| |
431 goto failed; 432 } 433
| 437 goto failed; 438 } 439
|
| 440 app_joint_rpc->app_joint = app->joint; 441 app_joint_rpc->generation = app->generation; 442 443 nxt_router_app_joint_use(task, app->joint, 1); 444
|
434 nxt_router_app_use(task, app, -1); 435 436 return; 437 438failed: 439 440 if (b != NULL) { 441 mp = b->data; 442 nxt_mp_free(mp, b); 443 nxt_mp_release(mp); 444 } 445 446 nxt_thread_mutex_lock(&app->mutex); 447 448 app->pending_processes--; 449 450 nxt_thread_mutex_unlock(&app->mutex); 451 452 nxt_router_app_use(task, app, -1); 453} 454 455 456static void 457nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 458{ 459 app_joint->use_count += i; 460 461 if (app_joint->use_count == 0) { 462 nxt_assert(app_joint->app == NULL); 463 464 nxt_free(app_joint); 465 } 466} 467 468 469static nxt_int_t 470nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 471{ 472 nxt_int_t res; 473 nxt_port_t *router_port; 474 nxt_runtime_t *rt; 475 476 nxt_debug(task, "app '%V' start process", &app->name); 477 478 rt = task->thread->runtime; 479 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 480 481 nxt_router_app_use(task, app, 1); 482 483 res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 484 app); 485 486 if (res == NXT_OK) { 487 return res; 488 } 489 490 nxt_thread_mutex_lock(&app->mutex); 491 492 app->pending_processes--; 493 494 nxt_thread_mutex_unlock(&app->mutex); 495 496 nxt_router_app_use(task, app, -1); 497 498 return NXT_ERROR; 499} 500 501 502nxt_inline nxt_bool_t 503nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) 504{ 505 nxt_buf_t *b, *next; 506 nxt_bool_t cancelled;
| 445 nxt_router_app_use(task, app, -1); 446 447 return; 448 449failed: 450 451 if (b != NULL) { 452 mp = b->data; 453 nxt_mp_free(mp, b); 454 nxt_mp_release(mp); 455 } 456 457 nxt_thread_mutex_lock(&app->mutex); 458 459 app->pending_processes--; 460 461 nxt_thread_mutex_unlock(&app->mutex); 462 463 nxt_router_app_use(task, app, -1); 464} 465 466 467static void 468nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i) 469{ 470 app_joint->use_count += i; 471 472 if (app_joint->use_count == 0) { 473 nxt_assert(app_joint->app == NULL); 474 475 nxt_free(app_joint); 476 } 477} 478 479 480static nxt_int_t 481nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app) 482{ 483 nxt_int_t res; 484 nxt_port_t *router_port; 485 nxt_runtime_t *rt; 486 487 nxt_debug(task, "app '%V' start process", &app->name); 488 489 rt = task->thread->runtime; 490 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 491 492 nxt_router_app_use(task, app, 1); 493 494 res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler, 495 app); 496 497 if (res == NXT_OK) { 498 return res; 499 } 500 501 nxt_thread_mutex_lock(&app->mutex); 502 503 app->pending_processes--; 504 505 nxt_thread_mutex_unlock(&app->mutex); 506 507 nxt_router_app_use(task, app, -1); 508 509 return NXT_ERROR; 510} 511 512 513nxt_inline nxt_bool_t 514nxt_router_msg_cancel(nxt_task_t *task, nxt_request_rpc_data_t *req_rpc_data) 515{ 516 nxt_buf_t *b, *next; 517 nxt_bool_t cancelled;
|
| 518 nxt_port_t *app_port;
|
507 nxt_msg_info_t *msg_info; 508 509 msg_info = &req_rpc_data->msg_info; 510 511 if (msg_info->buf == NULL) { 512 return 0; 513 } 514
| 519 nxt_msg_info_t *msg_info; 520 521 msg_info = &req_rpc_data->msg_info; 522 523 if (msg_info->buf == NULL) { 524 return 0; 525 } 526
|
515 cancelled = nxt_app_queue_cancel(req_rpc_data->app->shared_port->queue, 516 msg_info->tracking_cookie, 517 req_rpc_data->stream);
| 527 app_port = req_rpc_data->app_port;
|
518
| 528
|
519 if (cancelled) { 520 nxt_debug(task, "stream #%uD: cancelled by router", 521 req_rpc_data->stream);
| 529 if (app_port != NULL && app_port->id == NXT_SHARED_PORT_ID) { 530 cancelled = nxt_app_queue_cancel(app_port->queue, 531 msg_info->tracking_cookie, 532 req_rpc_data->stream); 533 534 if (cancelled) { 535 nxt_debug(task, "stream #%uD: cancelled by router", 536 req_rpc_data->stream); 537 } 538 539 } else { 540 cancelled = 0;
|
522 } 523 524 for (b = msg_info->buf; b != NULL; b = next) { 525 next = b->next; 526 b->next = NULL; 527 528 if (b->is_port_mmap_sent) { 529 b->is_port_mmap_sent = cancelled == 0; 530 } 531 532 b->completion_handler(task, b, b->parent); 533 } 534 535 msg_info->buf = NULL; 536 537 return cancelled; 538} 539 540 541nxt_inline nxt_bool_t 542nxt_queue_chk_remove(nxt_queue_link_t *lnk) 543{ 544 if (lnk->next != NULL) { 545 nxt_queue_remove(lnk); 546 547 lnk->next = NULL; 548 549 return 1; 550 } 551 552 return 0; 553} 554 555 556nxt_inline void 557nxt_request_rpc_data_unlink(nxt_task_t *task, 558 nxt_request_rpc_data_t *req_rpc_data) 559{ 560 nxt_app_t *app; 561 nxt_bool_t unlinked; 562 nxt_http_request_t *r; 563 564 nxt_router_msg_cancel(task, req_rpc_data); 565 566 if (req_rpc_data->app_port != NULL) { 567 nxt_router_app_port_release(task, req_rpc_data->app_port, 568 req_rpc_data->apr_action); 569 570 req_rpc_data->app_port = NULL; 571 } 572 573 app = req_rpc_data->app; 574 r = req_rpc_data->request; 575 576 if (r != NULL) { 577 r->timer_data = NULL; 578 579 nxt_router_http_request_release_post(task, r); 580 581 r->req_rpc_data = NULL; 582 req_rpc_data->request = NULL; 583 584 if (app != NULL) { 585 unlinked = 0; 586 587 nxt_thread_mutex_lock(&app->mutex); 588 589 if (r->app_link.next != NULL) { 590 nxt_queue_remove(&r->app_link); 591 r->app_link.next = NULL; 592 593 unlinked = 1; 594 } 595 596 nxt_thread_mutex_unlock(&app->mutex); 597 598 if (unlinked) { 599 nxt_mp_release(r->mem_pool); 600 } 601 } 602 } 603 604 if (app != NULL) { 605 nxt_router_app_use(task, app, -1); 606 607 req_rpc_data->app = NULL; 608 } 609 610 if (req_rpc_data->msg_info.body_fd != -1) { 611 nxt_fd_close(req_rpc_data->msg_info.body_fd); 612 613 req_rpc_data->msg_info.body_fd = -1; 614 } 615 616 if (req_rpc_data->rpc_cancel) { 617 req_rpc_data->rpc_cancel = 0; 618 619 nxt_port_rpc_cancel(task, task->thread->engine->port, 620 req_rpc_data->stream); 621 } 622} 623 624 625static void 626nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 627{ 628 nxt_int_t res; 629 nxt_app_t *app; 630 nxt_port_t *port, *main_app_port; 631 nxt_runtime_t *rt; 632 633 nxt_port_new_port_handler(task, msg); 634 635 port = msg->u.new_port; 636 637 if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { 638 nxt_router_greet_controller(task, msg->u.new_port); 639 } 640 641 if (port == NULL || port->type != NXT_PROCESS_APP) { 642 643 if (msg->port_msg.stream == 0) { 644 return; 645 } 646 647 msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 648 649 } else { 650 if (msg->fd[1] != -1) { 651 res = nxt_router_port_queue_map(task, port, msg->fd[1]); 652 if (nxt_slow_path(res != NXT_OK)) { 653 return; 654 } 655 656 nxt_fd_close(msg->fd[1]); 657 msg->fd[1] = -1; 658 } 659 } 660 661 if (msg->port_msg.stream != 0) { 662 nxt_port_rpc_handler(task, msg); 663 return; 664 } 665 666 /* 667 * Port with "id == 0" is application 'main' port and it always 668 * should come with non-zero stream. 669 */ 670 nxt_assert(port->id != 0); 671 672 /* Find 'main' app port and get app reference. */ 673 rt = task->thread->runtime; 674 675 /* 676 * It is safe to access 'runtime->ports' hash because 'NEW_PORT' 677 * sent to main port (with id == 0) and processed in main thread. 678 */ 679 main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); 680 nxt_assert(main_app_port != NULL); 681 682 app = main_app_port->app; 683 684 if (nxt_fast_path(app != NULL)) { 685 nxt_thread_mutex_lock(&app->mutex); 686 687 /* TODO here should be find-and-add code because there can be 688 port waiters in port_hash */ 689 nxt_port_hash_add(&app->port_hash, port); 690 app->port_hash_count++; 691 692 nxt_thread_mutex_unlock(&app->mutex); 693 694 port->app = app; 695 } 696 697 port->main_app_port = main_app_port; 698 699 nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); 700} 701 702 703static void 704nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 705{ 706 void *p; 707 size_t size; 708 nxt_int_t ret; 709 nxt_port_t *port; 710 nxt_router_temp_conf_t *tmcf; 711 712 port = nxt_runtime_port_find(task->thread->runtime, 713 msg->port_msg.pid, 714 msg->port_msg.reply_port); 715 if (nxt_slow_path(port == NULL)) { 716 nxt_alert(task, "conf_data_handler: reply port not found"); 717 return; 718 } 719 720 p = MAP_FAILED; 721 722 /* 723 * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be 724 * initialized in 'cleanup' section. 725 */ 726 size = 0; 727 728 tmcf = nxt_router_temp_conf(task); 729 if (nxt_slow_path(tmcf == NULL)) { 730 goto fail; 731 } 732 733 if (nxt_slow_path(msg->fd[0] == -1)) { 734 nxt_alert(task, "conf_data_handler: invalid shm fd"); 735 goto fail; 736 } 737 738 if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { 739 nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)", 740 (int) nxt_buf_mem_used_size(&msg->buf->mem)); 741 goto fail; 742 } 743 744 nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); 745 746 p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); 747 748 nxt_fd_close(msg->fd[0]); 749 msg->fd[0] = -1; 750 751 if (nxt_slow_path(p == MAP_FAILED)) { 752 goto fail; 753 } 754 755 nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p); 756 757 tmcf->router_conf->router = nxt_router; 758 tmcf->stream = msg->port_msg.stream; 759 tmcf->port = port; 760 761 nxt_port_use(task, tmcf->port, 1); 762 763 ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size)); 764 765 if (nxt_fast_path(ret == NXT_OK)) { 766 nxt_router_conf_apply(task, tmcf, NULL); 767 768 } else { 769 nxt_router_conf_error(task, tmcf); 770 } 771 772 goto cleanup; 773 774fail: 775 776 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, 777 msg->port_msg.stream, 0, NULL); 778 779 if (tmcf != NULL) { 780 nxt_mp_release(tmcf->mem_pool); 781 } 782 783cleanup: 784 785 if (p != MAP_FAILED) { 786 nxt_mem_munmap(p, size); 787 } 788 789 if (msg->fd[0] != -1) { 790 nxt_fd_close(msg->fd[0]); 791 msg->fd[0] = -1; 792 } 793} 794 795 796static void
| 541 } 542 543 for (b = msg_info->buf; b != NULL; b = next) { 544 next = b->next; 545 b->next = NULL; 546 547 if (b->is_port_mmap_sent) { 548 b->is_port_mmap_sent = cancelled == 0; 549 } 550 551 b->completion_handler(task, b, b->parent); 552 } 553 554 msg_info->buf = NULL; 555 556 return cancelled; 557} 558 559 560nxt_inline nxt_bool_t 561nxt_queue_chk_remove(nxt_queue_link_t *lnk) 562{ 563 if (lnk->next != NULL) { 564 nxt_queue_remove(lnk); 565 566 lnk->next = NULL; 567 568 return 1; 569 } 570 571 return 0; 572} 573 574 575nxt_inline void 576nxt_request_rpc_data_unlink(nxt_task_t *task, 577 nxt_request_rpc_data_t *req_rpc_data) 578{ 579 nxt_app_t *app; 580 nxt_bool_t unlinked; 581 nxt_http_request_t *r; 582 583 nxt_router_msg_cancel(task, req_rpc_data); 584 585 if (req_rpc_data->app_port != NULL) { 586 nxt_router_app_port_release(task, req_rpc_data->app_port, 587 req_rpc_data->apr_action); 588 589 req_rpc_data->app_port = NULL; 590 } 591 592 app = req_rpc_data->app; 593 r = req_rpc_data->request; 594 595 if (r != NULL) { 596 r->timer_data = NULL; 597 598 nxt_router_http_request_release_post(task, r); 599 600 r->req_rpc_data = NULL; 601 req_rpc_data->request = NULL; 602 603 if (app != NULL) { 604 unlinked = 0; 605 606 nxt_thread_mutex_lock(&app->mutex); 607 608 if (r->app_link.next != NULL) { 609 nxt_queue_remove(&r->app_link); 610 r->app_link.next = NULL; 611 612 unlinked = 1; 613 } 614 615 nxt_thread_mutex_unlock(&app->mutex); 616 617 if (unlinked) { 618 nxt_mp_release(r->mem_pool); 619 } 620 } 621 } 622 623 if (app != NULL) { 624 nxt_router_app_use(task, app, -1); 625 626 req_rpc_data->app = NULL; 627 } 628 629 if (req_rpc_data->msg_info.body_fd != -1) { 630 nxt_fd_close(req_rpc_data->msg_info.body_fd); 631 632 req_rpc_data->msg_info.body_fd = -1; 633 } 634 635 if (req_rpc_data->rpc_cancel) { 636 req_rpc_data->rpc_cancel = 0; 637 638 nxt_port_rpc_cancel(task, task->thread->engine->port, 639 req_rpc_data->stream); 640 } 641} 642 643 644static void 645nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 646{ 647 nxt_int_t res; 648 nxt_app_t *app; 649 nxt_port_t *port, *main_app_port; 650 nxt_runtime_t *rt; 651 652 nxt_port_new_port_handler(task, msg); 653 654 port = msg->u.new_port; 655 656 if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) { 657 nxt_router_greet_controller(task, msg->u.new_port); 658 } 659 660 if (port == NULL || port->type != NXT_PROCESS_APP) { 661 662 if (msg->port_msg.stream == 0) { 663 return; 664 } 665 666 msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 667 668 } else { 669 if (msg->fd[1] != -1) { 670 res = nxt_router_port_queue_map(task, port, msg->fd[1]); 671 if (nxt_slow_path(res != NXT_OK)) { 672 return; 673 } 674 675 nxt_fd_close(msg->fd[1]); 676 msg->fd[1] = -1; 677 } 678 } 679 680 if (msg->port_msg.stream != 0) { 681 nxt_port_rpc_handler(task, msg); 682 return; 683 } 684 685 /* 686 * Port with "id == 0" is application 'main' port and it always 687 * should come with non-zero stream. 688 */ 689 nxt_assert(port->id != 0); 690 691 /* Find 'main' app port and get app reference. */ 692 rt = task->thread->runtime; 693 694 /* 695 * It is safe to access 'runtime->ports' hash because 'NEW_PORT' 696 * sent to main port (with id == 0) and processed in main thread. 697 */ 698 main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0); 699 nxt_assert(main_app_port != NULL); 700 701 app = main_app_port->app; 702 703 if (nxt_fast_path(app != NULL)) { 704 nxt_thread_mutex_lock(&app->mutex); 705 706 /* TODO here should be find-and-add code because there can be 707 port waiters in port_hash */ 708 nxt_port_hash_add(&app->port_hash, port); 709 app->port_hash_count++; 710 711 nxt_thread_mutex_unlock(&app->mutex); 712 713 port->app = app; 714 } 715 716 port->main_app_port = main_app_port; 717 718 nxt_port_socket_write(task, port, NXT_PORT_MSG_PORT_ACK, -1, 0, 0, NULL); 719} 720 721 722static void 723nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 724{ 725 void *p; 726 size_t size; 727 nxt_int_t ret; 728 nxt_port_t *port; 729 nxt_router_temp_conf_t *tmcf; 730 731 port = nxt_runtime_port_find(task->thread->runtime, 732 msg->port_msg.pid, 733 msg->port_msg.reply_port); 734 if (nxt_slow_path(port == NULL)) { 735 nxt_alert(task, "conf_data_handler: reply port not found"); 736 return; 737 } 738 739 p = MAP_FAILED; 740 741 /* 742 * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be 743 * initialized in 'cleanup' section. 744 */ 745 size = 0; 746 747 tmcf = nxt_router_temp_conf(task); 748 if (nxt_slow_path(tmcf == NULL)) { 749 goto fail; 750 } 751 752 if (nxt_slow_path(msg->fd[0] == -1)) { 753 nxt_alert(task, "conf_data_handler: invalid shm fd"); 754 goto fail; 755 } 756 757 if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { 758 nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)", 759 (int) nxt_buf_mem_used_size(&msg->buf->mem)); 760 goto fail; 761 } 762 763 nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); 764 765 p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); 766 767 nxt_fd_close(msg->fd[0]); 768 msg->fd[0] = -1; 769 770 if (nxt_slow_path(p == MAP_FAILED)) { 771 goto fail; 772 } 773 774 nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p); 775 776 tmcf->router_conf->router = nxt_router; 777 tmcf->stream = msg->port_msg.stream; 778 tmcf->port = port; 779 780 nxt_port_use(task, tmcf->port, 1); 781 782 ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size)); 783 784 if (nxt_fast_path(ret == NXT_OK)) { 785 nxt_router_conf_apply(task, tmcf, NULL); 786 787 } else { 788 nxt_router_conf_error(task, tmcf); 789 } 790 791 goto cleanup; 792 793fail: 794 795 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, 796 msg->port_msg.stream, 0, NULL); 797 798 if (tmcf != NULL) { 799 nxt_mp_release(tmcf->mem_pool); 800 } 801 802cleanup: 803 804 if (p != MAP_FAILED) { 805 nxt_mem_munmap(p, size); 806 } 807 808 if (msg->fd[0] != -1) { 809 nxt_fd_close(msg->fd[0]); 810 msg->fd[0] = -1; 811 } 812} 813 814 815static void
|
| 816nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 817{ 818 nxt_app_t *app; 819 nxt_int_t ret; 820 nxt_str_t app_name; 821 nxt_port_t *port, *reply_port, *shared_port, *old_shared_port; 822 nxt_port_msg_type_t reply; 823 824 reply_port = nxt_runtime_port_find(task->thread->runtime, 825 msg->port_msg.pid, 826 msg->port_msg.reply_port); 827 if (nxt_slow_path(reply_port == NULL)) { 828 nxt_alert(task, "app_restart_handler: reply port not found"); 829 return; 830 } 831 832 app_name.length = nxt_buf_mem_used_size(&msg->buf->mem); 833 app_name.start = msg->buf->mem.pos; 834 835 nxt_debug(task, "app_restart_handler: %V", &app_name); 836 837 app = nxt_router_app_find(&nxt_router->apps, &app_name); 838 839 if (nxt_fast_path(app != NULL)) { 840 shared_port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid, 841 NXT_PROCESS_APP); 842 if (nxt_slow_path(shared_port == NULL)) { 843 goto fail; 844 } 845 846 ret = nxt_port_socket_init(task, shared_port, 0); 847 if (nxt_slow_path(ret != NXT_OK)) { 848 nxt_port_use(task, shared_port, -1); 849 goto fail; 850 } 851 852 ret = nxt_router_app_queue_init(task, shared_port); 853 if (nxt_slow_path(ret != NXT_OK)) { 854 nxt_port_write_close(shared_port); 855 nxt_port_read_close(shared_port); 856 nxt_port_use(task, shared_port, -1); 857 goto fail; 858 } 859 860 nxt_port_write_enable(task, shared_port); 861 862 nxt_thread_mutex_lock(&app->mutex); 863 864 nxt_queue_each(port, &app->ports, nxt_port_t, app_link) { 865 866 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 867 0, 0, NULL); 868 869 } nxt_queue_loop; 870 871 app->generation++; 872 873 shared_port->app = app; 874 875 old_shared_port = app->shared_port; 876 old_shared_port->app = NULL; 877 878 app->shared_port = shared_port; 879 880 nxt_thread_mutex_unlock(&app->mutex); 881 882 nxt_port_close(task, old_shared_port); 883 nxt_port_use(task, old_shared_port, -1); 884 885 reply = NXT_PORT_MSG_RPC_READY_LAST; 886 887 } else { 888 889fail: 890 891 reply = NXT_PORT_MSG_RPC_ERROR; 892 } 893 894 nxt_port_socket_write(task, reply_port, reply, -1, msg->port_msg.stream, 895 0, NULL); 896} 897 898 899static void
|
797nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, 798 void *data) 799{ 800 union { 801 nxt_pid_t removed_pid; 802 void *data; 803 } u; 804 805 u.data = data; 806 807 nxt_port_rpc_remove_peer(task, port, u.removed_pid); 808} 809 810 811static void 812nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 813{ 814 nxt_event_engine_t *engine; 815 816 nxt_port_remove_pid_handler(task, msg); 817 818 nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) 819 { 820 if (nxt_fast_path(engine->port != NULL)) { 821 nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid, 822 msg->u.data); 823 } 824 } 825 nxt_queue_loop; 826 827 if (msg->port_msg.stream == 0) { 828 return; 829 } 830 831 msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 832 833 nxt_port_rpc_handler(task, msg); 834} 835 836 837static nxt_router_temp_conf_t * 838nxt_router_temp_conf(nxt_task_t *task) 839{ 840 nxt_mp_t *mp, *tmp; 841 nxt_router_conf_t *rtcf; 842 nxt_router_temp_conf_t *tmcf; 843 844 mp = nxt_mp_create(1024, 128, 256, 32); 845 if (nxt_slow_path(mp == NULL)) { 846 return NULL; 847 } 848 849 rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 850 if (nxt_slow_path(rtcf == NULL)) { 851 goto fail; 852 } 853 854 rtcf->mem_pool = mp; 855 856 tmp = nxt_mp_create(1024, 128, 256, 32); 857 if (nxt_slow_path(tmp == NULL)) { 858 goto fail; 859 } 860 861 tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 862 if (nxt_slow_path(tmcf == NULL)) { 863 goto temp_fail; 864 } 865 866 tmcf->mem_pool = tmp; 867 tmcf->router_conf = rtcf; 868 tmcf->count = 1; 869 tmcf->engine = task->thread->engine; 870 871 tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 872 sizeof(nxt_router_engine_conf_t)); 873 if (nxt_slow_path(tmcf->engines == NULL)) { 874 goto temp_fail; 875 } 876 877 nxt_queue_init(&creating_sockets); 878 nxt_queue_init(&pending_sockets); 879 nxt_queue_init(&updating_sockets); 880 nxt_queue_init(&keeping_sockets); 881 nxt_queue_init(&deleting_sockets); 882 883#if (NXT_TLS) 884 nxt_queue_init(&tmcf->tls); 885#endif 886 887 nxt_queue_init(&tmcf->apps); 888 nxt_queue_init(&tmcf->previous); 889 890 return tmcf; 891 892temp_fail: 893 894 nxt_mp_destroy(tmp); 895 896fail: 897 898 nxt_mp_destroy(mp); 899 900 return NULL; 901} 902 903 904nxt_inline nxt_bool_t 905nxt_router_app_can_start(nxt_app_t *app) 906{ 907 return app->processes + app->pending_processes < app->max_processes 908 && app->pending_processes < app->max_pending_processes; 909} 910 911 912nxt_inline nxt_bool_t 913nxt_router_app_need_start(nxt_app_t *app) 914{ 915 return (app->active_requests 916 > app->port_hash_count + app->pending_processes) 917 || (app->spare_processes 918 > app->idle_processes + app->pending_processes); 919} 920 921 922static void 923nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) 924{ 925 nxt_int_t ret; 926 nxt_app_t *app; 927 nxt_router_t *router; 928 nxt_runtime_t *rt; 929 nxt_queue_link_t *qlk; 930 nxt_socket_conf_t *skcf; 931 nxt_router_conf_t *rtcf; 932 nxt_router_temp_conf_t *tmcf; 933 const nxt_event_interface_t *interface; 934#if (NXT_TLS) 935 nxt_router_tlssock_t *tls; 936#endif 937 938 tmcf = obj; 939 940 qlk = nxt_queue_first(&pending_sockets); 941 942 if (qlk != nxt_queue_tail(&pending_sockets)) { 943 nxt_queue_remove(qlk); 944 nxt_queue_insert_tail(&creating_sockets, qlk); 945 946 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 947 948 nxt_router_listen_socket_rpc_create(task, tmcf, skcf); 949 950 return; 951 } 952 953#if (NXT_TLS) 954 qlk = nxt_queue_last(&tmcf->tls); 955 956 if (qlk != nxt_queue_head(&tmcf->tls)) { 957 nxt_queue_remove(qlk); 958 959 tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link); 960 961 nxt_cert_store_get(task, &tls->name, tmcf->mem_pool, 962 nxt_router_tls_rpc_handler, tls); 963 return; 964 } 965#endif 966 967 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 968 969 if (nxt_router_app_need_start(app)) { 970 nxt_router_app_rpc_create(task, tmcf, app); 971 return; 972 } 973 974 } nxt_queue_loop; 975 976 rtcf = tmcf->router_conf; 977 978 if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) { 979 nxt_router_access_log_open(task, tmcf); 980 return; 981 } 982 983 rt = task->thread->runtime; 984 985 interface = nxt_service_get(rt->services, "engine", NULL); 986 987 router = rtcf->router; 988 989 ret = nxt_router_engines_create(task, router, tmcf, interface); 990 if (nxt_slow_path(ret != NXT_OK)) { 991 goto fail; 992 } 993 994 ret = nxt_router_threads_create(task, rt, tmcf); 995 if (nxt_slow_path(ret != NXT_OK)) { 996 goto fail; 997 } 998 999 nxt_router_apps_sort(task, router, tmcf); 1000 1001 nxt_router_apps_hash_use(task, rtcf, 1); 1002 1003 nxt_router_engines_post(router, tmcf); 1004 1005 nxt_queue_add(&router->sockets, &updating_sockets); 1006 nxt_queue_add(&router->sockets, &creating_sockets); 1007 1008 router->access_log = rtcf->access_log; 1009 1010 nxt_router_conf_ready(task, tmcf); 1011 1012 return; 1013 1014fail: 1015 1016 nxt_router_conf_error(task, tmcf); 1017 1018 return; 1019} 1020 1021 1022static void 1023nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 1024{ 1025 nxt_joint_job_t *job; 1026 1027 job = obj; 1028 1029 nxt_router_conf_ready(task, job->tmcf); 1030} 1031 1032 1033static void 1034nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1035{ 1036 uint32_t count; 1037 nxt_router_conf_t *rtcf; 1038 nxt_thread_spinlock_t *lock; 1039 1040 nxt_debug(task, "temp conf %p count: %D", tmcf, tmcf->count); 1041 1042 if (--tmcf->count > 0) { 1043 return; 1044 } 1045 1046 nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); 1047 1048 rtcf = tmcf->router_conf; 1049 1050 lock = &rtcf->router->lock; 1051 1052 nxt_thread_spin_lock(lock); 1053 1054 count = rtcf->count; 1055 1056 nxt_thread_spin_unlock(lock); 1057 1058 nxt_debug(task, "rtcf %p: %D", rtcf, count); 1059 1060 if (count == 0) { 1061 nxt_router_apps_hash_use(task, rtcf, -1); 1062 1063 nxt_router_access_log_release(task, lock, rtcf->access_log); 1064 1065 nxt_mp_destroy(rtcf->mem_pool); 1066 } 1067 1068 nxt_mp_release(tmcf->mem_pool); 1069} 1070 1071 1072static void 1073nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1074{ 1075 nxt_app_t *app; 1076 nxt_queue_t new_socket_confs; 1077 nxt_socket_t s; 1078 nxt_router_t *router; 1079 nxt_queue_link_t *qlk; 1080 nxt_socket_conf_t *skcf; 1081 nxt_router_conf_t *rtcf; 1082 1083 nxt_alert(task, "failed to apply new conf"); 1084 1085 for (qlk = nxt_queue_first(&creating_sockets); 1086 qlk != nxt_queue_tail(&creating_sockets); 1087 qlk = nxt_queue_next(qlk)) 1088 { 1089 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1090 s = skcf->listen->socket; 1091 1092 if (s != -1) { 1093 nxt_socket_close(task, s); 1094 } 1095 1096 nxt_free(skcf->listen); 1097 } 1098 1099 nxt_queue_init(&new_socket_confs); 1100 nxt_queue_add(&new_socket_confs, &updating_sockets); 1101 nxt_queue_add(&new_socket_confs, &pending_sockets); 1102 nxt_queue_add(&new_socket_confs, &creating_sockets); 1103 1104 rtcf = tmcf->router_conf; 1105 1106 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1107 1108 nxt_router_app_unlink(task, app); 1109 1110 } nxt_queue_loop; 1111 1112 router = rtcf->router; 1113 1114 nxt_queue_add(&router->sockets, &keeping_sockets); 1115 nxt_queue_add(&router->sockets, &deleting_sockets); 1116 1117 nxt_queue_add(&router->apps, &tmcf->previous); 1118 1119 // TODO: new engines and threads 1120 1121 nxt_router_access_log_release(task, &router->lock, rtcf->access_log); 1122 1123 nxt_mp_destroy(rtcf->mem_pool); 1124 1125 nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); 1126 1127 nxt_mp_release(tmcf->mem_pool); 1128} 1129 1130 1131static void 1132nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1133 nxt_port_msg_type_t type) 1134{ 1135 nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); 1136 1137 nxt_port_use(task, tmcf->port, -1); 1138 1139 tmcf->port = NULL; 1140} 1141 1142 1143static nxt_conf_map_t nxt_router_conf[] = { 1144 { 1145 nxt_string("listeners_threads"), 1146 NXT_CONF_MAP_INT32, 1147 offsetof(nxt_router_conf_t, threads), 1148 }, 1149}; 1150 1151 1152static nxt_conf_map_t nxt_router_app_conf[] = { 1153 { 1154 nxt_string("type"), 1155 NXT_CONF_MAP_STR, 1156 offsetof(nxt_router_app_conf_t, type), 1157 }, 1158 1159 { 1160 nxt_string("limits"), 1161 NXT_CONF_MAP_PTR, 1162 offsetof(nxt_router_app_conf_t, limits_value), 1163 }, 1164 1165 { 1166 nxt_string("processes"), 1167 NXT_CONF_MAP_INT32, 1168 offsetof(nxt_router_app_conf_t, processes), 1169 }, 1170 1171 { 1172 nxt_string("processes"), 1173 NXT_CONF_MAP_PTR, 1174 offsetof(nxt_router_app_conf_t, processes_value), 1175 }, 1176 1177 { 1178 nxt_string("targets"), 1179 NXT_CONF_MAP_PTR, 1180 offsetof(nxt_router_app_conf_t, targets_value), 1181 }, 1182}; 1183 1184 1185static nxt_conf_map_t nxt_router_app_limits_conf[] = { 1186 { 1187 nxt_string("timeout"), 1188 NXT_CONF_MAP_MSEC, 1189 offsetof(nxt_router_app_conf_t, timeout), 1190 }, 1191 1192 { 1193 nxt_string("requests"), 1194 NXT_CONF_MAP_INT32, 1195 offsetof(nxt_router_app_conf_t, requests), 1196 }, 1197}; 1198 1199 1200static nxt_conf_map_t nxt_router_app_processes_conf[] = { 1201 { 1202 nxt_string("spare"), 1203 NXT_CONF_MAP_INT32, 1204 offsetof(nxt_router_app_conf_t, spare_processes), 1205 }, 1206 1207 { 1208 nxt_string("max"), 1209 NXT_CONF_MAP_INT32, 1210 offsetof(nxt_router_app_conf_t, max_processes), 1211 }, 1212 1213 { 1214 nxt_string("idle_timeout"), 1215 NXT_CONF_MAP_MSEC, 1216 offsetof(nxt_router_app_conf_t, idle_timeout), 1217 }, 1218}; 1219 1220 1221static nxt_conf_map_t nxt_router_listener_conf[] = { 1222 { 1223 nxt_string("pass"), 1224 NXT_CONF_MAP_STR_COPY, 1225 offsetof(nxt_router_listener_conf_t, pass), 1226 }, 1227 1228 { 1229 nxt_string("application"), 1230 NXT_CONF_MAP_STR_COPY, 1231 offsetof(nxt_router_listener_conf_t, application), 1232 }, 1233}; 1234 1235 1236static nxt_conf_map_t nxt_router_http_conf[] = { 1237 { 1238 nxt_string("header_buffer_size"), 1239 NXT_CONF_MAP_SIZE, 1240 offsetof(nxt_socket_conf_t, header_buffer_size), 1241 }, 1242 1243 { 1244 nxt_string("large_header_buffer_size"), 1245 NXT_CONF_MAP_SIZE, 1246 offsetof(nxt_socket_conf_t, large_header_buffer_size), 1247 }, 1248 1249 { 1250 nxt_string("large_header_buffers"), 1251 NXT_CONF_MAP_SIZE, 1252 offsetof(nxt_socket_conf_t, large_header_buffers), 1253 }, 1254 1255 { 1256 nxt_string("body_buffer_size"), 1257 NXT_CONF_MAP_SIZE, 1258 offsetof(nxt_socket_conf_t, body_buffer_size), 1259 }, 1260 1261 { 1262 nxt_string("max_body_size"), 1263 NXT_CONF_MAP_SIZE, 1264 offsetof(nxt_socket_conf_t, max_body_size), 1265 }, 1266 1267 { 1268 nxt_string("idle_timeout"), 1269 NXT_CONF_MAP_MSEC, 1270 offsetof(nxt_socket_conf_t, idle_timeout), 1271 }, 1272 1273 { 1274 nxt_string("header_read_timeout"), 1275 NXT_CONF_MAP_MSEC, 1276 offsetof(nxt_socket_conf_t, header_read_timeout), 1277 }, 1278 1279 { 1280 nxt_string("body_read_timeout"), 1281 NXT_CONF_MAP_MSEC, 1282 offsetof(nxt_socket_conf_t, body_read_timeout), 1283 }, 1284 1285 { 1286 nxt_string("send_timeout"), 1287 NXT_CONF_MAP_MSEC, 1288 offsetof(nxt_socket_conf_t, send_timeout), 1289 }, 1290 1291 { 1292 nxt_string("body_temp_path"), 1293 NXT_CONF_MAP_STR, 1294 offsetof(nxt_socket_conf_t, body_temp_path), 1295 }, 1296 1297 { 1298 nxt_string("discard_unsafe_fields"), 1299 NXT_CONF_MAP_INT8, 1300 offsetof(nxt_socket_conf_t, discard_unsafe_fields), 1301 }, 1302}; 1303 1304 1305static nxt_conf_map_t nxt_router_websocket_conf[] = { 1306 { 1307 nxt_string("max_frame_size"), 1308 NXT_CONF_MAP_SIZE, 1309 offsetof(nxt_websocket_conf_t, max_frame_size), 1310 }, 1311 1312 { 1313 nxt_string("read_timeout"), 1314 NXT_CONF_MAP_MSEC, 1315 offsetof(nxt_websocket_conf_t, read_timeout), 1316 }, 1317 1318 { 1319 nxt_string("keepalive_interval"), 1320 NXT_CONF_MAP_MSEC, 1321 offsetof(nxt_websocket_conf_t, keepalive_interval), 1322 }, 1323 1324}; 1325 1326 1327static nxt_int_t 1328nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1329 u_char *start, u_char *end) 1330{ 1331 u_char *p; 1332 size_t size; 1333 nxt_mp_t *mp, *app_mp; 1334 uint32_t next, next_target; 1335 nxt_int_t ret; 1336 nxt_str_t name, path, target; 1337 nxt_app_t *app, *prev; 1338 nxt_str_t *t, *s, *targets; 1339 nxt_uint_t n, i; 1340 nxt_port_t *port; 1341 nxt_router_t *router; 1342 nxt_app_joint_t *app_joint; 1343#if (NXT_TLS) 1344 nxt_tls_init_t *tls_init; 1345 nxt_conf_value_t *certificate; 1346#endif 1347 nxt_conf_value_t *conf, *http, *value, *websocket; 1348 nxt_conf_value_t *applications, *application; 1349 nxt_conf_value_t *listeners, *listener; 1350 nxt_conf_value_t *routes_conf, *static_conf; 1351 nxt_socket_conf_t *skcf; 1352 nxt_http_routes_t *routes; 1353 nxt_event_engine_t *engine; 1354 nxt_app_lang_module_t *lang; 1355 nxt_router_app_conf_t apcf; 1356 nxt_router_access_log_t *access_log; 1357 nxt_router_listener_conf_t lscf; 1358 1359 static nxt_str_t http_path = nxt_string("/settings/http"); 1360 static nxt_str_t applications_path = nxt_string("/applications"); 1361 static nxt_str_t listeners_path = nxt_string("/listeners"); 1362 static nxt_str_t routes_path = nxt_string("/routes"); 1363 static nxt_str_t access_log_path = nxt_string("/access_log"); 1364#if (NXT_TLS) 1365 static nxt_str_t certificate_path = nxt_string("/tls/certificate"); 1366 static nxt_str_t conf_commands_path = nxt_string("/tls/conf_commands"); 1367 static nxt_str_t conf_cache_path = nxt_string("/tls/session/cache_size"); 1368 static nxt_str_t conf_timeout_path = nxt_string("/tls/session/timeout"); 1369#endif 1370 static nxt_str_t static_path = nxt_string("/settings/http/static"); 1371 static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); 1372 1373 conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); 1374 if (conf == NULL) { 1375 nxt_alert(task, "configuration parsing error"); 1376 return NXT_ERROR; 1377 } 1378 1379 mp = tmcf->router_conf->mem_pool; 1380 1381 ret = nxt_conf_map_object(mp, conf, nxt_router_conf, 1382 nxt_nitems(nxt_router_conf), tmcf->router_conf); 1383 if (ret != NXT_OK) { 1384 nxt_alert(task, "root map error"); 1385 return NXT_ERROR; 1386 } 1387 1388 if (tmcf->router_conf->threads == 0) { 1389 tmcf->router_conf->threads = nxt_ncpu; 1390 } 1391 1392 static_conf = nxt_conf_get_path(conf, &static_path); 1393 1394 ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf); 1395 if (nxt_slow_path(ret != NXT_OK)) { 1396 return NXT_ERROR; 1397 } 1398 1399 router = tmcf->router_conf->router; 1400 1401 applications = nxt_conf_get_path(conf, &applications_path); 1402 1403 if (applications != NULL) { 1404 next = 0; 1405 1406 for ( ;; ) { 1407 application = nxt_conf_next_object_member(applications, 1408 &name, &next); 1409 if (application == NULL) { 1410 break; 1411 } 1412 1413 nxt_debug(task, "application \"%V\"", &name); 1414 1415 size = nxt_conf_json_length(application, NULL); 1416 1417 app_mp = nxt_mp_create(4096, 128, 1024, 64); 1418 if (nxt_slow_path(app_mp == NULL)) { 1419 goto fail; 1420 } 1421 1422 app = nxt_mp_get(app_mp, sizeof(nxt_app_t) + name.length + size); 1423 if (app == NULL) { 1424 goto app_fail; 1425 } 1426 1427 nxt_memzero(app, sizeof(nxt_app_t)); 1428 1429 app->mem_pool = app_mp; 1430 1431 app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 1432 app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) 1433 + name.length); 1434 1435 p = nxt_conf_json_print(app->conf.start, application, NULL); 1436 app->conf.length = p - app->conf.start; 1437 1438 nxt_assert(app->conf.length <= size); 1439 1440 nxt_debug(task, "application conf \"%V\"", &app->conf); 1441 1442 prev = nxt_router_app_find(&router->apps, &name); 1443 1444 if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 1445 nxt_mp_destroy(app_mp); 1446 1447 nxt_queue_remove(&prev->link); 1448 nxt_queue_insert_tail(&tmcf->previous, &prev->link); 1449 1450 ret = nxt_router_apps_hash_add(tmcf->router_conf, prev); 1451 if (nxt_slow_path(ret != NXT_OK)) { 1452 goto fail; 1453 } 1454 1455 continue; 1456 } 1457 1458 apcf.processes = 1; 1459 apcf.max_processes = 1; 1460 apcf.spare_processes = 0; 1461 apcf.timeout = 0; 1462 apcf.idle_timeout = 15000; 1463 apcf.requests = 0; 1464 apcf.limits_value = NULL; 1465 apcf.processes_value = NULL; 1466 apcf.targets_value = NULL; 1467 1468 app_joint = nxt_malloc(sizeof(nxt_app_joint_t)); 1469 if (nxt_slow_path(app_joint == NULL)) { 1470 goto app_fail; 1471 } 1472 1473 nxt_memzero(app_joint, sizeof(nxt_app_joint_t)); 1474 1475 ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, 1476 nxt_nitems(nxt_router_app_conf), &apcf); 1477 if (ret != NXT_OK) { 1478 nxt_alert(task, "application map error"); 1479 goto app_fail; 1480 } 1481 1482 if (apcf.limits_value != NULL) { 1483 1484 if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) { 1485 nxt_alert(task, "application limits is not object"); 1486 goto app_fail; 1487 } 1488 1489 ret = nxt_conf_map_object(mp, apcf.limits_value, 1490 nxt_router_app_limits_conf, 1491 nxt_nitems(nxt_router_app_limits_conf), 1492 &apcf); 1493 if (ret != NXT_OK) { 1494 nxt_alert(task, "application limits map error"); 1495 goto app_fail; 1496 } 1497 } 1498 1499 if (apcf.processes_value != NULL 1500 && nxt_conf_type(apcf.processes_value) == NXT_CONF_OBJECT) 1501 { 1502 ret = nxt_conf_map_object(mp, apcf.processes_value, 1503 nxt_router_app_processes_conf, 1504 nxt_nitems(nxt_router_app_processes_conf), 1505 &apcf); 1506 if (ret != NXT_OK) { 1507 nxt_alert(task, "application processes map error"); 1508 goto app_fail; 1509 } 1510 1511 } else { 1512 apcf.max_processes = apcf.processes; 1513 apcf.spare_processes = apcf.processes; 1514 } 1515 1516 if (apcf.targets_value != NULL) { 1517 n = nxt_conf_object_members_count(apcf.targets_value); 1518 1519 targets = nxt_mp_get(app_mp, sizeof(nxt_str_t) * n); 1520 if (nxt_slow_path(targets == NULL)) { 1521 goto app_fail; 1522 } 1523 1524 next_target = 0; 1525 1526 for (i = 0; i < n; i++) { 1527 (void) nxt_conf_next_object_member(apcf.targets_value, 1528 &target, &next_target); 1529 1530 s = nxt_str_dup(app_mp, &targets[i], &target); 1531 if (nxt_slow_path(s == NULL)) { 1532 goto app_fail; 1533 } 1534 } 1535 1536 } else { 1537 targets = NULL; 1538 } 1539 1540 nxt_debug(task, "application type: %V", &apcf.type); 1541 nxt_debug(task, "application processes: %D", apcf.processes); 1542 nxt_debug(task, "application request timeout: %M", apcf.timeout); 1543 nxt_debug(task, "application requests: %D", apcf.requests); 1544 1545 lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); 1546 1547 if (lang == NULL) { 1548 nxt_alert(task, "unknown application type: \"%V\"", &apcf.type); 1549 goto app_fail; 1550 } 1551 1552 nxt_debug(task, "application language module: \"%s\"", lang->file); 1553 1554 ret = nxt_thread_mutex_create(&app->mutex); 1555 if (ret != NXT_OK) { 1556 goto app_fail; 1557 } 1558 1559 nxt_queue_init(&app->ports); 1560 nxt_queue_init(&app->spare_ports); 1561 nxt_queue_init(&app->idle_ports); 1562 nxt_queue_init(&app->ack_waiting_req); 1563 1564 app->name.length = name.length; 1565 nxt_memcpy(app->name.start, name.start, name.length); 1566 1567 app->type = lang->type; 1568 app->max_processes = apcf.max_processes; 1569 app->spare_processes = apcf.spare_processes; 1570 app->max_pending_processes = apcf.spare_processes 1571 ? apcf.spare_processes : 1; 1572 app->timeout = apcf.timeout; 1573 app->idle_timeout = apcf.idle_timeout; 1574 app->max_requests = apcf.requests; 1575 1576 app->targets = targets; 1577 1578 engine = task->thread->engine; 1579 1580 app->engine = engine; 1581 1582 app->adjust_idle_work.handler = nxt_router_adjust_idle_timer; 1583 app->adjust_idle_work.task = &engine->task; 1584 app->adjust_idle_work.obj = app; 1585 1586 nxt_queue_insert_tail(&tmcf->apps, &app->link); 1587 1588 ret = nxt_router_apps_hash_add(tmcf->router_conf, app); 1589 if (nxt_slow_path(ret != NXT_OK)) { 1590 goto app_fail; 1591 } 1592 1593 nxt_router_app_use(task, app, 1); 1594 1595 app->joint = app_joint; 1596 1597 app_joint->use_count = 1; 1598 app_joint->app = app; 1599 1600 app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS; 1601 app_joint->idle_timer.work_queue = &engine->fast_work_queue; 1602 app_joint->idle_timer.handler = nxt_router_app_idle_timeout; 1603 app_joint->idle_timer.task = &engine->task; 1604 app_joint->idle_timer.log = app_joint->idle_timer.task->log; 1605 1606 app_joint->free_app_work.handler = nxt_router_free_app; 1607 app_joint->free_app_work.task = &engine->task; 1608 app_joint->free_app_work.obj = app_joint; 1609
| 900nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, 901 void *data) 902{ 903 union { 904 nxt_pid_t removed_pid; 905 void *data; 906 } u; 907 908 u.data = data; 909 910 nxt_port_rpc_remove_peer(task, port, u.removed_pid); 911} 912 913 914static void 915nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 916{ 917 nxt_event_engine_t *engine; 918 919 nxt_port_remove_pid_handler(task, msg); 920 921 nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) 922 { 923 if (nxt_fast_path(engine->port != NULL)) { 924 nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid, 925 msg->u.data); 926 } 927 } 928 nxt_queue_loop; 929 930 if (msg->port_msg.stream == 0) { 931 return; 932 } 933 934 msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 935 936 nxt_port_rpc_handler(task, msg); 937} 938 939 940static nxt_router_temp_conf_t * 941nxt_router_temp_conf(nxt_task_t *task) 942{ 943 nxt_mp_t *mp, *tmp; 944 nxt_router_conf_t *rtcf; 945 nxt_router_temp_conf_t *tmcf; 946 947 mp = nxt_mp_create(1024, 128, 256, 32); 948 if (nxt_slow_path(mp == NULL)) { 949 return NULL; 950 } 951 952 rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 953 if (nxt_slow_path(rtcf == NULL)) { 954 goto fail; 955 } 956 957 rtcf->mem_pool = mp; 958 959 tmp = nxt_mp_create(1024, 128, 256, 32); 960 if (nxt_slow_path(tmp == NULL)) { 961 goto fail; 962 } 963 964 tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 965 if (nxt_slow_path(tmcf == NULL)) { 966 goto temp_fail; 967 } 968 969 tmcf->mem_pool = tmp; 970 tmcf->router_conf = rtcf; 971 tmcf->count = 1; 972 tmcf->engine = task->thread->engine; 973 974 tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 975 sizeof(nxt_router_engine_conf_t)); 976 if (nxt_slow_path(tmcf->engines == NULL)) { 977 goto temp_fail; 978 } 979 980 nxt_queue_init(&creating_sockets); 981 nxt_queue_init(&pending_sockets); 982 nxt_queue_init(&updating_sockets); 983 nxt_queue_init(&keeping_sockets); 984 nxt_queue_init(&deleting_sockets); 985 986#if (NXT_TLS) 987 nxt_queue_init(&tmcf->tls); 988#endif 989 990 nxt_queue_init(&tmcf->apps); 991 nxt_queue_init(&tmcf->previous); 992 993 return tmcf; 994 995temp_fail: 996 997 nxt_mp_destroy(tmp); 998 999fail: 1000 1001 nxt_mp_destroy(mp); 1002 1003 return NULL; 1004} 1005 1006 1007nxt_inline nxt_bool_t 1008nxt_router_app_can_start(nxt_app_t *app) 1009{ 1010 return app->processes + app->pending_processes < app->max_processes 1011 && app->pending_processes < app->max_pending_processes; 1012} 1013 1014 1015nxt_inline nxt_bool_t 1016nxt_router_app_need_start(nxt_app_t *app) 1017{ 1018 return (app->active_requests 1019 > app->port_hash_count + app->pending_processes) 1020 || (app->spare_processes 1021 > app->idle_processes + app->pending_processes); 1022} 1023 1024 1025static void 1026nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) 1027{ 1028 nxt_int_t ret; 1029 nxt_app_t *app; 1030 nxt_router_t *router; 1031 nxt_runtime_t *rt; 1032 nxt_queue_link_t *qlk; 1033 nxt_socket_conf_t *skcf; 1034 nxt_router_conf_t *rtcf; 1035 nxt_router_temp_conf_t *tmcf; 1036 const nxt_event_interface_t *interface; 1037#if (NXT_TLS) 1038 nxt_router_tlssock_t *tls; 1039#endif 1040 1041 tmcf = obj; 1042 1043 qlk = nxt_queue_first(&pending_sockets); 1044 1045 if (qlk != nxt_queue_tail(&pending_sockets)) { 1046 nxt_queue_remove(qlk); 1047 nxt_queue_insert_tail(&creating_sockets, qlk); 1048 1049 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1050 1051 nxt_router_listen_socket_rpc_create(task, tmcf, skcf); 1052 1053 return; 1054 } 1055 1056#if (NXT_TLS) 1057 qlk = nxt_queue_last(&tmcf->tls); 1058 1059 if (qlk != nxt_queue_head(&tmcf->tls)) { 1060 nxt_queue_remove(qlk); 1061 1062 tls = nxt_queue_link_data(qlk, nxt_router_tlssock_t, link); 1063 1064 nxt_cert_store_get(task, &tls->name, tmcf->mem_pool, 1065 nxt_router_tls_rpc_handler, tls); 1066 return; 1067 } 1068#endif 1069 1070 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1071 1072 if (nxt_router_app_need_start(app)) { 1073 nxt_router_app_rpc_create(task, tmcf, app); 1074 return; 1075 } 1076 1077 } nxt_queue_loop; 1078 1079 rtcf = tmcf->router_conf; 1080 1081 if (rtcf->access_log != NULL && rtcf->access_log->fd == -1) { 1082 nxt_router_access_log_open(task, tmcf); 1083 return; 1084 } 1085 1086 rt = task->thread->runtime; 1087 1088 interface = nxt_service_get(rt->services, "engine", NULL); 1089 1090 router = rtcf->router; 1091 1092 ret = nxt_router_engines_create(task, router, tmcf, interface); 1093 if (nxt_slow_path(ret != NXT_OK)) { 1094 goto fail; 1095 } 1096 1097 ret = nxt_router_threads_create(task, rt, tmcf); 1098 if (nxt_slow_path(ret != NXT_OK)) { 1099 goto fail; 1100 } 1101 1102 nxt_router_apps_sort(task, router, tmcf); 1103 1104 nxt_router_apps_hash_use(task, rtcf, 1); 1105 1106 nxt_router_engines_post(router, tmcf); 1107 1108 nxt_queue_add(&router->sockets, &updating_sockets); 1109 nxt_queue_add(&router->sockets, &creating_sockets); 1110 1111 router->access_log = rtcf->access_log; 1112 1113 nxt_router_conf_ready(task, tmcf); 1114 1115 return; 1116 1117fail: 1118 1119 nxt_router_conf_error(task, tmcf); 1120 1121 return; 1122} 1123 1124 1125static void 1126nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 1127{ 1128 nxt_joint_job_t *job; 1129 1130 job = obj; 1131 1132 nxt_router_conf_ready(task, job->tmcf); 1133} 1134 1135 1136static void 1137nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1138{ 1139 uint32_t count; 1140 nxt_router_conf_t *rtcf; 1141 nxt_thread_spinlock_t *lock; 1142 1143 nxt_debug(task, "temp conf %p count: %D", tmcf, tmcf->count); 1144 1145 if (--tmcf->count > 0) { 1146 return; 1147 } 1148 1149 nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); 1150 1151 rtcf = tmcf->router_conf; 1152 1153 lock = &rtcf->router->lock; 1154 1155 nxt_thread_spin_lock(lock); 1156 1157 count = rtcf->count; 1158 1159 nxt_thread_spin_unlock(lock); 1160 1161 nxt_debug(task, "rtcf %p: %D", rtcf, count); 1162 1163 if (count == 0) { 1164 nxt_router_apps_hash_use(task, rtcf, -1); 1165 1166 nxt_router_access_log_release(task, lock, rtcf->access_log); 1167 1168 nxt_mp_destroy(rtcf->mem_pool); 1169 } 1170 1171 nxt_mp_release(tmcf->mem_pool); 1172} 1173 1174 1175static void 1176nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1177{ 1178 nxt_app_t *app; 1179 nxt_queue_t new_socket_confs; 1180 nxt_socket_t s; 1181 nxt_router_t *router; 1182 nxt_queue_link_t *qlk; 1183 nxt_socket_conf_t *skcf; 1184 nxt_router_conf_t *rtcf; 1185 1186 nxt_alert(task, "failed to apply new conf"); 1187 1188 for (qlk = nxt_queue_first(&creating_sockets); 1189 qlk != nxt_queue_tail(&creating_sockets); 1190 qlk = nxt_queue_next(qlk)) 1191 { 1192 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1193 s = skcf->listen->socket; 1194 1195 if (s != -1) { 1196 nxt_socket_close(task, s); 1197 } 1198 1199 nxt_free(skcf->listen); 1200 } 1201 1202 nxt_queue_init(&new_socket_confs); 1203 nxt_queue_add(&new_socket_confs, &updating_sockets); 1204 nxt_queue_add(&new_socket_confs, &pending_sockets); 1205 nxt_queue_add(&new_socket_confs, &creating_sockets); 1206 1207 rtcf = tmcf->router_conf; 1208 1209 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1210 1211 nxt_router_app_unlink(task, app); 1212 1213 } nxt_queue_loop; 1214 1215 router = rtcf->router; 1216 1217 nxt_queue_add(&router->sockets, &keeping_sockets); 1218 nxt_queue_add(&router->sockets, &deleting_sockets); 1219 1220 nxt_queue_add(&router->apps, &tmcf->previous); 1221 1222 // TODO: new engines and threads 1223 1224 nxt_router_access_log_release(task, &router->lock, rtcf->access_log); 1225 1226 nxt_mp_destroy(rtcf->mem_pool); 1227 1228 nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); 1229 1230 nxt_mp_release(tmcf->mem_pool); 1231} 1232 1233 1234static void 1235nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1236 nxt_port_msg_type_t type) 1237{ 1238 nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); 1239 1240 nxt_port_use(task, tmcf->port, -1); 1241 1242 tmcf->port = NULL; 1243} 1244 1245 1246static nxt_conf_map_t nxt_router_conf[] = { 1247 { 1248 nxt_string("listeners_threads"), 1249 NXT_CONF_MAP_INT32, 1250 offsetof(nxt_router_conf_t, threads), 1251 }, 1252}; 1253 1254 1255static nxt_conf_map_t nxt_router_app_conf[] = { 1256 { 1257 nxt_string("type"), 1258 NXT_CONF_MAP_STR, 1259 offsetof(nxt_router_app_conf_t, type), 1260 }, 1261 1262 { 1263 nxt_string("limits"), 1264 NXT_CONF_MAP_PTR, 1265 offsetof(nxt_router_app_conf_t, limits_value), 1266 }, 1267 1268 { 1269 nxt_string("processes"), 1270 NXT_CONF_MAP_INT32, 1271 offsetof(nxt_router_app_conf_t, processes), 1272 }, 1273 1274 { 1275 nxt_string("processes"), 1276 NXT_CONF_MAP_PTR, 1277 offsetof(nxt_router_app_conf_t, processes_value), 1278 }, 1279 1280 { 1281 nxt_string("targets"), 1282 NXT_CONF_MAP_PTR, 1283 offsetof(nxt_router_app_conf_t, targets_value), 1284 }, 1285}; 1286 1287 1288static nxt_conf_map_t nxt_router_app_limits_conf[] = { 1289 { 1290 nxt_string("timeout"), 1291 NXT_CONF_MAP_MSEC, 1292 offsetof(nxt_router_app_conf_t, timeout), 1293 }, 1294 1295 { 1296 nxt_string("requests"), 1297 NXT_CONF_MAP_INT32, 1298 offsetof(nxt_router_app_conf_t, requests), 1299 }, 1300}; 1301 1302 1303static nxt_conf_map_t nxt_router_app_processes_conf[] = { 1304 { 1305 nxt_string("spare"), 1306 NXT_CONF_MAP_INT32, 1307 offsetof(nxt_router_app_conf_t, spare_processes), 1308 }, 1309 1310 { 1311 nxt_string("max"), 1312 NXT_CONF_MAP_INT32, 1313 offsetof(nxt_router_app_conf_t, max_processes), 1314 }, 1315 1316 { 1317 nxt_string("idle_timeout"), 1318 NXT_CONF_MAP_MSEC, 1319 offsetof(nxt_router_app_conf_t, idle_timeout), 1320 }, 1321}; 1322 1323 1324static nxt_conf_map_t nxt_router_listener_conf[] = { 1325 { 1326 nxt_string("pass"), 1327 NXT_CONF_MAP_STR_COPY, 1328 offsetof(nxt_router_listener_conf_t, pass), 1329 }, 1330 1331 { 1332 nxt_string("application"), 1333 NXT_CONF_MAP_STR_COPY, 1334 offsetof(nxt_router_listener_conf_t, application), 1335 }, 1336}; 1337 1338 1339static nxt_conf_map_t nxt_router_http_conf[] = { 1340 { 1341 nxt_string("header_buffer_size"), 1342 NXT_CONF_MAP_SIZE, 1343 offsetof(nxt_socket_conf_t, header_buffer_size), 1344 }, 1345 1346 { 1347 nxt_string("large_header_buffer_size"), 1348 NXT_CONF_MAP_SIZE, 1349 offsetof(nxt_socket_conf_t, large_header_buffer_size), 1350 }, 1351 1352 { 1353 nxt_string("large_header_buffers"), 1354 NXT_CONF_MAP_SIZE, 1355 offsetof(nxt_socket_conf_t, large_header_buffers), 1356 }, 1357 1358 { 1359 nxt_string("body_buffer_size"), 1360 NXT_CONF_MAP_SIZE, 1361 offsetof(nxt_socket_conf_t, body_buffer_size), 1362 }, 1363 1364 { 1365 nxt_string("max_body_size"), 1366 NXT_CONF_MAP_SIZE, 1367 offsetof(nxt_socket_conf_t, max_body_size), 1368 }, 1369 1370 { 1371 nxt_string("idle_timeout"), 1372 NXT_CONF_MAP_MSEC, 1373 offsetof(nxt_socket_conf_t, idle_timeout), 1374 }, 1375 1376 { 1377 nxt_string("header_read_timeout"), 1378 NXT_CONF_MAP_MSEC, 1379 offsetof(nxt_socket_conf_t, header_read_timeout), 1380 }, 1381 1382 { 1383 nxt_string("body_read_timeout"), 1384 NXT_CONF_MAP_MSEC, 1385 offsetof(nxt_socket_conf_t, body_read_timeout), 1386 }, 1387 1388 { 1389 nxt_string("send_timeout"), 1390 NXT_CONF_MAP_MSEC, 1391 offsetof(nxt_socket_conf_t, send_timeout), 1392 }, 1393 1394 { 1395 nxt_string("body_temp_path"), 1396 NXT_CONF_MAP_STR, 1397 offsetof(nxt_socket_conf_t, body_temp_path), 1398 }, 1399 1400 { 1401 nxt_string("discard_unsafe_fields"), 1402 NXT_CONF_MAP_INT8, 1403 offsetof(nxt_socket_conf_t, discard_unsafe_fields), 1404 }, 1405}; 1406 1407 1408static nxt_conf_map_t nxt_router_websocket_conf[] = { 1409 { 1410 nxt_string("max_frame_size"), 1411 NXT_CONF_MAP_SIZE, 1412 offsetof(nxt_websocket_conf_t, max_frame_size), 1413 }, 1414 1415 { 1416 nxt_string("read_timeout"), 1417 NXT_CONF_MAP_MSEC, 1418 offsetof(nxt_websocket_conf_t, read_timeout), 1419 }, 1420 1421 { 1422 nxt_string("keepalive_interval"), 1423 NXT_CONF_MAP_MSEC, 1424 offsetof(nxt_websocket_conf_t, keepalive_interval), 1425 }, 1426 1427}; 1428 1429 1430static nxt_int_t 1431nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1432 u_char *start, u_char *end) 1433{ 1434 u_char *p; 1435 size_t size; 1436 nxt_mp_t *mp, *app_mp; 1437 uint32_t next, next_target; 1438 nxt_int_t ret; 1439 nxt_str_t name, path, target; 1440 nxt_app_t *app, *prev; 1441 nxt_str_t *t, *s, *targets; 1442 nxt_uint_t n, i; 1443 nxt_port_t *port; 1444 nxt_router_t *router; 1445 nxt_app_joint_t *app_joint; 1446#if (NXT_TLS) 1447 nxt_tls_init_t *tls_init; 1448 nxt_conf_value_t *certificate; 1449#endif 1450 nxt_conf_value_t *conf, *http, *value, *websocket; 1451 nxt_conf_value_t *applications, *application; 1452 nxt_conf_value_t *listeners, *listener; 1453 nxt_conf_value_t *routes_conf, *static_conf; 1454 nxt_socket_conf_t *skcf; 1455 nxt_http_routes_t *routes; 1456 nxt_event_engine_t *engine; 1457 nxt_app_lang_module_t *lang; 1458 nxt_router_app_conf_t apcf; 1459 nxt_router_access_log_t *access_log; 1460 nxt_router_listener_conf_t lscf; 1461 1462 static nxt_str_t http_path = nxt_string("/settings/http"); 1463 static nxt_str_t applications_path = nxt_string("/applications"); 1464 static nxt_str_t listeners_path = nxt_string("/listeners"); 1465 static nxt_str_t routes_path = nxt_string("/routes"); 1466 static nxt_str_t access_log_path = nxt_string("/access_log"); 1467#if (NXT_TLS) 1468 static nxt_str_t certificate_path = nxt_string("/tls/certificate"); 1469 static nxt_str_t conf_commands_path = nxt_string("/tls/conf_commands"); 1470 static nxt_str_t conf_cache_path = nxt_string("/tls/session/cache_size"); 1471 static nxt_str_t conf_timeout_path = nxt_string("/tls/session/timeout"); 1472#endif 1473 static nxt_str_t static_path = nxt_string("/settings/http/static"); 1474 static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); 1475 1476 conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); 1477 if (conf == NULL) { 1478 nxt_alert(task, "configuration parsing error"); 1479 return NXT_ERROR; 1480 } 1481 1482 mp = tmcf->router_conf->mem_pool; 1483 1484 ret = nxt_conf_map_object(mp, conf, nxt_router_conf, 1485 nxt_nitems(nxt_router_conf), tmcf->router_conf); 1486 if (ret != NXT_OK) { 1487 nxt_alert(task, "root map error"); 1488 return NXT_ERROR; 1489 } 1490 1491 if (tmcf->router_conf->threads == 0) { 1492 tmcf->router_conf->threads = nxt_ncpu; 1493 } 1494 1495 static_conf = nxt_conf_get_path(conf, &static_path); 1496 1497 ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf); 1498 if (nxt_slow_path(ret != NXT_OK)) { 1499 return NXT_ERROR; 1500 } 1501 1502 router = tmcf->router_conf->router; 1503 1504 applications = nxt_conf_get_path(conf, &applications_path); 1505 1506 if (applications != NULL) { 1507 next = 0; 1508 1509 for ( ;; ) { 1510 application = nxt_conf_next_object_member(applications, 1511 &name, &next); 1512 if (application == NULL) { 1513 break; 1514 } 1515 1516 nxt_debug(task, "application \"%V\"", &name); 1517 1518 size = nxt_conf_json_length(application, NULL); 1519 1520 app_mp = nxt_mp_create(4096, 128, 1024, 64); 1521 if (nxt_slow_path(app_mp == NULL)) { 1522 goto fail; 1523 } 1524 1525 app = nxt_mp_get(app_mp, sizeof(nxt_app_t) + name.length + size); 1526 if (app == NULL) { 1527 goto app_fail; 1528 } 1529 1530 nxt_memzero(app, sizeof(nxt_app_t)); 1531 1532 app->mem_pool = app_mp; 1533 1534 app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 1535 app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) 1536 + name.length); 1537 1538 p = nxt_conf_json_print(app->conf.start, application, NULL); 1539 app->conf.length = p - app->conf.start; 1540 1541 nxt_assert(app->conf.length <= size); 1542 1543 nxt_debug(task, "application conf \"%V\"", &app->conf); 1544 1545 prev = nxt_router_app_find(&router->apps, &name); 1546 1547 if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 1548 nxt_mp_destroy(app_mp); 1549 1550 nxt_queue_remove(&prev->link); 1551 nxt_queue_insert_tail(&tmcf->previous, &prev->link); 1552 1553 ret = nxt_router_apps_hash_add(tmcf->router_conf, prev); 1554 if (nxt_slow_path(ret != NXT_OK)) { 1555 goto fail; 1556 } 1557 1558 continue; 1559 } 1560 1561 apcf.processes = 1; 1562 apcf.max_processes = 1; 1563 apcf.spare_processes = 0; 1564 apcf.timeout = 0; 1565 apcf.idle_timeout = 15000; 1566 apcf.requests = 0; 1567 apcf.limits_value = NULL; 1568 apcf.processes_value = NULL; 1569 apcf.targets_value = NULL; 1570 1571 app_joint = nxt_malloc(sizeof(nxt_app_joint_t)); 1572 if (nxt_slow_path(app_joint == NULL)) { 1573 goto app_fail; 1574 } 1575 1576 nxt_memzero(app_joint, sizeof(nxt_app_joint_t)); 1577 1578 ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, 1579 nxt_nitems(nxt_router_app_conf), &apcf); 1580 if (ret != NXT_OK) { 1581 nxt_alert(task, "application map error"); 1582 goto app_fail; 1583 } 1584 1585 if (apcf.limits_value != NULL) { 1586 1587 if (nxt_conf_type(apcf.limits_value) != NXT_CONF_OBJECT) { 1588 nxt_alert(task, "application limits is not object"); 1589 goto app_fail; 1590 } 1591 1592 ret = nxt_conf_map_object(mp, apcf.limits_value, 1593 nxt_router_app_limits_conf, 1594 nxt_nitems(nxt_router_app_limits_conf), 1595 &apcf); 1596 if (ret != NXT_OK) { 1597 nxt_alert(task, "application limits map error"); 1598 goto app_fail; 1599 } 1600 } 1601 1602 if (apcf.processes_value != NULL 1603 && nxt_conf_type(apcf.processes_value) == NXT_CONF_OBJECT) 1604 { 1605 ret = nxt_conf_map_object(mp, apcf.processes_value, 1606 nxt_router_app_processes_conf, 1607 nxt_nitems(nxt_router_app_processes_conf), 1608 &apcf); 1609 if (ret != NXT_OK) { 1610 nxt_alert(task, "application processes map error"); 1611 goto app_fail; 1612 } 1613 1614 } else { 1615 apcf.max_processes = apcf.processes; 1616 apcf.spare_processes = apcf.processes; 1617 } 1618 1619 if (apcf.targets_value != NULL) { 1620 n = nxt_conf_object_members_count(apcf.targets_value); 1621 1622 targets = nxt_mp_get(app_mp, sizeof(nxt_str_t) * n); 1623 if (nxt_slow_path(targets == NULL)) { 1624 goto app_fail; 1625 } 1626 1627 next_target = 0; 1628 1629 for (i = 0; i < n; i++) { 1630 (void) nxt_conf_next_object_member(apcf.targets_value, 1631 &target, &next_target); 1632 1633 s = nxt_str_dup(app_mp, &targets[i], &target); 1634 if (nxt_slow_path(s == NULL)) { 1635 goto app_fail; 1636 } 1637 } 1638 1639 } else { 1640 targets = NULL; 1641 } 1642 1643 nxt_debug(task, "application type: %V", &apcf.type); 1644 nxt_debug(task, "application processes: %D", apcf.processes); 1645 nxt_debug(task, "application request timeout: %M", apcf.timeout); 1646 nxt_debug(task, "application requests: %D", apcf.requests); 1647 1648 lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); 1649 1650 if (lang == NULL) { 1651 nxt_alert(task, "unknown application type: \"%V\"", &apcf.type); 1652 goto app_fail; 1653 } 1654 1655 nxt_debug(task, "application language module: \"%s\"", lang->file); 1656 1657 ret = nxt_thread_mutex_create(&app->mutex); 1658 if (ret != NXT_OK) { 1659 goto app_fail; 1660 } 1661 1662 nxt_queue_init(&app->ports); 1663 nxt_queue_init(&app->spare_ports); 1664 nxt_queue_init(&app->idle_ports); 1665 nxt_queue_init(&app->ack_waiting_req); 1666 1667 app->name.length = name.length; 1668 nxt_memcpy(app->name.start, name.start, name.length); 1669 1670 app->type = lang->type; 1671 app->max_processes = apcf.max_processes; 1672 app->spare_processes = apcf.spare_processes; 1673 app->max_pending_processes = apcf.spare_processes 1674 ? apcf.spare_processes : 1; 1675 app->timeout = apcf.timeout; 1676 app->idle_timeout = apcf.idle_timeout; 1677 app->max_requests = apcf.requests; 1678 1679 app->targets = targets; 1680 1681 engine = task->thread->engine; 1682 1683 app->engine = engine; 1684 1685 app->adjust_idle_work.handler = nxt_router_adjust_idle_timer; 1686 app->adjust_idle_work.task = &engine->task; 1687 app->adjust_idle_work.obj = app; 1688 1689 nxt_queue_insert_tail(&tmcf->apps, &app->link); 1690 1691 ret = nxt_router_apps_hash_add(tmcf->router_conf, app); 1692 if (nxt_slow_path(ret != NXT_OK)) { 1693 goto app_fail; 1694 } 1695 1696 nxt_router_app_use(task, app, 1); 1697 1698 app->joint = app_joint; 1699 1700 app_joint->use_count = 1; 1701 app_joint->app = app; 1702 1703 app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS; 1704 app_joint->idle_timer.work_queue = &engine->fast_work_queue; 1705 app_joint->idle_timer.handler = nxt_router_app_idle_timeout; 1706 app_joint->idle_timer.task = &engine->task; 1707 app_joint->idle_timer.log = app_joint->idle_timer.task->log; 1708 1709 app_joint->free_app_work.handler = nxt_router_free_app; 1710 app_joint->free_app_work.task = &engine->task; 1711 app_joint->free_app_work.obj = app_joint; 1712
|
1610 port = nxt_port_new(task, (nxt_port_id_t) -1, nxt_pid,
| 1713 port = nxt_port_new(task, NXT_SHARED_PORT_ID, nxt_pid,
|
1611 NXT_PROCESS_APP); 1612 if (nxt_slow_path(port == NULL)) { 1613 return NXT_ERROR; 1614 } 1615 1616 ret = nxt_port_socket_init(task, port, 0); 1617 if (nxt_slow_path(ret != NXT_OK)) { 1618 nxt_port_use(task, port, -1); 1619 return NXT_ERROR; 1620 } 1621 1622 ret = nxt_router_app_queue_init(task, port); 1623 if (nxt_slow_path(ret != NXT_OK)) { 1624 nxt_port_write_close(port); 1625 nxt_port_read_close(port); 1626 nxt_port_use(task, port, -1); 1627 return NXT_ERROR; 1628 } 1629 1630 nxt_port_write_enable(task, port); 1631 port->app = app; 1632 1633 app->shared_port = port; 1634 1635 nxt_thread_mutex_create(&app->outgoing.mutex); 1636 } 1637 } 1638 1639 routes_conf = nxt_conf_get_path(conf, &routes_path); 1640 if (nxt_fast_path(routes_conf != NULL)) { 1641 routes = nxt_http_routes_create(task, tmcf, routes_conf); 1642 if (nxt_slow_path(routes == NULL)) { 1643 return NXT_ERROR; 1644 } 1645 tmcf->router_conf->routes = routes; 1646 } 1647 1648 ret = nxt_upstreams_create(task, tmcf, conf); 1649 if (nxt_slow_path(ret != NXT_OK)) { 1650 return ret; 1651 } 1652 1653 http = nxt_conf_get_path(conf, &http_path); 1654#if 0 1655 if (http == NULL) { 1656 nxt_alert(task, "no \"http\" block"); 1657 return NXT_ERROR; 1658 } 1659#endif 1660 1661 websocket = nxt_conf_get_path(conf, &websocket_path); 1662 1663 listeners = nxt_conf_get_path(conf, &listeners_path); 1664 1665 if (listeners != NULL) { 1666 next = 0; 1667 1668 for ( ;; ) { 1669 listener = nxt_conf_next_object_member(listeners, &name, &next); 1670 if (listener == NULL) { 1671 break; 1672 } 1673 1674 skcf = nxt_router_socket_conf(task, tmcf, &name); 1675 if (skcf == NULL) { 1676 goto fail; 1677 } 1678 1679 nxt_memzero(&lscf, sizeof(lscf)); 1680 1681 ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, 1682 nxt_nitems(nxt_router_listener_conf), 1683 &lscf); 1684 if (ret != NXT_OK) { 1685 nxt_alert(task, "listener map error"); 1686 goto fail; 1687 } 1688 1689 nxt_debug(task, "application: %V", &lscf.application); 1690 1691 // STUB, default values if http block is not defined. 1692 skcf->header_buffer_size = 2048; 1693 skcf->large_header_buffer_size = 8192; 1694 skcf->large_header_buffers = 4; 1695 skcf->discard_unsafe_fields = 1; 1696 skcf->body_buffer_size = 16 * 1024; 1697 skcf->max_body_size = 8 * 1024 * 1024; 1698 skcf->proxy_header_buffer_size = 64 * 1024; 1699 skcf->proxy_buffer_size = 4096; 1700 skcf->proxy_buffers = 256; 1701 skcf->idle_timeout = 180 * 1000; 1702 skcf->header_read_timeout = 30 * 1000; 1703 skcf->body_read_timeout = 30 * 1000; 1704 skcf->send_timeout = 30 * 1000; 1705 skcf->proxy_timeout = 60 * 1000; 1706 skcf->proxy_send_timeout = 30 * 1000; 1707 skcf->proxy_read_timeout = 30 * 1000; 1708 1709 skcf->websocket_conf.max_frame_size = 1024 * 1024; 1710 skcf->websocket_conf.read_timeout = 60 * 1000; 1711 skcf->websocket_conf.keepalive_interval = 30 * 1000; 1712 1713 nxt_str_null(&skcf->body_temp_path); 1714 1715 if (http != NULL) { 1716 ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, 1717 nxt_nitems(nxt_router_http_conf), 1718 skcf); 1719 if (ret != NXT_OK) { 1720 nxt_alert(task, "http map error"); 1721 goto fail; 1722 } 1723 } 1724 1725 if (websocket != NULL) { 1726 ret = nxt_conf_map_object(mp, websocket, 1727 nxt_router_websocket_conf, 1728 nxt_nitems(nxt_router_websocket_conf), 1729 &skcf->websocket_conf); 1730 if (ret != NXT_OK) { 1731 nxt_alert(task, "websocket map error"); 1732 goto fail; 1733 } 1734 } 1735 1736 t = &skcf->body_temp_path; 1737 1738 if (t->length == 0) { 1739 t->start = (u_char *) task->thread->runtime->tmp; 1740 t->length = nxt_strlen(t->start); 1741 } 1742 1743#if (NXT_TLS) 1744 certificate = nxt_conf_get_path(listener, &certificate_path); 1745 1746 if (certificate != NULL) { 1747 tls_init = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_tls_init_t)); 1748 if (nxt_slow_path(tls_init == NULL)) { 1749 return NXT_ERROR; 1750 } 1751 1752 tls_init->cache_size = 0; 1753 tls_init->timeout = 300; 1754 1755 value = nxt_conf_get_path(listener, &conf_cache_path); 1756 if (value != NULL) { 1757 tls_init->cache_size = nxt_conf_get_number(value); 1758 } 1759 1760 value = nxt_conf_get_path(listener, &conf_timeout_path); 1761 if (value != NULL) { 1762 tls_init->timeout = nxt_conf_get_number(value); 1763 } 1764 1765 tls_init->conf_cmds = nxt_conf_get_path(listener, 1766 &conf_commands_path); 1767 1768 if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) { 1769 n = nxt_conf_array_elements_count(certificate); 1770 1771 for (i = 0; i < n; i++) { 1772 value = nxt_conf_get_array_element(certificate, i); 1773 1774 nxt_assert(value != NULL); 1775 1776 ret = nxt_router_conf_tls_insert(tmcf, value, skcf, 1777 tls_init, i == 0); 1778 if (nxt_slow_path(ret != NXT_OK)) { 1779 goto fail; 1780 } 1781 } 1782 1783 } else { 1784 /* NXT_CONF_STRING */ 1785 ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf, 1786 tls_init, 1); 1787 if (nxt_slow_path(ret != NXT_OK)) { 1788 goto fail; 1789 } 1790 } 1791 } 1792#endif 1793 1794 skcf->listen->handler = nxt_http_conn_init; 1795 skcf->router_conf = tmcf->router_conf; 1796 skcf->router_conf->count++; 1797 1798 if (lscf.pass.length != 0) { 1799 skcf->action = nxt_http_action_create(task, tmcf, &lscf.pass); 1800 1801 /* COMPATIBILITY: listener application. */ 1802 } else if (lscf.application.length > 0) { 1803 skcf->action = nxt_http_pass_application(task, 1804 tmcf->router_conf, 1805 &lscf.application); 1806 } 1807 1808 if (nxt_slow_path(skcf->action == NULL)) { 1809 goto fail; 1810 } 1811 } 1812 } 1813 1814 ret = nxt_http_routes_resolve(task, tmcf); 1815 if (nxt_slow_path(ret != NXT_OK)) { 1816 goto fail; 1817 } 1818 1819 value = nxt_conf_get_path(conf, &access_log_path); 1820 1821 if (value != NULL) { 1822 nxt_conf_get_string(value, &path); 1823 1824 access_log = router->access_log; 1825 1826 if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { 1827 nxt_thread_spin_lock(&router->lock); 1828 access_log->count++; 1829 nxt_thread_spin_unlock(&router->lock); 1830 1831 } else { 1832 access_log = nxt_malloc(sizeof(nxt_router_access_log_t) 1833 + path.length); 1834 if (access_log == NULL) { 1835 nxt_alert(task, "failed to allocate access log structure"); 1836 goto fail; 1837 } 1838 1839 access_log->fd = -1; 1840 access_log->handler = &nxt_router_access_log_writer; 1841 access_log->count = 1; 1842 1843 access_log->path.length = path.length; 1844 access_log->path.start = (u_char *) access_log 1845 + sizeof(nxt_router_access_log_t); 1846 1847 nxt_memcpy(access_log->path.start, path.start, path.length); 1848 } 1849 1850 tmcf->router_conf->access_log = access_log; 1851 } 1852 1853 nxt_queue_add(&deleting_sockets, &router->sockets); 1854 nxt_queue_init(&router->sockets); 1855 1856 return NXT_OK; 1857 1858app_fail: 1859 1860 nxt_mp_destroy(app_mp); 1861 1862fail: 1863 1864 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1865 1866 nxt_queue_remove(&app->link); 1867 nxt_thread_mutex_destroy(&app->mutex); 1868 nxt_mp_destroy(app->mem_pool); 1869 1870 } nxt_queue_loop; 1871 1872 return NXT_ERROR; 1873} 1874 1875 1876#if (NXT_TLS) 1877 1878static nxt_int_t 1879nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 1880 nxt_conf_value_t *value, nxt_socket_conf_t *skcf, 1881 nxt_tls_init_t *tls_init, nxt_bool_t last) 1882{ 1883 nxt_router_tlssock_t *tls; 1884 1885 tls = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_tlssock_t)); 1886 if (nxt_slow_path(tls == NULL)) { 1887 return NXT_ERROR; 1888 } 1889 1890 tls->tls_init = tls_init; 1891 tls->socket_conf = skcf; 1892 tls->temp_conf = tmcf; 1893 tls->last = last; 1894 nxt_conf_get_string(value, &tls->name); 1895 1896 nxt_queue_insert_tail(&tmcf->tls, &tls->link); 1897 1898 return NXT_OK; 1899} 1900 1901#endif 1902 1903 1904static nxt_int_t 1905nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, 1906 nxt_conf_value_t *conf) 1907{ 1908 uint32_t next, i; 1909 nxt_mp_t *mp; 1910 nxt_str_t *type, exten, str; 1911 nxt_int_t ret; 1912 nxt_uint_t exts; 1913 nxt_conf_value_t *mtypes_conf, *ext_conf, *value; 1914 1915 static nxt_str_t mtypes_path = nxt_string("/mime_types"); 1916 1917 mp = rtcf->mem_pool; 1918 1919 ret = nxt_http_static_mtypes_init(mp, &rtcf->mtypes_hash); 1920 if (nxt_slow_path(ret != NXT_OK)) { 1921 return NXT_ERROR; 1922 } 1923 1924 if (conf == NULL) { 1925 return NXT_OK; 1926 } 1927 1928 mtypes_conf = nxt_conf_get_path(conf, &mtypes_path); 1929 1930 if (mtypes_conf != NULL) { 1931 next = 0; 1932 1933 for ( ;; ) { 1934 ext_conf = nxt_conf_next_object_member(mtypes_conf, &str, &next); 1935 1936 if (ext_conf == NULL) { 1937 break; 1938 } 1939 1940 type = nxt_str_dup(mp, NULL, &str); 1941 if (nxt_slow_path(type == NULL)) { 1942 return NXT_ERROR; 1943 } 1944 1945 if (nxt_conf_type(ext_conf) == NXT_CONF_STRING) { 1946 nxt_conf_get_string(ext_conf, &str); 1947 1948 if (nxt_slow_path(nxt_str_dup(mp, &exten, &str) == NULL)) { 1949 return NXT_ERROR; 1950 } 1951 1952 ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, 1953 &exten, type); 1954 if (nxt_slow_path(ret != NXT_OK)) { 1955 return NXT_ERROR; 1956 } 1957 1958 continue; 1959 } 1960 1961 exts = nxt_conf_array_elements_count(ext_conf); 1962 1963 for (i = 0; i < exts; i++) { 1964 value = nxt_conf_get_array_element(ext_conf, i); 1965 1966 nxt_conf_get_string(value, &str); 1967 1968 if (nxt_slow_path(nxt_str_dup(mp, &exten, &str) == NULL)) { 1969 return NXT_ERROR; 1970 } 1971 1972 ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, 1973 &exten, type); 1974 if (nxt_slow_path(ret != NXT_OK)) { 1975 return NXT_ERROR; 1976 } 1977 } 1978 } 1979 } 1980 1981 return NXT_OK; 1982} 1983 1984 1985static nxt_app_t * 1986nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 1987{ 1988 nxt_app_t *app; 1989 1990 nxt_queue_each(app, queue, nxt_app_t, link) { 1991 1992 if (nxt_strstr_eq(name, &app->name)) { 1993 return app; 1994 } 1995 1996 } nxt_queue_loop; 1997 1998 return NULL; 1999} 2000 2001 2002static nxt_int_t 2003nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port) 2004{ 2005 void *mem; 2006 nxt_int_t fd; 2007 2008 fd = nxt_shm_open(task, sizeof(nxt_app_queue_t)); 2009 if (nxt_slow_path(fd == -1)) { 2010 return NXT_ERROR; 2011 } 2012 2013 mem = nxt_mem_mmap(NULL, sizeof(nxt_app_queue_t), 2014 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2015 if (nxt_slow_path(mem == MAP_FAILED)) { 2016 nxt_fd_close(fd); 2017 2018 return NXT_ERROR; 2019 } 2020 2021 nxt_app_queue_init(mem); 2022 2023 port->queue_fd = fd; 2024 port->queue = mem; 2025 2026 return NXT_OK; 2027} 2028 2029 2030static nxt_int_t 2031nxt_router_port_queue_init(nxt_task_t *task, nxt_port_t *port) 2032{ 2033 void *mem; 2034 nxt_int_t fd; 2035 2036 fd = nxt_shm_open(task, sizeof(nxt_port_queue_t)); 2037 if (nxt_slow_path(fd == -1)) { 2038 return NXT_ERROR; 2039 } 2040 2041 mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), 2042 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2043 if (nxt_slow_path(mem == MAP_FAILED)) { 2044 nxt_fd_close(fd); 2045 2046 return NXT_ERROR; 2047 } 2048 2049 nxt_port_queue_init(mem); 2050 2051 port->queue_fd = fd; 2052 port->queue = mem; 2053 2054 return NXT_OK; 2055} 2056 2057 2058static nxt_int_t 2059nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, nxt_fd_t fd) 2060{ 2061 void *mem; 2062 2063 nxt_assert(fd != -1); 2064 2065 mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), 2066 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2067 if (nxt_slow_path(mem == MAP_FAILED)) { 2068 2069 return NXT_ERROR; 2070 } 2071 2072 port->queue = mem; 2073 2074 return NXT_OK; 2075} 2076 2077 2078static const nxt_lvlhsh_proto_t nxt_router_apps_hash_proto nxt_aligned(64) = { 2079 NXT_LVLHSH_DEFAULT, 2080 nxt_router_apps_hash_test, 2081 nxt_mp_lvlhsh_alloc, 2082 nxt_mp_lvlhsh_free, 2083}; 2084 2085 2086static nxt_int_t 2087nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 2088{ 2089 nxt_app_t *app; 2090 2091 app = data; 2092 2093 return nxt_strstr_eq(&lhq->key, &app->name) ? NXT_OK : NXT_DECLINED; 2094} 2095 2096 2097static nxt_int_t 2098nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, nxt_app_t *app) 2099{ 2100 nxt_lvlhsh_query_t lhq; 2101 2102 lhq.key_hash = nxt_djb_hash(app->name.start, app->name.length); 2103 lhq.replace = 0; 2104 lhq.key = app->name; 2105 lhq.value = app; 2106 lhq.proto = &nxt_router_apps_hash_proto; 2107 lhq.pool = rtcf->mem_pool; 2108 2109 switch (nxt_lvlhsh_insert(&rtcf->apps_hash, &lhq)) { 2110 2111 case NXT_OK: 2112 return NXT_OK; 2113 2114 case NXT_DECLINED: 2115 nxt_thread_log_alert("router app hash adding failed: " 2116 "\"%V\" is already in hash", &lhq.key); 2117 /* Fall through. */ 2118 default: 2119 return NXT_ERROR; 2120 } 2121} 2122 2123 2124static nxt_app_t * 2125nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, nxt_str_t *name) 2126{ 2127 nxt_lvlhsh_query_t lhq; 2128 2129 lhq.key_hash = nxt_djb_hash(name->start, name->length); 2130 lhq.key = *name; 2131 lhq.proto = &nxt_router_apps_hash_proto; 2132 2133 if (nxt_lvlhsh_find(&rtcf->apps_hash, &lhq) != NXT_OK) { 2134 return NULL; 2135 } 2136 2137 return lhq.value; 2138} 2139 2140 2141static void 2142nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, int i) 2143{ 2144 nxt_app_t *app; 2145 nxt_lvlhsh_each_t lhe; 2146 2147 nxt_lvlhsh_each_init(&lhe, &nxt_router_apps_hash_proto); 2148 2149 for ( ;; ) { 2150 app = nxt_lvlhsh_each(&rtcf->apps_hash, &lhe); 2151 2152 if (app == NULL) { 2153 break; 2154 } 2155 2156 nxt_router_app_use(task, app, i); 2157 } 2158} 2159 2160 2161typedef struct { 2162 nxt_app_t *app; 2163 nxt_int_t target; 2164} nxt_http_app_conf_t; 2165 2166 2167nxt_int_t 2168nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, 2169 nxt_str_t *target, nxt_http_action_t *action) 2170{ 2171 nxt_app_t *app; 2172 nxt_str_t *targets; 2173 nxt_uint_t i; 2174 nxt_http_app_conf_t *conf; 2175 2176 app = nxt_router_apps_hash_get(rtcf, name); 2177 if (app == NULL) { 2178 return NXT_DECLINED; 2179 } 2180 2181 conf = nxt_mp_get(rtcf->mem_pool, sizeof(nxt_http_app_conf_t)); 2182 if (nxt_slow_path(conf == NULL)) { 2183 return NXT_ERROR; 2184 } 2185 2186 action->handler = nxt_http_application_handler; 2187 action->u.conf = conf; 2188 2189 conf->app = app; 2190 2191 if (target != NULL && target->length != 0) { 2192 targets = app->targets; 2193 2194 for (i = 0; !nxt_strstr_eq(target, &targets[i]); i++); 2195 2196 conf->target = i; 2197 2198 } else { 2199 conf->target = 0; 2200 } 2201 2202 return NXT_OK; 2203} 2204 2205 2206static nxt_socket_conf_t * 2207nxt_router_socket_conf(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 2208 nxt_str_t *name) 2209{ 2210 size_t size; 2211 nxt_int_t ret; 2212 nxt_bool_t wildcard; 2213 nxt_sockaddr_t *sa; 2214 nxt_socket_conf_t *skcf; 2215 nxt_listen_socket_t *ls; 2216 2217 sa = nxt_sockaddr_parse(tmcf->mem_pool, name); 2218 if (nxt_slow_path(sa == NULL)) { 2219 nxt_alert(task, "invalid listener \"%V\"", name); 2220 return NULL; 2221 } 2222 2223 sa->type = SOCK_STREAM; 2224 2225 nxt_debug(task, "router listener: \"%*s\"", 2226 (size_t) sa->length, nxt_sockaddr_start(sa)); 2227 2228 skcf = nxt_mp_zget(tmcf->router_conf->mem_pool, sizeof(nxt_socket_conf_t)); 2229 if (nxt_slow_path(skcf == NULL)) { 2230 return NULL; 2231 } 2232 2233 size = nxt_sockaddr_size(sa); 2234 2235 ret = nxt_router_listen_socket_find(tmcf, skcf, sa); 2236 2237 if (ret != NXT_OK) { 2238 2239 ls = nxt_zalloc(sizeof(nxt_listen_socket_t) + size); 2240 if (nxt_slow_path(ls == NULL)) { 2241 return NULL; 2242 } 2243 2244 skcf->listen = ls; 2245 2246 ls->sockaddr = nxt_pointer_to(ls, sizeof(nxt_listen_socket_t)); 2247 nxt_memcpy(ls->sockaddr, sa, size); 2248 2249 nxt_listen_socket_remote_size(ls); 2250 2251 ls->socket = -1; 2252 ls->backlog = NXT_LISTEN_BACKLOG; 2253 ls->flags = NXT_NONBLOCK; 2254 ls->read_after_accept = 1; 2255 } 2256 2257 switch (sa->u.sockaddr.sa_family) { 2258#if (NXT_HAVE_UNIX_DOMAIN) 2259 case AF_UNIX: 2260 wildcard = 0; 2261 break; 2262#endif 2263#if (NXT_INET6) 2264 case AF_INET6: 2265 wildcard = IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr); 2266 break; 2267#endif 2268 case AF_INET: 2269 default: 2270 wildcard = (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY); 2271 break; 2272 } 2273 2274 if (!wildcard) { 2275 skcf->sockaddr = nxt_mp_zget(tmcf->router_conf->mem_pool, size); 2276 if (nxt_slow_path(skcf->sockaddr == NULL)) { 2277 return NULL; 2278 } 2279 2280 nxt_memcpy(skcf->sockaddr, sa, size); 2281 } 2282 2283 return skcf; 2284} 2285 2286 2287static nxt_int_t 2288nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 2289 nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa) 2290{ 2291 nxt_router_t *router; 2292 nxt_queue_link_t *qlk; 2293 nxt_socket_conf_t *skcf; 2294 2295 router = tmcf->router_conf->router; 2296 2297 for (qlk = nxt_queue_first(&router->sockets); 2298 qlk != nxt_queue_tail(&router->sockets); 2299 qlk = nxt_queue_next(qlk)) 2300 { 2301 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 2302 2303 if (nxt_sockaddr_cmp(skcf->listen->sockaddr, sa)) { 2304 nskcf->listen = skcf->listen; 2305 2306 nxt_queue_remove(qlk); 2307 nxt_queue_insert_tail(&keeping_sockets, qlk); 2308 2309 nxt_queue_insert_tail(&updating_sockets, &nskcf->link); 2310 2311 return NXT_OK; 2312 } 2313 } 2314 2315 nxt_queue_insert_tail(&pending_sockets, &nskcf->link); 2316 2317 return NXT_DECLINED; 2318} 2319 2320 2321static void 2322nxt_router_listen_socket_rpc_create(nxt_task_t *task, 2323 nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf) 2324{ 2325 size_t size; 2326 uint32_t stream; 2327 nxt_int_t ret; 2328 nxt_buf_t *b; 2329 nxt_port_t *main_port, *router_port; 2330 nxt_runtime_t *rt; 2331 nxt_socket_rpc_t *rpc; 2332 2333 rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); 2334 if (rpc == NULL) { 2335 goto fail; 2336 } 2337 2338 rpc->socket_conf = skcf; 2339 rpc->temp_conf = tmcf; 2340 2341 size = nxt_sockaddr_size(skcf->listen->sockaddr); 2342 2343 b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2344 if (b == NULL) { 2345 goto fail; 2346 } 2347 2348 b->completion_handler = nxt_router_dummy_buf_completion; 2349 2350 b->mem.free = nxt_cpymem(b->mem.free, skcf->listen->sockaddr, size); 2351 2352 rt = task->thread->runtime; 2353 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2354 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2355 2356 stream = nxt_port_rpc_register_handler(task, router_port, 2357 nxt_router_listen_socket_ready, 2358 nxt_router_listen_socket_error, 2359 main_port->pid, rpc); 2360 if (nxt_slow_path(stream == 0)) { 2361 goto fail; 2362 } 2363 2364 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, 2365 stream, router_port->id, b); 2366 2367 if (nxt_slow_path(ret != NXT_OK)) { 2368 nxt_port_rpc_cancel(task, router_port, stream); 2369 goto fail; 2370 } 2371 2372 return; 2373 2374fail: 2375 2376 nxt_router_conf_error(task, tmcf); 2377} 2378 2379 2380static void 2381nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2382 void *data) 2383{ 2384 nxt_int_t ret; 2385 nxt_socket_t s; 2386 nxt_socket_rpc_t *rpc; 2387 2388 rpc = data; 2389 2390 s = msg->fd[0]; 2391 2392 ret = nxt_socket_nonblocking(task, s); 2393 if (nxt_slow_path(ret != NXT_OK)) { 2394 goto fail; 2395 } 2396 2397 nxt_socket_defer_accept(task, s, rpc->socket_conf->listen->sockaddr); 2398 2399 ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 2400 if (nxt_slow_path(ret != NXT_OK)) { 2401 goto fail; 2402 } 2403 2404 rpc->socket_conf->listen->socket = s; 2405 2406 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 2407 nxt_router_conf_apply, task, rpc->temp_conf, NULL); 2408 2409 return; 2410 2411fail: 2412 2413 nxt_socket_close(task, s); 2414 2415 nxt_router_conf_error(task, rpc->temp_conf); 2416} 2417 2418 2419static void 2420nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2421 void *data) 2422{ 2423 nxt_socket_rpc_t *rpc; 2424 nxt_router_temp_conf_t *tmcf; 2425 2426 rpc = data; 2427 tmcf = rpc->temp_conf; 2428 2429#if 0 2430 u_char *p; 2431 size_t size; 2432 uint8_t error; 2433 nxt_buf_t *in, *out; 2434 nxt_sockaddr_t *sa; 2435 2436 static nxt_str_t socket_errors[] = { 2437 nxt_string("ListenerSystem"), 2438 nxt_string("ListenerNoIPv6"), 2439 nxt_string("ListenerPort"), 2440 nxt_string("ListenerInUse"), 2441 nxt_string("ListenerNoAddress"), 2442 nxt_string("ListenerNoAccess"), 2443 nxt_string("ListenerPath"), 2444 }; 2445 2446 sa = rpc->socket_conf->listen->sockaddr; 2447 2448 in = nxt_buf_chk_make_plain(tmcf->mem_pool, msg->buf, msg->size); 2449 2450 if (nxt_slow_path(in == NULL)) { 2451 return; 2452 } 2453 2454 p = in->mem.pos; 2455 2456 error = *p++; 2457 2458 size = nxt_length("listen socket error: ") 2459 + nxt_length("{listener: \"\", code:\"\", message: \"\"}") 2460 + sa->length + socket_errors[error].length + (in->mem.free - p); 2461 2462 out = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2463 if (nxt_slow_path(out == NULL)) { 2464 return; 2465 } 2466 2467 out->mem.free = nxt_sprintf(out->mem.free, out->mem.end, 2468 "listen socket error: " 2469 "{listener: \"%*s\", code:\"%V\", message: \"%*s\"}", 2470 (size_t) sa->length, nxt_sockaddr_start(sa), 2471 &socket_errors[error], in->mem.free - p, p); 2472 2473 nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos); 2474#endif 2475 2476 nxt_router_conf_error(task, tmcf); 2477} 2478 2479 2480#if (NXT_TLS) 2481 2482static void 2483nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2484 void *data) 2485{ 2486 nxt_mp_t *mp; 2487 nxt_int_t ret; 2488 nxt_tls_conf_t *tlscf; 2489 nxt_router_tlssock_t *tls; 2490 nxt_tls_bundle_conf_t *bundle; 2491 nxt_router_temp_conf_t *tmcf; 2492 2493 nxt_debug(task, "tls rpc handler"); 2494 2495 tls = data; 2496 tmcf = tls->temp_conf; 2497 2498 if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { 2499 goto fail; 2500 } 2501 2502 mp = tmcf->router_conf->mem_pool; 2503 2504 if (tls->socket_conf->tls == NULL){ 2505 tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); 2506 if (nxt_slow_path(tlscf == NULL)) { 2507 goto fail; 2508 } 2509 2510 tlscf->no_wait_shutdown = 1; 2511 tls->socket_conf->tls = tlscf; 2512 2513 } else { 2514 tlscf = tls->socket_conf->tls; 2515 } 2516 2517 tls->tls_init->conf = tlscf; 2518 2519 bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t)); 2520 if (nxt_slow_path(bundle == NULL)) { 2521 goto fail; 2522 } 2523 2524 if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) { 2525 goto fail; 2526 } 2527 2528 bundle->chain_file = msg->fd[0]; 2529 bundle->next = tlscf->bundle; 2530 tlscf->bundle = bundle; 2531 2532 ret = task->thread->runtime->tls->server_init(task, mp, tls->tls_init, 2533 tls->last); 2534 if (nxt_slow_path(ret != NXT_OK)) { 2535 goto fail; 2536 } 2537 2538 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 2539 nxt_router_conf_apply, task, tmcf, NULL); 2540 return; 2541 2542fail: 2543 2544 nxt_router_conf_error(task, tmcf); 2545} 2546 2547#endif 2548 2549 2550static void 2551nxt_router_app_rpc_create(nxt_task_t *task, 2552 nxt_router_temp_conf_t *tmcf, nxt_app_t *app) 2553{ 2554 size_t size; 2555 uint32_t stream; 2556 nxt_int_t ret; 2557 nxt_buf_t *b; 2558 nxt_port_t *main_port, *router_port; 2559 nxt_runtime_t *rt; 2560 nxt_app_rpc_t *rpc; 2561 2562 rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_app_rpc_t)); 2563 if (rpc == NULL) { 2564 goto fail; 2565 } 2566 2567 rpc->app = app; 2568 rpc->temp_conf = tmcf; 2569 2570 nxt_debug(task, "app '%V' prefork", &app->name); 2571 2572 size = app->name.length + 1 + app->conf.length; 2573 2574 b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2575 if (nxt_slow_path(b == NULL)) { 2576 goto fail; 2577 } 2578 2579 b->completion_handler = nxt_router_dummy_buf_completion; 2580 2581 nxt_buf_cpystr(b, &app->name); 2582 *b->mem.free++ = '\0'; 2583 nxt_buf_cpystr(b, &app->conf); 2584 2585 rt = task->thread->runtime; 2586 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2587 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2588 2589 stream = nxt_port_rpc_register_handler(task, router_port, 2590 nxt_router_app_prefork_ready, 2591 nxt_router_app_prefork_error, 2592 -1, rpc); 2593 if (nxt_slow_path(stream == 0)) { 2594 goto fail; 2595 } 2596 2597 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS, 2598 -1, stream, router_port->id, b); 2599 2600 if (nxt_slow_path(ret != NXT_OK)) { 2601 nxt_port_rpc_cancel(task, router_port, stream); 2602 goto fail; 2603 } 2604 2605 app->pending_processes++; 2606 2607 return; 2608 2609fail: 2610 2611 nxt_router_conf_error(task, tmcf); 2612} 2613 2614 2615static void 2616nxt_router_app_prefork_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2617 void *data) 2618{ 2619 nxt_app_t *app; 2620 nxt_port_t *port; 2621 nxt_app_rpc_t *rpc; 2622 nxt_event_engine_t *engine; 2623 2624 rpc = data; 2625 app = rpc->app; 2626 2627 port = msg->u.new_port; 2628 2629 nxt_assert(port != NULL); 2630 nxt_assert(port->type == NXT_PROCESS_APP); 2631 nxt_assert(port->id == 0); 2632 2633 port->app = app; 2634 port->main_app_port = port; 2635 2636 app->pending_processes--; 2637 app->processes++; 2638 app->idle_processes++; 2639 2640 engine = task->thread->engine; 2641 2642 nxt_queue_insert_tail(&app->ports, &port->app_link); 2643 nxt_queue_insert_tail(&app->spare_ports, &port->idle_link); 2644 2645 nxt_debug(task, "app '%V' move new port %PI:%d to spare_ports", 2646 &app->name, port->pid, port->id); 2647 2648 nxt_port_hash_add(&app->port_hash, port); 2649 app->port_hash_count++; 2650 2651 port->idle_start = 0; 2652 2653 nxt_port_inc_use(port); 2654 2655 nxt_router_app_shared_port_send(task, port); 2656 2657 nxt_work_queue_add(&engine->fast_work_queue, 2658 nxt_router_conf_apply, task, rpc->temp_conf, NULL); 2659} 2660 2661 2662static void 2663nxt_router_app_prefork_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2664 void *data) 2665{ 2666 nxt_app_t *app; 2667 nxt_app_rpc_t *rpc; 2668 nxt_router_temp_conf_t *tmcf; 2669 2670 rpc = data; 2671 app = rpc->app; 2672 tmcf = rpc->temp_conf; 2673 2674 nxt_log(task, NXT_LOG_WARN, "failed to start application \"%V\"", 2675 &app->name); 2676 2677 app->pending_processes--; 2678 2679 nxt_router_conf_error(task, tmcf); 2680} 2681 2682 2683static nxt_int_t 2684nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 2685 nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 2686{ 2687 nxt_int_t ret; 2688 nxt_uint_t n, threads; 2689 nxt_queue_link_t *qlk; 2690 nxt_router_engine_conf_t *recf; 2691 2692 threads = tmcf->router_conf->threads; 2693 2694 tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 2695 sizeof(nxt_router_engine_conf_t)); 2696 if (nxt_slow_path(tmcf->engines == NULL)) { 2697 return NXT_ERROR; 2698 } 2699 2700 n = 0; 2701 2702 for (qlk = nxt_queue_first(&router->engines); 2703 qlk != nxt_queue_tail(&router->engines); 2704 qlk = nxt_queue_next(qlk)) 2705 { 2706 recf = nxt_array_zero_add(tmcf->engines); 2707 if (nxt_slow_path(recf == NULL)) { 2708 return NXT_ERROR; 2709 } 2710 2711 recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 2712 2713 if (n < threads) { 2714 recf->action = NXT_ROUTER_ENGINE_KEEP; 2715 ret = nxt_router_engine_conf_update(tmcf, recf); 2716 2717 } else { 2718 recf->action = NXT_ROUTER_ENGINE_DELETE; 2719 ret = nxt_router_engine_conf_delete(tmcf, recf); 2720 } 2721 2722 if (nxt_slow_path(ret != NXT_OK)) { 2723 return ret; 2724 } 2725 2726 n++; 2727 } 2728 2729 tmcf->new_threads = n; 2730 2731 while (n < threads) { 2732 recf = nxt_array_zero_add(tmcf->engines); 2733 if (nxt_slow_path(recf == NULL)) { 2734 return NXT_ERROR; 2735 } 2736 2737 recf->action = NXT_ROUTER_ENGINE_ADD; 2738 2739 recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 2740 if (nxt_slow_path(recf->engine == NULL)) { 2741 return NXT_ERROR; 2742 } 2743 2744 ret = nxt_router_engine_conf_create(tmcf, recf); 2745 if (nxt_slow_path(ret != NXT_OK)) { 2746 return ret; 2747 } 2748 2749 n++; 2750 } 2751 2752 return NXT_OK; 2753} 2754 2755 2756static nxt_int_t 2757nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 2758 nxt_router_engine_conf_t *recf) 2759{ 2760 nxt_int_t ret; 2761 2762 ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, 2763 nxt_router_listen_socket_create); 2764 if (nxt_slow_path(ret != NXT_OK)) { 2765 return ret; 2766 } 2767 2768 ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, 2769 nxt_router_listen_socket_create); 2770 if (nxt_slow_path(ret != NXT_OK)) { 2771 return ret; 2772 } 2773 2774 return ret; 2775} 2776 2777 2778static nxt_int_t 2779nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 2780 nxt_router_engine_conf_t *recf) 2781{ 2782 nxt_int_t ret; 2783 2784 ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, 2785 nxt_router_listen_socket_create); 2786 if (nxt_slow_path(ret != NXT_OK)) { 2787 return ret; 2788 } 2789 2790 ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, 2791 nxt_router_listen_socket_update); 2792 if (nxt_slow_path(ret != NXT_OK)) { 2793 return ret; 2794 } 2795 2796 ret = nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); 2797 if (nxt_slow_path(ret != NXT_OK)) { 2798 return ret; 2799 } 2800 2801 return ret; 2802} 2803 2804 2805static nxt_int_t 2806nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 2807 nxt_router_engine_conf_t *recf) 2808{ 2809 nxt_int_t ret; 2810 2811 ret = nxt_router_engine_quit(tmcf, recf); 2812 if (nxt_slow_path(ret != NXT_OK)) { 2813 return ret; 2814 } 2815 2816 ret = nxt_router_engine_joints_delete(tmcf, recf, &updating_sockets); 2817 if (nxt_slow_path(ret != NXT_OK)) { 2818 return ret; 2819 } 2820 2821 return nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); 2822} 2823 2824 2825static nxt_int_t 2826nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 2827 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 2828 nxt_work_handler_t handler) 2829{ 2830 nxt_int_t ret; 2831 nxt_joint_job_t *job; 2832 nxt_queue_link_t *qlk; 2833 nxt_socket_conf_t *skcf; 2834 nxt_socket_conf_joint_t *joint; 2835 2836 for (qlk = nxt_queue_first(sockets); 2837 qlk != nxt_queue_tail(sockets); 2838 qlk = nxt_queue_next(qlk)) 2839 { 2840 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 2841 if (nxt_slow_path(job == NULL)) { 2842 return NXT_ERROR; 2843 } 2844 2845 job->work.next = recf->jobs; 2846 recf->jobs = &job->work; 2847 2848 job->task = tmcf->engine->task; 2849 job->work.handler = handler; 2850 job->work.task = &job->task; 2851 job->work.obj = job; 2852 job->tmcf = tmcf; 2853 2854 tmcf->count++; 2855 2856 joint = nxt_mp_alloc(tmcf->router_conf->mem_pool, 2857 sizeof(nxt_socket_conf_joint_t)); 2858 if (nxt_slow_path(joint == NULL)) { 2859 return NXT_ERROR; 2860 } 2861 2862 job->work.data = joint; 2863 2864 ret = nxt_upstreams_joint_create(tmcf, &joint->upstreams); 2865 if (nxt_slow_path(ret != NXT_OK)) { 2866 return ret; 2867 } 2868 2869 joint->count = 1; 2870 2871 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 2872 skcf->count++; 2873 joint->socket_conf = skcf; 2874 2875 joint->engine = recf->engine; 2876 } 2877 2878 return NXT_OK; 2879} 2880 2881 2882static nxt_int_t 2883nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 2884 nxt_router_engine_conf_t *recf) 2885{ 2886 nxt_joint_job_t *job; 2887 2888 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 2889 if (nxt_slow_path(job == NULL)) { 2890 return NXT_ERROR; 2891 } 2892 2893 job->work.next = recf->jobs; 2894 recf->jobs = &job->work; 2895 2896 job->task = tmcf->engine->task; 2897 job->work.handler = nxt_router_worker_thread_quit; 2898 job->work.task = &job->task; 2899 job->work.obj = NULL; 2900 job->work.data = NULL; 2901 job->tmcf = NULL; 2902 2903 return NXT_OK; 2904} 2905 2906 2907static nxt_int_t 2908nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 2909 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 2910{ 2911 nxt_joint_job_t *job; 2912 nxt_queue_link_t *qlk; 2913 2914 for (qlk = nxt_queue_first(sockets); 2915 qlk != nxt_queue_tail(sockets); 2916 qlk = nxt_queue_next(qlk)) 2917 { 2918 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 2919 if (nxt_slow_path(job == NULL)) { 2920 return NXT_ERROR; 2921 } 2922 2923 job->work.next = recf->jobs; 2924 recf->jobs = &job->work; 2925 2926 job->task = tmcf->engine->task; 2927 job->work.handler = nxt_router_listen_socket_delete; 2928 job->work.task = &job->task; 2929 job->work.obj = job; 2930 job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 2931 job->tmcf = tmcf; 2932 2933 tmcf->count++; 2934 } 2935 2936 return NXT_OK; 2937} 2938 2939 2940static nxt_int_t 2941nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 2942 nxt_router_temp_conf_t *tmcf) 2943{ 2944 nxt_int_t ret; 2945 nxt_uint_t i, threads; 2946 nxt_router_engine_conf_t *recf; 2947 2948 recf = tmcf->engines->elts; 2949 threads = tmcf->router_conf->threads; 2950 2951 for (i = tmcf->new_threads; i < threads; i++) { 2952 ret = nxt_router_thread_create(task, rt, recf[i].engine); 2953 if (nxt_slow_path(ret != NXT_OK)) { 2954 return ret; 2955 } 2956 } 2957 2958 return NXT_OK; 2959} 2960 2961 2962static nxt_int_t 2963nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 2964 nxt_event_engine_t *engine) 2965{ 2966 nxt_int_t ret; 2967 nxt_thread_link_t *link; 2968 nxt_thread_handle_t handle; 2969 2970 link = nxt_zalloc(sizeof(nxt_thread_link_t)); 2971 2972 if (nxt_slow_path(link == NULL)) { 2973 return NXT_ERROR; 2974 } 2975 2976 link->start = nxt_router_thread_start; 2977 link->engine = engine; 2978 link->work.handler = nxt_router_thread_exit_handler; 2979 link->work.task = task; 2980 link->work.data = link; 2981 2982 nxt_queue_insert_tail(&rt->engines, &engine->link); 2983 2984 ret = nxt_thread_create(&handle, link); 2985 2986 if (nxt_slow_path(ret != NXT_OK)) { 2987 nxt_queue_remove(&engine->link); 2988 } 2989 2990 return ret; 2991} 2992 2993 2994static void 2995nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 2996 nxt_router_temp_conf_t *tmcf) 2997{ 2998 nxt_app_t *app; 2999 3000 nxt_queue_each(app, &router->apps, nxt_app_t, link) { 3001 3002 nxt_router_app_unlink(task, app); 3003 3004 } nxt_queue_loop; 3005 3006 nxt_queue_add(&router->apps, &tmcf->previous); 3007 nxt_queue_add(&router->apps, &tmcf->apps); 3008} 3009 3010 3011static void 3012nxt_router_engines_post(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 3013{ 3014 nxt_uint_t n; 3015 nxt_event_engine_t *engine; 3016 nxt_router_engine_conf_t *recf; 3017 3018 recf = tmcf->engines->elts; 3019 3020 for (n = tmcf->engines->nelts; n != 0; n--) { 3021 engine = recf->engine; 3022 3023 switch (recf->action) { 3024 3025 case NXT_ROUTER_ENGINE_KEEP: 3026 break; 3027 3028 case NXT_ROUTER_ENGINE_ADD: 3029 nxt_queue_insert_tail(&router->engines, &engine->link0); 3030 break; 3031 3032 case NXT_ROUTER_ENGINE_DELETE: 3033 nxt_queue_remove(&engine->link0); 3034 break; 3035 } 3036 3037 nxt_router_engine_post(engine, recf->jobs); 3038 3039 recf++; 3040 } 3041} 3042 3043 3044static void 3045nxt_router_engine_post(nxt_event_engine_t *engine, nxt_work_t *jobs) 3046{ 3047 nxt_work_t *work, *next; 3048 3049 for (work = jobs; work != NULL; work = next) { 3050 next = work->next; 3051 work->next = NULL; 3052 3053 nxt_event_engine_post(engine, work); 3054 } 3055} 3056 3057 3058static nxt_port_handlers_t nxt_router_app_port_handlers = { 3059 .rpc_error = nxt_port_rpc_handler, 3060 .mmap = nxt_port_mmap_handler, 3061 .data = nxt_port_rpc_handler, 3062 .oosm = nxt_router_oosm_handler, 3063 .req_headers_ack = nxt_port_rpc_handler, 3064}; 3065 3066 3067static void 3068nxt_router_thread_start(void *data) 3069{ 3070 nxt_int_t ret; 3071 nxt_port_t *port; 3072 nxt_task_t *task; 3073 nxt_work_t *work; 3074 nxt_thread_t *thread; 3075 nxt_thread_link_t *link; 3076 nxt_event_engine_t *engine; 3077 3078 link = data; 3079 engine = link->engine; 3080 task = &engine->task; 3081 3082 thread = nxt_thread(); 3083 3084 nxt_event_engine_thread_adopt(engine); 3085 3086 /* STUB */ 3087 thread->runtime = engine->task.thread->runtime; 3088 3089 engine->task.thread = thread; 3090 engine->task.log = thread->log; 3091 thread->engine = engine; 3092 thread->task = &engine->task; 3093#if 0 3094 thread->fiber = &engine->fibers->fiber; 3095#endif 3096 3097 engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 3098 if (nxt_slow_path(engine->mem_pool == NULL)) { 3099 return; 3100 } 3101 3102 port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, 3103 NXT_PROCESS_ROUTER); 3104 if (nxt_slow_path(port == NULL)) { 3105 return; 3106 } 3107 3108 ret = nxt_port_socket_init(task, port, 0); 3109 if (nxt_slow_path(ret != NXT_OK)) { 3110 nxt_port_use(task, port, -1); 3111 return; 3112 } 3113 3114 ret = nxt_router_port_queue_init(task, port); 3115 if (nxt_slow_path(ret != NXT_OK)) { 3116 nxt_port_use(task, port, -1); 3117 return; 3118 } 3119 3120 engine->port = port; 3121 3122 nxt_port_enable(task, port, &nxt_router_app_port_handlers); 3123 3124 work = nxt_zalloc(sizeof(nxt_work_t)); 3125 if (nxt_slow_path(work == NULL)) { 3126 return; 3127 } 3128 3129 work->handler = nxt_router_rt_add_port; 3130 work->task = link->work.task; 3131 work->obj = work; 3132 work->data = port; 3133 3134 nxt_event_engine_post(link->work.task->thread->engine, work); 3135 3136 nxt_event_engine_start(engine); 3137} 3138 3139 3140static void 3141nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data) 3142{ 3143 nxt_int_t res; 3144 nxt_port_t *port; 3145 nxt_runtime_t *rt; 3146 3147 rt = task->thread->runtime; 3148 port = data; 3149 3150 nxt_free(obj); 3151 3152 res = nxt_port_hash_add(&rt->ports, port); 3153 3154 if (nxt_fast_path(res == NXT_OK)) { 3155 nxt_port_use(task, port, 1); 3156 } 3157} 3158 3159 3160static void 3161nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 3162{ 3163 nxt_joint_job_t *job; 3164 nxt_socket_conf_t *skcf; 3165 nxt_listen_event_t *lev; 3166 nxt_listen_socket_t *ls; 3167 nxt_thread_spinlock_t *lock; 3168 nxt_socket_conf_joint_t *joint; 3169 3170 job = obj; 3171 joint = data; 3172 3173 nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); 3174 3175 skcf = joint->socket_conf; 3176 ls = skcf->listen; 3177 3178 lev = nxt_listen_event(task, ls); 3179 if (nxt_slow_path(lev == NULL)) { 3180 nxt_router_listen_socket_release(task, skcf); 3181 return; 3182 } 3183 3184 lev->socket.data = joint; 3185 3186 lock = &skcf->router_conf->router->lock; 3187 3188 nxt_thread_spin_lock(lock); 3189 ls->count++; 3190 nxt_thread_spin_unlock(lock); 3191 3192 job->work.next = NULL; 3193 job->work.handler = nxt_router_conf_wait; 3194 3195 nxt_event_engine_post(job->tmcf->engine, &job->work); 3196} 3197 3198 3199nxt_inline nxt_listen_event_t * 3200nxt_router_listen_event(nxt_queue_t *listen_connections, 3201 nxt_socket_conf_t *skcf) 3202{ 3203 nxt_socket_t fd; 3204 nxt_queue_link_t *qlk; 3205 nxt_listen_event_t *lev; 3206 3207 fd = skcf->listen->socket; 3208 3209 for (qlk = nxt_queue_first(listen_connections); 3210 qlk != nxt_queue_tail(listen_connections); 3211 qlk = nxt_queue_next(qlk)) 3212 { 3213 lev = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 3214 3215 if (fd == lev->socket.fd) { 3216 return lev; 3217 } 3218 } 3219 3220 return NULL; 3221} 3222 3223 3224static void 3225nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 3226{ 3227 nxt_joint_job_t *job; 3228 nxt_event_engine_t *engine; 3229 nxt_listen_event_t *lev; 3230 nxt_socket_conf_joint_t *joint, *old; 3231 3232 job = obj; 3233 joint = data; 3234 3235 engine = task->thread->engine; 3236 3237 nxt_queue_insert_tail(&engine->joints, &joint->link); 3238 3239 lev = nxt_router_listen_event(&engine->listen_connections, 3240 joint->socket_conf); 3241 3242 old = lev->socket.data; 3243 lev->socket.data = joint; 3244 lev->listen = joint->socket_conf->listen; 3245 3246 job->work.next = NULL; 3247 job->work.handler = nxt_router_conf_wait; 3248 3249 nxt_event_engine_post(job->tmcf->engine, &job->work); 3250 3251 /* 3252 * The task is allocated from configuration temporary 3253 * memory pool so it can be freed after engine post operation. 3254 */ 3255 3256 nxt_router_conf_release(&engine->task, old); 3257} 3258 3259 3260static void 3261nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 3262{ 3263 nxt_socket_conf_t *skcf; 3264 nxt_listen_event_t *lev; 3265 nxt_event_engine_t *engine; 3266 nxt_socket_conf_joint_t *joint; 3267 3268 skcf = data; 3269 3270 engine = task->thread->engine; 3271 3272 lev = nxt_router_listen_event(&engine->listen_connections, skcf); 3273 3274 nxt_fd_event_delete(engine, &lev->socket); 3275 3276 nxt_debug(task, "engine %p: listen socket delete: %d", engine, 3277 lev->socket.fd); 3278 3279 joint = lev->socket.data; 3280 joint->close_job = obj; 3281 3282 lev->timer.handler = nxt_router_listen_socket_close; 3283 lev->timer.work_queue = &engine->fast_work_queue; 3284 3285 nxt_timer_add(engine, &lev->timer, 0); 3286} 3287 3288 3289static void 3290nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, void *data) 3291{ 3292 nxt_event_engine_t *engine; 3293 3294 nxt_debug(task, "router worker thread quit"); 3295 3296 engine = task->thread->engine; 3297 3298 engine->shutdown = 1; 3299 3300 if (nxt_queue_is_empty(&engine->joints)) { 3301 nxt_thread_exit(task->thread); 3302 } 3303} 3304 3305 3306static void 3307nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 3308{ 3309 nxt_timer_t *timer; 3310 nxt_joint_job_t *job; 3311 nxt_listen_event_t *lev; 3312 nxt_socket_conf_joint_t *joint; 3313 3314 timer = obj; 3315 lev = nxt_timer_data(timer, nxt_listen_event_t, timer); 3316 3317 nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, 3318 lev->socket.fd); 3319 3320 nxt_queue_remove(&lev->link); 3321 3322 joint = lev->socket.data; 3323 lev->socket.data = NULL; 3324 3325 /* 'task' refers to lev->task and we cannot use after nxt_free() */ 3326 task = &task->thread->engine->task; 3327 3328 nxt_router_listen_socket_release(task, joint->socket_conf); 3329 3330 job = joint->close_job; 3331 job->work.next = NULL; 3332 job->work.handler = nxt_router_conf_wait; 3333 3334 nxt_event_engine_post(job->tmcf->engine, &job->work); 3335 3336 nxt_router_listen_event_release(task, lev, joint); 3337} 3338 3339 3340static void 3341nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf) 3342{ 3343 nxt_listen_socket_t *ls; 3344 nxt_thread_spinlock_t *lock; 3345 3346 ls = skcf->listen; 3347 lock = &skcf->router_conf->router->lock; 3348 3349 nxt_thread_spin_lock(lock); 3350 3351 nxt_debug(task, "engine %p: listen socket release: ls->count %D", 3352 task->thread->engine, ls->count); 3353 3354 if (--ls->count != 0) { 3355 ls = NULL; 3356 } 3357 3358 nxt_thread_spin_unlock(lock); 3359 3360 if (ls != NULL) { 3361 nxt_socket_close(task, ls->socket); 3362 nxt_free(ls); 3363 } 3364} 3365 3366 3367void 3368nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, 3369 nxt_socket_conf_joint_t *joint) 3370{ 3371 nxt_event_engine_t *engine; 3372 3373 nxt_debug(task, "listen event count: %D", lev->count); 3374 3375 engine = task->thread->engine; 3376 3377 if (--lev->count == 0) { 3378 if (lev->next != NULL) { 3379 nxt_sockaddr_cache_free(engine, lev->next); 3380 3381 nxt_conn_free(task, lev->next); 3382 } 3383 3384 nxt_free(lev); 3385 } 3386 3387 if (joint != NULL) { 3388 nxt_router_conf_release(task, joint); 3389 } 3390 3391 if (engine->shutdown && nxt_queue_is_empty(&engine->joints)) { 3392 nxt_thread_exit(task->thread); 3393 } 3394} 3395 3396 3397void 3398nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 3399{ 3400 nxt_socket_conf_t *skcf; 3401 nxt_router_conf_t *rtcf; 3402 nxt_thread_spinlock_t *lock; 3403 3404 nxt_debug(task, "conf joint %p count: %D", joint, joint->count); 3405 3406 if (--joint->count != 0) { 3407 return; 3408 } 3409 3410 nxt_queue_remove(&joint->link); 3411 3412 /* 3413 * The joint content can not be safely used after the critical 3414 * section protected by the spinlock because its memory pool may 3415 * be already destroyed by another thread. 3416 */ 3417 skcf = joint->socket_conf; 3418 rtcf = skcf->router_conf; 3419 lock = &rtcf->router->lock; 3420 3421 nxt_thread_spin_lock(lock); 3422 3423 nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, 3424 rtcf, rtcf->count); 3425 3426 if (--skcf->count != 0) { 3427 skcf = NULL; 3428 rtcf = NULL; 3429 3430 } else { 3431 nxt_queue_remove(&skcf->link); 3432 3433 if (--rtcf->count != 0) { 3434 rtcf = NULL; 3435 } 3436 } 3437 3438 nxt_thread_spin_unlock(lock); 3439 3440#if (NXT_TLS) 3441 if (skcf != NULL && skcf->tls != NULL) { 3442 task->thread->runtime->tls->server_free(task, skcf->tls); 3443 } 3444#endif 3445 3446 /* TODO remove engine->port */ 3447 3448 if (rtcf != NULL) { 3449 nxt_debug(task, "old router conf is destroyed"); 3450 3451 nxt_router_apps_hash_use(task, rtcf, -1); 3452 3453 nxt_router_access_log_release(task, lock, rtcf->access_log); 3454 3455 nxt_mp_thread_adopt(rtcf->mem_pool); 3456 3457 nxt_mp_destroy(rtcf->mem_pool); 3458 } 3459} 3460 3461 3462static void 3463nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, 3464 nxt_router_access_log_t *access_log) 3465{ 3466 size_t size; 3467 u_char *buf, *p; 3468 nxt_off_t bytes; 3469 3470 static nxt_time_string_t date_cache = { 3471 (nxt_atomic_uint_t) -1, 3472 nxt_router_access_log_date, 3473 "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", 3474 nxt_length("31/Dec/1986:19:40:00 +0300"), 3475 NXT_THREAD_TIME_LOCAL, 3476 NXT_THREAD_TIME_SEC, 3477 }; 3478 3479 size = r->remote->address_length 3480 + 6 /* ' - - [' */ 3481 + date_cache.size 3482 + 3 /* '] "' */ 3483 + r->method->length 3484 + 1 /* space */ 3485 + r->target.length 3486 + 1 /* space */ 3487 + r->version.length 3488 + 2 /* '" ' */ 3489 + 3 /* status */ 3490 + 1 /* space */ 3491 + NXT_OFF_T_LEN 3492 + 2 /* ' "' */ 3493 + (r->referer != NULL ? r->referer->value_length : 1) 3494 + 3 /* '" "' */ 3495 + (r->user_agent != NULL ? r->user_agent->value_length : 1) 3496 + 2 /* '"\n' */ 3497 ; 3498 3499 buf = nxt_mp_nget(r->mem_pool, size); 3500 if (nxt_slow_path(buf == NULL)) { 3501 return; 3502 } 3503 3504 p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), 3505 r->remote->address_length); 3506 3507 p = nxt_cpymem(p, " - - [", 6); 3508 3509 p = nxt_thread_time_string(task->thread, &date_cache, p); 3510 3511 p = nxt_cpymem(p, "] \"", 3); 3512 3513 if (r->method->length != 0) { 3514 p = nxt_cpymem(p, r->method->start, r->method->length); 3515 3516 if (r->target.length != 0) { 3517 *p++ = ' '; 3518 p = nxt_cpymem(p, r->target.start, r->target.length); 3519 3520 if (r->version.length != 0) { 3521 *p++ = ' '; 3522 p = nxt_cpymem(p, r->version.start, r->version.length); 3523 } 3524 } 3525 3526 } else { 3527 *p++ = '-'; 3528 } 3529 3530 p = nxt_cpymem(p, "\" ", 2); 3531 3532 p = nxt_sprintf(p, p + 3, "%03d", r->status); 3533 3534 *p++ = ' '; 3535 3536 bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); 3537 3538 p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); 3539 3540 p = nxt_cpymem(p, " \"", 2); 3541 3542 if (r->referer != NULL) { 3543 p = nxt_cpymem(p, r->referer->value, r->referer->value_length); 3544 3545 } else { 3546 *p++ = '-'; 3547 } 3548 3549 p = nxt_cpymem(p, "\" \"", 3); 3550 3551 if (r->user_agent != NULL) { 3552 p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); 3553 3554 } else { 3555 *p++ = '-'; 3556 } 3557 3558 p = nxt_cpymem(p, "\"\n", 2); 3559 3560 nxt_fd_write(access_log->fd, buf, p - buf); 3561} 3562 3563 3564static u_char * 3565nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, 3566 size_t size, const char *format) 3567{ 3568 u_char sign; 3569 time_t gmtoff; 3570 3571 static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 3572 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 3573 3574 gmtoff = nxt_timezone(tm) / 60; 3575 3576 if (gmtoff < 0) { 3577 gmtoff = -gmtoff; 3578 sign = '-'; 3579 3580 } else { 3581 sign = '+'; 3582 } 3583 3584 return nxt_sprintf(buf, buf + size, format, 3585 tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, 3586 tm->tm_hour, tm->tm_min, tm->tm_sec, 3587 sign, gmtoff / 60, gmtoff % 60); 3588} 3589 3590 3591static void 3592nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 3593{ 3594 uint32_t stream; 3595 nxt_int_t ret; 3596 nxt_buf_t *b; 3597 nxt_port_t *main_port, *router_port; 3598 nxt_runtime_t *rt; 3599 nxt_router_access_log_t *access_log; 3600 3601 access_log = tmcf->router_conf->access_log; 3602 3603 b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); 3604 if (nxt_slow_path(b == NULL)) { 3605 goto fail; 3606 } 3607 3608 b->completion_handler = nxt_router_dummy_buf_completion; 3609 3610 nxt_buf_cpystr(b, &access_log->path); 3611 *b->mem.free++ = '\0'; 3612 3613 rt = task->thread->runtime; 3614 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 3615 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 3616 3617 stream = nxt_port_rpc_register_handler(task, router_port, 3618 nxt_router_access_log_ready, 3619 nxt_router_access_log_error, 3620 -1, tmcf); 3621 if (nxt_slow_path(stream == 0)) { 3622 goto fail; 3623 } 3624 3625 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, 3626 stream, router_port->id, b); 3627 3628 if (nxt_slow_path(ret != NXT_OK)) { 3629 nxt_port_rpc_cancel(task, router_port, stream); 3630 goto fail; 3631 } 3632 3633 return; 3634 3635fail: 3636 3637 nxt_router_conf_error(task, tmcf); 3638} 3639 3640 3641static void 3642nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3643 void *data) 3644{ 3645 nxt_router_temp_conf_t *tmcf; 3646 nxt_router_access_log_t *access_log; 3647 3648 tmcf = data; 3649 3650 access_log = tmcf->router_conf->access_log; 3651 3652 access_log->fd = msg->fd[0]; 3653 3654 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 3655 nxt_router_conf_apply, task, tmcf, NULL); 3656} 3657 3658 3659static void 3660nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3661 void *data) 3662{ 3663 nxt_router_temp_conf_t *tmcf; 3664 3665 tmcf = data; 3666 3667 nxt_router_conf_error(task, tmcf); 3668} 3669 3670 3671static void 3672nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, 3673 nxt_router_access_log_t *access_log) 3674{ 3675 if (access_log == NULL) { 3676 return; 3677 } 3678 3679 nxt_thread_spin_lock(lock); 3680 3681 if (--access_log->count != 0) { 3682 access_log = NULL; 3683 } 3684 3685 nxt_thread_spin_unlock(lock); 3686 3687 if (access_log != NULL) { 3688 3689 if (access_log->fd != -1) { 3690 nxt_fd_close(access_log->fd); 3691 } 3692 3693 nxt_free(access_log); 3694 } 3695} 3696 3697 3698typedef struct { 3699 nxt_mp_t *mem_pool; 3700 nxt_router_access_log_t *access_log; 3701} nxt_router_access_log_reopen_t; 3702 3703 3704static void 3705nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 3706{ 3707 nxt_mp_t *mp; 3708 uint32_t stream; 3709 nxt_int_t ret; 3710 nxt_buf_t *b; 3711 nxt_port_t *main_port, *router_port; 3712 nxt_runtime_t *rt; 3713 nxt_router_access_log_t *access_log; 3714 nxt_router_access_log_reopen_t *reopen; 3715 3716 access_log = nxt_router->access_log; 3717 3718 if (access_log == NULL) { 3719 return; 3720 } 3721 3722 mp = nxt_mp_create(1024, 128, 256, 32); 3723 if (nxt_slow_path(mp == NULL)) { 3724 return; 3725 } 3726 3727 reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); 3728 if (nxt_slow_path(reopen == NULL)) { 3729 goto fail; 3730 } 3731 3732 reopen->mem_pool = mp; 3733 reopen->access_log = access_log; 3734 3735 b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); 3736 if (nxt_slow_path(b == NULL)) { 3737 goto fail; 3738 } 3739 3740 b->completion_handler = nxt_router_access_log_reopen_completion; 3741 3742 nxt_buf_cpystr(b, &access_log->path); 3743 *b->mem.free++ = '\0'; 3744 3745 rt = task->thread->runtime; 3746 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 3747 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 3748 3749 stream = nxt_port_rpc_register_handler(task, router_port, 3750 nxt_router_access_log_reopen_ready, 3751 nxt_router_access_log_reopen_error, 3752 -1, reopen); 3753 if (nxt_slow_path(stream == 0)) { 3754 goto fail; 3755 } 3756 3757 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, 3758 stream, router_port->id, b); 3759 3760 if (nxt_slow_path(ret != NXT_OK)) { 3761 nxt_port_rpc_cancel(task, router_port, stream); 3762 goto fail; 3763 } 3764 3765 nxt_mp_retain(mp); 3766 3767 return; 3768 3769fail: 3770 3771 nxt_mp_destroy(mp); 3772} 3773 3774 3775static void 3776nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) 3777{ 3778 nxt_mp_t *mp; 3779 nxt_buf_t *b; 3780 3781 b = obj; 3782 mp = b->data; 3783 3784 nxt_mp_release(mp); 3785} 3786 3787 3788static void 3789nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3790 void *data) 3791{ 3792 nxt_router_access_log_t *access_log; 3793 nxt_router_access_log_reopen_t *reopen; 3794 3795 reopen = data; 3796 3797 access_log = reopen->access_log; 3798 3799 if (access_log == nxt_router->access_log) { 3800 3801 if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { 3802 nxt_alert(task, "dup2(%FD, %FD) failed %E", 3803 msg->fd[0], access_log->fd, nxt_errno); 3804 } 3805 } 3806 3807 nxt_fd_close(msg->fd[0]); 3808 nxt_mp_release(reopen->mem_pool); 3809} 3810 3811 3812static void 3813nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3814 void *data) 3815{ 3816 nxt_router_access_log_reopen_t *reopen; 3817 3818 reopen = data; 3819 3820 nxt_mp_release(reopen->mem_pool); 3821} 3822 3823 3824static void 3825nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 3826{ 3827 nxt_port_t *port; 3828 nxt_thread_link_t *link; 3829 nxt_event_engine_t *engine; 3830 nxt_thread_handle_t handle; 3831 3832 handle = (nxt_thread_handle_t) (uintptr_t) obj; 3833 link = data; 3834 3835 nxt_thread_wait(handle); 3836 3837 engine = link->engine; 3838 3839 nxt_queue_remove(&engine->link); 3840 3841 port = engine->port; 3842 3843 // TODO notify all apps 3844 3845 port->engine = task->thread->engine; 3846 nxt_mp_thread_adopt(port->mem_pool); 3847 nxt_port_use(task, port, -1); 3848 3849 nxt_mp_thread_adopt(engine->mem_pool); 3850 nxt_mp_destroy(engine->mem_pool); 3851 3852 nxt_event_engine_free(engine); 3853 3854 nxt_free(link); 3855} 3856 3857 3858static void 3859nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3860 void *data) 3861{ 3862 size_t b_size, count; 3863 nxt_int_t ret; 3864 nxt_app_t *app; 3865 nxt_buf_t *b, *next; 3866 nxt_port_t *app_port; 3867 nxt_unit_field_t *f; 3868 nxt_http_field_t *field; 3869 nxt_http_request_t *r; 3870 nxt_unit_response_t *resp; 3871 nxt_request_rpc_data_t *req_rpc_data; 3872 3873 req_rpc_data = data; 3874 3875 r = req_rpc_data->request; 3876 if (nxt_slow_path(r == NULL)) { 3877 return; 3878 } 3879 3880 if (r->error) { 3881 nxt_request_rpc_data_unlink(task, req_rpc_data); 3882 return; 3883 } 3884 3885 app = req_rpc_data->app; 3886 nxt_assert(app != NULL); 3887 3888 if (msg->port_msg.type == _NXT_PORT_MSG_REQ_HEADERS_ACK) { 3889 nxt_router_req_headers_ack_handler(task, msg, req_rpc_data); 3890 3891 return; 3892 } 3893 3894 b = (msg->size == 0) ? NULL : msg->buf; 3895 3896 if (msg->port_msg.last != 0) { 3897 nxt_debug(task, "router data create last buf"); 3898 3899 nxt_buf_chain_add(&b, nxt_http_buf_last(r)); 3900 3901 req_rpc_data->rpc_cancel = 0; 3902 3903 if (req_rpc_data->apr_action == NXT_APR_REQUEST_FAILED) { 3904 req_rpc_data->apr_action = NXT_APR_GOT_RESPONSE; 3905 } 3906 3907 nxt_request_rpc_data_unlink(task, req_rpc_data); 3908 3909 } else { 3910 if (app->timeout != 0) { 3911 r->timer.handler = nxt_router_app_timeout; 3912 r->timer_data = req_rpc_data; 3913 nxt_timer_add(task->thread->engine, &r->timer, app->timeout); 3914 } 3915 } 3916 3917 if (b == NULL) { 3918 return; 3919 } 3920 3921 if (msg->buf == b) { 3922 /* Disable instant buffer completion/re-using by port. */ 3923 msg->buf = NULL; 3924 } 3925 3926 if (r->header_sent) { 3927 nxt_buf_chain_add(&r->out, b); 3928 nxt_http_request_send_body(task, r, NULL); 3929 3930 } else { 3931 b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0; 3932 3933 if (nxt_slow_path(b_size < sizeof(nxt_unit_response_t))) { 3934 nxt_alert(task, "response buffer too small: %z", b_size); 3935 goto fail; 3936 } 3937 3938 resp = (void *) b->mem.pos; 3939 count = (b_size - sizeof(nxt_unit_response_t)) 3940 / sizeof(nxt_unit_field_t); 3941 3942 if (nxt_slow_path(count < resp->fields_count)) { 3943 nxt_alert(task, "response buffer too small for fields count: %D", 3944 resp->fields_count); 3945 goto fail; 3946 } 3947 3948 field = NULL; 3949 3950 for (f = resp->fields; f < resp->fields + resp->fields_count; f++) { 3951 if (f->skip) { 3952 continue; 3953 } 3954 3955 field = nxt_list_add(r->resp.fields); 3956 3957 if (nxt_slow_path(field == NULL)) { 3958 goto fail; 3959 } 3960 3961 field->hash = f->hash; 3962 field->skip = 0; 3963 field->hopbyhop = 0; 3964 3965 field->name_length = f->name_length; 3966 field->value_length = f->value_length; 3967 field->name = nxt_unit_sptr_get(&f->name); 3968 field->value = nxt_unit_sptr_get(&f->value); 3969 3970 ret = nxt_http_field_process(field, &nxt_response_fields_hash, r); 3971 if (nxt_slow_path(ret != NXT_OK)) { 3972 goto fail; 3973 } 3974 3975 nxt_debug(task, "header%s: %*s: %*s", 3976 (field->skip ? " skipped" : ""), 3977 (size_t) field->name_length, field->name, 3978 (size_t) field->value_length, field->value); 3979 3980 if (field->skip) { 3981 r->resp.fields->last->nelts--; 3982 } 3983 } 3984 3985 r->status = resp->status; 3986 3987 if (resp->piggyback_content_length != 0) { 3988 b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content); 3989 b->mem.free = b->mem.pos + resp->piggyback_content_length; 3990 3991 } else { 3992 b->mem.pos = b->mem.free; 3993 } 3994 3995 if (nxt_buf_mem_used_size(&b->mem) == 0) { 3996 next = b->next; 3997 b->next = NULL; 3998 3999 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 4000 b->completion_handler, task, b, b->parent); 4001 4002 b = next; 4003 } 4004 4005 if (b != NULL) { 4006 nxt_buf_chain_add(&r->out, b); 4007 } 4008 4009 nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL); 4010 4011 if (r->websocket_handshake 4012 && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) 4013 { 4014 app_port = req_rpc_data->app_port; 4015 if (nxt_slow_path(app_port == NULL)) { 4016 goto fail; 4017 } 4018 4019 nxt_thread_mutex_lock(&app->mutex); 4020 4021 app_port->main_app_port->active_websockets++; 4022 4023 nxt_thread_mutex_unlock(&app->mutex); 4024 4025 nxt_router_app_port_release(task, app_port, NXT_APR_UPGRADE); 4026 req_rpc_data->apr_action = NXT_APR_CLOSE; 4027 4028 nxt_debug(task, "stream #%uD upgrade", req_rpc_data->stream); 4029 4030 r->state = &nxt_http_websocket; 4031 4032 } else { 4033 r->state = &nxt_http_request_send_state; 4034 } 4035 } 4036 4037 return; 4038 4039fail: 4040 4041 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 4042 4043 nxt_request_rpc_data_unlink(task, req_rpc_data); 4044} 4045 4046 4047static void 4048nxt_router_req_headers_ack_handler(nxt_task_t *task, 4049 nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data) 4050{ 4051 int res; 4052 nxt_app_t *app; 4053 nxt_buf_t *b; 4054 nxt_bool_t start_process, unlinked; 4055 nxt_port_t *app_port, *main_app_port, *idle_port; 4056 nxt_queue_link_t *idle_lnk; 4057 nxt_http_request_t *r; 4058 4059 nxt_debug(task, "stream #%uD: got ack from %PI:%d", 4060 req_rpc_data->stream, 4061 msg->port_msg.pid, msg->port_msg.reply_port); 4062 4063 nxt_port_rpc_ex_set_peer(task, msg->port, req_rpc_data, 4064 msg->port_msg.pid); 4065 4066 app = req_rpc_data->app; 4067 r = req_rpc_data->request; 4068 4069 start_process = 0; 4070 unlinked = 0; 4071 4072 nxt_thread_mutex_lock(&app->mutex); 4073 4074 if (r->app_link.next != NULL) { 4075 nxt_queue_remove(&r->app_link); 4076 r->app_link.next = NULL; 4077 4078 unlinked = 1; 4079 } 4080 4081 app_port = nxt_port_hash_find(&app->port_hash, msg->port_msg.pid, 4082 msg->port_msg.reply_port); 4083 if (nxt_slow_path(app_port == NULL)) { 4084 nxt_thread_mutex_unlock(&app->mutex); 4085 4086 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 4087 4088 if (unlinked) { 4089 nxt_mp_release(r->mem_pool); 4090 } 4091 4092 return; 4093 } 4094 4095 main_app_port = app_port->main_app_port; 4096 4097 if (nxt_queue_chk_remove(&main_app_port->idle_link)) { 4098 app->idle_processes--; 4099 4100 nxt_debug(task, "app '%V' move port %PI:%d out of %s (ack)", 4101 &app->name, main_app_port->pid, main_app_port->id, 4102 (main_app_port->idle_start ? "idle_ports" : "spare_ports")); 4103 4104 /* Check port was in 'spare_ports' using idle_start field. */ 4105 if (main_app_port->idle_start == 0 4106 && app->idle_processes >= app->spare_processes) 4107 { 4108 /* 4109 * If there is a vacant space in spare ports, 4110 * move the last idle to spare_ports. 4111 */ 4112 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4113 4114 idle_lnk = nxt_queue_last(&app->idle_ports); 4115 idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); 4116 nxt_queue_remove(idle_lnk); 4117 4118 nxt_queue_insert_tail(&app->spare_ports, idle_lnk); 4119 4120 idle_port->idle_start = 0; 4121 4122 nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " 4123 "to spare_ports", 4124 &app->name, idle_port->pid, idle_port->id); 4125 } 4126 4127 if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { 4128 app->pending_processes++; 4129 start_process = 1; 4130 } 4131 } 4132 4133 main_app_port->active_requests++; 4134 4135 nxt_port_inc_use(app_port); 4136 4137 nxt_thread_mutex_unlock(&app->mutex); 4138 4139 if (unlinked) { 4140 nxt_mp_release(r->mem_pool); 4141 } 4142 4143 if (start_process) { 4144 nxt_router_start_app_process(task, app); 4145 } 4146 4147 nxt_port_use(task, req_rpc_data->app_port, -1); 4148 4149 req_rpc_data->app_port = app_port; 4150 4151 b = req_rpc_data->msg_info.buf; 4152 4153 if (b != NULL) { 4154 /* First buffer is already sent. Start from second. */ 4155 b = b->next; 4156 4157 req_rpc_data->msg_info.buf->next = NULL; 4158 } 4159 4160 if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) { 4161 nxt_debug(task, "stream #%uD: send body fd %d", req_rpc_data->stream, 4162 req_rpc_data->msg_info.body_fd); 4163 4164 if (req_rpc_data->msg_info.body_fd != -1) { 4165 lseek(req_rpc_data->msg_info.body_fd, 0, SEEK_SET); 4166 } 4167 4168 res = nxt_port_socket_write(task, app_port, NXT_PORT_MSG_REQ_BODY, 4169 req_rpc_data->msg_info.body_fd, 4170 req_rpc_data->stream, 4171 task->thread->engine->port->id, b); 4172 4173 if (nxt_slow_path(res != NXT_OK)) { 4174 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 4175 } 4176 } 4177 4178 if (app->timeout != 0) { 4179 r->timer.handler = nxt_router_app_timeout; 4180 r->timer_data = req_rpc_data; 4181 nxt_timer_add(task->thread->engine, &r->timer, app->timeout); 4182 } 4183} 4184 4185 4186static const nxt_http_request_state_t nxt_http_request_send_state 4187 nxt_aligned(64) = 4188{ 4189 .error_handler = nxt_http_request_error_handler, 4190}; 4191 4192 4193static void 4194nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data) 4195{ 4196 nxt_buf_t *out; 4197 nxt_http_request_t *r; 4198 4199 r = obj; 4200 4201 out = r->out; 4202 4203 if (out != NULL) { 4204 r->out = NULL; 4205 nxt_http_request_send(task, r, out); 4206 } 4207} 4208 4209 4210static void 4211nxt_router_response_error_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4212 void *data) 4213{ 4214 nxt_request_rpc_data_t *req_rpc_data; 4215 4216 req_rpc_data = data; 4217 4218 req_rpc_data->rpc_cancel = 0; 4219 4220 /* TODO cancel message and return if cancelled. */ 4221 // nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream); 4222 4223 if (req_rpc_data->request != NULL) { 4224 nxt_http_request_error(task, req_rpc_data->request, 4225 NXT_HTTP_SERVICE_UNAVAILABLE); 4226 } 4227 4228 nxt_request_rpc_data_unlink(task, req_rpc_data); 4229} 4230 4231 4232static void 4233nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4234 void *data) 4235{
| 1714 NXT_PROCESS_APP); 1715 if (nxt_slow_path(port == NULL)) { 1716 return NXT_ERROR; 1717 } 1718 1719 ret = nxt_port_socket_init(task, port, 0); 1720 if (nxt_slow_path(ret != NXT_OK)) { 1721 nxt_port_use(task, port, -1); 1722 return NXT_ERROR; 1723 } 1724 1725 ret = nxt_router_app_queue_init(task, port); 1726 if (nxt_slow_path(ret != NXT_OK)) { 1727 nxt_port_write_close(port); 1728 nxt_port_read_close(port); 1729 nxt_port_use(task, port, -1); 1730 return NXT_ERROR; 1731 } 1732 1733 nxt_port_write_enable(task, port); 1734 port->app = app; 1735 1736 app->shared_port = port; 1737 1738 nxt_thread_mutex_create(&app->outgoing.mutex); 1739 } 1740 } 1741 1742 routes_conf = nxt_conf_get_path(conf, &routes_path); 1743 if (nxt_fast_path(routes_conf != NULL)) { 1744 routes = nxt_http_routes_create(task, tmcf, routes_conf); 1745 if (nxt_slow_path(routes == NULL)) { 1746 return NXT_ERROR; 1747 } 1748 tmcf->router_conf->routes = routes; 1749 } 1750 1751 ret = nxt_upstreams_create(task, tmcf, conf); 1752 if (nxt_slow_path(ret != NXT_OK)) { 1753 return ret; 1754 } 1755 1756 http = nxt_conf_get_path(conf, &http_path); 1757#if 0 1758 if (http == NULL) { 1759 nxt_alert(task, "no \"http\" block"); 1760 return NXT_ERROR; 1761 } 1762#endif 1763 1764 websocket = nxt_conf_get_path(conf, &websocket_path); 1765 1766 listeners = nxt_conf_get_path(conf, &listeners_path); 1767 1768 if (listeners != NULL) { 1769 next = 0; 1770 1771 for ( ;; ) { 1772 listener = nxt_conf_next_object_member(listeners, &name, &next); 1773 if (listener == NULL) { 1774 break; 1775 } 1776 1777 skcf = nxt_router_socket_conf(task, tmcf, &name); 1778 if (skcf == NULL) { 1779 goto fail; 1780 } 1781 1782 nxt_memzero(&lscf, sizeof(lscf)); 1783 1784 ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, 1785 nxt_nitems(nxt_router_listener_conf), 1786 &lscf); 1787 if (ret != NXT_OK) { 1788 nxt_alert(task, "listener map error"); 1789 goto fail; 1790 } 1791 1792 nxt_debug(task, "application: %V", &lscf.application); 1793 1794 // STUB, default values if http block is not defined. 1795 skcf->header_buffer_size = 2048; 1796 skcf->large_header_buffer_size = 8192; 1797 skcf->large_header_buffers = 4; 1798 skcf->discard_unsafe_fields = 1; 1799 skcf->body_buffer_size = 16 * 1024; 1800 skcf->max_body_size = 8 * 1024 * 1024; 1801 skcf->proxy_header_buffer_size = 64 * 1024; 1802 skcf->proxy_buffer_size = 4096; 1803 skcf->proxy_buffers = 256; 1804 skcf->idle_timeout = 180 * 1000; 1805 skcf->header_read_timeout = 30 * 1000; 1806 skcf->body_read_timeout = 30 * 1000; 1807 skcf->send_timeout = 30 * 1000; 1808 skcf->proxy_timeout = 60 * 1000; 1809 skcf->proxy_send_timeout = 30 * 1000; 1810 skcf->proxy_read_timeout = 30 * 1000; 1811 1812 skcf->websocket_conf.max_frame_size = 1024 * 1024; 1813 skcf->websocket_conf.read_timeout = 60 * 1000; 1814 skcf->websocket_conf.keepalive_interval = 30 * 1000; 1815 1816 nxt_str_null(&skcf->body_temp_path); 1817 1818 if (http != NULL) { 1819 ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, 1820 nxt_nitems(nxt_router_http_conf), 1821 skcf); 1822 if (ret != NXT_OK) { 1823 nxt_alert(task, "http map error"); 1824 goto fail; 1825 } 1826 } 1827 1828 if (websocket != NULL) { 1829 ret = nxt_conf_map_object(mp, websocket, 1830 nxt_router_websocket_conf, 1831 nxt_nitems(nxt_router_websocket_conf), 1832 &skcf->websocket_conf); 1833 if (ret != NXT_OK) { 1834 nxt_alert(task, "websocket map error"); 1835 goto fail; 1836 } 1837 } 1838 1839 t = &skcf->body_temp_path; 1840 1841 if (t->length == 0) { 1842 t->start = (u_char *) task->thread->runtime->tmp; 1843 t->length = nxt_strlen(t->start); 1844 } 1845 1846#if (NXT_TLS) 1847 certificate = nxt_conf_get_path(listener, &certificate_path); 1848 1849 if (certificate != NULL) { 1850 tls_init = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_tls_init_t)); 1851 if (nxt_slow_path(tls_init == NULL)) { 1852 return NXT_ERROR; 1853 } 1854 1855 tls_init->cache_size = 0; 1856 tls_init->timeout = 300; 1857 1858 value = nxt_conf_get_path(listener, &conf_cache_path); 1859 if (value != NULL) { 1860 tls_init->cache_size = nxt_conf_get_number(value); 1861 } 1862 1863 value = nxt_conf_get_path(listener, &conf_timeout_path); 1864 if (value != NULL) { 1865 tls_init->timeout = nxt_conf_get_number(value); 1866 } 1867 1868 tls_init->conf_cmds = nxt_conf_get_path(listener, 1869 &conf_commands_path); 1870 1871 if (nxt_conf_type(certificate) == NXT_CONF_ARRAY) { 1872 n = nxt_conf_array_elements_count(certificate); 1873 1874 for (i = 0; i < n; i++) { 1875 value = nxt_conf_get_array_element(certificate, i); 1876 1877 nxt_assert(value != NULL); 1878 1879 ret = nxt_router_conf_tls_insert(tmcf, value, skcf, 1880 tls_init, i == 0); 1881 if (nxt_slow_path(ret != NXT_OK)) { 1882 goto fail; 1883 } 1884 } 1885 1886 } else { 1887 /* NXT_CONF_STRING */ 1888 ret = nxt_router_conf_tls_insert(tmcf, certificate, skcf, 1889 tls_init, 1); 1890 if (nxt_slow_path(ret != NXT_OK)) { 1891 goto fail; 1892 } 1893 } 1894 } 1895#endif 1896 1897 skcf->listen->handler = nxt_http_conn_init; 1898 skcf->router_conf = tmcf->router_conf; 1899 skcf->router_conf->count++; 1900 1901 if (lscf.pass.length != 0) { 1902 skcf->action = nxt_http_action_create(task, tmcf, &lscf.pass); 1903 1904 /* COMPATIBILITY: listener application. */ 1905 } else if (lscf.application.length > 0) { 1906 skcf->action = nxt_http_pass_application(task, 1907 tmcf->router_conf, 1908 &lscf.application); 1909 } 1910 1911 if (nxt_slow_path(skcf->action == NULL)) { 1912 goto fail; 1913 } 1914 } 1915 } 1916 1917 ret = nxt_http_routes_resolve(task, tmcf); 1918 if (nxt_slow_path(ret != NXT_OK)) { 1919 goto fail; 1920 } 1921 1922 value = nxt_conf_get_path(conf, &access_log_path); 1923 1924 if (value != NULL) { 1925 nxt_conf_get_string(value, &path); 1926 1927 access_log = router->access_log; 1928 1929 if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { 1930 nxt_thread_spin_lock(&router->lock); 1931 access_log->count++; 1932 nxt_thread_spin_unlock(&router->lock); 1933 1934 } else { 1935 access_log = nxt_malloc(sizeof(nxt_router_access_log_t) 1936 + path.length); 1937 if (access_log == NULL) { 1938 nxt_alert(task, "failed to allocate access log structure"); 1939 goto fail; 1940 } 1941 1942 access_log->fd = -1; 1943 access_log->handler = &nxt_router_access_log_writer; 1944 access_log->count = 1; 1945 1946 access_log->path.length = path.length; 1947 access_log->path.start = (u_char *) access_log 1948 + sizeof(nxt_router_access_log_t); 1949 1950 nxt_memcpy(access_log->path.start, path.start, path.length); 1951 } 1952 1953 tmcf->router_conf->access_log = access_log; 1954 } 1955 1956 nxt_queue_add(&deleting_sockets, &router->sockets); 1957 nxt_queue_init(&router->sockets); 1958 1959 return NXT_OK; 1960 1961app_fail: 1962 1963 nxt_mp_destroy(app_mp); 1964 1965fail: 1966 1967 nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 1968 1969 nxt_queue_remove(&app->link); 1970 nxt_thread_mutex_destroy(&app->mutex); 1971 nxt_mp_destroy(app->mem_pool); 1972 1973 } nxt_queue_loop; 1974 1975 return NXT_ERROR; 1976} 1977 1978 1979#if (NXT_TLS) 1980 1981static nxt_int_t 1982nxt_router_conf_tls_insert(nxt_router_temp_conf_t *tmcf, 1983 nxt_conf_value_t *value, nxt_socket_conf_t *skcf, 1984 nxt_tls_init_t *tls_init, nxt_bool_t last) 1985{ 1986 nxt_router_tlssock_t *tls; 1987 1988 tls = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_router_tlssock_t)); 1989 if (nxt_slow_path(tls == NULL)) { 1990 return NXT_ERROR; 1991 } 1992 1993 tls->tls_init = tls_init; 1994 tls->socket_conf = skcf; 1995 tls->temp_conf = tmcf; 1996 tls->last = last; 1997 nxt_conf_get_string(value, &tls->name); 1998 1999 nxt_queue_insert_tail(&tmcf->tls, &tls->link); 2000 2001 return NXT_OK; 2002} 2003 2004#endif 2005 2006 2007static nxt_int_t 2008nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, 2009 nxt_conf_value_t *conf) 2010{ 2011 uint32_t next, i; 2012 nxt_mp_t *mp; 2013 nxt_str_t *type, exten, str; 2014 nxt_int_t ret; 2015 nxt_uint_t exts; 2016 nxt_conf_value_t *mtypes_conf, *ext_conf, *value; 2017 2018 static nxt_str_t mtypes_path = nxt_string("/mime_types"); 2019 2020 mp = rtcf->mem_pool; 2021 2022 ret = nxt_http_static_mtypes_init(mp, &rtcf->mtypes_hash); 2023 if (nxt_slow_path(ret != NXT_OK)) { 2024 return NXT_ERROR; 2025 } 2026 2027 if (conf == NULL) { 2028 return NXT_OK; 2029 } 2030 2031 mtypes_conf = nxt_conf_get_path(conf, &mtypes_path); 2032 2033 if (mtypes_conf != NULL) { 2034 next = 0; 2035 2036 for ( ;; ) { 2037 ext_conf = nxt_conf_next_object_member(mtypes_conf, &str, &next); 2038 2039 if (ext_conf == NULL) { 2040 break; 2041 } 2042 2043 type = nxt_str_dup(mp, NULL, &str); 2044 if (nxt_slow_path(type == NULL)) { 2045 return NXT_ERROR; 2046 } 2047 2048 if (nxt_conf_type(ext_conf) == NXT_CONF_STRING) { 2049 nxt_conf_get_string(ext_conf, &str); 2050 2051 if (nxt_slow_path(nxt_str_dup(mp, &exten, &str) == NULL)) { 2052 return NXT_ERROR; 2053 } 2054 2055 ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, 2056 &exten, type); 2057 if (nxt_slow_path(ret != NXT_OK)) { 2058 return NXT_ERROR; 2059 } 2060 2061 continue; 2062 } 2063 2064 exts = nxt_conf_array_elements_count(ext_conf); 2065 2066 for (i = 0; i < exts; i++) { 2067 value = nxt_conf_get_array_element(ext_conf, i); 2068 2069 nxt_conf_get_string(value, &str); 2070 2071 if (nxt_slow_path(nxt_str_dup(mp, &exten, &str) == NULL)) { 2072 return NXT_ERROR; 2073 } 2074 2075 ret = nxt_http_static_mtypes_hash_add(mp, &rtcf->mtypes_hash, 2076 &exten, type); 2077 if (nxt_slow_path(ret != NXT_OK)) { 2078 return NXT_ERROR; 2079 } 2080 } 2081 } 2082 } 2083 2084 return NXT_OK; 2085} 2086 2087 2088static nxt_app_t * 2089nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 2090{ 2091 nxt_app_t *app; 2092 2093 nxt_queue_each(app, queue, nxt_app_t, link) { 2094 2095 if (nxt_strstr_eq(name, &app->name)) { 2096 return app; 2097 } 2098 2099 } nxt_queue_loop; 2100 2101 return NULL; 2102} 2103 2104 2105static nxt_int_t 2106nxt_router_app_queue_init(nxt_task_t *task, nxt_port_t *port) 2107{ 2108 void *mem; 2109 nxt_int_t fd; 2110 2111 fd = nxt_shm_open(task, sizeof(nxt_app_queue_t)); 2112 if (nxt_slow_path(fd == -1)) { 2113 return NXT_ERROR; 2114 } 2115 2116 mem = nxt_mem_mmap(NULL, sizeof(nxt_app_queue_t), 2117 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2118 if (nxt_slow_path(mem == MAP_FAILED)) { 2119 nxt_fd_close(fd); 2120 2121 return NXT_ERROR; 2122 } 2123 2124 nxt_app_queue_init(mem); 2125 2126 port->queue_fd = fd; 2127 port->queue = mem; 2128 2129 return NXT_OK; 2130} 2131 2132 2133static nxt_int_t 2134nxt_router_port_queue_init(nxt_task_t *task, nxt_port_t *port) 2135{ 2136 void *mem; 2137 nxt_int_t fd; 2138 2139 fd = nxt_shm_open(task, sizeof(nxt_port_queue_t)); 2140 if (nxt_slow_path(fd == -1)) { 2141 return NXT_ERROR; 2142 } 2143 2144 mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), 2145 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2146 if (nxt_slow_path(mem == MAP_FAILED)) { 2147 nxt_fd_close(fd); 2148 2149 return NXT_ERROR; 2150 } 2151 2152 nxt_port_queue_init(mem); 2153 2154 port->queue_fd = fd; 2155 port->queue = mem; 2156 2157 return NXT_OK; 2158} 2159 2160 2161static nxt_int_t 2162nxt_router_port_queue_map(nxt_task_t *task, nxt_port_t *port, nxt_fd_t fd) 2163{ 2164 void *mem; 2165 2166 nxt_assert(fd != -1); 2167 2168 mem = nxt_mem_mmap(NULL, sizeof(nxt_port_queue_t), 2169 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2170 if (nxt_slow_path(mem == MAP_FAILED)) { 2171 2172 return NXT_ERROR; 2173 } 2174 2175 port->queue = mem; 2176 2177 return NXT_OK; 2178} 2179 2180 2181static const nxt_lvlhsh_proto_t nxt_router_apps_hash_proto nxt_aligned(64) = { 2182 NXT_LVLHSH_DEFAULT, 2183 nxt_router_apps_hash_test, 2184 nxt_mp_lvlhsh_alloc, 2185 nxt_mp_lvlhsh_free, 2186}; 2187 2188 2189static nxt_int_t 2190nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 2191{ 2192 nxt_app_t *app; 2193 2194 app = data; 2195 2196 return nxt_strstr_eq(&lhq->key, &app->name) ? NXT_OK : NXT_DECLINED; 2197} 2198 2199 2200static nxt_int_t 2201nxt_router_apps_hash_add(nxt_router_conf_t *rtcf, nxt_app_t *app) 2202{ 2203 nxt_lvlhsh_query_t lhq; 2204 2205 lhq.key_hash = nxt_djb_hash(app->name.start, app->name.length); 2206 lhq.replace = 0; 2207 lhq.key = app->name; 2208 lhq.value = app; 2209 lhq.proto = &nxt_router_apps_hash_proto; 2210 lhq.pool = rtcf->mem_pool; 2211 2212 switch (nxt_lvlhsh_insert(&rtcf->apps_hash, &lhq)) { 2213 2214 case NXT_OK: 2215 return NXT_OK; 2216 2217 case NXT_DECLINED: 2218 nxt_thread_log_alert("router app hash adding failed: " 2219 "\"%V\" is already in hash", &lhq.key); 2220 /* Fall through. */ 2221 default: 2222 return NXT_ERROR; 2223 } 2224} 2225 2226 2227static nxt_app_t * 2228nxt_router_apps_hash_get(nxt_router_conf_t *rtcf, nxt_str_t *name) 2229{ 2230 nxt_lvlhsh_query_t lhq; 2231 2232 lhq.key_hash = nxt_djb_hash(name->start, name->length); 2233 lhq.key = *name; 2234 lhq.proto = &nxt_router_apps_hash_proto; 2235 2236 if (nxt_lvlhsh_find(&rtcf->apps_hash, &lhq) != NXT_OK) { 2237 return NULL; 2238 } 2239 2240 return lhq.value; 2241} 2242 2243 2244static void 2245nxt_router_apps_hash_use(nxt_task_t *task, nxt_router_conf_t *rtcf, int i) 2246{ 2247 nxt_app_t *app; 2248 nxt_lvlhsh_each_t lhe; 2249 2250 nxt_lvlhsh_each_init(&lhe, &nxt_router_apps_hash_proto); 2251 2252 for ( ;; ) { 2253 app = nxt_lvlhsh_each(&rtcf->apps_hash, &lhe); 2254 2255 if (app == NULL) { 2256 break; 2257 } 2258 2259 nxt_router_app_use(task, app, i); 2260 } 2261} 2262 2263 2264typedef struct { 2265 nxt_app_t *app; 2266 nxt_int_t target; 2267} nxt_http_app_conf_t; 2268 2269 2270nxt_int_t 2271nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, 2272 nxt_str_t *target, nxt_http_action_t *action) 2273{ 2274 nxt_app_t *app; 2275 nxt_str_t *targets; 2276 nxt_uint_t i; 2277 nxt_http_app_conf_t *conf; 2278 2279 app = nxt_router_apps_hash_get(rtcf, name); 2280 if (app == NULL) { 2281 return NXT_DECLINED; 2282 } 2283 2284 conf = nxt_mp_get(rtcf->mem_pool, sizeof(nxt_http_app_conf_t)); 2285 if (nxt_slow_path(conf == NULL)) { 2286 return NXT_ERROR; 2287 } 2288 2289 action->handler = nxt_http_application_handler; 2290 action->u.conf = conf; 2291 2292 conf->app = app; 2293 2294 if (target != NULL && target->length != 0) { 2295 targets = app->targets; 2296 2297 for (i = 0; !nxt_strstr_eq(target, &targets[i]); i++); 2298 2299 conf->target = i; 2300 2301 } else { 2302 conf->target = 0; 2303 } 2304 2305 return NXT_OK; 2306} 2307 2308 2309static nxt_socket_conf_t * 2310nxt_router_socket_conf(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 2311 nxt_str_t *name) 2312{ 2313 size_t size; 2314 nxt_int_t ret; 2315 nxt_bool_t wildcard; 2316 nxt_sockaddr_t *sa; 2317 nxt_socket_conf_t *skcf; 2318 nxt_listen_socket_t *ls; 2319 2320 sa = nxt_sockaddr_parse(tmcf->mem_pool, name); 2321 if (nxt_slow_path(sa == NULL)) { 2322 nxt_alert(task, "invalid listener \"%V\"", name); 2323 return NULL; 2324 } 2325 2326 sa->type = SOCK_STREAM; 2327 2328 nxt_debug(task, "router listener: \"%*s\"", 2329 (size_t) sa->length, nxt_sockaddr_start(sa)); 2330 2331 skcf = nxt_mp_zget(tmcf->router_conf->mem_pool, sizeof(nxt_socket_conf_t)); 2332 if (nxt_slow_path(skcf == NULL)) { 2333 return NULL; 2334 } 2335 2336 size = nxt_sockaddr_size(sa); 2337 2338 ret = nxt_router_listen_socket_find(tmcf, skcf, sa); 2339 2340 if (ret != NXT_OK) { 2341 2342 ls = nxt_zalloc(sizeof(nxt_listen_socket_t) + size); 2343 if (nxt_slow_path(ls == NULL)) { 2344 return NULL; 2345 } 2346 2347 skcf->listen = ls; 2348 2349 ls->sockaddr = nxt_pointer_to(ls, sizeof(nxt_listen_socket_t)); 2350 nxt_memcpy(ls->sockaddr, sa, size); 2351 2352 nxt_listen_socket_remote_size(ls); 2353 2354 ls->socket = -1; 2355 ls->backlog = NXT_LISTEN_BACKLOG; 2356 ls->flags = NXT_NONBLOCK; 2357 ls->read_after_accept = 1; 2358 } 2359 2360 switch (sa->u.sockaddr.sa_family) { 2361#if (NXT_HAVE_UNIX_DOMAIN) 2362 case AF_UNIX: 2363 wildcard = 0; 2364 break; 2365#endif 2366#if (NXT_INET6) 2367 case AF_INET6: 2368 wildcard = IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr); 2369 break; 2370#endif 2371 case AF_INET: 2372 default: 2373 wildcard = (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY); 2374 break; 2375 } 2376 2377 if (!wildcard) { 2378 skcf->sockaddr = nxt_mp_zget(tmcf->router_conf->mem_pool, size); 2379 if (nxt_slow_path(skcf->sockaddr == NULL)) { 2380 return NULL; 2381 } 2382 2383 nxt_memcpy(skcf->sockaddr, sa, size); 2384 } 2385 2386 return skcf; 2387} 2388 2389 2390static nxt_int_t 2391nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf, 2392 nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa) 2393{ 2394 nxt_router_t *router; 2395 nxt_queue_link_t *qlk; 2396 nxt_socket_conf_t *skcf; 2397 2398 router = tmcf->router_conf->router; 2399 2400 for (qlk = nxt_queue_first(&router->sockets); 2401 qlk != nxt_queue_tail(&router->sockets); 2402 qlk = nxt_queue_next(qlk)) 2403 { 2404 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 2405 2406 if (nxt_sockaddr_cmp(skcf->listen->sockaddr, sa)) { 2407 nskcf->listen = skcf->listen; 2408 2409 nxt_queue_remove(qlk); 2410 nxt_queue_insert_tail(&keeping_sockets, qlk); 2411 2412 nxt_queue_insert_tail(&updating_sockets, &nskcf->link); 2413 2414 return NXT_OK; 2415 } 2416 } 2417 2418 nxt_queue_insert_tail(&pending_sockets, &nskcf->link); 2419 2420 return NXT_DECLINED; 2421} 2422 2423 2424static void 2425nxt_router_listen_socket_rpc_create(nxt_task_t *task, 2426 nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf) 2427{ 2428 size_t size; 2429 uint32_t stream; 2430 nxt_int_t ret; 2431 nxt_buf_t *b; 2432 nxt_port_t *main_port, *router_port; 2433 nxt_runtime_t *rt; 2434 nxt_socket_rpc_t *rpc; 2435 2436 rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); 2437 if (rpc == NULL) { 2438 goto fail; 2439 } 2440 2441 rpc->socket_conf = skcf; 2442 rpc->temp_conf = tmcf; 2443 2444 size = nxt_sockaddr_size(skcf->listen->sockaddr); 2445 2446 b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2447 if (b == NULL) { 2448 goto fail; 2449 } 2450 2451 b->completion_handler = nxt_router_dummy_buf_completion; 2452 2453 b->mem.free = nxt_cpymem(b->mem.free, skcf->listen->sockaddr, size); 2454 2455 rt = task->thread->runtime; 2456 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2457 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2458 2459 stream = nxt_port_rpc_register_handler(task, router_port, 2460 nxt_router_listen_socket_ready, 2461 nxt_router_listen_socket_error, 2462 main_port->pid, rpc); 2463 if (nxt_slow_path(stream == 0)) { 2464 goto fail; 2465 } 2466 2467 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, 2468 stream, router_port->id, b); 2469 2470 if (nxt_slow_path(ret != NXT_OK)) { 2471 nxt_port_rpc_cancel(task, router_port, stream); 2472 goto fail; 2473 } 2474 2475 return; 2476 2477fail: 2478 2479 nxt_router_conf_error(task, tmcf); 2480} 2481 2482 2483static void 2484nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2485 void *data) 2486{ 2487 nxt_int_t ret; 2488 nxt_socket_t s; 2489 nxt_socket_rpc_t *rpc; 2490 2491 rpc = data; 2492 2493 s = msg->fd[0]; 2494 2495 ret = nxt_socket_nonblocking(task, s); 2496 if (nxt_slow_path(ret != NXT_OK)) { 2497 goto fail; 2498 } 2499 2500 nxt_socket_defer_accept(task, s, rpc->socket_conf->listen->sockaddr); 2501 2502 ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 2503 if (nxt_slow_path(ret != NXT_OK)) { 2504 goto fail; 2505 } 2506 2507 rpc->socket_conf->listen->socket = s; 2508 2509 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 2510 nxt_router_conf_apply, task, rpc->temp_conf, NULL); 2511 2512 return; 2513 2514fail: 2515 2516 nxt_socket_close(task, s); 2517 2518 nxt_router_conf_error(task, rpc->temp_conf); 2519} 2520 2521 2522static void 2523nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2524 void *data) 2525{ 2526 nxt_socket_rpc_t *rpc; 2527 nxt_router_temp_conf_t *tmcf; 2528 2529 rpc = data; 2530 tmcf = rpc->temp_conf; 2531 2532#if 0 2533 u_char *p; 2534 size_t size; 2535 uint8_t error; 2536 nxt_buf_t *in, *out; 2537 nxt_sockaddr_t *sa; 2538 2539 static nxt_str_t socket_errors[] = { 2540 nxt_string("ListenerSystem"), 2541 nxt_string("ListenerNoIPv6"), 2542 nxt_string("ListenerPort"), 2543 nxt_string("ListenerInUse"), 2544 nxt_string("ListenerNoAddress"), 2545 nxt_string("ListenerNoAccess"), 2546 nxt_string("ListenerPath"), 2547 }; 2548 2549 sa = rpc->socket_conf->listen->sockaddr; 2550 2551 in = nxt_buf_chk_make_plain(tmcf->mem_pool, msg->buf, msg->size); 2552 2553 if (nxt_slow_path(in == NULL)) { 2554 return; 2555 } 2556 2557 p = in->mem.pos; 2558 2559 error = *p++; 2560 2561 size = nxt_length("listen socket error: ") 2562 + nxt_length("{listener: \"\", code:\"\", message: \"\"}") 2563 + sa->length + socket_errors[error].length + (in->mem.free - p); 2564 2565 out = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2566 if (nxt_slow_path(out == NULL)) { 2567 return; 2568 } 2569 2570 out->mem.free = nxt_sprintf(out->mem.free, out->mem.end, 2571 "listen socket error: " 2572 "{listener: \"%*s\", code:\"%V\", message: \"%*s\"}", 2573 (size_t) sa->length, nxt_sockaddr_start(sa), 2574 &socket_errors[error], in->mem.free - p, p); 2575 2576 nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos); 2577#endif 2578 2579 nxt_router_conf_error(task, tmcf); 2580} 2581 2582 2583#if (NXT_TLS) 2584 2585static void 2586nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2587 void *data) 2588{ 2589 nxt_mp_t *mp; 2590 nxt_int_t ret; 2591 nxt_tls_conf_t *tlscf; 2592 nxt_router_tlssock_t *tls; 2593 nxt_tls_bundle_conf_t *bundle; 2594 nxt_router_temp_conf_t *tmcf; 2595 2596 nxt_debug(task, "tls rpc handler"); 2597 2598 tls = data; 2599 tmcf = tls->temp_conf; 2600 2601 if (msg == NULL || msg->port_msg.type == _NXT_PORT_MSG_RPC_ERROR) { 2602 goto fail; 2603 } 2604 2605 mp = tmcf->router_conf->mem_pool; 2606 2607 if (tls->socket_conf->tls == NULL){ 2608 tlscf = nxt_mp_zget(mp, sizeof(nxt_tls_conf_t)); 2609 if (nxt_slow_path(tlscf == NULL)) { 2610 goto fail; 2611 } 2612 2613 tlscf->no_wait_shutdown = 1; 2614 tls->socket_conf->tls = tlscf; 2615 2616 } else { 2617 tlscf = tls->socket_conf->tls; 2618 } 2619 2620 tls->tls_init->conf = tlscf; 2621 2622 bundle = nxt_mp_get(mp, sizeof(nxt_tls_bundle_conf_t)); 2623 if (nxt_slow_path(bundle == NULL)) { 2624 goto fail; 2625 } 2626 2627 if (nxt_slow_path(nxt_str_dup(mp, &bundle->name, &tls->name) == NULL)) { 2628 goto fail; 2629 } 2630 2631 bundle->chain_file = msg->fd[0]; 2632 bundle->next = tlscf->bundle; 2633 tlscf->bundle = bundle; 2634 2635 ret = task->thread->runtime->tls->server_init(task, mp, tls->tls_init, 2636 tls->last); 2637 if (nxt_slow_path(ret != NXT_OK)) { 2638 goto fail; 2639 } 2640 2641 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 2642 nxt_router_conf_apply, task, tmcf, NULL); 2643 return; 2644 2645fail: 2646 2647 nxt_router_conf_error(task, tmcf); 2648} 2649 2650#endif 2651 2652 2653static void 2654nxt_router_app_rpc_create(nxt_task_t *task, 2655 nxt_router_temp_conf_t *tmcf, nxt_app_t *app) 2656{ 2657 size_t size; 2658 uint32_t stream; 2659 nxt_int_t ret; 2660 nxt_buf_t *b; 2661 nxt_port_t *main_port, *router_port; 2662 nxt_runtime_t *rt; 2663 nxt_app_rpc_t *rpc; 2664 2665 rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_app_rpc_t)); 2666 if (rpc == NULL) { 2667 goto fail; 2668 } 2669 2670 rpc->app = app; 2671 rpc->temp_conf = tmcf; 2672 2673 nxt_debug(task, "app '%V' prefork", &app->name); 2674 2675 size = app->name.length + 1 + app->conf.length; 2676 2677 b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 2678 if (nxt_slow_path(b == NULL)) { 2679 goto fail; 2680 } 2681 2682 b->completion_handler = nxt_router_dummy_buf_completion; 2683 2684 nxt_buf_cpystr(b, &app->name); 2685 *b->mem.free++ = '\0'; 2686 nxt_buf_cpystr(b, &app->conf); 2687 2688 rt = task->thread->runtime; 2689 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2690 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2691 2692 stream = nxt_port_rpc_register_handler(task, router_port, 2693 nxt_router_app_prefork_ready, 2694 nxt_router_app_prefork_error, 2695 -1, rpc); 2696 if (nxt_slow_path(stream == 0)) { 2697 goto fail; 2698 } 2699 2700 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS, 2701 -1, stream, router_port->id, b); 2702 2703 if (nxt_slow_path(ret != NXT_OK)) { 2704 nxt_port_rpc_cancel(task, router_port, stream); 2705 goto fail; 2706 } 2707 2708 app->pending_processes++; 2709 2710 return; 2711 2712fail: 2713 2714 nxt_router_conf_error(task, tmcf); 2715} 2716 2717 2718static void 2719nxt_router_app_prefork_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2720 void *data) 2721{ 2722 nxt_app_t *app; 2723 nxt_port_t *port; 2724 nxt_app_rpc_t *rpc; 2725 nxt_event_engine_t *engine; 2726 2727 rpc = data; 2728 app = rpc->app; 2729 2730 port = msg->u.new_port; 2731 2732 nxt_assert(port != NULL); 2733 nxt_assert(port->type == NXT_PROCESS_APP); 2734 nxt_assert(port->id == 0); 2735 2736 port->app = app; 2737 port->main_app_port = port; 2738 2739 app->pending_processes--; 2740 app->processes++; 2741 app->idle_processes++; 2742 2743 engine = task->thread->engine; 2744 2745 nxt_queue_insert_tail(&app->ports, &port->app_link); 2746 nxt_queue_insert_tail(&app->spare_ports, &port->idle_link); 2747 2748 nxt_debug(task, "app '%V' move new port %PI:%d to spare_ports", 2749 &app->name, port->pid, port->id); 2750 2751 nxt_port_hash_add(&app->port_hash, port); 2752 app->port_hash_count++; 2753 2754 port->idle_start = 0; 2755 2756 nxt_port_inc_use(port); 2757 2758 nxt_router_app_shared_port_send(task, port); 2759 2760 nxt_work_queue_add(&engine->fast_work_queue, 2761 nxt_router_conf_apply, task, rpc->temp_conf, NULL); 2762} 2763 2764 2765static void 2766nxt_router_app_prefork_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 2767 void *data) 2768{ 2769 nxt_app_t *app; 2770 nxt_app_rpc_t *rpc; 2771 nxt_router_temp_conf_t *tmcf; 2772 2773 rpc = data; 2774 app = rpc->app; 2775 tmcf = rpc->temp_conf; 2776 2777 nxt_log(task, NXT_LOG_WARN, "failed to start application \"%V\"", 2778 &app->name); 2779 2780 app->pending_processes--; 2781 2782 nxt_router_conf_error(task, tmcf); 2783} 2784 2785 2786static nxt_int_t 2787nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 2788 nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 2789{ 2790 nxt_int_t ret; 2791 nxt_uint_t n, threads; 2792 nxt_queue_link_t *qlk; 2793 nxt_router_engine_conf_t *recf; 2794 2795 threads = tmcf->router_conf->threads; 2796 2797 tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 2798 sizeof(nxt_router_engine_conf_t)); 2799 if (nxt_slow_path(tmcf->engines == NULL)) { 2800 return NXT_ERROR; 2801 } 2802 2803 n = 0; 2804 2805 for (qlk = nxt_queue_first(&router->engines); 2806 qlk != nxt_queue_tail(&router->engines); 2807 qlk = nxt_queue_next(qlk)) 2808 { 2809 recf = nxt_array_zero_add(tmcf->engines); 2810 if (nxt_slow_path(recf == NULL)) { 2811 return NXT_ERROR; 2812 } 2813 2814 recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 2815 2816 if (n < threads) { 2817 recf->action = NXT_ROUTER_ENGINE_KEEP; 2818 ret = nxt_router_engine_conf_update(tmcf, recf); 2819 2820 } else { 2821 recf->action = NXT_ROUTER_ENGINE_DELETE; 2822 ret = nxt_router_engine_conf_delete(tmcf, recf); 2823 } 2824 2825 if (nxt_slow_path(ret != NXT_OK)) { 2826 return ret; 2827 } 2828 2829 n++; 2830 } 2831 2832 tmcf->new_threads = n; 2833 2834 while (n < threads) { 2835 recf = nxt_array_zero_add(tmcf->engines); 2836 if (nxt_slow_path(recf == NULL)) { 2837 return NXT_ERROR; 2838 } 2839 2840 recf->action = NXT_ROUTER_ENGINE_ADD; 2841 2842 recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 2843 if (nxt_slow_path(recf->engine == NULL)) { 2844 return NXT_ERROR; 2845 } 2846 2847 ret = nxt_router_engine_conf_create(tmcf, recf); 2848 if (nxt_slow_path(ret != NXT_OK)) { 2849 return ret; 2850 } 2851 2852 n++; 2853 } 2854 2855 return NXT_OK; 2856} 2857 2858 2859static nxt_int_t 2860nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 2861 nxt_router_engine_conf_t *recf) 2862{ 2863 nxt_int_t ret; 2864 2865 ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, 2866 nxt_router_listen_socket_create); 2867 if (nxt_slow_path(ret != NXT_OK)) { 2868 return ret; 2869 } 2870 2871 ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, 2872 nxt_router_listen_socket_create); 2873 if (nxt_slow_path(ret != NXT_OK)) { 2874 return ret; 2875 } 2876 2877 return ret; 2878} 2879 2880 2881static nxt_int_t 2882nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 2883 nxt_router_engine_conf_t *recf) 2884{ 2885 nxt_int_t ret; 2886 2887 ret = nxt_router_engine_joints_create(tmcf, recf, &creating_sockets, 2888 nxt_router_listen_socket_create); 2889 if (nxt_slow_path(ret != NXT_OK)) { 2890 return ret; 2891 } 2892 2893 ret = nxt_router_engine_joints_create(tmcf, recf, &updating_sockets, 2894 nxt_router_listen_socket_update); 2895 if (nxt_slow_path(ret != NXT_OK)) { 2896 return ret; 2897 } 2898 2899 ret = nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); 2900 if (nxt_slow_path(ret != NXT_OK)) { 2901 return ret; 2902 } 2903 2904 return ret; 2905} 2906 2907 2908static nxt_int_t 2909nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 2910 nxt_router_engine_conf_t *recf) 2911{ 2912 nxt_int_t ret; 2913 2914 ret = nxt_router_engine_quit(tmcf, recf); 2915 if (nxt_slow_path(ret != NXT_OK)) { 2916 return ret; 2917 } 2918 2919 ret = nxt_router_engine_joints_delete(tmcf, recf, &updating_sockets); 2920 if (nxt_slow_path(ret != NXT_OK)) { 2921 return ret; 2922 } 2923 2924 return nxt_router_engine_joints_delete(tmcf, recf, &deleting_sockets); 2925} 2926 2927 2928static nxt_int_t 2929nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 2930 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 2931 nxt_work_handler_t handler) 2932{ 2933 nxt_int_t ret; 2934 nxt_joint_job_t *job; 2935 nxt_queue_link_t *qlk; 2936 nxt_socket_conf_t *skcf; 2937 nxt_socket_conf_joint_t *joint; 2938 2939 for (qlk = nxt_queue_first(sockets); 2940 qlk != nxt_queue_tail(sockets); 2941 qlk = nxt_queue_next(qlk)) 2942 { 2943 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 2944 if (nxt_slow_path(job == NULL)) { 2945 return NXT_ERROR; 2946 } 2947 2948 job->work.next = recf->jobs; 2949 recf->jobs = &job->work; 2950 2951 job->task = tmcf->engine->task; 2952 job->work.handler = handler; 2953 job->work.task = &job->task; 2954 job->work.obj = job; 2955 job->tmcf = tmcf; 2956 2957 tmcf->count++; 2958 2959 joint = nxt_mp_alloc(tmcf->router_conf->mem_pool, 2960 sizeof(nxt_socket_conf_joint_t)); 2961 if (nxt_slow_path(joint == NULL)) { 2962 return NXT_ERROR; 2963 } 2964 2965 job->work.data = joint; 2966 2967 ret = nxt_upstreams_joint_create(tmcf, &joint->upstreams); 2968 if (nxt_slow_path(ret != NXT_OK)) { 2969 return ret; 2970 } 2971 2972 joint->count = 1; 2973 2974 skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 2975 skcf->count++; 2976 joint->socket_conf = skcf; 2977 2978 joint->engine = recf->engine; 2979 } 2980 2981 return NXT_OK; 2982} 2983 2984 2985static nxt_int_t 2986nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf, 2987 nxt_router_engine_conf_t *recf) 2988{ 2989 nxt_joint_job_t *job; 2990 2991 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 2992 if (nxt_slow_path(job == NULL)) { 2993 return NXT_ERROR; 2994 } 2995 2996 job->work.next = recf->jobs; 2997 recf->jobs = &job->work; 2998 2999 job->task = tmcf->engine->task; 3000 job->work.handler = nxt_router_worker_thread_quit; 3001 job->work.task = &job->task; 3002 job->work.obj = NULL; 3003 job->work.data = NULL; 3004 job->tmcf = NULL; 3005 3006 return NXT_OK; 3007} 3008 3009 3010static nxt_int_t 3011nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 3012 nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 3013{ 3014 nxt_joint_job_t *job; 3015 nxt_queue_link_t *qlk; 3016 3017 for (qlk = nxt_queue_first(sockets); 3018 qlk != nxt_queue_tail(sockets); 3019 qlk = nxt_queue_next(qlk)) 3020 { 3021 job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 3022 if (nxt_slow_path(job == NULL)) { 3023 return NXT_ERROR; 3024 } 3025 3026 job->work.next = recf->jobs; 3027 recf->jobs = &job->work; 3028 3029 job->task = tmcf->engine->task; 3030 job->work.handler = nxt_router_listen_socket_delete; 3031 job->work.task = &job->task; 3032 job->work.obj = job; 3033 job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 3034 job->tmcf = tmcf; 3035 3036 tmcf->count++; 3037 } 3038 3039 return NXT_OK; 3040} 3041 3042 3043static nxt_int_t 3044nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 3045 nxt_router_temp_conf_t *tmcf) 3046{ 3047 nxt_int_t ret; 3048 nxt_uint_t i, threads; 3049 nxt_router_engine_conf_t *recf; 3050 3051 recf = tmcf->engines->elts; 3052 threads = tmcf->router_conf->threads; 3053 3054 for (i = tmcf->new_threads; i < threads; i++) { 3055 ret = nxt_router_thread_create(task, rt, recf[i].engine); 3056 if (nxt_slow_path(ret != NXT_OK)) { 3057 return ret; 3058 } 3059 } 3060 3061 return NXT_OK; 3062} 3063 3064 3065static nxt_int_t 3066nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 3067 nxt_event_engine_t *engine) 3068{ 3069 nxt_int_t ret; 3070 nxt_thread_link_t *link; 3071 nxt_thread_handle_t handle; 3072 3073 link = nxt_zalloc(sizeof(nxt_thread_link_t)); 3074 3075 if (nxt_slow_path(link == NULL)) { 3076 return NXT_ERROR; 3077 } 3078 3079 link->start = nxt_router_thread_start; 3080 link->engine = engine; 3081 link->work.handler = nxt_router_thread_exit_handler; 3082 link->work.task = task; 3083 link->work.data = link; 3084 3085 nxt_queue_insert_tail(&rt->engines, &engine->link); 3086 3087 ret = nxt_thread_create(&handle, link); 3088 3089 if (nxt_slow_path(ret != NXT_OK)) { 3090 nxt_queue_remove(&engine->link); 3091 } 3092 3093 return ret; 3094} 3095 3096 3097static void 3098nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router, 3099 nxt_router_temp_conf_t *tmcf) 3100{ 3101 nxt_app_t *app; 3102 3103 nxt_queue_each(app, &router->apps, nxt_app_t, link) { 3104 3105 nxt_router_app_unlink(task, app); 3106 3107 } nxt_queue_loop; 3108 3109 nxt_queue_add(&router->apps, &tmcf->previous); 3110 nxt_queue_add(&router->apps, &tmcf->apps); 3111} 3112 3113 3114static void 3115nxt_router_engines_post(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 3116{ 3117 nxt_uint_t n; 3118 nxt_event_engine_t *engine; 3119 nxt_router_engine_conf_t *recf; 3120 3121 recf = tmcf->engines->elts; 3122 3123 for (n = tmcf->engines->nelts; n != 0; n--) { 3124 engine = recf->engine; 3125 3126 switch (recf->action) { 3127 3128 case NXT_ROUTER_ENGINE_KEEP: 3129 break; 3130 3131 case NXT_ROUTER_ENGINE_ADD: 3132 nxt_queue_insert_tail(&router->engines, &engine->link0); 3133 break; 3134 3135 case NXT_ROUTER_ENGINE_DELETE: 3136 nxt_queue_remove(&engine->link0); 3137 break; 3138 } 3139 3140 nxt_router_engine_post(engine, recf->jobs); 3141 3142 recf++; 3143 } 3144} 3145 3146 3147static void 3148nxt_router_engine_post(nxt_event_engine_t *engine, nxt_work_t *jobs) 3149{ 3150 nxt_work_t *work, *next; 3151 3152 for (work = jobs; work != NULL; work = next) { 3153 next = work->next; 3154 work->next = NULL; 3155 3156 nxt_event_engine_post(engine, work); 3157 } 3158} 3159 3160 3161static nxt_port_handlers_t nxt_router_app_port_handlers = { 3162 .rpc_error = nxt_port_rpc_handler, 3163 .mmap = nxt_port_mmap_handler, 3164 .data = nxt_port_rpc_handler, 3165 .oosm = nxt_router_oosm_handler, 3166 .req_headers_ack = nxt_port_rpc_handler, 3167}; 3168 3169 3170static void 3171nxt_router_thread_start(void *data) 3172{ 3173 nxt_int_t ret; 3174 nxt_port_t *port; 3175 nxt_task_t *task; 3176 nxt_work_t *work; 3177 nxt_thread_t *thread; 3178 nxt_thread_link_t *link; 3179 nxt_event_engine_t *engine; 3180 3181 link = data; 3182 engine = link->engine; 3183 task = &engine->task; 3184 3185 thread = nxt_thread(); 3186 3187 nxt_event_engine_thread_adopt(engine); 3188 3189 /* STUB */ 3190 thread->runtime = engine->task.thread->runtime; 3191 3192 engine->task.thread = thread; 3193 engine->task.log = thread->log; 3194 thread->engine = engine; 3195 thread->task = &engine->task; 3196#if 0 3197 thread->fiber = &engine->fibers->fiber; 3198#endif 3199 3200 engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 3201 if (nxt_slow_path(engine->mem_pool == NULL)) { 3202 return; 3203 } 3204 3205 port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, 3206 NXT_PROCESS_ROUTER); 3207 if (nxt_slow_path(port == NULL)) { 3208 return; 3209 } 3210 3211 ret = nxt_port_socket_init(task, port, 0); 3212 if (nxt_slow_path(ret != NXT_OK)) { 3213 nxt_port_use(task, port, -1); 3214 return; 3215 } 3216 3217 ret = nxt_router_port_queue_init(task, port); 3218 if (nxt_slow_path(ret != NXT_OK)) { 3219 nxt_port_use(task, port, -1); 3220 return; 3221 } 3222 3223 engine->port = port; 3224 3225 nxt_port_enable(task, port, &nxt_router_app_port_handlers); 3226 3227 work = nxt_zalloc(sizeof(nxt_work_t)); 3228 if (nxt_slow_path(work == NULL)) { 3229 return; 3230 } 3231 3232 work->handler = nxt_router_rt_add_port; 3233 work->task = link->work.task; 3234 work->obj = work; 3235 work->data = port; 3236 3237 nxt_event_engine_post(link->work.task->thread->engine, work); 3238 3239 nxt_event_engine_start(engine); 3240} 3241 3242 3243static void 3244nxt_router_rt_add_port(nxt_task_t *task, void *obj, void *data) 3245{ 3246 nxt_int_t res; 3247 nxt_port_t *port; 3248 nxt_runtime_t *rt; 3249 3250 rt = task->thread->runtime; 3251 port = data; 3252 3253 nxt_free(obj); 3254 3255 res = nxt_port_hash_add(&rt->ports, port); 3256 3257 if (nxt_fast_path(res == NXT_OK)) { 3258 nxt_port_use(task, port, 1); 3259 } 3260} 3261 3262 3263static void 3264nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 3265{ 3266 nxt_joint_job_t *job; 3267 nxt_socket_conf_t *skcf; 3268 nxt_listen_event_t *lev; 3269 nxt_listen_socket_t *ls; 3270 nxt_thread_spinlock_t *lock; 3271 nxt_socket_conf_joint_t *joint; 3272 3273 job = obj; 3274 joint = data; 3275 3276 nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); 3277 3278 skcf = joint->socket_conf; 3279 ls = skcf->listen; 3280 3281 lev = nxt_listen_event(task, ls); 3282 if (nxt_slow_path(lev == NULL)) { 3283 nxt_router_listen_socket_release(task, skcf); 3284 return; 3285 } 3286 3287 lev->socket.data = joint; 3288 3289 lock = &skcf->router_conf->router->lock; 3290 3291 nxt_thread_spin_lock(lock); 3292 ls->count++; 3293 nxt_thread_spin_unlock(lock); 3294 3295 job->work.next = NULL; 3296 job->work.handler = nxt_router_conf_wait; 3297 3298 nxt_event_engine_post(job->tmcf->engine, &job->work); 3299} 3300 3301 3302nxt_inline nxt_listen_event_t * 3303nxt_router_listen_event(nxt_queue_t *listen_connections, 3304 nxt_socket_conf_t *skcf) 3305{ 3306 nxt_socket_t fd; 3307 nxt_queue_link_t *qlk; 3308 nxt_listen_event_t *lev; 3309 3310 fd = skcf->listen->socket; 3311 3312 for (qlk = nxt_queue_first(listen_connections); 3313 qlk != nxt_queue_tail(listen_connections); 3314 qlk = nxt_queue_next(qlk)) 3315 { 3316 lev = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 3317 3318 if (fd == lev->socket.fd) { 3319 return lev; 3320 } 3321 } 3322 3323 return NULL; 3324} 3325 3326 3327static void 3328nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 3329{ 3330 nxt_joint_job_t *job; 3331 nxt_event_engine_t *engine; 3332 nxt_listen_event_t *lev; 3333 nxt_socket_conf_joint_t *joint, *old; 3334 3335 job = obj; 3336 joint = data; 3337 3338 engine = task->thread->engine; 3339 3340 nxt_queue_insert_tail(&engine->joints, &joint->link); 3341 3342 lev = nxt_router_listen_event(&engine->listen_connections, 3343 joint->socket_conf); 3344 3345 old = lev->socket.data; 3346 lev->socket.data = joint; 3347 lev->listen = joint->socket_conf->listen; 3348 3349 job->work.next = NULL; 3350 job->work.handler = nxt_router_conf_wait; 3351 3352 nxt_event_engine_post(job->tmcf->engine, &job->work); 3353 3354 /* 3355 * The task is allocated from configuration temporary 3356 * memory pool so it can be freed after engine post operation. 3357 */ 3358 3359 nxt_router_conf_release(&engine->task, old); 3360} 3361 3362 3363static void 3364nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 3365{ 3366 nxt_socket_conf_t *skcf; 3367 nxt_listen_event_t *lev; 3368 nxt_event_engine_t *engine; 3369 nxt_socket_conf_joint_t *joint; 3370 3371 skcf = data; 3372 3373 engine = task->thread->engine; 3374 3375 lev = nxt_router_listen_event(&engine->listen_connections, skcf); 3376 3377 nxt_fd_event_delete(engine, &lev->socket); 3378 3379 nxt_debug(task, "engine %p: listen socket delete: %d", engine, 3380 lev->socket.fd); 3381 3382 joint = lev->socket.data; 3383 joint->close_job = obj; 3384 3385 lev->timer.handler = nxt_router_listen_socket_close; 3386 lev->timer.work_queue = &engine->fast_work_queue; 3387 3388 nxt_timer_add(engine, &lev->timer, 0); 3389} 3390 3391 3392static void 3393nxt_router_worker_thread_quit(nxt_task_t *task, void *obj, void *data) 3394{ 3395 nxt_event_engine_t *engine; 3396 3397 nxt_debug(task, "router worker thread quit"); 3398 3399 engine = task->thread->engine; 3400 3401 engine->shutdown = 1; 3402 3403 if (nxt_queue_is_empty(&engine->joints)) { 3404 nxt_thread_exit(task->thread); 3405 } 3406} 3407 3408 3409static void 3410nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 3411{ 3412 nxt_timer_t *timer; 3413 nxt_joint_job_t *job; 3414 nxt_listen_event_t *lev; 3415 nxt_socket_conf_joint_t *joint; 3416 3417 timer = obj; 3418 lev = nxt_timer_data(timer, nxt_listen_event_t, timer); 3419 3420 nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, 3421 lev->socket.fd); 3422 3423 nxt_queue_remove(&lev->link); 3424 3425 joint = lev->socket.data; 3426 lev->socket.data = NULL; 3427 3428 /* 'task' refers to lev->task and we cannot use after nxt_free() */ 3429 task = &task->thread->engine->task; 3430 3431 nxt_router_listen_socket_release(task, joint->socket_conf); 3432 3433 job = joint->close_job; 3434 job->work.next = NULL; 3435 job->work.handler = nxt_router_conf_wait; 3436 3437 nxt_event_engine_post(job->tmcf->engine, &job->work); 3438 3439 nxt_router_listen_event_release(task, lev, joint); 3440} 3441 3442 3443static void 3444nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf) 3445{ 3446 nxt_listen_socket_t *ls; 3447 nxt_thread_spinlock_t *lock; 3448 3449 ls = skcf->listen; 3450 lock = &skcf->router_conf->router->lock; 3451 3452 nxt_thread_spin_lock(lock); 3453 3454 nxt_debug(task, "engine %p: listen socket release: ls->count %D", 3455 task->thread->engine, ls->count); 3456 3457 if (--ls->count != 0) { 3458 ls = NULL; 3459 } 3460 3461 nxt_thread_spin_unlock(lock); 3462 3463 if (ls != NULL) { 3464 nxt_socket_close(task, ls->socket); 3465 nxt_free(ls); 3466 } 3467} 3468 3469 3470void 3471nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, 3472 nxt_socket_conf_joint_t *joint) 3473{ 3474 nxt_event_engine_t *engine; 3475 3476 nxt_debug(task, "listen event count: %D", lev->count); 3477 3478 engine = task->thread->engine; 3479 3480 if (--lev->count == 0) { 3481 if (lev->next != NULL) { 3482 nxt_sockaddr_cache_free(engine, lev->next); 3483 3484 nxt_conn_free(task, lev->next); 3485 } 3486 3487 nxt_free(lev); 3488 } 3489 3490 if (joint != NULL) { 3491 nxt_router_conf_release(task, joint); 3492 } 3493 3494 if (engine->shutdown && nxt_queue_is_empty(&engine->joints)) { 3495 nxt_thread_exit(task->thread); 3496 } 3497} 3498 3499 3500void 3501nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 3502{ 3503 nxt_socket_conf_t *skcf; 3504 nxt_router_conf_t *rtcf; 3505 nxt_thread_spinlock_t *lock; 3506 3507 nxt_debug(task, "conf joint %p count: %D", joint, joint->count); 3508 3509 if (--joint->count != 0) { 3510 return; 3511 } 3512 3513 nxt_queue_remove(&joint->link); 3514 3515 /* 3516 * The joint content can not be safely used after the critical 3517 * section protected by the spinlock because its memory pool may 3518 * be already destroyed by another thread. 3519 */ 3520 skcf = joint->socket_conf; 3521 rtcf = skcf->router_conf; 3522 lock = &rtcf->router->lock; 3523 3524 nxt_thread_spin_lock(lock); 3525 3526 nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, 3527 rtcf, rtcf->count); 3528 3529 if (--skcf->count != 0) { 3530 skcf = NULL; 3531 rtcf = NULL; 3532 3533 } else { 3534 nxt_queue_remove(&skcf->link); 3535 3536 if (--rtcf->count != 0) { 3537 rtcf = NULL; 3538 } 3539 } 3540 3541 nxt_thread_spin_unlock(lock); 3542 3543#if (NXT_TLS) 3544 if (skcf != NULL && skcf->tls != NULL) { 3545 task->thread->runtime->tls->server_free(task, skcf->tls); 3546 } 3547#endif 3548 3549 /* TODO remove engine->port */ 3550 3551 if (rtcf != NULL) { 3552 nxt_debug(task, "old router conf is destroyed"); 3553 3554 nxt_router_apps_hash_use(task, rtcf, -1); 3555 3556 nxt_router_access_log_release(task, lock, rtcf->access_log); 3557 3558 nxt_mp_thread_adopt(rtcf->mem_pool); 3559 3560 nxt_mp_destroy(rtcf->mem_pool); 3561 } 3562} 3563 3564 3565static void 3566nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, 3567 nxt_router_access_log_t *access_log) 3568{ 3569 size_t size; 3570 u_char *buf, *p; 3571 nxt_off_t bytes; 3572 3573 static nxt_time_string_t date_cache = { 3574 (nxt_atomic_uint_t) -1, 3575 nxt_router_access_log_date, 3576 "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", 3577 nxt_length("31/Dec/1986:19:40:00 +0300"), 3578 NXT_THREAD_TIME_LOCAL, 3579 NXT_THREAD_TIME_SEC, 3580 }; 3581 3582 size = r->remote->address_length 3583 + 6 /* ' - - [' */ 3584 + date_cache.size 3585 + 3 /* '] "' */ 3586 + r->method->length 3587 + 1 /* space */ 3588 + r->target.length 3589 + 1 /* space */ 3590 + r->version.length 3591 + 2 /* '" ' */ 3592 + 3 /* status */ 3593 + 1 /* space */ 3594 + NXT_OFF_T_LEN 3595 + 2 /* ' "' */ 3596 + (r->referer != NULL ? r->referer->value_length : 1) 3597 + 3 /* '" "' */ 3598 + (r->user_agent != NULL ? r->user_agent->value_length : 1) 3599 + 2 /* '"\n' */ 3600 ; 3601 3602 buf = nxt_mp_nget(r->mem_pool, size); 3603 if (nxt_slow_path(buf == NULL)) { 3604 return; 3605 } 3606 3607 p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), 3608 r->remote->address_length); 3609 3610 p = nxt_cpymem(p, " - - [", 6); 3611 3612 p = nxt_thread_time_string(task->thread, &date_cache, p); 3613 3614 p = nxt_cpymem(p, "] \"", 3); 3615 3616 if (r->method->length != 0) { 3617 p = nxt_cpymem(p, r->method->start, r->method->length); 3618 3619 if (r->target.length != 0) { 3620 *p++ = ' '; 3621 p = nxt_cpymem(p, r->target.start, r->target.length); 3622 3623 if (r->version.length != 0) { 3624 *p++ = ' '; 3625 p = nxt_cpymem(p, r->version.start, r->version.length); 3626 } 3627 } 3628 3629 } else { 3630 *p++ = '-'; 3631 } 3632 3633 p = nxt_cpymem(p, "\" ", 2); 3634 3635 p = nxt_sprintf(p, p + 3, "%03d", r->status); 3636 3637 *p++ = ' '; 3638 3639 bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); 3640 3641 p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); 3642 3643 p = nxt_cpymem(p, " \"", 2); 3644 3645 if (r->referer != NULL) { 3646 p = nxt_cpymem(p, r->referer->value, r->referer->value_length); 3647 3648 } else { 3649 *p++ = '-'; 3650 } 3651 3652 p = nxt_cpymem(p, "\" \"", 3); 3653 3654 if (r->user_agent != NULL) { 3655 p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); 3656 3657 } else { 3658 *p++ = '-'; 3659 } 3660 3661 p = nxt_cpymem(p, "\"\n", 2); 3662 3663 nxt_fd_write(access_log->fd, buf, p - buf); 3664} 3665 3666 3667static u_char * 3668nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, 3669 size_t size, const char *format) 3670{ 3671 u_char sign; 3672 time_t gmtoff; 3673 3674 static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 3675 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 3676 3677 gmtoff = nxt_timezone(tm) / 60; 3678 3679 if (gmtoff < 0) { 3680 gmtoff = -gmtoff; 3681 sign = '-'; 3682 3683 } else { 3684 sign = '+'; 3685 } 3686 3687 return nxt_sprintf(buf, buf + size, format, 3688 tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, 3689 tm->tm_hour, tm->tm_min, tm->tm_sec, 3690 sign, gmtoff / 60, gmtoff % 60); 3691} 3692 3693 3694static void 3695nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 3696{ 3697 uint32_t stream; 3698 nxt_int_t ret; 3699 nxt_buf_t *b; 3700 nxt_port_t *main_port, *router_port; 3701 nxt_runtime_t *rt; 3702 nxt_router_access_log_t *access_log; 3703 3704 access_log = tmcf->router_conf->access_log; 3705 3706 b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); 3707 if (nxt_slow_path(b == NULL)) { 3708 goto fail; 3709 } 3710 3711 b->completion_handler = nxt_router_dummy_buf_completion; 3712 3713 nxt_buf_cpystr(b, &access_log->path); 3714 *b->mem.free++ = '\0'; 3715 3716 rt = task->thread->runtime; 3717 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 3718 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 3719 3720 stream = nxt_port_rpc_register_handler(task, router_port, 3721 nxt_router_access_log_ready, 3722 nxt_router_access_log_error, 3723 -1, tmcf); 3724 if (nxt_slow_path(stream == 0)) { 3725 goto fail; 3726 } 3727 3728 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, 3729 stream, router_port->id, b); 3730 3731 if (nxt_slow_path(ret != NXT_OK)) { 3732 nxt_port_rpc_cancel(task, router_port, stream); 3733 goto fail; 3734 } 3735 3736 return; 3737 3738fail: 3739 3740 nxt_router_conf_error(task, tmcf); 3741} 3742 3743 3744static void 3745nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3746 void *data) 3747{ 3748 nxt_router_temp_conf_t *tmcf; 3749 nxt_router_access_log_t *access_log; 3750 3751 tmcf = data; 3752 3753 access_log = tmcf->router_conf->access_log; 3754 3755 access_log->fd = msg->fd[0]; 3756 3757 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 3758 nxt_router_conf_apply, task, tmcf, NULL); 3759} 3760 3761 3762static void 3763nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3764 void *data) 3765{ 3766 nxt_router_temp_conf_t *tmcf; 3767 3768 tmcf = data; 3769 3770 nxt_router_conf_error(task, tmcf); 3771} 3772 3773 3774static void 3775nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, 3776 nxt_router_access_log_t *access_log) 3777{ 3778 if (access_log == NULL) { 3779 return; 3780 } 3781 3782 nxt_thread_spin_lock(lock); 3783 3784 if (--access_log->count != 0) { 3785 access_log = NULL; 3786 } 3787 3788 nxt_thread_spin_unlock(lock); 3789 3790 if (access_log != NULL) { 3791 3792 if (access_log->fd != -1) { 3793 nxt_fd_close(access_log->fd); 3794 } 3795 3796 nxt_free(access_log); 3797 } 3798} 3799 3800 3801typedef struct { 3802 nxt_mp_t *mem_pool; 3803 nxt_router_access_log_t *access_log; 3804} nxt_router_access_log_reopen_t; 3805 3806 3807static void 3808nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 3809{ 3810 nxt_mp_t *mp; 3811 uint32_t stream; 3812 nxt_int_t ret; 3813 nxt_buf_t *b; 3814 nxt_port_t *main_port, *router_port; 3815 nxt_runtime_t *rt; 3816 nxt_router_access_log_t *access_log; 3817 nxt_router_access_log_reopen_t *reopen; 3818 3819 access_log = nxt_router->access_log; 3820 3821 if (access_log == NULL) { 3822 return; 3823 } 3824 3825 mp = nxt_mp_create(1024, 128, 256, 32); 3826 if (nxt_slow_path(mp == NULL)) { 3827 return; 3828 } 3829 3830 reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); 3831 if (nxt_slow_path(reopen == NULL)) { 3832 goto fail; 3833 } 3834 3835 reopen->mem_pool = mp; 3836 reopen->access_log = access_log; 3837 3838 b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); 3839 if (nxt_slow_path(b == NULL)) { 3840 goto fail; 3841 } 3842 3843 b->completion_handler = nxt_router_access_log_reopen_completion; 3844 3845 nxt_buf_cpystr(b, &access_log->path); 3846 *b->mem.free++ = '\0'; 3847 3848 rt = task->thread->runtime; 3849 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 3850 router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 3851 3852 stream = nxt_port_rpc_register_handler(task, router_port, 3853 nxt_router_access_log_reopen_ready, 3854 nxt_router_access_log_reopen_error, 3855 -1, reopen); 3856 if (nxt_slow_path(stream == 0)) { 3857 goto fail; 3858 } 3859 3860 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, 3861 stream, router_port->id, b); 3862 3863 if (nxt_slow_path(ret != NXT_OK)) { 3864 nxt_port_rpc_cancel(task, router_port, stream); 3865 goto fail; 3866 } 3867 3868 nxt_mp_retain(mp); 3869 3870 return; 3871 3872fail: 3873 3874 nxt_mp_destroy(mp); 3875} 3876 3877 3878static void 3879nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) 3880{ 3881 nxt_mp_t *mp; 3882 nxt_buf_t *b; 3883 3884 b = obj; 3885 mp = b->data; 3886 3887 nxt_mp_release(mp); 3888} 3889 3890 3891static void 3892nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3893 void *data) 3894{ 3895 nxt_router_access_log_t *access_log; 3896 nxt_router_access_log_reopen_t *reopen; 3897 3898 reopen = data; 3899 3900 access_log = reopen->access_log; 3901 3902 if (access_log == nxt_router->access_log) { 3903 3904 if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { 3905 nxt_alert(task, "dup2(%FD, %FD) failed %E", 3906 msg->fd[0], access_log->fd, nxt_errno); 3907 } 3908 } 3909 3910 nxt_fd_close(msg->fd[0]); 3911 nxt_mp_release(reopen->mem_pool); 3912} 3913 3914 3915static void 3916nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3917 void *data) 3918{ 3919 nxt_router_access_log_reopen_t *reopen; 3920 3921 reopen = data; 3922 3923 nxt_mp_release(reopen->mem_pool); 3924} 3925 3926 3927static void 3928nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 3929{ 3930 nxt_port_t *port; 3931 nxt_thread_link_t *link; 3932 nxt_event_engine_t *engine; 3933 nxt_thread_handle_t handle; 3934 3935 handle = (nxt_thread_handle_t) (uintptr_t) obj; 3936 link = data; 3937 3938 nxt_thread_wait(handle); 3939 3940 engine = link->engine; 3941 3942 nxt_queue_remove(&engine->link); 3943 3944 port = engine->port; 3945 3946 // TODO notify all apps 3947 3948 port->engine = task->thread->engine; 3949 nxt_mp_thread_adopt(port->mem_pool); 3950 nxt_port_use(task, port, -1); 3951 3952 nxt_mp_thread_adopt(engine->mem_pool); 3953 nxt_mp_destroy(engine->mem_pool); 3954 3955 nxt_event_engine_free(engine); 3956 3957 nxt_free(link); 3958} 3959 3960 3961static void 3962nxt_router_response_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 3963 void *data) 3964{ 3965 size_t b_size, count; 3966 nxt_int_t ret; 3967 nxt_app_t *app; 3968 nxt_buf_t *b, *next; 3969 nxt_port_t *app_port; 3970 nxt_unit_field_t *f; 3971 nxt_http_field_t *field; 3972 nxt_http_request_t *r; 3973 nxt_unit_response_t *resp; 3974 nxt_request_rpc_data_t *req_rpc_data; 3975 3976 req_rpc_data = data; 3977 3978 r = req_rpc_data->request; 3979 if (nxt_slow_path(r == NULL)) { 3980 return; 3981 } 3982 3983 if (r->error) { 3984 nxt_request_rpc_data_unlink(task, req_rpc_data); 3985 return; 3986 } 3987 3988 app = req_rpc_data->app; 3989 nxt_assert(app != NULL); 3990 3991 if (msg->port_msg.type == _NXT_PORT_MSG_REQ_HEADERS_ACK) { 3992 nxt_router_req_headers_ack_handler(task, msg, req_rpc_data); 3993 3994 return; 3995 } 3996 3997 b = (msg->size == 0) ? NULL : msg->buf; 3998 3999 if (msg->port_msg.last != 0) { 4000 nxt_debug(task, "router data create last buf"); 4001 4002 nxt_buf_chain_add(&b, nxt_http_buf_last(r)); 4003 4004 req_rpc_data->rpc_cancel = 0; 4005 4006 if (req_rpc_data->apr_action == NXT_APR_REQUEST_FAILED) { 4007 req_rpc_data->apr_action = NXT_APR_GOT_RESPONSE; 4008 } 4009 4010 nxt_request_rpc_data_unlink(task, req_rpc_data); 4011 4012 } else { 4013 if (app->timeout != 0) { 4014 r->timer.handler = nxt_router_app_timeout; 4015 r->timer_data = req_rpc_data; 4016 nxt_timer_add(task->thread->engine, &r->timer, app->timeout); 4017 } 4018 } 4019 4020 if (b == NULL) { 4021 return; 4022 } 4023 4024 if (msg->buf == b) { 4025 /* Disable instant buffer completion/re-using by port. */ 4026 msg->buf = NULL; 4027 } 4028 4029 if (r->header_sent) { 4030 nxt_buf_chain_add(&r->out, b); 4031 nxt_http_request_send_body(task, r, NULL); 4032 4033 } else { 4034 b_size = nxt_buf_is_mem(b) ? nxt_buf_mem_used_size(&b->mem) : 0; 4035 4036 if (nxt_slow_path(b_size < sizeof(nxt_unit_response_t))) { 4037 nxt_alert(task, "response buffer too small: %z", b_size); 4038 goto fail; 4039 } 4040 4041 resp = (void *) b->mem.pos; 4042 count = (b_size - sizeof(nxt_unit_response_t)) 4043 / sizeof(nxt_unit_field_t); 4044 4045 if (nxt_slow_path(count < resp->fields_count)) { 4046 nxt_alert(task, "response buffer too small for fields count: %D", 4047 resp->fields_count); 4048 goto fail; 4049 } 4050 4051 field = NULL; 4052 4053 for (f = resp->fields; f < resp->fields + resp->fields_count; f++) { 4054 if (f->skip) { 4055 continue; 4056 } 4057 4058 field = nxt_list_add(r->resp.fields); 4059 4060 if (nxt_slow_path(field == NULL)) { 4061 goto fail; 4062 } 4063 4064 field->hash = f->hash; 4065 field->skip = 0; 4066 field->hopbyhop = 0; 4067 4068 field->name_length = f->name_length; 4069 field->value_length = f->value_length; 4070 field->name = nxt_unit_sptr_get(&f->name); 4071 field->value = nxt_unit_sptr_get(&f->value); 4072 4073 ret = nxt_http_field_process(field, &nxt_response_fields_hash, r); 4074 if (nxt_slow_path(ret != NXT_OK)) { 4075 goto fail; 4076 } 4077 4078 nxt_debug(task, "header%s: %*s: %*s", 4079 (field->skip ? " skipped" : ""), 4080 (size_t) field->name_length, field->name, 4081 (size_t) field->value_length, field->value); 4082 4083 if (field->skip) { 4084 r->resp.fields->last->nelts--; 4085 } 4086 } 4087 4088 r->status = resp->status; 4089 4090 if (resp->piggyback_content_length != 0) { 4091 b->mem.pos = nxt_unit_sptr_get(&resp->piggyback_content); 4092 b->mem.free = b->mem.pos + resp->piggyback_content_length; 4093 4094 } else { 4095 b->mem.pos = b->mem.free; 4096 } 4097 4098 if (nxt_buf_mem_used_size(&b->mem) == 0) { 4099 next = b->next; 4100 b->next = NULL; 4101 4102 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 4103 b->completion_handler, task, b, b->parent); 4104 4105 b = next; 4106 } 4107 4108 if (b != NULL) { 4109 nxt_buf_chain_add(&r->out, b); 4110 } 4111 4112 nxt_http_request_header_send(task, r, nxt_http_request_send_body, NULL); 4113 4114 if (r->websocket_handshake 4115 && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) 4116 { 4117 app_port = req_rpc_data->app_port; 4118 if (nxt_slow_path(app_port == NULL)) { 4119 goto fail; 4120 } 4121 4122 nxt_thread_mutex_lock(&app->mutex); 4123 4124 app_port->main_app_port->active_websockets++; 4125 4126 nxt_thread_mutex_unlock(&app->mutex); 4127 4128 nxt_router_app_port_release(task, app_port, NXT_APR_UPGRADE); 4129 req_rpc_data->apr_action = NXT_APR_CLOSE; 4130 4131 nxt_debug(task, "stream #%uD upgrade", req_rpc_data->stream); 4132 4133 r->state = &nxt_http_websocket; 4134 4135 } else { 4136 r->state = &nxt_http_request_send_state; 4137 } 4138 } 4139 4140 return; 4141 4142fail: 4143 4144 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 4145 4146 nxt_request_rpc_data_unlink(task, req_rpc_data); 4147} 4148 4149 4150static void 4151nxt_router_req_headers_ack_handler(nxt_task_t *task, 4152 nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data) 4153{ 4154 int res; 4155 nxt_app_t *app; 4156 nxt_buf_t *b; 4157 nxt_bool_t start_process, unlinked; 4158 nxt_port_t *app_port, *main_app_port, *idle_port; 4159 nxt_queue_link_t *idle_lnk; 4160 nxt_http_request_t *r; 4161 4162 nxt_debug(task, "stream #%uD: got ack from %PI:%d", 4163 req_rpc_data->stream, 4164 msg->port_msg.pid, msg->port_msg.reply_port); 4165 4166 nxt_port_rpc_ex_set_peer(task, msg->port, req_rpc_data, 4167 msg->port_msg.pid); 4168 4169 app = req_rpc_data->app; 4170 r = req_rpc_data->request; 4171 4172 start_process = 0; 4173 unlinked = 0; 4174 4175 nxt_thread_mutex_lock(&app->mutex); 4176 4177 if (r->app_link.next != NULL) { 4178 nxt_queue_remove(&r->app_link); 4179 r->app_link.next = NULL; 4180 4181 unlinked = 1; 4182 } 4183 4184 app_port = nxt_port_hash_find(&app->port_hash, msg->port_msg.pid, 4185 msg->port_msg.reply_port); 4186 if (nxt_slow_path(app_port == NULL)) { 4187 nxt_thread_mutex_unlock(&app->mutex); 4188 4189 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 4190 4191 if (unlinked) { 4192 nxt_mp_release(r->mem_pool); 4193 } 4194 4195 return; 4196 } 4197 4198 main_app_port = app_port->main_app_port; 4199 4200 if (nxt_queue_chk_remove(&main_app_port->idle_link)) { 4201 app->idle_processes--; 4202 4203 nxt_debug(task, "app '%V' move port %PI:%d out of %s (ack)", 4204 &app->name, main_app_port->pid, main_app_port->id, 4205 (main_app_port->idle_start ? "idle_ports" : "spare_ports")); 4206 4207 /* Check port was in 'spare_ports' using idle_start field. */ 4208 if (main_app_port->idle_start == 0 4209 && app->idle_processes >= app->spare_processes) 4210 { 4211 /* 4212 * If there is a vacant space in spare ports, 4213 * move the last idle to spare_ports. 4214 */ 4215 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4216 4217 idle_lnk = nxt_queue_last(&app->idle_ports); 4218 idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); 4219 nxt_queue_remove(idle_lnk); 4220 4221 nxt_queue_insert_tail(&app->spare_ports, idle_lnk); 4222 4223 idle_port->idle_start = 0; 4224 4225 nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " 4226 "to spare_ports", 4227 &app->name, idle_port->pid, idle_port->id); 4228 } 4229 4230 if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { 4231 app->pending_processes++; 4232 start_process = 1; 4233 } 4234 } 4235 4236 main_app_port->active_requests++; 4237 4238 nxt_port_inc_use(app_port); 4239 4240 nxt_thread_mutex_unlock(&app->mutex); 4241 4242 if (unlinked) { 4243 nxt_mp_release(r->mem_pool); 4244 } 4245 4246 if (start_process) { 4247 nxt_router_start_app_process(task, app); 4248 } 4249 4250 nxt_port_use(task, req_rpc_data->app_port, -1); 4251 4252 req_rpc_data->app_port = app_port; 4253 4254 b = req_rpc_data->msg_info.buf; 4255 4256 if (b != NULL) { 4257 /* First buffer is already sent. Start from second. */ 4258 b = b->next; 4259 4260 req_rpc_data->msg_info.buf->next = NULL; 4261 } 4262 4263 if (req_rpc_data->msg_info.body_fd != -1 || b != NULL) { 4264 nxt_debug(task, "stream #%uD: send body fd %d", req_rpc_data->stream, 4265 req_rpc_data->msg_info.body_fd); 4266 4267 if (req_rpc_data->msg_info.body_fd != -1) { 4268 lseek(req_rpc_data->msg_info.body_fd, 0, SEEK_SET); 4269 } 4270 4271 res = nxt_port_socket_write(task, app_port, NXT_PORT_MSG_REQ_BODY, 4272 req_rpc_data->msg_info.body_fd, 4273 req_rpc_data->stream, 4274 task->thread->engine->port->id, b); 4275 4276 if (nxt_slow_path(res != NXT_OK)) { 4277 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 4278 } 4279 } 4280 4281 if (app->timeout != 0) { 4282 r->timer.handler = nxt_router_app_timeout; 4283 r->timer_data = req_rpc_data; 4284 nxt_timer_add(task->thread->engine, &r->timer, app->timeout); 4285 } 4286} 4287 4288 4289static const nxt_http_request_state_t nxt_http_request_send_state 4290 nxt_aligned(64) = 4291{ 4292 .error_handler = nxt_http_request_error_handler, 4293}; 4294 4295 4296static void 4297nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data) 4298{ 4299 nxt_buf_t *out; 4300 nxt_http_request_t *r; 4301 4302 r = obj; 4303 4304 out = r->out; 4305 4306 if (out != NULL) { 4307 r->out = NULL; 4308 nxt_http_request_send(task, r, out); 4309 } 4310} 4311 4312 4313static void 4314nxt_router_response_error_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4315 void *data) 4316{ 4317 nxt_request_rpc_data_t *req_rpc_data; 4318 4319 req_rpc_data = data; 4320 4321 req_rpc_data->rpc_cancel = 0; 4322 4323 /* TODO cancel message and return if cancelled. */ 4324 // nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream); 4325 4326 if (req_rpc_data->request != NULL) { 4327 nxt_http_request_error(task, req_rpc_data->request, 4328 NXT_HTTP_SERVICE_UNAVAILABLE); 4329 } 4330 4331 nxt_request_rpc_data_unlink(task, req_rpc_data); 4332} 4333 4334 4335static void 4336nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4337 void *data) 4338{
|
4236 nxt_app_t *app; 4237 nxt_port_t *port; 4238 nxt_app_joint_t *app_joint;
| 4339 nxt_app_t *app; 4340 nxt_bool_t start_process; 4341 nxt_port_t *port; 4342 nxt_app_joint_t *app_joint; 4343 nxt_app_joint_rpc_t *app_joint_rpc;
|
4239
| 4344
|
4240 app_joint = data;
| 4345 nxt_assert(data != NULL); 4346 4347 app_joint_rpc = data; 4348 app_joint = app_joint_rpc->app_joint;
|
4241 port = msg->u.new_port; 4242 4243 nxt_assert(app_joint != NULL); 4244 nxt_assert(port != NULL); 4245 nxt_assert(port->type == NXT_PROCESS_APP); 4246 nxt_assert(port->id == 0); 4247 4248 app = app_joint->app; 4249 4250 nxt_router_app_joint_use(task, app_joint, -1); 4251 4252 if (nxt_slow_path(app == NULL)) { 4253 nxt_debug(task, "new port ready for released app, send QUIT"); 4254 4255 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4256 4257 return; 4258 } 4259
| 4349 port = msg->u.new_port; 4350 4351 nxt_assert(app_joint != NULL); 4352 nxt_assert(port != NULL); 4353 nxt_assert(port->type == NXT_PROCESS_APP); 4354 nxt_assert(port->id == 0); 4355 4356 app = app_joint->app; 4357 4358 nxt_router_app_joint_use(task, app_joint, -1); 4359 4360 if (nxt_slow_path(app == NULL)) { 4361 nxt_debug(task, "new port ready for released app, send QUIT"); 4362 4363 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4364 4365 return; 4366 } 4367
|
4260 port->app = app; 4261 port->main_app_port = port; 4262
| |
4263 nxt_thread_mutex_lock(&app->mutex); 4264 4265 nxt_assert(app->pending_processes != 0); 4266 4267 app->pending_processes--;
| 4368 nxt_thread_mutex_lock(&app->mutex); 4369 4370 nxt_assert(app->pending_processes != 0); 4371 4372 app->pending_processes--;
|
| 4373 4374 if (nxt_slow_path(app->generation != app_joint_rpc->generation)) { 4375 nxt_debug(task, "new port ready for restarted app, send QUIT"); 4376 4377 start_process = !task->thread->engine->shutdown 4378 && nxt_router_app_can_start(app) 4379 && nxt_router_app_need_start(app); 4380 4381 if (start_process) { 4382 app->pending_processes++; 4383 } 4384 4385 nxt_thread_mutex_unlock(&app->mutex); 4386 4387 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4388 4389 if (start_process) { 4390 nxt_router_start_app_process(task, app); 4391 } 4392 4393 return; 4394 } 4395 4396 port->app = app; 4397 port->main_app_port = port; 4398
|
4268 app->processes++; 4269 nxt_port_hash_add(&app->port_hash, port); 4270 app->port_hash_count++; 4271 4272 nxt_thread_mutex_unlock(&app->mutex); 4273 4274 nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d", 4275 &app->name, port->pid, app->processes, app->pending_processes); 4276 4277 nxt_router_app_shared_port_send(task, port); 4278 4279 nxt_router_app_port_release(task, port, NXT_APR_NEW_PORT); 4280} 4281 4282 4283static nxt_int_t 4284nxt_router_app_shared_port_send(nxt_task_t *task, nxt_port_t *app_port) 4285{ 4286 nxt_buf_t *b; 4287 nxt_port_t *port; 4288 nxt_port_msg_new_port_t *msg; 4289 4290 b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 4291 sizeof(nxt_port_data_t)); 4292 if (nxt_slow_path(b == NULL)) { 4293 return NXT_ERROR; 4294 } 4295 4296 port = app_port->app->shared_port; 4297 4298 nxt_debug(task, "send port %FD to process %PI", 4299 port->pair[0], app_port->pid); 4300 4301 b->mem.free += sizeof(nxt_port_msg_new_port_t); 4302 msg = (nxt_port_msg_new_port_t *) b->mem.pos; 4303 4304 msg->id = port->id; 4305 msg->pid = port->pid; 4306 msg->max_size = port->max_size; 4307 msg->max_share = port->max_share; 4308 msg->type = port->type; 4309 4310 return nxt_port_socket_write2(task, app_port, 4311 NXT_PORT_MSG_NEW_PORT, 4312 port->pair[0], port->queue_fd, 4313 0, 0, b); 4314} 4315 4316 4317static void 4318nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4319 void *data) 4320{
| 4399 app->processes++; 4400 nxt_port_hash_add(&app->port_hash, port); 4401 app->port_hash_count++; 4402 4403 nxt_thread_mutex_unlock(&app->mutex); 4404 4405 nxt_debug(task, "app '%V' new port ready, pid %PI, %d/%d", 4406 &app->name, port->pid, app->processes, app->pending_processes); 4407 4408 nxt_router_app_shared_port_send(task, port); 4409 4410 nxt_router_app_port_release(task, port, NXT_APR_NEW_PORT); 4411} 4412 4413 4414static nxt_int_t 4415nxt_router_app_shared_port_send(nxt_task_t *task, nxt_port_t *app_port) 4416{ 4417 nxt_buf_t *b; 4418 nxt_port_t *port; 4419 nxt_port_msg_new_port_t *msg; 4420 4421 b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 4422 sizeof(nxt_port_data_t)); 4423 if (nxt_slow_path(b == NULL)) { 4424 return NXT_ERROR; 4425 } 4426 4427 port = app_port->app->shared_port; 4428 4429 nxt_debug(task, "send port %FD to process %PI", 4430 port->pair[0], app_port->pid); 4431 4432 b->mem.free += sizeof(nxt_port_msg_new_port_t); 4433 msg = (nxt_port_msg_new_port_t *) b->mem.pos; 4434 4435 msg->id = port->id; 4436 msg->pid = port->pid; 4437 msg->max_size = port->max_size; 4438 msg->max_share = port->max_share; 4439 msg->type = port->type; 4440 4441 return nxt_port_socket_write2(task, app_port, 4442 NXT_PORT_MSG_NEW_PORT, 4443 port->pair[0], port->queue_fd, 4444 0, 0, b); 4445} 4446 4447 4448static void 4449nxt_router_app_port_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 4450 void *data) 4451{
|
4321 nxt_app_t *app; 4322 nxt_app_joint_t *app_joint; 4323 nxt_queue_link_t *link; 4324 nxt_http_request_t *r;
| 4452 nxt_app_t *app; 4453 nxt_app_joint_t *app_joint; 4454 nxt_queue_link_t *link; 4455 nxt_http_request_t *r; 4456 nxt_app_joint_rpc_t *app_joint_rpc;
|
4325
| 4457
|
4326 app_joint = data;
| 4458 nxt_assert(data != NULL);
|
4327
| 4459
|
| 4460 app_joint_rpc = data; 4461 app_joint = app_joint_rpc->app_joint; 4462
|
4328 nxt_assert(app_joint != NULL); 4329 4330 app = app_joint->app; 4331 4332 nxt_router_app_joint_use(task, app_joint, -1); 4333 4334 if (nxt_slow_path(app == NULL)) { 4335 nxt_debug(task, "start error for released app"); 4336 4337 return; 4338 } 4339 4340 nxt_debug(task, "app '%V' %p start error", &app->name, app); 4341 4342 link = NULL; 4343 4344 nxt_thread_mutex_lock(&app->mutex); 4345 4346 nxt_assert(app->pending_processes != 0); 4347 4348 app->pending_processes--; 4349 4350 if (app->processes == 0 && !nxt_queue_is_empty(&app->ack_waiting_req)) { 4351 link = nxt_queue_first(&app->ack_waiting_req); 4352 4353 nxt_queue_remove(link); 4354 link->next = NULL; 4355 } 4356 4357 nxt_thread_mutex_unlock(&app->mutex); 4358 4359 while (link != NULL) { 4360 r = nxt_container_of(link, nxt_http_request_t, app_link); 4361 4362 nxt_event_engine_post(r->engine, &r->err_work); 4363 4364 link = NULL; 4365 4366 nxt_thread_mutex_lock(&app->mutex); 4367 4368 if (app->processes == 0 && app->pending_processes == 0 4369 && !nxt_queue_is_empty(&app->ack_waiting_req)) 4370 { 4371 link = nxt_queue_first(&app->ack_waiting_req); 4372 4373 nxt_queue_remove(link); 4374 link->next = NULL; 4375 } 4376 4377 nxt_thread_mutex_unlock(&app->mutex); 4378 } 4379} 4380 4381 4382 4383nxt_inline nxt_port_t * 4384nxt_router_app_get_port_for_quit(nxt_task_t *task, nxt_app_t *app) 4385{ 4386 nxt_port_t *port; 4387 4388 port = NULL; 4389 4390 nxt_thread_mutex_lock(&app->mutex); 4391 4392 nxt_queue_each(port, &app->ports, nxt_port_t, app_link) { 4393 4394 /* Caller is responsible to decrease port use count. */ 4395 nxt_queue_chk_remove(&port->app_link); 4396 4397 if (nxt_queue_chk_remove(&port->idle_link)) { 4398 app->idle_processes--; 4399 4400 nxt_debug(task, "app '%V' move port %PI:%d out of %s for quit", 4401 &app->name, port->pid, port->id, 4402 (port->idle_start ? "idle_ports" : "spare_ports")); 4403 } 4404 4405 nxt_port_hash_remove(&app->port_hash, port); 4406 app->port_hash_count--; 4407 4408 port->app = NULL; 4409 app->processes--; 4410 4411 break; 4412 4413 } nxt_queue_loop; 4414 4415 nxt_thread_mutex_unlock(&app->mutex); 4416 4417 return port; 4418} 4419 4420 4421static void 4422nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i) 4423{ 4424 int c; 4425 4426 c = nxt_atomic_fetch_add(&app->use_count, i); 4427 4428 if (i < 0 && c == -i) { 4429 4430 if (task->thread->engine != app->engine) { 4431 nxt_event_engine_post(app->engine, &app->joint->free_app_work); 4432 4433 } else { 4434 nxt_router_free_app(task, app->joint, NULL); 4435 } 4436 } 4437} 4438 4439 4440static void 4441nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app) 4442{ 4443 nxt_debug(task, "app '%V' %p unlink", &app->name, app); 4444 4445 nxt_queue_remove(&app->link); 4446 4447 nxt_router_app_use(task, app, -1); 4448} 4449 4450 4451static void 4452nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 4453 nxt_apr_action_t action) 4454{ 4455 int inc_use; 4456 uint32_t got_response, dec_requests; 4457 nxt_app_t *app; 4458 nxt_bool_t port_unchained, send_quit, adjust_idle_timer; 4459 nxt_port_t *main_app_port; 4460 4461 nxt_assert(port != NULL); 4462 nxt_assert(port->app != NULL); 4463 4464 app = port->app; 4465 4466 inc_use = 0; 4467 got_response = 0; 4468 dec_requests = 0; 4469 4470 switch (action) { 4471 case NXT_APR_NEW_PORT: 4472 break; 4473 case NXT_APR_REQUEST_FAILED: 4474 dec_requests = 1; 4475 inc_use = -1; 4476 break; 4477 case NXT_APR_GOT_RESPONSE: 4478 got_response = 1; 4479 inc_use = -1; 4480 break; 4481 case NXT_APR_UPGRADE: 4482 got_response = 1; 4483 break; 4484 case NXT_APR_CLOSE: 4485 inc_use = -1; 4486 break; 4487 } 4488 4489 nxt_debug(task, "app '%V' release port %PI:%d: %d %d", &app->name, 4490 port->pid, port->id, 4491 (int) inc_use, (int) got_response); 4492
| 4463 nxt_assert(app_joint != NULL); 4464 4465 app = app_joint->app; 4466 4467 nxt_router_app_joint_use(task, app_joint, -1); 4468 4469 if (nxt_slow_path(app == NULL)) { 4470 nxt_debug(task, "start error for released app"); 4471 4472 return; 4473 } 4474 4475 nxt_debug(task, "app '%V' %p start error", &app->name, app); 4476 4477 link = NULL; 4478 4479 nxt_thread_mutex_lock(&app->mutex); 4480 4481 nxt_assert(app->pending_processes != 0); 4482 4483 app->pending_processes--; 4484 4485 if (app->processes == 0 && !nxt_queue_is_empty(&app->ack_waiting_req)) { 4486 link = nxt_queue_first(&app->ack_waiting_req); 4487 4488 nxt_queue_remove(link); 4489 link->next = NULL; 4490 } 4491 4492 nxt_thread_mutex_unlock(&app->mutex); 4493 4494 while (link != NULL) { 4495 r = nxt_container_of(link, nxt_http_request_t, app_link); 4496 4497 nxt_event_engine_post(r->engine, &r->err_work); 4498 4499 link = NULL; 4500 4501 nxt_thread_mutex_lock(&app->mutex); 4502 4503 if (app->processes == 0 && app->pending_processes == 0 4504 && !nxt_queue_is_empty(&app->ack_waiting_req)) 4505 { 4506 link = nxt_queue_first(&app->ack_waiting_req); 4507 4508 nxt_queue_remove(link); 4509 link->next = NULL; 4510 } 4511 4512 nxt_thread_mutex_unlock(&app->mutex); 4513 } 4514} 4515 4516 4517 4518nxt_inline nxt_port_t * 4519nxt_router_app_get_port_for_quit(nxt_task_t *task, nxt_app_t *app) 4520{ 4521 nxt_port_t *port; 4522 4523 port = NULL; 4524 4525 nxt_thread_mutex_lock(&app->mutex); 4526 4527 nxt_queue_each(port, &app->ports, nxt_port_t, app_link) { 4528 4529 /* Caller is responsible to decrease port use count. */ 4530 nxt_queue_chk_remove(&port->app_link); 4531 4532 if (nxt_queue_chk_remove(&port->idle_link)) { 4533 app->idle_processes--; 4534 4535 nxt_debug(task, "app '%V' move port %PI:%d out of %s for quit", 4536 &app->name, port->pid, port->id, 4537 (port->idle_start ? "idle_ports" : "spare_ports")); 4538 } 4539 4540 nxt_port_hash_remove(&app->port_hash, port); 4541 app->port_hash_count--; 4542 4543 port->app = NULL; 4544 app->processes--; 4545 4546 break; 4547 4548 } nxt_queue_loop; 4549 4550 nxt_thread_mutex_unlock(&app->mutex); 4551 4552 return port; 4553} 4554 4555 4556static void 4557nxt_router_app_use(nxt_task_t *task, nxt_app_t *app, int i) 4558{ 4559 int c; 4560 4561 c = nxt_atomic_fetch_add(&app->use_count, i); 4562 4563 if (i < 0 && c == -i) { 4564 4565 if (task->thread->engine != app->engine) { 4566 nxt_event_engine_post(app->engine, &app->joint->free_app_work); 4567 4568 } else { 4569 nxt_router_free_app(task, app->joint, NULL); 4570 } 4571 } 4572} 4573 4574 4575static void 4576nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app) 4577{ 4578 nxt_debug(task, "app '%V' %p unlink", &app->name, app); 4579 4580 nxt_queue_remove(&app->link); 4581 4582 nxt_router_app_use(task, app, -1); 4583} 4584 4585 4586static void 4587nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port, 4588 nxt_apr_action_t action) 4589{ 4590 int inc_use; 4591 uint32_t got_response, dec_requests; 4592 nxt_app_t *app; 4593 nxt_bool_t port_unchained, send_quit, adjust_idle_timer; 4594 nxt_port_t *main_app_port; 4595 4596 nxt_assert(port != NULL); 4597 nxt_assert(port->app != NULL); 4598 4599 app = port->app; 4600 4601 inc_use = 0; 4602 got_response = 0; 4603 dec_requests = 0; 4604 4605 switch (action) { 4606 case NXT_APR_NEW_PORT: 4607 break; 4608 case NXT_APR_REQUEST_FAILED: 4609 dec_requests = 1; 4610 inc_use = -1; 4611 break; 4612 case NXT_APR_GOT_RESPONSE: 4613 got_response = 1; 4614 inc_use = -1; 4615 break; 4616 case NXT_APR_UPGRADE: 4617 got_response = 1; 4618 break; 4619 case NXT_APR_CLOSE: 4620 inc_use = -1; 4621 break; 4622 } 4623 4624 nxt_debug(task, "app '%V' release port %PI:%d: %d %d", &app->name, 4625 port->pid, port->id, 4626 (int) inc_use, (int) got_response); 4627
|
4493 if (port == app->shared_port) {
| 4628 if (port->id == NXT_SHARED_PORT_ID) {
|
4494 nxt_thread_mutex_lock(&app->mutex); 4495 4496 app->active_requests -= got_response + dec_requests; 4497 4498 nxt_thread_mutex_unlock(&app->mutex); 4499 4500 goto adjust_use; 4501 } 4502 4503 main_app_port = port->main_app_port; 4504 4505 nxt_thread_mutex_lock(&app->mutex); 4506 4507 main_app_port->app_responses += got_response; 4508 main_app_port->active_requests -= got_response + dec_requests; 4509 app->active_requests -= got_response + dec_requests; 4510 4511 if (main_app_port->pair[1] != -1 4512 && (app->max_requests == 0 4513 || main_app_port->app_responses < app->max_requests)) 4514 { 4515 if (main_app_port->app_link.next == NULL) { 4516 nxt_queue_insert_tail(&app->ports, &main_app_port->app_link); 4517 4518 nxt_port_inc_use(main_app_port); 4519 } 4520 } 4521 4522 send_quit = (app->max_requests > 0 4523 && main_app_port->app_responses >= app->max_requests); 4524 4525 if (send_quit) { 4526 port_unchained = nxt_queue_chk_remove(&main_app_port->app_link); 4527 4528 nxt_port_hash_remove(&app->port_hash, main_app_port); 4529 app->port_hash_count--; 4530 4531 main_app_port->app = NULL; 4532 app->processes--; 4533 4534 } else { 4535 port_unchained = 0; 4536 } 4537 4538 adjust_idle_timer = 0; 4539 4540 if (main_app_port->pair[1] != -1 && !send_quit 4541 && main_app_port->active_requests == 0 4542 && main_app_port->active_websockets == 0 4543 && main_app_port->idle_link.next == NULL) 4544 { 4545 if (app->idle_processes == app->spare_processes 4546 && app->adjust_idle_work.data == NULL) 4547 { 4548 adjust_idle_timer = 1; 4549 app->adjust_idle_work.data = app; 4550 app->adjust_idle_work.next = NULL; 4551 } 4552 4553 if (app->idle_processes < app->spare_processes) { 4554 nxt_queue_insert_tail(&app->spare_ports, &main_app_port->idle_link); 4555 4556 nxt_debug(task, "app '%V' move port %PI:%d to spare_ports", 4557 &app->name, main_app_port->pid, main_app_port->id); 4558 } else { 4559 nxt_queue_insert_tail(&app->idle_ports, &main_app_port->idle_link); 4560 4561 main_app_port->idle_start = task->thread->engine->timers.now; 4562 4563 nxt_debug(task, "app '%V' move port %PI:%d to idle_ports", 4564 &app->name, main_app_port->pid, main_app_port->id); 4565 } 4566 4567 app->idle_processes++; 4568 } 4569 4570 nxt_thread_mutex_unlock(&app->mutex); 4571 4572 if (adjust_idle_timer) { 4573 nxt_router_app_use(task, app, 1); 4574 nxt_event_engine_post(app->engine, &app->adjust_idle_work); 4575 } 4576 4577 /* ? */ 4578 if (main_app_port->pair[1] == -1) { 4579 nxt_debug(task, "app '%V' %p port %p already closed (pid %PI dead?)", 4580 &app->name, app, main_app_port, main_app_port->pid); 4581 4582 goto adjust_use; 4583 } 4584 4585 if (send_quit) { 4586 nxt_debug(task, "app '%V' %p send QUIT to port", &app->name, app); 4587 4588 nxt_port_socket_write(task, main_app_port, NXT_PORT_MSG_QUIT, -1, 0, 0, 4589 NULL); 4590 4591 if (port_unchained) { 4592 nxt_port_use(task, main_app_port, -1); 4593 } 4594 4595 goto adjust_use; 4596 } 4597 4598 nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", 4599 &app->name, app); 4600 4601adjust_use: 4602 4603 nxt_port_use(task, port, inc_use); 4604} 4605 4606 4607void 4608nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port) 4609{ 4610 nxt_app_t *app; 4611 nxt_bool_t unchain, start_process; 4612 nxt_port_t *idle_port; 4613 nxt_queue_link_t *idle_lnk; 4614 4615 app = port->app; 4616 4617 nxt_assert(app != NULL); 4618 4619 nxt_thread_mutex_lock(&app->mutex); 4620 4621 nxt_port_hash_remove(&app->port_hash, port); 4622 app->port_hash_count--; 4623 4624 if (port->id != 0) { 4625 nxt_thread_mutex_unlock(&app->mutex); 4626 4627 nxt_debug(task, "app '%V' port (%PI, %d) closed", &app->name, 4628 port->pid, port->id); 4629 4630 return; 4631 } 4632 4633 unchain = nxt_queue_chk_remove(&port->app_link); 4634 4635 if (nxt_queue_chk_remove(&port->idle_link)) { 4636 app->idle_processes--; 4637 4638 nxt_debug(task, "app '%V' move port %PI:%d out of %s before close", 4639 &app->name, port->pid, port->id, 4640 (port->idle_start ? "idle_ports" : "spare_ports")); 4641 4642 if (port->idle_start == 0 4643 && app->idle_processes >= app->spare_processes) 4644 { 4645 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4646 4647 idle_lnk = nxt_queue_last(&app->idle_ports); 4648 idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); 4649 nxt_queue_remove(idle_lnk); 4650 4651 nxt_queue_insert_tail(&app->spare_ports, idle_lnk); 4652 4653 idle_port->idle_start = 0; 4654 4655 nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " 4656 "to spare_ports", 4657 &app->name, idle_port->pid, idle_port->id); 4658 } 4659 } 4660 4661 app->processes--; 4662 4663 start_process = !task->thread->engine->shutdown 4664 && nxt_router_app_can_start(app) 4665 && nxt_router_app_need_start(app); 4666 4667 if (start_process) { 4668 app->pending_processes++; 4669 } 4670 4671 nxt_thread_mutex_unlock(&app->mutex); 4672 4673 nxt_debug(task, "app '%V' pid %PI closed", &app->name, port->pid); 4674 4675 if (unchain) { 4676 nxt_port_use(task, port, -1); 4677 } 4678 4679 if (start_process) { 4680 nxt_router_start_app_process(task, app); 4681 } 4682} 4683 4684 4685static void 4686nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data) 4687{ 4688 nxt_app_t *app; 4689 nxt_bool_t queued; 4690 nxt_port_t *port; 4691 nxt_msec_t timeout, threshold; 4692 nxt_queue_link_t *lnk; 4693 nxt_event_engine_t *engine; 4694 4695 app = obj; 4696 queued = (data == app); 4697 4698 nxt_debug(task, "nxt_router_adjust_idle_timer: app \"%V\", queued %b", 4699 &app->name, queued); 4700 4701 engine = task->thread->engine; 4702 4703 nxt_assert(app->engine == engine); 4704 4705 threshold = engine->timers.now + app->joint->idle_timer.bias; 4706 timeout = 0; 4707 4708 nxt_thread_mutex_lock(&app->mutex); 4709 4710 if (queued) { 4711 app->adjust_idle_work.data = NULL; 4712 } 4713 4714 nxt_debug(task, "app '%V' idle_processes %d, spare_processes %d", 4715 &app->name, 4716 (int) app->idle_processes, (int) app->spare_processes); 4717 4718 while (app->idle_processes > app->spare_processes) { 4719 4720 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4721 4722 lnk = nxt_queue_first(&app->idle_ports); 4723 port = nxt_queue_link_data(lnk, nxt_port_t, idle_link); 4724 4725 timeout = port->idle_start + app->idle_timeout; 4726 4727 nxt_debug(task, "app '%V' pid %PI, start %M, timeout %M, threshold %M", 4728 &app->name, port->pid, 4729 port->idle_start, timeout, threshold); 4730 4731 if (timeout > threshold) { 4732 break; 4733 } 4734 4735 nxt_queue_remove(lnk); 4736 lnk->next = NULL; 4737 4738 nxt_debug(task, "app '%V' move port %PI:%d out of idle_ports (timeout)", 4739 &app->name, port->pid, port->id); 4740 4741 nxt_queue_chk_remove(&port->app_link); 4742 4743 nxt_port_hash_remove(&app->port_hash, port); 4744 app->port_hash_count--; 4745 4746 app->idle_processes--; 4747 app->processes--; 4748 port->app = NULL; 4749 4750 nxt_thread_mutex_unlock(&app->mutex); 4751 4752 nxt_debug(task, "app '%V' send QUIT to idle port %PI", 4753 &app->name, port->pid); 4754 4755 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4756 4757 nxt_port_use(task, port, -1); 4758 4759 nxt_thread_mutex_lock(&app->mutex); 4760 } 4761 4762 nxt_thread_mutex_unlock(&app->mutex); 4763 4764 if (timeout > threshold) { 4765 nxt_timer_add(engine, &app->joint->idle_timer, timeout - threshold); 4766 4767 } else { 4768 nxt_timer_disable(engine, &app->joint->idle_timer); 4769 } 4770 4771 if (queued) { 4772 nxt_router_app_use(task, app, -1); 4773 } 4774} 4775 4776 4777static void 4778nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, void *data) 4779{ 4780 nxt_timer_t *timer; 4781 nxt_app_joint_t *app_joint; 4782 4783 timer = obj; 4784 app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); 4785 4786 if (nxt_fast_path(app_joint->app != NULL)) { 4787 nxt_router_adjust_idle_timer(task, app_joint->app, NULL); 4788 } 4789} 4790 4791 4792static void 4793nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, void *data) 4794{ 4795 nxt_timer_t *timer; 4796 nxt_app_joint_t *app_joint; 4797 4798 timer = obj; 4799 app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); 4800 4801 nxt_router_app_joint_use(task, app_joint, -1); 4802} 4803 4804 4805static void 4806nxt_router_free_app(nxt_task_t *task, void *obj, void *data) 4807{ 4808 nxt_app_t *app; 4809 nxt_port_t *port; 4810 nxt_app_joint_t *app_joint; 4811 4812 app_joint = obj; 4813 app = app_joint->app; 4814 4815 for ( ;; ) { 4816 port = nxt_router_app_get_port_for_quit(task, app); 4817 if (port == NULL) { 4818 break; 4819 } 4820 4821 nxt_debug(task, "send QUIT to app '%V' pid %PI", &app->name, port->pid); 4822 4823 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4824 4825 nxt_port_use(task, port, -1); 4826 } 4827 4828 nxt_thread_mutex_lock(&app->mutex); 4829 4830 for ( ;; ) { 4831 port = nxt_port_hash_retrieve(&app->port_hash); 4832 if (port == NULL) { 4833 break; 4834 } 4835 4836 app->port_hash_count--; 4837 4838 port->app = NULL; 4839 4840 nxt_port_close(task, port); 4841 4842 nxt_port_use(task, port, -1); 4843 } 4844 4845 nxt_thread_mutex_unlock(&app->mutex); 4846 4847 nxt_assert(app->processes == 0); 4848 nxt_assert(app->active_requests == 0); 4849 nxt_assert(app->port_hash_count == 0); 4850 nxt_assert(app->idle_processes == 0); 4851 nxt_assert(nxt_queue_is_empty(&app->ports)); 4852 nxt_assert(nxt_queue_is_empty(&app->spare_ports)); 4853 nxt_assert(nxt_queue_is_empty(&app->idle_ports)); 4854 4855 nxt_port_mmaps_destroy(&app->outgoing, 1); 4856 4857 nxt_thread_mutex_destroy(&app->outgoing.mutex); 4858 4859 if (app->shared_port != NULL) { 4860 app->shared_port->app = NULL; 4861 nxt_port_close(task, app->shared_port); 4862 nxt_port_use(task, app->shared_port, -1);
| 4629 nxt_thread_mutex_lock(&app->mutex); 4630 4631 app->active_requests -= got_response + dec_requests; 4632 4633 nxt_thread_mutex_unlock(&app->mutex); 4634 4635 goto adjust_use; 4636 } 4637 4638 main_app_port = port->main_app_port; 4639 4640 nxt_thread_mutex_lock(&app->mutex); 4641 4642 main_app_port->app_responses += got_response; 4643 main_app_port->active_requests -= got_response + dec_requests; 4644 app->active_requests -= got_response + dec_requests; 4645 4646 if (main_app_port->pair[1] != -1 4647 && (app->max_requests == 0 4648 || main_app_port->app_responses < app->max_requests)) 4649 { 4650 if (main_app_port->app_link.next == NULL) { 4651 nxt_queue_insert_tail(&app->ports, &main_app_port->app_link); 4652 4653 nxt_port_inc_use(main_app_port); 4654 } 4655 } 4656 4657 send_quit = (app->max_requests > 0 4658 && main_app_port->app_responses >= app->max_requests); 4659 4660 if (send_quit) { 4661 port_unchained = nxt_queue_chk_remove(&main_app_port->app_link); 4662 4663 nxt_port_hash_remove(&app->port_hash, main_app_port); 4664 app->port_hash_count--; 4665 4666 main_app_port->app = NULL; 4667 app->processes--; 4668 4669 } else { 4670 port_unchained = 0; 4671 } 4672 4673 adjust_idle_timer = 0; 4674 4675 if (main_app_port->pair[1] != -1 && !send_quit 4676 && main_app_port->active_requests == 0 4677 && main_app_port->active_websockets == 0 4678 && main_app_port->idle_link.next == NULL) 4679 { 4680 if (app->idle_processes == app->spare_processes 4681 && app->adjust_idle_work.data == NULL) 4682 { 4683 adjust_idle_timer = 1; 4684 app->adjust_idle_work.data = app; 4685 app->adjust_idle_work.next = NULL; 4686 } 4687 4688 if (app->idle_processes < app->spare_processes) { 4689 nxt_queue_insert_tail(&app->spare_ports, &main_app_port->idle_link); 4690 4691 nxt_debug(task, "app '%V' move port %PI:%d to spare_ports", 4692 &app->name, main_app_port->pid, main_app_port->id); 4693 } else { 4694 nxt_queue_insert_tail(&app->idle_ports, &main_app_port->idle_link); 4695 4696 main_app_port->idle_start = task->thread->engine->timers.now; 4697 4698 nxt_debug(task, "app '%V' move port %PI:%d to idle_ports", 4699 &app->name, main_app_port->pid, main_app_port->id); 4700 } 4701 4702 app->idle_processes++; 4703 } 4704 4705 nxt_thread_mutex_unlock(&app->mutex); 4706 4707 if (adjust_idle_timer) { 4708 nxt_router_app_use(task, app, 1); 4709 nxt_event_engine_post(app->engine, &app->adjust_idle_work); 4710 } 4711 4712 /* ? */ 4713 if (main_app_port->pair[1] == -1) { 4714 nxt_debug(task, "app '%V' %p port %p already closed (pid %PI dead?)", 4715 &app->name, app, main_app_port, main_app_port->pid); 4716 4717 goto adjust_use; 4718 } 4719 4720 if (send_quit) { 4721 nxt_debug(task, "app '%V' %p send QUIT to port", &app->name, app); 4722 4723 nxt_port_socket_write(task, main_app_port, NXT_PORT_MSG_QUIT, -1, 0, 0, 4724 NULL); 4725 4726 if (port_unchained) { 4727 nxt_port_use(task, main_app_port, -1); 4728 } 4729 4730 goto adjust_use; 4731 } 4732 4733 nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", 4734 &app->name, app); 4735 4736adjust_use: 4737 4738 nxt_port_use(task, port, inc_use); 4739} 4740 4741 4742void 4743nxt_router_app_port_close(nxt_task_t *task, nxt_port_t *port) 4744{ 4745 nxt_app_t *app; 4746 nxt_bool_t unchain, start_process; 4747 nxt_port_t *idle_port; 4748 nxt_queue_link_t *idle_lnk; 4749 4750 app = port->app; 4751 4752 nxt_assert(app != NULL); 4753 4754 nxt_thread_mutex_lock(&app->mutex); 4755 4756 nxt_port_hash_remove(&app->port_hash, port); 4757 app->port_hash_count--; 4758 4759 if (port->id != 0) { 4760 nxt_thread_mutex_unlock(&app->mutex); 4761 4762 nxt_debug(task, "app '%V' port (%PI, %d) closed", &app->name, 4763 port->pid, port->id); 4764 4765 return; 4766 } 4767 4768 unchain = nxt_queue_chk_remove(&port->app_link); 4769 4770 if (nxt_queue_chk_remove(&port->idle_link)) { 4771 app->idle_processes--; 4772 4773 nxt_debug(task, "app '%V' move port %PI:%d out of %s before close", 4774 &app->name, port->pid, port->id, 4775 (port->idle_start ? "idle_ports" : "spare_ports")); 4776 4777 if (port->idle_start == 0 4778 && app->idle_processes >= app->spare_processes) 4779 { 4780 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4781 4782 idle_lnk = nxt_queue_last(&app->idle_ports); 4783 idle_port = nxt_queue_link_data(idle_lnk, nxt_port_t, idle_link); 4784 nxt_queue_remove(idle_lnk); 4785 4786 nxt_queue_insert_tail(&app->spare_ports, idle_lnk); 4787 4788 idle_port->idle_start = 0; 4789 4790 nxt_debug(task, "app '%V' move port %PI:%d from idle_ports " 4791 "to spare_ports", 4792 &app->name, idle_port->pid, idle_port->id); 4793 } 4794 } 4795 4796 app->processes--; 4797 4798 start_process = !task->thread->engine->shutdown 4799 && nxt_router_app_can_start(app) 4800 && nxt_router_app_need_start(app); 4801 4802 if (start_process) { 4803 app->pending_processes++; 4804 } 4805 4806 nxt_thread_mutex_unlock(&app->mutex); 4807 4808 nxt_debug(task, "app '%V' pid %PI closed", &app->name, port->pid); 4809 4810 if (unchain) { 4811 nxt_port_use(task, port, -1); 4812 } 4813 4814 if (start_process) { 4815 nxt_router_start_app_process(task, app); 4816 } 4817} 4818 4819 4820static void 4821nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data) 4822{ 4823 nxt_app_t *app; 4824 nxt_bool_t queued; 4825 nxt_port_t *port; 4826 nxt_msec_t timeout, threshold; 4827 nxt_queue_link_t *lnk; 4828 nxt_event_engine_t *engine; 4829 4830 app = obj; 4831 queued = (data == app); 4832 4833 nxt_debug(task, "nxt_router_adjust_idle_timer: app \"%V\", queued %b", 4834 &app->name, queued); 4835 4836 engine = task->thread->engine; 4837 4838 nxt_assert(app->engine == engine); 4839 4840 threshold = engine->timers.now + app->joint->idle_timer.bias; 4841 timeout = 0; 4842 4843 nxt_thread_mutex_lock(&app->mutex); 4844 4845 if (queued) { 4846 app->adjust_idle_work.data = NULL; 4847 } 4848 4849 nxt_debug(task, "app '%V' idle_processes %d, spare_processes %d", 4850 &app->name, 4851 (int) app->idle_processes, (int) app->spare_processes); 4852 4853 while (app->idle_processes > app->spare_processes) { 4854 4855 nxt_assert(!nxt_queue_is_empty(&app->idle_ports)); 4856 4857 lnk = nxt_queue_first(&app->idle_ports); 4858 port = nxt_queue_link_data(lnk, nxt_port_t, idle_link); 4859 4860 timeout = port->idle_start + app->idle_timeout; 4861 4862 nxt_debug(task, "app '%V' pid %PI, start %M, timeout %M, threshold %M", 4863 &app->name, port->pid, 4864 port->idle_start, timeout, threshold); 4865 4866 if (timeout > threshold) { 4867 break; 4868 } 4869 4870 nxt_queue_remove(lnk); 4871 lnk->next = NULL; 4872 4873 nxt_debug(task, "app '%V' move port %PI:%d out of idle_ports (timeout)", 4874 &app->name, port->pid, port->id); 4875 4876 nxt_queue_chk_remove(&port->app_link); 4877 4878 nxt_port_hash_remove(&app->port_hash, port); 4879 app->port_hash_count--; 4880 4881 app->idle_processes--; 4882 app->processes--; 4883 port->app = NULL; 4884 4885 nxt_thread_mutex_unlock(&app->mutex); 4886 4887 nxt_debug(task, "app '%V' send QUIT to idle port %PI", 4888 &app->name, port->pid); 4889 4890 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4891 4892 nxt_port_use(task, port, -1); 4893 4894 nxt_thread_mutex_lock(&app->mutex); 4895 } 4896 4897 nxt_thread_mutex_unlock(&app->mutex); 4898 4899 if (timeout > threshold) { 4900 nxt_timer_add(engine, &app->joint->idle_timer, timeout - threshold); 4901 4902 } else { 4903 nxt_timer_disable(engine, &app->joint->idle_timer); 4904 } 4905 4906 if (queued) { 4907 nxt_router_app_use(task, app, -1); 4908 } 4909} 4910 4911 4912static void 4913nxt_router_app_idle_timeout(nxt_task_t *task, void *obj, void *data) 4914{ 4915 nxt_timer_t *timer; 4916 nxt_app_joint_t *app_joint; 4917 4918 timer = obj; 4919 app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); 4920 4921 if (nxt_fast_path(app_joint->app != NULL)) { 4922 nxt_router_adjust_idle_timer(task, app_joint->app, NULL); 4923 } 4924} 4925 4926 4927static void 4928nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj, void *data) 4929{ 4930 nxt_timer_t *timer; 4931 nxt_app_joint_t *app_joint; 4932 4933 timer = obj; 4934 app_joint = nxt_container_of(timer, nxt_app_joint_t, idle_timer); 4935 4936 nxt_router_app_joint_use(task, app_joint, -1); 4937} 4938 4939 4940static void 4941nxt_router_free_app(nxt_task_t *task, void *obj, void *data) 4942{ 4943 nxt_app_t *app; 4944 nxt_port_t *port; 4945 nxt_app_joint_t *app_joint; 4946 4947 app_joint = obj; 4948 app = app_joint->app; 4949 4950 for ( ;; ) { 4951 port = nxt_router_app_get_port_for_quit(task, app); 4952 if (port == NULL) { 4953 break; 4954 } 4955 4956 nxt_debug(task, "send QUIT to app '%V' pid %PI", &app->name, port->pid); 4957 4958 nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 4959 4960 nxt_port_use(task, port, -1); 4961 } 4962 4963 nxt_thread_mutex_lock(&app->mutex); 4964 4965 for ( ;; ) { 4966 port = nxt_port_hash_retrieve(&app->port_hash); 4967 if (port == NULL) { 4968 break; 4969 } 4970 4971 app->port_hash_count--; 4972 4973 port->app = NULL; 4974 4975 nxt_port_close(task, port); 4976 4977 nxt_port_use(task, port, -1); 4978 } 4979 4980 nxt_thread_mutex_unlock(&app->mutex); 4981 4982 nxt_assert(app->processes == 0); 4983 nxt_assert(app->active_requests == 0); 4984 nxt_assert(app->port_hash_count == 0); 4985 nxt_assert(app->idle_processes == 0); 4986 nxt_assert(nxt_queue_is_empty(&app->ports)); 4987 nxt_assert(nxt_queue_is_empty(&app->spare_ports)); 4988 nxt_assert(nxt_queue_is_empty(&app->idle_ports)); 4989 4990 nxt_port_mmaps_destroy(&app->outgoing, 1); 4991 4992 nxt_thread_mutex_destroy(&app->outgoing.mutex); 4993 4994 if (app->shared_port != NULL) { 4995 app->shared_port->app = NULL; 4996 nxt_port_close(task, app->shared_port); 4997 nxt_port_use(task, app->shared_port, -1);
|
| 4998 4999 app->shared_port = NULL;
|
4863 } 4864 4865 nxt_thread_mutex_destroy(&app->mutex); 4866 nxt_mp_destroy(app->mem_pool); 4867 4868 app_joint->app = NULL; 4869 4870 if (nxt_timer_delete(task->thread->engine, &app_joint->idle_timer)) { 4871 app_joint->idle_timer.handler = nxt_router_app_joint_release_handler; 4872 nxt_timer_add(task->thread->engine, &app_joint->idle_timer, 0); 4873 4874 } else { 4875 nxt_router_app_joint_use(task, app_joint, -1); 4876 } 4877} 4878 4879 4880static void 4881nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 4882 nxt_request_rpc_data_t *req_rpc_data) 4883{ 4884 nxt_bool_t start_process; 4885 nxt_port_t *port; 4886 nxt_http_request_t *r; 4887 4888 start_process = 0; 4889 4890 nxt_thread_mutex_lock(&app->mutex); 4891 4892 port = app->shared_port; 4893 nxt_port_inc_use(port); 4894 4895 app->active_requests++; 4896 4897 if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { 4898 app->pending_processes++; 4899 start_process = 1; 4900 } 4901 4902 r = req_rpc_data->request; 4903 4904 /* 4905 * Put request into application-wide list to be able to cancel request 4906 * if something goes wrong with application processes. 4907 */ 4908 nxt_queue_insert_tail(&app->ack_waiting_req, &r->app_link); 4909 4910 nxt_thread_mutex_unlock(&app->mutex); 4911 4912 /* 4913 * Retain request memory pool while request is linked in ack_waiting_req 4914 * to guarantee request structure memory is accessble. 4915 */ 4916 nxt_mp_retain(r->mem_pool); 4917 4918 req_rpc_data->app_port = port; 4919 req_rpc_data->apr_action = NXT_APR_REQUEST_FAILED; 4920 4921 if (start_process) { 4922 nxt_router_start_app_process(task, app); 4923 } 4924} 4925 4926 4927void 4928nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r, 4929 nxt_http_action_t *action) 4930{ 4931 nxt_event_engine_t *engine; 4932 nxt_http_app_conf_t *conf; 4933 nxt_request_rpc_data_t *req_rpc_data; 4934 4935 conf = action->u.conf; 4936 engine = task->thread->engine; 4937 4938 r->app_target = conf->target; 4939 4940 req_rpc_data = nxt_port_rpc_register_handler_ex(task, engine->port, 4941 nxt_router_response_ready_handler, 4942 nxt_router_response_error_handler, 4943 sizeof(nxt_request_rpc_data_t)); 4944 if (nxt_slow_path(req_rpc_data == NULL)) { 4945 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 4946 return; 4947 } 4948 4949 /* 4950 * At this point we have request req_rpc_data allocated and registered 4951 * in port handlers. Need to fixup request memory pool. Counterpart 4952 * release will be called via following call chain: 4953 * nxt_request_rpc_data_unlink() -> 4954 * nxt_router_http_request_release_post() -> 4955 * nxt_router_http_request_release() 4956 */ 4957 nxt_mp_retain(r->mem_pool); 4958 4959 r->timer.task = &engine->task; 4960 r->timer.work_queue = &engine->fast_work_queue; 4961 r->timer.log = engine->task.log; 4962 r->timer.bias = NXT_TIMER_DEFAULT_BIAS; 4963 4964 r->engine = engine; 4965 r->err_work.handler = nxt_router_http_request_error; 4966 r->err_work.task = task; 4967 r->err_work.obj = r; 4968 4969 req_rpc_data->stream = nxt_port_rpc_ex_stream(req_rpc_data); 4970 req_rpc_data->app = conf->app; 4971 req_rpc_data->msg_info.body_fd = -1; 4972 req_rpc_data->rpc_cancel = 1; 4973 4974 nxt_router_app_use(task, conf->app, 1); 4975 4976 req_rpc_data->request = r; 4977 r->req_rpc_data = req_rpc_data; 4978 4979 if (r->last != NULL) { 4980 r->last->completion_handler = nxt_router_http_request_done; 4981 } 4982 4983 nxt_router_app_port_get(task, conf->app, req_rpc_data); 4984 nxt_router_app_prepare_request(task, req_rpc_data); 4985} 4986 4987 4988static void 4989nxt_router_http_request_error(nxt_task_t *task, void *obj, void *data) 4990{ 4991 nxt_http_request_t *r; 4992 4993 r = obj; 4994 4995 nxt_debug(task, "router http request error (rpc_data %p)", r->req_rpc_data); 4996 4997 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 4998 4999 if (r->req_rpc_data != NULL) { 5000 nxt_request_rpc_data_unlink(task, r->req_rpc_data); 5001 } 5002 5003 nxt_mp_release(r->mem_pool); 5004} 5005 5006 5007static void 5008nxt_router_http_request_done(nxt_task_t *task, void *obj, void *data) 5009{ 5010 nxt_http_request_t *r; 5011 5012 r = data; 5013 5014 nxt_debug(task, "router http request done (rpc_data %p)", r->req_rpc_data); 5015 5016 if (r->req_rpc_data != NULL) { 5017 nxt_request_rpc_data_unlink(task, r->req_rpc_data); 5018 } 5019 5020 nxt_http_request_close_handler(task, r, r->proto.any); 5021} 5022 5023 5024static void 5025nxt_router_dummy_buf_completion(nxt_task_t *task, void *obj, void *data) 5026{ 5027} 5028 5029 5030static void 5031nxt_router_app_prepare_request(nxt_task_t *task, 5032 nxt_request_rpc_data_t *req_rpc_data) 5033{ 5034 nxt_app_t *app; 5035 nxt_buf_t *buf, *body; 5036 nxt_int_t res; 5037 nxt_port_t *port, *reply_port; 5038 5039 int notify; 5040 struct { 5041 nxt_port_msg_t pm; 5042 nxt_port_mmap_msg_t mm; 5043 } msg; 5044 5045 5046 app = req_rpc_data->app; 5047 5048 nxt_assert(app != NULL); 5049 5050 port = req_rpc_data->app_port; 5051 5052 nxt_assert(port != NULL); 5053 nxt_assert(port->queue != NULL); 5054 5055 reply_port = task->thread->engine->port; 5056 5057 buf = nxt_router_prepare_msg(task, req_rpc_data->request, app, 5058 nxt_app_msg_prefix[app->type]); 5059 if (nxt_slow_path(buf == NULL)) { 5060 nxt_alert(task, "stream #%uD, app '%V': failed to prepare app message", 5061 req_rpc_data->stream, &app->name); 5062 5063 nxt_http_request_error(task, req_rpc_data->request, 5064 NXT_HTTP_INTERNAL_SERVER_ERROR); 5065 5066 return; 5067 } 5068 5069 nxt_debug(task, "about to send %O bytes buffer to app process port %d", 5070 nxt_buf_used_size(buf), 5071 port->socket.fd); 5072 5073 req_rpc_data->msg_info.buf = buf; 5074 5075 body = req_rpc_data->request->body; 5076 5077 if (body != NULL && nxt_buf_is_file(body)) { 5078 req_rpc_data->msg_info.body_fd = body->file->fd; 5079 5080 body->file->fd = -1; 5081 5082 } else { 5083 req_rpc_data->msg_info.body_fd = -1; 5084 } 5085 5086 msg.pm.stream = req_rpc_data->stream; 5087 msg.pm.pid = reply_port->pid; 5088 msg.pm.reply_port = reply_port->id; 5089 msg.pm.type = NXT_PORT_MSG_REQ_HEADERS; 5090 msg.pm.last = 0; 5091 msg.pm.mmap = 1; 5092 msg.pm.nf = 0; 5093 msg.pm.mf = 0; 5094 msg.pm.tracking = 0; 5095 5096 nxt_port_mmap_handler_t *mmap_handler = buf->parent; 5097 nxt_port_mmap_header_t *hdr = mmap_handler->hdr; 5098 5099 msg.mm.mmap_id = hdr->id; 5100 msg.mm.chunk_id = nxt_port_mmap_chunk_id(hdr, buf->mem.pos); 5101 msg.mm.size = nxt_buf_used_size(buf); 5102 5103 res = nxt_app_queue_send(port->queue, &msg, sizeof(msg), 5104 req_rpc_data->stream, ¬ify, 5105 &req_rpc_data->msg_info.tracking_cookie); 5106 if (nxt_fast_path(res == NXT_OK)) { 5107 if (notify != 0) { 5108 (void) nxt_port_socket_write(task, port, 5109 NXT_PORT_MSG_READ_QUEUE, 5110 -1, req_rpc_data->stream, 5111 reply_port->id, NULL); 5112 5113 } else { 5114 nxt_debug(task, "queue is not empty"); 5115 } 5116 5117 buf->is_port_mmap_sent = 1; 5118 buf->mem.pos = buf->mem.free; 5119 5120 } else { 5121 nxt_alert(task, "stream #%uD, app '%V': failed to send app message", 5122 req_rpc_data->stream, &app->name); 5123 5124 nxt_http_request_error(task, req_rpc_data->request, 5125 NXT_HTTP_INTERNAL_SERVER_ERROR); 5126 } 5127} 5128 5129 5130struct nxt_fields_iter_s { 5131 nxt_list_part_t *part; 5132 nxt_http_field_t *field; 5133}; 5134 5135typedef struct nxt_fields_iter_s nxt_fields_iter_t; 5136 5137 5138static nxt_http_field_t * 5139nxt_fields_part_first(nxt_list_part_t *part, nxt_fields_iter_t *i) 5140{ 5141 if (part == NULL) { 5142 return NULL; 5143 } 5144 5145 while (part->nelts == 0) { 5146 part = part->next; 5147 if (part == NULL) { 5148 return NULL; 5149 } 5150 } 5151 5152 i->part = part; 5153 i->field = nxt_list_data(i->part); 5154 5155 return i->field; 5156} 5157 5158 5159static nxt_http_field_t * 5160nxt_fields_first(nxt_list_t *fields, nxt_fields_iter_t *i) 5161{ 5162 return nxt_fields_part_first(nxt_list_part(fields), i); 5163} 5164 5165 5166static nxt_http_field_t * 5167nxt_fields_next(nxt_fields_iter_t *i) 5168{ 5169 nxt_http_field_t *end = nxt_list_data(i->part); 5170 5171 end += i->part->nelts; 5172 i->field++; 5173 5174 if (i->field < end) { 5175 return i->field; 5176 } 5177 5178 return nxt_fields_part_first(i->part->next, i); 5179} 5180 5181 5182static nxt_buf_t * 5183nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, 5184 nxt_app_t *app, const nxt_str_t *prefix) 5185{ 5186 void *target_pos, *query_pos; 5187 u_char *pos, *end, *p, c; 5188 size_t fields_count, req_size, size, free_size; 5189 size_t copy_size; 5190 nxt_off_t content_length; 5191 nxt_buf_t *b, *buf, *out, **tail; 5192 nxt_http_field_t *field, *dup; 5193 nxt_unit_field_t *dst_field; 5194 nxt_fields_iter_t iter, dup_iter; 5195 nxt_unit_request_t *req; 5196 5197 req_size = sizeof(nxt_unit_request_t) 5198 + r->method->length + 1 5199 + r->version.length + 1 5200 + r->remote->length + 1 5201 + r->local->length + 1 5202 + r->server_name.length + 1 5203 + r->target.length + 1 5204 + (r->path->start != r->target.start ? r->path->length + 1 : 0); 5205 5206 content_length = r->content_length_n < 0 ? 0 : r->content_length_n; 5207 fields_count = 0; 5208 5209 nxt_list_each(field, r->fields) { 5210 fields_count++; 5211 5212 req_size += field->name_length + prefix->length + 1 5213 + field->value_length + 1; 5214 } nxt_list_loop; 5215 5216 req_size += fields_count * sizeof(nxt_unit_field_t); 5217 5218 if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) { 5219 nxt_alert(task, "headers to big to fit in shared memory (%d)", 5220 (int) req_size); 5221 5222 return NULL; 5223 } 5224 5225 out = nxt_port_mmap_get_buf(task, &app->outgoing, 5226 nxt_min(req_size + content_length, PORT_MMAP_DATA_SIZE)); 5227 if (nxt_slow_path(out == NULL)) { 5228 return NULL; 5229 } 5230 5231 req = (nxt_unit_request_t *) out->mem.free; 5232 out->mem.free += req_size; 5233 5234 req->app_target = r->app_target; 5235 5236 req->content_length = content_length; 5237 5238 p = (u_char *) (req->fields + fields_count); 5239 5240 nxt_debug(task, "fields_count=%d", (int) fields_count); 5241 5242 req->method_length = r->method->length; 5243 nxt_unit_sptr_set(&req->method, p); 5244 p = nxt_cpymem(p, r->method->start, r->method->length); 5245 *p++ = '\0'; 5246 5247 req->version_length = r->version.length; 5248 nxt_unit_sptr_set(&req->version, p); 5249 p = nxt_cpymem(p, r->version.start, r->version.length); 5250 *p++ = '\0'; 5251 5252 req->remote_length = r->remote->address_length; 5253 nxt_unit_sptr_set(&req->remote, p); 5254 p = nxt_cpymem(p, nxt_sockaddr_address(r->remote), 5255 r->remote->address_length); 5256 *p++ = '\0'; 5257 5258 req->local_length = r->local->address_length; 5259 nxt_unit_sptr_set(&req->local, p); 5260 p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); 5261 *p++ = '\0'; 5262 5263 req->tls = (r->tls != NULL); 5264 req->websocket_handshake = r->websocket_handshake; 5265 5266 req->server_name_length = r->server_name.length; 5267 nxt_unit_sptr_set(&req->server_name, p); 5268 p = nxt_cpymem(p, r->server_name.start, r->server_name.length); 5269 *p++ = '\0'; 5270 5271 target_pos = p; 5272 req->target_length = (uint32_t) r->target.length; 5273 nxt_unit_sptr_set(&req->target, p); 5274 p = nxt_cpymem(p, r->target.start, r->target.length); 5275 *p++ = '\0'; 5276 5277 req->path_length = (uint32_t) r->path->length; 5278 if (r->path->start == r->target.start) { 5279 nxt_unit_sptr_set(&req->path, target_pos); 5280 5281 } else { 5282 nxt_unit_sptr_set(&req->path, p); 5283 p = nxt_cpymem(p, r->path->start, r->path->length); 5284 *p++ = '\0'; 5285 } 5286 5287 req->query_length = r->args != NULL ? (uint32_t) r->args->length : 0; 5288 if (r->args != NULL && r->args->start != NULL) { 5289 query_pos = nxt_pointer_to(target_pos, 5290 r->args->start - r->target.start); 5291 5292 nxt_unit_sptr_set(&req->query, query_pos); 5293 5294 } else { 5295 req->query.offset = 0; 5296 } 5297 5298 req->content_length_field = NXT_UNIT_NONE_FIELD; 5299 req->content_type_field = NXT_UNIT_NONE_FIELD; 5300 req->cookie_field = NXT_UNIT_NONE_FIELD; 5301 req->authorization_field = NXT_UNIT_NONE_FIELD; 5302 5303 dst_field = req->fields; 5304 5305 for (field = nxt_fields_first(r->fields, &iter); 5306 field != NULL; 5307 field = nxt_fields_next(&iter)) 5308 { 5309 if (field->skip) { 5310 continue; 5311 } 5312 5313 dst_field->hash = field->hash; 5314 dst_field->skip = 0; 5315 dst_field->name_length = field->name_length + prefix->length; 5316 dst_field->value_length = field->value_length; 5317 5318 if (field == r->content_length) { 5319 req->content_length_field = dst_field - req->fields; 5320 5321 } else if (field == r->content_type) { 5322 req->content_type_field = dst_field - req->fields; 5323 5324 } else if (field == r->cookie) { 5325 req->cookie_field = dst_field - req->fields; 5326 5327 } else if (field == r->authorization) { 5328 req->authorization_field = dst_field - req->fields; 5329 } 5330 5331 nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p", 5332 (int) field->hash, (int) field->skip, 5333 (int) field->name_length, field->name, 5334 (int) field->value_length, field->value); 5335 5336 if (prefix->length != 0) { 5337 nxt_unit_sptr_set(&dst_field->name, p); 5338 p = nxt_cpymem(p, prefix->start, prefix->length); 5339 5340 end = field->name + field->name_length; 5341 for (pos = field->name; pos < end; pos++) { 5342 c = *pos; 5343 5344 if (c >= 'a' && c <= 'z') { 5345 *p++ = (c & ~0x20); 5346 continue; 5347 } 5348 5349 if (c == '-') { 5350 *p++ = '_'; 5351 continue; 5352 } 5353 5354 *p++ = c; 5355 } 5356 5357 } else { 5358 nxt_unit_sptr_set(&dst_field->name, p); 5359 p = nxt_cpymem(p, field->name, field->name_length); 5360 } 5361 5362 *p++ = '\0'; 5363 5364 nxt_unit_sptr_set(&dst_field->value, p); 5365 p = nxt_cpymem(p, field->value, field->value_length); 5366 5367 if (prefix->length != 0) { 5368 dup_iter = iter; 5369 5370 for (dup = nxt_fields_next(&dup_iter); 5371 dup != NULL; 5372 dup = nxt_fields_next(&dup_iter)) 5373 { 5374 if (dup->name_length != field->name_length 5375 || dup->skip 5376 || dup->hash != field->hash 5377 || nxt_memcasecmp(dup->name, field->name, dup->name_length)) 5378 { 5379 continue; 5380 } 5381 5382 p = nxt_cpymem(p, ", ", 2); 5383 p = nxt_cpymem(p, dup->value, dup->value_length); 5384 5385 dst_field->value_length += 2 + dup->value_length; 5386 5387 dup->skip = 1; 5388 } 5389 } 5390 5391 *p++ = '\0'; 5392 5393 dst_field++; 5394 } 5395 5396 req->fields_count = (uint32_t) (dst_field - req->fields); 5397 5398 nxt_unit_sptr_set(&req->preread_content, out->mem.free); 5399 5400 buf = out; 5401 tail = &buf->next; 5402 5403 for (b = r->body; b != NULL; b = b->next) { 5404 size = nxt_buf_mem_used_size(&b->mem); 5405 pos = b->mem.pos; 5406 5407 while (size > 0) { 5408 if (buf == NULL) { 5409 free_size = nxt_min(size, PORT_MMAP_DATA_SIZE); 5410 5411 buf = nxt_port_mmap_get_buf(task, &app->outgoing, free_size); 5412 if (nxt_slow_path(buf == NULL)) { 5413 while (out != NULL) { 5414 buf = out->next; 5415 out->next = NULL; 5416 out->completion_handler(task, out, out->parent); 5417 out = buf; 5418 } 5419 return NULL; 5420 } 5421 5422 *tail = buf; 5423 tail = &buf->next; 5424 5425 } else { 5426 free_size = nxt_buf_mem_free_size(&buf->mem); 5427 if (free_size < size 5428 && nxt_port_mmap_increase_buf(task, buf, size, 1) 5429 == NXT_OK) 5430 { 5431 free_size = nxt_buf_mem_free_size(&buf->mem); 5432 } 5433 } 5434 5435 if (free_size > 0) { 5436 copy_size = nxt_min(free_size, size); 5437 5438 buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size); 5439 5440 size -= copy_size; 5441 pos += copy_size; 5442 5443 if (size == 0) { 5444 break; 5445 } 5446 } 5447 5448 buf = NULL; 5449 } 5450 } 5451 5452 return out; 5453} 5454 5455 5456static void 5457nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data) 5458{ 5459 nxt_timer_t *timer; 5460 nxt_http_request_t *r; 5461 nxt_request_rpc_data_t *req_rpc_data; 5462 5463 timer = obj; 5464 5465 nxt_debug(task, "router app timeout"); 5466 5467 r = nxt_timer_data(timer, nxt_http_request_t, timer); 5468 req_rpc_data = r->timer_data; 5469 5470 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 5471 5472 nxt_request_rpc_data_unlink(task, req_rpc_data); 5473} 5474 5475 5476static void 5477nxt_router_http_request_release_post(nxt_task_t *task, nxt_http_request_t *r) 5478{ 5479 r->timer.handler = nxt_router_http_request_release; 5480 nxt_timer_add(task->thread->engine, &r->timer, 0); 5481} 5482 5483 5484static void 5485nxt_router_http_request_release(nxt_task_t *task, void *obj, void *data) 5486{ 5487 nxt_http_request_t *r; 5488 5489 nxt_debug(task, "http request pool release"); 5490 5491 r = nxt_timer_data(obj, nxt_http_request_t, timer); 5492 5493 nxt_mp_release(r->mem_pool); 5494} 5495 5496 5497static void 5498nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5499{ 5500 size_t mi; 5501 uint32_t i; 5502 nxt_bool_t ack; 5503 nxt_process_t *process; 5504 nxt_free_map_t *m; 5505 nxt_port_mmap_handler_t *mmap_handler; 5506 5507 nxt_debug(task, "oosm in %PI", msg->port_msg.pid); 5508 5509 process = nxt_runtime_process_find(task->thread->runtime, 5510 msg->port_msg.pid); 5511 if (nxt_slow_path(process == NULL)) { 5512 return; 5513 } 5514 5515 ack = 0; 5516 5517 /* 5518 * To mitigate possible racing condition (when OOSM message received 5519 * after some of the memory was already freed), need to try to find 5520 * first free segment in shared memory and send ACK if found. 5521 */ 5522 5523 nxt_thread_mutex_lock(&process->incoming.mutex); 5524 5525 for (i = 0; i < process->incoming.size; i++) { 5526 mmap_handler = process->incoming.elts[i].mmap_handler; 5527 5528 if (nxt_slow_path(mmap_handler == NULL)) { 5529 continue; 5530 } 5531 5532 m = mmap_handler->hdr->free_map; 5533 5534 for (mi = 0; mi < MAX_FREE_IDX; mi++) { 5535 if (m[mi] != 0) { 5536 ack = 1; 5537 5538 nxt_debug(task, "oosm: already free #%uD %uz = 0x%08xA", 5539 i, mi, m[mi]); 5540 5541 break; 5542 } 5543 } 5544 } 5545 5546 nxt_thread_mutex_unlock(&process->incoming.mutex); 5547 5548 if (ack) { 5549 nxt_process_broadcast_shm_ack(task, process); 5550 } 5551} 5552 5553 5554static void 5555nxt_router_get_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5556{ 5557 nxt_fd_t fd; 5558 nxt_port_t *port; 5559 nxt_runtime_t *rt; 5560 nxt_port_mmaps_t *mmaps; 5561 nxt_port_msg_get_mmap_t *get_mmap_msg; 5562 nxt_port_mmap_handler_t *mmap_handler; 5563 5564 rt = task->thread->runtime; 5565 5566 port = nxt_runtime_port_find(rt, msg->port_msg.pid, 5567 msg->port_msg.reply_port); 5568 if (nxt_slow_path(port == NULL)) { 5569 nxt_alert(task, "get_mmap_handler: reply_port %PI:%d not found", 5570 msg->port_msg.pid, msg->port_msg.reply_port); 5571 5572 return; 5573 } 5574 5575 if (nxt_slow_path(nxt_buf_used_size(msg->buf) 5576 < (int) sizeof(nxt_port_msg_get_mmap_t))) 5577 { 5578 nxt_alert(task, "get_mmap_handler: message buffer too small (%d)", 5579 (int) nxt_buf_used_size(msg->buf)); 5580 5581 return; 5582 } 5583 5584 get_mmap_msg = (nxt_port_msg_get_mmap_t *) msg->buf->mem.pos; 5585 5586 nxt_assert(port->type == NXT_PROCESS_APP); 5587 5588 if (nxt_slow_path(port->app == NULL)) { 5589 nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d", 5590 port->pid, port->id); 5591 5592 // FIXME 5593 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 5594 -1, msg->port_msg.stream, 0, NULL); 5595 5596 return; 5597 } 5598 5599 mmaps = &port->app->outgoing; 5600 nxt_thread_mutex_lock(&mmaps->mutex); 5601 5602 if (nxt_slow_path(get_mmap_msg->id >= mmaps->size)) { 5603 nxt_thread_mutex_unlock(&mmaps->mutex); 5604 5605 nxt_alert(task, "get_mmap_handler: mmap id is too big (%d)", 5606 (int) get_mmap_msg->id); 5607 5608 // FIXME 5609 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 5610 -1, msg->port_msg.stream, 0, NULL); 5611 return; 5612 } 5613 5614 mmap_handler = mmaps->elts[get_mmap_msg->id].mmap_handler; 5615 5616 fd = mmap_handler->fd; 5617 5618 nxt_thread_mutex_unlock(&mmaps->mutex); 5619 5620 nxt_debug(task, "get mmap %PI:%d found", 5621 msg->port_msg.pid, (int) get_mmap_msg->id); 5622 5623 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, NULL); 5624} 5625 5626 5627static void 5628nxt_router_get_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5629{ 5630 nxt_port_t *port, *reply_port; 5631 nxt_runtime_t *rt; 5632 nxt_port_msg_get_port_t *get_port_msg; 5633 5634 rt = task->thread->runtime; 5635 5636 reply_port = nxt_runtime_port_find(rt, msg->port_msg.pid, 5637 msg->port_msg.reply_port); 5638 if (nxt_slow_path(reply_port == NULL)) { 5639 nxt_alert(task, "get_port_handler: reply_port %PI:%d not found", 5640 msg->port_msg.pid, msg->port_msg.reply_port); 5641 5642 return; 5643 } 5644 5645 if (nxt_slow_path(nxt_buf_used_size(msg->buf) 5646 < (int) sizeof(nxt_port_msg_get_port_t))) 5647 { 5648 nxt_alert(task, "get_port_handler: message buffer too small (%d)", 5649 (int) nxt_buf_used_size(msg->buf)); 5650 5651 return; 5652 } 5653 5654 get_port_msg = (nxt_port_msg_get_port_t *) msg->buf->mem.pos; 5655 5656 port = nxt_runtime_port_find(rt, get_port_msg->pid, get_port_msg->id); 5657 if (nxt_slow_path(port == NULL)) { 5658 nxt_alert(task, "get_port_handler: port %PI:%d not found", 5659 get_port_msg->pid, get_port_msg->id); 5660 5661 return; 5662 } 5663 5664 nxt_debug(task, "get port %PI:%d found", get_port_msg->pid, 5665 get_port_msg->id); 5666 5667 (void) nxt_port_send_port(task, reply_port, port, msg->port_msg.stream); 5668}
| 5000 } 5001 5002 nxt_thread_mutex_destroy(&app->mutex); 5003 nxt_mp_destroy(app->mem_pool); 5004 5005 app_joint->app = NULL; 5006 5007 if (nxt_timer_delete(task->thread->engine, &app_joint->idle_timer)) { 5008 app_joint->idle_timer.handler = nxt_router_app_joint_release_handler; 5009 nxt_timer_add(task->thread->engine, &app_joint->idle_timer, 0); 5010 5011 } else { 5012 nxt_router_app_joint_use(task, app_joint, -1); 5013 } 5014} 5015 5016 5017static void 5018nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app, 5019 nxt_request_rpc_data_t *req_rpc_data) 5020{ 5021 nxt_bool_t start_process; 5022 nxt_port_t *port; 5023 nxt_http_request_t *r; 5024 5025 start_process = 0; 5026 5027 nxt_thread_mutex_lock(&app->mutex); 5028 5029 port = app->shared_port; 5030 nxt_port_inc_use(port); 5031 5032 app->active_requests++; 5033 5034 if (nxt_router_app_can_start(app) && nxt_router_app_need_start(app)) { 5035 app->pending_processes++; 5036 start_process = 1; 5037 } 5038 5039 r = req_rpc_data->request; 5040 5041 /* 5042 * Put request into application-wide list to be able to cancel request 5043 * if something goes wrong with application processes. 5044 */ 5045 nxt_queue_insert_tail(&app->ack_waiting_req, &r->app_link); 5046 5047 nxt_thread_mutex_unlock(&app->mutex); 5048 5049 /* 5050 * Retain request memory pool while request is linked in ack_waiting_req 5051 * to guarantee request structure memory is accessble. 5052 */ 5053 nxt_mp_retain(r->mem_pool); 5054 5055 req_rpc_data->app_port = port; 5056 req_rpc_data->apr_action = NXT_APR_REQUEST_FAILED; 5057 5058 if (start_process) { 5059 nxt_router_start_app_process(task, app); 5060 } 5061} 5062 5063 5064void 5065nxt_router_process_http_request(nxt_task_t *task, nxt_http_request_t *r, 5066 nxt_http_action_t *action) 5067{ 5068 nxt_event_engine_t *engine; 5069 nxt_http_app_conf_t *conf; 5070 nxt_request_rpc_data_t *req_rpc_data; 5071 5072 conf = action->u.conf; 5073 engine = task->thread->engine; 5074 5075 r->app_target = conf->target; 5076 5077 req_rpc_data = nxt_port_rpc_register_handler_ex(task, engine->port, 5078 nxt_router_response_ready_handler, 5079 nxt_router_response_error_handler, 5080 sizeof(nxt_request_rpc_data_t)); 5081 if (nxt_slow_path(req_rpc_data == NULL)) { 5082 nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 5083 return; 5084 } 5085 5086 /* 5087 * At this point we have request req_rpc_data allocated and registered 5088 * in port handlers. Need to fixup request memory pool. Counterpart 5089 * release will be called via following call chain: 5090 * nxt_request_rpc_data_unlink() -> 5091 * nxt_router_http_request_release_post() -> 5092 * nxt_router_http_request_release() 5093 */ 5094 nxt_mp_retain(r->mem_pool); 5095 5096 r->timer.task = &engine->task; 5097 r->timer.work_queue = &engine->fast_work_queue; 5098 r->timer.log = engine->task.log; 5099 r->timer.bias = NXT_TIMER_DEFAULT_BIAS; 5100 5101 r->engine = engine; 5102 r->err_work.handler = nxt_router_http_request_error; 5103 r->err_work.task = task; 5104 r->err_work.obj = r; 5105 5106 req_rpc_data->stream = nxt_port_rpc_ex_stream(req_rpc_data); 5107 req_rpc_data->app = conf->app; 5108 req_rpc_data->msg_info.body_fd = -1; 5109 req_rpc_data->rpc_cancel = 1; 5110 5111 nxt_router_app_use(task, conf->app, 1); 5112 5113 req_rpc_data->request = r; 5114 r->req_rpc_data = req_rpc_data; 5115 5116 if (r->last != NULL) { 5117 r->last->completion_handler = nxt_router_http_request_done; 5118 } 5119 5120 nxt_router_app_port_get(task, conf->app, req_rpc_data); 5121 nxt_router_app_prepare_request(task, req_rpc_data); 5122} 5123 5124 5125static void 5126nxt_router_http_request_error(nxt_task_t *task, void *obj, void *data) 5127{ 5128 nxt_http_request_t *r; 5129 5130 r = obj; 5131 5132 nxt_debug(task, "router http request error (rpc_data %p)", r->req_rpc_data); 5133 5134 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 5135 5136 if (r->req_rpc_data != NULL) { 5137 nxt_request_rpc_data_unlink(task, r->req_rpc_data); 5138 } 5139 5140 nxt_mp_release(r->mem_pool); 5141} 5142 5143 5144static void 5145nxt_router_http_request_done(nxt_task_t *task, void *obj, void *data) 5146{ 5147 nxt_http_request_t *r; 5148 5149 r = data; 5150 5151 nxt_debug(task, "router http request done (rpc_data %p)", r->req_rpc_data); 5152 5153 if (r->req_rpc_data != NULL) { 5154 nxt_request_rpc_data_unlink(task, r->req_rpc_data); 5155 } 5156 5157 nxt_http_request_close_handler(task, r, r->proto.any); 5158} 5159 5160 5161static void 5162nxt_router_dummy_buf_completion(nxt_task_t *task, void *obj, void *data) 5163{ 5164} 5165 5166 5167static void 5168nxt_router_app_prepare_request(nxt_task_t *task, 5169 nxt_request_rpc_data_t *req_rpc_data) 5170{ 5171 nxt_app_t *app; 5172 nxt_buf_t *buf, *body; 5173 nxt_int_t res; 5174 nxt_port_t *port, *reply_port; 5175 5176 int notify; 5177 struct { 5178 nxt_port_msg_t pm; 5179 nxt_port_mmap_msg_t mm; 5180 } msg; 5181 5182 5183 app = req_rpc_data->app; 5184 5185 nxt_assert(app != NULL); 5186 5187 port = req_rpc_data->app_port; 5188 5189 nxt_assert(port != NULL); 5190 nxt_assert(port->queue != NULL); 5191 5192 reply_port = task->thread->engine->port; 5193 5194 buf = nxt_router_prepare_msg(task, req_rpc_data->request, app, 5195 nxt_app_msg_prefix[app->type]); 5196 if (nxt_slow_path(buf == NULL)) { 5197 nxt_alert(task, "stream #%uD, app '%V': failed to prepare app message", 5198 req_rpc_data->stream, &app->name); 5199 5200 nxt_http_request_error(task, req_rpc_data->request, 5201 NXT_HTTP_INTERNAL_SERVER_ERROR); 5202 5203 return; 5204 } 5205 5206 nxt_debug(task, "about to send %O bytes buffer to app process port %d", 5207 nxt_buf_used_size(buf), 5208 port->socket.fd); 5209 5210 req_rpc_data->msg_info.buf = buf; 5211 5212 body = req_rpc_data->request->body; 5213 5214 if (body != NULL && nxt_buf_is_file(body)) { 5215 req_rpc_data->msg_info.body_fd = body->file->fd; 5216 5217 body->file->fd = -1; 5218 5219 } else { 5220 req_rpc_data->msg_info.body_fd = -1; 5221 } 5222 5223 msg.pm.stream = req_rpc_data->stream; 5224 msg.pm.pid = reply_port->pid; 5225 msg.pm.reply_port = reply_port->id; 5226 msg.pm.type = NXT_PORT_MSG_REQ_HEADERS; 5227 msg.pm.last = 0; 5228 msg.pm.mmap = 1; 5229 msg.pm.nf = 0; 5230 msg.pm.mf = 0; 5231 msg.pm.tracking = 0; 5232 5233 nxt_port_mmap_handler_t *mmap_handler = buf->parent; 5234 nxt_port_mmap_header_t *hdr = mmap_handler->hdr; 5235 5236 msg.mm.mmap_id = hdr->id; 5237 msg.mm.chunk_id = nxt_port_mmap_chunk_id(hdr, buf->mem.pos); 5238 msg.mm.size = nxt_buf_used_size(buf); 5239 5240 res = nxt_app_queue_send(port->queue, &msg, sizeof(msg), 5241 req_rpc_data->stream, ¬ify, 5242 &req_rpc_data->msg_info.tracking_cookie); 5243 if (nxt_fast_path(res == NXT_OK)) { 5244 if (notify != 0) { 5245 (void) nxt_port_socket_write(task, port, 5246 NXT_PORT_MSG_READ_QUEUE, 5247 -1, req_rpc_data->stream, 5248 reply_port->id, NULL); 5249 5250 } else { 5251 nxt_debug(task, "queue is not empty"); 5252 } 5253 5254 buf->is_port_mmap_sent = 1; 5255 buf->mem.pos = buf->mem.free; 5256 5257 } else { 5258 nxt_alert(task, "stream #%uD, app '%V': failed to send app message", 5259 req_rpc_data->stream, &app->name); 5260 5261 nxt_http_request_error(task, req_rpc_data->request, 5262 NXT_HTTP_INTERNAL_SERVER_ERROR); 5263 } 5264} 5265 5266 5267struct nxt_fields_iter_s { 5268 nxt_list_part_t *part; 5269 nxt_http_field_t *field; 5270}; 5271 5272typedef struct nxt_fields_iter_s nxt_fields_iter_t; 5273 5274 5275static nxt_http_field_t * 5276nxt_fields_part_first(nxt_list_part_t *part, nxt_fields_iter_t *i) 5277{ 5278 if (part == NULL) { 5279 return NULL; 5280 } 5281 5282 while (part->nelts == 0) { 5283 part = part->next; 5284 if (part == NULL) { 5285 return NULL; 5286 } 5287 } 5288 5289 i->part = part; 5290 i->field = nxt_list_data(i->part); 5291 5292 return i->field; 5293} 5294 5295 5296static nxt_http_field_t * 5297nxt_fields_first(nxt_list_t *fields, nxt_fields_iter_t *i) 5298{ 5299 return nxt_fields_part_first(nxt_list_part(fields), i); 5300} 5301 5302 5303static nxt_http_field_t * 5304nxt_fields_next(nxt_fields_iter_t *i) 5305{ 5306 nxt_http_field_t *end = nxt_list_data(i->part); 5307 5308 end += i->part->nelts; 5309 i->field++; 5310 5311 if (i->field < end) { 5312 return i->field; 5313 } 5314 5315 return nxt_fields_part_first(i->part->next, i); 5316} 5317 5318 5319static nxt_buf_t * 5320nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, 5321 nxt_app_t *app, const nxt_str_t *prefix) 5322{ 5323 void *target_pos, *query_pos; 5324 u_char *pos, *end, *p, c; 5325 size_t fields_count, req_size, size, free_size; 5326 size_t copy_size; 5327 nxt_off_t content_length; 5328 nxt_buf_t *b, *buf, *out, **tail; 5329 nxt_http_field_t *field, *dup; 5330 nxt_unit_field_t *dst_field; 5331 nxt_fields_iter_t iter, dup_iter; 5332 nxt_unit_request_t *req; 5333 5334 req_size = sizeof(nxt_unit_request_t) 5335 + r->method->length + 1 5336 + r->version.length + 1 5337 + r->remote->length + 1 5338 + r->local->length + 1 5339 + r->server_name.length + 1 5340 + r->target.length + 1 5341 + (r->path->start != r->target.start ? r->path->length + 1 : 0); 5342 5343 content_length = r->content_length_n < 0 ? 0 : r->content_length_n; 5344 fields_count = 0; 5345 5346 nxt_list_each(field, r->fields) { 5347 fields_count++; 5348 5349 req_size += field->name_length + prefix->length + 1 5350 + field->value_length + 1; 5351 } nxt_list_loop; 5352 5353 req_size += fields_count * sizeof(nxt_unit_field_t); 5354 5355 if (nxt_slow_path(req_size > PORT_MMAP_DATA_SIZE)) { 5356 nxt_alert(task, "headers to big to fit in shared memory (%d)", 5357 (int) req_size); 5358 5359 return NULL; 5360 } 5361 5362 out = nxt_port_mmap_get_buf(task, &app->outgoing, 5363 nxt_min(req_size + content_length, PORT_MMAP_DATA_SIZE)); 5364 if (nxt_slow_path(out == NULL)) { 5365 return NULL; 5366 } 5367 5368 req = (nxt_unit_request_t *) out->mem.free; 5369 out->mem.free += req_size; 5370 5371 req->app_target = r->app_target; 5372 5373 req->content_length = content_length; 5374 5375 p = (u_char *) (req->fields + fields_count); 5376 5377 nxt_debug(task, "fields_count=%d", (int) fields_count); 5378 5379 req->method_length = r->method->length; 5380 nxt_unit_sptr_set(&req->method, p); 5381 p = nxt_cpymem(p, r->method->start, r->method->length); 5382 *p++ = '\0'; 5383 5384 req->version_length = r->version.length; 5385 nxt_unit_sptr_set(&req->version, p); 5386 p = nxt_cpymem(p, r->version.start, r->version.length); 5387 *p++ = '\0'; 5388 5389 req->remote_length = r->remote->address_length; 5390 nxt_unit_sptr_set(&req->remote, p); 5391 p = nxt_cpymem(p, nxt_sockaddr_address(r->remote), 5392 r->remote->address_length); 5393 *p++ = '\0'; 5394 5395 req->local_length = r->local->address_length; 5396 nxt_unit_sptr_set(&req->local, p); 5397 p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); 5398 *p++ = '\0'; 5399 5400 req->tls = (r->tls != NULL); 5401 req->websocket_handshake = r->websocket_handshake; 5402 5403 req->server_name_length = r->server_name.length; 5404 nxt_unit_sptr_set(&req->server_name, p); 5405 p = nxt_cpymem(p, r->server_name.start, r->server_name.length); 5406 *p++ = '\0'; 5407 5408 target_pos = p; 5409 req->target_length = (uint32_t) r->target.length; 5410 nxt_unit_sptr_set(&req->target, p); 5411 p = nxt_cpymem(p, r->target.start, r->target.length); 5412 *p++ = '\0'; 5413 5414 req->path_length = (uint32_t) r->path->length; 5415 if (r->path->start == r->target.start) { 5416 nxt_unit_sptr_set(&req->path, target_pos); 5417 5418 } else { 5419 nxt_unit_sptr_set(&req->path, p); 5420 p = nxt_cpymem(p, r->path->start, r->path->length); 5421 *p++ = '\0'; 5422 } 5423 5424 req->query_length = r->args != NULL ? (uint32_t) r->args->length : 0; 5425 if (r->args != NULL && r->args->start != NULL) { 5426 query_pos = nxt_pointer_to(target_pos, 5427 r->args->start - r->target.start); 5428 5429 nxt_unit_sptr_set(&req->query, query_pos); 5430 5431 } else { 5432 req->query.offset = 0; 5433 } 5434 5435 req->content_length_field = NXT_UNIT_NONE_FIELD; 5436 req->content_type_field = NXT_UNIT_NONE_FIELD; 5437 req->cookie_field = NXT_UNIT_NONE_FIELD; 5438 req->authorization_field = NXT_UNIT_NONE_FIELD; 5439 5440 dst_field = req->fields; 5441 5442 for (field = nxt_fields_first(r->fields, &iter); 5443 field != NULL; 5444 field = nxt_fields_next(&iter)) 5445 { 5446 if (field->skip) { 5447 continue; 5448 } 5449 5450 dst_field->hash = field->hash; 5451 dst_field->skip = 0; 5452 dst_field->name_length = field->name_length + prefix->length; 5453 dst_field->value_length = field->value_length; 5454 5455 if (field == r->content_length) { 5456 req->content_length_field = dst_field - req->fields; 5457 5458 } else if (field == r->content_type) { 5459 req->content_type_field = dst_field - req->fields; 5460 5461 } else if (field == r->cookie) { 5462 req->cookie_field = dst_field - req->fields; 5463 5464 } else if (field == r->authorization) { 5465 req->authorization_field = dst_field - req->fields; 5466 } 5467 5468 nxt_debug(task, "add field 0x%04Xd, %d, %d, %p : %d %p", 5469 (int) field->hash, (int) field->skip, 5470 (int) field->name_length, field->name, 5471 (int) field->value_length, field->value); 5472 5473 if (prefix->length != 0) { 5474 nxt_unit_sptr_set(&dst_field->name, p); 5475 p = nxt_cpymem(p, prefix->start, prefix->length); 5476 5477 end = field->name + field->name_length; 5478 for (pos = field->name; pos < end; pos++) { 5479 c = *pos; 5480 5481 if (c >= 'a' && c <= 'z') { 5482 *p++ = (c & ~0x20); 5483 continue; 5484 } 5485 5486 if (c == '-') { 5487 *p++ = '_'; 5488 continue; 5489 } 5490 5491 *p++ = c; 5492 } 5493 5494 } else { 5495 nxt_unit_sptr_set(&dst_field->name, p); 5496 p = nxt_cpymem(p, field->name, field->name_length); 5497 } 5498 5499 *p++ = '\0'; 5500 5501 nxt_unit_sptr_set(&dst_field->value, p); 5502 p = nxt_cpymem(p, field->value, field->value_length); 5503 5504 if (prefix->length != 0) { 5505 dup_iter = iter; 5506 5507 for (dup = nxt_fields_next(&dup_iter); 5508 dup != NULL; 5509 dup = nxt_fields_next(&dup_iter)) 5510 { 5511 if (dup->name_length != field->name_length 5512 || dup->skip 5513 || dup->hash != field->hash 5514 || nxt_memcasecmp(dup->name, field->name, dup->name_length)) 5515 { 5516 continue; 5517 } 5518 5519 p = nxt_cpymem(p, ", ", 2); 5520 p = nxt_cpymem(p, dup->value, dup->value_length); 5521 5522 dst_field->value_length += 2 + dup->value_length; 5523 5524 dup->skip = 1; 5525 } 5526 } 5527 5528 *p++ = '\0'; 5529 5530 dst_field++; 5531 } 5532 5533 req->fields_count = (uint32_t) (dst_field - req->fields); 5534 5535 nxt_unit_sptr_set(&req->preread_content, out->mem.free); 5536 5537 buf = out; 5538 tail = &buf->next; 5539 5540 for (b = r->body; b != NULL; b = b->next) { 5541 size = nxt_buf_mem_used_size(&b->mem); 5542 pos = b->mem.pos; 5543 5544 while (size > 0) { 5545 if (buf == NULL) { 5546 free_size = nxt_min(size, PORT_MMAP_DATA_SIZE); 5547 5548 buf = nxt_port_mmap_get_buf(task, &app->outgoing, free_size); 5549 if (nxt_slow_path(buf == NULL)) { 5550 while (out != NULL) { 5551 buf = out->next; 5552 out->next = NULL; 5553 out->completion_handler(task, out, out->parent); 5554 out = buf; 5555 } 5556 return NULL; 5557 } 5558 5559 *tail = buf; 5560 tail = &buf->next; 5561 5562 } else { 5563 free_size = nxt_buf_mem_free_size(&buf->mem); 5564 if (free_size < size 5565 && nxt_port_mmap_increase_buf(task, buf, size, 1) 5566 == NXT_OK) 5567 { 5568 free_size = nxt_buf_mem_free_size(&buf->mem); 5569 } 5570 } 5571 5572 if (free_size > 0) { 5573 copy_size = nxt_min(free_size, size); 5574 5575 buf->mem.free = nxt_cpymem(buf->mem.free, pos, copy_size); 5576 5577 size -= copy_size; 5578 pos += copy_size; 5579 5580 if (size == 0) { 5581 break; 5582 } 5583 } 5584 5585 buf = NULL; 5586 } 5587 } 5588 5589 return out; 5590} 5591 5592 5593static void 5594nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data) 5595{ 5596 nxt_timer_t *timer; 5597 nxt_http_request_t *r; 5598 nxt_request_rpc_data_t *req_rpc_data; 5599 5600 timer = obj; 5601 5602 nxt_debug(task, "router app timeout"); 5603 5604 r = nxt_timer_data(timer, nxt_http_request_t, timer); 5605 req_rpc_data = r->timer_data; 5606 5607 nxt_http_request_error(task, r, NXT_HTTP_SERVICE_UNAVAILABLE); 5608 5609 nxt_request_rpc_data_unlink(task, req_rpc_data); 5610} 5611 5612 5613static void 5614nxt_router_http_request_release_post(nxt_task_t *task, nxt_http_request_t *r) 5615{ 5616 r->timer.handler = nxt_router_http_request_release; 5617 nxt_timer_add(task->thread->engine, &r->timer, 0); 5618} 5619 5620 5621static void 5622nxt_router_http_request_release(nxt_task_t *task, void *obj, void *data) 5623{ 5624 nxt_http_request_t *r; 5625 5626 nxt_debug(task, "http request pool release"); 5627 5628 r = nxt_timer_data(obj, nxt_http_request_t, timer); 5629 5630 nxt_mp_release(r->mem_pool); 5631} 5632 5633 5634static void 5635nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5636{ 5637 size_t mi; 5638 uint32_t i; 5639 nxt_bool_t ack; 5640 nxt_process_t *process; 5641 nxt_free_map_t *m; 5642 nxt_port_mmap_handler_t *mmap_handler; 5643 5644 nxt_debug(task, "oosm in %PI", msg->port_msg.pid); 5645 5646 process = nxt_runtime_process_find(task->thread->runtime, 5647 msg->port_msg.pid); 5648 if (nxt_slow_path(process == NULL)) { 5649 return; 5650 } 5651 5652 ack = 0; 5653 5654 /* 5655 * To mitigate possible racing condition (when OOSM message received 5656 * after some of the memory was already freed), need to try to find 5657 * first free segment in shared memory and send ACK if found. 5658 */ 5659 5660 nxt_thread_mutex_lock(&process->incoming.mutex); 5661 5662 for (i = 0; i < process->incoming.size; i++) { 5663 mmap_handler = process->incoming.elts[i].mmap_handler; 5664 5665 if (nxt_slow_path(mmap_handler == NULL)) { 5666 continue; 5667 } 5668 5669 m = mmap_handler->hdr->free_map; 5670 5671 for (mi = 0; mi < MAX_FREE_IDX; mi++) { 5672 if (m[mi] != 0) { 5673 ack = 1; 5674 5675 nxt_debug(task, "oosm: already free #%uD %uz = 0x%08xA", 5676 i, mi, m[mi]); 5677 5678 break; 5679 } 5680 } 5681 } 5682 5683 nxt_thread_mutex_unlock(&process->incoming.mutex); 5684 5685 if (ack) { 5686 nxt_process_broadcast_shm_ack(task, process); 5687 } 5688} 5689 5690 5691static void 5692nxt_router_get_mmap_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5693{ 5694 nxt_fd_t fd; 5695 nxt_port_t *port; 5696 nxt_runtime_t *rt; 5697 nxt_port_mmaps_t *mmaps; 5698 nxt_port_msg_get_mmap_t *get_mmap_msg; 5699 nxt_port_mmap_handler_t *mmap_handler; 5700 5701 rt = task->thread->runtime; 5702 5703 port = nxt_runtime_port_find(rt, msg->port_msg.pid, 5704 msg->port_msg.reply_port); 5705 if (nxt_slow_path(port == NULL)) { 5706 nxt_alert(task, "get_mmap_handler: reply_port %PI:%d not found", 5707 msg->port_msg.pid, msg->port_msg.reply_port); 5708 5709 return; 5710 } 5711 5712 if (nxt_slow_path(nxt_buf_used_size(msg->buf) 5713 < (int) sizeof(nxt_port_msg_get_mmap_t))) 5714 { 5715 nxt_alert(task, "get_mmap_handler: message buffer too small (%d)", 5716 (int) nxt_buf_used_size(msg->buf)); 5717 5718 return; 5719 } 5720 5721 get_mmap_msg = (nxt_port_msg_get_mmap_t *) msg->buf->mem.pos; 5722 5723 nxt_assert(port->type == NXT_PROCESS_APP); 5724 5725 if (nxt_slow_path(port->app == NULL)) { 5726 nxt_alert(task, "get_mmap_handler: app == NULL for reply port %PI:%d", 5727 port->pid, port->id); 5728 5729 // FIXME 5730 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 5731 -1, msg->port_msg.stream, 0, NULL); 5732 5733 return; 5734 } 5735 5736 mmaps = &port->app->outgoing; 5737 nxt_thread_mutex_lock(&mmaps->mutex); 5738 5739 if (nxt_slow_path(get_mmap_msg->id >= mmaps->size)) { 5740 nxt_thread_mutex_unlock(&mmaps->mutex); 5741 5742 nxt_alert(task, "get_mmap_handler: mmap id is too big (%d)", 5743 (int) get_mmap_msg->id); 5744 5745 // FIXME 5746 nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 5747 -1, msg->port_msg.stream, 0, NULL); 5748 return; 5749 } 5750 5751 mmap_handler = mmaps->elts[get_mmap_msg->id].mmap_handler; 5752 5753 fd = mmap_handler->fd; 5754 5755 nxt_thread_mutex_unlock(&mmaps->mutex); 5756 5757 nxt_debug(task, "get mmap %PI:%d found", 5758 msg->port_msg.pid, (int) get_mmap_msg->id); 5759 5760 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, NULL); 5761} 5762 5763 5764static void 5765nxt_router_get_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 5766{ 5767 nxt_port_t *port, *reply_port; 5768 nxt_runtime_t *rt; 5769 nxt_port_msg_get_port_t *get_port_msg; 5770 5771 rt = task->thread->runtime; 5772 5773 reply_port = nxt_runtime_port_find(rt, msg->port_msg.pid, 5774 msg->port_msg.reply_port); 5775 if (nxt_slow_path(reply_port == NULL)) { 5776 nxt_alert(task, "get_port_handler: reply_port %PI:%d not found", 5777 msg->port_msg.pid, msg->port_msg.reply_port); 5778 5779 return; 5780 } 5781 5782 if (nxt_slow_path(nxt_buf_used_size(msg->buf) 5783 < (int) sizeof(nxt_port_msg_get_port_t))) 5784 { 5785 nxt_alert(task, "get_port_handler: message buffer too small (%d)", 5786 (int) nxt_buf_used_size(msg->buf)); 5787 5788 return; 5789 } 5790 5791 get_port_msg = (nxt_port_msg_get_port_t *) msg->buf->mem.pos; 5792 5793 port = nxt_runtime_port_find(rt, get_port_msg->pid, get_port_msg->id); 5794 if (nxt_slow_path(port == NULL)) { 5795 nxt_alert(task, "get_port_handler: port %PI:%d not found", 5796 get_port_msg->pid, get_port_msg->id); 5797 5798 return; 5799 } 5800 5801 nxt_debug(task, "get port %PI:%d found", get_port_msg->pid, 5802 get_port_msg->id); 5803 5804 (void) nxt_port_send_port(task, reply_port, port, msg->port_msg.stream); 5805}
|