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 23167Smax.romanov@nginx.com typedef struct nxt_req_app_link_s nxt_req_app_link_t; 24141Smax.romanov@nginx.com typedef struct nxt_start_worker_s nxt_start_worker_t; 25141Smax.romanov@nginx.com 26141Smax.romanov@nginx.com struct nxt_start_worker_s { 27141Smax.romanov@nginx.com nxt_app_t *app; 28167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 29141Smax.romanov@nginx.com 30141Smax.romanov@nginx.com nxt_work_t work; 31141Smax.romanov@nginx.com }; 32141Smax.romanov@nginx.com 33141Smax.romanov@nginx.com 34167Smax.romanov@nginx.com struct nxt_req_app_link_s { 35167Smax.romanov@nginx.com nxt_req_id_t req_id; 36167Smax.romanov@nginx.com nxt_port_t *app_port; 37167Smax.romanov@nginx.com nxt_port_t *reply_port; 38167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 39167Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 40167Smax.romanov@nginx.com 41167Smax.romanov@nginx.com nxt_queue_link_t link; /* for nxt_app_t.requests */ 42167Smax.romanov@nginx.com 43167Smax.romanov@nginx.com nxt_mp_t *mem_pool; 44167Smax.romanov@nginx.com nxt_work_t work; 45167Smax.romanov@nginx.com }; 46167Smax.romanov@nginx.com 47167Smax.romanov@nginx.com 48198Sigor@sysoev.ru typedef struct { 49198Sigor@sysoev.ru nxt_socket_conf_t *socket_conf; 50198Sigor@sysoev.ru nxt_router_temp_conf_t *temp_conf; 51198Sigor@sysoev.ru } nxt_socket_rpc_t; 52198Sigor@sysoev.ru 53198Sigor@sysoev.ru 54139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); 55198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); 56198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task, 57139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 58139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task, 59139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 60139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task, 61193Smax.romanov@nginx.com nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); 6253Sigor@sysoev.ru static void nxt_router_listen_sockets_sort(nxt_router_t *router, 6353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 6453Sigor@sysoev.ru 65115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task, 66115Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); 67133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); 68133Sigor@sysoev.ru static nxt_app_t *nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, 69133Sigor@sysoev.ru nxt_str_t *name); 70198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task, 71198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf); 72198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task, 73198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 74198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task, 75198Sigor@sysoev.ru nxt_port_recv_msg_t *msg, void *data); 7665Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, 7765Sigor@sysoev.ru nxt_sockaddr_t *sa); 7853Sigor@sysoev.ru 7953Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task, 8053Sigor@sysoev.ru nxt_router_t *router, nxt_router_temp_conf_t *tmcf, 8153Sigor@sysoev.ru const nxt_event_interface_t *interface); 82115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 83115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 84115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 85115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 86115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 87115Sigor@sysoev.ru nxt_router_engine_conf_t *recf); 88115Sigor@sysoev.ru static void nxt_router_engine_socket_count(nxt_queue_t *sockets); 89154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 90154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 91154Sigor@sysoev.ru nxt_work_handler_t handler); 92139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 93139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets); 9453Sigor@sysoev.ru 9553Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 9653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 9753Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 9853Sigor@sysoev.ru nxt_event_engine_t *engine); 99133Sigor@sysoev.ru static void nxt_router_apps_sort(nxt_router_t *router, 100133Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf); 10153Sigor@sysoev.ru 10253Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_temp_conf_t *tmcf); 103154Sigor@sysoev.ru static void nxt_router_engine_post(nxt_router_engine_conf_t *recf); 10453Sigor@sysoev.ru 10553Sigor@sysoev.ru static void nxt_router_thread_start(void *data); 10653Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj, 10753Sigor@sysoev.ru void *data); 10853Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj, 10953Sigor@sysoev.ru void *data); 11053Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, 11153Sigor@sysoev.ru void *data); 11253Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj, 11353Sigor@sysoev.ru void *data); 11453Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task, 11553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 11653Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, 11753Sigor@sysoev.ru void *data); 11853Sigor@sysoev.ru static void nxt_router_conf_release(nxt_task_t *task, 11953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint); 12053Sigor@sysoev.ru 121167Smax.romanov@nginx.com static void nxt_router_send_sw_request(nxt_task_t *task, void *obj, 122167Smax.romanov@nginx.com void *data); 123167Smax.romanov@nginx.com static nxt_bool_t nxt_router_app_free(nxt_task_t *task, nxt_app_t *app); 124167Smax.romanov@nginx.com static nxt_port_t * nxt_router_app_get_port(nxt_app_t *app, uint32_t req_id); 125141Smax.romanov@nginx.com static void nxt_router_app_release_port(nxt_task_t *task, void *obj, 126141Smax.romanov@nginx.com void *data); 127141Smax.romanov@nginx.com 12853Sigor@sysoev.ru static void nxt_router_conn_init(nxt_task_t *task, void *obj, void *data); 12953Sigor@sysoev.ru static void nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, 13053Sigor@sysoev.ru void *data); 131206Smax.romanov@nginx.com static void nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, 132206Smax.romanov@nginx.com void *data); 13388Smax.romanov@nginx.com static void nxt_router_process_http_request(nxt_task_t *task, 13488Smax.romanov@nginx.com nxt_conn_t *c, nxt_app_parse_ctx_t *ap); 135141Smax.romanov@nginx.com static void nxt_router_process_http_request_mp(nxt_task_t *task, 136167Smax.romanov@nginx.com nxt_req_app_link_t *ra, nxt_port_t *port); 137216Sigor@sysoev.ru static nxt_int_t nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 138216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 139216Sigor@sysoev.ru static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 140216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 141216Sigor@sysoev.ru static nxt_int_t nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 142216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg); 14388Smax.romanov@nginx.com static void nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data); 14453Sigor@sysoev.ru static void nxt_router_conn_close(nxt_task_t *task, void *obj, void *data); 14553Sigor@sysoev.ru static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data); 14653Sigor@sysoev.ru static void nxt_router_conn_error(nxt_task_t *task, void *obj, void *data); 14753Sigor@sysoev.ru static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data); 14862Sigor@sysoev.ru static nxt_msec_t nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data); 14920Sigor@sysoev.ru 150141Smax.romanov@nginx.com static void nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 151141Smax.romanov@nginx.com const char* fmt, ...); 152141Smax.romanov@nginx.com 153119Smax.romanov@nginx.com static nxt_router_t *nxt_router; 15420Sigor@sysoev.ru 155216Sigor@sysoev.ru 156216Sigor@sysoev.ru static nxt_app_prepare_msg_t nxt_app_prepare_msg[] = { 157216Sigor@sysoev.ru nxt_python_prepare_msg, 158216Sigor@sysoev.ru nxt_php_prepare_msg, 159216Sigor@sysoev.ru nxt_go_prepare_msg, 160216Sigor@sysoev.ru }; 161216Sigor@sysoev.ru 162216Sigor@sysoev.ru 16320Sigor@sysoev.ru nxt_int_t 164141Smax.romanov@nginx.com nxt_router_start(nxt_task_t *task, void *data) 16520Sigor@sysoev.ru { 166141Smax.romanov@nginx.com nxt_int_t ret; 167141Smax.romanov@nginx.com nxt_router_t *router; 168141Smax.romanov@nginx.com nxt_runtime_t *rt; 169141Smax.romanov@nginx.com 170141Smax.romanov@nginx.com rt = task->thread->runtime; 17153Sigor@sysoev.ru 17288Smax.romanov@nginx.com ret = nxt_app_http_init(task, rt); 17388Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 17488Smax.romanov@nginx.com return ret; 17588Smax.romanov@nginx.com } 17688Smax.romanov@nginx.com 17753Sigor@sysoev.ru router = nxt_zalloc(sizeof(nxt_router_t)); 17853Sigor@sysoev.ru if (nxt_slow_path(router == NULL)) { 17953Sigor@sysoev.ru return NXT_ERROR; 18053Sigor@sysoev.ru } 18153Sigor@sysoev.ru 18253Sigor@sysoev.ru nxt_queue_init(&router->engines); 18353Sigor@sysoev.ru nxt_queue_init(&router->sockets); 184133Sigor@sysoev.ru nxt_queue_init(&router->apps); 18553Sigor@sysoev.ru 186119Smax.romanov@nginx.com nxt_router = router; 187119Smax.romanov@nginx.com 188115Sigor@sysoev.ru return NXT_OK; 189115Sigor@sysoev.ru } 190115Sigor@sysoev.ru 191115Sigor@sysoev.ru 192167Smax.romanov@nginx.com static nxt_start_worker_t * 193192Smax.romanov@nginx.com nxt_router_sw_create(nxt_task_t *task, nxt_app_t *app, nxt_req_app_link_t *ra) 194167Smax.romanov@nginx.com { 195240Sigor@sysoev.ru nxt_port_t *main_port; 196167Smax.romanov@nginx.com nxt_runtime_t *rt; 197167Smax.romanov@nginx.com nxt_start_worker_t *sw; 198167Smax.romanov@nginx.com 199192Smax.romanov@nginx.com sw = nxt_zalloc(sizeof(nxt_start_worker_t)); 200167Smax.romanov@nginx.com 201167Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 202167Smax.romanov@nginx.com return NULL; 203167Smax.romanov@nginx.com } 204167Smax.romanov@nginx.com 205167Smax.romanov@nginx.com sw->app = app; 206167Smax.romanov@nginx.com sw->ra = ra; 207167Smax.romanov@nginx.com 208192Smax.romanov@nginx.com nxt_debug(task, "sw %p create, request #%uxD, app '%V' %p", sw, 209167Smax.romanov@nginx.com ra->req_id, &app->name, app); 210167Smax.romanov@nginx.com 211167Smax.romanov@nginx.com rt = task->thread->runtime; 212240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 213167Smax.romanov@nginx.com 214167Smax.romanov@nginx.com sw->work.handler = nxt_router_send_sw_request; 215240Sigor@sysoev.ru sw->work.task = &main_port->engine->task; 216167Smax.romanov@nginx.com sw->work.obj = sw; 217167Smax.romanov@nginx.com sw->work.data = task->thread->engine; 218167Smax.romanov@nginx.com sw->work.next = NULL; 219167Smax.romanov@nginx.com 220240Sigor@sysoev.ru if (task->thread->engine != main_port->engine) { 221240Sigor@sysoev.ru nxt_debug(task, "sw %p post send to main engine %p", sw, 222240Sigor@sysoev.ru main_port->engine); 223240Sigor@sysoev.ru 224240Sigor@sysoev.ru nxt_event_engine_post(main_port->engine, &sw->work); 225167Smax.romanov@nginx.com 226167Smax.romanov@nginx.com } else { 227167Smax.romanov@nginx.com nxt_router_send_sw_request(task, sw, sw->work.data); 228167Smax.romanov@nginx.com } 229167Smax.romanov@nginx.com 230167Smax.romanov@nginx.com return sw; 231167Smax.romanov@nginx.com } 232167Smax.romanov@nginx.com 233167Smax.romanov@nginx.com 234192Smax.romanov@nginx.com nxt_inline void 235192Smax.romanov@nginx.com nxt_router_sw_release(nxt_task_t *task, nxt_start_worker_t *sw) 236141Smax.romanov@nginx.com { 237192Smax.romanov@nginx.com nxt_debug(task, "sw %p release", sw); 238192Smax.romanov@nginx.com 239192Smax.romanov@nginx.com nxt_free(sw); 240141Smax.romanov@nginx.com } 241141Smax.romanov@nginx.com 242141Smax.romanov@nginx.com 243167Smax.romanov@nginx.com static nxt_req_app_link_t * 244167Smax.romanov@nginx.com nxt_router_ra_create(nxt_task_t *task, nxt_req_conn_link_t *rc) 245167Smax.romanov@nginx.com { 246167Smax.romanov@nginx.com nxt_mp_t *mp; 247167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 248167Smax.romanov@nginx.com 249167Smax.romanov@nginx.com mp = rc->conn->mem_pool; 250167Smax.romanov@nginx.com 251167Smax.romanov@nginx.com ra = nxt_mp_retain(mp, sizeof(nxt_req_app_link_t)); 252167Smax.romanov@nginx.com 253167Smax.romanov@nginx.com if (nxt_slow_path(ra == NULL)) { 254167Smax.romanov@nginx.com return NULL; 255167Smax.romanov@nginx.com } 256167Smax.romanov@nginx.com 257167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD create", ra->req_id); 258167Smax.romanov@nginx.com 259167Smax.romanov@nginx.com nxt_memzero(ra, sizeof(nxt_req_app_link_t)); 260167Smax.romanov@nginx.com 261167Smax.romanov@nginx.com ra->req_id = rc->req_id; 262167Smax.romanov@nginx.com ra->app_port = NULL; 263167Smax.romanov@nginx.com ra->rc = rc; 264167Smax.romanov@nginx.com 265167Smax.romanov@nginx.com ra->mem_pool = mp; 266167Smax.romanov@nginx.com 267167Smax.romanov@nginx.com ra->work.handler = NULL; 268167Smax.romanov@nginx.com ra->work.task = &task->thread->engine->task; 269167Smax.romanov@nginx.com ra->work.obj = ra; 270167Smax.romanov@nginx.com ra->work.data = task->thread->engine; 271167Smax.romanov@nginx.com 272167Smax.romanov@nginx.com return ra; 273167Smax.romanov@nginx.com } 274167Smax.romanov@nginx.com 275167Smax.romanov@nginx.com 276167Smax.romanov@nginx.com static void 277167Smax.romanov@nginx.com nxt_router_ra_release(nxt_task_t *task, void *obj, void *data) 278167Smax.romanov@nginx.com { 279167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 280167Smax.romanov@nginx.com nxt_event_engine_t *engine; 281167Smax.romanov@nginx.com 282167Smax.romanov@nginx.com ra = obj; 283167Smax.romanov@nginx.com engine = data; 284167Smax.romanov@nginx.com 285167Smax.romanov@nginx.com if (task->thread->engine != engine) { 286167Smax.romanov@nginx.com ra->work.handler = nxt_router_ra_release; 287167Smax.romanov@nginx.com ra->work.task = &engine->task; 288167Smax.romanov@nginx.com ra->work.next = NULL; 289167Smax.romanov@nginx.com 290167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD post release to %p", ra->req_id, engine); 291167Smax.romanov@nginx.com 292167Smax.romanov@nginx.com nxt_event_engine_post(engine, &ra->work); 293167Smax.romanov@nginx.com 294167Smax.romanov@nginx.com return; 295167Smax.romanov@nginx.com } 296167Smax.romanov@nginx.com 297167Smax.romanov@nginx.com nxt_debug(task, "ra #%uxD release", ra->req_id); 298167Smax.romanov@nginx.com 299167Smax.romanov@nginx.com if (ra->app_port != NULL) { 300167Smax.romanov@nginx.com 301*264Smax.romanov@nginx.com nxt_router_app_release_port(task, ra->app_port, ra->app_port->app); 302*264Smax.romanov@nginx.com 303*264Smax.romanov@nginx.com #if 0 304*264Smax.romanov@nginx.com /* Uncomment to hold app port until complete response received. */ 305167Smax.romanov@nginx.com if (ra->rc->conn != NULL) { 306167Smax.romanov@nginx.com ra->rc->app_port = ra->app_port; 307167Smax.romanov@nginx.com 308167Smax.romanov@nginx.com } else { 309167Smax.romanov@nginx.com nxt_router_app_release_port(task, ra->app_port, ra->app_port->app); 310167Smax.romanov@nginx.com } 311*264Smax.romanov@nginx.com #endif 312167Smax.romanov@nginx.com } 313167Smax.romanov@nginx.com 314167Smax.romanov@nginx.com nxt_mp_release(ra->mem_pool, ra); 315167Smax.romanov@nginx.com } 316167Smax.romanov@nginx.com 317167Smax.romanov@nginx.com 318141Smax.romanov@nginx.com void 319141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 320141Smax.romanov@nginx.com { 321141Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 322141Smax.romanov@nginx.com 323192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 324141Smax.romanov@nginx.com return; 325141Smax.romanov@nginx.com } 326141Smax.romanov@nginx.com 327192Smax.romanov@nginx.com if (msg->new_port == NULL || msg->new_port->type != NXT_PROCESS_WORKER) { 328192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 329141Smax.romanov@nginx.com } 330192Smax.romanov@nginx.com 331192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 332141Smax.romanov@nginx.com } 333141Smax.romanov@nginx.com 334141Smax.romanov@nginx.com 335139Sigor@sysoev.ru void 336139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 337115Sigor@sysoev.ru { 338139Sigor@sysoev.ru size_t dump_size; 339198Sigor@sysoev.ru nxt_int_t ret; 340139Sigor@sysoev.ru nxt_buf_t *b; 341139Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 342139Sigor@sysoev.ru 343139Sigor@sysoev.ru b = msg->buf; 344139Sigor@sysoev.ru 345139Sigor@sysoev.ru dump_size = nxt_buf_used_size(b); 346139Sigor@sysoev.ru 347139Sigor@sysoev.ru if (dump_size > 300) { 348139Sigor@sysoev.ru dump_size = 300; 34953Sigor@sysoev.ru } 35053Sigor@sysoev.ru 351139Sigor@sysoev.ru nxt_debug(task, "router conf data (%z): %*s", 352139Sigor@sysoev.ru msg->size, dump_size, b->mem.pos); 353139Sigor@sysoev.ru 354139Sigor@sysoev.ru tmcf = nxt_router_temp_conf(task); 355139Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 356139Sigor@sysoev.ru return; 35753Sigor@sysoev.ru } 35853Sigor@sysoev.ru 359139Sigor@sysoev.ru tmcf->conf->router = nxt_router; 360139Sigor@sysoev.ru tmcf->stream = msg->port_msg.stream; 361139Sigor@sysoev.ru tmcf->port = nxt_runtime_port_find(task->thread->runtime, 362198Sigor@sysoev.ru msg->port_msg.pid, 363198Sigor@sysoev.ru msg->port_msg.reply_port); 364198Sigor@sysoev.ru 365198Sigor@sysoev.ru ret = nxt_router_conf_create(task, tmcf, b->mem.pos, b->mem.free); 366198Sigor@sysoev.ru 367198Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK)) { 368198Sigor@sysoev.ru nxt_router_conf_apply(task, tmcf, NULL); 369198Sigor@sysoev.ru 370198Sigor@sysoev.ru } else { 371198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 372139Sigor@sysoev.ru } 37353Sigor@sysoev.ru } 37453Sigor@sysoev.ru 37553Sigor@sysoev.ru 376192Smax.romanov@nginx.com void 377192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 378192Smax.romanov@nginx.com { 379192Smax.romanov@nginx.com nxt_port_remove_pid_handler(task, msg); 380192Smax.romanov@nginx.com 381192Smax.romanov@nginx.com if (msg->port_msg.stream == 0) { 382192Smax.romanov@nginx.com return; 383192Smax.romanov@nginx.com } 384192Smax.romanov@nginx.com 385192Smax.romanov@nginx.com msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR; 386192Smax.romanov@nginx.com 387192Smax.romanov@nginx.com nxt_port_rpc_handler(task, msg); 388192Smax.romanov@nginx.com } 389192Smax.romanov@nginx.com 390192Smax.romanov@nginx.com 39153Sigor@sysoev.ru static nxt_router_temp_conf_t * 392139Sigor@sysoev.ru nxt_router_temp_conf(nxt_task_t *task) 39353Sigor@sysoev.ru { 39465Sigor@sysoev.ru nxt_mp_t *mp, *tmp; 39553Sigor@sysoev.ru nxt_router_conf_t *rtcf; 39653Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 39753Sigor@sysoev.ru 39865Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 39953Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 40053Sigor@sysoev.ru return NULL; 40153Sigor@sysoev.ru } 40253Sigor@sysoev.ru 40365Sigor@sysoev.ru rtcf = nxt_mp_zget(mp, sizeof(nxt_router_conf_t)); 40453Sigor@sysoev.ru if (nxt_slow_path(rtcf == NULL)) { 40553Sigor@sysoev.ru goto fail; 40653Sigor@sysoev.ru } 40753Sigor@sysoev.ru 40853Sigor@sysoev.ru rtcf->mem_pool = mp; 40953Sigor@sysoev.ru 41065Sigor@sysoev.ru tmp = nxt_mp_create(1024, 128, 256, 32); 41153Sigor@sysoev.ru if (nxt_slow_path(tmp == NULL)) { 41253Sigor@sysoev.ru goto fail; 41353Sigor@sysoev.ru } 41453Sigor@sysoev.ru 41565Sigor@sysoev.ru tmcf = nxt_mp_zget(tmp, sizeof(nxt_router_temp_conf_t)); 41653Sigor@sysoev.ru if (nxt_slow_path(tmcf == NULL)) { 41753Sigor@sysoev.ru goto temp_fail; 41853Sigor@sysoev.ru } 41953Sigor@sysoev.ru 42053Sigor@sysoev.ru tmcf->mem_pool = tmp; 42153Sigor@sysoev.ru tmcf->conf = rtcf; 422139Sigor@sysoev.ru tmcf->count = 1; 423139Sigor@sysoev.ru tmcf->engine = task->thread->engine; 42453Sigor@sysoev.ru 42553Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, 4, 42653Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 42753Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 42853Sigor@sysoev.ru goto temp_fail; 42953Sigor@sysoev.ru } 43053Sigor@sysoev.ru 43153Sigor@sysoev.ru nxt_queue_init(&tmcf->deleting); 43253Sigor@sysoev.ru nxt_queue_init(&tmcf->keeping); 43353Sigor@sysoev.ru nxt_queue_init(&tmcf->updating); 43453Sigor@sysoev.ru nxt_queue_init(&tmcf->pending); 43553Sigor@sysoev.ru nxt_queue_init(&tmcf->creating); 436133Sigor@sysoev.ru nxt_queue_init(&tmcf->apps); 437133Sigor@sysoev.ru nxt_queue_init(&tmcf->previous); 43853Sigor@sysoev.ru 43953Sigor@sysoev.ru return tmcf; 44053Sigor@sysoev.ru 44153Sigor@sysoev.ru temp_fail: 44253Sigor@sysoev.ru 44365Sigor@sysoev.ru nxt_mp_destroy(tmp); 44453Sigor@sysoev.ru 44553Sigor@sysoev.ru fail: 44653Sigor@sysoev.ru 44765Sigor@sysoev.ru nxt_mp_destroy(mp); 44853Sigor@sysoev.ru 44953Sigor@sysoev.ru return NULL; 45053Sigor@sysoev.ru } 45153Sigor@sysoev.ru 45253Sigor@sysoev.ru 453198Sigor@sysoev.ru static void 454198Sigor@sysoev.ru nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) 455139Sigor@sysoev.ru { 456139Sigor@sysoev.ru nxt_int_t ret; 457139Sigor@sysoev.ru nxt_router_t *router; 458139Sigor@sysoev.ru nxt_runtime_t *rt; 459198Sigor@sysoev.ru nxt_queue_link_t *qlk; 460198Sigor@sysoev.ru nxt_socket_conf_t *skcf; 461198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 462139Sigor@sysoev.ru const nxt_event_interface_t *interface; 463139Sigor@sysoev.ru 464198Sigor@sysoev.ru tmcf = obj; 465198Sigor@sysoev.ru 466198Sigor@sysoev.ru qlk = nxt_queue_first(&tmcf->pending); 467198Sigor@sysoev.ru 468198Sigor@sysoev.ru if (qlk != nxt_queue_tail(&tmcf->pending)) { 469198Sigor@sysoev.ru nxt_queue_remove(qlk); 470198Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->creating, qlk); 471198Sigor@sysoev.ru 472198Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 473198Sigor@sysoev.ru 474198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(task, tmcf, skcf); 475198Sigor@sysoev.ru 476198Sigor@sysoev.ru return; 477139Sigor@sysoev.ru } 478139Sigor@sysoev.ru 479139Sigor@sysoev.ru rt = task->thread->runtime; 480139Sigor@sysoev.ru 481139Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 482139Sigor@sysoev.ru 483198Sigor@sysoev.ru router = tmcf->conf->router; 484198Sigor@sysoev.ru 485139Sigor@sysoev.ru ret = nxt_router_engines_create(task, router, tmcf, interface); 486139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 487198Sigor@sysoev.ru goto fail; 488139Sigor@sysoev.ru } 489139Sigor@sysoev.ru 490139Sigor@sysoev.ru ret = nxt_router_threads_create(task, rt, tmcf); 491139Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 492198Sigor@sysoev.ru goto fail; 493139Sigor@sysoev.ru } 494139Sigor@sysoev.ru 495139Sigor@sysoev.ru nxt_router_apps_sort(router, tmcf); 496139Sigor@sysoev.ru 497139Sigor@sysoev.ru nxt_router_engines_post(tmcf); 498139Sigor@sysoev.ru 499139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->updating); 500139Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->creating); 501139Sigor@sysoev.ru 502198Sigor@sysoev.ru nxt_router_conf_ready(task, tmcf); 503198Sigor@sysoev.ru 504198Sigor@sysoev.ru return; 505198Sigor@sysoev.ru 506198Sigor@sysoev.ru fail: 507198Sigor@sysoev.ru 508198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 509198Sigor@sysoev.ru 510198Sigor@sysoev.ru return; 511139Sigor@sysoev.ru } 512139Sigor@sysoev.ru 513139Sigor@sysoev.ru 514139Sigor@sysoev.ru static void 515139Sigor@sysoev.ru nxt_router_conf_wait(nxt_task_t *task, void *obj, void *data) 516139Sigor@sysoev.ru { 517153Sigor@sysoev.ru nxt_joint_job_t *job; 518153Sigor@sysoev.ru 519153Sigor@sysoev.ru job = obj; 520153Sigor@sysoev.ru 521198Sigor@sysoev.ru nxt_router_conf_ready(task, job->tmcf); 522139Sigor@sysoev.ru } 523139Sigor@sysoev.ru 524139Sigor@sysoev.ru 525139Sigor@sysoev.ru static void 526198Sigor@sysoev.ru nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 527139Sigor@sysoev.ru { 528139Sigor@sysoev.ru nxt_debug(task, "temp conf count:%D", tmcf->count); 529139Sigor@sysoev.ru 530139Sigor@sysoev.ru if (--tmcf->count == 0) { 531193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_READY_LAST); 532139Sigor@sysoev.ru } 533139Sigor@sysoev.ru } 534139Sigor@sysoev.ru 535139Sigor@sysoev.ru 536139Sigor@sysoev.ru static void 537139Sigor@sysoev.ru nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 538139Sigor@sysoev.ru { 539148Sigor@sysoev.ru nxt_socket_t s; 540149Sigor@sysoev.ru nxt_router_t *router; 541148Sigor@sysoev.ru nxt_queue_link_t *qlk; 542148Sigor@sysoev.ru nxt_socket_conf_t *skcf; 543148Sigor@sysoev.ru 544198Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "failed to apply new conf"); 545198Sigor@sysoev.ru 546148Sigor@sysoev.ru for (qlk = nxt_queue_first(&tmcf->creating); 547148Sigor@sysoev.ru qlk != nxt_queue_tail(&tmcf->creating); 548148Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 549148Sigor@sysoev.ru { 550148Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 551148Sigor@sysoev.ru s = skcf->listen.socket; 552148Sigor@sysoev.ru 553148Sigor@sysoev.ru if (s != -1) { 554148Sigor@sysoev.ru nxt_socket_close(task, s); 555148Sigor@sysoev.ru } 556148Sigor@sysoev.ru 557148Sigor@sysoev.ru nxt_free(skcf->socket); 558148Sigor@sysoev.ru } 559148Sigor@sysoev.ru 560149Sigor@sysoev.ru router = tmcf->conf->router; 561149Sigor@sysoev.ru 562149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->keeping); 563149Sigor@sysoev.ru nxt_queue_add(&router->sockets, &tmcf->deleting); 564149Sigor@sysoev.ru 565148Sigor@sysoev.ru // TODO: new engines and threads 566148Sigor@sysoev.ru 567139Sigor@sysoev.ru nxt_mp_destroy(tmcf->conf->mem_pool); 568139Sigor@sysoev.ru 569193Smax.romanov@nginx.com nxt_router_conf_send(task, tmcf, NXT_PORT_MSG_RPC_ERROR); 570139Sigor@sysoev.ru } 571139Sigor@sysoev.ru 572139Sigor@sysoev.ru 573139Sigor@sysoev.ru static void 574139Sigor@sysoev.ru nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 575193Smax.romanov@nginx.com nxt_port_msg_type_t type) 576139Sigor@sysoev.ru { 577193Smax.romanov@nginx.com nxt_port_socket_write(task, tmcf->port, type, -1, tmcf->stream, 0, NULL); 578139Sigor@sysoev.ru } 579139Sigor@sysoev.ru 580139Sigor@sysoev.ru 581115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_conf[] = { 582115Sigor@sysoev.ru { 583133Sigor@sysoev.ru nxt_string("listeners_threads"), 584115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 585115Sigor@sysoev.ru offsetof(nxt_router_conf_t, threads), 586115Sigor@sysoev.ru }, 587115Sigor@sysoev.ru }; 588115Sigor@sysoev.ru 589115Sigor@sysoev.ru 590133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_app_conf[] = { 591115Sigor@sysoev.ru { 592133Sigor@sysoev.ru nxt_string("type"), 593115Sigor@sysoev.ru NXT_CONF_MAP_STR, 594133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, type), 595115Sigor@sysoev.ru }, 596115Sigor@sysoev.ru 597115Sigor@sysoev.ru { 598133Sigor@sysoev.ru nxt_string("workers"), 599115Sigor@sysoev.ru NXT_CONF_MAP_INT32, 600133Sigor@sysoev.ru offsetof(nxt_router_app_conf_t, workers), 601133Sigor@sysoev.ru }, 602133Sigor@sysoev.ru }; 603133Sigor@sysoev.ru 604133Sigor@sysoev.ru 605133Sigor@sysoev.ru static nxt_conf_map_t nxt_router_listener_conf[] = { 606133Sigor@sysoev.ru { 607133Sigor@sysoev.ru nxt_string("application"), 608133Sigor@sysoev.ru NXT_CONF_MAP_STR, 609133Sigor@sysoev.ru offsetof(nxt_router_listener_conf_t, application), 610115Sigor@sysoev.ru }, 611115Sigor@sysoev.ru }; 612115Sigor@sysoev.ru 613115Sigor@sysoev.ru 614115Sigor@sysoev.ru static nxt_conf_map_t nxt_router_http_conf[] = { 615115Sigor@sysoev.ru { 616115Sigor@sysoev.ru nxt_string("header_buffer_size"), 617115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 618115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_buffer_size), 619115Sigor@sysoev.ru }, 620115Sigor@sysoev.ru 621115Sigor@sysoev.ru { 622115Sigor@sysoev.ru nxt_string("large_header_buffer_size"), 623115Sigor@sysoev.ru NXT_CONF_MAP_SIZE, 624115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, large_header_buffer_size), 625115Sigor@sysoev.ru }, 626115Sigor@sysoev.ru 627115Sigor@sysoev.ru { 628206Smax.romanov@nginx.com nxt_string("large_header_buffers"), 629206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 630206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, large_header_buffers), 631206Smax.romanov@nginx.com }, 632206Smax.romanov@nginx.com 633206Smax.romanov@nginx.com { 634206Smax.romanov@nginx.com nxt_string("body_buffer_size"), 635206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 636206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_buffer_size), 637206Smax.romanov@nginx.com }, 638206Smax.romanov@nginx.com 639206Smax.romanov@nginx.com { 640206Smax.romanov@nginx.com nxt_string("max_body_size"), 641206Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 642206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, max_body_size), 643206Smax.romanov@nginx.com }, 644206Smax.romanov@nginx.com 645206Smax.romanov@nginx.com { 646115Sigor@sysoev.ru nxt_string("header_read_timeout"), 647115Sigor@sysoev.ru NXT_CONF_MAP_MSEC, 648115Sigor@sysoev.ru offsetof(nxt_socket_conf_t, header_read_timeout), 649115Sigor@sysoev.ru }, 650206Smax.romanov@nginx.com 651206Smax.romanov@nginx.com { 652206Smax.romanov@nginx.com nxt_string("body_read_timeout"), 653206Smax.romanov@nginx.com NXT_CONF_MAP_MSEC, 654206Smax.romanov@nginx.com offsetof(nxt_socket_conf_t, body_read_timeout), 655206Smax.romanov@nginx.com }, 656115Sigor@sysoev.ru }; 657115Sigor@sysoev.ru 658115Sigor@sysoev.ru 65953Sigor@sysoev.ru static nxt_int_t 660115Sigor@sysoev.ru nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 661115Sigor@sysoev.ru u_char *start, u_char *end) 66253Sigor@sysoev.ru { 663133Sigor@sysoev.ru u_char *p; 664133Sigor@sysoev.ru size_t size; 665115Sigor@sysoev.ru nxt_mp_t *mp; 666115Sigor@sysoev.ru uint32_t next; 667115Sigor@sysoev.ru nxt_int_t ret; 668115Sigor@sysoev.ru nxt_str_t name; 669133Sigor@sysoev.ru nxt_app_t *app, *prev; 670133Sigor@sysoev.ru nxt_app_type_t type; 671115Sigor@sysoev.ru nxt_sockaddr_t *sa; 672133Sigor@sysoev.ru nxt_conf_value_t *conf, *http; 673133Sigor@sysoev.ru nxt_conf_value_t *applications, *application; 674133Sigor@sysoev.ru nxt_conf_value_t *listeners, *listener; 675115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 676216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 677133Sigor@sysoev.ru nxt_router_app_conf_t apcf; 678115Sigor@sysoev.ru nxt_router_listener_conf_t lscf; 679115Sigor@sysoev.ru 680115Sigor@sysoev.ru static nxt_str_t http_path = nxt_string("/http"); 681133Sigor@sysoev.ru static nxt_str_t applications_path = nxt_string("/applications"); 682115Sigor@sysoev.ru static nxt_str_t listeners_path = nxt_string("/listeners"); 683115Sigor@sysoev.ru 684208Svbart@nginx.com conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); 685115Sigor@sysoev.ru if (conf == NULL) { 686115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "configuration parsing error"); 687115Sigor@sysoev.ru return NXT_ERROR; 688115Sigor@sysoev.ru } 689115Sigor@sysoev.ru 690213Svbart@nginx.com mp = tmcf->conf->mem_pool; 691213Svbart@nginx.com 692213Svbart@nginx.com ret = nxt_conf_map_object(mp, conf, nxt_router_conf, 693136Svbart@nginx.com nxt_nitems(nxt_router_conf), tmcf->conf); 694115Sigor@sysoev.ru if (ret != NXT_OK) { 695133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "root map error"); 696115Sigor@sysoev.ru return NXT_ERROR; 697115Sigor@sysoev.ru } 698115Sigor@sysoev.ru 699117Sigor@sysoev.ru if (tmcf->conf->threads == 0) { 700117Sigor@sysoev.ru tmcf->conf->threads = nxt_ncpu; 701117Sigor@sysoev.ru } 702117Sigor@sysoev.ru 703133Sigor@sysoev.ru applications = nxt_conf_get_path(conf, &applications_path); 704133Sigor@sysoev.ru if (applications == NULL) { 705133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"applications\" block"); 706115Sigor@sysoev.ru return NXT_ERROR; 707115Sigor@sysoev.ru } 708115Sigor@sysoev.ru 709133Sigor@sysoev.ru next = 0; 710133Sigor@sysoev.ru 711133Sigor@sysoev.ru for ( ;; ) { 712133Sigor@sysoev.ru application = nxt_conf_next_object_member(applications, &name, &next); 713133Sigor@sysoev.ru if (application == NULL) { 714133Sigor@sysoev.ru break; 715133Sigor@sysoev.ru } 716133Sigor@sysoev.ru 717133Sigor@sysoev.ru nxt_debug(task, "application \"%V\"", &name); 718133Sigor@sysoev.ru 719144Smax.romanov@nginx.com size = nxt_conf_json_length(application, NULL); 720144Smax.romanov@nginx.com 721144Smax.romanov@nginx.com app = nxt_malloc(sizeof(nxt_app_t) + name.length + size); 722133Sigor@sysoev.ru if (app == NULL) { 723133Sigor@sysoev.ru goto fail; 724133Sigor@sysoev.ru } 725133Sigor@sysoev.ru 726144Smax.romanov@nginx.com nxt_memzero(app, sizeof(nxt_app_t)); 727144Smax.romanov@nginx.com 728144Smax.romanov@nginx.com app->name.start = nxt_pointer_to(app, sizeof(nxt_app_t)); 729144Smax.romanov@nginx.com app->conf.start = nxt_pointer_to(app, sizeof(nxt_app_t) + name.length); 730133Sigor@sysoev.ru 731133Sigor@sysoev.ru p = nxt_conf_json_print(app->conf.start, application, NULL); 732133Sigor@sysoev.ru app->conf.length = p - app->conf.start; 733133Sigor@sysoev.ru 734144Smax.romanov@nginx.com nxt_assert(app->conf.length <= size); 735144Smax.romanov@nginx.com 736133Sigor@sysoev.ru nxt_debug(task, "application conf \"%V\"", &app->conf); 737133Sigor@sysoev.ru 738133Sigor@sysoev.ru prev = nxt_router_app_find(&tmcf->conf->router->apps, &name); 739133Sigor@sysoev.ru 740133Sigor@sysoev.ru if (prev != NULL && nxt_strstr_eq(&app->conf, &prev->conf)) { 741133Sigor@sysoev.ru nxt_free(app); 742133Sigor@sysoev.ru 743133Sigor@sysoev.ru nxt_queue_remove(&prev->link); 744133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->previous, &prev->link); 745133Sigor@sysoev.ru continue; 746133Sigor@sysoev.ru } 747133Sigor@sysoev.ru 748263Smax.romanov@nginx.com apcf.workers = 1; 749263Smax.romanov@nginx.com 750213Svbart@nginx.com ret = nxt_conf_map_object(mp, application, nxt_router_app_conf, 751136Svbart@nginx.com nxt_nitems(nxt_router_app_conf), &apcf); 752133Sigor@sysoev.ru if (ret != NXT_OK) { 753133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "application map error"); 754133Sigor@sysoev.ru goto app_fail; 755133Sigor@sysoev.ru } 756115Sigor@sysoev.ru 757133Sigor@sysoev.ru nxt_debug(task, "application type: %V", &apcf.type); 758133Sigor@sysoev.ru nxt_debug(task, "application workers: %D", apcf.workers); 759133Sigor@sysoev.ru 760216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &apcf.type); 761216Sigor@sysoev.ru 762216Sigor@sysoev.ru if (lang == NULL) { 763141Smax.romanov@nginx.com nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 764141Smax.romanov@nginx.com &apcf.type); 765141Smax.romanov@nginx.com goto app_fail; 766141Smax.romanov@nginx.com } 767141Smax.romanov@nginx.com 768216Sigor@sysoev.ru nxt_debug(task, "application language module: \"%s\"", lang->file); 769216Sigor@sysoev.ru 770216Sigor@sysoev.ru type = nxt_app_parse_type(&lang->type); 771216Sigor@sysoev.ru 772216Sigor@sysoev.ru if (type == NXT_APP_UNKNOWN) { 773216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 774216Sigor@sysoev.ru &lang->type); 775216Sigor@sysoev.ru goto app_fail; 776216Sigor@sysoev.ru } 777216Sigor@sysoev.ru 778216Sigor@sysoev.ru if (nxt_app_prepare_msg[type] == NULL) { 779133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unsupported application type: \"%V\"", 780216Sigor@sysoev.ru &lang->type); 781133Sigor@sysoev.ru goto app_fail; 782133Sigor@sysoev.ru } 783133Sigor@sysoev.ru 784133Sigor@sysoev.ru ret = nxt_thread_mutex_create(&app->mutex); 785133Sigor@sysoev.ru if (ret != NXT_OK) { 786133Sigor@sysoev.ru goto app_fail; 787133Sigor@sysoev.ru } 788133Sigor@sysoev.ru 789141Smax.romanov@nginx.com nxt_queue_init(&app->ports); 790141Smax.romanov@nginx.com nxt_queue_init(&app->requests); 791141Smax.romanov@nginx.com 792144Smax.romanov@nginx.com app->name.length = name.length; 793144Smax.romanov@nginx.com nxt_memcpy(app->name.start, name.start, name.length); 794144Smax.romanov@nginx.com 795133Sigor@sysoev.ru app->type = type; 796133Sigor@sysoev.ru app->max_workers = apcf.workers; 797133Sigor@sysoev.ru app->live = 1; 798216Sigor@sysoev.ru app->prepare_msg = nxt_app_prepare_msg[type]; 799133Sigor@sysoev.ru 800133Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->apps, &app->link); 801133Sigor@sysoev.ru } 802133Sigor@sysoev.ru 803133Sigor@sysoev.ru http = nxt_conf_get_path(conf, &http_path); 804133Sigor@sysoev.ru #if 0 805133Sigor@sysoev.ru if (http == NULL) { 806133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"http\" block"); 807133Sigor@sysoev.ru return NXT_ERROR; 808133Sigor@sysoev.ru } 809133Sigor@sysoev.ru #endif 810133Sigor@sysoev.ru 811133Sigor@sysoev.ru listeners = nxt_conf_get_path(conf, &listeners_path); 812115Sigor@sysoev.ru if (listeners == NULL) { 813133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "no \"listeners\" block"); 814115Sigor@sysoev.ru return NXT_ERROR; 815115Sigor@sysoev.ru } 81653Sigor@sysoev.ru 817133Sigor@sysoev.ru next = 0; 81853Sigor@sysoev.ru 819115Sigor@sysoev.ru for ( ;; ) { 820115Sigor@sysoev.ru listener = nxt_conf_next_object_member(listeners, &name, &next); 821115Sigor@sysoev.ru if (listener == NULL) { 822115Sigor@sysoev.ru break; 823115Sigor@sysoev.ru } 82453Sigor@sysoev.ru 825115Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 826115Sigor@sysoev.ru if (sa == NULL) { 827115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid listener \"%V\"", &name); 828133Sigor@sysoev.ru goto fail; 829115Sigor@sysoev.ru } 830115Sigor@sysoev.ru 831115Sigor@sysoev.ru sa->type = SOCK_STREAM; 832115Sigor@sysoev.ru 833115Sigor@sysoev.ru nxt_debug(task, "router listener: \"%*s\"", 834115Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa)); 83553Sigor@sysoev.ru 836115Sigor@sysoev.ru skcf = nxt_router_socket_conf(task, mp, sa); 837115Sigor@sysoev.ru if (skcf == NULL) { 838133Sigor@sysoev.ru goto fail; 839115Sigor@sysoev.ru } 84053Sigor@sysoev.ru 841213Svbart@nginx.com ret = nxt_conf_map_object(mp, listener, nxt_router_listener_conf, 842136Svbart@nginx.com nxt_nitems(nxt_router_listener_conf), &lscf); 843115Sigor@sysoev.ru if (ret != NXT_OK) { 844115Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "listener map error"); 845133Sigor@sysoev.ru goto fail; 846115Sigor@sysoev.ru } 84753Sigor@sysoev.ru 848133Sigor@sysoev.ru nxt_debug(task, "application: %V", &lscf.application); 849133Sigor@sysoev.ru 850133Sigor@sysoev.ru // STUB, default values if http block is not defined. 851133Sigor@sysoev.ru skcf->header_buffer_size = 2048; 852133Sigor@sysoev.ru skcf->large_header_buffer_size = 8192; 853206Smax.romanov@nginx.com skcf->large_header_buffers = 4; 854206Smax.romanov@nginx.com skcf->body_buffer_size = 16 * 1024; 855206Smax.romanov@nginx.com skcf->max_body_size = 2 * 1024 * 1024; 856133Sigor@sysoev.ru skcf->header_read_timeout = 5000; 857206Smax.romanov@nginx.com skcf->body_read_timeout = 5000; 85853Sigor@sysoev.ru 859133Sigor@sysoev.ru if (http != NULL) { 860213Svbart@nginx.com ret = nxt_conf_map_object(mp, http, nxt_router_http_conf, 861136Svbart@nginx.com nxt_nitems(nxt_router_http_conf), skcf); 862133Sigor@sysoev.ru if (ret != NXT_OK) { 863133Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "http map error"); 864133Sigor@sysoev.ru goto fail; 865133Sigor@sysoev.ru } 866115Sigor@sysoev.ru } 867115Sigor@sysoev.ru 868115Sigor@sysoev.ru skcf->listen.handler = nxt_router_conn_init; 869115Sigor@sysoev.ru skcf->router_conf = tmcf->conf; 870160Sigor@sysoev.ru skcf->router_conf->count++; 871133Sigor@sysoev.ru skcf->application = nxt_router_listener_application(tmcf, 872133Sigor@sysoev.ru &lscf.application); 873115Sigor@sysoev.ru 874115Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->pending, &skcf->link); 875115Sigor@sysoev.ru } 87653Sigor@sysoev.ru 877198Sigor@sysoev.ru nxt_router_listen_sockets_sort(tmcf->conf->router, tmcf); 878198Sigor@sysoev.ru 87953Sigor@sysoev.ru return NXT_OK; 880133Sigor@sysoev.ru 881133Sigor@sysoev.ru app_fail: 882133Sigor@sysoev.ru 883133Sigor@sysoev.ru nxt_free(app); 884133Sigor@sysoev.ru 885133Sigor@sysoev.ru fail: 886133Sigor@sysoev.ru 887141Smax.romanov@nginx.com nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { 888141Smax.romanov@nginx.com 889141Smax.romanov@nginx.com nxt_queue_remove(&app->link); 890133Sigor@sysoev.ru nxt_thread_mutex_destroy(&app->mutex); 891133Sigor@sysoev.ru nxt_free(app); 892141Smax.romanov@nginx.com 893141Smax.romanov@nginx.com } nxt_queue_loop; 894133Sigor@sysoev.ru 895133Sigor@sysoev.ru return NXT_ERROR; 896133Sigor@sysoev.ru } 897133Sigor@sysoev.ru 898133Sigor@sysoev.ru 899133Sigor@sysoev.ru static nxt_app_t * 900133Sigor@sysoev.ru nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name) 901133Sigor@sysoev.ru { 902141Smax.romanov@nginx.com nxt_app_t *app; 903141Smax.romanov@nginx.com 904141Smax.romanov@nginx.com nxt_queue_each(app, queue, nxt_app_t, link) { 905133Sigor@sysoev.ru 906133Sigor@sysoev.ru if (nxt_strstr_eq(name, &app->name)) { 907133Sigor@sysoev.ru return app; 908133Sigor@sysoev.ru } 909141Smax.romanov@nginx.com 910141Smax.romanov@nginx.com } nxt_queue_loop; 911133Sigor@sysoev.ru 912133Sigor@sysoev.ru return NULL; 913133Sigor@sysoev.ru } 914133Sigor@sysoev.ru 915133Sigor@sysoev.ru 916133Sigor@sysoev.ru static nxt_app_t * 917133Sigor@sysoev.ru nxt_router_listener_application(nxt_router_temp_conf_t *tmcf, nxt_str_t *name) 918133Sigor@sysoev.ru { 919133Sigor@sysoev.ru nxt_app_t *app; 920133Sigor@sysoev.ru 921133Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->apps, name); 922133Sigor@sysoev.ru 923133Sigor@sysoev.ru if (app == NULL) { 924134Sigor@sysoev.ru app = nxt_router_app_find(&tmcf->previous, name); 925133Sigor@sysoev.ru } 926133Sigor@sysoev.ru 927133Sigor@sysoev.ru return app; 92853Sigor@sysoev.ru } 92953Sigor@sysoev.ru 93053Sigor@sysoev.ru 93153Sigor@sysoev.ru static nxt_socket_conf_t * 93265Sigor@sysoev.ru nxt_router_socket_conf(nxt_task_t *task, nxt_mp_t *mp, nxt_sockaddr_t *sa) 93353Sigor@sysoev.ru { 934163Smax.romanov@nginx.com nxt_socket_conf_t *skcf; 935163Smax.romanov@nginx.com 936163Smax.romanov@nginx.com skcf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); 937163Smax.romanov@nginx.com if (nxt_slow_path(skcf == NULL)) { 93853Sigor@sysoev.ru return NULL; 93953Sigor@sysoev.ru } 94053Sigor@sysoev.ru 941163Smax.romanov@nginx.com skcf->sockaddr = sa; 942163Smax.romanov@nginx.com 943163Smax.romanov@nginx.com skcf->listen.sockaddr = sa; 944163Smax.romanov@nginx.com skcf->listen.socklen = sa->socklen; 945163Smax.romanov@nginx.com skcf->listen.address_length = sa->length; 946163Smax.romanov@nginx.com 947163Smax.romanov@nginx.com skcf->listen.socket = -1; 948163Smax.romanov@nginx.com skcf->listen.backlog = NXT_LISTEN_BACKLOG; 949163Smax.romanov@nginx.com skcf->listen.flags = NXT_NONBLOCK; 950163Smax.romanov@nginx.com skcf->listen.read_after_accept = 1; 951163Smax.romanov@nginx.com 952163Smax.romanov@nginx.com return skcf; 95353Sigor@sysoev.ru } 95453Sigor@sysoev.ru 95553Sigor@sysoev.ru 95653Sigor@sysoev.ru static void 95753Sigor@sysoev.ru nxt_router_listen_sockets_sort(nxt_router_t *router, 95853Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 95953Sigor@sysoev.ru { 96053Sigor@sysoev.ru nxt_queue_link_t *nqlk, *oqlk, *next; 96153Sigor@sysoev.ru nxt_socket_conf_t *nskcf, *oskcf; 96253Sigor@sysoev.ru 96353Sigor@sysoev.ru for (nqlk = nxt_queue_first(&tmcf->pending); 96453Sigor@sysoev.ru nqlk != nxt_queue_tail(&tmcf->pending); 96553Sigor@sysoev.ru nqlk = next) 96653Sigor@sysoev.ru { 96753Sigor@sysoev.ru next = nxt_queue_next(nqlk); 96853Sigor@sysoev.ru nskcf = nxt_queue_link_data(nqlk, nxt_socket_conf_t, link); 96953Sigor@sysoev.ru 97053Sigor@sysoev.ru for (oqlk = nxt_queue_first(&router->sockets); 97153Sigor@sysoev.ru oqlk != nxt_queue_tail(&router->sockets); 97253Sigor@sysoev.ru oqlk = nxt_queue_next(oqlk)) 97353Sigor@sysoev.ru { 97453Sigor@sysoev.ru oskcf = nxt_queue_link_data(oqlk, nxt_socket_conf_t, link); 97553Sigor@sysoev.ru 976115Sigor@sysoev.ru if (nxt_sockaddr_cmp(nskcf->sockaddr, oskcf->sockaddr)) { 977115Sigor@sysoev.ru nskcf->socket = oskcf->socket; 978115Sigor@sysoev.ru nskcf->listen.socket = oskcf->listen.socket; 979115Sigor@sysoev.ru 98053Sigor@sysoev.ru nxt_queue_remove(oqlk); 98153Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->keeping, oqlk); 98253Sigor@sysoev.ru 98353Sigor@sysoev.ru nxt_queue_remove(nqlk); 98453Sigor@sysoev.ru nxt_queue_insert_tail(&tmcf->updating, nqlk); 98553Sigor@sysoev.ru 98653Sigor@sysoev.ru break; 98753Sigor@sysoev.ru } 98853Sigor@sysoev.ru } 98953Sigor@sysoev.ru } 99053Sigor@sysoev.ru 99153Sigor@sysoev.ru nxt_queue_add(&tmcf->deleting, &router->sockets); 992115Sigor@sysoev.ru nxt_queue_init(&router->sockets); 99353Sigor@sysoev.ru } 99453Sigor@sysoev.ru 99553Sigor@sysoev.ru 996198Sigor@sysoev.ru static void 997198Sigor@sysoev.ru nxt_router_listen_socket_rpc_create(nxt_task_t *task, 998198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf) 999198Sigor@sysoev.ru { 1000198Sigor@sysoev.ru uint32_t stream; 1001198Sigor@sysoev.ru nxt_buf_t *b; 1002198Sigor@sysoev.ru nxt_port_t *main_port, *router_port; 1003198Sigor@sysoev.ru nxt_runtime_t *rt; 1004198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1005198Sigor@sysoev.ru 1006198Sigor@sysoev.ru rpc = nxt_mp_alloc(tmcf->mem_pool, sizeof(nxt_socket_rpc_t)); 1007198Sigor@sysoev.ru if (rpc == NULL) { 1008198Sigor@sysoev.ru goto fail; 1009198Sigor@sysoev.ru } 1010198Sigor@sysoev.ru 1011198Sigor@sysoev.ru rpc->socket_conf = skcf; 1012198Sigor@sysoev.ru rpc->temp_conf = tmcf; 1013198Sigor@sysoev.ru 1014198Sigor@sysoev.ru b = nxt_buf_mem_alloc(tmcf->mem_pool, skcf->sockaddr->sockaddr_size, 0); 1015198Sigor@sysoev.ru if (b == NULL) { 1016198Sigor@sysoev.ru goto fail; 1017198Sigor@sysoev.ru } 1018198Sigor@sysoev.ru 1019198Sigor@sysoev.ru b->mem.free = nxt_cpymem(b->mem.free, skcf->sockaddr, 1020198Sigor@sysoev.ru skcf->sockaddr->sockaddr_size); 1021198Sigor@sysoev.ru 1022198Sigor@sysoev.ru rt = task->thread->runtime; 1023240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1024198Sigor@sysoev.ru router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 1025198Sigor@sysoev.ru 1026198Sigor@sysoev.ru stream = nxt_port_rpc_register_handler(task, router_port, 1027198Sigor@sysoev.ru nxt_router_listen_socket_ready, 1028198Sigor@sysoev.ru nxt_router_listen_socket_error, 1029198Sigor@sysoev.ru main_port->pid, rpc); 1030198Sigor@sysoev.ru if (stream == 0) { 1031198Sigor@sysoev.ru goto fail; 1032198Sigor@sysoev.ru } 1033198Sigor@sysoev.ru 1034198Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_SOCKET, -1, 1035198Sigor@sysoev.ru stream, router_port->id, b); 1036198Sigor@sysoev.ru 1037198Sigor@sysoev.ru return; 1038198Sigor@sysoev.ru 1039198Sigor@sysoev.ru fail: 1040198Sigor@sysoev.ru 1041198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 1042198Sigor@sysoev.ru } 1043198Sigor@sysoev.ru 1044198Sigor@sysoev.ru 1045198Sigor@sysoev.ru static void 1046198Sigor@sysoev.ru nxt_router_listen_socket_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, 1047198Sigor@sysoev.ru void *data) 104853Sigor@sysoev.ru { 1049115Sigor@sysoev.ru nxt_int_t ret; 1050115Sigor@sysoev.ru nxt_socket_t s; 1051198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1052115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 105353Sigor@sysoev.ru 1054198Sigor@sysoev.ru rpc = data; 1055198Sigor@sysoev.ru 1056198Sigor@sysoev.ru s = msg->fd; 1057198Sigor@sysoev.ru 1058198Sigor@sysoev.ru ret = nxt_socket_nonblocking(task, s); 1059198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1060198Sigor@sysoev.ru goto fail; 106153Sigor@sysoev.ru } 106253Sigor@sysoev.ru 1063229Sigor@sysoev.ru nxt_socket_defer_accept(task, s, rpc->socket_conf->sockaddr); 1064198Sigor@sysoev.ru 1065198Sigor@sysoev.ru ret = nxt_listen_socket(task, s, NXT_LISTEN_BACKLOG); 1066198Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1067198Sigor@sysoev.ru goto fail; 1068198Sigor@sysoev.ru } 1069198Sigor@sysoev.ru 1070198Sigor@sysoev.ru rtsk = nxt_malloc(sizeof(nxt_router_socket_t)); 1071198Sigor@sysoev.ru if (nxt_slow_path(rtsk == NULL)) { 1072198Sigor@sysoev.ru goto fail; 1073198Sigor@sysoev.ru } 1074198Sigor@sysoev.ru 1075198Sigor@sysoev.ru rtsk->count = 0; 1076198Sigor@sysoev.ru rtsk->fd = s; 1077198Sigor@sysoev.ru 1078198Sigor@sysoev.ru rpc->socket_conf->listen.socket = s; 1079198Sigor@sysoev.ru rpc->socket_conf->socket = rtsk; 1080198Sigor@sysoev.ru 1081198Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue, 1082198Sigor@sysoev.ru nxt_router_conf_apply, task, rpc->temp_conf, NULL); 1083198Sigor@sysoev.ru 1084198Sigor@sysoev.ru return; 1085148Sigor@sysoev.ru 1086148Sigor@sysoev.ru fail: 1087148Sigor@sysoev.ru 1088148Sigor@sysoev.ru nxt_socket_close(task, s); 1089148Sigor@sysoev.ru 1090198Sigor@sysoev.ru nxt_router_conf_error(task, rpc->temp_conf); 1091198Sigor@sysoev.ru } 1092198Sigor@sysoev.ru 1093198Sigor@sysoev.ru 1094198Sigor@sysoev.ru static void 1095198Sigor@sysoev.ru nxt_router_listen_socket_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 1096198Sigor@sysoev.ru void *data) 1097198Sigor@sysoev.ru { 1098198Sigor@sysoev.ru u_char *p; 1099198Sigor@sysoev.ru size_t size; 1100198Sigor@sysoev.ru uint8_t error; 1101198Sigor@sysoev.ru nxt_buf_t *in, *out; 1102198Sigor@sysoev.ru nxt_sockaddr_t *sa; 1103198Sigor@sysoev.ru nxt_socket_rpc_t *rpc; 1104198Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf; 1105198Sigor@sysoev.ru 1106198Sigor@sysoev.ru static nxt_str_t socket_errors[] = { 1107198Sigor@sysoev.ru nxt_string("ListenerSystem"), 1108198Sigor@sysoev.ru nxt_string("ListenerNoIPv6"), 1109198Sigor@sysoev.ru nxt_string("ListenerPort"), 1110198Sigor@sysoev.ru nxt_string("ListenerInUse"), 1111198Sigor@sysoev.ru nxt_string("ListenerNoAddress"), 1112198Sigor@sysoev.ru nxt_string("ListenerNoAccess"), 1113198Sigor@sysoev.ru nxt_string("ListenerPath"), 1114198Sigor@sysoev.ru }; 1115198Sigor@sysoev.ru 1116198Sigor@sysoev.ru rpc = data; 1117198Sigor@sysoev.ru sa = rpc->socket_conf->sockaddr; 1118198Sigor@sysoev.ru 1119198Sigor@sysoev.ru in = msg->buf; 1120198Sigor@sysoev.ru p = in->mem.pos; 1121198Sigor@sysoev.ru 1122198Sigor@sysoev.ru error = *p++; 1123198Sigor@sysoev.ru 1124198Sigor@sysoev.ru size = sizeof("listen socket error: ") - 1 1125198Sigor@sysoev.ru + sizeof("{listener: \"\", code:\"\", message: \"\"}") - 1 1126198Sigor@sysoev.ru + sa->length + socket_errors[error].length + (in->mem.free - p); 1127198Sigor@sysoev.ru 1128198Sigor@sysoev.ru tmcf = rpc->temp_conf; 1129198Sigor@sysoev.ru 1130198Sigor@sysoev.ru out = nxt_buf_mem_alloc(tmcf->mem_pool, size, 0); 1131198Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) { 1132198Sigor@sysoev.ru return; 1133198Sigor@sysoev.ru } 1134198Sigor@sysoev.ru 1135198Sigor@sysoev.ru out->mem.free = nxt_sprintf(out->mem.free, out->mem.end, 1136198Sigor@sysoev.ru "listen socket error: " 1137198Sigor@sysoev.ru "{listener: \"%*s\", code:\"%V\", message: \"%*s\"}", 1138198Sigor@sysoev.ru sa->length, nxt_sockaddr_start(sa), 1139198Sigor@sysoev.ru &socket_errors[error], in->mem.free - p, p); 1140198Sigor@sysoev.ru 1141198Sigor@sysoev.ru nxt_debug(task, "%*s", out->mem.free - out->mem.pos, out->mem.pos); 1142198Sigor@sysoev.ru 1143198Sigor@sysoev.ru nxt_router_conf_error(task, tmcf); 114453Sigor@sysoev.ru } 114553Sigor@sysoev.ru 114653Sigor@sysoev.ru 114753Sigor@sysoev.ru static nxt_int_t 114853Sigor@sysoev.ru nxt_router_engines_create(nxt_task_t *task, nxt_router_t *router, 114953Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, const nxt_event_interface_t *interface) 115053Sigor@sysoev.ru { 115153Sigor@sysoev.ru nxt_int_t ret; 115253Sigor@sysoev.ru nxt_uint_t n, threads; 115353Sigor@sysoev.ru nxt_queue_link_t *qlk; 115453Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 115553Sigor@sysoev.ru 115653Sigor@sysoev.ru threads = tmcf->conf->threads; 115753Sigor@sysoev.ru 115853Sigor@sysoev.ru tmcf->engines = nxt_array_create(tmcf->mem_pool, threads, 115953Sigor@sysoev.ru sizeof(nxt_router_engine_conf_t)); 116053Sigor@sysoev.ru if (nxt_slow_path(tmcf->engines == NULL)) { 116153Sigor@sysoev.ru return NXT_ERROR; 116253Sigor@sysoev.ru } 116353Sigor@sysoev.ru 116453Sigor@sysoev.ru n = 0; 116553Sigor@sysoev.ru 116653Sigor@sysoev.ru for (qlk = nxt_queue_first(&router->engines); 116753Sigor@sysoev.ru qlk != nxt_queue_tail(&router->engines); 116853Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 116953Sigor@sysoev.ru { 117053Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 117153Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 117253Sigor@sysoev.ru return NXT_ERROR; 117353Sigor@sysoev.ru } 117453Sigor@sysoev.ru 1175115Sigor@sysoev.ru recf->engine = nxt_queue_link_data(qlk, nxt_event_engine_t, link0); 117653Sigor@sysoev.ru 117753Sigor@sysoev.ru if (n < threads) { 1178115Sigor@sysoev.ru ret = nxt_router_engine_conf_update(tmcf, recf); 117953Sigor@sysoev.ru 118053Sigor@sysoev.ru } else { 1181115Sigor@sysoev.ru ret = nxt_router_engine_conf_delete(tmcf, recf); 118253Sigor@sysoev.ru } 118353Sigor@sysoev.ru 118453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 118553Sigor@sysoev.ru return ret; 118653Sigor@sysoev.ru } 118753Sigor@sysoev.ru 118853Sigor@sysoev.ru n++; 118953Sigor@sysoev.ru } 119053Sigor@sysoev.ru 119153Sigor@sysoev.ru tmcf->new_threads = n; 119253Sigor@sysoev.ru 119353Sigor@sysoev.ru while (n < threads) { 119453Sigor@sysoev.ru recf = nxt_array_zero_add(tmcf->engines); 119553Sigor@sysoev.ru if (nxt_slow_path(recf == NULL)) { 119653Sigor@sysoev.ru return NXT_ERROR; 119753Sigor@sysoev.ru } 119853Sigor@sysoev.ru 119953Sigor@sysoev.ru recf->engine = nxt_event_engine_create(task, interface, NULL, 0, 0); 120053Sigor@sysoev.ru if (nxt_slow_path(recf->engine == NULL)) { 120153Sigor@sysoev.ru return NXT_ERROR; 120253Sigor@sysoev.ru } 120353Sigor@sysoev.ru 1204115Sigor@sysoev.ru ret = nxt_router_engine_conf_create(tmcf, recf); 120553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 120653Sigor@sysoev.ru return ret; 120753Sigor@sysoev.ru } 120853Sigor@sysoev.ru 1209115Sigor@sysoev.ru nxt_queue_insert_tail(&router->engines, &recf->engine->link0); 1210115Sigor@sysoev.ru 121153Sigor@sysoev.ru n++; 121253Sigor@sysoev.ru } 121353Sigor@sysoev.ru 121453Sigor@sysoev.ru return NXT_OK; 121553Sigor@sysoev.ru } 121653Sigor@sysoev.ru 121753Sigor@sysoev.ru 121853Sigor@sysoev.ru static nxt_int_t 1219115Sigor@sysoev.ru nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf, 1220115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 122153Sigor@sysoev.ru { 1222115Sigor@sysoev.ru nxt_int_t ret; 1223115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 122453Sigor@sysoev.ru 1225154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 1226154Sigor@sysoev.ru nxt_router_listen_socket_create); 1227115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1228115Sigor@sysoev.ru return ret; 1229115Sigor@sysoev.ru } 1230115Sigor@sysoev.ru 1231154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 1232154Sigor@sysoev.ru nxt_router_listen_socket_create); 123353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 123453Sigor@sysoev.ru return ret; 123553Sigor@sysoev.ru } 123653Sigor@sysoev.ru 1237115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1238115Sigor@sysoev.ru 1239115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1240115Sigor@sysoev.ru 1241115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1242115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->updating); 1243115Sigor@sysoev.ru 1244115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1245115Sigor@sysoev.ru 1246115Sigor@sysoev.ru return ret; 124753Sigor@sysoev.ru } 124853Sigor@sysoev.ru 124953Sigor@sysoev.ru 125053Sigor@sysoev.ru static nxt_int_t 1251115Sigor@sysoev.ru nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf, 1252115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 125353Sigor@sysoev.ru { 1254115Sigor@sysoev.ru nxt_int_t ret; 1255115Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 125653Sigor@sysoev.ru 1257154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->creating, 1258154Sigor@sysoev.ru nxt_router_listen_socket_create); 125953Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 126053Sigor@sysoev.ru return ret; 126153Sigor@sysoev.ru } 126253Sigor@sysoev.ru 1263154Sigor@sysoev.ru ret = nxt_router_engine_joints_create(tmcf, recf, &tmcf->updating, 1264154Sigor@sysoev.ru nxt_router_listen_socket_update); 126553Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 126653Sigor@sysoev.ru return ret; 126753Sigor@sysoev.ru } 126853Sigor@sysoev.ru 1269139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 1270115Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1271115Sigor@sysoev.ru return ret; 1272115Sigor@sysoev.ru } 1273115Sigor@sysoev.ru 1274115Sigor@sysoev.ru lock = &tmcf->conf->router->lock; 1275115Sigor@sysoev.ru 1276115Sigor@sysoev.ru nxt_thread_spin_lock(lock); 1277115Sigor@sysoev.ru 1278115Sigor@sysoev.ru nxt_router_engine_socket_count(&tmcf->creating); 1279115Sigor@sysoev.ru 1280115Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 1281115Sigor@sysoev.ru 1282115Sigor@sysoev.ru return ret; 128353Sigor@sysoev.ru } 128453Sigor@sysoev.ru 128553Sigor@sysoev.ru 128653Sigor@sysoev.ru static nxt_int_t 1287115Sigor@sysoev.ru nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf, 1288115Sigor@sysoev.ru nxt_router_engine_conf_t *recf) 128953Sigor@sysoev.ru { 129053Sigor@sysoev.ru nxt_int_t ret; 129153Sigor@sysoev.ru 1292139Sigor@sysoev.ru ret = nxt_router_engine_joints_delete(tmcf, recf, &tmcf->updating); 129353Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 129453Sigor@sysoev.ru return ret; 129553Sigor@sysoev.ru } 129653Sigor@sysoev.ru 1297139Sigor@sysoev.ru return nxt_router_engine_joints_delete(tmcf, recf, &tmcf->deleting); 129853Sigor@sysoev.ru } 129953Sigor@sysoev.ru 130053Sigor@sysoev.ru 130153Sigor@sysoev.ru static nxt_int_t 1302154Sigor@sysoev.ru nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf, 1303154Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets, 130453Sigor@sysoev.ru nxt_work_handler_t handler) 130553Sigor@sysoev.ru { 1306153Sigor@sysoev.ru nxt_joint_job_t *job; 130753Sigor@sysoev.ru nxt_queue_link_t *qlk; 1308155Sigor@sysoev.ru nxt_socket_conf_t *skcf; 130953Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 131053Sigor@sysoev.ru 131153Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 131253Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 131353Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 131453Sigor@sysoev.ru { 1315154Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 1316153Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) { 1317139Sigor@sysoev.ru return NXT_ERROR; 1318139Sigor@sysoev.ru } 1319139Sigor@sysoev.ru 1320154Sigor@sysoev.ru job->work.next = recf->jobs; 1321154Sigor@sysoev.ru recf->jobs = &job->work; 1322154Sigor@sysoev.ru 1323153Sigor@sysoev.ru job->task = tmcf->engine->task; 1324153Sigor@sysoev.ru job->work.handler = handler; 1325153Sigor@sysoev.ru job->work.task = &job->task; 1326153Sigor@sysoev.ru job->work.obj = job; 1327153Sigor@sysoev.ru job->tmcf = tmcf; 132853Sigor@sysoev.ru 1329154Sigor@sysoev.ru tmcf->count++; 1330154Sigor@sysoev.ru 1331154Sigor@sysoev.ru joint = nxt_mp_alloc(tmcf->conf->mem_pool, 1332154Sigor@sysoev.ru sizeof(nxt_socket_conf_joint_t)); 133353Sigor@sysoev.ru if (nxt_slow_path(joint == NULL)) { 133453Sigor@sysoev.ru return NXT_ERROR; 133553Sigor@sysoev.ru } 133653Sigor@sysoev.ru 1337153Sigor@sysoev.ru job->work.data = joint; 133853Sigor@sysoev.ru 133953Sigor@sysoev.ru joint->count = 1; 1340155Sigor@sysoev.ru 1341155Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1342155Sigor@sysoev.ru skcf->count++; 1343155Sigor@sysoev.ru joint->socket_conf = skcf; 1344155Sigor@sysoev.ru 134588Smax.romanov@nginx.com joint->engine = recf->engine; 134653Sigor@sysoev.ru } 134753Sigor@sysoev.ru 134820Sigor@sysoev.ru return NXT_OK; 134920Sigor@sysoev.ru } 135020Sigor@sysoev.ru 135120Sigor@sysoev.ru 1352115Sigor@sysoev.ru static void 1353115Sigor@sysoev.ru nxt_router_engine_socket_count(nxt_queue_t *sockets) 1354115Sigor@sysoev.ru { 1355115Sigor@sysoev.ru nxt_queue_link_t *qlk; 1356115Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1357115Sigor@sysoev.ru 1358115Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 1359115Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 1360115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 1361115Sigor@sysoev.ru { 1362115Sigor@sysoev.ru skcf = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1363115Sigor@sysoev.ru skcf->socket->count++; 1364115Sigor@sysoev.ru } 1365115Sigor@sysoev.ru } 1366115Sigor@sysoev.ru 1367115Sigor@sysoev.ru 136820Sigor@sysoev.ru static nxt_int_t 1369139Sigor@sysoev.ru nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf, 1370139Sigor@sysoev.ru nxt_router_engine_conf_t *recf, nxt_queue_t *sockets) 137120Sigor@sysoev.ru { 1372153Sigor@sysoev.ru nxt_joint_job_t *job; 137353Sigor@sysoev.ru nxt_queue_link_t *qlk; 137420Sigor@sysoev.ru 137553Sigor@sysoev.ru for (qlk = nxt_queue_first(sockets); 137653Sigor@sysoev.ru qlk != nxt_queue_tail(sockets); 137753Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 137853Sigor@sysoev.ru { 1379154Sigor@sysoev.ru job = nxt_mp_get(tmcf->mem_pool, sizeof(nxt_joint_job_t)); 1380153Sigor@sysoev.ru if (nxt_slow_path(job == NULL)) { 1381139Sigor@sysoev.ru return NXT_ERROR; 1382139Sigor@sysoev.ru } 1383139Sigor@sysoev.ru 1384154Sigor@sysoev.ru job->work.next = recf->jobs; 1385154Sigor@sysoev.ru recf->jobs = &job->work; 1386154Sigor@sysoev.ru 1387153Sigor@sysoev.ru job->task = tmcf->engine->task; 1388153Sigor@sysoev.ru job->work.handler = nxt_router_listen_socket_delete; 1389153Sigor@sysoev.ru job->work.task = &job->task; 1390153Sigor@sysoev.ru job->work.obj = job; 1391153Sigor@sysoev.ru job->work.data = nxt_queue_link_data(qlk, nxt_socket_conf_t, link); 1392153Sigor@sysoev.ru job->tmcf = tmcf; 1393154Sigor@sysoev.ru 1394154Sigor@sysoev.ru tmcf->count++; 139520Sigor@sysoev.ru } 139620Sigor@sysoev.ru 139753Sigor@sysoev.ru return NXT_OK; 139853Sigor@sysoev.ru } 139920Sigor@sysoev.ru 140020Sigor@sysoev.ru 140153Sigor@sysoev.ru static nxt_int_t 140253Sigor@sysoev.ru nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt, 140353Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf) 140453Sigor@sysoev.ru { 140553Sigor@sysoev.ru nxt_int_t ret; 140653Sigor@sysoev.ru nxt_uint_t i, threads; 140753Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 140820Sigor@sysoev.ru 140953Sigor@sysoev.ru recf = tmcf->engines->elts; 141053Sigor@sysoev.ru threads = tmcf->conf->threads; 141120Sigor@sysoev.ru 141253Sigor@sysoev.ru for (i = tmcf->new_threads; i < threads; i++) { 141353Sigor@sysoev.ru ret = nxt_router_thread_create(task, rt, recf[i].engine); 141453Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 141553Sigor@sysoev.ru return ret; 141653Sigor@sysoev.ru } 141720Sigor@sysoev.ru } 141820Sigor@sysoev.ru 141920Sigor@sysoev.ru return NXT_OK; 142020Sigor@sysoev.ru } 142153Sigor@sysoev.ru 142253Sigor@sysoev.ru 142353Sigor@sysoev.ru static nxt_int_t 142453Sigor@sysoev.ru nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt, 142553Sigor@sysoev.ru nxt_event_engine_t *engine) 142653Sigor@sysoev.ru { 142753Sigor@sysoev.ru nxt_int_t ret; 142853Sigor@sysoev.ru nxt_thread_link_t *link; 142953Sigor@sysoev.ru nxt_thread_handle_t handle; 143053Sigor@sysoev.ru 143153Sigor@sysoev.ru link = nxt_zalloc(sizeof(nxt_thread_link_t)); 143253Sigor@sysoev.ru 143353Sigor@sysoev.ru if (nxt_slow_path(link == NULL)) { 143453Sigor@sysoev.ru return NXT_ERROR; 143553Sigor@sysoev.ru } 143653Sigor@sysoev.ru 143753Sigor@sysoev.ru link->start = nxt_router_thread_start; 143853Sigor@sysoev.ru link->engine = engine; 143953Sigor@sysoev.ru link->work.handler = nxt_router_thread_exit_handler; 144053Sigor@sysoev.ru link->work.task = task; 144153Sigor@sysoev.ru link->work.data = link; 144253Sigor@sysoev.ru 144353Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 144453Sigor@sysoev.ru 144553Sigor@sysoev.ru ret = nxt_thread_create(&handle, link); 144653Sigor@sysoev.ru 144753Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 144853Sigor@sysoev.ru nxt_queue_remove(&engine->link); 144953Sigor@sysoev.ru } 145053Sigor@sysoev.ru 145153Sigor@sysoev.ru return ret; 145253Sigor@sysoev.ru } 145353Sigor@sysoev.ru 145453Sigor@sysoev.ru 145553Sigor@sysoev.ru static void 1456133Sigor@sysoev.ru nxt_router_apps_sort(nxt_router_t *router, nxt_router_temp_conf_t *tmcf) 1457133Sigor@sysoev.ru { 1458167Smax.romanov@nginx.com nxt_app_t *app; 1459167Smax.romanov@nginx.com nxt_port_t *port; 1460141Smax.romanov@nginx.com 1461141Smax.romanov@nginx.com nxt_queue_each(app, &router->apps, nxt_app_t, link) { 1462133Sigor@sysoev.ru 1463133Sigor@sysoev.ru nxt_queue_remove(&app->link); 1464133Sigor@sysoev.ru 1465167Smax.romanov@nginx.com nxt_thread_log_debug("about to remove app '%V' %p", &app->name, app); 1466167Smax.romanov@nginx.com 1467163Smax.romanov@nginx.com app->live = 0; 1468163Smax.romanov@nginx.com 1469167Smax.romanov@nginx.com if (nxt_router_app_free(NULL, app) != 0) { 1470163Smax.romanov@nginx.com continue; 1471163Smax.romanov@nginx.com } 1472163Smax.romanov@nginx.com 1473167Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 1474167Smax.romanov@nginx.com 1475167Smax.romanov@nginx.com nxt_thread_log_debug("app '%V' %p pending requests found", 1476167Smax.romanov@nginx.com &app->name, app); 1477167Smax.romanov@nginx.com continue; 1478163Smax.romanov@nginx.com } 1479163Smax.romanov@nginx.com 1480167Smax.romanov@nginx.com do { 1481167Smax.romanov@nginx.com port = nxt_router_app_get_port(app, 0); 1482167Smax.romanov@nginx.com if (port == NULL) { 1483167Smax.romanov@nginx.com break; 1484167Smax.romanov@nginx.com } 1485167Smax.romanov@nginx.com 1486167Smax.romanov@nginx.com nxt_thread_log_debug("port %p send quit", port); 1487167Smax.romanov@nginx.com 1488167Smax.romanov@nginx.com nxt_port_socket_write(&port->engine->task, port, 1489167Smax.romanov@nginx.com NXT_PORT_MSG_QUIT, -1, 0, 0, NULL); 1490167Smax.romanov@nginx.com } while (1); 1491167Smax.romanov@nginx.com 1492141Smax.romanov@nginx.com } nxt_queue_loop; 1493133Sigor@sysoev.ru 1494133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->previous); 1495133Sigor@sysoev.ru nxt_queue_add(&router->apps, &tmcf->apps); 1496133Sigor@sysoev.ru } 1497133Sigor@sysoev.ru 1498133Sigor@sysoev.ru 1499133Sigor@sysoev.ru static void 150053Sigor@sysoev.ru nxt_router_engines_post(nxt_router_temp_conf_t *tmcf) 150153Sigor@sysoev.ru { 150253Sigor@sysoev.ru nxt_uint_t n; 150353Sigor@sysoev.ru nxt_router_engine_conf_t *recf; 150453Sigor@sysoev.ru 150553Sigor@sysoev.ru recf = tmcf->engines->elts; 150653Sigor@sysoev.ru 150753Sigor@sysoev.ru for (n = tmcf->engines->nelts; n != 0; n--) { 1508154Sigor@sysoev.ru nxt_router_engine_post(recf); 150953Sigor@sysoev.ru recf++; 151053Sigor@sysoev.ru } 151153Sigor@sysoev.ru } 151253Sigor@sysoev.ru 151353Sigor@sysoev.ru 151453Sigor@sysoev.ru static void 1515154Sigor@sysoev.ru nxt_router_engine_post(nxt_router_engine_conf_t *recf) 151653Sigor@sysoev.ru { 1517154Sigor@sysoev.ru nxt_work_t *work, *next; 1518154Sigor@sysoev.ru 1519154Sigor@sysoev.ru for (work = recf->jobs; work != NULL; work = next) { 1520154Sigor@sysoev.ru next = work->next; 1521154Sigor@sysoev.ru work->next = NULL; 1522154Sigor@sysoev.ru 1523154Sigor@sysoev.ru nxt_event_engine_post(recf->engine, work); 152453Sigor@sysoev.ru } 152553Sigor@sysoev.ru } 152653Sigor@sysoev.ru 152753Sigor@sysoev.ru 152853Sigor@sysoev.ru static void 1529119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); 153088Smax.romanov@nginx.com 1531119Smax.romanov@nginx.com static nxt_port_handler_t nxt_router_app_port_handlers[] = { 1532192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_QUIT */ 1533192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_NEW_PORT */ 1534192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_CHANGE_FILE */ 1535192Smax.romanov@nginx.com /* TODO: remove mmap_handler from app ports */ 1536192Smax.romanov@nginx.com nxt_port_mmap_handler, /* NXT_PORT_MSG_MMAP */ 1537119Smax.romanov@nginx.com nxt_router_app_data_handler, 1538192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_REMOVE_PID */ 1539192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_READY */ 1540192Smax.romanov@nginx.com NULL, /* NXT_PORT_MSG_START_WORKER */ 1541190Smax.romanov@nginx.com nxt_port_rpc_handler, 1542190Smax.romanov@nginx.com nxt_port_rpc_handler, 154388Smax.romanov@nginx.com }; 154488Smax.romanov@nginx.com 154588Smax.romanov@nginx.com 154688Smax.romanov@nginx.com static void 154753Sigor@sysoev.ru nxt_router_thread_start(void *data) 154853Sigor@sysoev.ru { 1549141Smax.romanov@nginx.com nxt_int_t ret; 1550141Smax.romanov@nginx.com nxt_port_t *port; 155188Smax.romanov@nginx.com nxt_task_t *task; 155253Sigor@sysoev.ru nxt_thread_t *thread; 155353Sigor@sysoev.ru nxt_thread_link_t *link; 155453Sigor@sysoev.ru nxt_event_engine_t *engine; 155553Sigor@sysoev.ru 155653Sigor@sysoev.ru link = data; 155753Sigor@sysoev.ru engine = link->engine; 155888Smax.romanov@nginx.com task = &engine->task; 155953Sigor@sysoev.ru 156053Sigor@sysoev.ru thread = nxt_thread(); 156153Sigor@sysoev.ru 1562165Smax.romanov@nginx.com nxt_event_engine_thread_adopt(engine); 1563165Smax.romanov@nginx.com 156453Sigor@sysoev.ru /* STUB */ 156553Sigor@sysoev.ru thread->runtime = engine->task.thread->runtime; 156653Sigor@sysoev.ru 156753Sigor@sysoev.ru engine->task.thread = thread; 156853Sigor@sysoev.ru engine->task.log = thread->log; 156953Sigor@sysoev.ru thread->engine = engine; 157063Sigor@sysoev.ru thread->task = &engine->task; 157153Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 157253Sigor@sysoev.ru 157363Sigor@sysoev.ru engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); 157453Sigor@sysoev.ru 1575197Smax.romanov@nginx.com port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, 1576197Smax.romanov@nginx.com NXT_PROCESS_ROUTER); 1577141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 1578141Smax.romanov@nginx.com return; 1579141Smax.romanov@nginx.com } 1580141Smax.romanov@nginx.com 1581141Smax.romanov@nginx.com ret = nxt_port_socket_init(task, port, 0); 1582141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 1583163Smax.romanov@nginx.com nxt_mp_release(port->mem_pool, port); 1584141Smax.romanov@nginx.com return; 1585141Smax.romanov@nginx.com } 1586141Smax.romanov@nginx.com 1587141Smax.romanov@nginx.com engine->port = port; 1588141Smax.romanov@nginx.com 1589141Smax.romanov@nginx.com nxt_port_enable(task, port, nxt_router_app_port_handlers); 1590141Smax.romanov@nginx.com 159153Sigor@sysoev.ru nxt_event_engine_start(engine); 159253Sigor@sysoev.ru } 159353Sigor@sysoev.ru 159453Sigor@sysoev.ru 159553Sigor@sysoev.ru static void 159653Sigor@sysoev.ru nxt_router_listen_socket_create(nxt_task_t *task, void *obj, void *data) 159753Sigor@sysoev.ru { 1598153Sigor@sysoev.ru nxt_joint_job_t *job; 159953Sigor@sysoev.ru nxt_listen_event_t *listen; 160053Sigor@sysoev.ru nxt_listen_socket_t *ls; 160153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 160253Sigor@sysoev.ru 1603153Sigor@sysoev.ru job = obj; 160453Sigor@sysoev.ru joint = data; 160553Sigor@sysoev.ru 160653Sigor@sysoev.ru ls = &joint->socket_conf->listen; 160753Sigor@sysoev.ru 1608159Sigor@sysoev.ru nxt_queue_insert_tail(&task->thread->engine->joints, &joint->link); 1609159Sigor@sysoev.ru 161053Sigor@sysoev.ru listen = nxt_listen_event(task, ls); 161153Sigor@sysoev.ru if (nxt_slow_path(listen == NULL)) { 161253Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 161353Sigor@sysoev.ru return; 161453Sigor@sysoev.ru } 161553Sigor@sysoev.ru 161653Sigor@sysoev.ru listen->socket.data = joint; 1617139Sigor@sysoev.ru 1618153Sigor@sysoev.ru job->work.next = NULL; 1619153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1620153Sigor@sysoev.ru 1621153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 162253Sigor@sysoev.ru } 162353Sigor@sysoev.ru 162453Sigor@sysoev.ru 162553Sigor@sysoev.ru nxt_inline nxt_listen_event_t * 162653Sigor@sysoev.ru nxt_router_listen_event(nxt_queue_t *listen_connections, 162753Sigor@sysoev.ru nxt_socket_conf_t *skcf) 162853Sigor@sysoev.ru { 1629115Sigor@sysoev.ru nxt_socket_t fd; 1630115Sigor@sysoev.ru nxt_queue_link_t *qlk; 163153Sigor@sysoev.ru nxt_listen_event_t *listen; 163253Sigor@sysoev.ru 1633115Sigor@sysoev.ru fd = skcf->socket->fd; 163453Sigor@sysoev.ru 1635115Sigor@sysoev.ru for (qlk = nxt_queue_first(listen_connections); 1636115Sigor@sysoev.ru qlk != nxt_queue_tail(listen_connections); 1637115Sigor@sysoev.ru qlk = nxt_queue_next(qlk)) 163853Sigor@sysoev.ru { 1639115Sigor@sysoev.ru listen = nxt_queue_link_data(qlk, nxt_listen_event_t, link); 164053Sigor@sysoev.ru 1641115Sigor@sysoev.ru if (fd == listen->socket.fd) { 164253Sigor@sysoev.ru return listen; 164353Sigor@sysoev.ru } 164453Sigor@sysoev.ru } 164553Sigor@sysoev.ru 164653Sigor@sysoev.ru return NULL; 164753Sigor@sysoev.ru } 164853Sigor@sysoev.ru 164953Sigor@sysoev.ru 165053Sigor@sysoev.ru static void 165153Sigor@sysoev.ru nxt_router_listen_socket_update(nxt_task_t *task, void *obj, void *data) 165253Sigor@sysoev.ru { 1653153Sigor@sysoev.ru nxt_joint_job_t *job; 165453Sigor@sysoev.ru nxt_event_engine_t *engine; 165553Sigor@sysoev.ru nxt_listen_event_t *listen; 165653Sigor@sysoev.ru nxt_socket_conf_joint_t *joint, *old; 165753Sigor@sysoev.ru 1658153Sigor@sysoev.ru job = obj; 165953Sigor@sysoev.ru joint = data; 166053Sigor@sysoev.ru 1661139Sigor@sysoev.ru engine = task->thread->engine; 1662139Sigor@sysoev.ru 1663159Sigor@sysoev.ru nxt_queue_insert_tail(&engine->joints, &joint->link); 1664159Sigor@sysoev.ru 166553Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, 166653Sigor@sysoev.ru joint->socket_conf); 166753Sigor@sysoev.ru 166853Sigor@sysoev.ru old = listen->socket.data; 166953Sigor@sysoev.ru listen->socket.data = joint; 1670177Sigor@sysoev.ru listen->listen = &joint->socket_conf->listen; 167153Sigor@sysoev.ru 1672153Sigor@sysoev.ru job->work.next = NULL; 1673153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1674153Sigor@sysoev.ru 1675153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 1676139Sigor@sysoev.ru 1677181Smax.romanov@nginx.com /* 1678181Smax.romanov@nginx.com * The task is allocated from configuration temporary 1679181Smax.romanov@nginx.com * memory pool so it can be freed after engine post operation. 1680181Smax.romanov@nginx.com */ 1681181Smax.romanov@nginx.com 1682181Smax.romanov@nginx.com nxt_router_conf_release(&engine->task, old); 168353Sigor@sysoev.ru } 168453Sigor@sysoev.ru 168553Sigor@sysoev.ru 168653Sigor@sysoev.ru static void 168753Sigor@sysoev.ru nxt_router_listen_socket_delete(nxt_task_t *task, void *obj, void *data) 168853Sigor@sysoev.ru { 1689153Sigor@sysoev.ru nxt_joint_job_t *job; 1690153Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1691153Sigor@sysoev.ru nxt_listen_event_t *listen; 1692153Sigor@sysoev.ru nxt_event_engine_t *engine; 1693153Sigor@sysoev.ru 1694153Sigor@sysoev.ru job = obj; 169553Sigor@sysoev.ru skcf = data; 169653Sigor@sysoev.ru 1697139Sigor@sysoev.ru engine = task->thread->engine; 1698139Sigor@sysoev.ru 169953Sigor@sysoev.ru listen = nxt_router_listen_event(&engine->listen_connections, skcf); 170053Sigor@sysoev.ru 170153Sigor@sysoev.ru nxt_fd_event_delete(engine, &listen->socket); 170253Sigor@sysoev.ru 1703163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket delete: %d", engine, 1704163Smax.romanov@nginx.com listen->socket.fd); 1705163Smax.romanov@nginx.com 170653Sigor@sysoev.ru listen->timer.handler = nxt_router_listen_socket_close; 170753Sigor@sysoev.ru listen->timer.work_queue = &engine->fast_work_queue; 170853Sigor@sysoev.ru 170953Sigor@sysoev.ru nxt_timer_add(engine, &listen->timer, 0); 1710139Sigor@sysoev.ru 1711153Sigor@sysoev.ru job->work.next = NULL; 1712153Sigor@sysoev.ru job->work.handler = nxt_router_conf_wait; 1713153Sigor@sysoev.ru 1714153Sigor@sysoev.ru nxt_event_engine_post(job->tmcf->engine, &job->work); 171553Sigor@sysoev.ru } 171653Sigor@sysoev.ru 171753Sigor@sysoev.ru 171853Sigor@sysoev.ru static void 171953Sigor@sysoev.ru nxt_router_listen_socket_close(nxt_task_t *task, void *obj, void *data) 172053Sigor@sysoev.ru { 172153Sigor@sysoev.ru nxt_timer_t *timer; 172253Sigor@sysoev.ru nxt_listen_event_t *listen; 172353Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 172453Sigor@sysoev.ru 172553Sigor@sysoev.ru timer = obj; 172653Sigor@sysoev.ru listen = nxt_timer_data(timer, nxt_listen_event_t, timer); 172753Sigor@sysoev.ru joint = listen->socket.data; 172853Sigor@sysoev.ru 1729163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket close: %d", task->thread->engine, 1730163Smax.romanov@nginx.com listen->socket.fd); 1731163Smax.romanov@nginx.com 173253Sigor@sysoev.ru nxt_queue_remove(&listen->link); 1733123Smax.romanov@nginx.com 1734123Smax.romanov@nginx.com /* 'task' refers to listen->task and we cannot use after nxt_free() */ 1735123Smax.romanov@nginx.com task = &task->thread->engine->task; 1736123Smax.romanov@nginx.com 173753Sigor@sysoev.ru nxt_free(listen); 173853Sigor@sysoev.ru 173953Sigor@sysoev.ru nxt_router_listen_socket_release(task, joint); 174053Sigor@sysoev.ru } 174153Sigor@sysoev.ru 174253Sigor@sysoev.ru 174353Sigor@sysoev.ru static void 174453Sigor@sysoev.ru nxt_router_listen_socket_release(nxt_task_t *task, 174553Sigor@sysoev.ru nxt_socket_conf_joint_t *joint) 174653Sigor@sysoev.ru { 1747118Sigor@sysoev.ru nxt_socket_conf_t *skcf; 1748115Sigor@sysoev.ru nxt_router_socket_t *rtsk; 174953Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 175053Sigor@sysoev.ru 1751118Sigor@sysoev.ru skcf = joint->socket_conf; 1752118Sigor@sysoev.ru rtsk = skcf->socket; 1753118Sigor@sysoev.ru lock = &skcf->router_conf->router->lock; 175453Sigor@sysoev.ru 175553Sigor@sysoev.ru nxt_thread_spin_lock(lock); 175653Sigor@sysoev.ru 1757163Smax.romanov@nginx.com nxt_debug(task, "engine %p: listen socket release: rtsk->count %D", 1758163Smax.romanov@nginx.com task->thread->engine, rtsk->count); 1759163Smax.romanov@nginx.com 1760115Sigor@sysoev.ru if (--rtsk->count != 0) { 1761115Sigor@sysoev.ru rtsk = NULL; 176253Sigor@sysoev.ru } 176353Sigor@sysoev.ru 176453Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 176553Sigor@sysoev.ru 1766115Sigor@sysoev.ru if (rtsk != NULL) { 1767115Sigor@sysoev.ru nxt_socket_close(task, rtsk->fd); 1768115Sigor@sysoev.ru nxt_free(rtsk); 1769118Sigor@sysoev.ru skcf->socket = NULL; 177053Sigor@sysoev.ru } 177153Sigor@sysoev.ru 177253Sigor@sysoev.ru nxt_router_conf_release(task, joint); 177353Sigor@sysoev.ru } 177453Sigor@sysoev.ru 177553Sigor@sysoev.ru 177653Sigor@sysoev.ru static void 177753Sigor@sysoev.ru nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) 177853Sigor@sysoev.ru { 1779156Sigor@sysoev.ru nxt_bool_t exit; 178053Sigor@sysoev.ru nxt_socket_conf_t *skcf; 178153Sigor@sysoev.ru nxt_router_conf_t *rtcf; 178253Sigor@sysoev.ru nxt_thread_spinlock_t *lock; 178353Sigor@sysoev.ru 1784163Smax.romanov@nginx.com nxt_debug(task, "conf joint %p count: %D", joint, joint->count); 178553Sigor@sysoev.ru 178653Sigor@sysoev.ru if (--joint->count != 0) { 178753Sigor@sysoev.ru return; 178853Sigor@sysoev.ru } 178953Sigor@sysoev.ru 179053Sigor@sysoev.ru nxt_queue_remove(&joint->link); 179153Sigor@sysoev.ru 179253Sigor@sysoev.ru skcf = joint->socket_conf; 179353Sigor@sysoev.ru rtcf = skcf->router_conf; 179453Sigor@sysoev.ru lock = &rtcf->router->lock; 179553Sigor@sysoev.ru 179653Sigor@sysoev.ru nxt_thread_spin_lock(lock); 179753Sigor@sysoev.ru 1798163Smax.romanov@nginx.com nxt_debug(task, "conf skcf %p: %D, rtcf %p: %D", skcf, skcf->count, 1799163Smax.romanov@nginx.com rtcf, rtcf->count); 1800163Smax.romanov@nginx.com 180153Sigor@sysoev.ru if (--skcf->count != 0) { 180253Sigor@sysoev.ru rtcf = NULL; 180353Sigor@sysoev.ru 180453Sigor@sysoev.ru } else { 180553Sigor@sysoev.ru nxt_queue_remove(&skcf->link); 180653Sigor@sysoev.ru 180753Sigor@sysoev.ru if (--rtcf->count != 0) { 180853Sigor@sysoev.ru rtcf = NULL; 180953Sigor@sysoev.ru } 181053Sigor@sysoev.ru } 181153Sigor@sysoev.ru 181253Sigor@sysoev.ru nxt_thread_spin_unlock(lock); 181353Sigor@sysoev.ru 1814141Smax.romanov@nginx.com /* TODO remove engine->port */ 1815141Smax.romanov@nginx.com /* TODO excude from connected ports */ 1816141Smax.romanov@nginx.com 1817156Sigor@sysoev.ru /* The joint content can be used before memory pool destruction. */ 1818156Sigor@sysoev.ru exit = nxt_queue_is_empty(&joint->engine->joints); 1819156Sigor@sysoev.ru 182053Sigor@sysoev.ru if (rtcf != NULL) { 1821115Sigor@sysoev.ru nxt_debug(task, "old router conf is destroyed"); 1822131Smax.romanov@nginx.com 1823131Smax.romanov@nginx.com nxt_mp_thread_adopt(rtcf->mem_pool); 1824131Smax.romanov@nginx.com 182565Sigor@sysoev.ru nxt_mp_destroy(rtcf->mem_pool); 182653Sigor@sysoev.ru } 182753Sigor@sysoev.ru 1828156Sigor@sysoev.ru if (exit) { 182953Sigor@sysoev.ru nxt_thread_exit(task->thread); 183053Sigor@sysoev.ru } 183153Sigor@sysoev.ru } 183253Sigor@sysoev.ru 183353Sigor@sysoev.ru 183453Sigor@sysoev.ru static void 183553Sigor@sysoev.ru nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) 183653Sigor@sysoev.ru { 1837141Smax.romanov@nginx.com nxt_port_t *port; 183853Sigor@sysoev.ru nxt_thread_link_t *link; 183953Sigor@sysoev.ru nxt_event_engine_t *engine; 184053Sigor@sysoev.ru nxt_thread_handle_t handle; 184153Sigor@sysoev.ru 184258Svbart@nginx.com handle = (nxt_thread_handle_t) obj; 184353Sigor@sysoev.ru link = data; 184453Sigor@sysoev.ru 184553Sigor@sysoev.ru nxt_thread_wait(handle); 184653Sigor@sysoev.ru 184753Sigor@sysoev.ru engine = link->engine; 184853Sigor@sysoev.ru 184953Sigor@sysoev.ru nxt_queue_remove(&engine->link); 185053Sigor@sysoev.ru 1851141Smax.romanov@nginx.com port = engine->port; 1852141Smax.romanov@nginx.com 1853141Smax.romanov@nginx.com // TODO notify all apps 1854141Smax.romanov@nginx.com 1855163Smax.romanov@nginx.com nxt_mp_thread_adopt(port->mem_pool); 1856163Smax.romanov@nginx.com nxt_port_release(port); 1857163Smax.romanov@nginx.com 1858163Smax.romanov@nginx.com nxt_mp_thread_adopt(engine->mem_pool); 185963Sigor@sysoev.ru nxt_mp_destroy(engine->mem_pool); 186053Sigor@sysoev.ru 186153Sigor@sysoev.ru nxt_event_engine_free(engine); 186253Sigor@sysoev.ru 186353Sigor@sysoev.ru nxt_free(link); 186453Sigor@sysoev.ru } 186553Sigor@sysoev.ru 186653Sigor@sysoev.ru 1867206Smax.romanov@nginx.com static const nxt_conn_state_t nxt_router_conn_read_header_state 186853Sigor@sysoev.ru nxt_aligned(64) = 186953Sigor@sysoev.ru { 187053Sigor@sysoev.ru .ready_handler = nxt_router_conn_http_header_parse, 187153Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 187253Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 187353Sigor@sysoev.ru 187453Sigor@sysoev.ru .timer_handler = nxt_router_conn_timeout, 187553Sigor@sysoev.ru .timer_value = nxt_router_conn_timeout_value, 187653Sigor@sysoev.ru .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 187753Sigor@sysoev.ru }; 187853Sigor@sysoev.ru 187953Sigor@sysoev.ru 1880206Smax.romanov@nginx.com static const nxt_conn_state_t nxt_router_conn_read_body_state 1881206Smax.romanov@nginx.com nxt_aligned(64) = 1882206Smax.romanov@nginx.com { 1883206Smax.romanov@nginx.com .ready_handler = nxt_router_conn_http_body_read, 1884206Smax.romanov@nginx.com .close_handler = nxt_router_conn_close, 1885206Smax.romanov@nginx.com .error_handler = nxt_router_conn_error, 1886206Smax.romanov@nginx.com 1887206Smax.romanov@nginx.com .timer_handler = nxt_router_conn_timeout, 1888206Smax.romanov@nginx.com .timer_value = nxt_router_conn_timeout_value, 1889206Smax.romanov@nginx.com .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout), 1890206Smax.romanov@nginx.com .timer_autoreset = 1, 1891206Smax.romanov@nginx.com }; 1892206Smax.romanov@nginx.com 1893206Smax.romanov@nginx.com 189453Sigor@sysoev.ru static void 189553Sigor@sysoev.ru nxt_router_conn_init(nxt_task_t *task, void *obj, void *data) 189653Sigor@sysoev.ru { 189753Sigor@sysoev.ru size_t size; 189862Sigor@sysoev.ru nxt_conn_t *c; 189953Sigor@sysoev.ru nxt_event_engine_t *engine; 190053Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 190153Sigor@sysoev.ru 190253Sigor@sysoev.ru c = obj; 190353Sigor@sysoev.ru joint = data; 190453Sigor@sysoev.ru 190553Sigor@sysoev.ru nxt_debug(task, "router conn init"); 190653Sigor@sysoev.ru 190753Sigor@sysoev.ru joint->count++; 190853Sigor@sysoev.ru 190953Sigor@sysoev.ru size = joint->socket_conf->header_buffer_size; 191053Sigor@sysoev.ru c->read = nxt_buf_mem_alloc(c->mem_pool, size, 0); 191153Sigor@sysoev.ru 191253Sigor@sysoev.ru c->socket.data = NULL; 191353Sigor@sysoev.ru 191453Sigor@sysoev.ru engine = task->thread->engine; 191553Sigor@sysoev.ru c->read_work_queue = &engine->fast_work_queue; 191653Sigor@sysoev.ru c->write_work_queue = &engine->fast_work_queue; 191753Sigor@sysoev.ru 1918206Smax.romanov@nginx.com c->read_state = &nxt_router_conn_read_header_state; 191953Sigor@sysoev.ru 192062Sigor@sysoev.ru nxt_conn_read(engine, c); 192153Sigor@sysoev.ru } 192253Sigor@sysoev.ru 192353Sigor@sysoev.ru 192462Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_write_state 192553Sigor@sysoev.ru nxt_aligned(64) = 192653Sigor@sysoev.ru { 192788Smax.romanov@nginx.com .ready_handler = nxt_router_conn_ready, 192853Sigor@sysoev.ru .close_handler = nxt_router_conn_close, 192953Sigor@sysoev.ru .error_handler = nxt_router_conn_error, 193053Sigor@sysoev.ru }; 193153Sigor@sysoev.ru 193253Sigor@sysoev.ru 193353Sigor@sysoev.ru static void 1934119Smax.romanov@nginx.com nxt_router_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 193588Smax.romanov@nginx.com { 193688Smax.romanov@nginx.com size_t dump_size; 1937194Smax.romanov@nginx.com nxt_buf_t *b, *last; 193888Smax.romanov@nginx.com nxt_conn_t *c; 193988Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 194088Smax.romanov@nginx.com nxt_event_engine_t *engine; 194188Smax.romanov@nginx.com 194288Smax.romanov@nginx.com b = msg->buf; 194388Smax.romanov@nginx.com engine = task->thread->engine; 194488Smax.romanov@nginx.com 194588Smax.romanov@nginx.com rc = nxt_event_engine_request_find(engine, msg->port_msg.stream); 194688Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 194788Smax.romanov@nginx.com nxt_debug(task, "request id %08uxD not found", msg->port_msg.stream); 194888Smax.romanov@nginx.com 194988Smax.romanov@nginx.com return; 195088Smax.romanov@nginx.com } 195188Smax.romanov@nginx.com 195288Smax.romanov@nginx.com c = rc->conn; 195388Smax.romanov@nginx.com 195488Smax.romanov@nginx.com dump_size = nxt_buf_used_size(b); 195588Smax.romanov@nginx.com 195688Smax.romanov@nginx.com if (dump_size > 300) { 195788Smax.romanov@nginx.com dump_size = 300; 195888Smax.romanov@nginx.com } 195988Smax.romanov@nginx.com 1960119Smax.romanov@nginx.com nxt_debug(task, "%srouter app data (%z): %*s", 196188Smax.romanov@nginx.com msg->port_msg.last ? "last " : "", msg->size, dump_size, 196288Smax.romanov@nginx.com b->mem.pos); 196388Smax.romanov@nginx.com 196488Smax.romanov@nginx.com if (msg->size == 0) { 196588Smax.romanov@nginx.com b = NULL; 196688Smax.romanov@nginx.com } 196788Smax.romanov@nginx.com 196888Smax.romanov@nginx.com if (msg->port_msg.last != 0) { 196988Smax.romanov@nginx.com nxt_debug(task, "router data create last buf"); 197088Smax.romanov@nginx.com 197188Smax.romanov@nginx.com last = nxt_buf_sync_alloc(c->mem_pool, NXT_BUF_SYNC_LAST); 197288Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 197388Smax.romanov@nginx.com /* TODO pogorevaTb */ 197488Smax.romanov@nginx.com } 197588Smax.romanov@nginx.com 197688Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 1977167Smax.romanov@nginx.com 1978167Smax.romanov@nginx.com if (rc->app_port != NULL) { 1979167Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 1980167Smax.romanov@nginx.com 1981167Smax.romanov@nginx.com rc->app_port = NULL; 1982167Smax.romanov@nginx.com } 1983206Smax.romanov@nginx.com 1984206Smax.romanov@nginx.com rc->conn = NULL; 198588Smax.romanov@nginx.com } 198688Smax.romanov@nginx.com 198788Smax.romanov@nginx.com if (b == NULL) { 198888Smax.romanov@nginx.com return; 198988Smax.romanov@nginx.com } 199088Smax.romanov@nginx.com 1991206Smax.romanov@nginx.com if (msg->buf == b) { 1992206Smax.romanov@nginx.com /* Disable instant buffer completion/re-using by port. */ 1993206Smax.romanov@nginx.com msg->buf = NULL; 1994206Smax.romanov@nginx.com } 1995194Smax.romanov@nginx.com 199688Smax.romanov@nginx.com if (c->write == NULL) { 199788Smax.romanov@nginx.com c->write = b; 199888Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 199988Smax.romanov@nginx.com 200088Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 200188Smax.romanov@nginx.com } else { 200288Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 200388Smax.romanov@nginx.com 200488Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 200588Smax.romanov@nginx.com } 200688Smax.romanov@nginx.com } 200788Smax.romanov@nginx.com 2008141Smax.romanov@nginx.com nxt_inline const char * 2009141Smax.romanov@nginx.com nxt_router_text_by_code(int code) 2010141Smax.romanov@nginx.com { 2011141Smax.romanov@nginx.com switch (code) { 2012141Smax.romanov@nginx.com case 400: return "Bad request"; 2013141Smax.romanov@nginx.com case 404: return "Not found"; 2014141Smax.romanov@nginx.com case 403: return "Forbidden"; 2015206Smax.romanov@nginx.com case 408: return "Request Timeout"; 2016206Smax.romanov@nginx.com case 411: return "Length Required"; 2017206Smax.romanov@nginx.com case 413: return "Request Entity Too Large"; 2018141Smax.romanov@nginx.com case 500: 2019141Smax.romanov@nginx.com default: return "Internal server error"; 2020141Smax.romanov@nginx.com } 2021141Smax.romanov@nginx.com } 2022141Smax.romanov@nginx.com 2023163Smax.romanov@nginx.com 2024163Smax.romanov@nginx.com static nxt_buf_t * 2025163Smax.romanov@nginx.com nxt_router_get_error_buf(nxt_task_t *task, nxt_mp_t *mp, int code, 2026163Smax.romanov@nginx.com const char* fmt, va_list args) 202788Smax.romanov@nginx.com { 2028163Smax.romanov@nginx.com nxt_buf_t *b, *last; 2029163Smax.romanov@nginx.com const char *msg; 2030163Smax.romanov@nginx.com 2031163Smax.romanov@nginx.com b = nxt_buf_mem_ts_alloc(task, mp, 16384); 2032141Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 2033163Smax.romanov@nginx.com return NULL; 2034141Smax.romanov@nginx.com } 2035141Smax.romanov@nginx.com 2036141Smax.romanov@nginx.com b->mem.free = nxt_sprintf(b->mem.free, b->mem.end, 2037141Smax.romanov@nginx.com "HTTP/1.0 %d %s\r\n" 2038141Smax.romanov@nginx.com "Content-Type: text/plain\r\n" 2039141Smax.romanov@nginx.com "Connection: close\r\n\r\n", 2040141Smax.romanov@nginx.com code, nxt_router_text_by_code(code)); 2041141Smax.romanov@nginx.com 2042141Smax.romanov@nginx.com msg = (const char *) b->mem.free; 2043141Smax.romanov@nginx.com 2044141Smax.romanov@nginx.com b->mem.free = nxt_vsprintf(b->mem.free, b->mem.end, fmt, args); 2045206Smax.romanov@nginx.com b->mem.free[0] = '\0'; 2046141Smax.romanov@nginx.com 2047141Smax.romanov@nginx.com nxt_log_alert(task->log, "error %d: %s", code, msg); 2048141Smax.romanov@nginx.com 2049163Smax.romanov@nginx.com last = nxt_buf_mem_ts_alloc(task, mp, 0); 2050163Smax.romanov@nginx.com 2051141Smax.romanov@nginx.com if (nxt_slow_path(last == NULL)) { 2052163Smax.romanov@nginx.com nxt_mp_release(mp, b); 2053163Smax.romanov@nginx.com return NULL; 2054141Smax.romanov@nginx.com } 2055141Smax.romanov@nginx.com 2056163Smax.romanov@nginx.com nxt_buf_set_sync(last); 2057163Smax.romanov@nginx.com nxt_buf_set_last(last); 2058163Smax.romanov@nginx.com 2059141Smax.romanov@nginx.com nxt_buf_chain_add(&b, last); 2060141Smax.romanov@nginx.com 2061163Smax.romanov@nginx.com return b; 2062163Smax.romanov@nginx.com } 2063163Smax.romanov@nginx.com 2064163Smax.romanov@nginx.com 2065163Smax.romanov@nginx.com 2066163Smax.romanov@nginx.com static void 2067163Smax.romanov@nginx.com nxt_router_gen_error(nxt_task_t *task, nxt_conn_t *c, int code, 2068163Smax.romanov@nginx.com const char* fmt, ...) 2069163Smax.romanov@nginx.com { 2070163Smax.romanov@nginx.com va_list args; 2071163Smax.romanov@nginx.com nxt_buf_t *b; 2072163Smax.romanov@nginx.com 2073163Smax.romanov@nginx.com va_start(args, fmt); 2074163Smax.romanov@nginx.com b = nxt_router_get_error_buf(task, c->mem_pool, code, fmt, args); 2075163Smax.romanov@nginx.com va_end(args); 2076163Smax.romanov@nginx.com 2077206Smax.romanov@nginx.com if (c->socket.data != NULL) { 2078206Smax.romanov@nginx.com nxt_mp_free(c->mem_pool, c->socket.data); 2079206Smax.romanov@nginx.com c->socket.data = NULL; 2080206Smax.romanov@nginx.com } 2081206Smax.romanov@nginx.com 2082141Smax.romanov@nginx.com if (c->write == NULL) { 2083141Smax.romanov@nginx.com c->write = b; 2084141Smax.romanov@nginx.com c->write_state = &nxt_router_conn_write_state; 2085141Smax.romanov@nginx.com 2086141Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 2087141Smax.romanov@nginx.com } else { 2088141Smax.romanov@nginx.com nxt_debug(task, "router data attach out bufs to existing chain"); 2089141Smax.romanov@nginx.com 2090141Smax.romanov@nginx.com nxt_buf_chain_add(&c->write, b); 2091141Smax.romanov@nginx.com } 2092141Smax.romanov@nginx.com } 2093141Smax.romanov@nginx.com 2094141Smax.romanov@nginx.com 2095141Smax.romanov@nginx.com static void 2096192Smax.romanov@nginx.com nxt_router_sw_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 2097192Smax.romanov@nginx.com { 2098192Smax.romanov@nginx.com nxt_start_worker_t *sw; 2099192Smax.romanov@nginx.com 2100192Smax.romanov@nginx.com sw = data; 2101192Smax.romanov@nginx.com 2102192Smax.romanov@nginx.com nxt_assert(sw != NULL); 2103192Smax.romanov@nginx.com nxt_assert(sw->app->pending_workers != 0); 2104192Smax.romanov@nginx.com 2105192Smax.romanov@nginx.com msg->new_port->app = sw->app; 2106192Smax.romanov@nginx.com 2107192Smax.romanov@nginx.com sw->app->pending_workers--; 2108192Smax.romanov@nginx.com sw->app->workers++; 2109192Smax.romanov@nginx.com 2110192Smax.romanov@nginx.com nxt_debug(task, "sw %p got port %p", sw, msg->new_port); 2111192Smax.romanov@nginx.com 2112192Smax.romanov@nginx.com nxt_router_app_release_port(task, msg->new_port, sw->app); 2113192Smax.romanov@nginx.com 2114192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2115192Smax.romanov@nginx.com } 2116192Smax.romanov@nginx.com 2117192Smax.romanov@nginx.com 2118192Smax.romanov@nginx.com static void 2119192Smax.romanov@nginx.com nxt_router_sw_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 2120192Smax.romanov@nginx.com { 2121192Smax.romanov@nginx.com nxt_start_worker_t *sw; 2122192Smax.romanov@nginx.com 2123192Smax.romanov@nginx.com sw = data; 2124192Smax.romanov@nginx.com 2125192Smax.romanov@nginx.com nxt_assert(sw != NULL); 2126192Smax.romanov@nginx.com nxt_assert(sw->app->pending_workers != 0); 2127192Smax.romanov@nginx.com 2128192Smax.romanov@nginx.com sw->app->pending_workers--; 2129192Smax.romanov@nginx.com 2130192Smax.romanov@nginx.com nxt_debug(task, "sw %p error, failed to start app '%V'", sw, &sw->app->name); 2131192Smax.romanov@nginx.com 2132192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2133192Smax.romanov@nginx.com } 2134192Smax.romanov@nginx.com 2135192Smax.romanov@nginx.com 2136192Smax.romanov@nginx.com static void 2137141Smax.romanov@nginx.com nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data) 2138141Smax.romanov@nginx.com { 2139174Sigor@sysoev.ru size_t size; 2140192Smax.romanov@nginx.com uint32_t stream; 2141141Smax.romanov@nginx.com nxt_buf_t *b; 2142141Smax.romanov@nginx.com nxt_app_t *app; 2143240Sigor@sysoev.ru nxt_port_t *main_port, *router_port; 2144141Smax.romanov@nginx.com nxt_runtime_t *rt; 2145141Smax.romanov@nginx.com nxt_start_worker_t *sw; 2146141Smax.romanov@nginx.com 2147141Smax.romanov@nginx.com sw = obj; 2148141Smax.romanov@nginx.com app = sw->app; 2149141Smax.romanov@nginx.com 2150167Smax.romanov@nginx.com nxt_queue_insert_tail(&app->requests, &sw->ra->link); 2151167Smax.romanov@nginx.com 2152163Smax.romanov@nginx.com if (app->workers + app->pending_workers >= app->max_workers) { 2153244Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p %uD/%uD running/pending workers, " 2154244Smax.romanov@nginx.com "max_workers (%uD) reached", &app->name, app, 2155244Smax.romanov@nginx.com app->workers, app->pending_workers, app->max_workers); 2156192Smax.romanov@nginx.com 2157192Smax.romanov@nginx.com nxt_router_sw_release(task, sw); 2158163Smax.romanov@nginx.com 2159163Smax.romanov@nginx.com return; 2160163Smax.romanov@nginx.com } 2161163Smax.romanov@nginx.com 2162163Smax.romanov@nginx.com app->pending_workers++; 2163163Smax.romanov@nginx.com 2164192Smax.romanov@nginx.com nxt_debug(task, "sw %p send", sw); 216588Smax.romanov@nginx.com 2166119Smax.romanov@nginx.com rt = task->thread->runtime; 2167240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 2168192Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 2169141Smax.romanov@nginx.com 2170174Sigor@sysoev.ru size = app->name.length + 1 + app->conf.length; 2171174Sigor@sysoev.ru 2172240Sigor@sysoev.ru b = nxt_buf_mem_alloc(main_port->mem_pool, size, 0); 2173174Sigor@sysoev.ru 2174174Sigor@sysoev.ru nxt_buf_cpystr(b, &app->name); 2175174Sigor@sysoev.ru *b->mem.free++ = '\0'; 2176141Smax.romanov@nginx.com nxt_buf_cpystr(b, &app->conf); 2177141Smax.romanov@nginx.com 2178192Smax.romanov@nginx.com stream = nxt_port_rpc_register_handler(task, router_port, 2179192Smax.romanov@nginx.com nxt_router_sw_ready, 2180192Smax.romanov@nginx.com nxt_router_sw_error, 2181240Sigor@sysoev.ru main_port->pid, sw); 2182240Sigor@sysoev.ru 2183240Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1, 2184192Smax.romanov@nginx.com stream, router_port->id, b); 2185141Smax.romanov@nginx.com } 2186141Smax.romanov@nginx.com 2187141Smax.romanov@nginx.com 2188163Smax.romanov@nginx.com static nxt_bool_t 2189167Smax.romanov@nginx.com nxt_router_app_free(nxt_task_t *task, nxt_app_t *app) 2190163Smax.romanov@nginx.com { 2191192Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2192192Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2193167Smax.romanov@nginx.com 2194167Smax.romanov@nginx.com nxt_thread_log_debug("app '%V' %p state: %d/%uD/%uD/%d", &app->name, app, 2195167Smax.romanov@nginx.com app->live, app->workers, app->pending_workers, 2196167Smax.romanov@nginx.com nxt_queue_is_empty(&app->requests)); 2197167Smax.romanov@nginx.com 2198163Smax.romanov@nginx.com if (app->live == 0 && app->workers == 0 && 2199163Smax.romanov@nginx.com app->pending_workers == 0 && 2200163Smax.romanov@nginx.com nxt_queue_is_empty(&app->requests)) { 2201163Smax.romanov@nginx.com 2202163Smax.romanov@nginx.com nxt_thread_mutex_destroy(&app->mutex); 2203163Smax.romanov@nginx.com nxt_free(app); 2204163Smax.romanov@nginx.com 2205163Smax.romanov@nginx.com return 1; 2206163Smax.romanov@nginx.com } 2207163Smax.romanov@nginx.com 2208167Smax.romanov@nginx.com if (app->live == 1 && nxt_queue_is_empty(&app->requests) == 0 && 2209167Smax.romanov@nginx.com (app->workers + app->pending_workers < app->max_workers)) { 2210167Smax.romanov@nginx.com 2211167Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 2212167Smax.romanov@nginx.com nxt_queue_remove(lnk); 2213167Smax.romanov@nginx.com 2214167Smax.romanov@nginx.com ra = nxt_queue_link_data(lnk, nxt_req_app_link_t, link); 2215167Smax.romanov@nginx.com 2216192Smax.romanov@nginx.com nxt_router_sw_create(task, app, ra); 2217167Smax.romanov@nginx.com } 2218167Smax.romanov@nginx.com 2219163Smax.romanov@nginx.com return 0; 2220163Smax.romanov@nginx.com } 2221163Smax.romanov@nginx.com 2222163Smax.romanov@nginx.com 2223141Smax.romanov@nginx.com static nxt_port_t * 2224167Smax.romanov@nginx.com nxt_router_app_get_port(nxt_app_t *app, uint32_t req_id) 2225141Smax.romanov@nginx.com { 2226141Smax.romanov@nginx.com nxt_port_t *port; 2227141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2228141Smax.romanov@nginx.com 2229141Smax.romanov@nginx.com port = NULL; 2230141Smax.romanov@nginx.com 2231141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2232141Smax.romanov@nginx.com 2233141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->ports)) { 2234141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->ports); 2235141Smax.romanov@nginx.com nxt_queue_remove(lnk); 2236141Smax.romanov@nginx.com 2237141Smax.romanov@nginx.com lnk->next = NULL; 2238141Smax.romanov@nginx.com 2239141Smax.romanov@nginx.com port = nxt_queue_link_data(lnk, nxt_port_t, app_link); 2240167Smax.romanov@nginx.com 2241167Smax.romanov@nginx.com port->app_req_id = req_id; 2242141Smax.romanov@nginx.com } 2243141Smax.romanov@nginx.com 2244141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2245141Smax.romanov@nginx.com 2246141Smax.romanov@nginx.com return port; 2247141Smax.romanov@nginx.com } 2248141Smax.romanov@nginx.com 2249141Smax.romanov@nginx.com 2250141Smax.romanov@nginx.com static void 2251141Smax.romanov@nginx.com nxt_router_app_release_port(nxt_task_t *task, void *obj, void *data) 2252141Smax.romanov@nginx.com { 2253141Smax.romanov@nginx.com nxt_app_t *app; 2254141Smax.romanov@nginx.com nxt_port_t *port; 2255141Smax.romanov@nginx.com nxt_work_t *work; 2256141Smax.romanov@nginx.com nxt_queue_link_t *lnk; 2257167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 2258141Smax.romanov@nginx.com 2259141Smax.romanov@nginx.com port = obj; 2260141Smax.romanov@nginx.com app = data; 2261141Smax.romanov@nginx.com 2262141Smax.romanov@nginx.com nxt_assert(app != NULL); 2263141Smax.romanov@nginx.com nxt_assert(app == port->app); 2264141Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 2265141Smax.romanov@nginx.com 2266141Smax.romanov@nginx.com 2267141Smax.romanov@nginx.com if (task->thread->engine != port->engine) { 2268163Smax.romanov@nginx.com work = &port->work; 2269141Smax.romanov@nginx.com 2270141Smax.romanov@nginx.com nxt_debug(task, "post release port to engine %p", port->engine); 2271141Smax.romanov@nginx.com 2272141Smax.romanov@nginx.com work->next = NULL; 2273141Smax.romanov@nginx.com work->handler = nxt_router_app_release_port; 2274166Smax.romanov@nginx.com work->task = &port->engine->task; 2275141Smax.romanov@nginx.com work->obj = port; 2276141Smax.romanov@nginx.com work->data = app; 2277141Smax.romanov@nginx.com 2278141Smax.romanov@nginx.com nxt_event_engine_post(port->engine, work); 2279141Smax.romanov@nginx.com 2280141Smax.romanov@nginx.com return; 2281141Smax.romanov@nginx.com } 2282141Smax.romanov@nginx.com 2283141Smax.romanov@nginx.com if (!nxt_queue_is_empty(&app->requests)) { 2284141Smax.romanov@nginx.com lnk = nxt_queue_first(&app->requests); 2285141Smax.romanov@nginx.com nxt_queue_remove(lnk); 2286141Smax.romanov@nginx.com 2287167Smax.romanov@nginx.com ra = nxt_queue_link_data(lnk, nxt_req_app_link_t, link); 2288167Smax.romanov@nginx.com 2289167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p process next request #%uxD", 2290167Smax.romanov@nginx.com &app->name, app, ra->req_id); 2291167Smax.romanov@nginx.com 2292167Smax.romanov@nginx.com ra->app_port = port; 2293182Smax.romanov@nginx.com port->app_req_id = ra->req_id; 2294167Smax.romanov@nginx.com 2295167Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, ra, port); 2296167Smax.romanov@nginx.com 2297167Smax.romanov@nginx.com nxt_router_ra_release(task, ra, ra->work.data); 2298141Smax.romanov@nginx.com 2299141Smax.romanov@nginx.com return; 2300141Smax.romanov@nginx.com } 2301141Smax.romanov@nginx.com 2302167Smax.romanov@nginx.com port->app_req_id = 0; 2303167Smax.romanov@nginx.com 2304163Smax.romanov@nginx.com if (port->pair[1] == -1) { 2305167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p port already closed (pid %PI dead?)", 2306167Smax.romanov@nginx.com &app->name, app, port->pid); 2307163Smax.romanov@nginx.com 2308163Smax.romanov@nginx.com app->workers--; 2309167Smax.romanov@nginx.com nxt_router_app_free(task, app); 2310163Smax.romanov@nginx.com 2311163Smax.romanov@nginx.com port->app = NULL; 2312163Smax.romanov@nginx.com 2313163Smax.romanov@nginx.com nxt_port_release(port); 2314163Smax.romanov@nginx.com 2315163Smax.romanov@nginx.com return; 2316163Smax.romanov@nginx.com } 2317163Smax.romanov@nginx.com 2318163Smax.romanov@nginx.com if (!app->live) { 2319167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p is not alive, send QUIT to port", 2320167Smax.romanov@nginx.com &app->name, app); 2321163Smax.romanov@nginx.com 2322163Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, 2323163Smax.romanov@nginx.com -1, 0, 0, NULL); 2324163Smax.romanov@nginx.com 2325163Smax.romanov@nginx.com return; 2326163Smax.romanov@nginx.com } 2327163Smax.romanov@nginx.com 2328167Smax.romanov@nginx.com nxt_debug(task, "app '%V' %p requests queue is empty, keep the port", 2329167Smax.romanov@nginx.com &app->name, app); 2330141Smax.romanov@nginx.com 2331141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2332141Smax.romanov@nginx.com 2333141Smax.romanov@nginx.com nxt_queue_insert_head(&app->ports, &port->app_link); 2334141Smax.romanov@nginx.com 2335141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2336141Smax.romanov@nginx.com } 2337141Smax.romanov@nginx.com 2338141Smax.romanov@nginx.com 2339163Smax.romanov@nginx.com nxt_bool_t 2340141Smax.romanov@nginx.com nxt_router_app_remove_port(nxt_port_t *port) 2341141Smax.romanov@nginx.com { 2342163Smax.romanov@nginx.com nxt_app_t *app; 2343163Smax.romanov@nginx.com nxt_bool_t busy; 2344141Smax.romanov@nginx.com 2345141Smax.romanov@nginx.com app = port->app; 2346167Smax.romanov@nginx.com busy = port->app_req_id != 0; 2347163Smax.romanov@nginx.com 2348163Smax.romanov@nginx.com if (app == NULL) { 2349167Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, no app", port); 2350167Smax.romanov@nginx.com 2351163Smax.romanov@nginx.com nxt_assert(port->app_link.next == NULL); 2352163Smax.romanov@nginx.com 2353163Smax.romanov@nginx.com return 1; 2354141Smax.romanov@nginx.com } 2355141Smax.romanov@nginx.com 2356141Smax.romanov@nginx.com nxt_thread_mutex_lock(&app->mutex); 2357141Smax.romanov@nginx.com 2358163Smax.romanov@nginx.com if (port->app_link.next != NULL) { 2359163Smax.romanov@nginx.com 2360163Smax.romanov@nginx.com nxt_queue_remove(&port->app_link); 2361163Smax.romanov@nginx.com port->app_link.next = NULL; 2362163Smax.romanov@nginx.com 2363163Smax.romanov@nginx.com } 2364141Smax.romanov@nginx.com 2365141Smax.romanov@nginx.com nxt_thread_mutex_unlock(&app->mutex); 2366163Smax.romanov@nginx.com 2367163Smax.romanov@nginx.com if (busy == 0) { 2368167Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, free, app '%V' %p", port, 2369167Smax.romanov@nginx.com &app->name, app); 2370163Smax.romanov@nginx.com 2371163Smax.romanov@nginx.com app->workers--; 2372167Smax.romanov@nginx.com nxt_router_app_free(&port->engine->task, app); 2373163Smax.romanov@nginx.com 2374163Smax.romanov@nginx.com return 1; 2375163Smax.romanov@nginx.com } 2376163Smax.romanov@nginx.com 2377167Smax.romanov@nginx.com nxt_thread_log_debug("port %p app remove, busy, app '%V' %p, req #%uxD", 2378167Smax.romanov@nginx.com port, &app->name, app, port->app_req_id); 2379167Smax.romanov@nginx.com 2380163Smax.romanov@nginx.com return 0; 2381141Smax.romanov@nginx.com } 2382141Smax.romanov@nginx.com 2383141Smax.romanov@nginx.com 2384167Smax.romanov@nginx.com static nxt_int_t 2385167Smax.romanov@nginx.com nxt_router_app_port(nxt_task_t *task, nxt_req_app_link_t *ra) 2386141Smax.romanov@nginx.com { 2387141Smax.romanov@nginx.com nxt_app_t *app; 2388141Smax.romanov@nginx.com nxt_conn_t *c; 2389167Smax.romanov@nginx.com nxt_port_t *port; 2390141Smax.romanov@nginx.com nxt_start_worker_t *sw; 2391141Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 2392141Smax.romanov@nginx.com 2393141Smax.romanov@nginx.com port = NULL; 2394167Smax.romanov@nginx.com c = ra->rc->conn; 2395141Smax.romanov@nginx.com 2396141Smax.romanov@nginx.com joint = c->listen->socket.data; 2397141Smax.romanov@nginx.com app = joint->socket_conf->application; 2398141Smax.romanov@nginx.com 2399141Smax.romanov@nginx.com if (app == NULL) { 2400167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2401141Smax.romanov@nginx.com "Application is NULL in socket_conf"); 2402141Smax.romanov@nginx.com return NXT_ERROR; 2403141Smax.romanov@nginx.com } 2404141Smax.romanov@nginx.com 2405141Smax.romanov@nginx.com 2406167Smax.romanov@nginx.com port = nxt_router_app_get_port(app, ra->req_id); 2407141Smax.romanov@nginx.com 2408141Smax.romanov@nginx.com if (port != NULL) { 2409163Smax.romanov@nginx.com nxt_debug(task, "already have port for app '%V'", &app->name); 2410163Smax.romanov@nginx.com 2411167Smax.romanov@nginx.com ra->app_port = port; 2412141Smax.romanov@nginx.com return NXT_OK; 2413141Smax.romanov@nginx.com } 2414141Smax.romanov@nginx.com 2415192Smax.romanov@nginx.com sw = nxt_router_sw_create(task, app, ra); 2416141Smax.romanov@nginx.com 2417141Smax.romanov@nginx.com if (nxt_slow_path(sw == NULL)) { 2418167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2419141Smax.romanov@nginx.com "Failed to allocate start worker struct"); 2420141Smax.romanov@nginx.com return NXT_ERROR; 2421141Smax.romanov@nginx.com } 2422141Smax.romanov@nginx.com 2423141Smax.romanov@nginx.com return NXT_AGAIN; 242488Smax.romanov@nginx.com } 242588Smax.romanov@nginx.com 242688Smax.romanov@nginx.com 242788Smax.romanov@nginx.com static void 242853Sigor@sysoev.ru nxt_router_conn_http_header_parse(nxt_task_t *task, void *obj, void *data) 242953Sigor@sysoev.ru { 2430206Smax.romanov@nginx.com size_t size; 243153Sigor@sysoev.ru nxt_int_t ret; 2432206Smax.romanov@nginx.com nxt_buf_t *buf; 243362Sigor@sysoev.ru nxt_conn_t *c; 243488Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2435206Smax.romanov@nginx.com nxt_app_request_body_t *b; 243653Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 243788Smax.romanov@nginx.com nxt_app_request_header_t *h; 243853Sigor@sysoev.ru 243953Sigor@sysoev.ru c = obj; 244088Smax.romanov@nginx.com ap = data; 2441206Smax.romanov@nginx.com buf = c->read; 2442206Smax.romanov@nginx.com joint = c->listen->socket.data; 244353Sigor@sysoev.ru 244453Sigor@sysoev.ru nxt_debug(task, "router conn http header parse"); 244553Sigor@sysoev.ru 244688Smax.romanov@nginx.com if (ap == NULL) { 2447206Smax.romanov@nginx.com ap = nxt_mp_zalloc(c->mem_pool, sizeof(nxt_app_parse_ctx_t)); 244888Smax.romanov@nginx.com if (nxt_slow_path(ap == NULL)) { 244953Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 245053Sigor@sysoev.ru return; 245153Sigor@sysoev.ru } 245253Sigor@sysoev.ru 245388Smax.romanov@nginx.com ret = nxt_app_http_req_init(task, ap); 245461Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 245561Sigor@sysoev.ru nxt_router_conn_close(task, c, data); 245661Sigor@sysoev.ru return; 245761Sigor@sysoev.ru } 245888Smax.romanov@nginx.com 245988Smax.romanov@nginx.com c->socket.data = ap; 2460113Smax.romanov@nginx.com 2461113Smax.romanov@nginx.com ap->r.remote.start = nxt_sockaddr_address(c->remote); 2462113Smax.romanov@nginx.com ap->r.remote.length = c->remote->address_length; 2463206Smax.romanov@nginx.com 2464206Smax.romanov@nginx.com ap->r.header.buf = buf; 246553Sigor@sysoev.ru } 246653Sigor@sysoev.ru 246788Smax.romanov@nginx.com h = &ap->r.header; 2468206Smax.romanov@nginx.com b = &ap->r.body; 2469206Smax.romanov@nginx.com 2470206Smax.romanov@nginx.com ret = nxt_app_http_req_header_parse(task, ap, buf); 2471206Smax.romanov@nginx.com 2472206Smax.romanov@nginx.com nxt_debug(task, "http parse request header: %d", ret); 247353Sigor@sysoev.ru 247453Sigor@sysoev.ru switch (nxt_expect(NXT_DONE, ret)) { 247553Sigor@sysoev.ru 247653Sigor@sysoev.ru case NXT_DONE: 247788Smax.romanov@nginx.com nxt_debug(task, "router request header parsing complete, " 247888Smax.romanov@nginx.com "content length: %O, preread: %uz", 2479206Smax.romanov@nginx.com h->parsed_content_length, nxt_buf_mem_used_size(&buf->mem)); 2480206Smax.romanov@nginx.com 2481206Smax.romanov@nginx.com if (b->done) { 2482206Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 2483206Smax.romanov@nginx.com 2484206Smax.romanov@nginx.com return; 2485206Smax.romanov@nginx.com } 2486206Smax.romanov@nginx.com 2487206Smax.romanov@nginx.com if (joint->socket_conf->max_body_size > 0 && 2488206Smax.romanov@nginx.com (size_t) h->parsed_content_length > 2489206Smax.romanov@nginx.com joint->socket_conf->max_body_size) { 2490206Smax.romanov@nginx.com 2491206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 413, "Content-Length too big"); 2492206Smax.romanov@nginx.com return; 2493206Smax.romanov@nginx.com } 2494206Smax.romanov@nginx.com 2495206Smax.romanov@nginx.com if (nxt_buf_mem_free_size(&buf->mem) == 0) { 2496206Smax.romanov@nginx.com size = nxt_min(joint->socket_conf->body_buffer_size, 2497206Smax.romanov@nginx.com (size_t) h->parsed_content_length); 2498206Smax.romanov@nginx.com 2499206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2500206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2501206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2502206Smax.romanov@nginx.com "buffer for request body"); 2503206Smax.romanov@nginx.com return; 2504206Smax.romanov@nginx.com } 2505206Smax.romanov@nginx.com 2506206Smax.romanov@nginx.com c->read = buf->next; 2507206Smax.romanov@nginx.com 2508206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 2509206Smax.romanov@nginx.com } 2510206Smax.romanov@nginx.com 2511206Smax.romanov@nginx.com if (b->buf == NULL) { 2512206Smax.romanov@nginx.com b->buf = c->read; 2513206Smax.romanov@nginx.com } 2514206Smax.romanov@nginx.com 2515206Smax.romanov@nginx.com c->read_state = &nxt_router_conn_read_body_state; 2516206Smax.romanov@nginx.com break; 2517206Smax.romanov@nginx.com 2518206Smax.romanov@nginx.com case NXT_ERROR: 2519206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 400, "Request header parse error"); 2520206Smax.romanov@nginx.com return; 2521206Smax.romanov@nginx.com 2522206Smax.romanov@nginx.com default: /* NXT_AGAIN */ 2523206Smax.romanov@nginx.com 2524206Smax.romanov@nginx.com if (c->read->mem.free == c->read->mem.end) { 2525206Smax.romanov@nginx.com size = joint->socket_conf->large_header_buffer_size; 2526206Smax.romanov@nginx.com 2527206Smax.romanov@nginx.com if (size <= (size_t) nxt_buf_mem_used_size(&buf->mem) || 2528206Smax.romanov@nginx.com ap->r.header.bufs >= joint->socket_conf->large_header_buffers) { 2529206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 413, 2530206Smax.romanov@nginx.com "Too long request headers"); 2531206Smax.romanov@nginx.com return; 2532206Smax.romanov@nginx.com } 2533206Smax.romanov@nginx.com 2534206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2535206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2536206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2537206Smax.romanov@nginx.com "Failed to allocate large header " 2538206Smax.romanov@nginx.com "buffer"); 2539206Smax.romanov@nginx.com return; 2540206Smax.romanov@nginx.com } 2541206Smax.romanov@nginx.com 2542206Smax.romanov@nginx.com ap->r.header.bufs++; 2543206Smax.romanov@nginx.com 2544206Smax.romanov@nginx.com size = c->read->mem.free - c->read->mem.pos; 2545206Smax.romanov@nginx.com 2546206Smax.romanov@nginx.com c->read = nxt_buf_cpy(buf->next, c->read->mem.pos, size); 2547206Smax.romanov@nginx.com } 2548206Smax.romanov@nginx.com 2549206Smax.romanov@nginx.com } 2550206Smax.romanov@nginx.com 2551206Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 2552206Smax.romanov@nginx.com } 2553206Smax.romanov@nginx.com 2554206Smax.romanov@nginx.com 2555206Smax.romanov@nginx.com static void 2556206Smax.romanov@nginx.com nxt_router_conn_http_body_read(nxt_task_t *task, void *obj, void *data) 2557206Smax.romanov@nginx.com { 2558206Smax.romanov@nginx.com size_t size; 2559206Smax.romanov@nginx.com nxt_int_t ret; 2560206Smax.romanov@nginx.com nxt_buf_t *buf; 2561206Smax.romanov@nginx.com nxt_conn_t *c; 2562206Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2563206Smax.romanov@nginx.com nxt_app_request_body_t *b; 2564206Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 2565206Smax.romanov@nginx.com nxt_app_request_header_t *h; 2566206Smax.romanov@nginx.com 2567206Smax.romanov@nginx.com c = obj; 2568206Smax.romanov@nginx.com ap = data; 2569206Smax.romanov@nginx.com buf = c->read; 2570206Smax.romanov@nginx.com 2571206Smax.romanov@nginx.com nxt_debug(task, "router conn http body read"); 2572206Smax.romanov@nginx.com 2573206Smax.romanov@nginx.com nxt_assert(ap != NULL); 2574206Smax.romanov@nginx.com 2575206Smax.romanov@nginx.com b = &ap->r.body; 2576206Smax.romanov@nginx.com h = &ap->r.header; 2577206Smax.romanov@nginx.com 2578206Smax.romanov@nginx.com ret = nxt_app_http_req_body_read(task, ap, buf); 2579206Smax.romanov@nginx.com 2580206Smax.romanov@nginx.com nxt_debug(task, "http read request body: %d", ret); 2581206Smax.romanov@nginx.com 2582206Smax.romanov@nginx.com switch (nxt_expect(NXT_DONE, ret)) { 2583206Smax.romanov@nginx.com 2584206Smax.romanov@nginx.com case NXT_DONE: 258588Smax.romanov@nginx.com nxt_router_process_http_request(task, c, ap); 258688Smax.romanov@nginx.com return; 258753Sigor@sysoev.ru 258853Sigor@sysoev.ru case NXT_ERROR: 2589206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Read body error"); 259053Sigor@sysoev.ru return; 259153Sigor@sysoev.ru 259253Sigor@sysoev.ru default: /* NXT_AGAIN */ 259353Sigor@sysoev.ru 2594206Smax.romanov@nginx.com if (nxt_buf_mem_free_size(&buf->mem) == 0) { 2595206Smax.romanov@nginx.com joint = c->listen->socket.data; 2596206Smax.romanov@nginx.com 2597206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 2598206Smax.romanov@nginx.com 2599206Smax.romanov@nginx.com size = nxt_min(joint->socket_conf->body_buffer_size, 2600206Smax.romanov@nginx.com (size_t) h->parsed_content_length - b->preread_size); 2601206Smax.romanov@nginx.com 2602206Smax.romanov@nginx.com buf->next = nxt_buf_mem_alloc(c->mem_pool, size, 0); 2603206Smax.romanov@nginx.com if (nxt_slow_path(buf->next == NULL)) { 2604206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2605206Smax.romanov@nginx.com "buffer for request body"); 2606206Smax.romanov@nginx.com return; 260788Smax.romanov@nginx.com } 2608206Smax.romanov@nginx.com 2609206Smax.romanov@nginx.com c->read = buf->next; 261088Smax.romanov@nginx.com } 261188Smax.romanov@nginx.com 2612206Smax.romanov@nginx.com nxt_debug(task, "router request body read again, rest: %uz", 2613206Smax.romanov@nginx.com h->parsed_content_length - b->preread_size); 261488Smax.romanov@nginx.com } 261588Smax.romanov@nginx.com 261688Smax.romanov@nginx.com nxt_conn_read(task->thread->engine, c); 261788Smax.romanov@nginx.com } 261888Smax.romanov@nginx.com 261988Smax.romanov@nginx.com 262088Smax.romanov@nginx.com static void 262188Smax.romanov@nginx.com nxt_router_process_http_request(nxt_task_t *task, nxt_conn_t *c, 262288Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap) 262388Smax.romanov@nginx.com { 2624167Smax.romanov@nginx.com nxt_mp_t *port_mp; 2625122Smax.romanov@nginx.com nxt_int_t res; 2626167Smax.romanov@nginx.com nxt_port_t *port; 262788Smax.romanov@nginx.com nxt_req_id_t req_id; 262888Smax.romanov@nginx.com nxt_event_engine_t *engine; 2629167Smax.romanov@nginx.com nxt_req_app_link_t *ra; 263088Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 263188Smax.romanov@nginx.com 263288Smax.romanov@nginx.com engine = task->thread->engine; 263388Smax.romanov@nginx.com 263488Smax.romanov@nginx.com do { 2635138Sigor@sysoev.ru req_id = nxt_random(&task->thread->random); 263688Smax.romanov@nginx.com } while (nxt_event_engine_request_find(engine, req_id) != NULL); 263788Smax.romanov@nginx.com 263888Smax.romanov@nginx.com rc = nxt_conn_request_add(c, req_id); 2639122Smax.romanov@nginx.com 264088Smax.romanov@nginx.com if (nxt_slow_path(rc == NULL)) { 2641141Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, "Failed to allocate " 2642141Smax.romanov@nginx.com "req->conn link"); 2643141Smax.romanov@nginx.com 2644141Smax.romanov@nginx.com return; 264588Smax.romanov@nginx.com } 264688Smax.romanov@nginx.com 264788Smax.romanov@nginx.com nxt_event_engine_request_add(engine, rc); 264888Smax.romanov@nginx.com 264988Smax.romanov@nginx.com nxt_debug(task, "req_id %uxD linked to conn %p at engine %p", 265088Smax.romanov@nginx.com req_id, c, engine); 265153Sigor@sysoev.ru 2652167Smax.romanov@nginx.com 2653167Smax.romanov@nginx.com ra = nxt_router_ra_create(task, rc); 2654167Smax.romanov@nginx.com 2655167Smax.romanov@nginx.com ra->ap = ap; 2656167Smax.romanov@nginx.com ra->reply_port = engine->port; 2657167Smax.romanov@nginx.com 2658167Smax.romanov@nginx.com res = nxt_router_app_port(task, ra); 2659141Smax.romanov@nginx.com 2660141Smax.romanov@nginx.com if (res != NXT_OK) { 2661141Smax.romanov@nginx.com return; 2662141Smax.romanov@nginx.com } 2663141Smax.romanov@nginx.com 2664167Smax.romanov@nginx.com port = ra->app_port; 2665141Smax.romanov@nginx.com 2666141Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 2667141Smax.romanov@nginx.com nxt_router_gen_error(task, rc->conn, 500, "Application port not found"); 2668141Smax.romanov@nginx.com return; 2669141Smax.romanov@nginx.com } 2670141Smax.romanov@nginx.com 2671122Smax.romanov@nginx.com port_mp = port->mem_pool; 2672167Smax.romanov@nginx.com port->mem_pool = c->mem_pool; 2673167Smax.romanov@nginx.com 2674167Smax.romanov@nginx.com nxt_router_process_http_request_mp(task, ra, port); 2675167Smax.romanov@nginx.com 2676167Smax.romanov@nginx.com port->mem_pool = port_mp; 2677167Smax.romanov@nginx.com 2678167Smax.romanov@nginx.com 2679167Smax.romanov@nginx.com nxt_router_ra_release(task, ra, ra->work.data); 2680167Smax.romanov@nginx.com } 2681167Smax.romanov@nginx.com 2682167Smax.romanov@nginx.com 2683167Smax.romanov@nginx.com static void 2684167Smax.romanov@nginx.com nxt_router_process_http_request_mp(nxt_task_t *task, nxt_req_app_link_t *ra, 2685167Smax.romanov@nginx.com nxt_port_t *port) 2686167Smax.romanov@nginx.com { 2687167Smax.romanov@nginx.com nxt_int_t res; 2688167Smax.romanov@nginx.com nxt_port_t *c_port, *reply_port; 2689167Smax.romanov@nginx.com nxt_conn_t *c; 2690167Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 2691167Smax.romanov@nginx.com nxt_app_parse_ctx_t *ap; 2692167Smax.romanov@nginx.com 2693167Smax.romanov@nginx.com reply_port = ra->reply_port; 2694167Smax.romanov@nginx.com ap = ra->ap; 2695167Smax.romanov@nginx.com c = ra->rc->conn; 2696141Smax.romanov@nginx.com 2697141Smax.romanov@nginx.com c_port = nxt_process_connected_port_find(port->process, reply_port->pid, 2698141Smax.romanov@nginx.com reply_port->id); 2699141Smax.romanov@nginx.com if (nxt_slow_path(c_port != reply_port)) { 2700141Smax.romanov@nginx.com res = nxt_port_send_port(task, port, reply_port, 0); 2701122Smax.romanov@nginx.com 2702122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2703167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2704141Smax.romanov@nginx.com "Failed to send reply port to application"); 2705167Smax.romanov@nginx.com return; 2706122Smax.romanov@nginx.com } 2707122Smax.romanov@nginx.com 2708141Smax.romanov@nginx.com nxt_process_connected_port_add(port->process, reply_port); 270988Smax.romanov@nginx.com } 271088Smax.romanov@nginx.com 271188Smax.romanov@nginx.com wmsg.port = port; 271288Smax.romanov@nginx.com wmsg.write = NULL; 271388Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 2714167Smax.romanov@nginx.com wmsg.stream = ra->req_id; 2715167Smax.romanov@nginx.com 2716216Sigor@sysoev.ru res = port->app->prepare_msg(task, &ap->r, &wmsg); 2717122Smax.romanov@nginx.com 2718122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2719167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2720141Smax.romanov@nginx.com "Failed to prepare message for application"); 2721167Smax.romanov@nginx.com return; 2722122Smax.romanov@nginx.com } 272388Smax.romanov@nginx.com 272488Smax.romanov@nginx.com nxt_debug(task, "about to send %d bytes buffer to worker port %d", 272588Smax.romanov@nginx.com nxt_buf_used_size(wmsg.write), 272688Smax.romanov@nginx.com wmsg.port->socket.fd); 272788Smax.romanov@nginx.com 2728122Smax.romanov@nginx.com res = nxt_port_socket_write(task, wmsg.port, NXT_PORT_MSG_DATA, 2729167Smax.romanov@nginx.com -1, ra->req_id, reply_port->id, wmsg.write); 2730122Smax.romanov@nginx.com 2731122Smax.romanov@nginx.com if (nxt_slow_path(res != NXT_OK)) { 2732167Smax.romanov@nginx.com nxt_router_gen_error(task, c, 500, 2733141Smax.romanov@nginx.com "Failed to send message to application"); 2734167Smax.romanov@nginx.com return; 2735122Smax.romanov@nginx.com } 273653Sigor@sysoev.ru } 273753Sigor@sysoev.ru 273853Sigor@sysoev.ru 2739216Sigor@sysoev.ru static nxt_int_t 2740216Sigor@sysoev.ru nxt_python_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 2741216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg) 2742216Sigor@sysoev.ru { 2743216Sigor@sysoev.ru nxt_int_t rc; 2744216Sigor@sysoev.ru nxt_buf_t *b; 2745216Sigor@sysoev.ru nxt_http_field_t *field; 2746216Sigor@sysoev.ru nxt_app_request_header_t *h; 2747216Sigor@sysoev.ru 2748216Sigor@sysoev.ru static const nxt_str_t prefix = nxt_string("HTTP_"); 2749216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 2750216Sigor@sysoev.ru 2751216Sigor@sysoev.ru h = &r->header; 2752216Sigor@sysoev.ru 2753216Sigor@sysoev.ru #define RC(S) \ 2754216Sigor@sysoev.ru do { \ 2755216Sigor@sysoev.ru rc = (S); \ 2756216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 2757216Sigor@sysoev.ru goto fail; \ 2758216Sigor@sysoev.ru } \ 2759216Sigor@sysoev.ru } while(0) 2760216Sigor@sysoev.ru 2761216Sigor@sysoev.ru #define NXT_WRITE(N) \ 2762216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 2763216Sigor@sysoev.ru 2764216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 2765216Sigor@sysoev.ru 2766216Sigor@sysoev.ru NXT_WRITE(&h->method); 2767216Sigor@sysoev.ru NXT_WRITE(&h->target); 2768216Sigor@sysoev.ru if (h->path.start == h->target.start) { 2769216Sigor@sysoev.ru NXT_WRITE(&eof); 2770216Sigor@sysoev.ru } else { 2771216Sigor@sysoev.ru NXT_WRITE(&h->path); 2772216Sigor@sysoev.ru } 2773216Sigor@sysoev.ru 2774216Sigor@sysoev.ru if (h->query.start != NULL) { 2775216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 2776216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 2777216Sigor@sysoev.ru } else { 2778216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 2779216Sigor@sysoev.ru } 2780216Sigor@sysoev.ru 2781216Sigor@sysoev.ru NXT_WRITE(&h->version); 2782216Sigor@sysoev.ru 2783216Sigor@sysoev.ru NXT_WRITE(&r->remote); 2784216Sigor@sysoev.ru 2785216Sigor@sysoev.ru NXT_WRITE(&h->host); 2786216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 2787216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 2788216Sigor@sysoev.ru 2789216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 2790216Sigor@sysoev.ru RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, 2791216Sigor@sysoev.ru &prefix, &field->name)); 2792216Sigor@sysoev.ru NXT_WRITE(&field->value); 2793216Sigor@sysoev.ru 2794216Sigor@sysoev.ru } nxt_list_loop; 2795216Sigor@sysoev.ru 2796216Sigor@sysoev.ru /* end-of-headers mark */ 2797216Sigor@sysoev.ru NXT_WRITE(&eof); 2798216Sigor@sysoev.ru 2799216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 2800216Sigor@sysoev.ru 2801216Sigor@sysoev.ru for(b = r->body.buf; b != NULL; b = b->next) { 2802216Sigor@sysoev.ru RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 2803216Sigor@sysoev.ru nxt_buf_mem_used_size(&b->mem))); 2804216Sigor@sysoev.ru } 2805216Sigor@sysoev.ru 2806216Sigor@sysoev.ru #undef NXT_WRITE 2807216Sigor@sysoev.ru #undef RC 2808216Sigor@sysoev.ru 2809216Sigor@sysoev.ru return NXT_OK; 2810216Sigor@sysoev.ru 2811216Sigor@sysoev.ru fail: 2812216Sigor@sysoev.ru 2813216Sigor@sysoev.ru return NXT_ERROR; 2814216Sigor@sysoev.ru } 2815216Sigor@sysoev.ru 2816216Sigor@sysoev.ru 2817216Sigor@sysoev.ru static nxt_int_t 2818216Sigor@sysoev.ru nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, 2819216Sigor@sysoev.ru nxt_app_wmsg_t *wmsg) 2820216Sigor@sysoev.ru { 2821216Sigor@sysoev.ru nxt_int_t rc; 2822216Sigor@sysoev.ru nxt_buf_t *b; 2823216Sigor@sysoev.ru nxt_http_field_t *field; 2824216Sigor@sysoev.ru nxt_app_request_header_t *h; 2825216Sigor@sysoev.ru 2826216Sigor@sysoev.ru static const nxt_str_t prefix = nxt_string("HTTP_"); 2827216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 2828216Sigor@sysoev.ru 2829216Sigor@sysoev.ru h = &r->header; 2830216Sigor@sysoev.ru 2831216Sigor@sysoev.ru #define RC(S) \ 2832216Sigor@sysoev.ru do { \ 2833216Sigor@sysoev.ru rc = (S); \ 2834216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 2835216Sigor@sysoev.ru goto fail; \ 2836216Sigor@sysoev.ru } \ 2837216Sigor@sysoev.ru } while(0) 2838216Sigor@sysoev.ru 2839216Sigor@sysoev.ru #define NXT_WRITE(N) \ 2840216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 2841216Sigor@sysoev.ru 2842216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 2843216Sigor@sysoev.ru 2844216Sigor@sysoev.ru NXT_WRITE(&h->method); 2845216Sigor@sysoev.ru NXT_WRITE(&h->target); 2846216Sigor@sysoev.ru if (h->path.start == h->target.start) { 2847216Sigor@sysoev.ru NXT_WRITE(&eof); 2848216Sigor@sysoev.ru } else { 2849216Sigor@sysoev.ru NXT_WRITE(&h->path); 2850216Sigor@sysoev.ru } 2851216Sigor@sysoev.ru 2852216Sigor@sysoev.ru if (h->query.start != NULL) { 2853216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 2854216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 2855216Sigor@sysoev.ru } else { 2856216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 2857216Sigor@sysoev.ru } 2858216Sigor@sysoev.ru 2859216Sigor@sysoev.ru NXT_WRITE(&h->version); 2860216Sigor@sysoev.ru 2861216Sigor@sysoev.ru // PHP_SELF 2862216Sigor@sysoev.ru // SCRIPT_NAME 2863216Sigor@sysoev.ru // SCRIPT_FILENAME 2864216Sigor@sysoev.ru // DOCUMENT_ROOT 2865216Sigor@sysoev.ru 2866216Sigor@sysoev.ru NXT_WRITE(&r->remote); 2867216Sigor@sysoev.ru 2868216Sigor@sysoev.ru NXT_WRITE(&h->host); 2869216Sigor@sysoev.ru NXT_WRITE(&h->cookie); 2870216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 2871216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 2872216Sigor@sysoev.ru 2873216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length)); 2874216Sigor@sysoev.ru 2875216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 2876216Sigor@sysoev.ru RC(nxt_app_msg_write_prefixed_upcase(task, wmsg, 2877216Sigor@sysoev.ru &prefix, &field->name)); 2878216Sigor@sysoev.ru NXT_WRITE(&field->value); 2879216Sigor@sysoev.ru 2880216Sigor@sysoev.ru } nxt_list_loop; 2881216Sigor@sysoev.ru 2882216Sigor@sysoev.ru /* end-of-headers mark */ 2883216Sigor@sysoev.ru NXT_WRITE(&eof); 2884216Sigor@sysoev.ru 2885216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 2886216Sigor@sysoev.ru 2887216Sigor@sysoev.ru for(b = r->body.buf; b != NULL; b = b->next) { 2888216Sigor@sysoev.ru RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 2889216Sigor@sysoev.ru nxt_buf_mem_used_size(&b->mem))); 2890216Sigor@sysoev.ru } 2891216Sigor@sysoev.ru 2892216Sigor@sysoev.ru #undef NXT_WRITE 2893216Sigor@sysoev.ru #undef RC 2894216Sigor@sysoev.ru 2895216Sigor@sysoev.ru return NXT_OK; 2896216Sigor@sysoev.ru 2897216Sigor@sysoev.ru fail: 2898216Sigor@sysoev.ru 2899216Sigor@sysoev.ru return NXT_ERROR; 2900216Sigor@sysoev.ru } 2901216Sigor@sysoev.ru 2902216Sigor@sysoev.ru 2903216Sigor@sysoev.ru static nxt_int_t 2904216Sigor@sysoev.ru nxt_go_prepare_msg(nxt_task_t *task, nxt_app_request_t *r, nxt_app_wmsg_t *wmsg) 2905216Sigor@sysoev.ru { 2906216Sigor@sysoev.ru nxt_int_t rc; 2907216Sigor@sysoev.ru nxt_buf_t *b; 2908216Sigor@sysoev.ru nxt_http_field_t *field; 2909216Sigor@sysoev.ru nxt_app_request_header_t *h; 2910216Sigor@sysoev.ru 2911216Sigor@sysoev.ru static const nxt_str_t eof = nxt_null_string; 2912216Sigor@sysoev.ru 2913216Sigor@sysoev.ru h = &r->header; 2914216Sigor@sysoev.ru 2915216Sigor@sysoev.ru #define RC(S) \ 2916216Sigor@sysoev.ru do { \ 2917216Sigor@sysoev.ru rc = (S); \ 2918216Sigor@sysoev.ru if (nxt_slow_path(rc != NXT_OK)) { \ 2919216Sigor@sysoev.ru goto fail; \ 2920216Sigor@sysoev.ru } \ 2921216Sigor@sysoev.ru } while(0) 2922216Sigor@sysoev.ru 2923216Sigor@sysoev.ru #define NXT_WRITE(N) \ 2924216Sigor@sysoev.ru RC(nxt_app_msg_write_str(task, wmsg, N)) 2925216Sigor@sysoev.ru 2926216Sigor@sysoev.ru /* TODO error handle, async mmap buffer assignment */ 2927216Sigor@sysoev.ru 2928216Sigor@sysoev.ru NXT_WRITE(&h->method); 2929216Sigor@sysoev.ru NXT_WRITE(&h->target); 2930216Sigor@sysoev.ru if (h->path.start == h->target.start) { 2931216Sigor@sysoev.ru NXT_WRITE(&eof); 2932216Sigor@sysoev.ru } else { 2933216Sigor@sysoev.ru NXT_WRITE(&h->path); 2934216Sigor@sysoev.ru } 2935216Sigor@sysoev.ru 2936216Sigor@sysoev.ru if (h->query.start != NULL) { 2937216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 2938216Sigor@sysoev.ru h->query.start - h->target.start + 1)); 2939216Sigor@sysoev.ru } else { 2940216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, 0)); 2941216Sigor@sysoev.ru } 2942216Sigor@sysoev.ru 2943216Sigor@sysoev.ru NXT_WRITE(&h->version); 2944253Smax.romanov@nginx.com NXT_WRITE(&r->remote); 2945216Sigor@sysoev.ru 2946216Sigor@sysoev.ru NXT_WRITE(&h->host); 2947216Sigor@sysoev.ru NXT_WRITE(&h->cookie); 2948216Sigor@sysoev.ru NXT_WRITE(&h->content_type); 2949216Sigor@sysoev.ru NXT_WRITE(&h->content_length); 2950216Sigor@sysoev.ru 2951216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length)); 2952216Sigor@sysoev.ru 2953216Sigor@sysoev.ru nxt_list_each(field, h->fields) { 2954216Sigor@sysoev.ru NXT_WRITE(&field->name); 2955216Sigor@sysoev.ru NXT_WRITE(&field->value); 2956216Sigor@sysoev.ru 2957216Sigor@sysoev.ru } nxt_list_loop; 2958216Sigor@sysoev.ru 2959216Sigor@sysoev.ru /* end-of-headers mark */ 2960216Sigor@sysoev.ru NXT_WRITE(&eof); 2961216Sigor@sysoev.ru 2962216Sigor@sysoev.ru RC(nxt_app_msg_write_size(task, wmsg, r->body.preread_size)); 2963216Sigor@sysoev.ru 2964216Sigor@sysoev.ru for(b = r->body.buf; b != NULL; b = b->next) { 2965216Sigor@sysoev.ru RC(nxt_app_msg_write_raw(task, wmsg, b->mem.pos, 2966216Sigor@sysoev.ru nxt_buf_mem_used_size(&b->mem))); 2967216Sigor@sysoev.ru } 2968216Sigor@sysoev.ru 2969216Sigor@sysoev.ru #undef NXT_WRITE 2970216Sigor@sysoev.ru #undef RC 2971216Sigor@sysoev.ru 2972216Sigor@sysoev.ru return NXT_OK; 2973216Sigor@sysoev.ru 2974216Sigor@sysoev.ru fail: 2975216Sigor@sysoev.ru 2976216Sigor@sysoev.ru return NXT_ERROR; 2977216Sigor@sysoev.ru } 2978216Sigor@sysoev.ru 2979216Sigor@sysoev.ru 298062Sigor@sysoev.ru static const nxt_conn_state_t nxt_router_conn_close_state 298153Sigor@sysoev.ru nxt_aligned(64) = 298253Sigor@sysoev.ru { 298353Sigor@sysoev.ru .ready_handler = nxt_router_conn_free, 298453Sigor@sysoev.ru }; 298553Sigor@sysoev.ru 298653Sigor@sysoev.ru 298753Sigor@sysoev.ru static void 298888Smax.romanov@nginx.com nxt_router_conn_ready(nxt_task_t *task, void *obj, void *data) 298988Smax.romanov@nginx.com { 299088Smax.romanov@nginx.com nxt_buf_t *b; 299188Smax.romanov@nginx.com nxt_bool_t last; 299288Smax.romanov@nginx.com nxt_conn_t *c; 299388Smax.romanov@nginx.com nxt_work_queue_t *wq; 299488Smax.romanov@nginx.com 299588Smax.romanov@nginx.com nxt_debug(task, "router conn ready %p", obj); 299688Smax.romanov@nginx.com 299788Smax.romanov@nginx.com c = obj; 299888Smax.romanov@nginx.com b = c->write; 299988Smax.romanov@nginx.com 300088Smax.romanov@nginx.com wq = &task->thread->engine->fast_work_queue; 300188Smax.romanov@nginx.com 300288Smax.romanov@nginx.com last = 0; 300388Smax.romanov@nginx.com 300488Smax.romanov@nginx.com while (b != NULL) { 300588Smax.romanov@nginx.com if (!nxt_buf_is_sync(b)) { 300688Smax.romanov@nginx.com if (nxt_buf_used_size(b) > 0) { 300788Smax.romanov@nginx.com break; 300888Smax.romanov@nginx.com } 300988Smax.romanov@nginx.com } 301088Smax.romanov@nginx.com 301188Smax.romanov@nginx.com if (nxt_buf_is_last(b)) { 301288Smax.romanov@nginx.com last = 1; 301388Smax.romanov@nginx.com } 301488Smax.romanov@nginx.com 301588Smax.romanov@nginx.com nxt_work_queue_add(wq, b->completion_handler, task, b, b->parent); 301688Smax.romanov@nginx.com 301788Smax.romanov@nginx.com b = b->next; 301888Smax.romanov@nginx.com } 301988Smax.romanov@nginx.com 302088Smax.romanov@nginx.com c->write = b; 302188Smax.romanov@nginx.com 302288Smax.romanov@nginx.com if (b != NULL) { 302388Smax.romanov@nginx.com nxt_debug(task, "router conn %p has more data to write", obj); 302488Smax.romanov@nginx.com 302588Smax.romanov@nginx.com nxt_conn_write(task->thread->engine, c); 302688Smax.romanov@nginx.com } else { 302788Smax.romanov@nginx.com nxt_debug(task, "router conn %p no more data to write, last = %d", obj, 302888Smax.romanov@nginx.com last); 302988Smax.romanov@nginx.com 303088Smax.romanov@nginx.com if (last != 0) { 303188Smax.romanov@nginx.com nxt_debug(task, "enqueue router conn close %p (ready handler)", c); 303288Smax.romanov@nginx.com 303388Smax.romanov@nginx.com nxt_work_queue_add(wq, nxt_router_conn_close, task, c, 303488Smax.romanov@nginx.com c->socket.data); 303588Smax.romanov@nginx.com } 303688Smax.romanov@nginx.com } 303788Smax.romanov@nginx.com } 303888Smax.romanov@nginx.com 303988Smax.romanov@nginx.com 304088Smax.romanov@nginx.com static void 304153Sigor@sysoev.ru nxt_router_conn_close(nxt_task_t *task, void *obj, void *data) 304253Sigor@sysoev.ru { 304362Sigor@sysoev.ru nxt_conn_t *c; 304453Sigor@sysoev.ru 304553Sigor@sysoev.ru c = obj; 304653Sigor@sysoev.ru 304753Sigor@sysoev.ru nxt_debug(task, "router conn close"); 304853Sigor@sysoev.ru 304953Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 305053Sigor@sysoev.ru 305162Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 305253Sigor@sysoev.ru } 305353Sigor@sysoev.ru 305453Sigor@sysoev.ru 305553Sigor@sysoev.ru static void 3056164Smax.romanov@nginx.com nxt_router_conn_mp_cleanup(nxt_task_t *task, void *obj, void *data) 3057164Smax.romanov@nginx.com { 3058164Smax.romanov@nginx.com nxt_socket_conf_joint_t *joint; 3059164Smax.romanov@nginx.com 3060164Smax.romanov@nginx.com joint = obj; 3061164Smax.romanov@nginx.com 3062164Smax.romanov@nginx.com nxt_router_conf_release(task, joint); 3063164Smax.romanov@nginx.com } 3064164Smax.romanov@nginx.com 3065164Smax.romanov@nginx.com 3066164Smax.romanov@nginx.com static void 306753Sigor@sysoev.ru nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) 306853Sigor@sysoev.ru { 306962Sigor@sysoev.ru nxt_conn_t *c; 307088Smax.romanov@nginx.com nxt_req_conn_link_t *rc; 307153Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 307253Sigor@sysoev.ru 307353Sigor@sysoev.ru c = obj; 307453Sigor@sysoev.ru 307553Sigor@sysoev.ru nxt_debug(task, "router conn close done"); 307653Sigor@sysoev.ru 307788Smax.romanov@nginx.com nxt_queue_each(rc, &c->requests, nxt_req_conn_link_t, link) { 307888Smax.romanov@nginx.com 307988Smax.romanov@nginx.com nxt_debug(task, "conn %p close, req %uxD", c, rc->req_id); 308088Smax.romanov@nginx.com 3081141Smax.romanov@nginx.com if (rc->app_port != NULL) { 3082141Smax.romanov@nginx.com nxt_router_app_release_port(task, rc->app_port, rc->app_port->app); 3083141Smax.romanov@nginx.com 3084141Smax.romanov@nginx.com rc->app_port = NULL; 3085141Smax.romanov@nginx.com } 3086141Smax.romanov@nginx.com 3087167Smax.romanov@nginx.com rc->conn = NULL; 3088167Smax.romanov@nginx.com 308988Smax.romanov@nginx.com nxt_event_engine_request_remove(task->thread->engine, rc); 309088Smax.romanov@nginx.com 309188Smax.romanov@nginx.com } nxt_queue_loop; 309288Smax.romanov@nginx.com 3093122Smax.romanov@nginx.com nxt_queue_remove(&c->link); 3094122Smax.romanov@nginx.com 3095131Smax.romanov@nginx.com joint = c->listen->socket.data; 3096131Smax.romanov@nginx.com 3097131Smax.romanov@nginx.com task = &task->thread->engine->task; 3098131Smax.romanov@nginx.com 3099164Smax.romanov@nginx.com nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup, task, joint, NULL); 3100164Smax.romanov@nginx.com 3101164Smax.romanov@nginx.com nxt_mp_release(c->mem_pool, c); 310253Sigor@sysoev.ru } 310353Sigor@sysoev.ru 310453Sigor@sysoev.ru 310553Sigor@sysoev.ru static void 310653Sigor@sysoev.ru nxt_router_conn_error(nxt_task_t *task, void *obj, void *data) 310753Sigor@sysoev.ru { 310862Sigor@sysoev.ru nxt_conn_t *c; 310953Sigor@sysoev.ru 311053Sigor@sysoev.ru c = obj; 311153Sigor@sysoev.ru 311253Sigor@sysoev.ru nxt_debug(task, "router conn error"); 311353Sigor@sysoev.ru 311453Sigor@sysoev.ru c->write_state = &nxt_router_conn_close_state; 311553Sigor@sysoev.ru 311662Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 311753Sigor@sysoev.ru } 311853Sigor@sysoev.ru 311953Sigor@sysoev.ru 312053Sigor@sysoev.ru static void 312153Sigor@sysoev.ru nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) 312253Sigor@sysoev.ru { 312362Sigor@sysoev.ru nxt_conn_t *c; 312462Sigor@sysoev.ru nxt_timer_t *timer; 312553Sigor@sysoev.ru 312653Sigor@sysoev.ru timer = obj; 312753Sigor@sysoev.ru 312853Sigor@sysoev.ru nxt_debug(task, "router conn timeout"); 312953Sigor@sysoev.ru 313062Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 313153Sigor@sysoev.ru 3132206Smax.romanov@nginx.com if (c->read_state == &nxt_router_conn_read_header_state) { 3133206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 408, "Read header timeout"); 3134206Smax.romanov@nginx.com 3135206Smax.romanov@nginx.com } else { 3136206Smax.romanov@nginx.com nxt_router_gen_error(task, c, 408, "Read body timeout"); 3137206Smax.romanov@nginx.com } 313853Sigor@sysoev.ru } 313953Sigor@sysoev.ru 314053Sigor@sysoev.ru 314153Sigor@sysoev.ru static nxt_msec_t 314262Sigor@sysoev.ru nxt_router_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 314353Sigor@sysoev.ru { 314453Sigor@sysoev.ru nxt_socket_conf_joint_t *joint; 314553Sigor@sysoev.ru 314653Sigor@sysoev.ru joint = c->listen->socket.data; 314753Sigor@sysoev.ru 314853Sigor@sysoev.ru return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 314953Sigor@sysoev.ru } 3150