120Sigor@sysoev.ru 220Sigor@sysoev.ru /* 320Sigor@sysoev.ru * Copyright (C) Igor Sysoev 420Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 520Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 620Sigor@sysoev.ru */ 720Sigor@sysoev.ru 853Sigor@sysoev.ru #include <nxt_router.h> 9115Sigor@sysoev.ru #include <nxt_conf.h> 1020Sigor@sysoev.ru 1120Sigor@sysoev.ru 12115Sigor@sysoev.ru typedef struct { 13133Sigor@sysoev.ru nxt_str_t type; 14133Sigor@sysoev.ru uint32_t workers; 15133Sigor@sysoev.ru } nxt_router_app_conf_t; 16133Sigor@sysoev.ru 17133Sigor@sysoev.ru 18133Sigor@sysoev.ru typedef struct { 19133Sigor@sysoev.ru nxt_str_t application; 20115Sigor@sysoev.ru } nxt_router_listener_conf_t; 21115Sigor@sysoev.ru 22115Sigor@sysoev.ru 23167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t; 24141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t; 25141Smax.romanov@nginx.com 26141Smax.romanov@nginx.com struct nxt_start_worker_s { 27141Smax.romanov@nginx.com nxt_app_t *app; 28167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 29141Smax.romanov@nginx.com 30141Smax.romanov@nginx.com nxt_work_t work; 31141Smax.romanov@nginx.com }; 32141Smax.romanov@nginx.com 33141Smax.romanov@nginx.com 34167Smax.romanov@nginx.com struct nxt_req_app_link_s { 35167Smax.romanov@nginx.com nxt_req_id_t req_id; 36167Smax.romanov@nginx.com nxt_port_t *app_port; 37167Smax.romanov@nginx.com nxt_port_t *reply_port; 38167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 39167Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 40167Smax.romanov@nginx.com 41167Smax.romanov@nginx.com nxt_queue_link_t link; /* for nxt_app_t.requests */ 42167Smax.romanov@nginx.com 43167Smax.romanov@nginx.com nxt_mp_t *mem_pool; 44167Smax.romanov@nginx.com nxt_work_t work; 45167Smax.romanov@nginx.com }; 46167Smax.romanov@nginx.com 47167Smax.romanov@nginx.com 48198Sigor@sysoev.ru typedef struct { 49198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 50198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 51198Sigor@sysoev.ru } nxt_socket_rpc_t; 52198Sigor@sysoev.ru 53198Sigor@sysoev.ru 54139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 55198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 56198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 57139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 58139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 59139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 60139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 61193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 6253Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 6353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 6453Sigor@sysoev.ru 65115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 66115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 67133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 68133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 69133Sigor@sysoev.ru nxt_str_t *name); 70198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 71198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 72198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 73198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 74198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 75198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 7665Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 7765Sigor@sysoev.ru nxt_sockaddr_t *sa); 7853Sigor@sysoev.ru 7953Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 8053Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 8153Sigor@sysoev.ru const nxt_event_interface_t *interface); 82115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 83115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 84115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 85115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 86115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 87115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 88115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 89154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 90154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 91154Sigor@sysoev.ru nxt_work_handler_t handler); 92139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 93139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 9453Sigor@sysoev.ru 9553Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 9653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 9753Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 9853Sigor@sysoev.ru nxt_event_engine_t *engine); 99133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 100133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 10153Sigor@sysoev.ru 10253Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 103154Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf); 10453Sigor@sysoev.ru 10553Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 10653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 10753Sigor@sysoev.ru void *data); 10853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 10953Sigor@sysoev.ru void *data); 11053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 11153Sigor@sysoev.ru void *data); 11253Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 11353Sigor@sysoev.ru void *data); 11453Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 11553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 11653Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 11753Sigor@sysoev.ru void *data); 11853Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 11953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 12053Sigor@sysoev.ru 121167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj, 122167Smax.romanov@nginx.com void *data); 123167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app); 124167Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t req_id); 125141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj, 126141Smax.romanov@nginx.com void *data); 127141Smax.romanov@nginx.com 12853Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 12953Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 13053Sigor@sysoev.ru void *data); 131206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, 132206Smax.romanov@nginx.com void *data); 13388Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 13488Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 135141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task, 136167Smax.romanov@nginx.com nxt_req_app_link_t *ra, nxt_port_t *port); 137*216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 138*216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 139*216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 140*216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 141*216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 142*216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 14388Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 14453Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 14553Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 14653Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 14753Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 14862Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 14920Sigor@sysoev.ru 150141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 151141Smax.romanov@nginx.com const char* fmt, ...); 152141Smax.romanov@nginx.com 153119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 15420Sigor@sysoev.ru 155*216Sigor@sysoev.ru 156*216Sigor@sysoev.ru static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = { 157*216Sigor@sysoev.ru nxt_python_prepare_msg, 158*216Sigor@sysoev.ru nxt_php_prepare_msg, 159*216Sigor@sysoev.ru nxt_go_prepare_msg, 160*216Sigor@sysoev.ru }; 161*216Sigor@sysoev.ru 162*216Sigor@sysoev.ru 16320Sigor@sysoev.ru nxt_int_t 164141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 16520Sigor@sysoev.ru { 166141Smax.romanov@nginx.com nxt_int_t ret; 167141Smax.romanov@nginx.com nxt_router_t *router; 168141Smax.romanov@nginx.com nxt_runtime_t *rt; 169141Smax.romanov@nginx.com 170141Smax.romanov@nginx.com rt = task->thread->runtime; 17153Sigor@sysoev.ru 17288Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 17388Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 17488Smax.romanov@nginx.com return ret; 17588Smax.romanov@nginx.com } 17688Smax.romanov@nginx.com 17753Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 17853Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 17953Sigor@sysoev.ru return NXT_ERROR; 18053Sigor@sysoev.ru } 18153Sigor@sysoev.ru 18253Sigor@sysoev.ru nxt_queue_init(&router->engines); 18353Sigor@sysoev.ru nxt_queue_init(&router->sockets); 184133Sigor@sysoev.ru nxt_queue_init(&router->apps); 18553Sigor@sysoev.ru 186119Smax.romanov@nginx.com nxt_router = router; 187119Smax.romanov@nginx.com 188115Sigor@sysoev.ru return NXT_OK; 189115Sigor@sysoev.ru } 190115Sigor@sysoev.ru 191115Sigor@sysoev.ru 192167Smax.romanov@nginx.com static nxt_start_worker_t * 193192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra) 194167Smax.romanov@nginx.com { 195167Smax.romanov@nginx.com nxt_port_t *master_port; 196167Smax.romanov@nginx.com nxt_runtime_t *rt; 197167Smax.romanov@nginx.com nxt_start_worker_t *sw; 198167Smax.romanov@nginx.com 199192Smax.romanov@nginx.com sw = nxt_zalloc(sizeof(nxt_start_worker_t)); 200167Smax.romanov@nginx.com 201167Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 202167Smax.romanov@nginx.com return NULL; 203167Smax.romanov@nginx.com } 204167Smax.romanov@nginx.com 205167Smax.romanov@nginx.com sw->app = app; 206167Smax.romanov@nginx.com sw->ra = ra; 207167Smax.romanov@nginx.com 208192Smax.romanov@nginx.com nxt_debug(task, "sw %p create, request #%uxD, app '%V' %p", sw, 209167Smax.romanov@nginx.com ra->req_id, &app->name, app); 210167Smax.romanov@nginx.com 211167Smax.romanov@nginx.com rt = task->thread->runtime; 212167Smax.romanov@nginx.com master_port = rt->port_by_type[NXT_PROCESS_MASTER]; 213167Smax.romanov@nginx.com 214167Smax.romanov@nginx.com sw->work.handler = nxt_router_send_sw_request; 215167Smax.romanov@nginx.com sw->work.task = &master_port->engine->task; 216167Smax.romanov@nginx.com sw->work.obj = sw; 217167Smax.romanov@nginx.com sw->work.data = task->thread->engine; 218167Smax.romanov@nginx.com sw->work.next = NULL; 219167Smax.romanov@nginx.com 220167Smax.romanov@nginx.com if (task->thread->engine != master_port->engine) { 221192Smax.romanov@nginx.com nxt_debug(task, "sw %p post send to master engine %p", sw, 222167Smax.romanov@nginx.com master_port->engine); 223167Smax.romanov@nginx.com 224167Smax.romanov@nginx.com nxt_event_engine_post(master_port->engine, &sw->work); 225167Smax.romanov@nginx.com 226167Smax.romanov@nginx.com } else { 227167Smax.romanov@nginx.com nxt_router_send_sw_request(task, sw, sw->work.data); 228167Smax.romanov@nginx.com } 229167Smax.romanov@nginx.com 230167Smax.romanov@nginx.com return sw; 231167Smax.romanov@nginx.com } 232167Smax.romanov@nginx.com 233167Smax.romanov@nginx.com 234192Smax.romanov@nginx.com nxt_inline void 235192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw) 236141Smax.romanov@nginx.com { 237192Smax.romanov@nginx.com nxt_debug(task, "sw %p release", sw); 238192Smax.romanov@nginx.com 239192Smax.romanov@nginx.com nxt_free(sw); 240141Smax.romanov@nginx.com } 241141Smax.romanov@nginx.com 242141Smax.romanov@nginx.com 243167Smax.romanov@nginx.com static nxt_req_app_link_t * 244167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc) 245167Smax.romanov@nginx.com { 246167Smax.romanov@nginx.com nxt_mp_t *mp; 247167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 248167Smax.romanov@nginx.com 249167Smax.romanov@nginx.com mp = rc->conn->mem_pool; 250167Smax.romanov@nginx.com 251167Smax.romanov@nginx.com ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t)); 252167Smax.romanov@nginx.com 253167Smax.romanov@nginx.com if (nxt_slow_path(ra == NULL)) { 254167Smax.romanov@nginx.com return NULL; 255167Smax.romanov@nginx.com } 256167Smax.romanov@nginx.com 257167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD create", ra->req_id); 258167Smax.romanov@nginx.com 259167Smax.romanov@nginx.com nxt_memzero(ra, sizeof(nxt_req_app_link_t)); 260167Smax.romanov@nginx.com 261167Smax.romanov@nginx.com ra->req_id = rc->req_id; 262167Smax.romanov@nginx.com ra->app_port = NULL; 263167Smax.romanov@nginx.com ra->rc = rc; 264167Smax.romanov@nginx.com 265167Smax.romanov@nginx.com ra->mem_pool = mp; 266167Smax.romanov@nginx.com 267167Smax.romanov@nginx.com ra->work.handler = NULL; 268167Smax.romanov@nginx.com ra->work.task = &task->thread->engine->task; 269167Smax.romanov@nginx.com ra->work.obj = ra; 270167Smax.romanov@nginx.com ra->work.data = task->thread->engine; 271167Smax.romanov@nginx.com 272167Smax.romanov@nginx.com return ra; 273167Smax.romanov@nginx.com } 274167Smax.romanov@nginx.com 275167Smax.romanov@nginx.com 276167Smax.romanov@nginx.com static void 277167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data) 278167Smax.romanov@nginx.com { 279167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 280167Smax.romanov@nginx.com nxt_event_engine_t *engine; 281167Smax.romanov@nginx.com 282167Smax.romanov@nginx.com ra = obj; 283167Smax.romanov@nginx.com engine = data; 284167Smax.romanov@nginx.com 285167Smax.romanov@nginx.com if (task->thread->engine != engine) { 286167Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_release; 287167Smax.romanov@nginx.com ra->work.task = &engine->task; 288167Smax.romanov@nginx.com ra->work.next = NULL; 289167Smax.romanov@nginx.com 290167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD post release to %p", ra->req_id, engine); 291167Smax.romanov@nginx.com 292167Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 293167Smax.romanov@nginx.com 294167Smax.romanov@nginx.com return; 295167Smax.romanov@nginx.com } 296167Smax.romanov@nginx.com 297167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD release", ra->req_id); 298167Smax.romanov@nginx.com 299167Smax.romanov@nginx.com if (ra->app_port != NULL) { 300167Smax.romanov@nginx.com 301167Smax.romanov@nginx.com if (ra->rc->conn != NULL) { 302167Smax.romanov@nginx.com ra->rc->app_port = ra->app_port; 303167Smax.romanov@nginx.com 304167Smax.romanov@nginx.com } else { 305167Smax.romanov@nginx.com nxt_router_app_release_port(task, ra->app_port, ra->app_port->app); 306167Smax.romanov@nginx.com } 307167Smax.romanov@nginx.com } 308167Smax.romanov@nginx.com 309167Smax.romanov@nginx.com nxt_mp_release(ra->mem_pool, ra); 310167Smax.romanov@nginx.com } 311167Smax.romanov@nginx.com 312167Smax.romanov@nginx.com 313141Smax.romanov@nginx.com void 314141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 315141Smax.romanov@nginx.com { 316141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 317141Smax.romanov@nginx.com 318192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 319141Smax.romanov@nginx.com return; 320141Smax.romanov@nginx.com } 321141Smax.romanov@nginx.com 322192Smax.romanov@nginx.com if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) { 323192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 324141Smax.romanov@nginx.com } 325192Smax.romanov@nginx.com 326192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 327141Smax.romanov@nginx.com } 328141Smax.romanov@nginx.com 329141Smax.romanov@nginx.com 330139Sigor@sysoev.ru void 331139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 332115Sigor@sysoev.ru { 333139Sigor@sysoev.ru size_t dump_size; 334198Sigor@sysoev.ru nxt_int_t ret; 335139Sigor@sysoev.ru nxt_buf_t *b; 336139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 337139Sigor@sysoev.ru 338139Sigor@sysoev.ru b = msg->buf; 339139Sigor@sysoev.ru 340139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 341139Sigor@sysoev.ru 342139Sigor@sysoev.ru if (dump_size > 300) { 343139Sigor@sysoev.ru dump_size = 300; 34453Sigor@sysoev.ru } 34553Sigor@sysoev.ru 346139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 347139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 348139Sigor@sysoev.ru 349139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 350139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 351139Sigor@sysoev.ru return; 35253Sigor@sysoev.ru } 35353Sigor@sysoev.ru 354139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 355139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 356139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 357198Sigor@sysoev.ru msg->port_msg.pid, 358198Sigor@sysoev.ru msg->port_msg.reply_port); 359198Sigor@sysoev.ru 360198Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free); 361198Sigor@sysoev.ru 362198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) { 363198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL); 364198Sigor@sysoev.ru 365198Sigor@sysoev.ru } else { 366198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 367139Sigor@sysoev.ru } 36853Sigor@sysoev.ru } 36953Sigor@sysoev.ru 37053Sigor@sysoev.ru 371192Smax.romanov@nginx.com void 372192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 373192Smax.romanov@nginx.com { 374192Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, msg); 375192Smax.romanov@nginx.com 376192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 377192Smax.romanov@nginx.com return; 378192Smax.romanov@nginx.com } 379192Smax.romanov@nginx.com 380192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 381192Smax.romanov@nginx.com 382192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 383192Smax.romanov@nginx.com } 384192Smax.romanov@nginx.com 385192Smax.romanov@nginx.com 38653Sigor@sysoev.ru static nxt_router_temp_conf_t * 387139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 38853Sigor@sysoev.ru { 38965Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 39053Sigor@sysoev.ru nxt_router_conf_t *rtcf; 39153Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 39253Sigor@sysoev.ru 39365Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 39453Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 39553Sigor@sysoev.ru return NULL; 39653Sigor@sysoev.ru } 39753Sigor@sysoev.ru 39865Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 39953Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 40053Sigor@sysoev.ru goto fail; 40153Sigor@sysoev.ru } 40253Sigor@sysoev.ru 40353Sigor@sysoev.ru rtcf->mem_pool = mp; 40453Sigor@sysoev.ru 40565Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 40653Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 40753Sigor@sysoev.ru goto fail; 40853Sigor@sysoev.ru } 40953Sigor@sysoev.ru 41065Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 41153Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 41253Sigor@sysoev.ru goto temp_fail; 41353Sigor@sysoev.ru } 41453Sigor@sysoev.ru 41553Sigor@sysoev.ru tmcf->mem_pool = tmp; 41653Sigor@sysoev.ru tmcf->conf = rtcf; 417139Sigor@sysoev.ru tmcf->count = 1; 418139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 41953Sigor@sysoev.ru 42053Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 42153Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 42253Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 42353Sigor@sysoev.ru goto temp_fail; 42453Sigor@sysoev.ru } 42553Sigor@sysoev.ru 42653Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 42753Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 42853Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 42953Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 43053Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 431133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 432133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 43353Sigor@sysoev.ru 43453Sigor@sysoev.ru return tmcf; 43553Sigor@sysoev.ru 43653Sigor@sysoev.ru temp_fail: 43753Sigor@sysoev.ru 43865Sigor@sysoev.ru nxt_mp_destroy(tmp); 43953Sigor@sysoev.ru 44053Sigor@sysoev.ru fail: 44153Sigor@sysoev.ru 44265Sigor@sysoev.ru nxt_mp_destroy(mp); 44353Sigor@sysoev.ru 44453Sigor@sysoev.ru return NULL; 44553Sigor@sysoev.ru } 44653Sigor@sysoev.ru 44753Sigor@sysoev.ru 448198Sigor@sysoev.ru static void 449198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) 450139Sigor@sysoev.ru { 451139Sigor@sysoev.ru nxt_int_t ret; 452139Sigor@sysoev.ru nxt_router_t *router; 453139Sigor@sysoev.ru nxt_runtime_t *rt; 454198Sigor@sysoev.ru nxt_queue_link_t *qlk; 455198Sigor@sysoev.ru nxt_socket_conf_t *skcf; 456198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 457139Sigor@sysoev.ru const nxt_event_interface_t *interface; 458139Sigor@sysoev.ru 459198Sigor@sysoev.ru tmcf = obj; 460198Sigor@sysoev.ru 461198Sigor@sysoev.ru qlk = nxt_queue_first(&tmcf->pending); 462198Sigor@sysoev.ru 463198Sigor@sysoev.ru if (qlk != nxt_queue_tail(&tmcf->pending)) { 464198Sigor@sysoev.ru nxt_queue_remove(qlk); 465198Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 466198Sigor@sysoev.ru 467198Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 468198Sigor@sysoev.ru 469198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(task, tmcf, skcf); 470198Sigor@sysoev.ru 471198Sigor@sysoev.ru return; 472139Sigor@sysoev.ru } 473139Sigor@sysoev.ru 474139Sigor@sysoev.ru rt = task->thread->runtime; 475139Sigor@sysoev.ru 476139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 477139Sigor@sysoev.ru 478198Sigor@sysoev.ru router = tmcf->conf->router; 479198Sigor@sysoev.ru 480139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 481139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 482198Sigor@sysoev.ru goto fail; 483139Sigor@sysoev.ru } 484139Sigor@sysoev.ru 485139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 486139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 487198Sigor@sysoev.ru goto fail; 488139Sigor@sysoev.ru } 489139Sigor@sysoev.ru 490139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 491139Sigor@sysoev.ru 492139Sigor@sysoev.ru nxt_router_engines_post(tmcf); 493139Sigor@sysoev.ru 494139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 495139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 496139Sigor@sysoev.ru 497198Sigor@sysoev.ru nxt_router_conf_ready(task, tmcf); 498198Sigor@sysoev.ru 499198Sigor@sysoev.ru return; 500198Sigor@sysoev.ru 501198Sigor@sysoev.ru fail: 502198Sigor@sysoev.ru 503198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 504198Sigor@sysoev.ru 505198Sigor@sysoev.ru return; 506139Sigor@sysoev.ru } 507139Sigor@sysoev.ru 508139Sigor@sysoev.ru 509139Sigor@sysoev.ru static void 510139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 511139Sigor@sysoev.ru { 512153Sigor@sysoev.ru nxt_joint_job_t *job; 513153Sigor@sysoev.ru 514153Sigor@sysoev.ru job = obj; 515153Sigor@sysoev.ru 516198Sigor@sysoev.ru nxt_router_conf_ready(task, job->tmcf); 517139Sigor@sysoev.ru } 518139Sigor@sysoev.ru 519139Sigor@sysoev.ru 520139Sigor@sysoev.ru static void 521198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 522139Sigor@sysoev.ru { 523139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 524139Sigor@sysoev.ru 525139Sigor@sysoev.ru if (--tmcf->count == 0) { 526193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); 527139Sigor@sysoev.ru } 528139Sigor@sysoev.ru } 529139Sigor@sysoev.ru 530139Sigor@sysoev.ru 531139Sigor@sysoev.ru static void 532139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 533139Sigor@sysoev.ru { 534148Sigor@sysoev.ru nxt_socket_t s; 535149Sigor@sysoev.ru nxt_router_t *router; 536148Sigor@sysoev.ru nxt_queue_link_t *qlk; 537148Sigor@sysoev.ru nxt_socket_conf_t *skcf; 538148Sigor@sysoev.ru 539198Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 540198Sigor@sysoev.ru 541148Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->creating); 542148Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->creating); 543148Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 544148Sigor@sysoev.ru { 545148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 546148Sigor@sysoev.ru s = skcf->listen.socket; 547148Sigor@sysoev.ru 548148Sigor@sysoev.ru if (s != -1) { 549148Sigor@sysoev.ru nxt_socket_close(task, s); 550148Sigor@sysoev.ru } 551148Sigor@sysoev.ru 552148Sigor@sysoev.ru nxt_free(skcf->socket); 553148Sigor@sysoev.ru } 554148Sigor@sysoev.ru 555149Sigor@sysoev.ru router = tmcf->conf->router; 556149Sigor@sysoev.ru 557149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->keeping); 558149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->deleting); 559149Sigor@sysoev.ru 560148Sigor@sysoev.ru // TODO: new engines and threads 561148Sigor@sysoev.ru 562139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 563139Sigor@sysoev.ru 564193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); 565139Sigor@sysoev.ru } 566139Sigor@sysoev.ru 567139Sigor@sysoev.ru 568139Sigor@sysoev.ru static void 569139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 570193Smax.romanov@nginx.com nxt_port_msg_type_t type) 571139Sigor@sysoev.ru { 572193Smax.romanov@nginx.com nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); 573139Sigor@sysoev.ru } 574139Sigor@sysoev.ru 575139Sigor@sysoev.ru 576115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 577115Sigor@sysoev.ru { 578133Sigor@sysoev.ru nxt_string("listeners_threads"), 579115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 580115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 581115Sigor@sysoev.ru }, 582115Sigor@sysoev.ru }; 583115Sigor@sysoev.ru 584115Sigor@sysoev.ru 585133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 586115Sigor@sysoev.ru { 587133Sigor@sysoev.ru nxt_string("type"), 588115Sigor@sysoev.ru NXT_CONF_MAP_STR, 589133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 590115Sigor@sysoev.ru }, 591115Sigor@sysoev.ru 592115Sigor@sysoev.ru { 593133Sigor@sysoev.ru nxt_string("workers"), 594115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 595133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 596133Sigor@sysoev.ru }, 597133Sigor@sysoev.ru }; 598133Sigor@sysoev.ru 599133Sigor@sysoev.ru 600133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 601133Sigor@sysoev.ru { 602133Sigor@sysoev.ru nxt_string("application"), 603133Sigor@sysoev.ru NXT_CONF_MAP_STR, 604133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 605115Sigor@sysoev.ru }, 606115Sigor@sysoev.ru }; 607115Sigor@sysoev.ru 608115Sigor@sysoev.ru 609115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 610115Sigor@sysoev.ru { 611115Sigor@sysoev.ru nxt_string("header_buffer_size"), 612115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 613115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 614115Sigor@sysoev.ru }, 615115Sigor@sysoev.ru 616115Sigor@sysoev.ru { 617115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 618115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 619115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 620115Sigor@sysoev.ru }, 621115Sigor@sysoev.ru 622115Sigor@sysoev.ru { 623206Smax.romanov@nginx.com nxt_string("large_header_buffers"), 624206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 625206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, large_header_buffers), 626206Smax.romanov@nginx.com }, 627206Smax.romanov@nginx.com 628206Smax.romanov@nginx.com { 629206Smax.romanov@nginx.com nxt_string("body_buffer_size"), 630206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 631206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_buffer_size), 632206Smax.romanov@nginx.com }, 633206Smax.romanov@nginx.com 634206Smax.romanov@nginx.com { 635206Smax.romanov@nginx.com nxt_string("max_body_size"), 636206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 637206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, max_body_size), 638206Smax.romanov@nginx.com }, 639206Smax.romanov@nginx.com 640206Smax.romanov@nginx.com { 641115Sigor@sysoev.ru nxt_string("header_read_timeout"), 642115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 643115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 644115Sigor@sysoev.ru }, 645206Smax.romanov@nginx.com 646206Smax.romanov@nginx.com { 647206Smax.romanov@nginx.com nxt_string("body_read_timeout"), 648206Smax.romanov@nginx.com NXT_CONF_MAP_MSEC, 649206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_read_timeout), 650206Smax.romanov@nginx.com }, 651115Sigor@sysoev.ru }; 652115Sigor@sysoev.ru 653115Sigor@sysoev.ru 65453Sigor@sysoev.ru static nxt_int_t 655115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 656115Sigor@sysoev.ru u_char *start, u_char *end) 65753Sigor@sysoev.ru { 658133Sigor@sysoev.ru u_char *p; 659133Sigor@sysoev.ru size_t size; 660115Sigor@sysoev.ru nxt_mp_t *mp; 661115Sigor@sysoev.ru uint32_t next; 662115Sigor@sysoev.ru nxt_int_t ret; 663115Sigor@sysoev.ru nxt_str_t name; 664133Sigor@sysoev.ru nxt_app_t *app, *prev; 665133Sigor@sysoev.ru nxt_app_type_t type; 666115Sigor@sysoev.ru nxt_sockaddr_t *sa; 667133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 668133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 669133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 670115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 671*216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 672133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 673115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 674115Sigor@sysoev.ru 675115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 676133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 677115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 678115Sigor@sysoev.ru 679208Svbart@nginx.com conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); 680115Sigor@sysoev.ru if (conf == NULL) { 681115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 682115Sigor@sysoev.ru return NXT_ERROR; 683115Sigor@sysoev.ru } 684115Sigor@sysoev.ru 685213Svbart@nginx.com mp = tmcf->conf->mem_pool; 686213Svbart@nginx.com 687213Svbart@nginx.com ret = nxt_conf_map_object(mp, conf, nxt_router_conf, 688136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 689115Sigor@sysoev.ru if (ret != NXT_OK) { 690133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 691115Sigor@sysoev.ru return NXT_ERROR; 692115Sigor@sysoev.ru } 693115Sigor@sysoev.ru 694117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 695117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 696117Sigor@sysoev.ru } 697117Sigor@sysoev.ru 698133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 699133Sigor@sysoev.ru if (applications == NULL) { 700133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 701115Sigor@sysoev.ru return NXT_ERROR; 702115Sigor@sysoev.ru } 703115Sigor@sysoev.ru 704133Sigor@sysoev.ru next = 0; 705133Sigor@sysoev.ru 706133Sigor@sysoev.ru for ( ;; ) { 707133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 708133Sigor@sysoev.ru if (application == NULL) { 709133Sigor@sysoev.ru break; 710133Sigor@sysoev.ru } 711133Sigor@sysoev.ru 712133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 713133Sigor@sysoev.ru 714144Smax.romanov@nginx.com size = nxt_conf_json_length(application, NULL); 715144Smax.romanov@nginx.com 716144Smax.romanov@nginx.com app = nxt_malloc(sizeof(nxt_app_t) + name.length + size); 717133Sigor@sysoev.ru if (app == NULL) { 718133Sigor@sysoev.ru goto fail; 719133Sigor@sysoev.ru } 720133Sigor@sysoev.ru 721144Smax.romanov@nginx.com nxt_memzero(app, sizeof(nxt_app_t)); 722144Smax.romanov@nginx.com 723144Smax.romanov@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 724144Smax.romanov@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); 725133Sigor@sysoev.ru 726133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 727133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 728133Sigor@sysoev.ru 729144Smax.romanov@nginx.com nxt_assert(app->conf.length <= size); 730144Smax.romanov@nginx.com 731133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 732133Sigor@sysoev.ru 733133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 734133Sigor@sysoev.ru 735133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 736133Sigor@sysoev.ru nxt_free(app); 737133Sigor@sysoev.ru 738133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 739133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 740133Sigor@sysoev.ru continue; 741133Sigor@sysoev.ru } 742133Sigor@sysoev.ru 743213Svbart@nginx.com ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, 744136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 745133Sigor@sysoev.ru if (ret != NXT_OK) { 746133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 747133Sigor@sysoev.ru goto app_fail; 748133Sigor@sysoev.ru } 749115Sigor@sysoev.ru 750133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 751133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 752133Sigor@sysoev.ru 753*216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); 754*216Sigor@sysoev.ru 755*216Sigor@sysoev.ru if (lang == NULL) { 756141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 757141Smax.romanov@nginx.com &apcf.type); 758141Smax.romanov@nginx.com goto app_fail; 759141Smax.romanov@nginx.com } 760141Smax.romanov@nginx.com 761*216Sigor@sysoev.ru nxt_debug(task, "application language module: \"%s\"", lang->file); 762*216Sigor@sysoev.ru 763*216Sigor@sysoev.ru type = nxt_app_parse_type(&lang->type); 764*216Sigor@sysoev.ru 765*216Sigor@sysoev.ru if (type == NXT_APP_UNKNOWN) { 766*216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 767*216Sigor@sysoev.ru &lang->type); 768*216Sigor@sysoev.ru goto app_fail; 769*216Sigor@sysoev.ru } 770*216Sigor@sysoev.ru 771*216Sigor@sysoev.ru if (nxt_app_prepare_msg[type] == NULL) { 772133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 773*216Sigor@sysoev.ru &lang->type); 774133Sigor@sysoev.ru goto app_fail; 775133Sigor@sysoev.ru } 776133Sigor@sysoev.ru 777133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 778133Sigor@sysoev.ru if (ret != NXT_OK) { 779133Sigor@sysoev.ru goto app_fail; 780133Sigor@sysoev.ru } 781133Sigor@sysoev.ru 782141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 783141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 784141Smax.romanov@nginx.com 785144Smax.romanov@nginx.com app->name.length = name.length; 786144Smax.romanov@nginx.com nxt_memcpy(app->name.start, name.start, name.length); 787144Smax.romanov@nginx.com 788133Sigor@sysoev.ru app->type = type; 789133Sigor@sysoev.ru app->max_workers = apcf.workers; 790133Sigor@sysoev.ru app->live = 1; 791*216Sigor@sysoev.ru app->prepare_msg = nxt_app_prepare_msg[type]; 792133Sigor@sysoev.ru 793133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 794133Sigor@sysoev.ru } 795133Sigor@sysoev.ru 796133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 797133Sigor@sysoev.ru #if 0 798133Sigor@sysoev.ru if (http == NULL) { 799133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 800133Sigor@sysoev.ru return NXT_ERROR; 801133Sigor@sysoev.ru } 802133Sigor@sysoev.ru #endif 803133Sigor@sysoev.ru 804133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 805115Sigor@sysoev.ru if (listeners == NULL) { 806133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 807115Sigor@sysoev.ru return NXT_ERROR; 808115Sigor@sysoev.ru } 80953Sigor@sysoev.ru 810133Sigor@sysoev.ru next = 0; 81153Sigor@sysoev.ru 812115Sigor@sysoev.ru for ( ;; ) { 813115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 814115Sigor@sysoev.ru if (listener == NULL) { 815115Sigor@sysoev.ru break; 816115Sigor@sysoev.ru } 81753Sigor@sysoev.ru 818115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 819115Sigor@sysoev.ru if (sa == NULL) { 820115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 821133Sigor@sysoev.ru goto fail; 822115Sigor@sysoev.ru } 823115Sigor@sysoev.ru 824115Sigor@sysoev.ru sa->type = SOCK_STREAM; 825115Sigor@sysoev.ru 826115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 827115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 82853Sigor@sysoev.ru 829115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 830115Sigor@sysoev.ru if (skcf == NULL) { 831133Sigor@sysoev.ru goto fail; 832115Sigor@sysoev.ru } 83353Sigor@sysoev.ru 834213Svbart@nginx.com ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, 835136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 836115Sigor@sysoev.ru if (ret != NXT_OK) { 837115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 838133Sigor@sysoev.ru goto fail; 839115Sigor@sysoev.ru } 84053Sigor@sysoev.ru 841133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 842133Sigor@sysoev.ru 843133Sigor@sysoev.ru // STUB, default values if http block is not defined. 844133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 845133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 846206Smax.romanov@nginx.com skcf->large_header_buffers = 4; 847206Smax.romanov@nginx.com skcf->body_buffer_size = 16 * 1024; 848206Smax.romanov@nginx.com skcf->max_body_size = 2 * 1024 * 1024; 849133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 850206Smax.romanov@nginx.com skcf->body_read_timeout = 5000; 85153Sigor@sysoev.ru 852133Sigor@sysoev.ru if (http != NULL) { 853213Svbart@nginx.com ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, 854136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 855133Sigor@sysoev.ru if (ret != NXT_OK) { 856133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 857133Sigor@sysoev.ru goto fail; 858133Sigor@sysoev.ru } 859115Sigor@sysoev.ru } 860115Sigor@sysoev.ru 861115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 862115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 863160Sigor@sysoev.ru skcf->router_conf->count++; 864133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 865133Sigor@sysoev.ru &lscf.application); 866115Sigor@sysoev.ru 867115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 868115Sigor@sysoev.ru } 86953Sigor@sysoev.ru 870198Sigor@sysoev.ru nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf); 871198Sigor@sysoev.ru 87253Sigor@sysoev.ru return NXT_OK; 873133Sigor@sysoev.ru 874133Sigor@sysoev.ru app_fail: 875133Sigor@sysoev.ru 876133Sigor@sysoev.ru nxt_free(app); 877133Sigor@sysoev.ru 878133Sigor@sysoev.ru fail: 879133Sigor@sysoev.ru 880141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 881141Smax.romanov@nginx.com 882141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 883133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 884133Sigor@sysoev.ru nxt_free(app); 885141Smax.romanov@nginx.com 886141Smax.romanov@nginx.com } nxt_queue_loop; 887133Sigor@sysoev.ru 888133Sigor@sysoev.ru return NXT_ERROR; 889133Sigor@sysoev.ru } 890133Sigor@sysoev.ru 891133Sigor@sysoev.ru 892133Sigor@sysoev.ru static nxt_app_t * 893133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 894133Sigor@sysoev.ru { 895141Smax.romanov@nginx.com nxt_app_t *app; 896141Smax.romanov@nginx.com 897141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 898133Sigor@sysoev.ru 899133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 900133Sigor@sysoev.ru return app; 901133Sigor@sysoev.ru } 902141Smax.romanov@nginx.com 903141Smax.romanov@nginx.com } nxt_queue_loop; 904133Sigor@sysoev.ru 905133Sigor@sysoev.ru return NULL; 906133Sigor@sysoev.ru } 907133Sigor@sysoev.ru 908133Sigor@sysoev.ru 909133Sigor@sysoev.ru static nxt_app_t * 910133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 911133Sigor@sysoev.ru { 912133Sigor@sysoev.ru nxt_app_t *app; 913133Sigor@sysoev.ru 914133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 915133Sigor@sysoev.ru 916133Sigor@sysoev.ru if (app == NULL) { 917134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 918133Sigor@sysoev.ru } 919133Sigor@sysoev.ru 920133Sigor@sysoev.ru return app; 92153Sigor@sysoev.ru } 92253Sigor@sysoev.ru 92353Sigor@sysoev.ru 92453Sigor@sysoev.ru static nxt_socket_conf_t * 92565Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 92653Sigor@sysoev.ru { 927163Smax.romanov@nginx.com nxt_socket_conf_t *skcf; 928163Smax.romanov@nginx.com 929163Smax.romanov@nginx.com skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 930163Smax.romanov@nginx.com if (nxt_slow_path(skcf == NULL)) { 93153Sigor@sysoev.ru return NULL; 93253Sigor@sysoev.ru } 93353Sigor@sysoev.ru 934163Smax.romanov@nginx.com skcf->sockaddr = sa; 935163Smax.romanov@nginx.com 936163Smax.romanov@nginx.com skcf->listen.sockaddr = sa; 937163Smax.romanov@nginx.com skcf->listen.socklen = sa->socklen; 938163Smax.romanov@nginx.com skcf->listen.address_length = sa->length; 939163Smax.romanov@nginx.com 940163Smax.romanov@nginx.com skcf->listen.socket = -1; 941