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 820Sigor@sysoev.ru #include <nxt_main.h> 920Sigor@sysoev.ru #include <nxt_runtime.h> 10240Sigor@sysoev.ru #include <nxt_main_process.h> 1129Svbart@nginx.com #include <nxt_conf.h> 12774Svbart@nginx.com #include <nxt_cert.h> 1320Sigor@sysoev.ru 1420Sigor@sysoev.ru 1527Svbart@nginx.com typedef struct { 16106Svbart@nginx.com nxt_conf_value_t *root; 17106Svbart@nginx.com nxt_mp_t *pool; 1844Svbart@nginx.com } nxt_controller_conf_t; 1944Svbart@nginx.com 2044Svbart@nginx.com 2144Svbart@nginx.com typedef struct { 2227Svbart@nginx.com nxt_http_request_parse_t parser; 2327Svbart@nginx.com size_t length; 2444Svbart@nginx.com nxt_controller_conf_t conf; 25140Svbart@nginx.com nxt_conn_t *conn; 26140Svbart@nginx.com nxt_queue_link_t link; 2727Svbart@nginx.com } nxt_controller_request_t; 2827Svbart@nginx.com 2927Svbart@nginx.com 3044Svbart@nginx.com typedef struct { 31208Svbart@nginx.com nxt_uint_t status; 32106Svbart@nginx.com nxt_conf_value_t *conf; 33208Svbart@nginx.com 34208Svbart@nginx.com u_char *title; 35357Svbart@nginx.com nxt_str_t detail; 36208Svbart@nginx.com ssize_t offset; 37208Svbart@nginx.com nxt_uint_t line; 38208Svbart@nginx.com nxt_uint_t column; 3944Svbart@nginx.com } nxt_controller_response_t; 4044Svbart@nginx.com 4144Svbart@nginx.com 42248Svbart@nginx.com static void nxt_controller_process_new_port_handler(nxt_task_t *task, 43248Svbart@nginx.com nxt_port_recv_msg_t *msg); 44662Smax.romanov@nginx.com static void nxt_controller_send_current_conf(nxt_task_t *task); 45662Smax.romanov@nginx.com static void nxt_controller_router_ready_handler(nxt_task_t *task, 46662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg); 47249Svbart@nginx.com static nxt_int_t nxt_controller_conf_default(void); 48249Svbart@nginx.com static void nxt_controller_conf_init_handler(nxt_task_t *task, 49249Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 50249Svbart@nginx.com static nxt_int_t nxt_controller_conf_send(nxt_task_t *task, 51249Svbart@nginx.com nxt_conf_value_t *conf, nxt_port_rpc_handler_t handler, void *data); 52248Svbart@nginx.com 5320Sigor@sysoev.ru static void nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data); 5420Sigor@sysoev.ru static void nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data); 5562Sigor@sysoev.ru static nxt_msec_t nxt_controller_conn_timeout_value(nxt_conn_t *c, 5620Sigor@sysoev.ru uintptr_t data); 5720Sigor@sysoev.ru static void nxt_controller_conn_read_error(nxt_task_t *task, void *obj, 5820Sigor@sysoev.ru void *data); 5920Sigor@sysoev.ru static void nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, 6020Sigor@sysoev.ru void *data); 6127Svbart@nginx.com static void nxt_controller_conn_body_read(nxt_task_t *task, void *obj, 6227Svbart@nginx.com void *data); 6327Svbart@nginx.com static void nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data); 6427Svbart@nginx.com static void nxt_controller_conn_write_error(nxt_task_t *task, void *obj, 6527Svbart@nginx.com void *data); 6627Svbart@nginx.com static void nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, 6727Svbart@nginx.com void *data); 6820Sigor@sysoev.ru static void nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data); 6920Sigor@sysoev.ru static void nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data); 7020Sigor@sysoev.ru 7127Svbart@nginx.com static nxt_int_t nxt_controller_request_content_length(void *ctx, 72417Svbart@nginx.com nxt_http_field_t *field, uintptr_t data); 7327Svbart@nginx.com 7427Svbart@nginx.com static void nxt_controller_process_request(nxt_task_t *task, 75140Svbart@nginx.com nxt_controller_request_t *req); 76774Svbart@nginx.com static void nxt_controller_process_config(nxt_task_t *task, 77774Svbart@nginx.com nxt_controller_request_t *req, nxt_str_t *path); 78774Svbart@nginx.com #if (NXT_TLS) 79774Svbart@nginx.com static void nxt_controller_process_cert(nxt_task_t *task, 80774Svbart@nginx.com nxt_controller_request_t *req, nxt_str_t *path); 81774Svbart@nginx.com static void nxt_controller_process_cert_save(nxt_task_t *task, 82774Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 83774Svbart@nginx.com static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name); 84774Svbart@nginx.com #endif 85238Svbart@nginx.com static void nxt_controller_conf_handler(nxt_task_t *task, 86238Svbart@nginx.com nxt_port_recv_msg_t *msg, void *data); 87314Svbart@nginx.com static void nxt_controller_conf_store(nxt_task_t *task, 88314Svbart@nginx.com nxt_conf_value_t *conf); 89140Svbart@nginx.com static void nxt_controller_response(nxt_task_t *task, 90140Svbart@nginx.com nxt_controller_request_t *req, nxt_controller_response_t *resp); 91208Svbart@nginx.com static u_char *nxt_controller_date(u_char *buf, nxt_realtime_t *now, 92208Svbart@nginx.com struct tm *tm, size_t size, const char *format); 9327Svbart@nginx.com 9427Svbart@nginx.com 95417Svbart@nginx.com static nxt_http_field_proc_t nxt_controller_request_fields[] = { 9627Svbart@nginx.com { nxt_string("Content-Length"), 9727Svbart@nginx.com &nxt_controller_request_content_length, 0 }, 9827Svbart@nginx.com }; 9927Svbart@nginx.com 100417Svbart@nginx.com static nxt_lvlhsh_t nxt_controller_fields_hash; 10127Svbart@nginx.com 102314Svbart@nginx.com static nxt_uint_t nxt_controller_listening; 103662Smax.romanov@nginx.com static nxt_uint_t nxt_controller_router_ready; 104238Svbart@nginx.com static nxt_controller_conf_t nxt_controller_conf; 105238Svbart@nginx.com static nxt_queue_t nxt_controller_waiting_requests; 10627Svbart@nginx.com 10720Sigor@sysoev.ru 10820Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state; 10927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state; 11027Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state; 11120Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state; 11220Sigor@sysoev.ru 11320Sigor@sysoev.ru 114320Smax.romanov@nginx.com nxt_port_handlers_t nxt_controller_process_port_handlers = { 115662Smax.romanov@nginx.com .quit = nxt_worker_process_quit_handler, 116662Smax.romanov@nginx.com .new_port = nxt_controller_process_new_port_handler, 117662Smax.romanov@nginx.com .change_file = nxt_port_change_log_file_handler, 118662Smax.romanov@nginx.com .mmap = nxt_port_mmap_handler, 119662Smax.romanov@nginx.com .process_ready = nxt_controller_router_ready_handler, 120662Smax.romanov@nginx.com .data = nxt_port_data_handler, 121662Smax.romanov@nginx.com .remove_pid = nxt_port_remove_pid_handler, 122662Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 123662Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 124248Svbart@nginx.com }; 125248Svbart@nginx.com 126248Svbart@nginx.com 12720Sigor@sysoev.ru nxt_int_t 128141Smax.romanov@nginx.com nxt_controller_start(nxt_task_t *task, void *data) 12920Sigor@sysoev.ru { 130417Svbart@nginx.com nxt_mp_t *mp; 131417Svbart@nginx.com nxt_int_t ret; 132417Svbart@nginx.com nxt_str_t *json; 133417Svbart@nginx.com nxt_conf_value_t *conf; 134417Svbart@nginx.com nxt_conf_validation_t vldt; 135774Svbart@nginx.com nxt_controller_init_t *init; 13627Svbart@nginx.com 137*1459Smax.romanov@nginx.com ret = nxt_http_fields_hash(&nxt_controller_fields_hash, 138417Svbart@nginx.com nxt_controller_request_fields, 139417Svbart@nginx.com nxt_nitems(nxt_controller_request_fields)); 140417Svbart@nginx.com 141417Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14227Svbart@nginx.com return NXT_ERROR; 14327Svbart@nginx.com } 14427Svbart@nginx.com 145248Svbart@nginx.com nxt_queue_init(&nxt_controller_waiting_requests); 14627Svbart@nginx.com 147774Svbart@nginx.com init = data; 148774Svbart@nginx.com 149774Svbart@nginx.com #if (NXT_TLS) 150314Svbart@nginx.com 151774Svbart@nginx.com if (init->certs != NULL) { 152774Svbart@nginx.com nxt_cert_info_init(task, init->certs); 153774Svbart@nginx.com nxt_cert_store_release(init->certs); 154774Svbart@nginx.com } 155774Svbart@nginx.com 156774Svbart@nginx.com #endif 157774Svbart@nginx.com 158774Svbart@nginx.com json = &init->conf; 159774Svbart@nginx.com 160774Svbart@nginx.com if (json->start == NULL) { 161314Svbart@nginx.com return NXT_OK; 162314Svbart@nginx.com } 163314Svbart@nginx.com 164314Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 165314Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 166314Svbart@nginx.com return NXT_ERROR; 167314Svbart@nginx.com } 168314Svbart@nginx.com 169314Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, json); 170314Svbart@nginx.com nxt_free(json->start); 171314Svbart@nginx.com 172314Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 173564Svbart@nginx.com nxt_alert(task, "failed to restore previous configuration: " 174564Svbart@nginx.com "file is corrupted or not enough memory"); 175314Svbart@nginx.com 176314Svbart@nginx.com nxt_mp_destroy(mp); 177314Svbart@nginx.com return NXT_OK; 178314Svbart@nginx.com } 179314Svbart@nginx.com 180357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 181314Svbart@nginx.com 182357Svbart@nginx.com vldt.pool = nxt_mp_create(1024, 128, 256, 32); 183357Svbart@nginx.com if (nxt_slow_path(vldt.pool == NULL)) { 1841013Smax.romanov@nginx.com nxt_mp_destroy(mp); 185357Svbart@nginx.com return NXT_ERROR; 186314Svbart@nginx.com } 187314Svbart@nginx.com 188357Svbart@nginx.com vldt.conf = conf; 189357Svbart@nginx.com 190357Svbart@nginx.com ret = nxt_conf_validate(&vldt); 191357Svbart@nginx.com 192357Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 193357Svbart@nginx.com 194357Svbart@nginx.com if (ret == NXT_DECLINED) { 195564Svbart@nginx.com nxt_alert(task, "the previous configuration is invalid: %V", 196564Svbart@nginx.com &vldt.error); 197357Svbart@nginx.com 198357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 199357Svbart@nginx.com nxt_mp_destroy(mp); 200357Svbart@nginx.com 201357Svbart@nginx.com return NXT_OK; 202357Svbart@nginx.com } 203357Svbart@nginx.com 204357Svbart@nginx.com /* ret == NXT_ERROR */ 205357Svbart@nginx.com 206357Svbart@nginx.com return NXT_ERROR; 207357Svbart@nginx.com } 208357Svbart@nginx.com 209357Svbart@nginx.com nxt_mp_destroy(vldt.pool); 210314Svbart@nginx.com 211314Svbart@nginx.com nxt_controller_conf.root = conf; 212314Svbart@nginx.com nxt_controller_conf.pool = mp; 213314Svbart@nginx.com 214248Svbart@nginx.com return NXT_OK; 215248Svbart@nginx.com } 216248Svbart@nginx.com 217248Svbart@nginx.com 218248Svbart@nginx.com static void 219248Svbart@nginx.com nxt_controller_process_new_port_handler(nxt_task_t *task, 220248Svbart@nginx.com nxt_port_recv_msg_t *msg) 221248Svbart@nginx.com { 222662Smax.romanov@nginx.com nxt_port_new_port_handler(task, msg); 223662Smax.romanov@nginx.com 224662Smax.romanov@nginx.com if (msg->u.new_port->type != NXT_PROCESS_ROUTER 225662Smax.romanov@nginx.com || !nxt_controller_router_ready) 226662Smax.romanov@nginx.com { 227662Smax.romanov@nginx.com return; 228662Smax.romanov@nginx.com } 229662Smax.romanov@nginx.com 230662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 231662Smax.romanov@nginx.com } 232662Smax.romanov@nginx.com 233662Smax.romanov@nginx.com 234662Smax.romanov@nginx.com static void 235662Smax.romanov@nginx.com nxt_controller_send_current_conf(nxt_task_t *task) 236662Smax.romanov@nginx.com { 237249Svbart@nginx.com nxt_int_t rc; 238248Svbart@nginx.com nxt_runtime_t *rt; 239248Svbart@nginx.com nxt_conf_value_t *conf; 240248Svbart@nginx.com 241249Svbart@nginx.com conf = nxt_controller_conf.root; 242249Svbart@nginx.com 243249Svbart@nginx.com if (conf != NULL) { 244249Svbart@nginx.com rc = nxt_controller_conf_send(task, conf, 245249Svbart@nginx.com nxt_controller_conf_init_handler, NULL); 24644Svbart@nginx.com 247249Svbart@nginx.com if (nxt_fast_path(rc == NXT_OK)) { 248249Svbart@nginx.com return; 249249Svbart@nginx.com } 250249Svbart@nginx.com 251249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 252249Svbart@nginx.com 253249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 254249Svbart@nginx.com nxt_abort(); 255249Svbart@nginx.com } 25644Svbart@nginx.com } 25744Svbart@nginx.com 258249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 259248Svbart@nginx.com nxt_abort(); 26044Svbart@nginx.com } 26144Svbart@nginx.com 262248Svbart@nginx.com rt = task->thread->runtime; 263140Svbart@nginx.com 264248Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) == NULL)) { 265248Svbart@nginx.com nxt_abort(); 266248Svbart@nginx.com } 267314Svbart@nginx.com 268314Svbart@nginx.com nxt_controller_listening = 1; 26920Sigor@sysoev.ru } 27020Sigor@sysoev.ru 27120Sigor@sysoev.ru 272662Smax.romanov@nginx.com static void 273662Smax.romanov@nginx.com nxt_controller_router_ready_handler(nxt_task_t *task, 274662Smax.romanov@nginx.com nxt_port_recv_msg_t *msg) 275662Smax.romanov@nginx.com { 276662Smax.romanov@nginx.com nxt_port_t *router_port; 277662Smax.romanov@nginx.com nxt_runtime_t *rt; 278662Smax.romanov@nginx.com 279662Smax.romanov@nginx.com rt = task->thread->runtime; 280662Smax.romanov@nginx.com 281662Smax.romanov@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 282662Smax.romanov@nginx.com 283662Smax.romanov@nginx.com nxt_controller_router_ready = 1; 284662Smax.romanov@nginx.com 285662Smax.romanov@nginx.com if (router_port != NULL) { 286662Smax.romanov@nginx.com nxt_controller_send_current_conf(task); 287662Smax.romanov@nginx.com } 288662Smax.romanov@nginx.com } 289662Smax.romanov@nginx.com 290662Smax.romanov@nginx.com 291249Svbart@nginx.com static nxt_int_t 292249Svbart@nginx.com nxt_controller_conf_default(void) 293249Svbart@nginx.com { 294249Svbart@nginx.com nxt_mp_t *mp; 295249Svbart@nginx.com nxt_conf_value_t *conf; 296249Svbart@nginx.com 297249Svbart@nginx.com static const nxt_str_t json 298249Svbart@nginx.com = nxt_string("{ \"listeners\": {}, \"applications\": {} }"); 299249Svbart@nginx.com 300249Svbart@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 301249Svbart@nginx.com 302249Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 303249Svbart@nginx.com return NXT_ERROR; 304249Svbart@nginx.com } 305249Svbart@nginx.com 306249Svbart@nginx.com conf = nxt_conf_json_parse_str(mp, &json); 307249Svbart@nginx.com 308249Svbart@nginx.com if (nxt_slow_path(conf == NULL)) { 309249Svbart@nginx.com return NXT_ERROR; 310249Svbart@nginx.com } 311249Svbart@nginx.com 312249Svbart@nginx.com nxt_controller_conf.root = conf; 313249Svbart@nginx.com nxt_controller_conf.pool = mp; 314249Svbart@nginx.com 315249Svbart@nginx.com return NXT_OK; 316249Svbart@nginx.com } 317249Svbart@nginx.com 318249Svbart@nginx.com 319249Svbart@nginx.com static void 320249Svbart@nginx.com nxt_controller_conf_init_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, 321249Svbart@nginx.com void *data) 322249Svbart@nginx.com { 323314Svbart@nginx.com nxt_runtime_t *rt; 324314Svbart@nginx.com 325249Svbart@nginx.com if (msg->port_msg.type != NXT_PORT_MSG_RPC_READY) { 326564Svbart@nginx.com nxt_alert(task, "failed to apply previous configuration"); 327314Svbart@nginx.com 328249Svbart@nginx.com nxt_mp_destroy(nxt_controller_conf.pool); 329249Svbart@nginx.com 330249Svbart@nginx.com if (nxt_slow_path(nxt_controller_conf_default() != NXT_OK)) { 331249Svbart@nginx.com nxt_abort(); 332249Svbart@nginx.com } 333249Svbart@nginx.com } 334314Svbart@nginx.com 335314Svbart@nginx.com if (nxt_controller_listening == 0) { 336314Svbart@nginx.com rt = task->thread->runtime; 337314Svbart@nginx.com 338314Svbart@nginx.com if (nxt_slow_path(nxt_listen_event(task, rt->controller_socket) 339314Svbart@nginx.com == NULL)) 340314Svbart@nginx.com { 341314Svbart@nginx.com nxt_abort(); 342314Svbart@nginx.com } 343314Svbart@nginx.com 344314Svbart@nginx.com nxt_controller_listening = 1; 345314Svbart@nginx.com } 346249Svbart@nginx.com } 347249Svbart@nginx.com 348249Svbart@nginx.com 349249Svbart@nginx.com static nxt_int_t 350249Svbart@nginx.com nxt_controller_conf_send(nxt_task_t *task, nxt_conf_value_t *conf, 351249Svbart@nginx.com nxt_port_rpc_handler_t handler, void *data) 352249Svbart@nginx.com { 353249Svbart@nginx.com size_t size; 354249Svbart@nginx.com uint32_t stream; 355249Svbart@nginx.com nxt_int_t rc; 356249Svbart@nginx.com nxt_buf_t *b; 357249Svbart@nginx.com nxt_port_t *router_port, *controller_port; 358249Svbart@nginx.com nxt_runtime_t *rt; 359249Svbart@nginx.com 360249Svbart@nginx.com rt = task->thread->runtime; 361249Svbart@nginx.com 362249Svbart@nginx.com router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; 363249Svbart@nginx.com 364662Smax.romanov@nginx.com if (nxt_slow_path(router_port == NULL || !nxt_controller_router_ready)) { 365249Svbart@nginx.com return NXT_DECLINED; 366249Svbart@nginx.com } 367249Svbart@nginx.com 368249Svbart@nginx.com controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; 369249Svbart@nginx.com 370249Svbart@nginx.com size = nxt_conf_json_length(conf, NULL); 371249Svbart@nginx.com 372249Svbart@nginx.com b = nxt_port_mmap_get_buf(task, router_port, size); 373379Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 374379Smax.romanov@nginx.com return NXT_ERROR; 375379Smax.romanov@nginx.com } 376249Svbart@nginx.com 377249Svbart@nginx.com b->mem.free = nxt_conf_json_print(b->mem.free, conf, NULL); 378249Svbart@nginx.com 379249Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, controller_port, 380249Svbart@nginx.com handler, handler, 381249Svbart@nginx.com router_port->pid, data); 382249Svbart@nginx.com 383645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 384645Svbart@nginx.com return NXT_ERROR; 385645Svbart@nginx.com } 386645Svbart@nginx.com 387249Svbart@nginx.com rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_DATA_LAST, -1, 388249Svbart@nginx.com stream, controller_port->id, b); 389249Svbart@nginx.com 390249Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 391249Svbart@nginx.com nxt_port_rpc_cancel(task, controller_port, stream); 392249Svbart@nginx.com return NXT_ERROR; 393249Svbart@nginx.com } 394249Svbart@nginx.com 395249Svbart@nginx.com return NXT_OK; 396249Svbart@nginx.com } 397249Svbart@nginx.com 398249Svbart@nginx.com 39920Sigor@sysoev.ru nxt_int_t 40020Sigor@sysoev.ru nxt_runtime_controller_socket(nxt_task_t *task, nxt_runtime_t *rt) 40120Sigor@sysoev.ru { 40220Sigor@sysoev.ru nxt_listen_socket_t *ls; 40320Sigor@sysoev.ru 40465Sigor@sysoev.ru ls = nxt_mp_alloc(rt->mem_pool, sizeof(nxt_listen_socket_t)); 40520Sigor@sysoev.ru if (ls == NULL) { 40620Sigor@sysoev.ru return NXT_ERROR; 40720Sigor@sysoev.ru } 40820Sigor@sysoev.ru 4091448Svbart@nginx.com ls->sockaddr = rt->controller_listen; 41020Sigor@sysoev.ru 411359Sigor@sysoev.ru nxt_listen_socket_remote_size(ls); 41220Sigor@sysoev.ru 41320Sigor@sysoev.ru ls->socket = -1; 41420Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 41520Sigor@sysoev.ru ls->read_after_accept = 1; 41620Sigor@sysoev.ru ls->flags = NXT_NONBLOCK; 41720Sigor@sysoev.ru 41820Sigor@sysoev.ru #if 0 41920Sigor@sysoev.ru /* STUB */ 42065Sigor@sysoev.ru wq = nxt_mp_zget(cf->mem_pool, sizeof(nxt_work_queue_t)); 42120Sigor@sysoev.ru if (wq == NULL) { 42220Sigor@sysoev.ru return NXT_ERROR; 42320Sigor@sysoev.ru } 42420Sigor@sysoev.ru nxt_work_queue_name(wq, "listen"); 42520Sigor@sysoev.ru /**/ 42620Sigor@sysoev.ru 42720Sigor@sysoev.ru ls->work_queue = wq; 42820Sigor@sysoev.ru #endif 42920Sigor@sysoev.ru ls->handler = nxt_controller_conn_init; 43020Sigor@sysoev.ru 4311451Svbart@nginx.com if (nxt_listen_socket_create(task, rt->mem_pool, ls) != NXT_OK) { 43220Sigor@sysoev.ru return NXT_ERROR; 43320Sigor@sysoev.ru } 43420Sigor@sysoev.ru 43520Sigor@sysoev.ru rt->controller_socket = ls; 43620Sigor@sysoev.ru 43720Sigor@sysoev.ru return NXT_OK; 43820Sigor@sysoev.ru } 43920Sigor@sysoev.ru 44020Sigor@sysoev.ru 44120Sigor@sysoev.ru static void 44220Sigor@sysoev.ru nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) 44320Sigor@sysoev.ru { 44427Svbart@nginx.com nxt_buf_t *b; 44562Sigor@sysoev.ru nxt_conn_t *c; 44627Svbart@nginx.com nxt_event_engine_t *engine; 44727Svbart@nginx.com nxt_controller_request_t *r; 44820Sigor@sysoev.ru 44920Sigor@sysoev.ru c = obj; 45020Sigor@sysoev.ru 45120Sigor@sysoev.ru nxt_debug(task, "controller conn init fd:%d", c->socket.fd); 45220Sigor@sysoev.ru 45365Sigor@sysoev.ru r = nxt_mp_zget(c->mem_pool, sizeof(nxt_controller_request_t)); 45427Svbart@nginx.com if (nxt_slow_path(r == NULL)) { 45527Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 45627Svbart@nginx.com return; 45727Svbart@nginx.com } 45827Svbart@nginx.com 459140Svbart@nginx.com r->conn = c; 460140Svbart@nginx.com 46160Svbart@nginx.com if (nxt_slow_path(nxt_http_parse_request_init(&r->parser, c->mem_pool) 46260Svbart@nginx.com != NXT_OK)) 46360Svbart@nginx.com { 46460Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 46560Svbart@nginx.com return; 46660Svbart@nginx.com } 46727Svbart@nginx.com 4681167Svbart@nginx.com r->parser.encoded_slashes = 1; 4691167Svbart@nginx.com 47020Sigor@sysoev.ru b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); 47120Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 47220Sigor@sysoev.ru nxt_controller_conn_free(task, c, NULL); 47320Sigor@sysoev.ru return; 47420Sigor@sysoev.ru } 47520Sigor@sysoev.ru 47620Sigor@sysoev.ru c->read = b; 47727Svbart@nginx.com c->socket.data = r; 47820Sigor@sysoev.ru c->socket.read_ready = 1; 47920Sigor@sysoev.ru c->read_state = &nxt_controller_conn_read_state; 48020Sigor@sysoev.ru 48120Sigor@sysoev.ru engine = task->thread->engine; 48220Sigor@sysoev.ru c->read_work_queue = &engine->read_work_queue; 48327Svbart@nginx.com c->write_work_queue = &engine->write_work_queue; 48420Sigor@sysoev.ru 48562Sigor@sysoev.ru nxt_conn_read(engine, c); 48620Sigor@sysoev.ru } 48720Sigor@sysoev.ru 48820Sigor@sysoev.ru 48920Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_read_state 49020Sigor@sysoev.ru nxt_aligned(64) = 49120Sigor@sysoev.ru { 49256Sigor@sysoev.ru .ready_handler = nxt_controller_conn_read, 49356Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 49456Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 49520Sigor@sysoev.ru 49656Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 49756Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 49856Sigor@sysoev.ru .timer_data = 60 * 1000, 49920Sigor@sysoev.ru }; 50020Sigor@sysoev.ru 50120Sigor@sysoev.ru 50220Sigor@sysoev.ru static void 50320Sigor@sysoev.ru nxt_controller_conn_read(nxt_task_t *task, void *obj, void *data) 50420Sigor@sysoev.ru { 50527Svbart@nginx.com size_t preread; 50627Svbart@nginx.com nxt_buf_t *b; 50727Svbart@nginx.com nxt_int_t rc; 50862Sigor@sysoev.ru nxt_conn_t *c; 50927Svbart@nginx.com nxt_controller_request_t *r; 51020Sigor@sysoev.ru 51120Sigor@sysoev.ru c = obj; 51227Svbart@nginx.com r = data; 51320Sigor@sysoev.ru 51420Sigor@sysoev.ru nxt_debug(task, "controller conn read"); 51520Sigor@sysoev.ru 51627Svbart@nginx.com nxt_queue_remove(&c->link); 51727Svbart@nginx.com nxt_queue_self(&c->link); 51827Svbart@nginx.com 51927Svbart@nginx.com b = c->read; 52027Svbart@nginx.com 52127Svbart@nginx.com rc = nxt_http_parse_request(&r->parser, &b->mem); 52227Svbart@nginx.com 52327Svbart@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 52427Svbart@nginx.com 52527Svbart@nginx.com if (rc == NXT_AGAIN) { 52627Svbart@nginx.com if (nxt_buf_mem_free_size(&b->mem) == 0) { 52727Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "too long request headers"); 52827Svbart@nginx.com nxt_controller_conn_close(task, c, r); 52927Svbart@nginx.com return; 53027Svbart@nginx.com } 53127Svbart@nginx.com 53262Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 53327Svbart@nginx.com return; 53427Svbart@nginx.com } 53527Svbart@nginx.com 53627Svbart@nginx.com /* rc == NXT_ERROR */ 53727Svbart@nginx.com 53827Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "parsing error"); 53927Svbart@nginx.com 54027Svbart@nginx.com nxt_controller_conn_close(task, c, r); 54127Svbart@nginx.com return; 54227Svbart@nginx.com } 54327Svbart@nginx.com 544417Svbart@nginx.com rc = nxt_http_fields_process(r->parser.fields, &nxt_controller_fields_hash, 545417Svbart@nginx.com r); 54660Svbart@nginx.com 54760Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 54860Svbart@nginx.com nxt_controller_conn_close(task, c, r); 54960Svbart@nginx.com return; 55060Svbart@nginx.com } 55160Svbart@nginx.com 55227Svbart@nginx.com preread = nxt_buf_mem_used_size(&b->mem); 55327Svbart@nginx.com 55427Svbart@nginx.com nxt_debug(task, "controller request header parsing complete, " 555107Svbart@nginx.com "body length: %uz, preread: %uz", 55627Svbart@nginx.com r->length, preread); 55727Svbart@nginx.com 55827Svbart@nginx.com if (preread >= r->length) { 559140Svbart@nginx.com nxt_controller_process_request(task, r); 56027Svbart@nginx.com return; 56127Svbart@nginx.com } 56227Svbart@nginx.com 56327Svbart@nginx.com if (r->length - preread > (size_t) nxt_buf_mem_free_size(&b->mem)) { 56427Svbart@nginx.com b = nxt_buf_mem_alloc(c->mem_pool, r->length, 0); 56527Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 56627Svbart@nginx.com nxt_controller_conn_free(task, c, NULL); 56727Svbart@nginx.com return; 56827Svbart@nginx.com } 56927Svbart@nginx.com 57027Svbart@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c->read->mem.pos, preread); 57127Svbart@nginx.com 57227Svbart@nginx.com c->read = b; 57327Svbart@nginx.com } 57427Svbart@nginx.com 57527Svbart@nginx.com c->read_state = &nxt_controller_conn_body_read_state; 57627Svbart@nginx.com 57762Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 57820Sigor@sysoev.ru } 57920Sigor@sysoev.ru 58020Sigor@sysoev.ru 58120Sigor@sysoev.ru static nxt_msec_t 58262Sigor@sysoev.ru nxt_controller_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 58320Sigor@sysoev.ru { 58420Sigor@sysoev.ru return (nxt_msec_t) data; 58520Sigor@sysoev.ru } 58620Sigor@sysoev.ru 58720Sigor@sysoev.ru 58820Sigor@sysoev.ru static void 58920Sigor@sysoev.ru nxt_controller_conn_read_error(nxt_task_t *task, void *obj, void *data) 59020Sigor@sysoev.ru { 59162Sigor@sysoev.ru nxt_conn_t *c; 59220Sigor@sysoev.ru 59320Sigor@sysoev.ru c = obj; 59420Sigor@sysoev.ru 59520Sigor@sysoev.ru nxt_debug(task, "controller conn read error"); 59620Sigor@sysoev.ru 59727Svbart@nginx.com nxt_controller_conn_close(task, c, data); 59820Sigor@sysoev.ru } 59920Sigor@sysoev.ru 60020Sigor@sysoev.ru 60120Sigor@sysoev.ru static void 60220Sigor@sysoev.ru nxt_controller_conn_read_timeout(nxt_task_t *task, void *obj, void *data) 60320Sigor@sysoev.ru { 60462Sigor@sysoev.ru nxt_timer_t *timer; 60562Sigor@sysoev.ru nxt_conn_t *c; 60620Sigor@sysoev.ru 60762Sigor@sysoev.ru timer = obj; 60820Sigor@sysoev.ru 60962Sigor@sysoev.ru c = nxt_read_timer_conn(timer); 61020Sigor@sysoev.ru c->socket.timedout = 1; 61120Sigor@sysoev.ru c->socket.closed = 1; 61220Sigor@sysoev.ru 61320Sigor@sysoev.ru nxt_debug(task, "controller conn read timeout"); 61420Sigor@sysoev.ru 61527Svbart@nginx.com nxt_controller_conn_close(task, c, data); 61627Svbart@nginx.com } 61727Svbart@nginx.com 61827Svbart@nginx.com 61927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_body_read_state 62027Svbart@nginx.com nxt_aligned(64) = 62127Svbart@nginx.com { 62256Sigor@sysoev.ru .ready_handler = nxt_controller_conn_body_read, 62356Sigor@sysoev.ru .close_handler = nxt_controller_conn_close, 62456Sigor@sysoev.ru .error_handler = nxt_controller_conn_read_error, 62527Svbart@nginx.com 62656Sigor@sysoev.ru .timer_handler = nxt_controller_conn_read_timeout, 62756Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 62856Sigor@sysoev.ru .timer_data = 60 * 1000, 62956Sigor@sysoev.ru .timer_autoreset = 1, 63027Svbart@nginx.com }; 63127Svbart@nginx.com 63227Svbart@nginx.com 63327Svbart@nginx.com static void 63427Svbart@nginx.com nxt_controller_conn_body_read(nxt_task_t *task, void *obj, void *data) 63527Svbart@nginx.com { 636107Svbart@nginx.com size_t read; 637107Svbart@nginx.com nxt_buf_t *b; 638107Svbart@nginx.com nxt_conn_t *c; 639107Svbart@nginx.com nxt_controller_request_t *r; 64027Svbart@nginx.com 64127Svbart@nginx.com c = obj; 642107Svbart@nginx.com r = data; 64327Svbart@nginx.com b = c->read; 64427Svbart@nginx.com 645107Svbart@nginx.com read = nxt_buf_mem_used_size(&b->mem); 64627Svbart@nginx.com 647107Svbart@nginx.com nxt_debug(task, "controller conn body read: %uz of %uz", 648107Svbart@nginx.com read, r->length); 64927Svbart@nginx.com 650107Svbart@nginx.com if (read >= r->length) { 651140Svbart@nginx.com nxt_controller_process_request(task, r); 65227Svbart@nginx.com return; 65327Svbart@nginx.com } 65427Svbart@nginx.com 65562Sigor@sysoev.ru nxt_conn_read(task->thread->engine, c); 65627Svbart@nginx.com } 65727Svbart@nginx.com 65827Svbart@nginx.com 65927Svbart@nginx.com static const nxt_event_conn_state_t nxt_controller_conn_write_state 66027Svbart@nginx.com nxt_aligned(64) = 66127Svbart@nginx.com { 66256Sigor@sysoev.ru .ready_handler = nxt_controller_conn_write, 66356Sigor@sysoev.ru .error_handler = nxt_controller_conn_write_error, 66427Svbart@nginx.com 66556Sigor@sysoev.ru .timer_handler = nxt_controller_conn_write_timeout, 66656Sigor@sysoev.ru .timer_value = nxt_controller_conn_timeout_value, 66756Sigor@sysoev.ru .timer_data = 60 * 1000, 66856Sigor@sysoev.ru .timer_autoreset = 1, 66927Svbart@nginx.com }; 67027Svbart@nginx.com 67127Svbart@nginx.com 67227Svbart@nginx.com static void 67327Svbart@nginx.com nxt_controller_conn_write(nxt_task_t *task, void *obj, void *data) 67427Svbart@nginx.com { 67562Sigor@sysoev.ru nxt_buf_t *b; 67662Sigor@sysoev.ru nxt_conn_t *c; 67727Svbart@nginx.com 67827Svbart@nginx.com c = obj; 67927Svbart@nginx.com 68027Svbart@nginx.com nxt_debug(task, "controller conn write"); 68127Svbart@nginx.com 68227Svbart@nginx.com b = c->write; 68327Svbart@nginx.com 68427Svbart@nginx.com if (b->mem.pos != b->mem.free) { 68562Sigor@sysoev.ru nxt_conn_write(task->thread->engine, c); 68627Svbart@nginx.com return; 68727Svbart@nginx.com } 68827Svbart@nginx.com 68927Svbart@nginx.com nxt_debug(task, "controller conn write complete"); 69027Svbart@nginx.com 69127Svbart@nginx.com nxt_controller_conn_close(task, c, data); 69227Svbart@nginx.com } 69327Svbart@nginx.com 69427Svbart@nginx.com 69527Svbart@nginx.com static void 69627Svbart@nginx.com nxt_controller_conn_write_error(nxt_task_t *task, void *obj, void *data) 69727Svbart@nginx.com { 69862Sigor@sysoev.ru nxt_conn_t *c; 69927Svbart@nginx.com 70027Svbart@nginx.com c = obj; 70127Svbart@nginx.com 70227Svbart@nginx.com nxt_debug(task, "controller conn write error"); 70327Svbart@nginx.com 70427Svbart@nginx.com nxt_controller_conn_close(task, c, data); 70527Svbart@nginx.com } 70627Svbart@nginx.com 70727Svbart@nginx.com 70827Svbart@nginx.com static void 70927Svbart@nginx.com nxt_controller_conn_write_timeout(nxt_task_t *task, void *obj, void *data) 71027Svbart@nginx.com { 71162Sigor@sysoev.ru nxt_conn_t *c; 71262Sigor@sysoev.ru nxt_timer_t *timer; 71327Svbart@nginx.com 71462Sigor@sysoev.ru timer = obj; 71527Svbart@nginx.com 71662Sigor@sysoev.ru c = nxt_write_timer_conn(timer); 71727Svbart@nginx.com c->socket.timedout = 1; 71827Svbart@nginx.com c->socket.closed = 1; 71927Svbart@nginx.com 72027Svbart@nginx.com nxt_debug(task, "controller conn write timeout"); 72127Svbart@nginx.com 72227Svbart@nginx.com nxt_controller_conn_close(task, c, data); 72320Sigor@sysoev.ru } 72420Sigor@sysoev.ru 72520Sigor@sysoev.ru 72620Sigor@sysoev.ru static const nxt_event_conn_state_t nxt_controller_conn_close_state 72720Sigor@sysoev.ru nxt_aligned(64) = 72820Sigor@sysoev.ru { 72956Sigor@sysoev.ru .ready_handler = nxt_controller_conn_free, 73020Sigor@sysoev.ru }; 73120Sigor@sysoev.ru 73220Sigor@sysoev.ru 73320Sigor@sysoev.ru static void 73420Sigor@sysoev.ru nxt_controller_conn_close(nxt_task_t *task, void *obj, void *data) 73520Sigor@sysoev.ru { 73662Sigor@sysoev.ru nxt_conn_t *c; 73720Sigor@sysoev.ru 73820Sigor@sysoev.ru c = obj; 73920Sigor@sysoev.ru 74020Sigor@sysoev.ru nxt_debug(task, "controller conn close"); 74120Sigor@sysoev.ru 74227Svbart@nginx.com nxt_queue_remove(&c->link); 74327Svbart@nginx.com 74420Sigor@sysoev.ru c->write_state = &nxt_controller_conn_close_state; 74520Sigor@sysoev.ru 74662Sigor@sysoev.ru nxt_conn_close(task->thread->engine, c); 74720Sigor@sysoev.ru } 74820Sigor@sysoev.ru 74920Sigor@sysoev.ru 75020Sigor@sysoev.ru static void 75120Sigor@sysoev.ru nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) 75220Sigor@sysoev.ru { 75362Sigor@sysoev.ru nxt_conn_t *c; 75420Sigor@sysoev.ru 75520Sigor@sysoev.ru c = obj; 75620Sigor@sysoev.ru 75720Sigor@sysoev.ru nxt_debug(task, "controller conn free"); 75820Sigor@sysoev.ru 759337Sigor@sysoev.ru nxt_sockaddr_cache_free(task->thread->engine, c); 760337Sigor@sysoev.ru 761386Sigor@sysoev.ru nxt_conn_free(task, c); 76220Sigor@sysoev.ru } 76327Svbart@nginx.com 76427Svbart@nginx.com 76527Svbart@nginx.com static nxt_int_t 76660Svbart@nginx.com nxt_controller_request_content_length(void *ctx, nxt_http_field_t *field, 767417Svbart@nginx.com uintptr_t data) 76827Svbart@nginx.com { 76927Svbart@nginx.com off_t length; 77027Svbart@nginx.com nxt_controller_request_t *r; 77127Svbart@nginx.com 77227Svbart@nginx.com r = ctx; 77327Svbart@nginx.com 774417Svbart@nginx.com length = nxt_off_t_parse(field->value, field->value_length); 77527Svbart@nginx.com 776710Svbart@nginx.com if (nxt_fast_path(length >= 0)) { 777107Svbart@nginx.com 778107Svbart@nginx.com if (nxt_slow_path(length > NXT_SIZE_T_MAX)) { 779417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, 780417Svbart@nginx.com "Content-Length is too big"); 781107Svbart@nginx.com return NXT_ERROR; 782107Svbart@nginx.com } 78327Svbart@nginx.com 78427Svbart@nginx.com r->length = length; 78527Svbart@nginx.com return NXT_OK; 78627Svbart@nginx.com } 78727Svbart@nginx.com 788417Svbart@nginx.com nxt_log_error(NXT_LOG_ERR, &r->conn->log, "Content-Length is invalid"); 78927Svbart@nginx.com 79027Svbart@nginx.com return NXT_ERROR; 79127Svbart@nginx.com } 79227Svbart@nginx.com 79327Svbart@nginx.com 79427Svbart@nginx.com static void 795140Svbart@nginx.com nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) 79627Svbart@nginx.com { 797774Svbart@nginx.com uint32_t i, count; 798774Svbart@nginx.com nxt_str_t path; 799774Svbart@nginx.com nxt_conn_t *c; 800774Svbart@nginx.com nxt_conf_value_t *value; 801774Svbart@nginx.com nxt_controller_response_t resp; 802774Svbart@nginx.com #if (NXT_TLS) 803774Svbart@nginx.com nxt_conf_value_t *certs; 804774Svbart@nginx.com 805774Svbart@nginx.com static nxt_str_t certificates = nxt_string("certificates"); 806774Svbart@nginx.com #endif 807774Svbart@nginx.com static nxt_str_t config = nxt_string("config"); 808774Svbart@nginx.com 809774Svbart@nginx.com c = req->conn; 810774Svbart@nginx.com path = req->parser.path; 811774Svbart@nginx.com 812774Svbart@nginx.com if (path.length > 1 && path.start[path.length - 1] == '/') { 813774Svbart@nginx.com path.length--; 814774Svbart@nginx.com } 815774Svbart@nginx.com 816774Svbart@nginx.com if (nxt_str_start(&path, "/config", 7) 817774Svbart@nginx.com && (path.length == 7 || path.start[7] == '/')) 818774Svbart@nginx.com { 819774Svbart@nginx.com if (path.length == 7) { 820774Svbart@nginx.com path.length = 1; 821774Svbart@nginx.com 822774Svbart@nginx.com } else { 823774Svbart@nginx.com path.length -= 7; 824774Svbart@nginx.com path.start += 7; 825774Svbart@nginx.com } 826774Svbart@nginx.com 827774Svbart@nginx.com nxt_controller_process_config(task, req, &path); 828774Svbart@nginx.com return; 829774Svbart@nginx.com } 830774Svbart@nginx.com 831774Svbart@nginx.com #if (NXT_TLS) 832774Svbart@nginx.com 833774Svbart@nginx.com if (nxt_str_start(&path, "/certificates", 13) 834774Svbart@nginx.com && (path.length == 13 || path.start[13] == '/')) 835774Svbart@nginx.com { 836774Svbart@nginx.com if (path.length == 13) { 837774Svbart@nginx.com path.length = 1; 838774Svbart@nginx.com 839774Svbart@nginx.com } else { 840774Svbart@nginx.com path.length -= 13; 841774Svbart@nginx.com path.start += 13; 842774Svbart@nginx.com } 843774Svbart@nginx.com 844774Svbart@nginx.com nxt_controller_process_cert(task, req, &path); 845774Svbart@nginx.com return; 846774Svbart@nginx.com } 847774Svbart@nginx.com 848774Svbart@nginx.com #endif 849774Svbart@nginx.com 850774Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 851774Svbart@nginx.com 852774Svbart@nginx.com if (path.length == 1 && path.start[0] == '/') { 853774Svbart@nginx.com 854774Svbart@nginx.com if (!nxt_str_eq(&req->parser.method, "GET", 3)) { 855774Svbart@nginx.com goto invalid_method; 856774Svbart@nginx.com } 857774Svbart@nginx.com 858774Svbart@nginx.com count = 1; 859774Svbart@nginx.com #if (NXT_TLS) 860774Svbart@nginx.com count++; 861774Svbart@nginx.com #endif 862774Svbart@nginx.com 863774Svbart@nginx.com value = nxt_conf_create_object(c->mem_pool, count); 864774Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 865774Svbart@nginx.com goto alloc_fail; 866774Svbart@nginx.com } 867774Svbart@nginx.com 868774Svbart@nginx.com i = 0; 869774Svbart@nginx.com 870774Svbart@nginx.com #if (NXT_TLS) 871774Svbart@nginx.com certs = nxt_cert_info_get_all(c->mem_pool); 872774Svbart@nginx.com if (nxt_slow_path(certs == NULL)) { 873774Svbart@nginx.com goto alloc_fail; 874774Svbart@nginx.com } 875774Svbart@nginx.com 876774Svbart@nginx.com nxt_conf_set_member(value, &certificates, certs, i++); 877774Svbart@nginx.com #endif 878774Svbart@nginx.com 879774Svbart@nginx.com nxt_conf_set_member(value, &config, nxt_controller_conf.root, i); 880774Svbart@nginx.com 881774Svbart@nginx.com resp.status = 200; 882774Svbart@nginx.com resp.conf = value; 883774Svbart@nginx.com 884774Svbart@nginx.com nxt_controller_response(task, req, &resp); 885774Svbart@nginx.com return; 886774Svbart@nginx.com } 887774Svbart@nginx.com 888774Svbart@nginx.com resp.status = 404; 889774Svbart@nginx.com resp.title = (u_char *) "Value doesn't exist."; 890774Svbart@nginx.com resp.offset = -1; 891774Svbart@nginx.com 892774Svbart@nginx.com nxt_controller_response(task, req, &resp); 893774Svbart@nginx.com return; 894774Svbart@nginx.com 895774Svbart@nginx.com invalid_method: 896774Svbart@nginx.com 897774Svbart@nginx.com resp.status = 405; 898774Svbart@nginx.com resp.title = (u_char *) "Invalid method."; 899774Svbart@nginx.com resp.offset = -1; 900774Svbart@nginx.com 901774Svbart@nginx.com nxt_controller_response(task, req, &resp); 902774Svbart@nginx.com return; 903774Svbart@nginx.com 904774Svbart@nginx.com alloc_fail: 905774Svbart@nginx.com 906774Svbart@nginx.com resp.status = 500; 907774Svbart@nginx.com resp.title = (u_char *) "Memory allocation failed."; 908774Svbart@nginx.com resp.offset = -1; 909774Svbart@nginx.com 910774Svbart@nginx.com nxt_controller_response(task, req, &resp); 911774Svbart@nginx.com return; 912774Svbart@nginx.com } 913774Svbart@nginx.com 914774Svbart@nginx.com 915774Svbart@nginx.com static void 916774Svbart@nginx.com nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, 917774Svbart@nginx.com nxt_str_t *path) 918774Svbart@nginx.com { 91965Sigor@sysoev.ru nxt_mp_t *mp; 92051Svbart@nginx.com nxt_int_t rc; 921140Svbart@nginx.com nxt_conn_t *c; 9221049Svbart@nginx.com nxt_bool_t post; 92351Svbart@nginx.com nxt_buf_mem_t *mbuf; 924106Svbart@nginx.com nxt_conf_op_t *ops; 925106Svbart@nginx.com nxt_conf_value_t *value; 926357Svbart@nginx.com nxt_conf_validation_t vldt; 927208Svbart@nginx.com nxt_conf_json_error_t error; 92844Svbart@nginx.com nxt_controller_response_t resp; 92944Svbart@nginx.com 93051Svbart@nginx.com static const nxt_str_t empty_obj = nxt_string("{}"); 93151Svbart@nginx.com 932774Svbart@nginx.com nxt_memzero(&resp, sizeof(nxt_controller_response_t)); 933632Svbart@nginx.com 934774Svbart@nginx.com c = req->conn; 93544Svbart@nginx.com 93644Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "GET", 3)) { 93746Svbart@nginx.com 938774Svbart@nginx.com value = nxt_conf_get_path(nxt_controller_conf.root, path); 93951Svbart@nginx.com 94051Svbart@nginx.com if (value == NULL) { 941208Svbart@nginx.com goto not_found; 94251Svbart@nginx.com } 94351Svbart@nginx.com 944208Svbart@nginx.com resp.status = 200; 945106Svbart@nginx.com resp.conf = value; 94646Svbart@nginx.com 947208Svbart@nginx.com nxt_controller_response(task, req, &resp); 948208Svbart@nginx.com return; 94951Svbart@nginx.com } 95051Svbart@nginx.com 9511049Svbart@nginx.com if (nxt_str_eq(&req->parser.method, "POST", 4)) { 9521049Svbart@nginx.com if (path->length == 1) { 9531049Svbart@nginx.com goto not_allowed; 9541049Svbart@nginx.com } 9551049Svbart@nginx.com 9561049Svbart@nginx.com post = 1; 9571049Svbart@nginx.com 9581049Svbart@nginx.com } else { 9591049Svbart@nginx.com post = 0; 9601049Svbart@nginx.com } 9611049Svbart@nginx.com 9621049Svbart@nginx.com if (post || nxt_str_eq(&req->parser.method, "PUT", 3)) { 96346Svbart@nginx.com 964238Svbart@nginx.com if (!nxt_queue_is_empty(&nxt_controller_waiting_requests)) { 965238Svbart@nginx.com nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); 966238Svbart@nginx.com return; 967238Svbart@nginx.com } 968238Svbart@nginx.com 96965Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 97051Svbart@nginx.com 97151Svbart@nginx.com if (nxt_slow_path(mp == NULL)) { 972208Svbart@nginx.com goto alloc_fail; 97346Svbart@nginx.com } 97446Svbart@nginx.com 97551Svbart@nginx.com mbuf = &c->read->mem; 97651Svbart@nginx.com 977208Svbart@nginx.com nxt_memzero(&error, sizeof(nxt_conf_json_error_t)); 978208Svbart@nginx.com 9791364Svbart@nginx.com /* Skip UTF-8 BOM. */ 9801364Svbart@nginx.com if (nxt_buf_mem_used_size(mbuf) >= 3 9811364Svbart@nginx.com && nxt_memcmp(mbuf->pos, "\xEF\xBB\xBF", 3) == 0) 9821364Svbart@nginx.com { 9831364Svbart@nginx.com mbuf->pos += 3; 9841364Svbart@nginx.com } 9851364Svbart@nginx.com 986208Svbart@nginx.com value = nxt_conf_json_parse(mp, mbuf->pos, mbuf->free, &error); 98751Svbart@nginx.com 98851Svbart@nginx.com if (value == NULL) { 98965Sigor@sysoev.ru nxt_mp_destroy(mp); 990208Svbart@nginx.com 991208Svbart@nginx.com if (error.pos == NULL) { 992208Svbart@nginx.com goto alloc_fail; 993208Svbart@nginx.com } 994208Svbart@nginx.com 995208Svbart@nginx.com resp.status = 400; 996208Svbart@nginx.com resp.title = (u_char *) "Invalid JSON."; 997357Svbart@nginx.com resp.detail.length = nxt_strlen(error.detail); 998357Svbart@nginx.com resp.detail.start = error.detail; 999208Svbart@nginx.com resp.offset = error.pos - mbuf->pos; 1000208Svbart@nginx.com 1001208Svbart@nginx.com nxt_conf_json_position(mbuf->pos, error.pos, 1002208Svbart@nginx.com &resp.line, &resp.column); 1003208Svbart@nginx.com 1004208Svbart@nginx.com nxt_controller_response(task, req, &resp); 1005208Svbart@nginx.com return; 100651Svbart@nginx.com } 100751Svbart@nginx.com 1008774Svbart@nginx.com if (path->length != 1) { 1009106Svbart@nginx.com rc = nxt_conf_op_compile(c->mem_pool, &ops, 1010106Svbart@nginx.com nxt_controller_conf.root, 10111049Svbart@nginx.com path, value, post); 101246Svbart@nginx.com 10131049Svbart@nginx.com if (rc != NXT_CONF_OP_OK) { 1014619Svbart@nginx.com nxt_mp_destroy(mp); 1015619Svbart@nginx.com 10161049Svbart@nginx.com switch (rc) { 10171049Svbart@nginx.com case NXT_CONF_OP_NOT_FOUND: 1018208Svbart@nginx.com goto not_found; 10191049Svbart@nginx.com 10201049Svbart@nginx.com case NXT_CONF_OP_NOT_ALLOWED: 10211049Svbart@nginx.com goto not_allowed; 102251Svbart@nginx.com } 102346Svbart@nginx.com 10241049Svbart@nginx.com /* rc == NXT_CONF_OP_ERROR */ 1025208Svbart@nginx.com goto alloc_fail; 102651Svbart@nginx.com } 102751Svbart@nginx.com 1028106Svbart@nginx.com value = nxt_conf_clone(mp, ops, nxt_controller_conf.root); 102951Svbart@nginx.com 103051Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 103165Sigor@sysoev.ru nxt_mp_destroy(mp); 1032208Svbart@nginx.com goto alloc_fail; 103351Svbart@nginx.com } 103446Svbart@nginx.com } 103544Svbart@nginx.com 1036357Svbart@nginx.com nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); 1037357Svbart@nginx.com 1038357Svbart@nginx.com vldt.conf = value; 1039357Svbart@nginx.com vldt.pool = c->mem_pool; 1040357Svbart@nginx.com 1041357Svbart@nginx.com rc = nxt_conf_validate(&vldt); 1042357Svbart@nginx.com 1043357Svbart@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1044121Svbart@nginx.com nxt_mp_destroy(mp); 1045357Svbart@nginx.com 1046357Svbart@nginx.com if (rc == NXT_DECLINED) { 1047357Svbart@nginx.com resp.detail = vldt.error; 1048357Svbart@nginx.com goto invalid_conf; 1049357Svbart@nginx.com } 1050357Svbart@nginx.com