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(nxt_router_temp_conf_t *tmcf, 1033115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 103453Sigor@sysoev.ru { 103553Sigor@sysoev.ru nxt_int_t ret; 103653Sigor@sysoev.ru 103753Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 103853Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 103953Sigor@sysoev.ru return NXT_ERROR; 104053Sigor@sysoev.ru } 104153Sigor@sysoev.ru 1042139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 104353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 104453Sigor@sysoev.ru return ret; 104553Sigor@sysoev.ru } 104653Sigor@sysoev.ru 1047139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 104853Sigor@sysoev.ru } 104953Sigor@sysoev.ru 105053Sigor@sysoev.ru 105153Sigor@sysoev.ru static nxt_int_t 1052139Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_mp_t *mp, nxt_router_temp_conf_t *tmcf, 1053139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array, 105453Sigor@sysoev.ru nxt_work_handler_t handler) 105553Sigor@sysoev.ru { 1056139Sigor@sysoev.ru nxt_work_t *work, *back; 105753Sigor@sysoev.ru nxt_queue_link_t *qlk; 105853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 105953Sigor@sysoev.ru 106053Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 106153Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 106253Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 106353Sigor@sysoev.ru { 1064139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 1065139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 1066139Sigor@sysoev.ru return NXT_ERROR; 1067139Sigor@sysoev.ru } 1068139Sigor@sysoev.ru 1069139Sigor@sysoev.ru back->next = NULL; 1070139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 1071139Sigor@sysoev.ru back->task = &tmcf->engine->task; 1072139Sigor@sysoev.ru back->obj = tmcf; 1073139Sigor@sysoev.ru back->data = NULL; 1074139Sigor@sysoev.ru 107553Sigor@sysoev.ru work = nxt_array_add(array); 107653Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 107753Sigor@sysoev.ru return NXT_ERROR; 107853Sigor@sysoev.ru } 107953Sigor@sysoev.ru 108053Sigor@sysoev.ru work->next = NULL; 108153Sigor@sysoev.ru work->handler = handler; 1082139Sigor@sysoev.ru work->task = &recf->engine->task; 1083139Sigor@sysoev.ru work->obj = back; 108453Sigor@sysoev.ru 108565Sigor@sysoev.ru joint = nxt_mp_alloc(mp, sizeof(nxt_socket_conf_joint_t)); 108653Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 108753Sigor@sysoev.ru return NXT_ERROR; 108853Sigor@sysoev.ru } 108953Sigor@sysoev.ru 109053Sigor@sysoev.ru work->data = joint; 109153Sigor@sysoev.ru 109253Sigor@sysoev.ru joint->count = 1; 109353Sigor@sysoev.ru joint->socket_conf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 109488Smax.romanov@nginx.com joint->engine = recf->engine; 1095115Sigor@sysoev.ru 1096115Sigor@sysoev.ru nxt_queue_insert_tail(&joint->engine->joints, &joint->link); 109753Sigor@sysoev.ru } 109853Sigor@sysoev.ru 109920Sigor@sysoev.ru return NXT_OK; 110020Sigor@sysoev.ru } 110120Sigor@sysoev.ru 110220Sigor@sysoev.ru 1103115Sigor@sysoev.ru static void 1104115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 1105115Sigor@sysoev.ru { 1106115Sigor@sysoev.ru nxt_queue_link_t *qlk; 1107115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1108115Sigor@sysoev.ru 1109115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 1110115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 1111115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 1112115Sigor@sysoev.ru { 1113115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1114115Sigor@sysoev.ru skcf->socket->count++; 1115115Sigor@sysoev.ru } 1116115Sigor@sysoev.ru } 1117115Sigor@sysoev.ru 1118115Sigor@sysoev.ru 111920Sigor@sysoev.ru static nxt_int_t 1120139Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 1121139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 112220Sigor@sysoev.ru { 1123139Sigor@sysoev.ru nxt_work_t *work, *back; 112453Sigor@sysoev.ru nxt_queue_link_t *qlk; 112520Sigor@sysoev.ru 112653Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 112753Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 112853Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 112953Sigor@sysoev.ru { 1130139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 1131139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 1132139Sigor@sysoev.ru return NXT_ERROR; 1133139Sigor@sysoev.ru } 1134139Sigor@sysoev.ru 1135139Sigor@sysoev.ru back->next = NULL; 1136139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 1137139Sigor@sysoev.ru back->task = &tmcf->engine->task; 1138139Sigor@sysoev.ru back->obj = tmcf; 1139139Sigor@sysoev.ru back->data = NULL; 1140139Sigor@sysoev.ru 1141115Sigor@sysoev.ru work = nxt_array_add(recf->deleting); 114253Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 114353Sigor@sysoev.ru return NXT_ERROR; 114453Sigor@sysoev.ru } 114520Sigor@sysoev.ru 114653Sigor@sysoev.ru work->next = NULL; 114753Sigor@sysoev.ru work->handler = nxt_router_listen_socket_delete; 1148139Sigor@sysoev.ru work->task = &recf->engine->task; 1149139Sigor@sysoev.ru work->obj = back; 115053Sigor@sysoev.ru work->data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 115120Sigor@sysoev.ru } 115220Sigor@sysoev.ru 115353Sigor@sysoev.ru return NXT_OK; 115453Sigor@sysoev.ru } 115520Sigor@sysoev.ru 115620Sigor@sysoev.ru 115753Sigor@sysoev.ru static nxt_int_t 115853Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 115953Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 116053Sigor@sysoev.ru { 116153Sigor@sysoev.ru nxt_int_t ret; 116253Sigor@sysoev.ru nxt_uint_t i, threads; 116353Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 116420Sigor@sysoev.ru 116553Sigor@sysoev.ru recf = tmcf->engines->elts; 116653Sigor@sysoev.ru threads = tmcf->conf->threads; 116720Sigor@sysoev.ru 116853Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 116953Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 117053Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 117153Sigor@sysoev.ru return ret; 117253Sigor@sysoev.ru } 117320Sigor@sysoev.ru } 117420Sigor@sysoev.ru 117520Sigor@sysoev.ru return NXT_OK; 117620Sigor@sysoev.ru } 117753Sigor@sysoev.ru 117853Sigor@sysoev.ru 117953Sigor@sysoev.ru static nxt_int_t 118053Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 118153Sigor@sysoev.ru nxt_event_engine_t *engine) 118253Sigor@sysoev.ru { 118353Sigor@sysoev.ru nxt_int_t ret; 118453Sigor@sysoev.ru nxt_thread_link_t *link; 118553Sigor@sysoev.ru nxt_thread_handle_t handle; 118653Sigor@sysoev.ru 118753Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 118853Sigor@sysoev.ru 118953Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 119053Sigor@sysoev.ru return NXT_ERROR; 119153Sigor@sysoev.ru } 119253Sigor@sysoev.ru 119353Sigor@sysoev.ru link->start = nxt_router_thread_start; 119453Sigor@sysoev.ru link->engine = engine; 119553Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 119653Sigor@sysoev.ru link->work.task = task; 119753Sigor@sysoev.ru link->work.data = link; 119853Sigor@sysoev.ru 119953Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 120053Sigor@sysoev.ru 120153Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 120253Sigor@sysoev.ru 120353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 120453Sigor@sysoev.ru nxt_queue_remove(&engine->link); 120553Sigor@sysoev.ru } 120653Sigor@sysoev.ru 120753Sigor@sysoev.ru return ret; 120853Sigor@sysoev.ru } 120953Sigor@sysoev.ru 121053Sigor@sysoev.ru 121153Sigor@sysoev.ru static void 1212133Sigor@sysoev.ru nxt_router_apps_sort(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 1213133Sigor@sysoev.ru { 1214141Smax.romanov@nginx.com nxt_app_t *app; 1215141Smax.romanov@nginx.com 1216141Smax.romanov@nginx.com nxt_queue_each(app, &router->apps, nxt_app_t, link) { 1217133Sigor@sysoev.ru 1218133Sigor@sysoev.ru nxt_queue_remove(&app->link); 1219133Sigor@sysoev.ru 1220141Smax.romanov@nginx.com // TODO RELEASE APP 1221144Smax.romanov@nginx.com #if 0 1222144Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->mutex); 1223144Smax.romanov@nginx.com nxt_free(app); 1224144Smax.romanov@nginx.com #endif 1225141Smax.romanov@nginx.com } nxt_queue_loop; 1226133Sigor@sysoev.ru 1227133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous); 1228133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps); 1229133Sigor@sysoev.ru } 1230133Sigor@sysoev.ru 1231133Sigor@sysoev.ru 1232133Sigor@sysoev.ru static void 123353Sigor@sysoev.ru nxt_router_engines_post(nxt_router_temp_conf_t *tmcf) 123453Sigor@sysoev.ru { 123553Sigor@sysoev.ru nxt_uint_t n; 123653Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 123753Sigor@sysoev.ru 123853Sigor@sysoev.ru recf = tmcf->engines->elts; 123953Sigor@sysoev.ru 124053Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 1241139Sigor@sysoev.ru nxt_router_engine_post(tmcf, recf); 124253Sigor@sysoev.ru recf++; 124353Sigor@sysoev.ru } 124453Sigor@sysoev.ru } 124553Sigor@sysoev.ru 124653Sigor@sysoev.ru 124753Sigor@sysoev.ru static void 1248139Sigor@sysoev.ru nxt_router_engine_post(nxt_router_temp_conf_t *tmcf, 1249139Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 125053Sigor@sysoev.ru { 125153Sigor@sysoev.ru nxt_uint_t n; 125253Sigor@sysoev.ru nxt_work_t *work; 125353Sigor@sysoev.ru 1254115Sigor@sysoev.ru if (recf->creating != NULL) { 1255115Sigor@sysoev.ru work = recf->creating->elts; 1256115Sigor@sysoev.ru 1257115Sigor@sysoev.ru for (n = recf->creating->nelts; n != 0; n--) { 1258115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1259115Sigor@sysoev.ru work++; 1260139Sigor@sysoev.ru tmcf->count++; 1261115Sigor@sysoev.ru } 1262115Sigor@sysoev.ru } 1263115Sigor@sysoev.ru 1264115Sigor@sysoev.ru if (recf->updating != NULL) { 1265115Sigor@sysoev.ru work = recf->updating->elts; 126653Sigor@sysoev.ru 1267115Sigor@sysoev.ru for (n = recf->updating->nelts; n != 0; n--) { 1268115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1269115Sigor@sysoev.ru work++; 1270139Sigor@sysoev.ru tmcf->count++; 1271115Sigor@sysoev.ru } 1272115Sigor@sysoev.ru } 1273115Sigor@sysoev.ru 1274115Sigor@sysoev.ru if (recf->deleting != NULL) { 1275115Sigor@sysoev.ru work = recf->deleting->elts; 1276115Sigor@sysoev.ru 1277115Sigor@sysoev.ru for (n = recf->deleting->nelts; n != 0; n--) { 1278115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1279115Sigor@sysoev.ru work++; 1280139Sigor@sysoev.ru tmcf->count++; 1281115Sigor@sysoev.ru } 128253Sigor@sysoev.ru } 128353Sigor@sysoev.ru } 128453Sigor@sysoev.ru 128553Sigor@sysoev.ru 128653Sigor@sysoev.ru static void 1287119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 128888Smax.romanov@nginx.com 1289119Smax.romanov@nginx.com static nxt_port_handler_t nxt_router_app_port_handlers[] = { 129088Smax.romanov@nginx.com NULL, 129188Smax.romanov@nginx.com nxt_port_new_port_handler, 129288Smax.romanov@nginx.com nxt_port_change_log_file_handler, 129388Smax.romanov@nginx.com nxt_port_mmap_handler, 1294119Smax.romanov@nginx.com nxt_router_app_data_handler, 1295125Smax.romanov@nginx.com nxt_port_remove_pid_handler, 129688Smax.romanov@nginx.com }; 129788Smax.romanov@nginx.com 129888Smax.romanov@nginx.com 129988Smax.romanov@nginx.com static void 130053Sigor@sysoev.ru nxt_router_thread_start(void *data) 130153Sigor@sysoev.ru { 1302141Smax.romanov@nginx.com nxt_int_t ret; 1303141Smax.romanov@nginx.com nxt_port_t *port; 130488Smax.romanov@nginx.com nxt_task_t *task; 130553Sigor@sysoev.ru nxt_thread_t *thread; 130653Sigor@sysoev.ru nxt_thread_link_t *link; 130753Sigor@sysoev.ru nxt_event_engine_t *engine; 130853Sigor@sysoev.ru 130953Sigor@sysoev.ru link = data; 131053Sigor@sysoev.ru engine = link->engine; 131188Smax.romanov@nginx.com task = &engine->task; 131253Sigor@sysoev.ru 131353Sigor@sysoev.ru thread = nxt_thread(); 131453Sigor@sysoev.ru 131553Sigor@sysoev.ru /* STUB */ 131653Sigor@sysoev.ru thread->runtime = engine->task.thread->runtime; 131753Sigor@sysoev.ru 131853Sigor@sysoev.ru engine->task.thread = thread; 131953Sigor@sysoev.ru engine->task.log = thread->log; 132053Sigor@sysoev.ru thread->engine = engine; 132163Sigor@sysoev.ru thread->task = &engine->task; 132253Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 132353Sigor@sysoev.ru 132463Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 132553Sigor@sysoev.ru 1326141Smax.romanov@nginx.com port = nxt_mp_zalloc(engine->mem_pool, sizeof(nxt_port_t)); 1327141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 1328141Smax.romanov@nginx.com return; 1329141Smax.romanov@nginx.com } 1330141Smax.romanov@nginx.com 1331141Smax.romanov@nginx.com port->id = nxt_port_get_next_id(); 1332141Smax.romanov@nginx.com port->pid = nxt_pid; 1333141Smax.romanov@nginx.com 1334141Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0); 1335141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 1336141Smax.romanov@nginx.com return; 1337141Smax.romanov@nginx.com } 1338141Smax.romanov@nginx.com 1339141Smax.romanov@nginx.com port->type = NXT_PROCESS_ROUTER; 1340141Smax.romanov@nginx.com 1341141Smax.romanov@nginx.com engine->port = port; 1342141Smax.romanov@nginx.com 1343141Smax.romanov@nginx.com nxt_port_enable(task, port, nxt_router_app_port_handlers); 1344141Smax.romanov@nginx.com 134553Sigor@sysoev.ru nxt_event_engine_start(engine); 134653Sigor@sysoev.ru } 134753Sigor@sysoev.ru 134853Sigor@sysoev.ru 134953Sigor@sysoev.ru static void 135053Sigor@sysoev.ru nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 135153Sigor@sysoev.ru { 1352139Sigor@sysoev.ru nxt_work_t *work; 135353Sigor@sysoev.ru nxt_listen_event_t *listen; 135453Sigor@sysoev.ru nxt_listen_socket_t *ls; 1355139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 135653Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 135753Sigor@sysoev.ru 1358139Sigor@sysoev.ru work = obj; 135953Sigor@sysoev.ru joint = data; 136053Sigor@sysoev.ru 136153Sigor@sysoev.ru ls = &joint->socket_conf->listen; 136253Sigor@sysoev.ru 136353Sigor@sysoev.ru listen = nxt_listen_event(task, ls); 136453Sigor@sysoev.ru if (nxt_slow_path(listen == NULL)) { 136553Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 136653Sigor@sysoev.ru return; 136753Sigor@sysoev.ru } 136853Sigor@sysoev.ru 136953Sigor@sysoev.ru listen->socket.data = joint; 1370139Sigor@sysoev.ru 1371139Sigor@sysoev.ru tmcf = work->obj; 1372139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 137353Sigor@sysoev.ru } 137453Sigor@sysoev.ru 137553Sigor@sysoev.ru 137653Sigor@sysoev.ru nxt_inline nxt_listen_event_t * 137753Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections, 137853Sigor@sysoev.ru nxt_socket_conf_t *skcf) 137953Sigor@sysoev.ru { 1380115Sigor@sysoev.ru nxt_socket_t fd; 1381115Sigor@sysoev.ru nxt_queue_link_t *qlk; 138253Sigor@sysoev.ru nxt_listen_event_t *listen; 138353Sigor@sysoev.ru 1384115Sigor@sysoev.ru fd = skcf->socket->fd; 138553Sigor@sysoev.ru 1386115Sigor@sysoev.ru for (qlk = nxt_queue_first(listen_connections); 1387115Sigor@sysoev.ru qlk != nxt_queue_tail(listen_connections); 1388115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 138953Sigor@sysoev.ru { 1390115Sigor@sysoev.ru listen = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 139153Sigor@sysoev.ru 1392115Sigor@sysoev.ru if (fd == listen->socket.fd) { 139353Sigor@sysoev.ru return listen; 139453Sigor@sysoev.ru } 139553Sigor@sysoev.ru } 139653Sigor@sysoev.ru 139753Sigor@sysoev.ru return NULL; 139853Sigor@sysoev.ru } 139953Sigor@sysoev.ru 140053Sigor@sysoev.ru 140153Sigor@sysoev.ru static void 140253Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 140353Sigor@sysoev.ru { 1404139Sigor@sysoev.ru nxt_work_t *work; 140553Sigor@sysoev.ru nxt_event_engine_t *engine; 140653Sigor@sysoev.ru nxt_listen_event_t *listen; 1407139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 140853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old; 140953Sigor@sysoev.ru 1410139Sigor@sysoev.ru work = obj; 141153Sigor@sysoev.ru joint = data; 141253Sigor@sysoev.ru 1413139Sigor@sysoev.ru engine = task->thread->engine; 1414139Sigor@sysoev.ru 141553Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, 141653Sigor@sysoev.ru joint->socket_conf); 141753Sigor@sysoev.ru 141853Sigor@sysoev.ru old = listen->socket.data; 141953Sigor@sysoev.ru listen->socket.data = joint; 142053Sigor@sysoev.ru 1421139Sigor@sysoev.ru tmcf = work->obj; 1422139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 1423139Sigor@sysoev.ru 142453Sigor@sysoev.ru nxt_router_conf_release(task, old); 142553Sigor@sysoev.ru } 142653Sigor@sysoev.ru 142753Sigor@sysoev.ru 142853Sigor@sysoev.ru static void 142953Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 143053Sigor@sysoev.ru { 1431139Sigor@sysoev.ru nxt_work_t *work; 1432139Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1433139Sigor@sysoev.ru nxt_listen_event_t *listen; 1434139Sigor@sysoev.ru nxt_event_engine_t *engine; 1435139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 1436139Sigor@sysoev.ru 1437139Sigor@sysoev.ru work = obj; 143853Sigor@sysoev.ru skcf = data; 143953Sigor@sysoev.ru 1440139Sigor@sysoev.ru engine = task->thread->engine; 1441139Sigor@sysoev.ru 144253Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, skcf); 144353Sigor@sysoev.ru 144453Sigor@sysoev.ru nxt_fd_event_delete(engine, &listen->socket); 144553Sigor@sysoev.ru 144653Sigor@sysoev.ru listen->timer.handler = nxt_router_listen_socket_close; 144753Sigor@sysoev.ru listen->timer.work_queue = &engine->fast_work_queue; 144853Sigor@sysoev.ru 144953Sigor@sysoev.ru nxt_timer_add(engine, &listen->timer, 0); 1450139Sigor@sysoev.ru 1451139Sigor@sysoev.ru tmcf = work->obj; 1452139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 145353Sigor@sysoev.ru } 145453Sigor@sysoev.ru 145553Sigor@sysoev.ru 145653Sigor@sysoev.ru static void 145753Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 145853Sigor@sysoev.ru { 145953Sigor@sysoev.ru nxt_timer_t *timer; 146053Sigor@sysoev.ru nxt_listen_event_t *listen; 146153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 146253Sigor@sysoev.ru 146353Sigor@sysoev.ru timer = obj; 146453Sigor@sysoev.ru listen = nxt_timer_data(timer, nxt_listen_event_t, timer); 146553Sigor@sysoev.ru joint = listen->socket.data; 146653Sigor@sysoev.ru 146753Sigor@sysoev.ru nxt_queue_remove(&listen->link); 1468123Smax.romanov@nginx.com 1469123Smax.romanov@nginx.com /* 'task' refers to listen->task and we cannot use after nxt_free() */ 1470123Smax.romanov@nginx.com task = &task->thread->engine->task; 1471123Smax.romanov@nginx.com 147253Sigor@sysoev.ru nxt_free(listen); 147353Sigor@sysoev.ru 147453Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 147553Sigor@sysoev.ru } 147653Sigor@sysoev.ru 147753Sigor@sysoev.ru 147853Sigor@sysoev.ru static void 147953Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, 148053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint) 148153Sigor@sysoev.ru { 1482118Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1483115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 148453Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 148553Sigor@sysoev.ru 1486118Sigor@sysoev.ru skcf = joint->socket_conf; 1487118Sigor@sysoev.ru rtsk = skcf->socket; 1488118Sigor@sysoev.ru lock = &skcf->router_conf->router->lock; 148953Sigor@sysoev.ru 149053Sigor@sysoev.ru nxt_thread_spin_lock(lock); 149153Sigor@sysoev.ru 1492115Sigor@sysoev.ru if (--rtsk->count != 0) { 1493115Sigor@sysoev.ru rtsk = NULL; 149453Sigor@sysoev.ru } 149553Sigor@sysoev.ru 149653Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 149753Sigor@sysoev.ru 1498115Sigor@sysoev.ru if (rtsk != NULL) { 1499115Sigor@sysoev.ru nxt_socket_close(task, rtsk->fd); 1500115Sigor@sysoev.ru nxt_free(rtsk); 1501118Sigor@sysoev.ru skcf->socket = NULL; 150253Sigor@sysoev.ru } 150353Sigor@sysoev.ru 150453Sigor@sysoev.ru nxt_router_conf_release(task, joint); 150553Sigor@sysoev.ru } 150653Sigor@sysoev.ru 150753Sigor@sysoev.ru 150853Sigor@sysoev.ru static void 150953Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 151053Sigor@sysoev.ru { 151153Sigor@sysoev.ru nxt_socket_conf_t *skcf; 151253Sigor@sysoev.ru nxt_router_conf_t *rtcf; 151353Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 151453Sigor@sysoev.ru 151553Sigor@sysoev.ru nxt_debug(task, "conf joint count: %D", joint->count); 151653Sigor@sysoev.ru 151753Sigor@sysoev.ru if (--joint->count != 0) { 151853Sigor@sysoev.ru return; 151953Sigor@sysoev.ru } 152053Sigor@sysoev.ru 152153Sigor@sysoev.ru nxt_queue_remove(&joint->link); 152253Sigor@sysoev.ru 152353Sigor@sysoev.ru skcf = joint->socket_conf; 152453Sigor@sysoev.ru rtcf = skcf->router_conf; 152553Sigor@sysoev.ru lock = &rtcf->router->lock; 152653Sigor@sysoev.ru 152753Sigor@sysoev.ru nxt_thread_spin_lock(lock); 152853Sigor@sysoev.ru 152953Sigor@sysoev.ru if (--skcf->count != 0) { 153053Sigor@sysoev.ru rtcf = NULL; 153153Sigor@sysoev.ru 153253Sigor@sysoev.ru } else { 153353Sigor@sysoev.ru nxt_queue_remove(&skcf->link); 153453Sigor@sysoev.ru 153553Sigor@sysoev.ru if (--rtcf->count != 0) { 153653Sigor@sysoev.ru rtcf = NULL; 153753Sigor@sysoev.ru } 153853Sigor@sysoev.ru } 153953Sigor@sysoev.ru 154053Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 154153Sigor@sysoev.ru 1542141Smax.romanov@nginx.com /* TODO remove engine->port */ 1543141Smax.romanov@nginx.com /* TODO excude from connected ports */ 1544141Smax.romanov@nginx.com 154553Sigor@sysoev.ru if (rtcf != NULL) { 1546115Sigor@sysoev.ru nxt_debug(task, "old router conf is destroyed"); 1547131Smax.romanov@nginx.com 1548131Smax.romanov@nginx.com nxt_mp_thread_adopt(rtcf->mem_pool); 1549131Smax.romanov@nginx.com 155065Sigor@sysoev.ru nxt_mp_destroy(rtcf->mem_pool); 155153Sigor@sysoev.ru } 155253Sigor@sysoev.ru 155353Sigor@sysoev.ru if (nxt_queue_is_empty(&joint->engine->joints)) { 155453Sigor@sysoev.ru nxt_thread_exit(task->thread); 155553Sigor@sysoev.ru } 155653Sigor@sysoev.ru } 155753Sigor@sysoev.ru 155853Sigor@sysoev.ru 155953Sigor@sysoev.ru static void 156053Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 156153Sigor@sysoev.ru { 1562141Smax.romanov@nginx.com nxt_port_t *port; 156353Sigor@sysoev.ru nxt_thread_link_t *link; 156453Sigor@sysoev.ru nxt_event_engine_t *engine; 156553Sigor@sysoev.ru nxt_thread_handle_t handle; 156653Sigor@sysoev.ru 156758Svbart@nginx.com handle = (nxt_thread_handle_t) obj; 156853Sigor@sysoev.ru link = data; 156953Sigor@sysoev.ru 157053Sigor@sysoev.ru nxt_thread_wait(handle); 157153Sigor@sysoev.ru 157253Sigor@sysoev.ru engine = link->engine; 157353Sigor@sysoev.ru 157453Sigor@sysoev.ru nxt_queue_remove(&engine->link); 157553Sigor@sysoev.ru 1576141Smax.romanov@nginx.com port = engine->port; 1577141Smax.romanov@nginx.com 1578141Smax.romanov@nginx.com // TODO notify all apps 1579141Smax.romanov@nginx.com 1580141Smax.romanov@nginx.com if (port->pair[0] != -1) { 1581141Smax.romanov@nginx.com nxt_fd_close(port->pair[0]); 1582141Smax.romanov@nginx.com } 1583141Smax.romanov@nginx.com 1584141Smax.romanov@nginx.com if (port->pair[1] != -1) { 1585141Smax.romanov@nginx.com nxt_fd_close(port->pair[1]); 1586141Smax.romanov@nginx.com } 1587141Smax.romanov@nginx.com 1588141Smax.romanov@nginx.com if (port->mem_pool) { 1589141Smax.romanov@nginx.com nxt_mp_destroy(port->mem_pool); 1590141Smax.romanov@nginx.com } 1591141Smax.romanov@nginx.com 159263Sigor@sysoev.ru nxt_mp_destroy(engine->mem_pool); 159353Sigor@sysoev.ru 159453Sigor@sysoev.ru nxt_event_engine_free(engine); 159553Sigor@sysoev.ru 159653Sigor@sysoev.ru nxt_free(link); 159753Sigor@sysoev.ru } 159853Sigor@sysoev.ru 159953Sigor@sysoev.ru 160062Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_read_state 160153Sigor@sysoev.ru nxt_aligned(64) = 160253Sigor@sysoev.ru { 160353Sigor@sysoev.ru .ready_handler = nxt_router_conn_http_header_parse, 160453Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 160553Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 160653Sigor@sysoev.ru 160753Sigor@sysoev.ru .timer_handler = nxt_router_conn_timeout, 160853Sigor@sysoev.ru .timer_value = nxt_router_conn_timeout_value, 160953Sigor@sysoev.ru .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 161053Sigor@sysoev.ru }; 161153Sigor@sysoev.ru 161253Sigor@sysoev.ru 161353Sigor@sysoev.ru static void 161453Sigor@sysoev.ru nxt_router_conn_init(nxt_task_t *task, void *obj, void *data) 161553Sigor@sysoev.ru { 161653Sigor@sysoev.ru size_t size; 161762Sigor@sysoev.ru nxt_conn_t *c; 161853Sigor@sysoev.ru nxt_event_engine_t *engine; 161953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 162053Sigor@sysoev.ru 162153Sigor@sysoev.ru c = obj; 162253Sigor@sysoev.ru joint = data; 162353Sigor@sysoev.ru 162453Sigor@sysoev.ru nxt_debug(task, "router conn init"); 162553Sigor@sysoev.ru 162653Sigor@sysoev.ru joint->count++; 162753Sigor@sysoev.ru 162853Sigor@sysoev.ru size = joint->socket_conf->header_buffer_size; 162953Sigor@sysoev.ru c->read = nxt_buf_mem_alloc(c->mem_pool, size, 0); 163053Sigor@sysoev.ru 163153Sigor@sysoev.ru c->socket.data = NULL; 163253Sigor@sysoev.ru 163353Sigor@sysoev.ru engine = task->thread->engine; 163453Sigor@sysoev.ru c->read_work_queue = &engine->fast_work_queue; 163553Sigor@sysoev.ru c->write_work_queue = &engine->fast_work_queue; 163653Sigor@sysoev.ru 163753Sigor@sysoev.ru c->read_state = &nxt_router_conn_read_state; 163853Sigor@sysoev.ru 163962Sigor@sysoev.ru nxt_conn_read(engine, c); 164053Sigor@sysoev.ru } 164153Sigor@sysoev.ru 164253Sigor@sysoev.ru 164362Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_write_state 164453Sigor@sysoev.ru nxt_aligned(64) = 164553Sigor@sysoev.ru { 164688Smax.romanov@nginx.com .ready_handler = nxt_router_conn_ready, 164753Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 164853Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 164953Sigor@sysoev.ru }; 165053Sigor@sysoev.ru 165153Sigor@sysoev.ru 165253Sigor@sysoev.ru static void 1653119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 165488Smax.romanov@nginx.com { 165588Smax.romanov@nginx.com size_t dump_size; 165688Smax.romanov@nginx.com nxt_buf_t *b, *i, *last; 165788Smax.romanov@nginx.com nxt_conn_t *c; 165888Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 165988Smax.romanov@nginx.com nxt_event_engine_t *engine; 166088Smax.romanov@nginx.com 166188Smax.romanov@nginx.com b = msg->buf; 166288Smax.romanov@nginx.com engine = task->thread->engine; 166388Smax.romanov@nginx.com 166488Smax.romanov@nginx.com rc = nxt_event_engine_request_find(engine, msg->port_msg.stream); 166588Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 166688Smax.romanov@nginx.com 166788Smax.romanov@nginx.com nxt_debug(task, "request id %08uxD not found", msg->port_msg.stream); 166888Smax.romanov@nginx.com 166995Smax.romanov@nginx.com /* Mark buffers as read. */ 167088Smax.romanov@nginx.com for (i = b; i != NULL; i = i->next) { 167188Smax.romanov@nginx.com i->mem.pos = i->mem.free; 167288Smax.romanov@nginx.com } 167388Smax.romanov@nginx.com 167488Smax.romanov@nginx.com return; 167588Smax.romanov@nginx.com } 167688Smax.romanov@nginx.com 167788Smax.romanov@nginx.com c = rc->conn; 167888Smax.romanov@nginx.com 167988Smax.romanov@nginx.com dump_size = nxt_buf_used_size(b); 168088Smax.romanov@nginx.com 168188Smax.romanov@nginx.com if (dump_size > 300) { 168288Smax.romanov@nginx.com dump_size = 300; 168388Smax.romanov@nginx.com } 168488Smax.romanov@nginx.com 1685119Smax.romanov@nginx.com nxt_debug(task, "%srouter app data (%z): %*s", 168688Smax.romanov@nginx.com msg->port_msg.last ? "last " : "", msg->size, dump_size, 168788Smax.romanov@nginx.com b->mem.pos); 168888Smax.romanov@nginx.com 168988Smax.romanov@nginx.com if (msg->size == 0) { 169088Smax.romanov@nginx.com b = NULL; 169188Smax.romanov@nginx.com } 169288Smax.romanov@nginx.com 169388Smax.romanov@nginx.com if (msg->port_msg.last != 0) { 169488Smax.romanov@nginx.com nxt_debug(task, "router data create last buf"); 169588Smax.romanov@nginx.com 169688Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 169788Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 169888Smax.romanov@nginx.com /* TODO pogorevaTb */ 169988Smax.romanov@nginx.com } 170088Smax.romanov@nginx.com 170188Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 170288Smax.romanov@nginx.com } 170388Smax.romanov@nginx.com 170488Smax.romanov@nginx.com if (b == NULL) { 170588Smax.romanov@nginx.com return; 170688Smax.romanov@nginx.com } 170788Smax.romanov@nginx.com 170888Smax.romanov@nginx.com if (c->write == NULL) { 170988Smax.romanov@nginx.com c->write = b; 171088Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 171188Smax.romanov@nginx.com 171288Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 171388Smax.romanov@nginx.com } else { 171488Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 171588Smax.romanov@nginx.com 171688Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 171788Smax.romanov@nginx.com } 171888Smax.romanov@nginx.com } 171988Smax.romanov@nginx.com 1720141Smax.romanov@nginx.com nxt_inline const char * 1721141Smax.romanov@nginx.com nxt_router_text_by_code(int code) 1722141Smax.romanov@nginx.com { 1723141Smax.romanov@nginx.com switch (code) { 1724141Smax.romanov@nginx.com case 400: return "Bad request"; 1725141Smax.romanov@nginx.com case 404: return "Not found"; 1726141Smax.romanov@nginx.com case 403: return "Forbidden"; 1727141Smax.romanov@nginx.com case 500: 1728141Smax.romanov@nginx.com default: return "Internal server error"; 1729141Smax.romanov@nginx.com } 1730141Smax.romanov@nginx.com } 1731141Smax.romanov@nginx.com 1732141Smax.romanov@nginx.com static void 1733141Smax.romanov@nginx.com nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 1734141Smax.romanov@nginx.com const char* fmt, ...) 173588Smax.romanov@nginx.com { 1736141Smax.romanov@nginx.com va_list args; 1737141Smax.romanov@nginx.com nxt_buf_t *b, *last; 1738141Smax.romanov@nginx.com const char *msg; 1739141Smax.romanov@nginx.com 1740141Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, 16384, 0); 1741141Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 1742141Smax.romanov@nginx.com /* TODO pogorevaTb */ 1743141Smax.romanov@nginx.com } 1744141Smax.romanov@nginx.com 1745141Smax.romanov@nginx.com b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, 1746141Smax.romanov@nginx.com "HTTP/1.0 %d %s\r\n" 1747141Smax.romanov@nginx.com "Content-Type: text/plain\r\n" 1748141Smax.romanov@nginx.com "Connection: close\r\n\r\n", 1749141Smax.romanov@nginx.com code, nxt_router_text_by_code(code)); 1750141Smax.romanov@nginx.com 1751141Smax.romanov@nginx.com msg = (const char *) b->mem.free; 1752141Smax.romanov@nginx.com 1753141Smax.romanov@nginx.com va_start(args, fmt); 1754141Smax.romanov@nginx.com b->mem.free = nxt_vsprintf(b->mem.free, b->mem.end, fmt, args); 1755141Smax.romanov@nginx.com va_end(args); 1756141Smax.romanov@nginx.com 1757141Smax.romanov@nginx.com nxt_log_alert(task->log, "error %d: %s", code, msg); 1758141Smax.romanov@nginx.com 1759141Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 1760141Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 1761141Smax.romanov@nginx.com /* TODO pogorevaTb */ 1762141Smax.romanov@nginx.com } 1763141Smax.romanov@nginx.com 1764141Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 1765141Smax.romanov@nginx.com 1766141Smax.romanov@nginx.com if (c->write == NULL) { 1767141Smax.romanov@nginx.com c->write = b; 1768141Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 1769141Smax.romanov@nginx.com 1770141Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 1771141Smax.romanov@nginx.com } else { 1772141Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 1773141Smax.romanov@nginx.com 1774141Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 1775141Smax.romanov@nginx.com } 1776141Smax.romanov@nginx.com } 1777141Smax.romanov@nginx.com 1778141Smax.romanov@nginx.com 1779141Smax.romanov@nginx.com static void 1780141Smax.romanov@nginx.com nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data) 1781141Smax.romanov@nginx.com { 1782141Smax.romanov@nginx.com nxt_buf_t *b; 1783141Smax.romanov@nginx.com nxt_app_t *app; 1784141Smax.romanov@nginx.com nxt_port_t *port; 1785141Smax.romanov@nginx.com nxt_runtime_t *rt; 1786141Smax.romanov@nginx.com nxt_start_worker_t *sw; 1787141Smax.romanov@nginx.com 1788141Smax.romanov@nginx.com sw = obj; 1789141Smax.romanov@nginx.com app = sw->app; 1790141Smax.romanov@nginx.com 1791141Smax.romanov@nginx.com nxt_debug(task, "send sw #%uD", sw->stream); 1792141Smax.romanov@nginx.com 1793141Smax.romanov@nginx.com nxt_router_sw_add(task, nxt_router, sw); 1794141Smax.romanov@nginx.com nxt_queue_insert_tail(&app->requests, &sw->rc->app_link); 179588Smax.romanov@nginx.com 1796119Smax.romanov@nginx.com rt = task->thread->runtime; 1797141Smax.romanov@nginx.com port = rt->port_by_type[NXT_PROCESS_MASTER]; 1798141Smax.romanov@nginx.com 1799141Smax.romanov@nginx.com b = nxt_buf_mem_alloc(port->mem_pool, app->conf.length, 0); 1800141Smax.romanov@nginx.com 1801141Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 1802141Smax.romanov@nginx.com 1803141Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, -1, sw->stream, 0, b); 1804141Smax.romanov@nginx.com } 1805141Smax.romanov@nginx.com 1806141Smax.romanov@nginx.com 1807141Smax.romanov@nginx.com static nxt_port_t * 1808141Smax.romanov@nginx.com nxt_router_app_get_port(nxt_app_t *app) 1809141Smax.romanov@nginx.com { 1810141Smax.romanov@nginx.com nxt_port_t *port; 1811141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 1812141Smax.romanov@nginx.com 1813141Smax.romanov@nginx.com port = NULL; 1814141Smax.romanov@nginx.com 1815141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1816141Smax.romanov@nginx.com 1817141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->ports)) { 1818141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->ports); 1819141Smax.romanov@nginx.com nxt_queue_remove(lnk); 1820141Smax.romanov@nginx.com 1821141Smax.romanov@nginx.com lnk->next = NULL; 1822141Smax.romanov@nginx.com 1823141Smax.romanov@nginx.com port = nxt_queue_link_data(lnk, nxt_port_t, app_link); 1824141Smax.romanov@nginx.com } 1825141Smax.romanov@nginx.com 1826141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1827141Smax.romanov@nginx.com 1828141Smax.romanov@nginx.com return port; 1829141Smax.romanov@nginx.com } 1830141Smax.romanov@nginx.com 1831141Smax.romanov@nginx.com 1832141Smax.romanov@nginx.com static void 1833141Smax.romanov@nginx.com nxt_router_app_release_port(nxt_task_t *task, void *obj, void *data) 1834141Smax.romanov@nginx.com { 1835141Smax.romanov@nginx.com nxt_app_t *app; 1836141Smax.romanov@nginx.com nxt_port_t *port; 1837141Smax.romanov@nginx.com nxt_work_t *work; 1838141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 1839141Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 1840141Smax.romanov@nginx.com 1841141Smax.romanov@nginx.com port = obj; 1842141Smax.romanov@nginx.com app = data; 1843141Smax.romanov@nginx.com 1844141Smax.romanov@nginx.com nxt_assert(app != NULL); 1845141Smax.romanov@nginx.com nxt_assert(app == port->app); 1846141Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 1847141Smax.romanov@nginx.com 1848141Smax.romanov@nginx.com 1849141Smax.romanov@nginx.com if (task->thread->engine != port->engine) { 1850141Smax.romanov@nginx.com work = (nxt_work_t *) (port + 1); 1851141Smax.romanov@nginx.com 1852141Smax.romanov@nginx.com nxt_debug(task, "post release port to engine %p", port->engine); 1853141Smax.romanov@nginx.com 1854141Smax.romanov@nginx.com work->next = NULL; 1855141Smax.romanov@nginx.com work->handler = nxt_router_app_release_port; 1856141Smax.romanov@nginx.com work->task = port->socket.task; 1857141Smax.romanov@nginx.com work->obj = port; 1858141Smax.romanov@nginx.com work->data = app; 1859141Smax.romanov@nginx.com 1860141Smax.romanov@nginx.com nxt_event_engine_post(port->engine, work); 1861141Smax.romanov@nginx.com 1862141Smax.romanov@nginx.com return; 1863141Smax.romanov@nginx.com } 1864141Smax.romanov@nginx.com 1865141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 1866141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 1867141Smax.romanov@nginx.com nxt_queue_remove(lnk); 1868141Smax.romanov@nginx.com 1869141Smax.romanov@nginx.com rc = nxt_queue_link_data(lnk, nxt_req_conn_link_t, app_link); 1870141Smax.romanov@nginx.com 1871141Smax.romanov@nginx.com nxt_debug(task, "process request #%uxD", rc->req_id); 1872141Smax.romanov@nginx.com 1873141Smax.romanov@nginx.com rc->app_port = port; 1874141Smax.romanov@nginx.com 1875141Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, rc, rc->app_port->mem_pool); 1876141Smax.romanov@nginx.com 1877141Smax.romanov@nginx.com return; 1878141Smax.romanov@nginx.com } 1879141Smax.romanov@nginx.com 1880141Smax.romanov@nginx.com nxt_debug(task, "app requests queue is empty"); 1881141Smax.romanov@nginx.com 1882141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1883141Smax.romanov@nginx.com 1884141Smax.romanov@nginx.com nxt_queue_insert_head(&app->ports, &port->app_link); 1885141Smax.romanov@nginx.com 1886141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1887141Smax.romanov@nginx.com } 1888141Smax.romanov@nginx.com 1889141Smax.romanov@nginx.com 1890141Smax.romanov@nginx.com void 1891141Smax.romanov@nginx.com nxt_router_app_remove_port(nxt_port_t *port) 1892141Smax.romanov@nginx.com { 1893141Smax.romanov@nginx.com nxt_app_t *app; 1894141Smax.romanov@nginx.com 1895141Smax.romanov@nginx.com if (port->app_link.next == NULL) { 1896141Smax.romanov@nginx.com return; 1897141Smax.romanov@nginx.com } 1898141Smax.romanov@nginx.com 1899141Smax.romanov@nginx.com app = port->app; 1900141Smax.romanov@nginx.com 1901141Smax.romanov@nginx.com #if (NXT_DEBUG) 1902141Smax.romanov@nginx.com if (nxt_slow_path(app == NULL)) { 1903141Smax.romanov@nginx.com nxt_abort(); 1904141Smax.romanov@nginx.com } 1905141Smax.romanov@nginx.com #endif 1906141Smax.romanov@nginx.com 1907141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1908141Smax.romanov@nginx.com 1909141Smax.romanov@nginx.com nxt_queue_remove(&port->app_link); 1910141Smax.romanov@nginx.com port->app_link.next = NULL; 1911141Smax.romanov@nginx.com 1912141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1913141Smax.romanov@nginx.com } 1914141Smax.romanov@nginx.com 1915141Smax.romanov@nginx.com 1916141Smax.romanov@nginx.com nxt_inline nxt_int_t 1917141Smax.romanov@nginx.com nxt_router_app_port(nxt_task_t *task, nxt_req_conn_link_t *rc) 1918141Smax.romanov@nginx.com { 1919141Smax.romanov@nginx.com nxt_app_t *app; 1920141Smax.romanov@nginx.com nxt_conn_t *c; 1921141Smax.romanov@nginx.com nxt_port_t *port, *master_port; 1922141Smax.romanov@nginx.com nxt_runtime_t *rt; 1923141Smax.romanov@nginx.com nxt_start_worker_t *sw; 1924141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 1925141Smax.romanov@nginx.com 1926141Smax.romanov@nginx.com port = NULL; 1927141Smax.romanov@nginx.com c = rc->conn; 1928141Smax.romanov@nginx.com 1929141Smax.romanov@nginx.com joint = c->listen->socket.data; 1930141Smax.romanov@nginx.com app = joint->socket_conf->application; 1931141Smax.romanov@nginx.com 1932141Smax.romanov@nginx.com 1933141Smax.romanov@nginx.com if (app == NULL) { 1934141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 1935141Smax.romanov@nginx.com "Application is NULL in socket_conf"); 1936141Smax.romanov@nginx.com return NXT_ERROR; 1937141Smax.romanov@nginx.com } 1938141Smax.romanov@nginx.com 1939141Smax.romanov@nginx.com 1940141Smax.romanov@nginx.com port = nxt_router_app_get_port(app); 1941141Smax.romanov@nginx.com 1942141Smax.romanov@nginx.com if (port != NULL) { 1943141Smax.romanov@nginx.com rc->app_port = port; 1944141Smax.romanov@nginx.com return NXT_OK; 1945141Smax.romanov@nginx.com } 1946141Smax.romanov@nginx.com 1947141Smax.romanov@nginx.com 1948141Smax.romanov@nginx.com sw = nxt_mp_retain(c->mem_pool, sizeof(nxt_start_worker_t)); 1949141Smax.romanov@nginx.com 1950141Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 1951141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 1952141Smax.romanov@nginx.com "Failed to allocate start worker struct"); 1953141Smax.romanov@nginx.com return NXT_ERROR; 1954141Smax.romanov@nginx.com } 1955141Smax.romanov@nginx.com 1956141Smax.romanov@nginx.com nxt_memzero(sw, sizeof(nxt_start_worker_t)); 1957141Smax.romanov@nginx.com 1958141Smax.romanov@nginx.com sw->stream = nxt_random(&task->thread->random); 1959141Smax.romanov@nginx.com sw->app = app; 1960141Smax.romanov@nginx.com sw->rc = rc; 1961141Smax.romanov@nginx.com sw->mem_pool = c->mem_pool; 1962141Smax.romanov@nginx.com sw->joint = c->listen->socket.data; 1963141Smax.romanov@nginx.com 1964141Smax.romanov@nginx.com sw->work.handler = nxt_router_send_sw_request; 1965141Smax.romanov@nginx.com sw->work.task = task; 1966141Smax.romanov@nginx.com sw->work.obj = sw; 1967141Smax.romanov@nginx.com sw->work.data = task->thread->engine; 1968141Smax.romanov@nginx.com 1969141Smax.romanov@nginx.com rt = task->thread->runtime; 1970141Smax.romanov@nginx.com 1971141Smax.romanov@nginx.com master_port = rt->port_by_type[NXT_PROCESS_MASTER]; 1972141Smax.romanov@nginx.com 1973141Smax.romanov@nginx.com nxt_debug(task, "post send sw %uxD to master engine %p", sw->stream, 1974141Smax.romanov@nginx.com master_port->engine); 1975141Smax.romanov@nginx.com 1976141Smax.romanov@nginx.com nxt_event_engine_post(master_port->engine, &sw->work); 1977141Smax.romanov@nginx.com 1978141Smax.romanov@nginx.com return NXT_AGAIN; 197988Smax.romanov@nginx.com } 198088Smax.romanov@nginx.com 198188Smax.romanov@nginx.com 198288Smax.romanov@nginx.com static void 198353Sigor@sysoev.ru nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, void *data) 198453Sigor@sysoev.ru { 198588Smax.romanov@nginx.com size_t size, preread; 198653Sigor@sysoev.ru nxt_int_t ret; 198753Sigor@sysoev.ru nxt_buf_t *b; 198862Sigor@sysoev.ru nxt_conn_t *c; 198988Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 199053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 199188Smax.romanov@nginx.com nxt_app_request_header_t *h; 199253Sigor@sysoev.ru 199353Sigor@sysoev.ru c = obj; 199488Smax.romanov@nginx.com ap = data; 199588Smax.romanov@nginx.com b = c->read; 199653Sigor@sysoev.ru 199753Sigor@sysoev.ru nxt_debug(task, "router conn http header parse"); 199853Sigor@sysoev.ru 199988Smax.romanov@nginx.com if (ap == NULL) { 200088Smax.romanov@nginx.com ap = nxt_mp_zget(c->mem_pool, sizeof(nxt_app_parse_ctx_t)); 200188Smax.romanov@nginx.com if (nxt_slow_path(ap == NULL)) { 200253Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 200353Sigor@sysoev.ru return; 200453Sigor@sysoev.ru } 200553Sigor@sysoev.ru 200688Smax.romanov@nginx.com ret = nxt_app_http_req_init(task, ap); 200761Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 200861Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 200961Sigor@sysoev.ru return; 201061Sigor@sysoev.ru } 201188Smax.romanov@nginx.com 201288Smax.romanov@nginx.com c->socket.data = ap; 2013113Smax.romanov@nginx.com 2014113Smax.romanov@nginx.com ap->r.remote.start = nxt_sockaddr_address(c->remote); 2015113Smax.romanov@nginx.com ap->r.remote.length = c->remote->address_length; 201653Sigor@sysoev.ru } 201753Sigor@sysoev.ru 201888Smax.romanov@nginx.com h = &ap->r.header; 201988Smax.romanov@nginx.com 202088Smax.romanov@nginx.com ret = nxt_app_http_req_parse(task, ap, b); 202153Sigor@sysoev.ru 202253Sigor@sysoev.ru nxt_debug(task, "http parse request: %d", ret); 202353Sigor@sysoev.ru 202453Sigor@sysoev.ru switch (nxt_expect(NXT_DONE, ret)) { 202553Sigor@sysoev.ru 202653Sigor@sysoev.ru case NXT_DONE: 202788Smax.romanov@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 202888Smax.romanov@nginx.com 202988Smax.romanov@nginx.com nxt_debug(task, "router request header parsing complete, " 203088Smax.romanov@nginx.com "content length: %O, preread: %uz", 203188Smax.romanov@nginx.com h->parsed_content_length, preread); 203288Smax.romanov@nginx.com 203388Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 203488Smax.romanov@nginx.com return; 203553Sigor@sysoev.ru 203653Sigor@sysoev.ru case NXT_ERROR: 203753Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 203853Sigor@sysoev.ru return; 203953Sigor@sysoev.ru 204053Sigor@sysoev.ru default: /* NXT_AGAIN */ 204153Sigor@sysoev.ru 204288Smax.romanov@nginx.com if (h->done == 0) { 204388Smax.romanov@nginx.com 204488Smax.romanov@nginx.com if (c->read->mem.free == c->read->mem.end) { 204588Smax.romanov@nginx.com joint = c->listen->socket.data; 204688Smax.romanov@nginx.com size = joint->socket_conf->large_header_buffer_size; 204788Smax.romanov@nginx.com 204888Smax.romanov@nginx.com if (size > (size_t) nxt_buf_mem_size(&b->mem)) { 204988Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 205088Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 205188Smax.romanov@nginx.com nxt_router_conn_close(task, c, data); 205288Smax.romanov@nginx.com return; 205388Smax.romanov@nginx.com } 205488Smax.romanov@nginx.com 205588Smax.romanov@nginx.com size = c->read->mem.free - c->read->mem.pos; 2056141Smax.romanov@nginx.com 2057141Smax.romanov@nginx.com c->read = nxt_buf_cpy(b, c->read->mem.pos, size); 205888Smax.romanov@nginx.com } else { 2059141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 400, 2060141Smax.romanov@nginx.com "Too long request headers"); 2061141Smax.romanov@nginx.com return; 206288Smax.romanov@nginx.com } 206388Smax.romanov@nginx.com } 206488Smax.romanov@nginx.com } 206588Smax.romanov@nginx.com 206688Smax.romanov@nginx.com if (ap->r.body.done == 0) { 206788Smax.romanov@nginx.com 206888Smax.romanov@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 206988Smax.romanov@nginx.com 207088Smax.romanov@nginx.com if (h->parsed_content_length - preread > 207188Smax.romanov@nginx.com (size_t) nxt_buf_mem_free_size(&b->mem)) { 207288Smax.romanov@nginx.com 207388Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, h->parsed_content_length, 0); 207488Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 2075141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2076141Smax.romanov@nginx.com "buffer for request body"); 2077141Smax.romanov@nginx.com return; 207888Smax.romanov@nginx.com } 207988Smax.romanov@nginx.com 2080141Smax.romanov@nginx.com c->read = nxt_buf_cpy(b, c->read->mem.pos, preread); 208153Sigor@sysoev.ru } 208253Sigor@sysoev.ru 208388Smax.romanov@nginx.com nxt_debug(task, "router request body read again, rest: %uz", 208488Smax.romanov@nginx.com h->parsed_content_length - preread); 208553Sigor@sysoev.ru 208653Sigor@sysoev.ru } 208753Sigor@sysoev.ru 208888Smax.romanov@nginx.com } 208988Smax.romanov@nginx.com 209088Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 209188Smax.romanov@nginx.com } 209288Smax.romanov@nginx.com 209388Smax.romanov@nginx.com 209488Smax.romanov@nginx.com static void 209588Smax.romanov@nginx.com nxt_router_process_http_request(nxt_task_t *task, nxt_conn_t *c, 209688Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap) 209788Smax.romanov@nginx.com { 2098122Smax.romanov@nginx.com nxt_int_t res; 209988Smax.romanov@nginx.com nxt_req_id_t req_id; 210088Smax.romanov@nginx.com nxt_event_engine_t *engine; 210188Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 210288Smax.romanov@nginx.com 210388Smax.romanov@nginx.com engine = task->thread->engine; 210488Smax.romanov@nginx.com 210588Smax.romanov@nginx.com do { 2106138Sigor@sysoev.ru req_id = nxt_random(&task->thread->random); 210788Smax.romanov@nginx.com } while (nxt_event_engine_request_find(engine, req_id) != NULL); 210888Smax.romanov@nginx.com 210988Smax.romanov@nginx.com rc = nxt_conn_request_add(c, req_id); 2110122Smax.romanov@nginx.com 211188Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 2112141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2113141Smax.romanov@nginx.com "req->conn link"); 2114141Smax.romanov@nginx.com 2115141Smax.romanov@nginx.com return; 211688Smax.romanov@nginx.com } 211788Smax.romanov@nginx.com 211888Smax.romanov@nginx.com nxt_event_engine_request_add(engine, rc); 211988Smax.romanov@nginx.com 212088Smax.romanov@nginx.com nxt_debug(task, "req_id %uxD linked to conn %p at engine %p", 212188Smax.romanov@nginx.com req_id, c, engine); 212253Sigor@sysoev.ru 2123141Smax.romanov@nginx.com rc->reply_port = engine->port; 2124141Smax.romanov@nginx.com 2125141Smax.romanov@nginx.com res = nxt_router_app_port(task, rc); 2126141Smax.romanov@nginx.com 2127141Smax.romanov@nginx.com if (res != NXT_OK) { 2128141Smax.romanov@nginx.com return; 2129141Smax.romanov@nginx.com } 2130141Smax.romanov@nginx.com 2131141Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, rc, c->mem_pool); 2132141Smax.romanov@nginx.com } 2133141Smax.romanov@nginx.com 2134141Smax.romanov@nginx.com 2135141Smax.romanov@nginx.com static void 2136141Smax.romanov@nginx.com nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_conn_link_t *rc, 2137141Smax.romanov@nginx.com nxt_mp_t *mp) 2138141Smax.romanov@nginx.com { 2139141Smax.romanov@nginx.com nxt_mp_t *port_mp; 2140141Smax.romanov@nginx.com nxt_int_t res; 2141141Smax.romanov@nginx.com nxt_port_t *port, *c_port, *reply_port; 2142141Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 2143141Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2144141Smax.romanov@nginx.com 2145141Smax.romanov@nginx.com port = rc->app_port; 2146141Smax.romanov@nginx.com 2147141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 2148141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, "Application port not found"); 2149141Smax.romanov@nginx.com return; 2150141Smax.romanov@nginx.com } 2151141Smax.romanov@nginx.com 2152141Smax.romanov@nginx.com reply_port = rc->reply_port; 2153141Smax.romanov@nginx.com ap = rc->conn->socket.data; 2154141Smax.romanov@nginx.com 2155122Smax.romanov@nginx.com port_mp = port->mem_pool; 2156141Smax.romanov@nginx.com port->mem_pool = mp; 2157141Smax.romanov@nginx.com 2158141Smax.romanov@nginx.com c_port = nxt_process_connected_port_find(port->process, reply_port->pid, 2159141Smax.romanov@nginx.com reply_port->id); 2160141Smax.romanov@nginx.com if (nxt_slow_path(c_port != reply_port)) { 2161141Smax.romanov@nginx.com res = nxt_port_send_port(task, port, reply_port, 0); 2162122Smax.romanov@nginx.com 2163122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2164141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2165141Smax.romanov@nginx.com "Failed to send reply port to application"); 2166141Smax.romanov@nginx.com goto fail; 2167122Smax.romanov@nginx.com } 2168122Smax.romanov@nginx.com 2169141Smax.romanov@nginx.com nxt_process_connected_port_add(port->process, reply_port); 217088Smax.romanov@nginx.com } 217188Smax.romanov@nginx.com 217288Smax.romanov@nginx.com wmsg.port = port; 217388Smax.romanov@nginx.com wmsg.write = NULL; 217488Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 2175141Smax.romanov@nginx.com wmsg.stream = rc->req_id; 2176141Smax.romanov@nginx.com 2177141Smax.romanov@nginx.com res = rc->app_port->app->module->prepare_msg(task, &ap->r, &wmsg); 2178122Smax.romanov@nginx.com 2179122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2180141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2181141Smax.romanov@nginx.com "Failed to prepare message for application"); 2182141Smax.romanov@nginx.com goto fail; 2183122Smax.romanov@nginx.com } 218488Smax.romanov@nginx.com 218588Smax.romanov@nginx.com nxt_debug(task, "about to send %d bytes buffer to worker port %d", 218688Smax.romanov@nginx.com nxt_buf_used_size(wmsg.write), 218788Smax.romanov@nginx.com wmsg.port->socket.fd); 218888Smax.romanov@nginx.com 2189122Smax.romanov@nginx.com res = nxt_port_socket_write(task, wmsg.port, NXT_PORT_MSG_DATA, 2190141Smax.romanov@nginx.com -1, rc->req_id, reply_port->id, wmsg.write); 2191122Smax.romanov@nginx.com 2192122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2193141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2194141Smax.romanov@nginx.com "Failed to send message to application"); 2195141Smax.romanov@nginx.com goto fail; 2196122Smax.romanov@nginx.com } 2197122Smax.romanov@nginx.com 2198141Smax.romanov@nginx.com fail: 2199122Smax.romanov@nginx.com port->mem_pool = port_mp; 220053Sigor@sysoev.ru } 220153Sigor@sysoev.ru 220253Sigor@sysoev.ru 220362Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_close_state 220453Sigor@sysoev.ru nxt_aligned(64) = 220553Sigor@sysoev.ru { 220653Sigor@sysoev.ru .ready_handler = nxt_router_conn_free, 220753Sigor@sysoev.ru }; 220853Sigor@sysoev.ru 220953Sigor@sysoev.ru 221053Sigor@sysoev.ru static void 221188Smax.romanov@nginx.com nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data) 221288Smax.romanov@nginx.com { 221388Smax.romanov@nginx.com nxt_buf_t *b; 221488Smax.romanov@nginx.com nxt_bool_t last; 221588Smax.romanov@nginx.com nxt_conn_t *c; 221688Smax.romanov@nginx.com nxt_work_queue_t *wq; 221788Smax.romanov@nginx.com 221888Smax.romanov@nginx.com nxt_debug(task, "router conn ready %p", obj); 221988Smax.romanov@nginx.com 222088Smax.romanov@nginx.com c = obj; 222188Smax.romanov@nginx.com b = c->write; 222288Smax.romanov@nginx.com 222388Smax.romanov@nginx.com wq = &task->thread->engine->fast_work_queue; 222488Smax.romanov@nginx.com 222588Smax.romanov@nginx.com last = 0; 222688Smax.romanov@nginx.com 222788Smax.romanov@nginx.com while (b != NULL) { 222888Smax.romanov@nginx.com if (!nxt_buf_is_sync(b)) { 222988Smax.romanov@nginx.com if (nxt_buf_used_size(b) > 0) { 223088Smax.romanov@nginx.com break; 223188Smax.romanov@nginx.com } 223288Smax.romanov@nginx.com } 223388Smax.romanov@nginx.com 223488Smax.romanov@nginx.com if (nxt_buf_is_last(b)) { 223588Smax.romanov@nginx.com last = 1; 223688Smax.romanov@nginx.com } 223788Smax.romanov@nginx.com 223888Smax.romanov@nginx.com nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); 223988Smax.romanov@nginx.com 224088Smax.romanov@nginx.com b = b->next; 224188Smax.romanov@nginx.com } 224288Smax.romanov@nginx.com 224388Smax.romanov@nginx.com c->write = b; 224488Smax.romanov@nginx.com 224588Smax.romanov@nginx.com if (b != NULL) { 224688Smax.romanov@nginx.com nxt_debug(task, "router conn %p has more data to write", obj); 224788Smax.romanov@nginx.com 224888Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 224988Smax.romanov@nginx.com } else { 225088Smax.romanov@nginx.com nxt_debug(task, "router conn %p no more data to write, last = %d", obj, 225188Smax.romanov@nginx.com last); 225288Smax.romanov@nginx.com 225388Smax.romanov@nginx.com if (last != 0) { 225488Smax.romanov@nginx.com nxt_debug(task, "enqueue router conn close %p (ready handler)", c); 225588Smax.romanov@nginx.com 225688Smax.romanov@nginx.com nxt_work_queue_add(wq, nxt_router_conn_close, task, c, 225788Smax.romanov@nginx.com c->socket.data); 225888Smax.romanov@nginx.com } 225988Smax.romanov@nginx.com } 226088Smax.romanov@nginx.com } 226188Smax.romanov@nginx.com 226288Smax.romanov@nginx.com 226388Smax.romanov@nginx.com static void 226453Sigor@sysoev.ru nxt_router_conn_close(nxt_task_t *task, void *obj, void *data) 226553Sigor@sysoev.ru { 226662Sigor@sysoev.ru nxt_conn_t *c; 226753Sigor@sysoev.ru 226853Sigor@sysoev.ru c = obj; 226953Sigor@sysoev.ru 227053Sigor@sysoev.ru nxt_debug(task, "router conn close"); 227153Sigor@sysoev.ru 227253Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 227353Sigor@sysoev.ru 227462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 227553Sigor@sysoev.ru } 227653Sigor@sysoev.ru 227753Sigor@sysoev.ru 227853Sigor@sysoev.ru static void 227953Sigor@sysoev.ru nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) 228053Sigor@sysoev.ru { 228162Sigor@sysoev.ru nxt_conn_t *c; 228288Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 228353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 228453Sigor@sysoev.ru 228553Sigor@sysoev.ru c = obj; 228653Sigor@sysoev.ru 228753Sigor@sysoev.ru nxt_debug(task, "router conn close done"); 228853Sigor@sysoev.ru 228988Smax.romanov@nginx.com nxt_queue_each(rc, &c->requests, nxt_req_conn_link_t, link) { 229088Smax.romanov@nginx.com 229188Smax.romanov@nginx.com nxt_debug(task, "conn %p close, req %uxD", c, rc->req_id); 229288Smax.romanov@nginx.com 2293141Smax.romanov@nginx.com if (rc->app_port != NULL) { 2294141Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 2295141Smax.romanov@nginx.com 2296141Smax.romanov@nginx.com rc->app_port = NULL; 2297141Smax.romanov@nginx.com } 2298141Smax.romanov@nginx.com 229988Smax.romanov@nginx.com nxt_event_engine_request_remove(task->thread->engine, rc); 230088Smax.romanov@nginx.com 230188Smax.romanov@nginx.com } nxt_queue_loop; 230288Smax.romanov@nginx.com 2303122Smax.romanov@nginx.com nxt_queue_remove(&c->link); 2304122Smax.romanov@nginx.com 2305131Smax.romanov@nginx.com joint = c->listen->socket.data; 2306131Smax.romanov@nginx.com 2307131Smax.romanov@nginx.com task = &task->thread->engine->task; 2308131Smax.romanov@nginx.com 2309141Smax.romanov@nginx.com if (nxt_mp_release(c->mem_pool, c) == 0) { 2310141Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 2311141Smax.romanov@nginx.com } 231253Sigor@sysoev.ru } 231353Sigor@sysoev.ru 231453Sigor@sysoev.ru 231553Sigor@sysoev.ru static void 231653Sigor@sysoev.ru nxt_router_conn_error(nxt_task_t *task, void *obj, void *data) 231753Sigor@sysoev.ru { 231862Sigor@sysoev.ru nxt_conn_t *c; 231953Sigor@sysoev.ru 232053Sigor@sysoev.ru c = obj; 232153Sigor@sysoev.ru 232253Sigor@sysoev.ru nxt_debug(task, "router conn error"); 232353Sigor@sysoev.ru 232453Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 232553Sigor@sysoev.ru 232662Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 232753Sigor@sysoev.ru } 232853Sigor@sysoev.ru 232953Sigor@sysoev.ru 233053Sigor@sysoev.ru static void 233153Sigor@sysoev.ru nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) 233253Sigor@sysoev.ru { 233362Sigor@sysoev.ru nxt_conn_t *c; 233462Sigor@sysoev.ru nxt_timer_t *timer; 233553Sigor@sysoev.ru 233653Sigor@sysoev.ru timer = obj; 233753Sigor@sysoev.ru 233853Sigor@sysoev.ru nxt_debug(task, "router conn timeout"); 233953Sigor@sysoev.ru 234062Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 234153Sigor@sysoev.ru 234253Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 234353Sigor@sysoev.ru 234462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 234553Sigor@sysoev.ru } 234653Sigor@sysoev.ru 234753Sigor@sysoev.ru 234853Sigor@sysoev.ru static nxt_msec_t 234962Sigor@sysoev.ru nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 235053Sigor@sysoev.ru { 235153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 235253Sigor@sysoev.ru 235353Sigor@sysoev.ru joint = c->listen->socket.data; 235453Sigor@sysoev.ru 235553Sigor@sysoev.ru return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 235653Sigor@sysoev.ru } 2357141Smax.romanov@nginx.com 2358141Smax.romanov@nginx.com 2359141Smax.romanov@nginx.com static nxt_int_t 2360141Smax.romanov@nginx.com nxt_sw_test(nxt_lvlhsh_query_t *lhq, void *data) 2361141Smax.romanov@nginx.com { 2362141Smax.romanov@nginx.com return NXT_OK; 2363141Smax.romanov@nginx.com } 2364141Smax.romanov@nginx.com 2365141Smax.romanov@nginx.com 2366141Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t lvlhsh_sw_proto nxt_aligned(64) = { 2367141Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT, 2368141Smax.romanov@nginx.com nxt_sw_test, 2369141Smax.romanov@nginx.com nxt_lvlhsh_alloc, 2370141Smax.romanov@nginx.com nxt_lvlhsh_free, 2371141Smax.romanov@nginx.com }; 2372141Smax.romanov@nginx.com 2373141Smax.romanov@nginx.com 2374141Smax.romanov@nginx.com static void 2375141Smax.romanov@nginx.com nxt_router_sw_add(nxt_task_t *task, nxt_router_t *router, 2376141Smax.romanov@nginx.com nxt_start_worker_t *sw) 2377141Smax.romanov@nginx.com { 2378141Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 2379141Smax.romanov@nginx.com 2380141Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&sw->stream, sizeof(sw->stream)); 2381141Smax.romanov@nginx.com lhq.key.length = sizeof(sw->stream); 2382141Smax.romanov@nginx.com lhq.key.start = (u_char *) &sw->stream; 2383141Smax.romanov@nginx.com lhq.proto = &lvlhsh_sw_proto; 2384141Smax.romanov@nginx.com lhq.replace = 0; 2385141Smax.romanov@nginx.com lhq.value = sw; 2386141Smax.romanov@nginx.com lhq.pool = task->thread->runtime->mem_pool; 2387141Smax.romanov@nginx.com 2388141Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&router->start_workers, &lhq)) { 2389141Smax.romanov@nginx.com 2390141Smax.romanov@nginx.com case NXT_OK: 2391141Smax.romanov@nginx.com break; 2392141Smax.romanov@nginx.com 2393141Smax.romanov@nginx.com default: 2394141Smax.romanov@nginx.com nxt_log_error(NXT_LOG_WARN, task->log, "stream %08uxD sw add failed", 2395141Smax.romanov@nginx.com sw->stream); 2396141Smax.romanov@nginx.com break; 2397141Smax.romanov@nginx.com } 2398141Smax.romanov@nginx.com } 2399141Smax.romanov@nginx.com 2400141Smax.romanov@nginx.com 2401141Smax.romanov@nginx.com static nxt_start_worker_t * 2402141Smax.romanov@nginx.com nxt_router_sw_find_remove(nxt_task_t *task, nxt_router_t *router, uint32_t id) 2403141Smax.romanov@nginx.com { 2404141Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 2405141Smax.romanov@nginx.com 2406141Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&id, sizeof(id)); 2407141Smax.romanov@nginx.com lhq.key.length = sizeof(id); 2408141Smax.romanov@nginx.com lhq.key.start = (u_char *) &id; 2409141Smax.romanov@nginx.com lhq.proto = &lvlhsh_sw_proto; 2410141Smax.romanov@nginx.com lhq.pool = task->thread->runtime->mem_pool; 2411141Smax.romanov@nginx.com 2412141Smax.romanov@nginx.com switch (nxt_lvlhsh_delete(&router->start_workers, &lhq)) { 2413141Smax.romanov@nginx.com 2414141Smax.romanov@nginx.com case NXT_OK: 2415141Smax.romanov@nginx.com return lhq.value; 2416141Smax.romanov@nginx.com 2417141Smax.romanov@nginx.com default: 2418141Smax.romanov@nginx.com nxt_log_error(NXT_LOG_WARN, task->log, "stream %08uxD sw remove failed", 2419141Smax.romanov@nginx.com id); 2420141Smax.romanov@nginx.com break; 2421141Smax.romanov@nginx.com } 2422141Smax.romanov@nginx.com 2423141Smax.romanov@nginx.com return NULL; 2424141Smax.romanov@nginx.com } 2425