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 8*53Sigor@sysoev.ru #include <nxt_router.h> 920Sigor@sysoev.ru 1020Sigor@sysoev.ru 11*53Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task, 12*53Sigor@sysoev.ru nxt_router_t *router); 13*53Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 14*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 15*53Sigor@sysoev.ru 16*53Sigor@sysoev.ru static nxt_int_t nxt_router_stub_conf(nxt_task_t *task, 17*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 18*53Sigor@sysoev.ru static nxt_int_t nxt_router_listen_sockets_stub_create(nxt_task_t *task, 19*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 20*53Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, 21*53Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_sockaddr_t *sa); 22*53Sigor@sysoev.ru static nxt_sockaddr_t *nxt_router_listen_sockaddr_stub(nxt_task_t *task, 23*53Sigor@sysoev.ru nxt_mem_pool_t *mp, uint32_t port); 24*53Sigor@sysoev.ru 25*53Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 26*53Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 27*53Sigor@sysoev.ru const nxt_event_interface_t *interface); 28*53Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_task_t *task, 29*53Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_router_temp_conf_t *tmcf, 30*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 31*53Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_task_t *task, 32*53Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_router_temp_conf_t *tmcf, 33*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 34*53Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_task_t *task, 35*53Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_router_temp_conf_t *tmcf, 36*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 37*53Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_task_t *task, 38*53Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 39*53Sigor@sysoev.ru nxt_array_t *array, nxt_work_handler_t handler); 40*53Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_task_t *task, 41*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array); 42*53Sigor@sysoev.ru 43*53Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 44*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 45*53Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 46*53Sigor@sysoev.ru nxt_event_engine_t *engine); 47*53Sigor@sysoev.ru 48*53Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 49*53Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf); 50*53Sigor@sysoev.ru 51*53Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 52*53Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 53*53Sigor@sysoev.ru void *data); 54*53Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 55*53Sigor@sysoev.ru void *data); 56*53Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 57*53Sigor@sysoev.ru void *data); 58*53Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 59*53Sigor@sysoev.ru void *data); 60*53Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 61*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 62*53Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 63*53Sigor@sysoev.ru void *data); 64*53Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 65*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 66*53Sigor@sysoev.ru 67*53Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 68*53Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 69*53Sigor@sysoev.ru void *data); 70*53Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 71*53Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 72*53Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 73*53Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 74*53Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_event_conn_t *c, 75*53Sigor@sysoev.ru uintptr_t data); 7620Sigor@sysoev.ru 7720Sigor@sysoev.ru 7820Sigor@sysoev.ru nxt_int_t 7920Sigor@sysoev.ru nxt_router_start(nxt_task_t *task, nxt_runtime_t *rt) 8020Sigor@sysoev.ru { 81*53Sigor@sysoev.ru nxt_int_t ret; 82*53Sigor@sysoev.ru nxt_router_t *router; 83*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 84*53Sigor@sysoev.ru const nxt_event_interface_t *interface; 85*53Sigor@sysoev.ru 86*53Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 87*53Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 88*53Sigor@sysoev.ru return NXT_ERROR; 89*53Sigor@sysoev.ru } 90*53Sigor@sysoev.ru 91*53Sigor@sysoev.ru nxt_queue_init(&router->engines); 92*53Sigor@sysoev.ru nxt_queue_init(&router->sockets); 93*53Sigor@sysoev.ru 94*53Sigor@sysoev.ru /**/ 95*53Sigor@sysoev.ru 96*53Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task, router); 97*53Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 9820Sigor@sysoev.ru return NXT_ERROR; 9920Sigor@sysoev.ru } 10020Sigor@sysoev.ru 101*53Sigor@sysoev.ru ret = nxt_router_stub_conf(task, tmcf); 102*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 103*53Sigor@sysoev.ru return ret; 104*53Sigor@sysoev.ru } 105*53Sigor@sysoev.ru 106*53Sigor@sysoev.ru nxt_router_listen_sockets_sort(router, tmcf); 107*53Sigor@sysoev.ru 108*53Sigor@sysoev.ru ret = nxt_router_listen_sockets_stub_create(task, tmcf); 109*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 110*53Sigor@sysoev.ru return ret; 111*53Sigor@sysoev.ru } 112*53Sigor@sysoev.ru 113*53Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 114*53Sigor@sysoev.ru 115*53Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 116*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 117*53Sigor@sysoev.ru return ret; 118*53Sigor@sysoev.ru } 119*53Sigor@sysoev.ru 120*53Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 121*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 122*53Sigor@sysoev.ru return ret; 123*53Sigor@sysoev.ru } 124*53Sigor@sysoev.ru 125*53Sigor@sysoev.ru nxt_router_engines_post(tmcf); 126*53Sigor@sysoev.ru 127*53Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 128*53Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 129*53Sigor@sysoev.ru 130*53Sigor@sysoev.ru return NXT_OK; 131*53Sigor@sysoev.ru } 132*53Sigor@sysoev.ru 133*53Sigor@sysoev.ru 134*53Sigor@sysoev.ru static nxt_router_temp_conf_t * 135*53Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task, nxt_router_t *router) 136*53Sigor@sysoev.ru { 137*53Sigor@sysoev.ru nxt_mem_pool_t *mp, *tmp; 138*53Sigor@sysoev.ru nxt_router_conf_t *rtcf; 139*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 140*53Sigor@sysoev.ru 141*53Sigor@sysoev.ru mp = nxt_mem_pool_create(1024); 142*53Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 143*53Sigor@sysoev.ru return NULL; 144*53Sigor@sysoev.ru } 145*53Sigor@sysoev.ru 146*53Sigor@sysoev.ru rtcf = nxt_mem_zalloc(mp, sizeof(nxt_router_conf_t)); 147*53Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 148*53Sigor@sysoev.ru goto fail; 149*53Sigor@sysoev.ru } 150*53Sigor@sysoev.ru 151*53Sigor@sysoev.ru rtcf->mem_pool = mp; 152*53Sigor@sysoev.ru rtcf->router = router; 153*53Sigor@sysoev.ru rtcf->count = 1; 154*53Sigor@sysoev.ru 155*53Sigor@sysoev.ru tmp = nxt_mem_pool_create(1024); 156*53Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 157*53Sigor@sysoev.ru goto fail; 158*53Sigor@sysoev.ru } 159*53Sigor@sysoev.ru 160*53Sigor@sysoev.ru tmcf = nxt_mem_zalloc(tmp, sizeof(nxt_router_temp_conf_t)); 161*53Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 162*53Sigor@sysoev.ru goto temp_fail; 163*53Sigor@sysoev.ru } 164*53Sigor@sysoev.ru 165*53Sigor@sysoev.ru tmcf->mem_pool = tmp; 166*53Sigor@sysoev.ru tmcf->conf = rtcf; 167*53Sigor@sysoev.ru 168*53Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 169*53Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 170*53Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 171*53Sigor@sysoev.ru goto temp_fail; 172*53Sigor@sysoev.ru } 173*53Sigor@sysoev.ru 174*53Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 175*53Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 176*53Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 177*53Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 178*53Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 179*53Sigor@sysoev.ru 180*53Sigor@sysoev.ru return tmcf; 181*53Sigor@sysoev.ru 182*53Sigor@sysoev.ru temp_fail: 183*53Sigor@sysoev.ru 184*53Sigor@sysoev.ru nxt_mem_pool_destroy(tmp); 185*53Sigor@sysoev.ru 186*53Sigor@sysoev.ru fail: 187*53Sigor@sysoev.ru 188*53Sigor@sysoev.ru nxt_mem_pool_destroy(mp); 189*53Sigor@sysoev.ru 190*53Sigor@sysoev.ru return NULL; 191*53Sigor@sysoev.ru } 192*53Sigor@sysoev.ru 193*53Sigor@sysoev.ru 194*53Sigor@sysoev.ru static nxt_int_t 195*53Sigor@sysoev.ru nxt_router_stub_conf(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 196*53Sigor@sysoev.ru { 197*53Sigor@sysoev.ru nxt_sockaddr_t *sa; 198*53Sigor@sysoev.ru nxt_mem_pool_t *mp; 199*53Sigor@sysoev.ru nxt_socket_conf_t *skcf; 200*53Sigor@sysoev.ru 201*53Sigor@sysoev.ru tmcf->conf->threads = 1; 202*53Sigor@sysoev.ru 203*53Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 204*53Sigor@sysoev.ru 205*53Sigor@sysoev.ru sa = nxt_router_listen_sockaddr_stub(task, mp, 8000); 206*53Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 207*53Sigor@sysoev.ru 208*53Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 209*53Sigor@sysoev.ru skcf->listen.mem_pool_size = nxt_listen_socket_pool_min_size(&skcf->listen) 210*53Sigor@sysoev.ru + sizeof(nxt_event_conn_proxy_t) 211*53Sigor@sysoev.ru + sizeof(nxt_event_conn_t) 212*53Sigor@sysoev.ru + 4 * sizeof(nxt_buf_t); 213*53Sigor@sysoev.ru 214*53Sigor@sysoev.ru skcf->header_buffer_size = 2048; 215*53Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 216*53Sigor@sysoev.ru skcf->header_read_timeout = 5000; 217*53Sigor@sysoev.ru 218*53Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 219*53Sigor@sysoev.ru 220*53Sigor@sysoev.ru sa = nxt_router_listen_sockaddr_stub(task, mp, 8001); 221*53Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 222*53Sigor@sysoev.ru 223*53Sigor@sysoev.ru skcf->listen.handler = nxt_stream_connection_init; 224*53Sigor@sysoev.ru skcf->listen.mem_pool_size = nxt_listen_socket_pool_min_size(&skcf->listen) 225*53Sigor@sysoev.ru + sizeof(nxt_event_conn_proxy_t) 226*53Sigor@sysoev.ru + sizeof(nxt_event_conn_t) 227*53Sigor@sysoev.ru + 4 * sizeof(nxt_buf_t); 228*53Sigor@sysoev.ru 229*53Sigor@sysoev.ru skcf->header_read_timeout = 5000; 230*53Sigor@sysoev.ru 231*53Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 232*53Sigor@sysoev.ru 233*53Sigor@sysoev.ru return NXT_OK; 234*53Sigor@sysoev.ru } 235*53Sigor@sysoev.ru 236*53Sigor@sysoev.ru 237*53Sigor@sysoev.ru static nxt_socket_conf_t * 238*53Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mem_pool_t *mp, nxt_sockaddr_t *sa) 239*53Sigor@sysoev.ru { 240*53Sigor@sysoev.ru nxt_socket_conf_t *conf; 241*53Sigor@sysoev.ru 242*53Sigor@sysoev.ru conf = nxt_mem_zalloc(mp, sizeof(nxt_socket_conf_t)); 243*53Sigor@sysoev.ru if (nxt_slow_path(conf == NULL)) { 244*53Sigor@sysoev.ru return NULL; 245*53Sigor@sysoev.ru } 246*53Sigor@sysoev.ru 247*53Sigor@sysoev.ru conf->listen.sockaddr = sa; 248*53Sigor@sysoev.ru 249*53Sigor@sysoev.ru conf->listen.socket = -1; 250*53Sigor@sysoev.ru conf->listen.backlog = NXT_LISTEN_BACKLOG; 251*53Sigor@sysoev.ru conf->listen.flags = NXT_NONBLOCK; 252*53Sigor@sysoev.ru conf->listen.read_after_accept = 1; 253*53Sigor@sysoev.ru 254*53Sigor@sysoev.ru return conf; 255*53Sigor@sysoev.ru } 256*53Sigor@sysoev.ru 257*53Sigor@sysoev.ru 258*53Sigor@sysoev.ru static nxt_sockaddr_t * 259*53Sigor@sysoev.ru nxt_router_listen_sockaddr_stub(nxt_task_t *task, nxt_mem_pool_t *mp, 260*53Sigor@sysoev.ru uint32_t port) 261*53Sigor@sysoev.ru { 262*53Sigor@sysoev.ru nxt_sockaddr_t *sa; 263*53Sigor@sysoev.ru struct sockaddr_in sin; 264*53Sigor@sysoev.ru 265*53Sigor@sysoev.ru nxt_memzero(&sin, sizeof(struct sockaddr_in)); 266*53Sigor@sysoev.ru 267*53Sigor@sysoev.ru sin.sin_family = AF_INET; 268*53Sigor@sysoev.ru sin.sin_port = htons(port); 269*53Sigor@sysoev.ru 270*53Sigor@sysoev.ru sa = nxt_sockaddr_create(mp, (struct sockaddr *) &sin, 271*53Sigor@sysoev.ru sizeof(struct sockaddr_in), NXT_INET_ADDR_STR_LEN); 272*53Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 273*53Sigor@sysoev.ru return NULL; 274*53Sigor@sysoev.ru } 275*53Sigor@sysoev.ru 276*53Sigor@sysoev.ru sa->type = SOCK_STREAM; 277*53Sigor@sysoev.ru 278*53Sigor@sysoev.ru nxt_sockaddr_text(sa); 279*53Sigor@sysoev.ru 280*53Sigor@sysoev.ru return sa; 281*53Sigor@sysoev.ru } 282*53Sigor@sysoev.ru 283*53Sigor@sysoev.ru 284*53Sigor@sysoev.ru static void 285*53Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 286*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 287*53Sigor@sysoev.ru { 288*53Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 289*53Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 290*53Sigor@sysoev.ru 291*53Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 292*53Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 293*53Sigor@sysoev.ru nqlk = next) 294*53Sigor@sysoev.ru { 295*53Sigor@sysoev.ru next = nxt_queue_next(nqlk); 296*53Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 297*53Sigor@sysoev.ru 298*53Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 299*53Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 300*53Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 301*53Sigor@sysoev.ru { 302*53Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 303*53Sigor@sysoev.ru 304*53Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->listen.sockaddr, 305*53Sigor@sysoev.ru oskcf->listen.sockaddr)) 306*53Sigor@sysoev.ru { 307*53Sigor@sysoev.ru nxt_queue_remove(oqlk); 308*53Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 309*53Sigor@sysoev.ru 310*53Sigor@sysoev.ru nxt_queue_remove(nqlk); 311*53Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 312*53Sigor@sysoev.ru 313*53Sigor@sysoev.ru break; 314*53Sigor@sysoev.ru } 315*53Sigor@sysoev.ru } 316*53Sigor@sysoev.ru } 317*53Sigor@sysoev.ru 318*53Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 319*53Sigor@sysoev.ru } 320*53Sigor@sysoev.ru 321*53Sigor@sysoev.ru 322*53Sigor@sysoev.ru static nxt_int_t 323*53Sigor@sysoev.ru nxt_router_listen_sockets_stub_create(nxt_task_t *task, 324*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 325*53Sigor@sysoev.ru { 326*53Sigor@sysoev.ru nxt_queue_link_t *qlk, *nqlk; 327*53Sigor@sysoev.ru nxt_socket_conf_t *skcf; 328*53Sigor@sysoev.ru 329*53Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->pending); 330*53Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->pending); 331*53Sigor@sysoev.ru qlk = nqlk) 332*53Sigor@sysoev.ru { 333*53Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 334*53Sigor@sysoev.ru 335*53Sigor@sysoev.ru if (nxt_listen_socket_create(task, &skcf->listen, 0) != NXT_OK) { 336*53Sigor@sysoev.ru return NXT_ERROR; 337*53Sigor@sysoev.ru } 338*53Sigor@sysoev.ru 339*53Sigor@sysoev.ru nqlk = nxt_queue_next(qlk); 340*53Sigor@sysoev.ru nxt_queue_remove(qlk); 341*53Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 342*53Sigor@sysoev.ru } 343*53Sigor@sysoev.ru 344*53Sigor@sysoev.ru return NXT_OK; 345*53Sigor@sysoev.ru } 346*53Sigor@sysoev.ru 347*53Sigor@sysoev.ru 348*53Sigor@sysoev.ru static nxt_int_t 349*53Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 350*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 351*53Sigor@sysoev.ru { 352*53Sigor@sysoev.ru nxt_int_t ret; 353*53Sigor@sysoev.ru nxt_uint_t n, threads; 354*53Sigor@sysoev.ru nxt_mem_pool_t *mp; 355*53Sigor@sysoev.ru nxt_queue_link_t *qlk; 356*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 357*53Sigor@sysoev.ru 358*53Sigor@sysoev.ru mp = tmcf->conf->mem_pool; 359*53Sigor@sysoev.ru threads = tmcf->conf->threads; 360*53Sigor@sysoev.ru 361*53Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 362*53Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 363*53Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 364*53Sigor@sysoev.ru return NXT_ERROR; 365*53Sigor@sysoev.ru } 366*53Sigor@sysoev.ru 367*53Sigor@sysoev.ru n = 0; 368*53Sigor@sysoev.ru 369*53Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 370*53Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 371*53Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 372*53Sigor@sysoev.ru { 373*53Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 374*53Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 375*53Sigor@sysoev.ru return NXT_ERROR; 376*53Sigor@sysoev.ru } 377*53Sigor@sysoev.ru 378*53Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link); 379*53Sigor@sysoev.ru // STUB 380*53Sigor@sysoev.ru recf->task = recf->engine->task; 381*53Sigor@sysoev.ru 382*53Sigor@sysoev.ru if (n < threads) { 383*53Sigor@sysoev.ru ret = nxt_router_engine_conf_update(task, mp, tmcf, recf); 384*53Sigor@sysoev.ru 385*53Sigor@sysoev.ru } else { 386*53Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(task, mp, tmcf, recf); 387*53Sigor@sysoev.ru } 388*53Sigor@sysoev.ru 389*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 390*53Sigor@sysoev.ru return ret; 391*53Sigor@sysoev.ru } 392*53Sigor@sysoev.ru 393*53Sigor@sysoev.ru n++; 394*53Sigor@sysoev.ru } 395*53Sigor@sysoev.ru 396*53Sigor@sysoev.ru tmcf->new_threads = n; 397*53Sigor@sysoev.ru 398*53Sigor@sysoev.ru while (n < threads) { 399*53Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 400*53Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 401*53Sigor@sysoev.ru return NXT_ERROR; 402*53Sigor@sysoev.ru } 403*53Sigor@sysoev.ru 404*53Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 405*53Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 406*53Sigor@sysoev.ru return NXT_ERROR; 407*53Sigor@sysoev.ru } 408*53Sigor@sysoev.ru // STUB 409*53Sigor@sysoev.ru recf->task = recf->engine->task; 410*53Sigor@sysoev.ru 411*53Sigor@sysoev.ru ret = nxt_router_engine_conf_create(task, mp, tmcf, recf); 412*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 413*53Sigor@sysoev.ru return ret; 414*53Sigor@sysoev.ru } 415*53Sigor@sysoev.ru 416*53Sigor@sysoev.ru n++; 417*53Sigor@sysoev.ru } 418*53Sigor@sysoev.ru 419*53Sigor@sysoev.ru return NXT_OK; 420*53Sigor@sysoev.ru } 421*53Sigor@sysoev.ru 422*53Sigor@sysoev.ru 423*53Sigor@sysoev.ru static nxt_int_t 424*53Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_task_t *task, nxt_mem_pool_t *mp, 425*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_router_engine_conf_t *recf) 426*53Sigor@sysoev.ru { 427*53Sigor@sysoev.ru nxt_int_t ret; 428*53Sigor@sysoev.ru 429*53Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 430*53Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 431*53Sigor@sysoev.ru return NXT_ERROR; 432*53Sigor@sysoev.ru } 433*53Sigor@sysoev.ru 434*53Sigor@sysoev.ru ret = nxt_router_engine_joints_create(task, mp, recf, &tmcf->creating, 435*53Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 436*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 437*53Sigor@sysoev.ru return ret; 438*53Sigor@sysoev.ru } 439*53Sigor@sysoev.ru 440*53Sigor@sysoev.ru return nxt_router_engine_joints_create(task, mp, recf, &tmcf->updating, 441*53Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 442*53Sigor@sysoev.ru } 443*53Sigor@sysoev.ru 444*53Sigor@sysoev.ru 445*53Sigor@sysoev.ru static nxt_int_t 446*53Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_task_t *task, nxt_mem_pool_t *mp, 447*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_router_engine_conf_t *recf) 448*53Sigor@sysoev.ru { 449*53Sigor@sysoev.ru nxt_int_t ret; 450*53Sigor@sysoev.ru 451*53Sigor@sysoev.ru recf->creating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 452*53Sigor@sysoev.ru if (nxt_slow_path(recf->creating == NULL)) { 453*53Sigor@sysoev.ru return NXT_ERROR; 454*53Sigor@sysoev.ru } 455*53Sigor@sysoev.ru 456*53Sigor@sysoev.ru ret = nxt_router_engine_joints_create(task, mp, recf, &tmcf->creating, 457*53Sigor@sysoev.ru recf->creating, nxt_router_listen_socket_create); 458*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 459*53Sigor@sysoev.ru return ret; 460*53Sigor@sysoev.ru } 461*53Sigor@sysoev.ru 462*53Sigor@sysoev.ru recf->updating = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 463*53Sigor@sysoev.ru if (nxt_slow_path(recf->updating == NULL)) { 464*53Sigor@sysoev.ru return NXT_ERROR; 465*53Sigor@sysoev.ru } 466*53Sigor@sysoev.ru 467*53Sigor@sysoev.ru ret = nxt_router_engine_joints_create(task, mp, recf, &tmcf->updating, 468*53Sigor@sysoev.ru recf->updating, nxt_router_listen_socket_update); 469*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 470*53Sigor@sysoev.ru return ret; 471*53Sigor@sysoev.ru } 472*53Sigor@sysoev.ru 473*53Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 474*53Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 475*53Sigor@sysoev.ru return NXT_ERROR; 476*53Sigor@sysoev.ru } 477*53Sigor@sysoev.ru 478*53Sigor@sysoev.ru return nxt_router_engine_joints_delete(task, recf, &tmcf->deleting, 479*53Sigor@sysoev.ru recf->deleting); 480*53Sigor@sysoev.ru } 481*53Sigor@sysoev.ru 482*53Sigor@sysoev.ru 483*53Sigor@sysoev.ru static nxt_int_t 484*53Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_task_t *task, nxt_mem_pool_t *mp, 485*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_router_engine_conf_t *recf) 486*53Sigor@sysoev.ru { 487*53Sigor@sysoev.ru nxt_int_t ret; 488*53Sigor@sysoev.ru 489*53Sigor@sysoev.ru recf->deleting = nxt_array_create(tmcf->mem_pool, 4, sizeof(nxt_work_t)); 490*53Sigor@sysoev.ru if (nxt_slow_path(recf->deleting == NULL)) { 491*53Sigor@sysoev.ru return NXT_ERROR; 492*53Sigor@sysoev.ru } 493*53Sigor@sysoev.ru 494*53Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(task, recf, &tmcf->updating, 495*53Sigor@sysoev.ru recf->deleting); 496*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 497*53Sigor@sysoev.ru return ret; 498*53Sigor@sysoev.ru } 499*53Sigor@sysoev.ru 500*53Sigor@sysoev.ru return nxt_router_engine_joints_delete(task, recf, &tmcf->deleting, 501*53Sigor@sysoev.ru recf->deleting); 502*53Sigor@sysoev.ru } 503*53Sigor@sysoev.ru 504*53Sigor@sysoev.ru 505*53Sigor@sysoev.ru static nxt_int_t 506*53Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_task_t *task, nxt_mem_pool_t *mp, 507*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array, 508*53Sigor@sysoev.ru nxt_work_handler_t handler) 509*53Sigor@sysoev.ru { 510*53Sigor@sysoev.ru nxt_work_t *work; 511*53Sigor@sysoev.ru nxt_queue_link_t *qlk; 512*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 513*53Sigor@sysoev.ru 514*53Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 515*53Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 516*53Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 517*53Sigor@sysoev.ru { 518*53Sigor@sysoev.ru work = nxt_array_add(array); 519*53Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 520*53Sigor@sysoev.ru return NXT_ERROR; 521*53Sigor@sysoev.ru } 522*53Sigor@sysoev.ru 523*53Sigor@sysoev.ru work->next = NULL; 524*53Sigor@sysoev.ru work->handler = handler; 525*53Sigor@sysoev.ru work->task = &recf->task; 526*53Sigor@sysoev.ru work->obj = recf->engine; 527*53Sigor@sysoev.ru 528*53Sigor@sysoev.ru joint = nxt_mem_alloc(mp, sizeof(nxt_socket_conf_joint_t)); 529*53Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 530*53Sigor@sysoev.ru return NXT_ERROR; 531*53Sigor@sysoev.ru } 532*53Sigor@sysoev.ru 533*53Sigor@sysoev.ru work->data = joint; 534*53Sigor@sysoev.ru 535*53Sigor@sysoev.ru joint->count = 1; 536*53Sigor@sysoev.ru joint->socket_conf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 537*53Sigor@sysoev.ru } 538*53Sigor@sysoev.ru 53920Sigor@sysoev.ru return NXT_OK; 54020Sigor@sysoev.ru } 54120Sigor@sysoev.ru 54220Sigor@sysoev.ru 54320Sigor@sysoev.ru static nxt_int_t 544*53Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_task_t *task, 545*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, nxt_array_t *array) 54620Sigor@sysoev.ru { 547*53Sigor@sysoev.ru nxt_work_t *work; 548*53Sigor@sysoev.ru nxt_queue_link_t *qlk; 54920Sigor@sysoev.ru 550*53Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 551*53Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 552*53Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 553*53Sigor@sysoev.ru { 554*53Sigor@sysoev.ru work = nxt_array_add(array); 555*53Sigor@sysoev.ru if (nxt_slow_path(work == NULL)) { 556*53Sigor@sysoev.ru return NXT_ERROR; 557*53Sigor@sysoev.ru } 55820Sigor@sysoev.ru 559*53Sigor@sysoev.ru work->next = NULL; 560*53Sigor@sysoev.ru work->handler = nxt_router_listen_socket_delete; 561*53Sigor@sysoev.ru work->task = &recf->task; 562*53Sigor@sysoev.ru work->obj = recf->engine; 563*53Sigor@sysoev.ru work->data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 56420Sigor@sysoev.ru } 56520Sigor@sysoev.ru 566*53Sigor@sysoev.ru return NXT_OK; 567*53Sigor@sysoev.ru } 56820Sigor@sysoev.ru 56920Sigor@sysoev.ru 570*53Sigor@sysoev.ru static nxt_int_t 571*53Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 572*53Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 573*53Sigor@sysoev.ru { 574*53Sigor@sysoev.ru nxt_int_t ret; 575*53Sigor@sysoev.ru nxt_uint_t i, threads; 576*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 57720Sigor@sysoev.ru 578*53Sigor@sysoev.ru recf = tmcf->engines->elts; 579*53Sigor@sysoev.ru threads = tmcf->conf->threads; 58020Sigor@sysoev.ru 581*53Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 582*53Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 583*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 584*53Sigor@sysoev.ru return ret; 585*53Sigor@sysoev.ru } 58620Sigor@sysoev.ru } 58720Sigor@sysoev.ru 58820Sigor@sysoev.ru return NXT_OK; 58920Sigor@sysoev.ru } 590*53Sigor@sysoev.ru 591*53Sigor@sysoev.ru 592*53Sigor@sysoev.ru static nxt_int_t 593*53Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 594*53Sigor@sysoev.ru nxt_event_engine_t *engine) 595*53Sigor@sysoev.ru { 596*53Sigor@sysoev.ru nxt_int_t ret; 597*53Sigor@sysoev.ru nxt_thread_link_t *link; 598*53Sigor@sysoev.ru nxt_thread_handle_t handle; 599*53Sigor@sysoev.ru 600*53Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 601*53Sigor@sysoev.ru 602*53Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 603*53Sigor@sysoev.ru return NXT_ERROR; 604*53Sigor@sysoev.ru } 605*53Sigor@sysoev.ru 606*53Sigor@sysoev.ru link->start = nxt_router_thread_start; 607*53Sigor@sysoev.ru link->engine = engine; 608*53Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 609*53Sigor@sysoev.ru link->work.task = task; 610*53Sigor@sysoev.ru link->work.data = link; 611*53Sigor@sysoev.ru 612*53Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 613*53Sigor@sysoev.ru 614*53Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 615*53Sigor@sysoev.ru 616*53Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 617*53Sigor@sysoev.ru nxt_queue_remove(&engine->link); 618*53Sigor@sysoev.ru } 619*53Sigor@sysoev.ru 620*53Sigor@sysoev.ru return ret; 621*53Sigor@sysoev.ru } 622*53Sigor@sysoev.ru 623*53Sigor@sysoev.ru 624*53Sigor@sysoev.ru static void 625*53Sigor@sysoev.ru nxt_router_engines_post(nxt_router_temp_conf_t *tmcf) 626*53Sigor@sysoev.ru { 627*53Sigor@sysoev.ru nxt_uint_t n; 628*53Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 629*53Sigor@sysoev.ru 630*53Sigor@sysoev.ru recf = tmcf->engines->elts; 631*53Sigor@sysoev.ru 632*53Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 633*53Sigor@sysoev.ru nxt_router_engine_post(recf); 634*53Sigor@sysoev.ru recf++; 635*53Sigor@sysoev.ru } 636*53Sigor@sysoev.ru } 637*53Sigor@sysoev.ru 638*53Sigor@sysoev.ru 639*53Sigor@sysoev.ru static void 640*53Sigor@sysoev.ru nxt_router_engine_post(nxt_router_engine_conf_t *recf) 641*53Sigor@sysoev.ru { 642*53Sigor@sysoev.ru nxt_uint_t n; 643*53Sigor@sysoev.ru nxt_work_t *work; 644*53Sigor@sysoev.ru 645*53Sigor@sysoev.ru work = recf->creating->elts; 646*53Sigor@sysoev.ru 647*53Sigor@sysoev.ru for (n = recf->creating->nelts; n != 0; n--) { 648*53Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 649*53Sigor@sysoev.ru work++; 650*53Sigor@sysoev.ru } 651*53Sigor@sysoev.ru } 652*53Sigor@sysoev.ru 653*53Sigor@sysoev.ru 654*53Sigor@sysoev.ru static void 655*53Sigor@sysoev.ru nxt_router_thread_start(void *data) 656*53Sigor@sysoev.ru { 657*53Sigor@sysoev.ru nxt_thread_t *thread; 658*53Sigor@sysoev.ru nxt_thread_link_t *link; 659*53Sigor@sysoev.ru nxt_event_engine_t *engine; 660*53Sigor@sysoev.ru 661*53Sigor@sysoev.ru link = data; 662*53Sigor@sysoev.ru engine = link->engine; 663*53Sigor@sysoev.ru 664*53Sigor@sysoev.ru thread = nxt_thread(); 665*53Sigor@sysoev.ru 666*53Sigor@sysoev.ru /* STUB */ 667*53Sigor@sysoev.ru thread->runtime = engine->task.thread->runtime; 668*53Sigor@sysoev.ru 669*53Sigor@sysoev.ru engine->task.thread = thread; 670*53Sigor@sysoev.ru engine->task.log = thread->log; 671*53Sigor@sysoev.ru thread->engine = engine; 672*53Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 673*53Sigor@sysoev.ru 674*53Sigor@sysoev.ru engine->mem_pool = nxt_mem_cache_pool_create(4096, 1024, 1024, 64); 675*53Sigor@sysoev.ru 676*53Sigor@sysoev.ru nxt_event_engine_start(engine); 677*53Sigor@sysoev.ru } 678*53Sigor@sysoev.ru 679*53Sigor@sysoev.ru 680*53Sigor@sysoev.ru static void 681*53Sigor@sysoev.ru nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 682*53Sigor@sysoev.ru { 683*53Sigor@sysoev.ru nxt_listen_event_t *listen; 684*53Sigor@sysoev.ru nxt_event_engine_t *engine; 685*53Sigor@sysoev.ru nxt_listen_socket_t *ls; 686*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 687*53Sigor@sysoev.ru 688*53Sigor@sysoev.ru engine = obj; 689*53Sigor@sysoev.ru joint = data; 690*53Sigor@sysoev.ru 691*53Sigor@sysoev.ru ls = &joint->socket_conf->listen; 692*53Sigor@sysoev.ru 693*53Sigor@sysoev.ru listen = nxt_listen_event(task, ls); 694*53Sigor@sysoev.ru if (nxt_slow_path(listen == NULL)) { 695*53Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 696*53Sigor@sysoev.ru return; 697*53Sigor@sysoev.ru } 698*53Sigor@sysoev.ru 699*53Sigor@sysoev.ru listen->socket.data = joint; 700*53Sigor@sysoev.ru } 701*53Sigor@sysoev.ru 702*53Sigor@sysoev.ru 703*53Sigor@sysoev.ru nxt_inline nxt_listen_event_t * 704*53Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections, 705*53Sigor@sysoev.ru nxt_socket_conf_t *skcf) 706*53Sigor@sysoev.ru { 707*53Sigor@sysoev.ru nxt_socket_t socket; 708*53Sigor@sysoev.ru nxt_queue_link_t *link; 709*53Sigor@sysoev.ru nxt_listen_event_t *listen; 710*53Sigor@sysoev.ru 711*53Sigor@sysoev.ru socket = skcf->listen.socket; 712*53Sigor@sysoev.ru 713*53Sigor@sysoev.ru for (link = nxt_queue_first(listen_connections); 714*53Sigor@sysoev.ru link != nxt_queue_tail(listen_connections); 715*53Sigor@sysoev.ru link = nxt_queue_next(link)) 716*53Sigor@sysoev.ru { 717*53Sigor@sysoev.ru listen = nxt_queue_link_data(link, nxt_listen_event_t, link); 718*53Sigor@sysoev.ru 719*53Sigor@sysoev.ru if (socket == listen->socket.fd) { 720*53Sigor@sysoev.ru return listen; 721*53Sigor@sysoev.ru } 722*53Sigor@sysoev.ru } 723*53Sigor@sysoev.ru 724*53Sigor@sysoev.ru return NULL; 725*53Sigor@sysoev.ru } 726*53Sigor@sysoev.ru 727*53Sigor@sysoev.ru 728*53Sigor@sysoev.ru static void 729*53Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 730*53Sigor@sysoev.ru { 731*53Sigor@sysoev.ru nxt_event_engine_t *engine; 732*53Sigor@sysoev.ru nxt_listen_event_t *listen; 733*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old; 734*53Sigor@sysoev.ru 735*53Sigor@sysoev.ru engine = obj; 736*53Sigor@sysoev.ru joint = data; 737*53Sigor@sysoev.ru 738*53Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, 739*53Sigor@sysoev.ru joint->socket_conf); 740*53Sigor@sysoev.ru 741*53Sigor@sysoev.ru old = listen->socket.data; 742*53Sigor@sysoev.ru listen->socket.data = joint; 743*53Sigor@sysoev.ru 744*53Sigor@sysoev.ru nxt_router_conf_release(task, old); 745*53Sigor@sysoev.ru } 746*53Sigor@sysoev.ru 747*53Sigor@sysoev.ru 748*53Sigor@sysoev.ru static void 749*53Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 750*53Sigor@sysoev.ru { 751*53Sigor@sysoev.ru nxt_socket_conf_t *skcf; 752*53Sigor@sysoev.ru nxt_listen_event_t *listen; 753*53Sigor@sysoev.ru nxt_event_engine_t *engine; 754*53Sigor@sysoev.ru 755*53Sigor@sysoev.ru engine = obj; 756*53Sigor@sysoev.ru skcf = data; 757*53Sigor@sysoev.ru 758*53Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, skcf); 759*53Sigor@sysoev.ru 760*53Sigor@sysoev.ru nxt_fd_event_delete(engine, &listen->socket); 761*53Sigor@sysoev.ru 762*53Sigor@sysoev.ru listen->timer.handler = nxt_router_listen_socket_close; 763*53Sigor@sysoev.ru listen->timer.work_queue = &engine->fast_work_queue; 764*53Sigor@sysoev.ru 765*53Sigor@sysoev.ru nxt_timer_add(engine, &listen->timer, 0); 766*53Sigor@sysoev.ru } 767*53Sigor@sysoev.ru 768*53Sigor@sysoev.ru 769*53Sigor@sysoev.ru static void 770*53Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 771*53Sigor@sysoev.ru { 772*53Sigor@sysoev.ru nxt_timer_t *timer; 773*53Sigor@sysoev.ru nxt_listen_event_t *listen; 774*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 775*53Sigor@sysoev.ru 776*53Sigor@sysoev.ru timer = obj; 777*53Sigor@sysoev.ru listen = nxt_timer_data(timer, nxt_listen_event_t, timer); 778*53Sigor@sysoev.ru joint = listen->socket.data; 779*53Sigor@sysoev.ru 780*53Sigor@sysoev.ru nxt_queue_remove(&listen->link); 781*53Sigor@sysoev.ru nxt_free(listen); 782*53Sigor@sysoev.ru 783*53Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 784*53Sigor@sysoev.ru } 785*53Sigor@sysoev.ru 786*53Sigor@sysoev.ru 787*53Sigor@sysoev.ru static void 788*53Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, 789*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint) 790*53Sigor@sysoev.ru { 791*53Sigor@sysoev.ru nxt_socket_t s; 792*53Sigor@sysoev.ru nxt_listen_socket_t *ls; 793*53Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 794*53Sigor@sysoev.ru 795*53Sigor@sysoev.ru s = -1; 796*53Sigor@sysoev.ru ls = &joint->socket_conf->listen; 797*53Sigor@sysoev.ru lock = &joint->socket_conf->router_conf->router->lock; 798*53Sigor@sysoev.ru 799*53Sigor@sysoev.ru nxt_thread_spin_lock(lock); 800*53Sigor@sysoev.ru 801*53Sigor@sysoev.ru if (--ls->count == 0) { 802*53Sigor@sysoev.ru s = ls->socket; 803*53Sigor@sysoev.ru ls->socket = -1; 804*53Sigor@sysoev.ru } 805*53Sigor@sysoev.ru 806*53Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 807*53Sigor@sysoev.ru 808*53Sigor@sysoev.ru if (s != -1) { 809*53Sigor@sysoev.ru nxt_socket_close(task, s); 810*53Sigor@sysoev.ru } 811*53Sigor@sysoev.ru 812*53Sigor@sysoev.ru nxt_router_conf_release(task, joint); 813*53Sigor@sysoev.ru } 814*53Sigor@sysoev.ru 815*53Sigor@sysoev.ru 816*53Sigor@sysoev.ru static void 817*53Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 818*53Sigor@sysoev.ru { 819*53Sigor@sysoev.ru nxt_socket_conf_t *skcf; 820*53Sigor@sysoev.ru nxt_router_conf_t *rtcf; 821*53Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 822*53Sigor@sysoev.ru 823*53Sigor@sysoev.ru nxt_debug(task, "conf joint count: %D", joint->count); 824*53Sigor@sysoev.ru 825*53Sigor@sysoev.ru if (--joint->count != 0) { 826*53Sigor@sysoev.ru return; 827*53Sigor@sysoev.ru } 828*53Sigor@sysoev.ru 829*53Sigor@sysoev.ru nxt_queue_remove(&joint->link); 830*53Sigor@sysoev.ru 831*53Sigor@sysoev.ru skcf = joint->socket_conf; 832*53Sigor@sysoev.ru rtcf = skcf->router_conf; 833*53Sigor@sysoev.ru lock = &rtcf->router->lock; 834*53Sigor@sysoev.ru 835*53Sigor@sysoev.ru nxt_thread_spin_lock(lock); 836*53Sigor@sysoev.ru 837*53Sigor@sysoev.ru if (--skcf->count != 0) { 838*53Sigor@sysoev.ru rtcf = NULL; 839*53Sigor@sysoev.ru 840*53Sigor@sysoev.ru } else { 841*53Sigor@sysoev.ru nxt_queue_remove(&skcf->link); 842*53Sigor@sysoev.ru 843*53Sigor@sysoev.ru if (--rtcf->count != 0) { 844*53Sigor@sysoev.ru rtcf = NULL; 845*53Sigor@sysoev.ru } 846*53Sigor@sysoev.ru } 847*53Sigor@sysoev.ru 848*53Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 849*53Sigor@sysoev.ru 850*53Sigor@sysoev.ru if (rtcf != NULL) { 851*53Sigor@sysoev.ru nxt_mem_pool_destroy(rtcf->mem_pool); 852*53Sigor@sysoev.ru } 853*53Sigor@sysoev.ru 854*53Sigor@sysoev.ru if (nxt_queue_is_empty(&joint->engine->joints)) { 855*53Sigor@sysoev.ru nxt_thread_exit(task->thread); 856*53Sigor@sysoev.ru } 857*53Sigor@sysoev.ru } 858*53Sigor@sysoev.ru 859*53Sigor@sysoev.ru 860*53Sigor@sysoev.ru static void 861*53Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 862*53Sigor@sysoev.ru { 863*53Sigor@sysoev.ru nxt_thread_link_t *link; 864*53Sigor@sysoev.ru nxt_event_engine_t *engine; 865*53Sigor@sysoev.ru nxt_thread_handle_t handle; 866*53Sigor@sysoev.ru 867*53Sigor@sysoev.ru handle = obj; 868*53Sigor@sysoev.ru link = data; 869*53Sigor@sysoev.ru 870*53Sigor@sysoev.ru nxt_thread_wait(handle); 871*53Sigor@sysoev.ru 872*53Sigor@sysoev.ru engine = link->engine; 873*53Sigor@sysoev.ru 874*53Sigor@sysoev.ru nxt_queue_remove(&engine->link); 875*53Sigor@sysoev.ru 876*53Sigor@sysoev.ru nxt_mem_cache_pool_destroy(engine->mem_pool); 877*53Sigor@sysoev.ru 878*53Sigor@sysoev.ru nxt_event_engine_free(engine); 879*53Sigor@sysoev.ru 880*53Sigor@sysoev.ru nxt_free(link); 881*53Sigor@sysoev.ru 882*53Sigor@sysoev.ru // TODO: free port 883*53Sigor@sysoev.ru } 884*53Sigor@sysoev.ru 885*53Sigor@sysoev.ru 886*53Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_router_conn_read_state 887*53Sigor@sysoev.ru nxt_aligned(64) = 888*53Sigor@sysoev.ru { 889*53Sigor@sysoev.ru .ready_handler = nxt_router_conn_http_header_parse, 890*53Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 891*53Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 892*53Sigor@sysoev.ru 893*53Sigor@sysoev.ru .timer_handler = nxt_router_conn_timeout, 894*53Sigor@sysoev.ru .timer_value = nxt_router_conn_timeout_value, 895*53Sigor@sysoev.ru .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 896*53Sigor@sysoev.ru }; 897*53Sigor@sysoev.ru 898*53Sigor@sysoev.ru 899*53Sigor@sysoev.ru static void 900*53Sigor@sysoev.ru nxt_router_conn_init(nxt_task_t *task, void *obj, void *data) 901*53Sigor@sysoev.ru { 902*53Sigor@sysoev.ru size_t size; 903*53Sigor@sysoev.ru nxt_event_conn_t *c; 904*53Sigor@sysoev.ru nxt_event_engine_t *engine; 905*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 906*53Sigor@sysoev.ru 907*53Sigor@sysoev.ru c = obj; 908*53Sigor@sysoev.ru joint = data; 909*53Sigor@sysoev.ru 910*53Sigor@sysoev.ru nxt_debug(task, "router conn init"); 911*53Sigor@sysoev.ru 912*53Sigor@sysoev.ru joint->count++; 913*53Sigor@sysoev.ru 914*53Sigor@sysoev.ru size = joint->socket_conf->header_buffer_size; 915*53Sigor@sysoev.ru c->read = nxt_buf_mem_alloc(c->mem_pool, size, 0); 916*53Sigor@sysoev.ru 917*53Sigor@sysoev.ru c->socket.data = NULL; 918*53Sigor@sysoev.ru 919*53Sigor@sysoev.ru engine = task->thread->engine; 920*53Sigor@sysoev.ru c->read_work_queue = &engine->fast_work_queue; 921*53Sigor@sysoev.ru c->write_work_queue = &engine->fast_work_queue; 922*53Sigor@sysoev.ru 923*53Sigor@sysoev.ru c->read_state = &nxt_router_conn_read_state; 924*53Sigor@sysoev.ru 925*53Sigor@sysoev.ru nxt_event_conn_read(engine, c); 926*53Sigor@sysoev.ru } 927*53Sigor@sysoev.ru 928*53Sigor@sysoev.ru 929*53Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_router_conn_write_state 930*53Sigor@sysoev.ru nxt_aligned(64) = 931*53Sigor@sysoev.ru { 932*53Sigor@sysoev.ru .ready_handler = nxt_router_conn_close, 933*53Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 934*53Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 935*53Sigor@sysoev.ru }; 936*53Sigor@sysoev.ru 937*53Sigor@sysoev.ru 938*53Sigor@sysoev.ru static void 939*53Sigor@sysoev.ru nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, void *data) 940*53Sigor@sysoev.ru { 941*53Sigor@sysoev.ru size_t size; 942*53Sigor@sysoev.ru nxt_int_t ret; 943*53Sigor@sysoev.ru nxt_buf_t *b; 944*53Sigor@sysoev.ru nxt_event_conn_t *c; 945*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 946*53Sigor@sysoev.ru nxt_http_request_parse_t *rp; 947*53Sigor@sysoev.ru 948*53Sigor@sysoev.ru c = obj; 949*53Sigor@sysoev.ru rp = data; 950*53Sigor@sysoev.ru 951*53Sigor@sysoev.ru nxt_debug(task, "router conn http header parse"); 952*53Sigor@sysoev.ru 953*53Sigor@sysoev.ru if (rp == NULL) { 954*53Sigor@sysoev.ru rp = nxt_mem_zalloc(c->mem_pool, sizeof(nxt_http_request_parse_t)); 955*53Sigor@sysoev.ru if (nxt_slow_path(rp == NULL)) { 956*53Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 957*53Sigor@sysoev.ru return; 958*53Sigor@sysoev.ru } 959*53Sigor@sysoev.ru 960*53Sigor@sysoev.ru c->socket.data = rp; 961*53Sigor@sysoev.ru } 962*53Sigor@sysoev.ru 963*53Sigor@sysoev.ru ret = nxt_http_parse_request(rp, &c->read->mem); 964*53Sigor@sysoev.ru 965*53Sigor@sysoev.ru nxt_debug(task, "http parse request: %d", ret); 966*53Sigor@sysoev.ru 967*53Sigor@sysoev.ru switch (nxt_expect(NXT_DONE, ret)) { 968*53Sigor@sysoev.ru 969*53Sigor@sysoev.ru case NXT_DONE: 970*53Sigor@sysoev.ru break; 971*53Sigor@sysoev.ru 972*53Sigor@sysoev.ru case NXT_ERROR: 973*53Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 974*53Sigor@sysoev.ru return; 975*53Sigor@sysoev.ru 976*53Sigor@sysoev.ru default: /* NXT_AGAIN */ 977*53Sigor@sysoev.ru 978*53Sigor@sysoev.ru if (c->read->mem.free == c->read->mem.end) { 979*53Sigor@sysoev.ru joint = c->listen->socket.data; 980*53Sigor@sysoev.ru size = joint->socket_conf->large_header_buffer_size, 981*53Sigor@sysoev.ru 982*53Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 983*53Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 984*53Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 985*53Sigor@sysoev.ru return; 986*53Sigor@sysoev.ru } 987*53Sigor@sysoev.ru 988*53Sigor@sysoev.ru size = c->read->mem.free - c->read->mem.pos; 989*53Sigor@sysoev.ru nxt_memcpy(b->mem.pos, c->read->mem.pos, size); 990*53Sigor@sysoev.ru 991*53Sigor@sysoev.ru b->mem.free += size; 992*53Sigor@sysoev.ru c->read = b; 993*53Sigor@sysoev.ru } 994*53Sigor@sysoev.ru 995*53Sigor@sysoev.ru nxt_event_conn_read(task->thread->engine, c); 996*53Sigor@sysoev.ru return; 997*53Sigor@sysoev.ru } 998*53Sigor@sysoev.ru 999*53Sigor@sysoev.ru c->write = c->read; 1000*53Sigor@sysoev.ru c->write->mem.pos = c->write->mem.start; 1001*53Sigor@sysoev.ru c->write_state = &nxt_router_conn_write_state; 1002*53Sigor@sysoev.ru 1003*53Sigor@sysoev.ru nxt_event_conn_write(task->thread->engine, c); 1004*53Sigor@sysoev.ru } 1005*53Sigor@sysoev.ru 1006*53Sigor@sysoev.ru 1007*53Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_router_conn_close_state 1008*53Sigor@sysoev.ru nxt_aligned(64) = 1009*53Sigor@sysoev.ru { 1010*53Sigor@sysoev.ru .ready_handler = nxt_router_conn_free, 1011*53Sigor@sysoev.ru }; 1012*53Sigor@sysoev.ru 1013*53Sigor@sysoev.ru 1014*53Sigor@sysoev.ru static void 1015*53Sigor@sysoev.ru nxt_router_conn_close(nxt_task_t *task, void *obj, void *data) 1016*53Sigor@sysoev.ru { 1017*53Sigor@sysoev.ru nxt_event_conn_t *c; 1018*53Sigor@sysoev.ru 1019*53Sigor@sysoev.ru c = obj; 1020*53Sigor@sysoev.ru 1021*53Sigor@sysoev.ru nxt_debug(task, "router conn close"); 1022*53Sigor@sysoev.ru 1023*53Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 1024*53Sigor@sysoev.ru 1025*53Sigor@sysoev.ru nxt_event_conn_close(task->thread->engine, c); 1026*53Sigor@sysoev.ru } 1027*53Sigor@sysoev.ru 1028*53Sigor@sysoev.ru 1029*53Sigor@sysoev.ru static void 1030*53Sigor@sysoev.ru nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) 1031*53Sigor@sysoev.ru { 1032*53Sigor@sysoev.ru nxt_event_conn_t *c; 1033*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 1034*53Sigor@sysoev.ru 1035*53Sigor@sysoev.ru c = obj; 1036*53Sigor@sysoev.ru 1037*53Sigor@sysoev.ru nxt_debug(task, "router conn close done"); 1038*53Sigor@sysoev.ru 1039*53Sigor@sysoev.ru joint = c->listen->socket.data; 1040*53Sigor@sysoev.ru nxt_router_conf_release(task, joint); 1041*53Sigor@sysoev.ru 1042*53Sigor@sysoev.ru nxt_mem_pool_destroy(c->mem_pool); 1043*53Sigor@sysoev.ru } 1044*53Sigor@sysoev.ru 1045*53Sigor@sysoev.ru 1046*53Sigor@sysoev.ru static void 1047*53Sigor@sysoev.ru nxt_router_conn_error(nxt_task_t *task, void *obj, void *data) 1048*53Sigor@sysoev.ru { 1049*53Sigor@sysoev.ru nxt_event_conn_t *c; 1050*53Sigor@sysoev.ru 1051*53Sigor@sysoev.ru c = obj; 1052*53Sigor@sysoev.ru 1053*53Sigor@sysoev.ru nxt_debug(task, "router conn error"); 1054*53Sigor@sysoev.ru 1055*53Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 1056*53Sigor@sysoev.ru 1057*53Sigor@sysoev.ru nxt_event_conn_close(task->thread->engine, c); 1058*53Sigor@sysoev.ru } 1059*53Sigor@sysoev.ru 1060*53Sigor@sysoev.ru 1061*53Sigor@sysoev.ru static void 1062*53Sigor@sysoev.ru nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) 1063*53Sigor@sysoev.ru { 1064*53Sigor@sysoev.ru nxt_timer_t *timer; 1065*53Sigor@sysoev.ru nxt_event_conn_t *c; 1066*53Sigor@sysoev.ru 1067*53Sigor@sysoev.ru timer = obj; 1068*53Sigor@sysoev.ru 1069*53Sigor@sysoev.ru nxt_debug(task, "router conn timeout"); 1070*53Sigor@sysoev.ru 1071*53Sigor@sysoev.ru c = nxt_event_read_timer_conn(timer); 1072*53Sigor@sysoev.ru 1073*53Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 1074*53Sigor@sysoev.ru 1075*53Sigor@sysoev.ru nxt_event_conn_close(task->thread->engine, c); 1076*53Sigor@sysoev.ru } 1077*53Sigor@sysoev.ru 1078*53Sigor@sysoev.ru 1079*53Sigor@sysoev.ru static nxt_msec_t 1080*53Sigor@sysoev.ru nxt_router_conn_timeout_value(nxt_event_conn_t *c, uintptr_t data) 1081*53Sigor@sysoev.ru { 1082*53Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 1083*53Sigor@sysoev.ru 1084*53Sigor@sysoev.ru joint = c->listen->socket.data; 1085*53Sigor@sysoev.ru 1086*53Sigor@sysoev.ru return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 1087*53Sigor@sysoev.ru } 1088