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 23141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t; 24141Smax.romanov@nginx.com 25141Smax.romanov@nginx.com struct nxt_start_worker_s { 26141Smax.romanov@nginx.com uint32_t stream; 27141Smax.romanov@nginx.com nxt_app_t *app; 28141Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 29141Smax.romanov@nginx.com nxt_mp_t *mem_pool; 30141Smax.romanov@nginx.com void *joint; 31141Smax.romanov@nginx.com 32141Smax.romanov@nginx.com nxt_work_t work; 33141Smax.romanov@nginx.com }; 34141Smax.romanov@nginx.com 35141Smax.romanov@nginx.com 36139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 37139Sigor@sysoev.ru static nxt_int_t nxt_router_conf_new(nxt_task_t *task, 38139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 39139Sigor@sysoev.ru static void nxt_router_conf_success(nxt_task_t *task, 40139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 41139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 42139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 43139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 44139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, size_t size); 45139Sigor@sysoev.ru static void nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, 46139Sigor@sysoev.ru void *data); 4753Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 4853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 4953Sigor@sysoev.ru 50115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 51115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 52133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 53133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 54133Sigor@sysoev.ru nxt_str_t *name); 5553Sigor@sysoev.ru static nxt_int_t nxt_router_listen_sockets_stub_create(nxt_task_t *task, 5653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 5765Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 5865Sigor@sysoev.ru nxt_sockaddr_t *sa); 5953Sigor@sysoev.ru 6053Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 6153Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 6253Sigor@sysoev.ru const nxt_event_interface_t *interface); 63115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 64115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 65115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 66115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 67115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 68115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 69115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 70115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_mp_t *mp, 71139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_router_engine_conf_t *recf, 72139Sigor@sysoev.ru nxt_queue_t *sockets, nxt_array_t *array, nxt_work_handler_t handler); 73139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 74139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 7553Sigor@sysoev.ru 7653Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 7753Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 7853Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 7953Sigor@sysoev.ru nxt_event_engine_t *engine); 80133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 81133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 8253Sigor@sysoev.ru 8353Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 84139Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_temp_conf_t *tmcf, 85139Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 8653Sigor@sysoev.ru 8753Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 8853Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 8953Sigor@sysoev.ru void *data); 9053Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 9153Sigor@sysoev.ru void *data); 9253Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 9353Sigor@sysoev.ru void *data); 9453Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 9553Sigor@sysoev.ru void *data); 9653Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 9753Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 9853Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 9953Sigor@sysoev.ru void *data); 10053Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 10153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 10253Sigor@sysoev.ru 103141Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app); 104141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj, 105141Smax.romanov@nginx.com void *data); 106141Smax.romanov@nginx.com 107141Smax.romanov@nginx.com static void nxt_router_sw_add(nxt_task_t *task, nxt_router_t *router, 108141Smax.romanov@nginx.com nxt_start_worker_t *sw); 109141Smax.romanov@nginx.com static nxt_start_worker_t *nxt_router_sw_find_remove(nxt_task_t *task, 110141Smax.romanov@nginx.com nxt_router_t *router, uint32_t id); 111141Smax.romanov@nginx.com 11253Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 11353Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 11453Sigor@sysoev.ru void *data); 11588Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 11688Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 117141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task, 118141Smax.romanov@nginx.com nxt_req_conn_link_t *rc, nxt_mp_t *mp); 11988Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 12053Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 12153Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 12253Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 12353Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 12462Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 12520Sigor@sysoev.ru 126141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 127141Smax.romanov@nginx.com const char* fmt, ...); 128141Smax.romanov@nginx.com 129119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 13020Sigor@sysoev.ru 13120Sigor@sysoev.ru nxt_int_t 132141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 13320Sigor@sysoev.ru { 134141Smax.romanov@nginx.com nxt_int_t ret; 135141Smax.romanov@nginx.com nxt_router_t *router; 136141Smax.romanov@nginx.com nxt_runtime_t *rt; 137141Smax.romanov@nginx.com 138141Smax.romanov@nginx.com rt = task->thread->runtime; 13953Sigor@sysoev.ru 14088Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 14188Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14288Smax.romanov@nginx.com return ret; 14388Smax.romanov@nginx.com } 14488Smax.romanov@nginx.com 14553Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 14653Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 14753Sigor@sysoev.ru return NXT_ERROR; 14853Sigor@sysoev.ru } 14953Sigor@sysoev.ru 15053Sigor@sysoev.ru nxt_queue_init(&router->engines); 15153Sigor@sysoev.ru nxt_queue_init(&router->sockets); 152133Sigor@sysoev.ru nxt_queue_init(&router->apps); 15353Sigor@sysoev.ru 154119Smax.romanov@nginx.com nxt_router = router; 155119Smax.romanov@nginx.com 156115Sigor@sysoev.ru return NXT_OK; 157115Sigor@sysoev.ru } 158115Sigor@sysoev.ru 159115Sigor@sysoev.ru 160141Smax.romanov@nginx.com static void 161141Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, void *obj, void *data) 162141Smax.romanov@nginx.com { 163141Smax.romanov@nginx.com nxt_start_worker_t *sw; 164141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 165141Smax.romanov@nginx.com 166141Smax.romanov@nginx.com sw = obj; 167141Smax.romanov@nginx.com joint = sw->joint; 168141Smax.romanov@nginx.com 169141Smax.romanov@nginx.com nxt_debug(task, "sw #%uxD release", sw->stream); 170141Smax.romanov@nginx.com 171141Smax.romanov@nginx.com if (nxt_mp_release(sw->mem_pool, sw) == 0) { 172141Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 173141Smax.romanov@nginx.com } 174141Smax.romanov@nginx.com } 175141Smax.romanov@nginx.com 176141Smax.romanov@nginx.com 177141Smax.romanov@nginx.com void 178141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 179141Smax.romanov@nginx.com { 180141Smax.romanov@nginx.com nxt_start_worker_t *sw; 181141Smax.romanov@nginx.com 182141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 183141Smax.romanov@nginx.com 184141Smax.romanov@nginx.com if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) { 185141Smax.romanov@nginx.com return; 186141Smax.romanov@nginx.com } 187141Smax.romanov@nginx.com 188141Smax.romanov@nginx.com sw = nxt_router_sw_find_remove(task, nxt_router, msg->port_msg.stream); 189141Smax.romanov@nginx.com 190141Smax.romanov@nginx.com if (nxt_fast_path(sw != NULL)) { 191141Smax.romanov@nginx.com msg->new_port->app = sw->app; 192141Smax.romanov@nginx.com 193141Smax.romanov@nginx.com nxt_router_app_release_port(task, msg->new_port, sw->app); 194141Smax.romanov@nginx.com 195141Smax.romanov@nginx.com sw->work.handler = nxt_router_sw_release; 196141Smax.romanov@nginx.com 197141Smax.romanov@nginx.com nxt_debug(task, "post sw #%uxD release to %p", sw->stream, 198141Smax.romanov@nginx.com sw->work.data); 199141Smax.romanov@nginx.com 200141Smax.romanov@nginx.com nxt_event_engine_post(sw->work.data, &sw->work); 201141Smax.romanov@nginx.com } 202141Smax.romanov@nginx.com } 203141Smax.romanov@nginx.com 204141Smax.romanov@nginx.com 205139Sigor@sysoev.ru void 206139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 207115Sigor@sysoev.ru { 208139Sigor@sysoev.ru size_t dump_size; 209139Sigor@sysoev.ru nxt_buf_t *b; 210139Sigor@sysoev.ru nxt_int_t ret; 211139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 212139Sigor@sysoev.ru 213139Sigor@sysoev.ru b = msg->buf; 214139Sigor@sysoev.ru 215139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 216139Sigor@sysoev.ru 217139Sigor@sysoev.ru if (dump_size > 300) { 218139Sigor@sysoev.ru dump_size = 300; 21953Sigor@sysoev.ru } 22053Sigor@sysoev.ru 221139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 222139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 223139Sigor@sysoev.ru 224139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 225139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 226139Sigor@sysoev.ru return; 22753Sigor@sysoev.ru } 22853Sigor@sysoev.ru 229139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 230139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 231139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 232139Sigor@sysoev.ru msg->port_msg.pid, 0); 233139Sigor@sysoev.ru 234139Sigor@sysoev.ru ret = nxt_router_conf_new(task, tmcf, b->mem.pos, b->mem.free); 235139Sigor@sysoev.ru 236139Sigor@sysoev.ru b->mem.pos = b->mem.free; 237139Sigor@sysoev.ru 238139Sigor@sysoev.ru if (ret == NXT_OK) { 239139Sigor@sysoev.ru return nxt_router_conf_success(task, tmcf); 240139Sigor@sysoev.ru } 241139Sigor@sysoev.ru 242139Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 243139Sigor@sysoev.ru 244139Sigor@sysoev.ru return nxt_router_conf_error(task, tmcf); 24553Sigor@sysoev.ru } 24653Sigor@sysoev.ru 24753Sigor@sysoev.ru 24853Sigor@sysoev.ru static nxt_router_temp_conf_t * 249139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 25053Sigor@sysoev.ru { 25165Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 25253Sigor@sysoev.ru nxt_router_conf_t *rtcf; 25353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 25453Sigor@sysoev.ru 25565Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 25653Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 25753Sigor@sysoev.ru return NULL; 25853Sigor@sysoev.ru } 25953Sigor@sysoev.ru 26065Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 26153Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 26253Sigor@sysoev.ru goto fail; 26353Sigor@sysoev.ru } 26453Sigor@sysoev.ru 26553Sigor@sysoev.ru rtcf->mem_pool = mp; 26653Sigor@sysoev.ru rtcf->count = 1; 26753Sigor@sysoev.ru 26865Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 26953Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 27053Sigor@sysoev.ru goto fail; 27153Sigor@sysoev.ru } 27253Sigor@sysoev.ru 27365Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 27453Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 27553Sigor@sysoev.ru goto temp_fail; 27653Sigor@sysoev.ru } 27753Sigor@sysoev.ru 27853Sigor@sysoev.ru tmcf->mem_pool = tmp; 27953Sigor@sysoev.ru tmcf->conf = rtcf; 280139Sigor@sysoev.ru tmcf->count = 1; 281139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 28253Sigor@sysoev.ru 28353Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 28453Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 28553Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 28653Sigor@sysoev.ru goto temp_fail; 28753Sigor@sysoev.ru } 28853Sigor@sysoev.ru 28953Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 29053Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 29153Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 29253Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 29353Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 294133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 295133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 29653Sigor@sysoev.ru 29753Sigor@sysoev.ru return tmcf; 29853Sigor@sysoev.ru 29953Sigor@sysoev.ru temp_fail: 30053Sigor@sysoev.ru 30165Sigor@sysoev.ru nxt_mp_destroy(tmp); 30253Sigor@sysoev.ru 30353Sigor@sysoev.ru fail: 30453Sigor@sysoev.ru 30565Sigor@sysoev.ru nxt_mp_destroy(mp); 30653Sigor@sysoev.ru 30753Sigor@sysoev.ru return NULL; 30853Sigor@sysoev.ru } 30953Sigor@sysoev.ru 31053Sigor@sysoev.ru 311139Sigor@sysoev.ru static nxt_int_t 312139Sigor@sysoev.ru nxt_router_conf_new(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 313139Sigor@sysoev.ru u_char *start, u_char *end) 314139Sigor@sysoev.ru { 315139Sigor@sysoev.ru nxt_int_t ret; 316139Sigor@sysoev.ru nxt_router_t *router; 317139Sigor@sysoev.ru nxt_runtime_t *rt; 318139Sigor@sysoev.ru const nxt_event_interface_t *interface; 319139Sigor@sysoev.ru 320139Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, start, end); 321139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 322139Sigor@sysoev.ru return ret; 323139Sigor@sysoev.ru } 324139Sigor@sysoev.ru 325139Sigor@sysoev.ru router = tmcf->conf->router; 326139Sigor@sysoev.ru 327139Sigor@sysoev.ru nxt_router_listen_sockets_sort(router, tmcf); 328139Sigor@sysoev.ru 329139Sigor@sysoev.ru ret = nxt_router_listen_sockets_stub_create(task, tmcf); 330139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 331139Sigor@sysoev.ru return ret; 332139Sigor@sysoev.ru } 333139Sigor@sysoev.ru 334139Sigor@sysoev.ru rt = task->thread->runtime; 335139Sigor@sysoev.ru 336139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 337139Sigor@sysoev.ru 338139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 339139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 340139Sigor@sysoev.ru return ret; 341139Sigor@sysoev.ru } 342139Sigor@sysoev.ru 343139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 344139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 345139Sigor@sysoev.ru return ret; 346139Sigor@sysoev.ru } 347139Sigor@sysoev.ru 348139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 349139Sigor@sysoev.ru 350139Sigor@sysoev.ru nxt_router_engines_post(tmcf); 351139Sigor@sysoev.ru 352139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 353139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 354139Sigor@sysoev.ru 355139Sigor@sysoev.ru return NXT_OK; 356139Sigor@sysoev.ru } 357139Sigor@sysoev.ru 358139Sigor@sysoev.ru 359139Sigor@sysoev.ru static void 360139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 361139Sigor@sysoev.ru { 362139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 363139Sigor@sysoev.ru 364139Sigor@sysoev.ru tmcf = obj; 365139Sigor@sysoev.ru 366139Sigor@sysoev.ru nxt_router_conf_success(task, tmcf); 367139Sigor@sysoev.ru } 368139Sigor@sysoev.ru 369139Sigor@sysoev.ru 370139Sigor@sysoev.ru static void 371139Sigor@sysoev.ru nxt_router_conf_success(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 372139Sigor@sysoev.ru { 373139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 374139Sigor@sysoev.ru 375139Sigor@sysoev.ru if (--tmcf->count == 0) { 376139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "OK", 2); 377139Sigor@sysoev.ru } 378139Sigor@sysoev.ru } 379139Sigor@sysoev.ru 380139Sigor@sysoev.ru 381139Sigor@sysoev.ru static void 382139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 383139Sigor@sysoev.ru { 384*148Sigor@sysoev.ru nxt_socket_t s; 385*148Sigor@sysoev.ru nxt_queue_link_t *qlk; 386*148Sigor@sysoev.ru nxt_socket_conf_t *skcf; 387*148Sigor@sysoev.ru 388*148Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->creating); 389*148Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->creating); 390*148Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 391*148Sigor@sysoev.ru { 392*148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 393*148Sigor@sysoev.ru s = skcf->listen.socket; 394*148Sigor@sysoev.ru 395*148Sigor@sysoev.ru if (s != -1) { 396*148Sigor@sysoev.ru nxt_socket_close(task, s); 397*148Sigor@sysoev.ru } 398*148Sigor@sysoev.ru 399*148Sigor@sysoev.ru nxt_free(skcf->socket); 400*148Sigor@sysoev.ru } 401*148Sigor@sysoev.ru 402*148Sigor@sysoev.ru // TODO: new engines and threads 403*148Sigor@sysoev.ru 404139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 405139Sigor@sysoev.ru 406139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "ERROR", 5); 407139Sigor@sysoev.ru } 408139Sigor@sysoev.ru 409139Sigor@sysoev.ru 410139Sigor@sysoev.ru static void 411139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 412139Sigor@sysoev.ru u_char *start, size_t size) 413139Sigor@sysoev.ru { 414139Sigor@sysoev.ru nxt_buf_t *b; 415139Sigor@sysoev.ru 416139Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 417139Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 418139Sigor@sysoev.ru return; 419139Sigor@sysoev.ru } 420139Sigor@sysoev.ru 421140Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, start, size); 422140Svbart@nginx.com 423139Sigor@sysoev.ru b->parent = tmcf->mem_pool; 424139Sigor@sysoev.ru b->completion_handler = nxt_router_conf_buf_completion; 425139Sigor@sysoev.ru 426139Sigor@sysoev.ru nxt_port_socket_write(task, tmcf->port, NXT_PORT_MSG_DATA, -1, 427139Sigor@sysoev.ru tmcf->stream, 0, b); 428139Sigor@sysoev.ru } 429139Sigor@sysoev.ru 430139Sigor@sysoev.ru 431139Sigor@sysoev.ru static void 432139Sigor@sysoev.ru nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, void *data) 433139Sigor@sysoev.ru { 434139Sigor@sysoev.ru nxt_mp_t *mp; 435139Sigor@sysoev.ru 436139Sigor@sysoev.ru /* nxt_router_temp_conf_t mem pool. */ 437139Sigor@sysoev.ru mp = data; 438139Sigor@sysoev.ru 439139Sigor@sysoev.ru nxt_mp_destroy(mp); 440139Sigor@sysoev.ru } 441139Sigor@sysoev.ru 442139Sigor@sysoev.ru 443115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 444115Sigor@sysoev.ru { 445133Sigor@sysoev.ru nxt_string("listeners_threads"), 446115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 447115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 448115Sigor@sysoev.ru }, 449115Sigor@sysoev.ru }; 450115Sigor@sysoev.ru 451115Sigor@sysoev.ru 452133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 453115Sigor@sysoev.ru { 454133Sigor@sysoev.ru nxt_string("type"), 455115Sigor@sysoev.ru NXT_CONF_MAP_STR, 456133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 457115Sigor@sysoev.ru }, 458115Sigor@sysoev.ru 459115Sigor@sysoev.ru { 460133Sigor@sysoev.ru nxt_string("workers"), 461115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 462133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 463133Sigor@sysoev.ru }, 464133Sigor@sysoev.ru }; 465133Sigor@sysoev.ru 466133Sigor@sysoev.ru 467133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 468133Sigor@sysoev.ru { 469133Sigor@sysoev.ru nxt_string("application"), 470133Sigor@sysoev.ru NXT_CONF_MAP_STR, 471133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 472115Sigor@sysoev.ru }, 473115Sigor@sysoev.ru }; 474115Sigor@sysoev.ru 475115Sigor@sysoev.ru 476115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 477115Sigor@sysoev.ru { 478115Sigor@sysoev.ru nxt_string("header_buffer_size"), 479115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 480115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 481115Sigor@sysoev.ru }, 482115Sigor@sysoev.ru 483115Sigor@sysoev.ru { 484115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 485115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 486115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 487115Sigor@sysoev.ru }, 488115Sigor@sysoev.ru 489115Sigor@sysoev.ru { 490115Sigor@sysoev.ru nxt_string("header_read_timeout"), 491115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 492115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 493115Sigor@sysoev.ru }, 494115Sigor@sysoev.ru }; 495115Sigor@sysoev.ru 496115Sigor@sysoev.ru 49753Sigor@sysoev.ru static nxt_int_t 498115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 499115Sigor@sysoev.ru u_char *start, u_char *end) 50053Sigor@sysoev.ru { 501133Sigor@sysoev.ru u_char *p; 502133Sigor@sysoev.ru size_t size; 503115Sigor@sysoev.ru nxt_mp_t *mp; 504115Sigor@sysoev.ru uint32_t next; 505115Sigor@sysoev.ru nxt_int_t ret; 506115Sigor@sysoev.ru nxt_str_t name; 507133Sigor@sysoev.ru nxt_app_t *app, *prev; 508133Sigor@sysoev.ru nxt_app_type_t type; 509115Sigor@sysoev.ru nxt_sockaddr_t *sa; 510133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 511133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 512133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 513115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 514133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 515115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 516115Sigor@sysoev.ru 517115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 518133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 519115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 520115Sigor@sysoev.ru 521115Sigor@sysoev.ru conf = nxt_conf_json_parse(tmcf->mem_pool, start, end); 522115Sigor@sysoev.ru if (conf == NULL) { 523115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 524115Sigor@sysoev.ru return NXT_ERROR; 525115Sigor@sysoev.ru } 526115Sigor@sysoev.ru 527136Svbart@nginx.com ret = nxt_conf_map_object(conf, nxt_router_conf, 528136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 529115Sigor@sysoev.ru if (ret != NXT_OK) { 530133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 531115Sigor@sysoev.ru return NXT_ERROR; 532115Sigor@sysoev.ru } 533115Sigor@sysoev.ru 534117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 535117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 536117Sigor@sysoev.ru } 537117Sigor@sysoev.ru 538133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 539133Sigor@sysoev.ru if (applications == NULL) { 540133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 541115Sigor@sysoev.ru return NXT_ERROR; 542115Sigor@sysoev.ru } 543115Sigor@sysoev.ru 544133Sigor@sysoev.ru next = 0; 545133Sigor@sysoev.ru 546133Sigor@sysoev.ru for ( ;; ) { 547133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 548133Sigor@sysoev.ru if (application == NULL) { 549133Sigor@sysoev.ru break; 550133Sigor@sysoev.ru } 551133Sigor@sysoev.ru 552133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 553133Sigor@sysoev.ru 554144Smax.romanov@nginx.com size = nxt_conf_json_length(application, NULL); 555144Smax.romanov@nginx.com 556144Smax.romanov@nginx.com app = nxt_malloc(sizeof(nxt_app_t) + name.length + size); 557133Sigor@sysoev.ru if (app == NULL) { 558133Sigor@sysoev.ru goto fail; 559133Sigor@sysoev.ru } 560133Sigor@sysoev.ru 561144Smax.romanov@nginx.com nxt_memzero(app, sizeof(nxt_app_t)); 562144Smax.romanov@nginx.com 563144Smax.romanov@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 564144Smax.romanov@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); 565133Sigor@sysoev.ru 566133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 567133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 568133Sigor@sysoev.ru 569144Smax.romanov@nginx.com nxt_assert(app->conf.length <= size); 570144Smax.romanov@nginx.com 571133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 572133Sigor@sysoev.ru 573133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 574133Sigor@sysoev.ru 575133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 576133Sigor@sysoev.ru nxt_free(app); 577133Sigor@sysoev.ru 578133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 579133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 580133Sigor@sysoev.ru continue; 581133Sigor@sysoev.ru } 582133Sigor@sysoev.ru 583136Svbart@nginx.com ret = nxt_conf_map_object(application, nxt_router_app_conf, 584136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 585133Sigor@sysoev.ru if (ret != NXT_OK) { 586133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 587133Sigor@sysoev.ru goto app_fail; 588133Sigor@sysoev.ru } 589115Sigor@sysoev.ru 590133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 591133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 592133Sigor@sysoev.ru 593141Smax.romanov@nginx.com type = nxt_app_parse_type(&apcf.type); 594141Smax.romanov@nginx.com 595141Smax.romanov@nginx.com if (type == NXT_APP_UNKNOWN) { 596141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 597141Smax.romanov@nginx.com &apcf.type); 598141Smax.romanov@nginx.com goto app_fail; 599141Smax.romanov@nginx.com } 600141Smax.romanov@nginx.com 601141Smax.romanov@nginx.com if (nxt_app_modules[type] == NULL) { 602133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 603133Sigor@sysoev.ru &apcf.type); 604133Sigor@sysoev.ru goto app_fail; 605133Sigor@sysoev.ru } 606133Sigor@sysoev.ru 607133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 608133Sigor@sysoev.ru if (ret != NXT_OK) { 609133Sigor@sysoev.ru goto app_fail; 610133Sigor@sysoev.ru } 611133Sigor@sysoev.ru 612141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 613141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 614141Smax.romanov@nginx.com 615144Smax.romanov@nginx.com app->name.length = name.length; 616144Smax.romanov@nginx.com nxt_memcpy(app->name.start, name.start, name.length); 617144Smax.romanov@nginx.com 618133Sigor@sysoev.ru app->type = type; 619133Sigor@sysoev.ru app->max_workers = apcf.workers; 620133Sigor@sysoev.ru app->live = 1; 621141Smax.romanov@nginx.com app->module = nxt_app_modules[type]; 622133Sigor@sysoev.ru 623133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 624133Sigor@sysoev.ru } 625133Sigor@sysoev.ru 626133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 627133Sigor@sysoev.ru #if 0 628133Sigor@sysoev.ru if (http == NULL) { 629133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 630133Sigor@sysoev.ru return NXT_ERROR; 631133Sigor@sysoev.ru } 632133Sigor@sysoev.ru #endif 633133Sigor@sysoev.ru 634133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 635115Sigor@sysoev.ru if (listeners == NULL) { 636133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 637115Sigor@sysoev.ru return NXT_ERROR; 638115Sigor@sysoev.ru } 63953Sigor@sysoev.ru 640133Sigor@sysoev.ru next = 0; 64153Sigor@sysoev.ru 642133Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 643115Sigor@sysoev.ru 644115Sigor@sysoev.ru for ( ;; ) { 645115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 646115Sigor@sysoev.ru if (listener == NULL) { 647115Sigor@sysoev.ru break; 648115Sigor@sysoev.ru } 64953Sigor@sysoev.ru 650115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 651115Sigor@sysoev.ru if (sa == NULL) { 652115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 653133Sigor@sysoev.ru goto fail; 654115Sigor@sysoev.ru } 655115Sigor@sysoev.ru 656115Sigor@sysoev.ru sa->type = SOCK_STREAM; 657115Sigor@sysoev.ru 658115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 659115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 66053Sigor@sysoev.ru 661115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 662115Sigor@sysoev.ru if (skcf == NULL) { 663133Sigor@sysoev.ru goto fail; 664115Sigor@sysoev.ru } 66553Sigor@sysoev.ru 666136Svbart@nginx.com ret = nxt_conf_map_object(listener, nxt_router_listener_conf, 667136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 668115Sigor@sysoev.ru if (ret != NXT_OK) { 669115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 670133Sigor@sysoev.ru goto fail; 671115Sigor@sysoev.ru } 67253Sigor@sysoev.ru 673133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 674133Sigor@sysoev.ru 675133Sigor@sysoev.ru // STUB, default values if http block is not defined. 676133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 677133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 678133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 67953Sigor@sysoev.ru 680133Sigor@sysoev.ru if (http != NULL) { 681136Svbart@nginx.com ret = nxt_conf_map_object(http, nxt_router_http_conf, 682136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 683133Sigor@sysoev.ru if (ret != NXT_OK) { 684133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 685133Sigor@sysoev.ru goto fail; 686133Sigor@sysoev.ru } 687115Sigor@sysoev.ru } 688115Sigor@sysoev.ru 689115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 690115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 691133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 692133Sigor@sysoev.ru &lscf.application); 693115Sigor@sysoev.ru 694115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 695115Sigor@sysoev.ru } 69653Sigor@sysoev.ru 69753Sigor@sysoev.ru return NXT_OK; 698133Sigor@sysoev.ru 699133Sigor@sysoev.ru app_fail: 700133Sigor@sysoev.ru 701133Sigor@sysoev.ru nxt_free(app); 702133Sigor@sysoev.ru 703133Sigor@sysoev.ru fail: 704133Sigor@sysoev.ru 705141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 706141Smax.romanov@nginx.com 707141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 708133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 709133Sigor@sysoev.ru nxt_free(app); 710141Smax.romanov@nginx.com 711141Smax.romanov@nginx.com } nxt_queue_loop; 712133Sigor@sysoev.ru 713133Sigor@sysoev.ru return NXT_ERROR; 714133Sigor@sysoev.ru } 715133Sigor@sysoev.ru 716133Sigor@sysoev.ru 717133Sigor@sysoev.ru static nxt_app_t * 718133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 719133Sigor@sysoev.ru { 720141Smax.romanov@nginx.com nxt_app_t *app; 721141Smax.romanov@nginx.com 722141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 723133Sigor@sysoev.ru 724133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 725133Sigor@sysoev.ru return app; 726133Sigor@sysoev.ru } 727141Smax.romanov@nginx.com 728141Smax.romanov@nginx.com } nxt_queue_loop; 729133Sigor@sysoev.ru 730133Sigor@sysoev.ru return NULL; 731133Sigor@sysoev.ru } 732133Sigor@sysoev.ru 733133Sigor@sysoev.ru 734133Sigor@sysoev.ru static nxt_app_t * 735133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 736133Sigor@sysoev.ru { 737133Sigor@sysoev.ru nxt_app_t *app; 738133Sigor@sysoev.ru 739133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 740133Sigor@sysoev.ru 741133Sigor@sysoev.ru if (app == NULL) { 742134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 743133Sigor@sysoev.ru } 744133Sigor@sysoev.ru 745133Sigor@sysoev.ru return app; 74653Sigor@sysoev.ru } 74753Sigor@sysoev.ru 74853Sigor@sysoev.ru 74953Sigor@sysoev.ru static nxt_socket_conf_t * 75065Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 75153Sigor@sysoev.ru { 75253Sigor@sysoev.ru nxt_socket_conf_t *conf; 75353Sigor@sysoev.ru 75465Sigor@sysoev.ru conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 75553Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) { 75653Sigor@sysoev.ru return NULL; 75753Sigor@sysoev.ru } 75853Sigor@sysoev.ru 759115Sigor@sysoev.ru conf->sockaddr = sa; 760115Sigor@sysoev.ru 76153Sigor@sysoev.ru conf->listen.sockaddr = sa; 762103Sigor@sysoev.ru conf->listen.socklen = sa->socklen; 763103Sigor@sysoev.ru conf->listen.address_length = sa->length; 76453Sigor@sysoev.ru 76553Sigor@sysoev.ru conf->listen.socket = -1; 76653Sigor@sysoev.ru conf->listen.backlog = NXT_LISTEN_BACKLOG; 76753Sigor@sysoev.ru conf->listen.flags = NXT_NONBLOCK; 76853Sigor@sysoev.ru conf->listen.read_after_accept = 1; 76953Sigor@sysoev.ru 77053Sigor@sysoev.ru return conf; 77153Sigor@sysoev.ru } 77253Sigor@sysoev.ru 77353Sigor@sysoev.ru 77453Sigor@sysoev.ru static void 77553Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 77653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 77753Sigor@sysoev.ru { 77853Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 77953Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 78053Sigor@sysoev.ru 78153Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 78253Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 78353Sigor@sysoev.ru nqlk = next) 78453Sigor@sysoev.ru { 78553Sigor@sysoev.ru next = nxt_queue_next(nqlk); 78653Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 78753Sigor@sysoev.ru 78853Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 78953Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 79053Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 79153Sigor@sysoev.ru { 79253Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 79353Sigor@sysoev.ru 794115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 795115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 796115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 797115Sigor@sysoev.ru 79853Sigor@sysoev.ru nxt_queue_remove(oqlk); 79953Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 80053Sigor@sysoev.ru 80153Sigor@sysoev.ru nxt_queue_remove(nqlk); 80253Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 80353Sigor@sysoev.ru 80453Sigor@sysoev.ru break; 80553Sigor@sysoev.ru } 80653Sigor@sysoev.ru } 80753Sigor@sysoev.ru } 80853Sigor@sysoev.ru 80953Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 810115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 81153Sigor@sysoev.ru } 81253Sigor@sysoev.ru 81353Sigor@sysoev.ru 81453Sigor@sysoev.ru static nxt_int_t 81553Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 81653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 81753Sigor@sysoev.ru { 818115Sigor@sysoev.ru nxt_int_t ret; 819115Sigor@sysoev.ru nxt_socket_t s; 820115Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 821115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 822115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 82353Sigor@sysoev.ru 82453Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 82553Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 82653Sigor@sysoev.ru qlk = nqlk) 82753Sigor@sysoev.ru { 828115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 829115Sigor@sysoev.ru 830115Sigor@sysoev.ru s = nxt_listen_socket_create0(task, skcf->sockaddr, NXT_NONBLOCK); 831115Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 832115Sigor@sysoev.ru return NXT_ERROR; 833115Sigor@sysoev.ru } 834115Sigor@sysoev.ru 835115Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 836115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 837*148Sigor@sysoev.ru goto fail; 838115Sigor@sysoev.ru } 839115Sigor@sysoev.ru 840115Sigor@sysoev.ru skcf->listen.socket = s; 841115Sigor@sysoev.ru 842*148Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 843*148Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 844*148Sigor@sysoev.ru goto fail; 845*148Sigor@sysoev.ru } 846*148Sigor@sysoev.ru 847*148Sigor@sysoev.ru rtsk->count = 0; 848*148Sigor@sysoev.ru rtsk->fd = skcf->listen.socket; 849*148Sigor@sysoev.ru skcf->socket = rtsk; 850115Sigor@sysoev.ru 85153Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 85253Sigor@sysoev.ru nxt_queue_remove(qlk); 85353Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 85453Sigor@sysoev.ru } 85553Sigor@sysoev.ru 85653Sigor@sysoev.ru return NXT_OK; 857*148Sigor@sysoev.ru 858*148Sigor@sysoev.ru fail: 859*148Sigor@sysoev.ru 860*148Sigor@sysoev.ru nxt_socket_close(task, s); 861*148Sigor@sysoev.ru 862*148Sigor@sysoev.ru return NXT_ERROR; 86353Sigor@sysoev.ru } 86453Sigor@sysoev.ru 86553Sigor@sysoev.ru 86653Sigor@sysoev.ru static nxt_int_t 86753Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 86853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 86953Sigor@sysoev.ru { 87053Sigor@sysoev.ru nxt_int_t ret; 87153Sigor@sysoev.ru nxt_uint_t n, threads; 87253Sigor@sysoev.ru nxt_queue_link_t *qlk; 87353Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 87453Sigor@sysoev.ru 87553Sigor@sysoev.ru threads = tmcf->conf->threads; 87653Sigor@sysoev.ru 87753Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 87853Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 87953Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 88053Sigor@sysoev.ru return NXT_ERROR; 88153Sigor@sysoev.ru } 88253Sigor@sysoev.ru 88353Sigor@sysoev.ru n = 0; 88453Sigor@sysoev.ru 88553Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 88653Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 88753Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 88853Sigor@sysoev.ru { 88953Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 89053Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 89153Sigor@sysoev.ru return NXT_ERROR; 89253Sigor@sysoev.ru } 89353Sigor@sysoev.ru 894115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 89553Sigor@sysoev.ru 89653Sigor@sysoev.ru if (n < threads) { 897115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 89853Sigor@sysoev.ru 89953Sigor@sysoev.ru } else { 900115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 90153Sigor@sysoev.ru } 90253Sigor@sysoev.ru 90353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 90453Sigor@sysoev.ru return ret; 90553Sigor@sysoev.ru } 90653Sigor@sysoev.ru 90753Sigor@sysoev.ru n++; 90853Sigor@sysoev.ru } 90953Sigor@sysoev.ru 91053Sigor@sysoev.ru tmcf->new_threads = n; 91153Sigor@sysoev.ru 91253Sigor@sysoev.ru while (n < threads) { 91353Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 91453Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 91553Sigor@sysoev.ru return NXT_ERROR; 91653Sigor@sysoev.ru } 91753Sigor@sysoev.ru 91853Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 91953Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 92053Sigor@sysoev.ru return NXT_ERROR; 92153Sigor@sysoev.ru } 92253Sigor@sysoev.ru 923115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 92453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 92553Sigor@sysoev.ru return ret; 92653Sigor@sysoev.ru } 92753Sigor@sysoev.ru 928115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 929115Sigor@sysoev.ru 93053Sigor@sysoev.ru n++; 93153Sigor@sysoev.ru } 93253Sigor@sysoev.ru 93353Sigor@sysoev.ru return NXT_OK; 93453Sigor@sysoev.ru } 93553Sigor@sysoev.ru 93653Sigor@sysoev.ru 93753Sigor@sysoev.ru static nxt_int_t 938115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 939115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 94053Sigor@sysoev.ru { 941115Sigor@sysoev.ru nxt_mp_t *mp; 942115Sigor@sysoev.ru nxt_int_t ret; 943115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 94453Sigor@sysoev.ru 94553Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 94653Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 94753Sigor@sysoev.ru return NXT_ERROR; 94853Sigor@sysoev.ru } 94953Sigor@sysoev.ru 950115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 951115Sigor@sysoev.ru 952139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 953115Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 954115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 955115Sigor@sysoev.ru return ret; 956115Sigor@sysoev.ru } 957115Sigor@sysoev.ru 958139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 95953Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 96053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 96153Sigor@sysoev.ru return ret; 96253Sigor@sysoev.ru } 96353Sigor@sysoev.ru 964115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 965115Sigor@sysoev.ru 966115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 967115Sigor@sysoev.ru 968115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 969115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 970115Sigor@sysoev.ru 971115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 972115Sigor@sysoev.ru 973115Sigor@sysoev.ru return ret; 97453Sigor@sysoev.ru } 97553Sigor@sysoev.ru 97653Sigor@sysoev.ru 97753Sigor@sysoev.ru static nxt_int_t 978115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 979115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 98053Sigor@sysoev.ru { 981115Sigor@sysoev.ru nxt_mp_t *mp; 982115Sigor@sysoev.ru nxt_int_t ret; 983115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 98453Sigor@sysoev.ru 98553Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 98653Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 98753Sigor@sysoev.ru return NXT_ERROR; 98853Sigor@sysoev.ru } 98953Sigor@sysoev.ru 990115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 991115Sigor@sysoev.ru 992139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 99353Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 99453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 99553Sigor@sysoev.ru return ret; 99653Sigor@sysoev.ru } 99753Sigor@sysoev.ru 99853Sigor@sysoev.ru recf->updating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 99953Sigor@sysoev.ru if (nxt_slow_path(recf->updating == NULL)) { 100053Sigor@sysoev.ru return NXT_ERROR; 100153Sigor@sysoev.ru } 100253Sigor@sysoev.ru 1003139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 100453Sigor@sysoev.ru recf->updating, nxt_router_listen_socket_update); 100553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 100653Sigor@sysoev.ru return ret; 100753Sigor@sysoev.ru } 100853Sigor@sysoev.ru 100953Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 101053Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 101153Sigor@sysoev.ru return NXT_ERROR; 101253Sigor@sysoev.ru } 101353Sigor@sysoev.ru 1014139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 1015115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1016115Sigor@sysoev.ru return ret; 1017115Sigor@sysoev.ru } 1018115Sigor@sysoev.ru 1019115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1020115Sigor@sysoev.ru 1021115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1022115Sigor@sysoev.ru 1023115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1024115Sigor@sysoev.ru 1025115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1026115Sigor@sysoev.ru 1027115Sigor@sysoev.ru return ret; 102853Sigor@sysoev.ru } 102953Sigor@sysoev.ru 103053Sigor@sysoev.ru 103153Sigor@sysoev.ru static nxt_int_t 1032115Sigor@sysoev.ru nxt_router_engine_conf_delete(