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 23*141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t; 24*141Smax.romanov@nginx.com 25*141Smax.romanov@nginx.com struct nxt_start_worker_s { 26*141Smax.romanov@nginx.com uint32_t stream; 27*141Smax.romanov@nginx.com nxt_app_t *app; 28*141Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 29*141Smax.romanov@nginx.com nxt_mp_t *mem_pool; 30*141Smax.romanov@nginx.com void *joint; 31*141Smax.romanov@nginx.com 32*141Smax.romanov@nginx.com nxt_work_t work; 33*141Smax.romanov@nginx.com }; 34*141Smax.romanov@nginx.com 35*141Smax.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 103*141Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app); 104*141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj, 105*141Smax.romanov@nginx.com void *data); 106*141Smax.romanov@nginx.com 107*141Smax.romanov@nginx.com static void nxt_router_sw_add(nxt_task_t *task, nxt_router_t *router, 108*141Smax.romanov@nginx.com nxt_start_worker_t *sw); 109*141Smax.romanov@nginx.com static nxt_start_worker_t *nxt_router_sw_find_remove(nxt_task_t *task, 110*141Smax.romanov@nginx.com nxt_router_t *router, uint32_t id); 111*141Smax.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); 117*141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task, 118*141Smax.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 126*141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 127*141Smax.romanov@nginx.com const char* fmt, ...); 128*141Smax.romanov@nginx.com 129119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 13020Sigor@sysoev.ru 13120Sigor@sysoev.ru nxt_int_t 132*141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 13320Sigor@sysoev.ru { 134*141Smax.romanov@nginx.com nxt_int_t ret; 135*141Smax.romanov@nginx.com nxt_router_t *router; 136*141Smax.romanov@nginx.com nxt_runtime_t *rt; 137*141Smax.romanov@nginx.com 138*141Smax.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 160*141Smax.romanov@nginx.com static void 161*141Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, void *obj, void *data) 162*141Smax.romanov@nginx.com { 163*141Smax.romanov@nginx.com nxt_start_worker_t *sw; 164*141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 165*141Smax.romanov@nginx.com 166*141Smax.romanov@nginx.com sw = obj; 167*141Smax.romanov@nginx.com joint = sw->joint; 168*141Smax.romanov@nginx.com 169*141Smax.romanov@nginx.com nxt_debug(task, "sw #%uxD release", sw->stream); 170*141Smax.romanov@nginx.com 171*141Smax.romanov@nginx.com if (nxt_mp_release(sw->mem_pool, sw) == 0) { 172*141Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 173*141Smax.romanov@nginx.com } 174*141Smax.romanov@nginx.com } 175*141Smax.romanov@nginx.com 176*141Smax.romanov@nginx.com 177*141Smax.romanov@nginx.com void 178*141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 179*141Smax.romanov@nginx.com { 180*141Smax.romanov@nginx.com nxt_start_worker_t *sw; 181*141Smax.romanov@nginx.com 182*141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 183*141Smax.romanov@nginx.com 184*141Smax.romanov@nginx.com if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) { 185*141Smax.romanov@nginx.com return; 186*141Smax.romanov@nginx.com } 187*141Smax.romanov@nginx.com 188*141Smax.romanov@nginx.com sw = nxt_router_sw_find_remove(task, nxt_router, msg->port_msg.stream); 189*141Smax.romanov@nginx.com 190*141Smax.romanov@nginx.com if (nxt_fast_path(sw != NULL)) { 191*141Smax.romanov@nginx.com msg->new_port->app = sw->app; 192*141Smax.romanov@nginx.com 193*141Smax.romanov@nginx.com nxt_router_app_release_port(task, msg->new_port, sw->app); 194*141Smax.romanov@nginx.com 195*141Smax.romanov@nginx.com sw->work.handler = nxt_router_sw_release; 196*141Smax.romanov@nginx.com 197*141Smax.romanov@nginx.com nxt_debug(task, "post sw #%uxD release to %p", sw->stream, 198*141Smax.romanov@nginx.com sw->work.data); 199*141Smax.romanov@nginx.com 200*141Smax.romanov@nginx.com nxt_event_engine_post(sw->work.data, &sw->work); 201*141Smax.romanov@nginx.com } 202*141Smax.romanov@nginx.com } 203*141Smax.romanov@nginx.com 204*141Smax.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 { 384139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 385139Sigor@sysoev.ru 386139Sigor@sysoev.ru nxt_router_conf_send(task, tmcf, (u_char *) "ERROR", 5); 387139Sigor@sysoev.ru } 388139Sigor@sysoev.ru 389139Sigor@sysoev.ru 390139Sigor@sysoev.ru static void 391139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 392139Sigor@sysoev.ru u_char *start, size_t size) 393139Sigor@sysoev.ru { 394139Sigor@sysoev.ru nxt_buf_t *b; 395139Sigor@sysoev.ru 396139Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 397139Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 398139Sigor@sysoev.ru return; 399139Sigor@sysoev.ru } 400139Sigor@sysoev.ru 401140Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, start, size); 402140Svbart@nginx.com 403139Sigor@sysoev.ru b->parent = tmcf->mem_pool; 404139Sigor@sysoev.ru b->completion_handler = nxt_router_conf_buf_completion; 405139Sigor@sysoev.ru 406139Sigor@sysoev.ru nxt_port_socket_write(task, tmcf->port, NXT_PORT_MSG_DATA, -1, 407139Sigor@sysoev.ru tmcf->stream, 0, b); 408139Sigor@sysoev.ru } 409139Sigor@sysoev.ru 410139Sigor@sysoev.ru 411139Sigor@sysoev.ru static void 412139Sigor@sysoev.ru nxt_router_conf_buf_completion(nxt_task_t *task, void *obj, void *data) 413139Sigor@sysoev.ru { 414139Sigor@sysoev.ru nxt_mp_t *mp; 415139Sigor@sysoev.ru 416139Sigor@sysoev.ru /* nxt_router_temp_conf_t mem pool. */ 417139Sigor@sysoev.ru mp = data; 418139Sigor@sysoev.ru 419139Sigor@sysoev.ru nxt_mp_destroy(mp); 420139Sigor@sysoev.ru } 421139Sigor@sysoev.ru 422139Sigor@sysoev.ru 423115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 424115Sigor@sysoev.ru { 425133Sigor@sysoev.ru nxt_string("listeners_threads"), 426115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 427115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 428115Sigor@sysoev.ru }, 429115Sigor@sysoev.ru }; 430115Sigor@sysoev.ru 431115Sigor@sysoev.ru 432133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 433115Sigor@sysoev.ru { 434133Sigor@sysoev.ru nxt_string("type"), 435115Sigor@sysoev.ru NXT_CONF_MAP_STR, 436133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 437115Sigor@sysoev.ru }, 438115Sigor@sysoev.ru 439115Sigor@sysoev.ru { 440133Sigor@sysoev.ru nxt_string("workers"), 441115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 442133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 443133Sigor@sysoev.ru }, 444133Sigor@sysoev.ru }; 445133Sigor@sysoev.ru 446133Sigor@sysoev.ru 447133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 448133Sigor@sysoev.ru { 449133Sigor@sysoev.ru nxt_string("application"), 450133Sigor@sysoev.ru NXT_CONF_MAP_STR, 451133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 452115Sigor@sysoev.ru }, 453115Sigor@sysoev.ru }; 454115Sigor@sysoev.ru 455115Sigor@sysoev.ru 456115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 457115Sigor@sysoev.ru { 458115Sigor@sysoev.ru nxt_string("header_buffer_size"), 459115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 460115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 461115Sigor@sysoev.ru }, 462115Sigor@sysoev.ru 463115Sigor@sysoev.ru { 464115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 465115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 466115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 467115Sigor@sysoev.ru }, 468115Sigor@sysoev.ru 469115Sigor@sysoev.ru { 470115Sigor@sysoev.ru nxt_string("header_read_timeout"), 471115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 472115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 473115Sigor@sysoev.ru }, 474115Sigor@sysoev.ru }; 475115Sigor@sysoev.ru 476115Sigor@sysoev.ru 47753Sigor@sysoev.ru static nxt_int_t 478115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 479115Sigor@sysoev.ru u_char *start, u_char *end) 48053Sigor@sysoev.ru { 481133Sigor@sysoev.ru u_char *p; 482133Sigor@sysoev.ru size_t size; 483115Sigor@sysoev.ru nxt_mp_t *mp; 484115Sigor@sysoev.ru uint32_t next; 485115Sigor@sysoev.ru nxt_int_t ret; 486115Sigor@sysoev.ru nxt_str_t name; 487133Sigor@sysoev.ru nxt_app_t *app, *prev; 488133Sigor@sysoev.ru nxt_app_type_t type; 489115Sigor@sysoev.ru nxt_sockaddr_t *sa; 490133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 491133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 492133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 493115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 494133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 495115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 496115Sigor@sysoev.ru 497115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 498133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 499115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 500115Sigor@sysoev.ru 501115Sigor@sysoev.ru conf = nxt_conf_json_parse(tmcf->mem_pool, start, end); 502115Sigor@sysoev.ru if (conf == NULL) { 503115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 504115Sigor@sysoev.ru return NXT_ERROR; 505115Sigor@sysoev.ru } 506115Sigor@sysoev.ru 507136Svbart@nginx.com ret = nxt_conf_map_object(conf, nxt_router_conf, 508136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 509115Sigor@sysoev.ru if (ret != NXT_OK) { 510133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 511115Sigor@sysoev.ru return NXT_ERROR; 512115Sigor@sysoev.ru } 513115Sigor@sysoev.ru 514117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 515117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 516117Sigor@sysoev.ru } 517117Sigor@sysoev.ru 518133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 519133Sigor@sysoev.ru if (applications == NULL) { 520133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 521115Sigor@sysoev.ru return NXT_ERROR; 522115Sigor@sysoev.ru } 523115Sigor@sysoev.ru 524133Sigor@sysoev.ru next = 0; 525133Sigor@sysoev.ru 526133Sigor@sysoev.ru for ( ;; ) { 527133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 528133Sigor@sysoev.ru if (application == NULL) { 529133Sigor@sysoev.ru break; 530133Sigor@sysoev.ru } 531133Sigor@sysoev.ru 532133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 533133Sigor@sysoev.ru 534133Sigor@sysoev.ru app = nxt_zalloc(sizeof(nxt_app_t)); 535133Sigor@sysoev.ru if (app == NULL) { 536133Sigor@sysoev.ru goto fail; 537133Sigor@sysoev.ru } 538133Sigor@sysoev.ru 539133Sigor@sysoev.ru size = nxt_conf_json_length(application, NULL); 540133Sigor@sysoev.ru 541133Sigor@sysoev.ru app->conf.start = nxt_malloc(size); 542133Sigor@sysoev.ru if (app->conf.start == NULL) { 543133Sigor@sysoev.ru nxt_free(app); 544133Sigor@sysoev.ru goto fail; 545133Sigor@sysoev.ru } 546133Sigor@sysoev.ru 547133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 548133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 549133Sigor@sysoev.ru 550133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 551133Sigor@sysoev.ru 552133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 553133Sigor@sysoev.ru 554133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 555133Sigor@sysoev.ru nxt_free(app->conf.start); 556133Sigor@sysoev.ru nxt_free(app); 557133Sigor@sysoev.ru 558133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 559133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 560133Sigor@sysoev.ru continue; 561133Sigor@sysoev.ru } 562133Sigor@sysoev.ru 563136Svbart@nginx.com ret = nxt_conf_map_object(application, nxt_router_app_conf, 564136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 565133Sigor@sysoev.ru if (ret != NXT_OK) { 566133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 567133Sigor@sysoev.ru goto app_fail; 568133Sigor@sysoev.ru } 569115Sigor@sysoev.ru 570133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 571133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 572133Sigor@sysoev.ru 573*141Smax.romanov@nginx.com type = nxt_app_parse_type(&apcf.type); 574*141Smax.romanov@nginx.com 575*141Smax.romanov@nginx.com if (type == NXT_APP_UNKNOWN) { 576*141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 577*141Smax.romanov@nginx.com &apcf.type); 578*141Smax.romanov@nginx.com goto app_fail; 579*141Smax.romanov@nginx.com } 580*141Smax.romanov@nginx.com 581*141Smax.romanov@nginx.com if (nxt_app_modules[type] == NULL) { 582133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 583133Sigor@sysoev.ru &apcf.type); 584133Sigor@sysoev.ru goto app_fail; 585133Sigor@sysoev.ru } 586133Sigor@sysoev.ru 587133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 588133Sigor@sysoev.ru if (ret != NXT_OK) { 589133Sigor@sysoev.ru goto app_fail; 590133Sigor@sysoev.ru } 591133Sigor@sysoev.ru 592*141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 593*141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 594*141Smax.romanov@nginx.com 595133Sigor@sysoev.ru app->name = name; 596133Sigor@sysoev.ru app->type = type; 597133Sigor@sysoev.ru app->max_workers = apcf.workers; 598133Sigor@sysoev.ru app->live = 1; 599*141Smax.romanov@nginx.com app->module = nxt_app_modules[type]; 600133Sigor@sysoev.ru 601133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 602133Sigor@sysoev.ru } 603133Sigor@sysoev.ru 604133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 605133Sigor@sysoev.ru #if 0 606133Sigor@sysoev.ru if (http == NULL) { 607133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 608133Sigor@sysoev.ru return NXT_ERROR; 609133Sigor@sysoev.ru } 610133Sigor@sysoev.ru #endif 611133Sigor@sysoev.ru 612133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 613115Sigor@sysoev.ru if (listeners == NULL) { 614133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 615115Sigor@sysoev.ru return NXT_ERROR; 616115Sigor@sysoev.ru } 61753Sigor@sysoev.ru 618133Sigor@sysoev.ru next = 0; 61953Sigor@sysoev.ru 620133Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 621115Sigor@sysoev.ru 622115Sigor@sysoev.ru for ( ;; ) { 623115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 624115Sigor@sysoev.ru if (listener == NULL) { 625115Sigor@sysoev.ru break; 626115Sigor@sysoev.ru } 62753Sigor@sysoev.ru 628115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 629115Sigor@sysoev.ru if (sa == NULL) { 630115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 631133Sigor@sysoev.ru goto fail; 632115Sigor@sysoev.ru } 633115Sigor@sysoev.ru 634115Sigor@sysoev.ru sa->type = SOCK_STREAM; 635115Sigor@sysoev.ru 636115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 637115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 63853Sigor@sysoev.ru 639115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 640115Sigor@sysoev.ru if (skcf == NULL) { 641133Sigor@sysoev.ru goto fail; 642115Sigor@sysoev.ru } 64353Sigor@sysoev.ru 644136Svbart@nginx.com ret = nxt_conf_map_object(listener, nxt_router_listener_conf, 645136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 646115Sigor@sysoev.ru if (ret != NXT_OK) { 647115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 648133Sigor@sysoev.ru goto fail; 649115Sigor@sysoev.ru } 65053Sigor@sysoev.ru 651133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 652133Sigor@sysoev.ru 653133Sigor@sysoev.ru // STUB, default values if http block is not defined. 654133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 655133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 656133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 65753Sigor@sysoev.ru 658133Sigor@sysoev.ru if (http != NULL) { 659136Svbart@nginx.com ret = nxt_conf_map_object(http, nxt_router_http_conf, 660136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 661133Sigor@sysoev.ru if (ret != NXT_OK) { 662133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 663133Sigor@sysoev.ru goto fail; 664133Sigor@sysoev.ru } 665115Sigor@sysoev.ru } 666115Sigor@sysoev.ru 667115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 668115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 669133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 670133Sigor@sysoev.ru &lscf.application); 671115Sigor@sysoev.ru 672115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 673115Sigor@sysoev.ru } 67453Sigor@sysoev.ru 67553Sigor@sysoev.ru return NXT_OK; 676133Sigor@sysoev.ru 677133Sigor@sysoev.ru app_fail: 678133Sigor@sysoev.ru 679133Sigor@sysoev.ru nxt_free(app->conf.start); 680133Sigor@sysoev.ru nxt_free(app); 681133Sigor@sysoev.ru 682133Sigor@sysoev.ru fail: 683133Sigor@sysoev.ru 684*141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 685*141Smax.romanov@nginx.com 686*141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 687133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 688133Sigor@sysoev.ru nxt_free(app); 689*141Smax.romanov@nginx.com 690*141Smax.romanov@nginx.com } nxt_queue_loop; 691133Sigor@sysoev.ru 692133Sigor@sysoev.ru return NXT_ERROR; 693133Sigor@sysoev.ru } 694133Sigor@sysoev.ru 695133Sigor@sysoev.ru 696133Sigor@sysoev.ru static nxt_app_t * 697133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 698133Sigor@sysoev.ru { 699*141Smax.romanov@nginx.com nxt_app_t *app; 700*141Smax.romanov@nginx.com 701*141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 702133Sigor@sysoev.ru 703133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 704133Sigor@sysoev.ru return app; 705133Sigor@sysoev.ru } 706*141Smax.romanov@nginx.com 707*141Smax.romanov@nginx.com } nxt_queue_loop; 708133Sigor@sysoev.ru 709133Sigor@sysoev.ru return NULL; 710133Sigor@sysoev.ru } 711133Sigor@sysoev.ru 712133Sigor@sysoev.ru 713133Sigor@sysoev.ru static nxt_app_t * 714133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 715133Sigor@sysoev.ru { 716133Sigor@sysoev.ru nxt_app_t *app; 717133Sigor@sysoev.ru 718133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 719133Sigor@sysoev.ru 720133Sigor@sysoev.ru if (app == NULL) { 721134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 722133Sigor@sysoev.ru } 723133Sigor@sysoev.ru 724133Sigor@sysoev.ru return app; 72553Sigor@sysoev.ru } 72653Sigor@sysoev.ru 72753Sigor@sysoev.ru 72853Sigor@sysoev.ru static nxt_socket_conf_t * 72965Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 73053Sigor@sysoev.ru { 73153Sigor@sysoev.ru nxt_socket_conf_t *conf; 73253Sigor@sysoev.ru 73365Sigor@sysoev.ru conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 73453Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) { 73553Sigor@sysoev.ru return NULL; 73653Sigor@sysoev.ru } 73753Sigor@sysoev.ru 738115Sigor@sysoev.ru conf->sockaddr = sa; 739115Sigor@sysoev.ru 74053Sigor@sysoev.ru conf->listen.sockaddr = sa; 741103Sigor@sysoev.ru conf->listen.socklen = sa->socklen; 742103Sigor@sysoev.ru conf->listen.address_length = sa->length; 74353Sigor@sysoev.ru 74453Sigor@sysoev.ru conf->listen.socket = -1; 74553Sigor@sysoev.ru conf->listen.backlog = NXT_LISTEN_BACKLOG; 74653Sigor@sysoev.ru conf->listen.flags = NXT_NONBLOCK; 74753Sigor@sysoev.ru conf->listen.read_after_accept = 1; 74853Sigor@sysoev.ru 74953Sigor@sysoev.ru return conf; 75053Sigor@sysoev.ru } 75153Sigor@sysoev.ru 75253Sigor@sysoev.ru 75353Sigor@sysoev.ru static void 75453Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 75553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 75653Sigor@sysoev.ru { 75753Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 75853Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 75953Sigor@sysoev.ru 76053Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 76153Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 76253Sigor@sysoev.ru nqlk = next) 76353Sigor@sysoev.ru { 76453Sigor@sysoev.ru next = nxt_queue_next(nqlk); 76553Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 76653Sigor@sysoev.ru 76753Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 76853Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 76953Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 77053Sigor@sysoev.ru { 77153Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 77253Sigor@sysoev.ru 773115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 774115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 775115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 776115Sigor@sysoev.ru 77753Sigor@sysoev.ru nxt_queue_remove(oqlk); 77853Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 77953Sigor@sysoev.ru 78053Sigor@sysoev.ru nxt_queue_remove(nqlk); 78153Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 78253Sigor@sysoev.ru 78353Sigor@sysoev.ru break; 78453Sigor@sysoev.ru } 78553Sigor@sysoev.ru } 78653Sigor@sysoev.ru } 78753Sigor@sysoev.ru 78853Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 789115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 79053Sigor@sysoev.ru } 79153Sigor@sysoev.ru 79253Sigor@sysoev.ru 79353Sigor@sysoev.ru static nxt_int_t 79453Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 79553Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 79653Sigor@sysoev.ru { 797115Sigor@sysoev.ru nxt_int_t ret; 798115Sigor@sysoev.ru nxt_socket_t s; 799115Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 800115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 801115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 80253Sigor@sysoev.ru 80353Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 80453Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 80553Sigor@sysoev.ru qlk = nqlk) 80653Sigor@sysoev.ru { 807115Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 808115Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 80953Sigor@sysoev.ru return NXT_ERROR; 81053Sigor@sysoev.ru } 81153Sigor@sysoev.ru 812115Sigor@sysoev.ru rtsk->count = 0; 813115Sigor@sysoev.ru 814115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 815115Sigor@sysoev.ru skcf->socket = rtsk; 816115Sigor@sysoev.ru 817115Sigor@sysoev.ru s = nxt_listen_socket_create0(task, skcf->sockaddr, NXT_NONBLOCK); 818115Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 819115Sigor@sysoev.ru return NXT_ERROR; 820115Sigor@sysoev.ru } 821115Sigor@sysoev.ru 822115Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 823115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 824115Sigor@sysoev.ru return NXT_ERROR; 825115Sigor@sysoev.ru } 826115Sigor@sysoev.ru 827115Sigor@sysoev.ru skcf->listen.socket = s; 828115Sigor@sysoev.ru 829115Sigor@sysoev.ru rtsk->fd = s; 830115Sigor@sysoev.ru 83153Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 83253Sigor@sysoev.ru nxt_queue_remove(qlk); 83353Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 83453Sigor@sysoev.ru } 83553Sigor@sysoev.ru 83653Sigor@sysoev.ru return NXT_OK; 83753Sigor@sysoev.ru } 83853Sigor@sysoev.ru 83953Sigor@sysoev.ru 84053Sigor@sysoev.ru static nxt_int_t 84153Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 84253Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 84353Sigor@sysoev.ru { 84453Sigor@sysoev.ru nxt_int_t ret; 84553Sigor@sysoev.ru nxt_uint_t n, threads; 84653Sigor@sysoev.ru nxt_queue_link_t *qlk; 84753Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 84853Sigor@sysoev.ru 84953Sigor@sysoev.ru threads = tmcf->conf->threads; 85053Sigor@sysoev.ru 85153Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 85253Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 85353Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 85453Sigor@sysoev.ru return NXT_ERROR; 85553Sigor@sysoev.ru } 85653Sigor@sysoev.ru 85753Sigor@sysoev.ru n = 0; 85853Sigor@sysoev.ru 85953Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 86053Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 86153Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 86253Sigor@sysoev.ru { 86353Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 86453Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 86553Sigor@sysoev.ru return NXT_ERROR; 86653Sigor@sysoev.ru } 86753Sigor@sysoev.ru 868115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 86953Sigor@sysoev.ru 87053Sigor@sysoev.ru if (n < threads) { 871115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 87253Sigor@sysoev.ru 87353Sigor@sysoev.ru } else { 874115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 87553Sigor@sysoev.ru } 87653Sigor@sysoev.ru 87753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 87853Sigor@sysoev.ru return ret; 87953Sigor@sysoev.ru } 88053Sigor@sysoev.ru 88153Sigor@sysoev.ru n++; 88253Sigor@sysoev.ru } 88353Sigor@sysoev.ru 88453Sigor@sysoev.ru tmcf->new_threads = n; 88553Sigor@sysoev.ru 88653Sigor@sysoev.ru while (n < threads) { 88753Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 88853Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 88953Sigor@sysoev.ru return NXT_ERROR; 89053Sigor@sysoev.ru } 89153Sigor@sysoev.ru 89253Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 89353Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 89453Sigor@sysoev.ru return NXT_ERROR; 89553Sigor@sysoev.ru } 89653Sigor@sysoev.ru 897115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 89853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 89953Sigor@sysoev.ru return ret; 90053Sigor@sysoev.ru } 90153Sigor@sysoev.ru 902115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 903115Sigor@sysoev.ru 90453Sigor@sysoev.ru n++; 90553Sigor@sysoev.ru } 90653Sigor@sysoev.ru 90753Sigor@sysoev.ru return NXT_OK; 90853Sigor@sysoev.ru } 90953Sigor@sysoev.ru 91053Sigor@sysoev.ru 91153Sigor@sysoev.ru static nxt_int_t 912115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 913115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 91453Sigor@sysoev.ru { 915115Sigor@sysoev.ru nxt_mp_t *mp; 916115Sigor@sysoev.ru nxt_int_t ret; 917115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 91853Sigor@sysoev.ru 91953Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 92053Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 92153Sigor@sysoev.ru return NXT_ERROR; 92253Sigor@sysoev.ru } 92353Sigor@sysoev.ru 924115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 925115Sigor@sysoev.ru 926139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 927115Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 928115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 929115Sigor@sysoev.ru return ret; 930115Sigor@sysoev.ru } 931115Sigor@sysoev.ru 932139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 93353Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 93453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 93553Sigor@sysoev.ru return ret; 93653Sigor@sysoev.ru } 93753Sigor@sysoev.ru 938115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 939115Sigor@sysoev.ru 940115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 941115Sigor@sysoev.ru 942115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 943115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 944115Sigor@sysoev.ru 945115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 946115Sigor@sysoev.ru 947115Sigor@sysoev.ru return ret; 94853Sigor@sysoev.ru } 94953Sigor@sysoev.ru 95053Sigor@sysoev.ru 95153Sigor@sysoev.ru static nxt_int_t 952115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 953115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 95453Sigor@sysoev.ru { 955115Sigor@sysoev.ru nxt_mp_t *mp; 956115Sigor@sysoev.ru nxt_int_t ret; 957115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 95853Sigor@sysoev.ru 95953Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 96053Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 96153Sigor@sysoev.ru return NXT_ERROR; 96253Sigor@sysoev.ru } 96353Sigor@sysoev.ru 964115Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 965115Sigor@sysoev.ru 966139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->creating, 96753Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 96853Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 96953Sigor@sysoev.ru return ret; 97053Sigor@sysoev.ru } 97153Sigor@sysoev.ru 97253Sigor@sysoev.ru recf->updating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 97353Sigor@sysoev.ru if (nxt_slow_path(recf->updating == NULL)) { 97453Sigor@sysoev.ru return NXT_ERROR; 97553Sigor@sysoev.ru } 97653Sigor@sysoev.ru 977139Sigor@sysoev.ru ret = nxt_router_engine_joints_create(mp, tmcf, recf, &tmcf->updating, 97853Sigor@sysoev.ru recf->updating, nxt_router_listen_socket_update); 97953Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 98053Sigor@sysoev.ru return ret; 98153Sigor@sysoev.ru } 98253Sigor@sysoev.ru 98353Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 98453Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 98553Sigor@sysoev.ru return NXT_ERROR; 98653Sigor@sysoev.ru } 98753Sigor@sysoev.ru 988139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 989115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 990115Sigor@sysoev.ru return ret; 991115Sigor@sysoev.ru } 992115Sigor@sysoev.ru 993115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 994115Sigor@sysoev.ru 995115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 996115Sigor@sysoev.ru 997115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 998115Sigor@sysoev.ru 999115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1000115Sigor@sysoev.ru 1001115Sigor@sysoev.ru return ret; 100253Sigor@sysoev.ru } 100353Sigor@sysoev.ru 100453Sigor@sysoev.ru 100553Sigor@sysoev.ru static nxt_int_t 1006115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 1007115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 100853Sigor@sysoev.ru { 100953Sigor@sysoev.ru nxt_int_t ret; 101053Sigor@sysoev.ru 101153Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 101253Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 101353Sigor@sysoev.ru return NXT_ERROR; 101453Sigor@sysoev.ru } 101553Sigor@sysoev.ru 1016139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 101753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 101853Sigor@sysoev.ru return ret; 101953Sigor@sysoev.ru } 102053Sigor@sysoev.ru 1021139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 102253Sigor@sysoev.ru } 102353Sigor@sysoev.ru 102453Sigor@sysoev.ru 102553Sigor@sysoev.ru static nxt_int_t 1026139Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_mp_t *mp, nxt_router_temp_conf_t *tmcf, 1027139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array, 102853Sigor@sysoev.ru nxt_work_handler_t handler) 102953Sigor@sysoev.ru { 1030139Sigor@sysoev.ru nxt_work_t *work, *back; 103153Sigor@sysoev.ru nxt_queue_link_t *qlk; 103253Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 103353Sigor@sysoev.ru 103453Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 103553Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 103653Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 103753Sigor@sysoev.ru { 1038139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 1039139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 1040139Sigor@sysoev.ru return NXT_ERROR; 1041139Sigor@sysoev.ru } 1042139Sigor@sysoev.ru 1043139Sigor@sysoev.ru back->next = NULL; 1044139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 1045139Sigor@sysoev.ru back->task = &tmcf->engine->task; 1046139Sigor@sysoev.ru back->obj = tmcf; 1047139Sigor@sysoev.ru back->data = NULL; 1048139Sigor@sysoev.ru 104953Sigor@sysoev.ru work = nxt_array_add(array); 105053Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 105153Sigor@sysoev.ru return NXT_ERROR; 105253Sigor@sysoev.ru } 105353Sigor@sysoev.ru 105453Sigor@sysoev.ru work->next = NULL; 105553Sigor@sysoev.ru work->handler = handler; 1056139Sigor@sysoev.ru work->task = &recf->engine->task; 1057139Sigor@sysoev.ru work->obj = back; 105853Sigor@sysoev.ru 105965Sigor@sysoev.ru joint = nxt_mp_alloc(mp, sizeof(nxt_socket_conf_joint_t)); 106053Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 106153Sigor@sysoev.ru return NXT_ERROR; 106253Sigor@sysoev.ru } 106353Sigor@sysoev.ru 106453Sigor@sysoev.ru work->data = joint; 106553Sigor@sysoev.ru 106653Sigor@sysoev.ru joint->count = 1; 106753Sigor@sysoev.ru joint->socket_conf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 106888Smax.romanov@nginx.com joint->engine = recf->engine; 1069115Sigor@sysoev.ru 1070115Sigor@sysoev.ru nxt_queue_insert_tail(&joint->engine->joints, &joint->link); 107153Sigor@sysoev.ru } 107253Sigor@sysoev.ru 107320Sigor@sysoev.ru return NXT_OK; 107420Sigor@sysoev.ru } 107520Sigor@sysoev.ru 107620Sigor@sysoev.ru 1077115Sigor@sysoev.ru static void 1078115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 1079115Sigor@sysoev.ru { 1080115Sigor@sysoev.ru nxt_queue_link_t *qlk; 1081115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1082115Sigor@sysoev.ru 1083115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 1084115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 1085115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 1086115Sigor@sysoev.ru { 1087115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1088115Sigor@sysoev.ru skcf->socket->count++; 1089115Sigor@sysoev.ru } 1090115Sigor@sysoev.ru } 1091115Sigor@sysoev.ru 1092115Sigor@sysoev.ru 109320Sigor@sysoev.ru static nxt_int_t 1094139Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 1095139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 109620Sigor@sysoev.ru { 1097139Sigor@sysoev.ru nxt_work_t *work, *back; 109853Sigor@sysoev.ru nxt_queue_link_t *qlk; 109920Sigor@sysoev.ru 110053Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 110153Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 110253Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 110353Sigor@sysoev.ru { 1104139Sigor@sysoev.ru back = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_work_t)); 1105139Sigor@sysoev.ru if (nxt_slow_path(back == NULL)) { 1106139Sigor@sysoev.ru return NXT_ERROR; 1107139Sigor@sysoev.ru } 1108139Sigor@sysoev.ru 1109139Sigor@sysoev.ru back->next = NULL; 1110139Sigor@sysoev.ru back->handler = nxt_router_conf_wait; 1111139Sigor@sysoev.ru back->task = &tmcf->engine->task; 1112139Sigor@sysoev.ru back->obj = tmcf; 1113139Sigor@sysoev.ru back->data = NULL; 1114139Sigor@sysoev.ru 1115115Sigor@sysoev.ru work = nxt_array_add(recf->deleting); 111653Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 111753Sigor@sysoev.ru return NXT_ERROR; 111853Sigor@sysoev.ru } 111920Sigor@sysoev.ru 112053Sigor@sysoev.ru work->next = NULL; 112153Sigor@sysoev.ru work->handler = nxt_router_listen_socket_delete; 1122139Sigor@sysoev.ru work->task = &recf->engine->task; 1123139Sigor@sysoev.ru work->obj = back; 112453Sigor@sysoev.ru work->data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 112520Sigor@sysoev.ru } 112620Sigor@sysoev.ru 112753Sigor@sysoev.ru return NXT_OK; 112853Sigor@sysoev.ru } 112920Sigor@sysoev.ru 113020Sigor@sysoev.ru 113153Sigor@sysoev.ru static nxt_int_t 113253Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 113353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 113453Sigor@sysoev.ru { 113553Sigor@sysoev.ru nxt_int_t ret; 113653Sigor@sysoev.ru nxt_uint_t i, threads; 113753Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 113820Sigor@sysoev.ru 113953Sigor@sysoev.ru recf = tmcf->engines->elts; 114053Sigor@sysoev.ru threads = tmcf->conf->threads; 114120Sigor@sysoev.ru 114253Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 114353Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 114453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 114553Sigor@sysoev.ru return ret; 114653Sigor@sysoev.ru } 114720Sigor@sysoev.ru } 114820Sigor@sysoev.ru 114920Sigor@sysoev.ru return NXT_OK; 115020Sigor@sysoev.ru } 115153Sigor@sysoev.ru 115253Sigor@sysoev.ru 115353Sigor@sysoev.ru static nxt_int_t 115453Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 115553Sigor@sysoev.ru nxt_event_engine_t *engine) 115653Sigor@sysoev.ru { 115753Sigor@sysoev.ru nxt_int_t ret; 115853Sigor@sysoev.ru nxt_thread_link_t *link; 115953Sigor@sysoev.ru nxt_thread_handle_t handle; 116053Sigor@sysoev.ru 116153Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 116253Sigor@sysoev.ru 116353Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 116453Sigor@sysoev.ru return NXT_ERROR; 116553Sigor@sysoev.ru } 116653Sigor@sysoev.ru 116753Sigor@sysoev.ru link->start = nxt_router_thread_start; 116853Sigor@sysoev.ru link->engine = engine; 116953Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 117053Sigor@sysoev.ru link->work.task = task; 117153Sigor@sysoev.ru link->work.data = link; 117253Sigor@sysoev.ru 117353Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 117453Sigor@sysoev.ru 117553Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 117653Sigor@sysoev.ru 117753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 117853Sigor@sysoev.ru nxt_queue_remove(&engine->link); 117953Sigor@sysoev.ru } 118053Sigor@sysoev.ru 118153Sigor@sysoev.ru return ret; 118253Sigor@sysoev.ru } 118353Sigor@sysoev.ru 118453Sigor@sysoev.ru 118553Sigor@sysoev.ru static void 1186133Sigor@sysoev.ru nxt_router_apps_sort(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 1187133Sigor@sysoev.ru { 1188*141Smax.romanov@nginx.com nxt_app_t *app; 1189*141Smax.romanov@nginx.com 1190*141Smax.romanov@nginx.com nxt_queue_each(app, &router->apps, nxt_app_t, link) { 1191133Sigor@sysoev.ru 1192133Sigor@sysoev.ru nxt_queue_remove(&app->link); 1193133Sigor@sysoev.ru 1194*141Smax.romanov@nginx.com // TODO RELEASE APP 1195*141Smax.romanov@nginx.com } nxt_queue_loop; 1196133Sigor@sysoev.ru 1197133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous); 1198133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps); 1199133Sigor@sysoev.ru } 1200133Sigor@sysoev.ru 1201133Sigor@sysoev.ru 1202133Sigor@sysoev.ru static void 120353Sigor@sysoev.ru nxt_router_engines_post(nxt_router_temp_conf_t *tmcf) 120453Sigor@sysoev.ru { 120553Sigor@sysoev.ru nxt_uint_t n; 120653Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 120753Sigor@sysoev.ru 120853Sigor@sysoev.ru recf = tmcf->engines->elts; 120953Sigor@sysoev.ru 121053Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 1211139Sigor@sysoev.ru nxt_router_engine_post(tmcf, recf); 121253Sigor@sysoev.ru recf++; 121353Sigor@sysoev.ru } 121453Sigor@sysoev.ru } 121553Sigor@sysoev.ru 121653Sigor@sysoev.ru 121753Sigor@sysoev.ru static void 1218139Sigor@sysoev.ru nxt_router_engine_post(nxt_router_temp_conf_t *tmcf, 1219139Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 122053Sigor@sysoev.ru { 122153Sigor@sysoev.ru nxt_uint_t n; 122253Sigor@sysoev.ru nxt_work_t *work; 122353Sigor@sysoev.ru 1224115Sigor@sysoev.ru if (recf->creating != NULL) { 1225115Sigor@sysoev.ru work = recf->creating->elts; 1226115Sigor@sysoev.ru 1227115Sigor@sysoev.ru for (n = recf->creating->nelts; n != 0; n--) { 1228115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1229115Sigor@sysoev.ru work++; 1230139Sigor@sysoev.ru tmcf->count++; 1231115Sigor@sysoev.ru } 1232115Sigor@sysoev.ru } 1233115Sigor@sysoev.ru 1234115Sigor@sysoev.ru if (recf->updating != NULL) { 1235115Sigor@sysoev.ru work = recf->updating->elts; 123653Sigor@sysoev.ru 1237115Sigor@sysoev.ru for (n = recf->updating->nelts; n != 0; n--) { 1238115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1239115Sigor@sysoev.ru work++; 1240139Sigor@sysoev.ru tmcf->count++; 1241115Sigor@sysoev.ru } 1242115Sigor@sysoev.ru } 1243115Sigor@sysoev.ru 1244115Sigor@sysoev.ru if (recf->deleting != NULL) { 1245115Sigor@sysoev.ru work = recf->deleting->elts; 1246115Sigor@sysoev.ru 1247115Sigor@sysoev.ru for (n = recf->deleting->nelts; n != 0; n--) { 1248115Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 1249115Sigor@sysoev.ru work++; 1250139Sigor@sysoev.ru tmcf->count++; 1251115Sigor@sysoev.ru } 125253Sigor@sysoev.ru } 125353Sigor@sysoev.ru } 125453Sigor@sysoev.ru 125553Sigor@sysoev.ru 125653Sigor@sysoev.ru static void 1257119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 125888Smax.romanov@nginx.com 1259119Smax.romanov@nginx.com static nxt_port_handler_t nxt_router_app_port_handlers[] = { 126088Smax.romanov@nginx.com NULL, 126188Smax.romanov@nginx.com nxt_port_new_port_handler, 126288Smax.romanov@nginx.com nxt_port_change_log_file_handler, 126388Smax.romanov@nginx.com nxt_port_mmap_handler, 1264119Smax.romanov@nginx.com nxt_router_app_data_handler, 1265125Smax.romanov@nginx.com nxt_port_remove_pid_handler, 126688Smax.romanov@nginx.com }; 126788Smax.romanov@nginx.com 126888Smax.romanov@nginx.com 126988Smax.romanov@nginx.com static void 127053Sigor@sysoev.ru nxt_router_thread_start(void *data) 127153Sigor@sysoev.ru { 1272*141Smax.romanov@nginx.com nxt_int_t ret; 1273*141Smax.romanov@nginx.com nxt_port_t *port; 127488Smax.romanov@nginx.com nxt_task_t *task; 127553Sigor@sysoev.ru nxt_thread_t *thread; 127653Sigor@sysoev.ru nxt_thread_link_t *link; 127753Sigor@sysoev.ru nxt_event_engine_t *engine; 127853Sigor@sysoev.ru 127953Sigor@sysoev.ru link = data; 128053Sigor@sysoev.ru engine = link->engine; 128188Smax.romanov@nginx.com task = &engine->task; 128253Sigor@sysoev.ru 128353Sigor@sysoev.ru thread = nxt_thread(); 128453Sigor@sysoev.ru 128553Sigor@sysoev.ru /* STUB */ 128653Sigor@sysoev.ru thread->runtime = engine->task.thread->runtime; 128753Sigor@sysoev.ru 128853Sigor@sysoev.ru engine->task.thread = thread; 128953Sigor@sysoev.ru engine->task.log = thread->log; 129053Sigor@sysoev.ru thread->engine = engine; 129163Sigor@sysoev.ru thread->task = &engine->task; 129253Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 129353Sigor@sysoev.ru 129463Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 129553Sigor@sysoev.ru 1296*141Smax.romanov@nginx.com port = nxt_mp_zalloc(engine->mem_pool, sizeof(nxt_port_t)); 1297*141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 1298*141Smax.romanov@nginx.com return; 1299*141Smax.romanov@nginx.com } 1300*141Smax.romanov@nginx.com 1301*141Smax.romanov@nginx.com port->id = nxt_port_get_next_id(); 1302*141Smax.romanov@nginx.com port->pid = nxt_pid; 1303*141Smax.romanov@nginx.com 1304*141Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0); 1305*141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 1306*141Smax.romanov@nginx.com return; 1307*141Smax.romanov@nginx.com } 1308*141Smax.romanov@nginx.com 1309*141Smax.romanov@nginx.com port->type = NXT_PROCESS_ROUTER; 1310*141Smax.romanov@nginx.com 1311*141Smax.romanov@nginx.com engine->port = port; 1312*141Smax.romanov@nginx.com 1313*141Smax.romanov@nginx.com nxt_port_enable(task, port, nxt_router_app_port_handlers); 1314*141Smax.romanov@nginx.com 131553Sigor@sysoev.ru nxt_event_engine_start(engine); 131653Sigor@sysoev.ru } 131753Sigor@sysoev.ru 131853Sigor@sysoev.ru 131953Sigor@sysoev.ru static void 132053Sigor@sysoev.ru nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 132153Sigor@sysoev.ru { 1322139Sigor@sysoev.ru nxt_work_t *work; 132353Sigor@sysoev.ru nxt_listen_event_t *listen; 132453Sigor@sysoev.ru nxt_listen_socket_t *ls; 1325139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 132653Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 132753Sigor@sysoev.ru 1328139Sigor@sysoev.ru work = obj; 132953Sigor@sysoev.ru joint = data; 133053Sigor@sysoev.ru 133153Sigor@sysoev.ru ls = &joint->socket_conf->listen; 133253Sigor@sysoev.ru 133353Sigor@sysoev.ru listen = nxt_listen_event(task, ls); 133453Sigor@sysoev.ru if (nxt_slow_path(listen == NULL)) { 133553Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 133653Sigor@sysoev.ru return; 133753Sigor@sysoev.ru } 133853Sigor@sysoev.ru 133953Sigor@sysoev.ru listen->socket.data = joint; 1340139Sigor@sysoev.ru 1341139Sigor@sysoev.ru tmcf = work->obj; 1342139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 134353Sigor@sysoev.ru } 134453Sigor@sysoev.ru 134553Sigor@sysoev.ru 134653Sigor@sysoev.ru nxt_inline nxt_listen_event_t * 134753Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections, 134853Sigor@sysoev.ru nxt_socket_conf_t *skcf) 134953Sigor@sysoev.ru { 1350115Sigor@sysoev.ru nxt_socket_t fd; 1351115Sigor@sysoev.ru nxt_queue_link_t *qlk; 135253Sigor@sysoev.ru nxt_listen_event_t *listen; 135353Sigor@sysoev.ru 1354115Sigor@sysoev.ru fd = skcf->socket->fd; 135553Sigor@sysoev.ru 1356115Sigor@sysoev.ru for (qlk = nxt_queue_first(listen_connections); 1357115Sigor@sysoev.ru qlk != nxt_queue_tail(listen_connections); 1358115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 135953Sigor@sysoev.ru { 1360115Sigor@sysoev.ru listen = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 136153Sigor@sysoev.ru 1362115Sigor@sysoev.ru if (fd == listen->socket.fd) { 136353Sigor@sysoev.ru return listen; 136453Sigor@sysoev.ru } 136553Sigor@sysoev.ru } 136653Sigor@sysoev.ru 136753Sigor@sysoev.ru return NULL; 136853Sigor@sysoev.ru } 136953Sigor@sysoev.ru 137053Sigor@sysoev.ru 137153Sigor@sysoev.ru static void 137253Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 137353Sigor@sysoev.ru { 1374139Sigor@sysoev.ru nxt_work_t *work; 137553Sigor@sysoev.ru nxt_event_engine_t *engine; 137653Sigor@sysoev.ru nxt_listen_event_t *listen; 1377139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 137853Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old; 137953Sigor@sysoev.ru 1380139Sigor@sysoev.ru work = obj; 138153Sigor@sysoev.ru joint = data; 138253Sigor@sysoev.ru 1383139Sigor@sysoev.ru engine = task->thread->engine; 1384139Sigor@sysoev.ru 138553Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, 138653Sigor@sysoev.ru joint->socket_conf); 138753Sigor@sysoev.ru 138853Sigor@sysoev.ru old = listen->socket.data; 138953Sigor@sysoev.ru listen->socket.data = joint; 139053Sigor@sysoev.ru 1391139Sigor@sysoev.ru tmcf = work->obj; 1392139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 1393139Sigor@sysoev.ru 139453Sigor@sysoev.ru nxt_router_conf_release(task, old); 139553Sigor@sysoev.ru } 139653Sigor@sysoev.ru 139753Sigor@sysoev.ru 139853Sigor@sysoev.ru static void 139953Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 140053Sigor@sysoev.ru { 1401139Sigor@sysoev.ru nxt_work_t *work; 1402139Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1403139Sigor@sysoev.ru nxt_listen_event_t *listen; 1404139Sigor@sysoev.ru nxt_event_engine_t *engine; 1405139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 1406139Sigor@sysoev.ru 1407139Sigor@sysoev.ru work = obj; 140853Sigor@sysoev.ru skcf = data; 140953Sigor@sysoev.ru 1410139Sigor@sysoev.ru engine = task->thread->engine; 1411139Sigor@sysoev.ru 141253Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, skcf); 141353Sigor@sysoev.ru 141453Sigor@sysoev.ru nxt_fd_event_delete(engine, &listen->socket); 141553Sigor@sysoev.ru 141653Sigor@sysoev.ru listen->timer.handler = nxt_router_listen_socket_close; 141753Sigor@sysoev.ru listen->timer.work_queue = &engine->fast_work_queue; 141853Sigor@sysoev.ru 141953Sigor@sysoev.ru nxt_timer_add(engine, &listen->timer, 0); 1420139Sigor@sysoev.ru 1421139Sigor@sysoev.ru tmcf = work->obj; 1422139Sigor@sysoev.ru nxt_event_engine_post(tmcf->engine, work); 142353Sigor@sysoev.ru } 142453Sigor@sysoev.ru 142553Sigor@sysoev.ru 142653Sigor@sysoev.ru static void 142753Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 142853Sigor@sysoev.ru { 142953Sigor@sysoev.ru nxt_timer_t *timer; 143053Sigor@sysoev.ru nxt_listen_event_t *listen; 143153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 143253Sigor@sysoev.ru 143353Sigor@sysoev.ru timer = obj; 143453Sigor@sysoev.ru listen = nxt_timer_data(timer, nxt_listen_event_t, timer); 143553Sigor@sysoev.ru joint = listen->socket.data; 143653Sigor@sysoev.ru 143753Sigor@sysoev.ru nxt_queue_remove(&listen->link); 1438123Smax.romanov@nginx.com 1439123Smax.romanov@nginx.com /* 'task' refers to listen->task and we cannot use after nxt_free() */ 1440123Smax.romanov@nginx.com task = &task->thread->engine->task; 1441123Smax.romanov@nginx.com 144253Sigor@sysoev.ru nxt_free(listen); 144353Sigor@sysoev.ru 144453Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 144553Sigor@sysoev.ru } 144653Sigor@sysoev.ru 144753Sigor@sysoev.ru 144853Sigor@sysoev.ru static void 144953Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, 145053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint) 145153Sigor@sysoev.ru { 1452118Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1453115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 145453Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 145553Sigor@sysoev.ru 1456118Sigor@sysoev.ru skcf = joint->socket_conf; 1457118Sigor@sysoev.ru rtsk = skcf->socket; 1458118Sigor@sysoev.ru lock = &skcf->router_conf->router->lock; 145953Sigor@sysoev.ru 146053Sigor@sysoev.ru nxt_thread_spin_lock(lock); 146153Sigor@sysoev.ru 1462115Sigor@sysoev.ru if (--rtsk->count != 0) { 1463115Sigor@sysoev.ru rtsk = NULL; 146453Sigor@sysoev.ru } 146553Sigor@sysoev.ru 146653Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 146753Sigor@sysoev.ru 1468115Sigor@sysoev.ru if (rtsk != NULL) { 1469115Sigor@sysoev.ru nxt_socket_close(task, rtsk->fd); 1470115Sigor@sysoev.ru nxt_free(rtsk); 1471118Sigor@sysoev.ru skcf->socket = NULL; 147253Sigor@sysoev.ru } 147353Sigor@sysoev.ru 147453Sigor@sysoev.ru nxt_router_conf_release(task, joint); 147553Sigor@sysoev.ru } 147653Sigor@sysoev.ru 147753Sigor@sysoev.ru 147853Sigor@sysoev.ru static void 147953Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 148053Sigor@sysoev.ru { 148153Sigor@sysoev.ru nxt_socket_conf_t *skcf; 148253Sigor@sysoev.ru nxt_router_conf_t *rtcf; 148353Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 148453Sigor@sysoev.ru 148553Sigor@sysoev.ru nxt_debug(task, "conf joint count: %D", joint->count); 148653Sigor@sysoev.ru 148753Sigor@sysoev.ru if (--joint->count != 0) { 148853Sigor@sysoev.ru return; 148953Sigor@sysoev.ru } 149053Sigor@sysoev.ru 149153Sigor@sysoev.ru nxt_queue_remove(&joint->link); 149253Sigor@sysoev.ru 149353Sigor@sysoev.ru skcf = joint->socket_conf; 149453Sigor@sysoev.ru rtcf = skcf->router_conf; 149553Sigor@sysoev.ru lock = &rtcf->router->lock; 149653Sigor@sysoev.ru 149753Sigor@sysoev.ru nxt_thread_spin_lock(lock); 149853Sigor@sysoev.ru 149953Sigor@sysoev.ru if (--skcf->count != 0) { 150053Sigor@sysoev.ru rtcf = NULL; 150153Sigor@sysoev.ru 150253Sigor@sysoev.ru } else { 150353Sigor@sysoev.ru nxt_queue_remove(&skcf->link); 150453Sigor@sysoev.ru 150553Sigor@sysoev.ru if (--rtcf->count != 0) { 150653Sigor@sysoev.ru rtcf = NULL; 150753Sigor@sysoev.ru } 150853Sigor@sysoev.ru } 150953Sigor@sysoev.ru 151053Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 151153Sigor@sysoev.ru 1512*141Smax.romanov@nginx.com /* TODO remove engine->port */ 1513*141Smax.romanov@nginx.com /* TODO excude from connected ports */ 1514*141Smax.romanov@nginx.com 151553Sigor@sysoev.ru if (rtcf != NULL) { 1516115Sigor@sysoev.ru nxt_debug(task, "old router conf is destroyed"); 1517131Smax.romanov@nginx.com 1518131Smax.romanov@nginx.com nxt_mp_thread_adopt(rtcf->mem_pool); 1519131Smax.romanov@nginx.com 152065Sigor@sysoev.ru nxt_mp_destroy(rtcf->mem_pool); 152153Sigor@sysoev.ru } 152253Sigor@sysoev.ru 152353Sigor@sysoev.ru if (nxt_queue_is_empty(&joint->engine->joints)) { 152453Sigor@sysoev.ru nxt_thread_exit(task->thread); 152553Sigor@sysoev.ru } 152653Sigor@sysoev.ru } 152753Sigor@sysoev.ru 152853Sigor@sysoev.ru 152953Sigor@sysoev.ru static void 153053Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 153153Sigor@sysoev.ru { 1532*141Smax.romanov@nginx.com nxt_port_t *port; 153353Sigor@sysoev.ru nxt_thread_link_t *link; 153453Sigor@sysoev.ru nxt_event_engine_t *engine; 153553Sigor@sysoev.ru nxt_thread_handle_t handle; 153653Sigor@sysoev.ru 153758Svbart@nginx.com handle = (nxt_thread_handle_t) obj; 153853Sigor@sysoev.ru link = data; 153953Sigor@sysoev.ru 154053Sigor@sysoev.ru nxt_thread_wait(handle); 154153Sigor@sysoev.ru 154253Sigor@sysoev.ru engine = link->engine; 154353Sigor@sysoev.ru 154453Sigor@sysoev.ru nxt_queue_remove(&engine->link); 154553Sigor@sysoev.ru 1546*141Smax.romanov@nginx.com port = engine->port; 1547*141Smax.romanov@nginx.com 1548*141Smax.romanov@nginx.com // TODO notify all apps 1549*141Smax.romanov@nginx.com 1550*141Smax.romanov@nginx.com if (port->pair[0] != -1) { 1551*141Smax.romanov@nginx.com nxt_fd_close(port->pair[0]); 1552*141Smax.romanov@nginx.com } 1553*141Smax.romanov@nginx.com 1554*141Smax.romanov@nginx.com if (port->pair[1] != -1) { 1555*141Smax.romanov@nginx.com nxt_fd_close(port->pair[1]); 1556*141Smax.romanov@nginx.com } 1557*141Smax.romanov@nginx.com 1558*141Smax.romanov@nginx.com if (port->mem_pool) { 1559*141Smax.romanov@nginx.com nxt_mp_destroy(port->mem_pool); 1560*141Smax.romanov@nginx.com } 1561*141Smax.romanov@nginx.com 156263Sigor@sysoev.ru nxt_mp_destroy(engine->mem_pool); 156353Sigor@sysoev.ru 156453Sigor@sysoev.ru nxt_event_engine_free(engine); 156553Sigor@sysoev.ru 156653Sigor@sysoev.ru nxt_free(link); 156753Sigor@sysoev.ru } 156853Sigor@sysoev.ru 156953Sigor@sysoev.ru 157062Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_read_state 157153Sigor@sysoev.ru nxt_aligned(64) = 157253Sigor@sysoev.ru { 157353Sigor@sysoev.ru .ready_handler = nxt_router_conn_http_header_parse, 157453Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 157553Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 157653Sigor@sysoev.ru 157753Sigor@sysoev.ru .timer_handler = nxt_router_conn_timeout, 157853Sigor@sysoev.ru .timer_value = nxt_router_conn_timeout_value, 157953Sigor@sysoev.ru .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 158053Sigor@sysoev.ru }; 158153Sigor@sysoev.ru 158253Sigor@sysoev.ru 158353Sigor@sysoev.ru static void 158453Sigor@sysoev.ru nxt_router_conn_init(nxt_task_t *task, void *obj, void *data) 158553Sigor@sysoev.ru { 158653Sigor@sysoev.ru size_t size; 158762Sigor@sysoev.ru nxt_conn_t *c; 158853Sigor@sysoev.ru nxt_event_engine_t *engine; 158953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 159053Sigor@sysoev.ru 159153Sigor@sysoev.ru c = obj; 159253Sigor@sysoev.ru joint = data; 159353Sigor@sysoev.ru 159453Sigor@sysoev.ru nxt_debug(task, "router conn init"); 159553Sigor@sysoev.ru 159653Sigor@sysoev.ru joint->count++; 159753Sigor@sysoev.ru 159853Sigor@sysoev.ru size = joint->socket_conf->header_buffer_size; 159953Sigor@sysoev.ru c->read = nxt_buf_mem_alloc(c->mem_pool, size, 0); 160053Sigor@sysoev.ru 160153Sigor@sysoev.ru c->socket.data = NULL; 160253Sigor@sysoev.ru 160353Sigor@sysoev.ru engine = task->thread->engine; 160453Sigor@sysoev.ru c->read_work_queue = &engine->fast_work_queue; 160553Sigor@sysoev.ru c->write_work_queue = &engine->fast_work_queue; 160653Sigor@sysoev.ru 160753Sigor@sysoev.ru c->read_state = &nxt_router_conn_read_state; 160853Sigor@sysoev.ru 160962Sigor@sysoev.ru nxt_conn_read(engine, c); 161053Sigor@sysoev.ru } 161153Sigor@sysoev.ru 161253Sigor@sysoev.ru 161362Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_write_state 161453Sigor@sysoev.ru nxt_aligned(64) = 161553Sigor@sysoev.ru { 161688Smax.romanov@nginx.com .ready_handler = nxt_router_conn_ready, 161753Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 161853Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 161953Sigor@sysoev.ru }; 162053Sigor@sysoev.ru 162153Sigor@sysoev.ru 162253Sigor@sysoev.ru static void 1623119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 162488Smax.romanov@nginx.com { 162588Smax.romanov@nginx.com size_t dump_size; 162688Smax.romanov@nginx.com nxt_buf_t *b, *i, *last; 162788Smax.romanov@nginx.com nxt_conn_t *c; 162888Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 162988Smax.romanov@nginx.com nxt_event_engine_t *engine; 163088Smax.romanov@nginx.com 163188Smax.romanov@nginx.com b = msg->buf; 163288Smax.romanov@nginx.com engine = task->thread->engine; 163388Smax.romanov@nginx.com 163488Smax.romanov@nginx.com rc = nxt_event_engine_request_find(engine, msg->port_msg.stream); 163588Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 163688Smax.romanov@nginx.com 163788Smax.romanov@nginx.com nxt_debug(task, "request id %08uxD not found", msg->port_msg.stream); 163888Smax.romanov@nginx.com 163995Smax.romanov@nginx.com /* Mark buffers as read. */ 164088Smax.romanov@nginx.com for (i = b; i != NULL; i = i->next) { 164188Smax.romanov@nginx.com i->mem.pos = i->mem.free; 164288Smax.romanov@nginx.com } 164388Smax.romanov@nginx.com 164488Smax.romanov@nginx.com return; 164588Smax.romanov@nginx.com } 164688Smax.romanov@nginx.com 164788Smax.romanov@nginx.com c = rc->conn; 164888Smax.romanov@nginx.com 164988Smax.romanov@nginx.com dump_size = nxt_buf_used_size(b); 165088Smax.romanov@nginx.com 165188Smax.romanov@nginx.com if (dump_size > 300) { 165288Smax.romanov@nginx.com dump_size = 300; 165388Smax.romanov@nginx.com } 165488Smax.romanov@nginx.com 1655119Smax.romanov@nginx.com nxt_debug(task, "%srouter app data (%z): %*s", 165688Smax.romanov@nginx.com msg->port_msg.last ? "last " : "", msg->size, dump_size, 165788Smax.romanov@nginx.com b->mem.pos); 165888Smax.romanov@nginx.com 165988Smax.romanov@nginx.com if (msg->size == 0) { 166088Smax.romanov@nginx.com b = NULL; 166188Smax.romanov@nginx.com } 166288Smax.romanov@nginx.com 166388Smax.romanov@nginx.com if (msg->port_msg.last != 0) { 166488Smax.romanov@nginx.com nxt_debug(task, "router data create last buf"); 166588Smax.romanov@nginx.com 166688Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 166788Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 166888Smax.romanov@nginx.com /* TODO pogorevaTb */ 166988Smax.romanov@nginx.com } 167088Smax.romanov@nginx.com 167188Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 167288Smax.romanov@nginx.com } 167388Smax.romanov@nginx.com 167488Smax.romanov@nginx.com if (b == NULL) { 167588Smax.romanov@nginx.com return; 167688Smax.romanov@nginx.com } 167788Smax.romanov@nginx.com 167888Smax.romanov@nginx.com if (c->write == NULL) { 167988Smax.romanov@nginx.com c->write = b; 168088Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 168188Smax.romanov@nginx.com 168288Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 168388Smax.romanov@nginx.com } else { 168488Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 168588Smax.romanov@nginx.com 168688Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 168788Smax.romanov@nginx.com } 168888Smax.romanov@nginx.com } 168988Smax.romanov@nginx.com 1690*141Smax.romanov@nginx.com nxt_inline const char * 1691*141Smax.romanov@nginx.com nxt_router_text_by_code(int code) 1692*141Smax.romanov@nginx.com { 1693*141Smax.romanov@nginx.com switch (code) { 1694*141Smax.romanov@nginx.com case 400: return "Bad request"; 1695*141Smax.romanov@nginx.com case 404: return "Not found"; 1696*141Smax.romanov@nginx.com case 403: return "Forbidden"; 1697*141Smax.romanov@nginx.com case 500: 1698*141Smax.romanov@nginx.com default: return "Internal server error"; 1699*141Smax.romanov@nginx.com } 1700*141Smax.romanov@nginx.com } 1701*141Smax.romanov@nginx.com 1702*141Smax.romanov@nginx.com static void 1703*141Smax.romanov@nginx.com nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 1704*141Smax.romanov@nginx.com const char* fmt, ...) 170588Smax.romanov@nginx.com { 1706*141Smax.romanov@nginx.com va_list args; 1707*141Smax.romanov@nginx.com nxt_buf_t *b, *last; 1708*141Smax.romanov@nginx.com const char *msg; 1709*141Smax.romanov@nginx.com 1710*141Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, 16384, 0); 1711*141Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 1712*141Smax.romanov@nginx.com /* TODO pogorevaTb */ 1713*141Smax.romanov@nginx.com } 1714*141Smax.romanov@nginx.com 1715*141Smax.romanov@nginx.com b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, 1716*141Smax.romanov@nginx.com "HTTP/1.0 %d %s\r\n" 1717*141Smax.romanov@nginx.com "Content-Type: text/plain\r\n" 1718*141Smax.romanov@nginx.com "Connection: close\r\n\r\n", 1719*141Smax.romanov@nginx.com code, nxt_router_text_by_code(code)); 1720*141Smax.romanov@nginx.com 1721*141Smax.romanov@nginx.com msg = (const char *) b->mem.free; 1722*141Smax.romanov@nginx.com 1723*141Smax.romanov@nginx.com va_start(args, fmt); 1724*141Smax.romanov@nginx.com b->mem.free = nxt_vsprintf(b->mem.free, b->mem.end, fmt, args); 1725*141Smax.romanov@nginx.com va_end(args); 1726*141Smax.romanov@nginx.com 1727*141Smax.romanov@nginx.com nxt_log_alert(task->log, "error %d: %s", code, msg); 1728*141Smax.romanov@nginx.com 1729*141Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 1730*141Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 1731*141Smax.romanov@nginx.com /* TODO pogorevaTb */ 1732*141Smax.romanov@nginx.com } 1733*141Smax.romanov@nginx.com 1734*141Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 1735*141Smax.romanov@nginx.com 1736*141Smax.romanov@nginx.com if (c->write == NULL) { 1737*141Smax.romanov@nginx.com c->write = b; 1738*141Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 1739*141Smax.romanov@nginx.com 1740*141Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 1741*141Smax.romanov@nginx.com } else { 1742*141Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 1743*141Smax.romanov@nginx.com 1744*141Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 1745*141Smax.romanov@nginx.com } 1746*141Smax.romanov@nginx.com } 1747*141Smax.romanov@nginx.com 1748*141Smax.romanov@nginx.com 1749*141Smax.romanov@nginx.com static void 1750*141Smax.romanov@nginx.com nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data) 1751*141Smax.romanov@nginx.com { 1752*141Smax.romanov@nginx.com nxt_buf_t *b; 1753*141Smax.romanov@nginx.com nxt_app_t *app; 1754*141Smax.romanov@nginx.com nxt_port_t *port; 1755*141Smax.romanov@nginx.com nxt_runtime_t *rt; 1756*141Smax.romanov@nginx.com nxt_start_worker_t *sw; 1757*141Smax.romanov@nginx.com 1758*141Smax.romanov@nginx.com sw = obj; 1759*141Smax.romanov@nginx.com app = sw->app; 1760*141Smax.romanov@nginx.com 1761*141Smax.romanov@nginx.com nxt_debug(task, "send sw #%uD", sw->stream); 1762*141Smax.romanov@nginx.com 1763*141Smax.romanov@nginx.com nxt_router_sw_add(task, nxt_router, sw); 1764*141Smax.romanov@nginx.com nxt_queue_insert_tail(&app->requests, &sw->rc->app_link); 176588Smax.romanov@nginx.com 1766119Smax.romanov@nginx.com rt = task->thread->runtime; 1767*141Smax.romanov@nginx.com port = rt->port_by_type[NXT_PROCESS_MASTER]; 1768*141Smax.romanov@nginx.com 1769*141Smax.romanov@nginx.com b = nxt_buf_mem_alloc(port->mem_pool, app->conf.length, 0); 1770*141Smax.romanov@nginx.com 1771*141Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 1772*141Smax.romanov@nginx.com 1773*141Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, -1, sw->stream, 0, b); 1774*141Smax.romanov@nginx.com } 1775*141Smax.romanov@nginx.com 1776*141Smax.romanov@nginx.com 1777*141Smax.romanov@nginx.com static nxt_port_t * 1778*141Smax.romanov@nginx.com nxt_router_app_get_port(nxt_app_t *app) 1779*141Smax.romanov@nginx.com { 1780*141Smax.romanov@nginx.com nxt_port_t *port; 1781*141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 1782*141Smax.romanov@nginx.com 1783*141Smax.romanov@nginx.com port = NULL; 1784*141Smax.romanov@nginx.com 1785*141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1786*141Smax.romanov@nginx.com 1787*141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->ports)) { 1788*141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->ports); 1789*141Smax.romanov@nginx.com nxt_queue_remove(lnk); 1790*141Smax.romanov@nginx.com 1791*141Smax.romanov@nginx.com lnk->next = NULL; 1792*141Smax.romanov@nginx.com 1793*141Smax.romanov@nginx.com port = nxt_queue_link_data(lnk, nxt_port_t, app_link); 1794*141Smax.romanov@nginx.com } 1795*141Smax.romanov@nginx.com 1796*141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1797*141Smax.romanov@nginx.com 1798*141Smax.romanov@nginx.com return port; 1799*141Smax.romanov@nginx.com } 1800*141Smax.romanov@nginx.com 1801*141Smax.romanov@nginx.com 1802*141Smax.romanov@nginx.com static void 1803*141Smax.romanov@nginx.com nxt_router_app_release_port(nxt_task_t *task, void *obj, void *data) 1804*141Smax.romanov@nginx.com { 1805*141Smax.romanov@nginx.com nxt_app_t *app; 1806*141Smax.romanov@nginx.com nxt_port_t *port; 1807*141Smax.romanov@nginx.com nxt_work_t *work; 1808*141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 1809*141Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 1810*141Smax.romanov@nginx.com 1811*141Smax.romanov@nginx.com port = obj; 1812*141Smax.romanov@nginx.com app = data; 1813*141Smax.romanov@nginx.com 1814*141Smax.romanov@nginx.com nxt_assert(app != NULL); 1815*141Smax.romanov@nginx.com nxt_assert(app == port->app); 1816*141Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 1817*141Smax.romanov@nginx.com 1818*141Smax.romanov@nginx.com 1819*141Smax.romanov@nginx.com if (task->thread->engine != port->engine) { 1820*141Smax.romanov@nginx.com work = (nxt_work_t *) (port + 1); 1821*141Smax.romanov@nginx.com 1822*141Smax.romanov@nginx.com nxt_debug(task, "post release port to engine %p", port->engine); 1823*141Smax.romanov@nginx.com 1824*141Smax.romanov@nginx.com work->next = NULL; 1825*141Smax.romanov@nginx.com work->handler = nxt_router_app_release_port; 1826*141Smax.romanov@nginx.com work->task = port->socket.task; 1827*141Smax.romanov@nginx.com work->obj = port; 1828*141Smax.romanov@nginx.com work->data = app; 1829*141Smax.romanov@nginx.com 1830*141Smax.romanov@nginx.com nxt_event_engine_post(port->engine, work); 1831*141Smax.romanov@nginx.com 1832*141Smax.romanov@nginx.com return; 1833*141Smax.romanov@nginx.com } 1834*141Smax.romanov@nginx.com 1835*141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 1836*141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 1837*141Smax.romanov@nginx.com nxt_queue_remove(lnk); 1838*141Smax.romanov@nginx.com 1839*141Smax.romanov@nginx.com rc = nxt_queue_link_data(lnk, nxt_req_conn_link_t, app_link); 1840*141Smax.romanov@nginx.com 1841*141Smax.romanov@nginx.com nxt_debug(task, "process request #%uxD", rc->req_id); 1842*141Smax.romanov@nginx.com 1843*141Smax.romanov@nginx.com rc->app_port = port; 1844*141Smax.romanov@nginx.com 1845*141Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, rc, rc->app_port->mem_pool); 1846*141Smax.romanov@nginx.com 1847*141Smax.romanov@nginx.com return; 1848*141Smax.romanov@nginx.com } 1849*141Smax.romanov@nginx.com 1850*141Smax.romanov@nginx.com nxt_debug(task, "app requests queue is empty"); 1851*141Smax.romanov@nginx.com 1852*141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1853*141Smax.romanov@nginx.com 1854*141Smax.romanov@nginx.com nxt_queue_insert_head(&app->ports, &port->app_link); 1855*141Smax.romanov@nginx.com 1856*141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1857*141Smax.romanov@nginx.com } 1858*141Smax.romanov@nginx.com 1859*141Smax.romanov@nginx.com 1860*141Smax.romanov@nginx.com void 1861*141Smax.romanov@nginx.com nxt_router_app_remove_port(nxt_port_t *port) 1862*141Smax.romanov@nginx.com { 1863*141Smax.romanov@nginx.com nxt_app_t *app; 1864*141Smax.romanov@nginx.com 1865*141Smax.romanov@nginx.com if (port->app_link.next == NULL) { 1866*141Smax.romanov@nginx.com return; 1867*141Smax.romanov@nginx.com } 1868*141Smax.romanov@nginx.com 1869*141Smax.romanov@nginx.com app = port->app; 1870*141Smax.romanov@nginx.com 1871*141Smax.romanov@nginx.com #if (NXT_DEBUG) 1872*141Smax.romanov@nginx.com if (nxt_slow_path(app == NULL)) { 1873*141Smax.romanov@nginx.com nxt_abort(); 1874*141Smax.romanov@nginx.com } 1875*141Smax.romanov@nginx.com #endif 1876*141Smax.romanov@nginx.com 1877*141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 1878*141Smax.romanov@nginx.com 1879*141Smax.romanov@nginx.com nxt_queue_remove(&port->app_link); 1880*141Smax.romanov@nginx.com port->app_link.next = NULL; 1881*141Smax.romanov@nginx.com 1882*141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 1883*141Smax.romanov@nginx.com } 1884*141Smax.romanov@nginx.com 1885*141Smax.romanov@nginx.com 1886*141Smax.romanov@nginx.com nxt_inline nxt_int_t 1887*141Smax.romanov@nginx.com nxt_router_app_port(nxt_task_t *task, nxt_req_conn_link_t *rc) 1888*141Smax.romanov@nginx.com { 1889*141Smax.romanov@nginx.com nxt_app_t *app; 1890*141Smax.romanov@nginx.com nxt_conn_t *c; 1891*141Smax.romanov@nginx.com nxt_port_t *port, *master_port; 1892*141Smax.romanov@nginx.com nxt_runtime_t *rt; 1893*141Smax.romanov@nginx.com nxt_start_worker_t *sw; 1894*141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 1895*141Smax.romanov@nginx.com 1896*141Smax.romanov@nginx.com port = NULL; 1897*141Smax.romanov@nginx.com c = rc->conn; 1898*141Smax.romanov@nginx.com 1899*141Smax.romanov@nginx.com joint = c->listen->socket.data; 1900*141Smax.romanov@nginx.com app = joint->socket_conf->application; 1901*141Smax.romanov@nginx.com 1902*141Smax.romanov@nginx.com 1903*141Smax.romanov@nginx.com if (app == NULL) { 1904*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 1905*141Smax.romanov@nginx.com "Application is NULL in socket_conf"); 1906*141Smax.romanov@nginx.com return NXT_ERROR; 1907*141Smax.romanov@nginx.com } 1908*141Smax.romanov@nginx.com 1909*141Smax.romanov@nginx.com 1910*141Smax.romanov@nginx.com port = nxt_router_app_get_port(app); 1911*141Smax.romanov@nginx.com 1912*141Smax.romanov@nginx.com if (port != NULL) { 1913*141Smax.romanov@nginx.com rc->app_port = port; 1914*141Smax.romanov@nginx.com return NXT_OK; 1915*141Smax.romanov@nginx.com } 1916*141Smax.romanov@nginx.com 1917*141Smax.romanov@nginx.com 1918*141Smax.romanov@nginx.com sw = nxt_mp_retain(c->mem_pool, sizeof(nxt_start_worker_t)); 1919*141Smax.romanov@nginx.com 1920*141Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 1921*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 1922*141Smax.romanov@nginx.com "Failed to allocate start worker struct"); 1923*141Smax.romanov@nginx.com return NXT_ERROR; 1924*141Smax.romanov@nginx.com } 1925*141Smax.romanov@nginx.com 1926*141Smax.romanov@nginx.com nxt_memzero(sw, sizeof(nxt_start_worker_t)); 1927*141Smax.romanov@nginx.com 1928*141Smax.romanov@nginx.com sw->stream = nxt_random(&task->thread->random); 1929*141Smax.romanov@nginx.com sw->app = app; 1930*141Smax.romanov@nginx.com sw->rc = rc; 1931*141Smax.romanov@nginx.com sw->mem_pool = c->mem_pool; 1932*141Smax.romanov@nginx.com sw->joint = c->listen->socket.data; 1933*141Smax.romanov@nginx.com 1934*141Smax.romanov@nginx.com sw->work.handler = nxt_router_send_sw_request; 1935*141Smax.romanov@nginx.com sw->work.task = task; 1936*141Smax.romanov@nginx.com sw->work.obj = sw; 1937*141Smax.romanov@nginx.com sw->work.data = task->thread->engine; 1938*141Smax.romanov@nginx.com 1939*141Smax.romanov@nginx.com rt = task->thread->runtime; 1940*141Smax.romanov@nginx.com 1941*141Smax.romanov@nginx.com master_port = rt->port_by_type[NXT_PROCESS_MASTER]; 1942*141Smax.romanov@nginx.com 1943*141Smax.romanov@nginx.com nxt_debug(task, "post send sw %uxD to master engine %p", sw->stream, 1944*141Smax.romanov@nginx.com master_port->engine); 1945*141Smax.romanov@nginx.com 1946*141Smax.romanov@nginx.com nxt_event_engine_post(master_port->engine, &sw->work); 1947*141Smax.romanov@nginx.com 1948*141Smax.romanov@nginx.com return NXT_AGAIN; 194988Smax.romanov@nginx.com } 195088Smax.romanov@nginx.com 195188Smax.romanov@nginx.com 195288Smax.romanov@nginx.com static void 195353Sigor@sysoev.ru nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, void *data) 195453Sigor@sysoev.ru { 195588Smax.romanov@nginx.com size_t size, preread; 195653Sigor@sysoev.ru nxt_int_t ret; 195753Sigor@sysoev.ru nxt_buf_t *b; 195862Sigor@sysoev.ru nxt_conn_t *c; 195988Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 196053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 196188Smax.romanov@nginx.com nxt_app_request_header_t *h; 196253Sigor@sysoev.ru 196353Sigor@sysoev.ru c = obj; 196488Smax.romanov@nginx.com ap = data; 196588Smax.romanov@nginx.com b = c->read; 196653Sigor@sysoev.ru 196753Sigor@sysoev.ru nxt_debug(task, "router conn http header parse"); 196853Sigor@sysoev.ru 196988Smax.romanov@nginx.com if (ap == NULL) { 197088Smax.romanov@nginx.com ap = nxt_mp_zget(c->mem_pool, sizeof(nxt_app_parse_ctx_t)); 197188Smax.romanov@nginx.com if (nxt_slow_path(ap == NULL)) { 197253Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 197353Sigor@sysoev.ru return; 197453Sigor@sysoev.ru } 197553Sigor@sysoev.ru 197688Smax.romanov@nginx.com ret = nxt_app_http_req_init(task, ap); 197761Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 197861Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 197961Sigor@sysoev.ru return; 198061Sigor@sysoev.ru } 198188Smax.romanov@nginx.com 198288Smax.romanov@nginx.com c->socket.data = ap; 1983113Smax.romanov@nginx.com 1984113Smax.romanov@nginx.com ap->r.remote.start = nxt_sockaddr_address(c->remote); 1985113Smax.romanov@nginx.com ap->r.remote.length = c->remote->address_length; 198653Sigor@sysoev.ru } 198753Sigor@sysoev.ru 198888Smax.romanov@nginx.com h = &ap->r.header; 198988Smax.romanov@nginx.com 199088Smax.romanov@nginx.com ret = nxt_app_http_req_parse(task, ap, b); 199153Sigor@sysoev.ru 199253Sigor@sysoev.ru nxt_debug(task, "http parse request: %d", ret); 199353Sigor@sysoev.ru 199453Sigor@sysoev.ru switch (nxt_expect(NXT_DONE, ret)) { 199553Sigor@sysoev.ru 199653Sigor@sysoev.ru case NXT_DONE: 199788Smax.romanov@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 199888Smax.romanov@nginx.com 199988Smax.romanov@nginx.com nxt_debug(task, "router request header parsing complete, " 200088Smax.romanov@nginx.com "content length: %O, preread: %uz", 200188Smax.romanov@nginx.com h->parsed_content_length, preread); 200288Smax.romanov@nginx.com 200388Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 200488Smax.romanov@nginx.com return; 200553Sigor@sysoev.ru 200653Sigor@sysoev.ru case NXT_ERROR: 200753Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 200853Sigor@sysoev.ru return; 200953Sigor@sysoev.ru 201053Sigor@sysoev.ru default: /* NXT_AGAIN */ 201153Sigor@sysoev.ru 201288Smax.romanov@nginx.com if (h->done == 0) { 201388Smax.romanov@nginx.com 201488Smax.romanov@nginx.com if (c->read->mem.free == c->read->mem.end) { 201588Smax.romanov@nginx.com joint = c->listen->socket.data; 201688Smax.romanov@nginx.com size = joint->socket_conf->large_header_buffer_size; 201788Smax.romanov@nginx.com 201888Smax.romanov@nginx.com if (size > (size_t) nxt_buf_mem_size(&b->mem)) { 201988Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 202088Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 202188Smax.romanov@nginx.com nxt_router_conn_close(task, c, data); 202288Smax.romanov@nginx.com return; 202388Smax.romanov@nginx.com } 202488Smax.romanov@nginx.com 202588Smax.romanov@nginx.com size = c->read->mem.free - c->read->mem.pos; 2026*141Smax.romanov@nginx.com 2027*141Smax.romanov@nginx.com c->read = nxt_buf_cpy(b, c->read->mem.pos, size); 202888Smax.romanov@nginx.com } else { 2029*141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 400, 2030*141Smax.romanov@nginx.com "Too long request headers"); 2031*141Smax.romanov@nginx.com return; 203288Smax.romanov@nginx.com } 203388Smax.romanov@nginx.com } 203488Smax.romanov@nginx.com } 203588Smax.romanov@nginx.com 203688Smax.romanov@nginx.com if (ap->r.body.done == 0) { 203788Smax.romanov@nginx.com 203888Smax.romanov@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 203988Smax.romanov@nginx.com 204088Smax.romanov@nginx.com if (h->parsed_content_length - preread > 204188Smax.romanov@nginx.com (size_t) nxt_buf_mem_free_size(&b->mem)) { 204288Smax.romanov@nginx.com 204388Smax.romanov@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, h->parsed_content_length, 0); 204488Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 2045*141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2046*141Smax.romanov@nginx.com "buffer for request body"); 2047*141Smax.romanov@nginx.com return; 204888Smax.romanov@nginx.com } 204988Smax.romanov@nginx.com 2050*141Smax.romanov@nginx.com c->read = nxt_buf_cpy(b, c->read->mem.pos, preread); 205153Sigor@sysoev.ru } 205253Sigor@sysoev.ru 205388Smax.romanov@nginx.com nxt_debug(task, "router request body read again, rest: %uz", 205488Smax.romanov@nginx.com h->parsed_content_length - preread); 205553Sigor@sysoev.ru 205653Sigor@sysoev.ru } 205753Sigor@sysoev.ru 205888Smax.romanov@nginx.com } 205988Smax.romanov@nginx.com 206088Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 206188Smax.romanov@nginx.com } 206288Smax.romanov@nginx.com 206388Smax.romanov@nginx.com 206488Smax.romanov@nginx.com static void 206588Smax.romanov@nginx.com nxt_router_process_http_request(nxt_task_t *task, nxt_conn_t *c, 206688Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap) 206788Smax.romanov@nginx.com { 2068122Smax.romanov@nginx.com nxt_int_t res; 206988Smax.romanov@nginx.com nxt_req_id_t req_id; 207088Smax.romanov@nginx.com nxt_event_engine_t *engine; 207188Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 207288Smax.romanov@nginx.com 207388Smax.romanov@nginx.com engine = task->thread->engine; 207488Smax.romanov@nginx.com 207588Smax.romanov@nginx.com do { 2076138Sigor@sysoev.ru req_id = nxt_random(&task->thread->random); 207788Smax.romanov@nginx.com } while (nxt_event_engine_request_find(engine, req_id) != NULL); 207888Smax.romanov@nginx.com 207988Smax.romanov@nginx.com rc = nxt_conn_request_add(c, req_id); 2080122Smax.romanov@nginx.com 208188Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 2082*141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2083*141Smax.romanov@nginx.com "req->conn link"); 2084*141Smax.romanov@nginx.com 2085*141Smax.romanov@nginx.com return; 208688Smax.romanov@nginx.com } 208788Smax.romanov@nginx.com 208888Smax.romanov@nginx.com nxt_event_engine_request_add(engine, rc); 208988Smax.romanov@nginx.com 209088Smax.romanov@nginx.com nxt_debug(task, "req_id %uxD linked to conn %p at engine %p", 209188Smax.romanov@nginx.com req_id, c, engine); 209253Sigor@sysoev.ru 2093*141Smax.romanov@nginx.com rc->reply_port = engine->port; 2094*141Smax.romanov@nginx.com 2095*141Smax.romanov@nginx.com res = nxt_router_app_port(task, rc); 2096*141Smax.romanov@nginx.com 2097*141Smax.romanov@nginx.com if (res != NXT_OK) { 2098*141Smax.romanov@nginx.com return; 2099*141Smax.romanov@nginx.com } 2100*141Smax.romanov@nginx.com 2101*141Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, rc, c->mem_pool); 2102*141Smax.romanov@nginx.com } 2103*141Smax.romanov@nginx.com 2104*141Smax.romanov@nginx.com 2105*141Smax.romanov@nginx.com static void 2106*141Smax.romanov@nginx.com nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_conn_link_t *rc, 2107*141Smax.romanov@nginx.com nxt_mp_t *mp) 2108*141Smax.romanov@nginx.com { 2109*141Smax.romanov@nginx.com nxt_mp_t *port_mp; 2110*141Smax.romanov@nginx.com nxt_int_t res; 2111*141Smax.romanov@nginx.com nxt_port_t *port, *c_port, *reply_port; 2112*141Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 2113*141Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2114*141Smax.romanov@nginx.com 2115*141Smax.romanov@nginx.com port = rc->app_port; 2116*141Smax.romanov@nginx.com 2117*141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 2118*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, "Application port not found"); 2119*141Smax.romanov@nginx.com return; 2120*141Smax.romanov@nginx.com } 2121*141Smax.romanov@nginx.com 2122*141Smax.romanov@nginx.com reply_port = rc->reply_port; 2123*141Smax.romanov@nginx.com ap = rc->conn->socket.data; 2124*141Smax.romanov@nginx.com 2125122Smax.romanov@nginx.com port_mp = port->mem_pool; 2126*141Smax.romanov@nginx.com port->mem_pool = mp; 2127*141Smax.romanov@nginx.com 2128*141Smax.romanov@nginx.com c_port = nxt_process_connected_port_find(port->process, reply_port->pid, 2129*141Smax.romanov@nginx.com reply_port->id); 2130*141Smax.romanov@nginx.com if (nxt_slow_path(c_port != reply_port)) { 2131*141Smax.romanov@nginx.com res = nxt_port_send_port(task, port, reply_port, 0); 2132122Smax.romanov@nginx.com 2133122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2134*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2135*141Smax.romanov@nginx.com "Failed to send reply port to application"); 2136*141Smax.romanov@nginx.com goto fail; 2137122Smax.romanov@nginx.com } 2138122Smax.romanov@nginx.com 2139*141Smax.romanov@nginx.com nxt_process_connected_port_add(port->process, reply_port); 214088Smax.romanov@nginx.com } 214188Smax.romanov@nginx.com 214288Smax.romanov@nginx.com wmsg.port = port; 214388Smax.romanov@nginx.com wmsg.write = NULL; 214488Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 2145*141Smax.romanov@nginx.com wmsg.stream = rc->req_id; 2146*141Smax.romanov@nginx.com 2147*141Smax.romanov@nginx.com res = rc->app_port->app->module->prepare_msg(task, &ap->r, &wmsg); 2148122Smax.romanov@nginx.com 2149122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2150*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2151*141Smax.romanov@nginx.com "Failed to prepare message for application"); 2152*141Smax.romanov@nginx.com goto fail; 2153122Smax.romanov@nginx.com } 215488Smax.romanov@nginx.com 215588Smax.romanov@nginx.com nxt_debug(task, "about to send %d bytes buffer to worker port %d", 215688Smax.romanov@nginx.com nxt_buf_used_size(wmsg.write), 215788Smax.romanov@nginx.com wmsg.port->socket.fd); 215888Smax.romanov@nginx.com 2159122Smax.romanov@nginx.com res = nxt_port_socket_write(task, wmsg.port, NXT_PORT_MSG_DATA, 2160*141Smax.romanov@nginx.com -1, rc->req_id, reply_port->id, wmsg.write); 2161122Smax.romanov@nginx.com 2162122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2163*141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, 2164*141Smax.romanov@nginx.com "Failed to send message to application"); 2165*141Smax.romanov@nginx.com goto fail; 2166122Smax.romanov@nginx.com } 2167122Smax.romanov@nginx.com 2168*141Smax.romanov@nginx.com fail: 2169122Smax.romanov@nginx.com port->mem_pool = port_mp; 217053Sigor@sysoev.ru } 217153Sigor@sysoev.ru 217253Sigor@sysoev.ru 217362Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_close_state 217453Sigor@sysoev.ru nxt_aligned(64) = 217553Sigor@sysoev.ru { 217653Sigor@sysoev.ru .ready_handler = nxt_router_conn_free, 217753Sigor@sysoev.ru }; 217853Sigor@sysoev.ru 217953Sigor@sysoev.ru 218053Sigor@sysoev.ru static void 218188Smax.romanov@nginx.com nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data) 218288Smax.romanov@nginx.com { 218388Smax.romanov@nginx.com nxt_buf_t *b; 218488Smax.romanov@nginx.com nxt_bool_t last; 218588Smax.romanov@nginx.com nxt_conn_t *c; 218688Smax.romanov@nginx.com nxt_work_queue_t *wq; 218788Smax.romanov@nginx.com 218888Smax.romanov@nginx.com nxt_debug(task, "router conn ready %p", obj); 218988Smax.romanov@nginx.com 219088Smax.romanov@nginx.com c = obj; 219188Smax.romanov@nginx.com b = c->write; 219288Smax.romanov@nginx.com 219388Smax.romanov@nginx.com wq = &task->thread->engine->fast_work_queue; 219488Smax.romanov@nginx.com 219588Smax.romanov@nginx.com last = 0; 219688Smax.romanov@nginx.com 219788Smax.romanov@nginx.com while (b != NULL) { 219888Smax.romanov@nginx.com if (!nxt_buf_is_sync(b)) { 219988Smax.romanov@nginx.com if (nxt_buf_used_size(b) > 0) { 220088Smax.romanov@nginx.com break; 220188Smax.romanov@nginx.com } 220288Smax.romanov@nginx.com } 220388Smax.romanov@nginx.com 220488Smax.romanov@nginx.com if (nxt_buf_is_last(b)) { 220588Smax.romanov@nginx.com last = 1; 220688Smax.romanov@nginx.com } 220788Smax.romanov@nginx.com 220888Smax.romanov@nginx.com nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); 220988Smax.romanov@nginx.com 221088Smax.romanov@nginx.com b = b->next; 221188Smax.romanov@nginx.com } 221288Smax.romanov@nginx.com 221388Smax.romanov@nginx.com c->write = b; 221488Smax.romanov@nginx.com 221588Smax.romanov@nginx.com if (b != NULL) { 221688Smax.romanov@nginx.com nxt_debug(task, "router conn %p has more data to write", obj); 221788Smax.romanov@nginx.com 221888Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 221988Smax.romanov@nginx.com } else { 222088Smax.romanov@nginx.com nxt_debug(task, "router conn %p no more data to write, last = %d", obj, 222188Smax.romanov@nginx.com last); 222288Smax.romanov@nginx.com 222388Smax.romanov@nginx.com if (last != 0) { 222488Smax.romanov@nginx.com nxt_debug(task, "enqueue router conn close %p (ready handler)", c); 222588Smax.romanov@nginx.com 222688Smax.romanov@nginx.com nxt_work_queue_add(wq, nxt_router_conn_close, task, c, 222788Smax.romanov@nginx.com c->socket.data); 222888Smax.romanov@nginx.com } 222988Smax.romanov@nginx.com } 223088Smax.romanov@nginx.com } 223188Smax.romanov@nginx.com 223288Smax.romanov@nginx.com 223388Smax.romanov@nginx.com static void 223453Sigor@sysoev.ru nxt_router_conn_close(nxt_task_t *task, void *obj, void *data) 223553Sigor@sysoev.ru { 223662Sigor@sysoev.ru nxt_conn_t *c; 223753Sigor@sysoev.ru 223853Sigor@sysoev.ru c = obj; 223953Sigor@sysoev.ru 224053Sigor@sysoev.ru nxt_debug(task, "router conn close"); 224153Sigor@sysoev.ru 224253Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 224353Sigor@sysoev.ru 224462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 224553Sigor@sysoev.ru } 224653Sigor@sysoev.ru 224753Sigor@sysoev.ru 224853Sigor@sysoev.ru static void 224953Sigor@sysoev.ru nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) 225053Sigor@sysoev.ru { 225162Sigor@sysoev.ru nxt_conn_t *c; 225288Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 225353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 225453Sigor@sysoev.ru 225553Sigor@sysoev.ru c = obj; 225653Sigor@sysoev.ru 225753Sigor@sysoev.ru nxt_debug(task, "router conn close done"); 225853Sigor@sysoev.ru 225988Smax.romanov@nginx.com nxt_queue_each(rc, &c->requests, nxt_req_conn_link_t, link) { 226088Smax.romanov@nginx.com 226188Smax.romanov@nginx.com nxt_debug(task, "conn %p close, req %uxD", c, rc->req_id); 226288Smax.romanov@nginx.com 2263*141Smax.romanov@nginx.com if (rc->app_port != NULL) { 2264*141Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 2265*141Smax.romanov@nginx.com 2266*141Smax.romanov@nginx.com rc->app_port = NULL; 2267*141Smax.romanov@nginx.com } 2268*141Smax.romanov@nginx.com 226988Smax.romanov@nginx.com nxt_event_engine_request_remove(task->thread->engine, rc); 227088Smax.romanov@nginx.com 227188Smax.romanov@nginx.com } nxt_queue_loop; 227288Smax.romanov@nginx.com 2273122Smax.romanov@nginx.com nxt_queue_remove(&c->link); 2274122Smax.romanov@nginx.com 2275131Smax.romanov@nginx.com joint = c->listen->socket.data; 2276131Smax.romanov@nginx.com 2277131Smax.romanov@nginx.com task = &task->thread->engine->task; 2278131Smax.romanov@nginx.com 2279*141Smax.romanov@nginx.com if (nxt_mp_release(c->mem_pool, c) == 0) { 2280*141Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 2281*141Smax.romanov@nginx.com } 228253Sigor@sysoev.ru } 228353Sigor@sysoev.ru 228453Sigor@sysoev.ru 228553Sigor@sysoev.ru static void 228653Sigor@sysoev.ru nxt_router_conn_error(nxt_task_t *task, void *obj, void *data) 228753Sigor@sysoev.ru { 228862Sigor@sysoev.ru nxt_conn_t *c; 228953Sigor@sysoev.ru 229053Sigor@sysoev.ru c = obj; 229153Sigor@sysoev.ru 229253Sigor@sysoev.ru nxt_debug(task, "router conn error"); 229353Sigor@sysoev.ru 229453Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 229553Sigor@sysoev.ru 229662Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 229753Sigor@sysoev.ru } 229853Sigor@sysoev.ru 229953Sigor@sysoev.ru 230053Sigor@sysoev.ru static void 230153Sigor@sysoev.ru nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) 230253Sigor@sysoev.ru { 230362Sigor@sysoev.ru nxt_conn_t *c; 230462Sigor@sysoev.ru nxt_timer_t *timer; 230553Sigor@sysoev.ru 230653Sigor@sysoev.ru timer = obj; 230753Sigor@sysoev.ru 230853Sigor@sysoev.ru nxt_debug(task, "router conn timeout"); 230953Sigor@sysoev.ru 231062Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 231153Sigor@sysoev.ru 231253Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 231353Sigor@sysoev.ru 231462Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 231553Sigor@sysoev.ru } 231653Sigor@sysoev.ru 231753Sigor@sysoev.ru 231853Sigor@sysoev.ru static nxt_msec_t 231962Sigor@sysoev.ru nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 232053Sigor@sysoev.ru { 232153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 232253Sigor@sysoev.ru 232353Sigor@sysoev.ru joint = c->listen->socket.data; 232453Sigor@sysoev.ru 232553Sigor@sysoev.ru return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 232653Sigor@sysoev.ru } 2327*141Smax.romanov@nginx.com 2328*141Smax.romanov@nginx.com 2329*141Smax.romanov@nginx.com static nxt_int_t 2330*141Smax.romanov@nginx.com nxt_sw_test(nxt_lvlhsh_query_t *lhq, void *data) 2331*141Smax.romanov@nginx.com { 2332*141Smax.romanov@nginx.com return NXT_OK; 2333*141Smax.romanov@nginx.com } 2334*141Smax.romanov@nginx.com 2335*141Smax.romanov@nginx.com 2336*141Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t lvlhsh_sw_proto nxt_aligned(64) = { 2337*141Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT, 2338*141Smax.romanov@nginx.com nxt_sw_test, 2339*141Smax.romanov@nginx.com nxt_lvlhsh_alloc, 2340*141Smax.romanov@nginx.com nxt_lvlhsh_free, 2341*141Smax.romanov@nginx.com }; 2342*141Smax.romanov@nginx.com 2343*141Smax.romanov@nginx.com 2344*141Smax.romanov@nginx.com static void 2345*141Smax.romanov@nginx.com nxt_router_sw_add(nxt_task_t *task, nxt_router_t *router, 2346*141Smax.romanov@nginx.com nxt_start_worker_t *sw) 2347*141Smax.romanov@nginx.com { 2348*141Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 2349*141Smax.romanov@nginx.com 2350*141Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&sw->stream, sizeof(sw->stream)); 2351*141Smax.romanov@nginx.com lhq.key.length = sizeof(sw->stream); 2352*141Smax.romanov@nginx.com lhq.key.start = (u_char *) &sw->stream; 2353*141Smax.romanov@nginx.com lhq.proto = &lvlhsh_sw_proto; 2354*141Smax.romanov@nginx.com lhq.replace = 0; 2355*141Smax.romanov@nginx.com lhq.value = sw; 2356*141Smax.romanov@nginx.com lhq.pool = task->thread->runtime->mem_pool; 2357*141Smax.romanov@nginx.com 2358*141Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&router->start_workers, &lhq)) { 2359*141Smax.romanov@nginx.com 2360*141Smax.romanov@nginx.com case NXT_OK: 2361*141Smax.romanov@nginx.com break; 2362*141Smax.romanov@nginx.com 2363*141Smax.romanov@nginx.com default: 2364*141Smax.romanov@nginx.com nxt_log_error(NXT_LOG_WARN, task->log, "stream %08uxD sw add failed", 2365*141Smax.romanov@nginx.com sw->stream); 2366*141Smax.romanov@nginx.com break; 2367*141Smax.romanov@nginx.com } 2368*141Smax.romanov@nginx.com } 2369*141Smax.romanov@nginx.com 2370*141Smax.romanov@nginx.com 2371*141Smax.romanov@nginx.com static nxt_start_worker_t * 2372*141Smax.romanov@nginx.com nxt_router_sw_find_remove(nxt_task_t *task, nxt_router_t *router, uint32_t id) 2373*141Smax.romanov@nginx.com { 2374*141Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 2375*141Smax.romanov@nginx.com 2376*141Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&id, sizeof(id)); 2377*141Smax.romanov@nginx.com lhq.key.length = sizeof(id); 2378*141Smax.romanov@nginx.com lhq.key.start = (u_char *) &id; 2379*141Smax.romanov@nginx.com lhq.proto = &lvlhsh_sw_proto; 2380*141Smax.romanov@nginx.com lhq.pool = task->thread->runtime->mem_pool; 2381*141Smax.romanov@nginx.com 2382*141Smax.romanov@nginx.com switch (nxt_lvlhsh_delete(&router->start_workers, &lhq)) { 2383*141Smax.romanov@nginx.com 2384*141Smax.romanov@nginx.com case NXT_OK: 2385*141Smax.romanov@nginx.com return lhq.value; 2386*141Smax.romanov@nginx.com 2387*141Smax.romanov@nginx.com default: 2388*141Smax.romanov@nginx.com nxt_log_error(NXT_LOG_WARN, task->log, "stream %08uxD sw remove failed", 2389*141Smax.romanov@nginx.com id); 2390*141Smax.romanov@nginx.com break; 2391*141Smax.romanov@nginx.com } 2392*141Smax.romanov@nginx.com 2393*141Smax.romanov@nginx.com return NULL; 2394*141Smax.romanov@nginx.com } 2395