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); 70154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 71154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 72154Sigor@sysoev.ru 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); 84154Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf); 8553Sigor@sysoev.ru 8653Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 8753Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 8853Sigor@sysoev.ru void *data); 8953Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 9053Sigor@sysoev.ru void *data); 9153Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 9253Sigor@sysoev.ru void *data); 9353Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 9453Sigor@sysoev.ru void *data); 9553Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 9653Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 9753Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 9853Sigor@sysoev.ru void *data); 9953Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 10053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 10153Sigor@sysoev.ru 102*163Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_app_t *app); 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 193*163Smax.romanov@nginx.com sw->app->workers++; 194*163Smax.romanov@nginx.com 195*163Smax.romanov@nginx.com nxt_assert(sw->app->pending_workers != 0); 196*163Smax.romanov@nginx.com 197*163Smax.romanov@nginx.com sw->app->pending_workers--; 198*163Smax.romanov@nginx.com 199141Smax.romanov@nginx.com nxt_router_app_release_port(task, msg->new_port, sw->app); 200141Smax.romanov@nginx.com 201141Smax.romanov@nginx.com sw->work.handler = nxt_router_sw_release; 202141Smax.romanov@nginx.com 203141Smax.romanov@nginx.com nxt_debug(task, "post sw #%uxD release to %p", sw->stream, 204141Smax.romanov@nginx.com sw->work.data); 205141Smax.romanov@nginx.com 206141Smax.romanov@nginx.com nxt_event_engine_post(sw->work.data, &sw->work); 207141Smax.romanov@nginx.com } 208141Smax.romanov@nginx.com } 209141Smax.romanov@nginx.com 210141Smax.romanov@nginx.com 211139Sigor@sysoev.ru void 212139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 213115Sigor@sysoev.ru { 214139Sigor@sysoev.ru size_t dump_size; 215139Sigor@sysoev.ru nxt_buf_t *b; 216139Sigor@sysoev.ru nxt_int_t ret; 217139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 218139Sigor@sysoev.ru 219139Sigor@sysoev.ru b = msg->buf; 220139Sigor@sysoev.ru 221139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 222139Sigor@sysoev.ru 223139Sigor@sysoev.ru if (dump_size > 300) { 224139Sigor@sysoev.ru dump_size = 300; 22553Sigor@sysoev.ru } 22653Sigor@sysoev.ru 227139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 228139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 229139Sigor@sysoev.ru 230139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 231139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 232139Sigor@sysoev.ru return; 23353Sigor@sysoev.ru } 23453Sigor@sysoev.ru 235139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 236139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 237139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 238139Sigor@sysoev.ru msg->port_msg.pid, 0); 239139Sigor@sysoev.ru 240139Sigor@sysoev.ru ret = nxt_router_conf_new(task, tmcf, b->mem.pos, b->mem.free); 241139Sigor@sysoev.ru 242139Sigor@sysoev.ru b->mem.pos = b->mem.free; 243139Sigor@sysoev.ru 244139Sigor@sysoev.ru if (ret == NXT_OK) { 245139Sigor@sysoev.ru return nxt_router_conf_success(task, tmcf); 246139Sigor@sysoev.ru } 247139Sigor@sysoev.ru 248139Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 249139Sigor@sysoev.ru 250139Sigor@sysoev.ru return nxt_router_conf_error(task, tmcf); 25153Sigor@sysoev.ru } 25253Sigor@sysoev.ru 25353Sigor@sysoev.ru 25453Sigor@sysoev.ru static nxt_router_temp_conf_t * 255139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 25653Sigor@sysoev.ru { 25765Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 25853Sigor@sysoev.ru nxt_router_conf_t *rtcf; 25953Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 26053Sigor@sysoev.ru 26165Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 26253Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 26353Sigor@sysoev.ru return NULL; 26453Sigor@sysoev.ru } 26553Sigor@sysoev.ru 26665Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 26753Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 26853Sigor@sysoev.ru goto fail; 26953Sigor@sysoev.ru } 27053Sigor@sysoev.ru 27153Sigor@sysoev.ru rtcf->mem_pool = mp; 27253Sigor@sysoev.ru 27365Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 27453Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 27553Sigor@sysoev.ru goto fail; 27653Sigor@sysoev.ru } 27753Sigor@sysoev.ru 27865Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 27953Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 28053Sigor@sysoev.ru goto temp_fail; 28153Sigor@sysoev.ru } 28253Sigor@sysoev.ru 28353Sigor@sysoev.ru tmcf->mem_pool = tmp; 28453Sigor@sysoev.ru tmcf->conf = rtcf; 285139Sigor@sysoev.ru tmcf->count = 1; 286139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 28753Sigor@sysoev.ru 28853Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 28953Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 29053Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 29153Sigor@sysoev.ru goto temp_fail; 29253Sigor@sysoev.ru } 29353Sigor@sysoev.ru 29453Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 29553Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 29653Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 29753Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 29853Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 299133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 300133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 30153Sigor@sysoev.ru 30253Sigor@sysoev.ru return tmcf; 30353Sigor@sysoev.ru 30453Sigor@sysoev.ru temp_fail: 30553Sigor@sysoev.ru 30665Sigor@sysoev.ru nxt_mp_destroy(tmp); 30753Sigor@sysoev.ru 30853Sigor@sysoev.ru fail: 30953Sigor@sysoev.ru 31065Sigor@sysoev.ru nxt_mp_destroy(mp); 31153Sigor@sysoev.ru 31253Sigor@sysoev.ru return NULL; 31353Sigor@sysoev.ru } 31453Sigor@sysoev.ru 31553Sigor@sysoev.ru 316139Sigor@sysoev.ru static nxt_int_t 317139Sigor@sysoev.ru nxt_router_conf_new(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 318139Sigor@sysoev.ru u_char *start, u_char *end) 319139Sigor@sysoev.ru { 320139Sigor@sysoev.ru nxt_int_t ret; 321139Sigor@sysoev.ru nxt_router_t *router; 322139Sigor@sysoev.ru nxt_runtime_t *rt; 323139Sigor@sysoev.ru const nxt_event_interface_t *interface; 324139Sigor@sysoev.ru 325139Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, start, end); 326139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 327139Sigor@sysoev.ru return ret; 328139Sigor@sysoev.ru } 329139Sigor@sysoev.ru 330139Sigor@sysoev.ru router = tmcf->conf->router; 331139Sigor@sysoev.ru 332139Sigor@sysoev.ru nxt_router_listen_sockets_sort(router, tmcf); 333139Sigor@sysoev.ru 334139Sigor@sysoev.ru ret = nxt_router_listen_sockets_stub_create(task, tmcf); 335139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 336139Sigor@sysoev.ru return ret; 337139Sigor@sysoev.ru } 338139Sigor@sysoev.ru 339139Sigor@sysoev.ru rt = task->thread->runtime; 340139Sigor@sysoev.ru 341139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 342139Sigor@sysoev.ru 343139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 344139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 345139Sigor@sysoev.ru return ret; 346139Sigor@sysoev.ru } 347139Sigor@sysoev.ru 348139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 349139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 350139Sigor@sysoev.ru return ret; 351139Sigor@sysoev.ru } 352139Sigor@sysoev.ru 353139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 354139Sigor@sysoev.ru 355139Sigor@sysoev.ru nxt_router_engines_post(tmcf); 356139Sigor@sysoev.ru 357139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 358139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 359139Sigor@sysoev.ru 360139Sigor@sysoev.ru return NXT_OK; 361139Sigor@sysoev.ru } 362139Sigor@sysoev.ru 363139Sigor@sysoev.ru 364139Sigor@sysoev.ru static void 365139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 366139Sigor@sysoev.ru { 367153Sigor@sysoev.ru nxt_joint_job_t *job; 368153Sigor@sysoev.ru 369153Sigor@sysoev.ru job = obj; 370153Sigor@sysoev.ru 371153Sigor@sysoev.ru nxt_router_conf_success(task, job->tmcf); 372139Sigor@sysoev.ru } 373139Sigor@sysoev.ru 374139Sigor@sysoev.ru 375139Sigor@sysoev.ru static void 376139Sigor@sysoev.ru nxt_router_conf_success(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 377139Sigor@sysoev.ru { 378139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 379139Sigor@sysoev.ru 380139Sigor@sysoev.ru if (--tmcf->count == 0) { 381139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "OK", 2); 382139Sigor@sysoev.ru } 383139Sigor@sysoev.ru } 384139Sigor@sysoev.ru 385139Sigor@sysoev.ru 386139Sigor@sysoev.ru static void 387139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 388139Sigor@sysoev.ru { 389148Sigor@sysoev.ru nxt_socket_t s; 390149Sigor@sysoev.ru nxt_router_t *router; 391148Sigor@sysoev.ru nxt_queue_link_t *qlk; 392148Sigor@sysoev.ru nxt_socket_conf_t *skcf; 393148Sigor@sysoev.ru 394148Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->creating); 395148Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->creating); 396148Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 397148Sigor@sysoev.ru { 398148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 399148Sigor@sysoev.ru s = skcf->listen.socket; 400148Sigor@sysoev.ru 401148Sigor@sysoev.ru if (s != -1) { 402148Sigor@sysoev.ru nxt_socket_close(task, s); 403148Sigor@sysoev.ru } 404148Sigor@sysoev.ru 405148Sigor@sysoev.ru nxt_free(skcf->socket); 406148Sigor@sysoev.ru } 407148Sigor@sysoev.ru 408149Sigor@sysoev.ru router = tmcf->conf->router; 409149Sigor@sysoev.ru 410149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->keeping); 411149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->deleting); 412149Sigor@sysoev.ru 413148Sigor@sysoev.ru // TODO: new engines and threads 414148Sigor@sysoev.ru 415139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 416139Sigor@sysoev.ru 417139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "ERROR", 5); 418139Sigor@sysoev.ru } 419139Sigor@sysoev.ru 420139Sigor@sysoev.ru 421139Sigor@sysoev.ru static void 422139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 423139Sigor@sysoev.ru u_char *start, size_t size) 424139Sigor@sysoev.ru { 425139Sigor@sysoev.ru nxt_buf_t *b; 426139Sigor@sysoev.ru 427139Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 428139Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 429139Sigor@sysoev.ru return; 430139Sigor@sysoev.ru } 431139Sigor@sysoev.ru 432140Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, start, size); 433140Svbart@nginx.com 434139Sigor@sysoev.ru b->parent = tmcf->mem_pool; 435139Sigor@sysoev.ru b->completion_handler = nxt_router_conf_buf_completion; 436139Sigor@sysoev.ru 437139Sigor@sysoev.ru nxt_port_socket_write(task, tmcf->port, NXT_PORT_MSG_DATA, -1, 438139Sigor@sysoev.ru tmcf->stream, 0, b); 439139Sigor@sysoev.ru } 440139Sigor@sysoev.ru 441139Sigor@sysoev.ru 442139Sigor@sysoev.ru static void 443139Sigor@sysoev.ru nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, void *data) 444139Sigor@sysoev.ru { 445139Sigor@sysoev.ru nxt_mp_t *mp; 446139Sigor@sysoev.ru 447139Sigor@sysoev.ru /* nxt_router_temp_conf_t mem pool. */ 448139Sigor@sysoev.ru mp = data; 449139Sigor@sysoev.ru 450139Sigor@sysoev.ru nxt_mp_destroy(mp); 451139Sigor@sysoev.ru } 452139Sigor@sysoev.ru 453139Sigor@sysoev.ru 454115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 455115Sigor@sysoev.ru { 456133Sigor@sysoev.ru nxt_string("listeners_threads"), 457115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 458115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 459115Sigor@sysoev.ru }, 460115Sigor@sysoev.ru }; 461115Sigor@sysoev.ru 462115Sigor@sysoev.ru 463133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 464115Sigor@sysoev.ru { 465133Sigor@sysoev.ru nxt_string("type"), 466115Sigor@sysoev.ru NXT_CONF_MAP_STR, 467133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 468115Sigor@sysoev.ru }, 469115Sigor@sysoev.ru 470115Sigor@sysoev.ru { 471133Sigor@sysoev.ru nxt_string("workers"), 472115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 473133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 474133Sigor@sysoev.ru }, 475133Sigor@sysoev.ru }; 476133Sigor@sysoev.ru 477133Sigor@sysoev.ru 478133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 479133Sigor@sysoev.ru { 480133Sigor@sysoev.ru nxt_string("application"), 481133Sigor@sysoev.ru NXT_CONF_MAP_STR, 482133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 483115Sigor@sysoev.ru }, 484115Sigor@sysoev.ru }; 485115Sigor@sysoev.ru 486115Sigor@sysoev.ru 487115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 488115Sigor@sysoev.ru { 489115Sigor@sysoev.ru nxt_string("header_buffer_size"), 490115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 491115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 492115Sigor@sysoev.ru }, 493115Sigor@sysoev.ru 494115Sigor@sysoev.ru { 495115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 496115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 497115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 498115Sigor@sysoev.ru }, 499115Sigor@sysoev.ru 500115Sigor@sysoev.ru { 501115Sigor@sysoev.ru nxt_string("header_read_timeout"), 502115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 503115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 504115Sigor@sysoev.ru }, 505115Sigor@sysoev.ru }; 506115Sigor@sysoev.ru 507115Sigor@sysoev.ru 50853Sigor@sysoev.ru static nxt_int_t 509115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 510115Sigor@sysoev.ru u_char *start, u_char *end) 51153Sigor@sysoev.ru { 512133Sigor@sysoev.ru u_char *p; 513133Sigor@sysoev.ru size_t size; 514115Sigor@sysoev.ru nxt_mp_t *mp; 515115Sigor@sysoev.ru uint32_t next; 516115Sigor@sysoev.ru nxt_int_t ret; 517115Sigor@sysoev.ru nxt_str_t name; 518133Sigor@sysoev.ru nxt_app_t *app, *prev; 519133Sigor@sysoev.ru nxt_app_type_t type; 520115Sigor@sysoev.ru nxt_sockaddr_t *sa; 521133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 522133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 523133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 524115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 525133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 526115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 527115Sigor@sysoev.ru 528115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 529133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 530115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 531115Sigor@sysoev.ru 532115Sigor@sysoev.ru conf = nxt_conf_json_parse(tmcf->mem_pool, start, end); 533115Sigor@sysoev.ru if (conf == NULL) { 534115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 535115Sigor@sysoev.ru return NXT_ERROR; 536115Sigor@sysoev.ru } 537115Sigor@sysoev.ru 538136Svbart@nginx.com ret = nxt_conf_map_object(conf, nxt_router_conf, 539136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 540115Sigor@sysoev.ru if (ret != NXT_OK) { 541133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 542115Sigor@sysoev.ru return NXT_ERROR; 543115Sigor@sysoev.ru } 544115Sigor@sysoev.ru 545117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 546117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 547117Sigor@sysoev.ru } 548117Sigor@sysoev.ru 549133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 550133Sigor@sysoev.ru if (applications == NULL) { 551133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 552115Sigor@sysoev.ru return NXT_ERROR; 553115Sigor@sysoev.ru } 554115Sigor@sysoev.ru 555133Sigor@sysoev.ru next = 0; 556133Sigor@sysoev.ru 557133Sigor@sysoev.ru for ( ;; ) { 558133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 559133Sigor@sysoev.ru if (application == NULL) { 560133Sigor@sysoev.ru break; 561133Sigor@sysoev.ru } 562133Sigor@sysoev.ru 563133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 564133Sigor@sysoev.ru 565144Smax.romanov@nginx.com size = nxt_conf_json_length(application, NULL); 566144Smax.romanov@nginx.com 567144Smax.romanov@nginx.com app = nxt_malloc(sizeof(nxt_app_t) + name.length + size); 568133Sigor@sysoev.ru if (app == NULL) { 569133Sigor@sysoev.ru goto fail; 570133Sigor@sysoev.ru } 571133Sigor@sysoev.ru 572144Smax.romanov@nginx.com nxt_memzero(app, sizeof(nxt_app_t)); 573144Smax.romanov@nginx.com 574144Smax.romanov@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 575144Smax.romanov@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); 576133Sigor@sysoev.ru 577133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 578133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 579133Sigor@sysoev.ru 580144Smax.romanov@nginx.com nxt_assert(app->conf.length <= size); 581144Smax.romanov@nginx.com 582133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 583133Sigor@sysoev.ru 584133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 585133Sigor@sysoev.ru 586133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 587133Sigor@sysoev.ru nxt_free(app); 588133Sigor@sysoev.ru 589133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 590133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 591133Sigor@sysoev.ru continue; 592133Sigor@sysoev.ru } 593133Sigor@sysoev.ru 594136Svbart@nginx.com ret = nxt_conf_map_object(application, nxt_router_app_conf, 595136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 596133Sigor@sysoev.ru if (ret != NXT_OK) { 597133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 598133Sigor@sysoev.ru goto app_fail; 599133Sigor@sysoev.ru } 600115Sigor@sysoev.ru 601133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 602133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 603133Sigor@sysoev.ru 604141Smax.romanov@nginx.com type = nxt_app_parse_type(&apcf.type); 605141Smax.romanov@nginx.com 606141Smax.romanov@nginx.com if (type == NXT_APP_UNKNOWN) { 607141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 608141Smax.romanov@nginx.com &apcf.type); 609141Smax.romanov@nginx.com goto app_fail; 610141Smax.romanov@nginx.com } 611141Smax.romanov@nginx.com 612141Smax.romanov@nginx.com if (nxt_app_modules[type] == NULL) { 613133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 614133Sigor@sysoev.ru &apcf.type); 615133Sigor@sysoev.ru goto app_fail; 616133Sigor@sysoev.ru } 617133Sigor@sysoev.ru 618133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 619133Sigor@sysoev.ru if (ret != NXT_OK) { 620133Sigor@sysoev.ru goto app_fail; 621133Sigor@sysoev.ru } 622133Sigor@sysoev.ru 623141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 624141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 625141Smax.romanov@nginx.com 626144Smax.romanov@nginx.com app->name.length = name.length; 627144Smax.romanov@nginx.com nxt_memcpy(app->name.start, name.start, name.length); 628144Smax.romanov@nginx.com 629133Sigor@sysoev.ru app->type = type; 630133Sigor@sysoev.ru app->max_workers = apcf.workers; 631133Sigor@sysoev.ru app->live = 1; 632141Smax.romanov@nginx.com app->module = nxt_app_modules[type]; 633133Sigor@sysoev.ru 634133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 635133Sigor@sysoev.ru } 636133Sigor@sysoev.ru 637133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 638133Sigor@sysoev.ru #if 0 639133Sigor@sysoev.ru if (http == NULL) { 640133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 641133Sigor@sysoev.ru return NXT_ERROR; 642133Sigor@sysoev.ru } 643133Sigor@sysoev.ru #endif 644133Sigor@sysoev.ru 645133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 646115Sigor@sysoev.ru if (listeners == NULL) { 647133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 648115Sigor@sysoev.ru return NXT_ERROR; 649115Sigor@sysoev.ru } 65053Sigor@sysoev.ru 651133Sigor@sysoev.ru next = 0; 65253Sigor@sysoev.ru 653133Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 654115Sigor@sysoev.ru 655115Sigor@sysoev.ru for ( ;; ) { 656115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 657115Sigor@sysoev.ru if (listener == NULL) { 658115Sigor@sysoev.ru break; 659115Sigor@sysoev.ru } 66053Sigor@sysoev.ru 661115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 662115Sigor@sysoev.ru if (sa == NULL) { 663115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 664133Sigor@sysoev.ru goto fail; 665115Sigor@sysoev.ru } 666115Sigor@sysoev.ru 667115Sigor@sysoev.ru sa->type = SOCK_STREAM; 668115Sigor@sysoev.ru 669115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 670115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 67153Sigor@sysoev.ru 672115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 673115Sigor@sysoev.ru if (skcf == NULL) { 674133Sigor@sysoev.ru goto fail; 675115Sigor@sysoev.ru } 67653Sigor@sysoev.ru 677136Svbart@nginx.com ret = nxt_conf_map_object(listener, nxt_router_listener_conf, 678136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 679115Sigor@sysoev.ru if (ret != NXT_OK) { 680115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 681133Sigor@sysoev.ru goto fail; 682115Sigor@sysoev.ru } 68353Sigor@sysoev.ru 684133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 685133Sigor@sysoev.ru 686133Sigor@sysoev.ru // STUB, default values if http block is not defined. 687133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 688133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 689133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 69053Sigor@sysoev.ru 691133Sigor@sysoev.ru if (http != NULL) { 692136Svbart@nginx.com ret = nxt_conf_map_object(http, nxt_router_http_conf, 693136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 694133Sigor@sysoev.ru if (ret != NXT_OK) { 695133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 696133Sigor@sysoev.ru goto fail; 697133Sigor@sysoev.ru } 698115Sigor@sysoev.ru } 699115Sigor@sysoev.ru 700115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 701115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 702160Sigor@sysoev.ru skcf->router_conf->count++; 703133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 704133Sigor@sysoev.ru &lscf.application); 705115Sigor@sysoev.ru 706115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 707115Sigor@sysoev.ru } 70853Sigor@sysoev.ru 70953Sigor@sysoev.ru return NXT_OK; 710133Sigor@sysoev.ru 711133Sigor@sysoev.ru app_fail: 712133Sigor@sysoev.ru 713133Sigor@sysoev.ru nxt_free(app); 714133Sigor@sysoev.ru 715133Sigor@sysoev.ru fail: 716133Sigor@sysoev.ru 717141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 718141Smax.romanov@nginx.com 719141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 720133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 721133Sigor@sysoev.ru nxt_free(app); 722141Smax.romanov@nginx.com 723141Smax.romanov@nginx.com } nxt_queue_loop; 724133Sigor@sysoev.ru 725133Sigor@sysoev.ru return NXT_ERROR; 726133Sigor@sysoev.ru } 727133Sigor@sysoev.ru 728133Sigor@sysoev.ru 729133Sigor@sysoev.ru static nxt_app_t * 730133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 731133Sigor@sysoev.ru { 732141Smax.romanov@nginx.com nxt_app_t *app; 733141Smax.romanov@nginx.com 734141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 735133Sigor@sysoev.ru 736133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 737133Sigor@sysoev.ru return app; 738133Sigor@sysoev.ru } 739141Smax.romanov@nginx.com 740141Smax.romanov@nginx.com } nxt_queue_loop; 741133Sigor@sysoev.ru 742133Sigor@sysoev.ru return NULL; 743133Sigor@sysoev.ru } 744133Sigor@sysoev.ru 745133Sigor@sysoev.ru 746133Sigor@sysoev.ru static nxt_app_t * 747133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 748133Sigor@sysoev.ru { 749133Sigor@sysoev.ru nxt_app_t *app; 750133Sigor@sysoev.ru 751133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 752133Sigor@sysoev.ru 753133Sigor@sysoev.ru if (app == NULL) { 754134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 755133Sigor@sysoev.ru } 756133Sigor@sysoev.ru 757133Sigor@sysoev.ru return app; 75853Sigor@sysoev.ru } 75953Sigor@sysoev.ru 76053Sigor@sysoev.ru 76153Sigor@sysoev.ru static nxt_socket_conf_t * 76265Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 76353Sigor@sysoev.ru { 764*163Smax.romanov@nginx.com nxt_socket_conf_t *skcf; 765*163Smax.romanov@nginx.com 766*163Smax.romanov@nginx.com skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 767*163Smax.romanov@nginx.com if (nxt_slow_path(skcf == NULL)) { 76853Sigor@sysoev.ru return NULL; 76953Sigor@sysoev.ru } 77053Sigor@sysoev.ru 771*163Smax.romanov@nginx.com skcf->sockaddr = sa; 772*163Smax.romanov@nginx.com 773*163Smax.romanov@nginx.com skcf->listen.sockaddr = sa; 774*163Smax.romanov@nginx.com skcf->listen.socklen = sa->socklen; 775*163Smax.romanov@nginx.com skcf->listen.address_length = sa->length; 776*163Smax.romanov@nginx.com 777*163Smax.romanov@nginx.com skcf->listen.socket = -1; 778*163Smax.romanov@nginx.com skcf->listen.backlog = NXT_LISTEN_BACKLOG; 779*163Smax.romanov@nginx.com skcf->listen.flags = NXT_NONBLOCK; 780*163Smax.romanov@nginx.com skcf->listen.read_after_accept = 1; 781*163Smax.romanov@nginx.com 782*163Smax.romanov@nginx.com return skcf; 78353Sigor@sysoev.ru } 78453Sigor@sysoev.ru 78553Sigor@sysoev.ru 78653Sigor@sysoev.ru static void 78753Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 78853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 78953Sigor@sysoev.ru { 79053Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 79153Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 79253Sigor@sysoev.ru 79353Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 79453Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 79553Sigor@sysoev.ru nqlk = next) 79653Sigor@sysoev.ru { 79753Sigor@sysoev.ru next = nxt_queue_next(nqlk); 79853Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 79953Sigor@sysoev.ru 80053Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 80153Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 80253Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 80353Sigor@sysoev.ru { 80453Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 80553Sigor@sysoev.ru 806115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 807115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 808115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 809115Sigor@sysoev.ru 81053Sigor@sysoev.ru nxt_queue_remove(oqlk); 81153Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 81253Sigor@sysoev.ru 81353Sigor@sysoev.ru nxt_queue_remove(nqlk); 81453Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 81553Sigor@sysoev.ru 81653Sigor@sysoev.ru break; 81753Sigor@sysoev.ru } 81853Sigor@sysoev.ru } 81953Sigor@sysoev.ru } 82053Sigor@sysoev.ru 82153Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 822115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 82353Sigor@sysoev.ru } 82453Sigor@sysoev.ru 82553Sigor@sysoev.ru 82653Sigor@sysoev.ru static nxt_int_t 82753Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 82853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 82953Sigor@sysoev.ru { 830115Sigor@sysoev.ru nxt_int_t ret; 831115Sigor@sysoev.ru nxt_socket_t s; 832115Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 833115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 834115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 83553Sigor@sysoev.ru 83653Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 83753Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 83853Sigor@sysoev.ru qlk = nqlk) 83953Sigor@sysoev.ru { 840115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 841115Sigor@sysoev.ru 842115Sigor@sysoev.ru s = nxt_listen_socket_create0(task, skcf->sockaddr, NXT_NONBLOCK); 843115Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 844115Sigor@sysoev.ru return NXT_ERROR; 845115Sigor@sysoev.ru } 846115Sigor@sysoev.ru 847115Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 848115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 849148Sigor@sysoev.ru goto fail; 850115Sigor@sysoev.ru } 851115Sigor@sysoev.ru 852115Sigor@sysoev.ru skcf->listen.socket = s; 853115Sigor@sysoev.ru 854148Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 855148Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 856148Sigor@sysoev.ru goto fail; 857148Sigor@sysoev.ru } 858148Sigor@sysoev.ru 859148Sigor@sysoev.ru rtsk->count = 0; 860148Sigor@sysoev.ru rtsk->fd = skcf->listen.socket; 861148Sigor@sysoev.ru skcf->socket = rtsk; 862115Sigor@sysoev.ru 86353Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 86453Sigor@sysoev.ru nxt_queue_remove(qlk); 86553Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 86653Sigor@sysoev.ru } 86753Sigor@sysoev.ru 86853Sigor@sysoev.ru return NXT_OK; 869148Sigor@sysoev.ru 870148Sigor@sysoev.ru fail: 871148Sigor@sysoev.ru 872148Sigor@sysoev.ru nxt_socket_close(task, s); 873148Sigor@sysoev.ru 874148Sigor@sysoev.ru return NXT_ERROR; 87553Sigor@sysoev.ru } 87653Sigor@sysoev.ru 87753Sigor@sysoev.ru 87853Sigor@sysoev.ru static nxt_int_t 87953Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 88053Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 88153Sigor@sysoev.ru { 88253Sigor@sysoev.ru nxt_int_t ret; 88353Sigor@sysoev.ru nxt_uint_t n, threads; 88453Sigor@sysoev.ru nxt_queue_link_t *qlk; 88553Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 88653Sigor@sysoev.ru 88753Sigor@sysoev.ru threads = tmcf->conf->threads; 88853Sigor@sysoev.ru 88953Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 89053Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 89153Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 89253Sigor@sysoev.ru return NXT_ERROR; 89353Sigor@sysoev.ru } 89453Sigor@sysoev.ru 89553Sigor@sysoev.ru n = 0; 89653Sigor@sysoev.ru 89753Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 89853Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 89953Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 90053Sigor@sysoev.ru { 90153Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 90253Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 90353Sigor@sysoev.ru return NXT_ERROR; 90453Sigor@sysoev.ru } 90553Sigor@sysoev.ru 906115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 90753Sigor@sysoev.ru 90853Sigor@sysoev.ru if (n < threads) { 909115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 91053Sigor@sysoev.ru 91153Sigor@sysoev.ru } else { 912115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 91353Sigor@sysoev.ru } 91453Sigor@sysoev.ru 91553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 91653Sigor@sysoev.ru return ret; 91753Sigor@sysoev.ru } 91853Sigor@sysoev.ru 91953Sigor@sysoev.ru n++; 92053Sigor@sysoev.ru } 92153Sigor@sysoev.ru 92253Sigor@sysoev.ru tmcf->new_threads = n; 92353Sigor@sysoev.ru 92453Sigor@sysoev.ru while (n < threads) { 92553Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 92653Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 92753Sigor@sysoev.ru return NXT_ERROR; 92853Sigor@sysoev.ru } 92953Sigor@sysoev.ru 93053Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 93153Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 93253Sigor@sysoev.ru return NXT_ERROR; 93353Sigor@sysoev.ru } 93453Sigor@sysoev.ru 935115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 93653Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 93753Sigor@sysoev.ru return ret; 93853Sigor@sysoev.ru } 93953Sigor@sysoev.ru 940115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 941115Sigor@sysoev.ru 94253Sigor@sysoev.ru n++; 94353Sigor@sysoev.ru } 94453Sigor@sysoev.ru 94553Sigor@sysoev.ru return NXT_OK; 94653Sigor@sysoev.ru } 94753Sigor@sysoev.ru 94853Sigor@sysoev.ru 94953Sigor@sysoev.ru static nxt_int_t 950115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 951115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 95253Sigor@sysoev.ru { 953115Sigor@sysoev.ru nxt_int_t ret; 954115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 95553Sigor@sysoev.ru 956154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 957154Sigor@sysoev.ru nxt_router_listen_socket_create); 958115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 959115Sigor@sysoev.ru return ret; 960115Sigor@sysoev.ru } 961115Sigor@sysoev.ru 962154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 963154Sigor@sysoev.ru nxt_router_listen_socket_create); 96453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 96553Sigor@sysoev.ru return ret; 96653Sigor@sysoev.ru } 96753Sigor@sysoev.ru 968115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 969115Sigor@sysoev.ru 970115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 971115Sigor@sysoev.ru 972115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 973115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 974115Sigor@sysoev.ru 975115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 976115Sigor@sysoev.ru 977115Sigor@sysoev.ru return ret; 97853Sigor@sysoev.ru } 97953Sigor@sysoev.ru 98053Sigor@sysoev.ru 98153Sigor@sysoev.ru static nxt_int_t 982115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 983115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 98453Sigor@sysoev.ru { 985115Sigor@sysoev.ru nxt_int_t ret; 986115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 98753Sigor@sysoev.ru 988154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 989154Sigor@sysoev.ru nxt_router_listen_socket_create); 99053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 99153Sigor@sysoev.ru return ret; 99253Sigor@sysoev.ru } 99353Sigor@sysoev.ru 994154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 995154Sigor@sysoev.ru nxt_router_listen_socket_update); 99653Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 99753Sigor@sysoev.ru return ret; 99853Sigor@sysoev.ru } 99953Sigor@sysoev.ru 1000139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 1001115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1002115Sigor@sysoev.ru return ret; 1003115Sigor@sysoev.ru } 1004115Sigor@sysoev.ru 1005115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1006115Sigor@sysoev.ru 1007115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1008115Sigor@sysoev.ru 1009115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1010115Sigor@sysoev.ru 1011115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1012115Sigor@sysoev.ru 1013115Sigor@sysoev.ru return ret; 101453Sigor@sysoev.ru } 101553Sigor@sysoev.ru 101653Sigor@sysoev.ru 101753Sigor@sysoev.ru static nxt_int_t 1018115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 1019115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 102053Sigor@sysoev.ru { 102153Sigor@sysoev.ru nxt_int_t ret; 102253Sigor@sysoev.ru 1023139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 102453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 102553Sigor@sysoev.ru return ret; 102653Sigor@sysoev.ru } 102753Sigor@sysoev.ru 1028139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 102953Sigor@sysoev.ru } 103053Sigor@sysoev.ru 103153Sigor@sysoev.ru 103253Sigor@sysoev.ru static nxt_int_t 1033154Sigor@sysoev.ru