10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 384Smax.romanov@nginx.com * Copyright (C) Max Romanov 40Sigor@sysoev.ru * Copyright (C) Igor Sysoev 50Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 60Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 70Sigor@sysoev.ru */ 80Sigor@sysoev.ru 90Sigor@sysoev.ru #include <nxt_main.h> 1020Sigor@sysoev.ru #include <nxt_runtime.h> 110Sigor@sysoev.ru #include <nxt_application.h> 12141Smax.romanov@nginx.com #include <nxt_master_process.h> 130Sigor@sysoev.ru 14216Sigor@sysoev.ru #include <glob.h> 150Sigor@sysoev.ru 16216Sigor@sysoev.ru 17216Sigor@sysoev.ru typedef struct { 18216Sigor@sysoev.ru nxt_str_t type; 19216Sigor@sysoev.ru nxt_str_t version; 20216Sigor@sysoev.ru nxt_str_t file; 21216Sigor@sysoev.ru } nxt_module_t; 22216Sigor@sysoev.ru 23216Sigor@sysoev.ru 24216Sigor@sysoev.ru static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path); 25216Sigor@sysoev.ru static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, 26216Sigor@sysoev.ru nxt_array_t *modules, const char *name); 27216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, 28216Sigor@sysoev.ru const char *name); 29216Sigor@sysoev.ru 300Sigor@sysoev.ru 310Sigor@sysoev.ru static nxt_thread_mutex_t nxt_app_mutex; 320Sigor@sysoev.ru static nxt_thread_cond_t nxt_app_cond; 330Sigor@sysoev.ru 3484Smax.romanov@nginx.com static nxt_http_fields_hash_entry_t nxt_app_request_fields[]; 35141Smax.romanov@nginx.com static nxt_http_fields_hash_t *nxt_app_request_fields_hash; 36141Smax.romanov@nginx.com 37141Smax.romanov@nginx.com static nxt_application_module_t *nxt_app; 380Sigor@sysoev.ru 39216Sigor@sysoev.ru 40216Sigor@sysoev.ru nxt_int_t 41216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data) 42216Sigor@sysoev.ru { 43216Sigor@sysoev.ru nxt_buf_t *b; 44216Sigor@sysoev.ru nxt_port_t *main_port; 45216Sigor@sysoev.ru nxt_runtime_t *rt; 46216Sigor@sysoev.ru 47216Sigor@sysoev.ru nxt_debug(task, "DISCOVERY"); 48216Sigor@sysoev.ru 49*233Sigor@sysoev.ru rt = task->thread->runtime; 50216Sigor@sysoev.ru 51*233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 52*233Sigor@sysoev.ru 53216Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MASTER]; 54216Sigor@sysoev.ru 55216Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 56216Sigor@sysoev.ru 0, -1, b); 57216Sigor@sysoev.ru 58216Sigor@sysoev.ru return NXT_OK; 59216Sigor@sysoev.ru } 60216Sigor@sysoev.ru 61216Sigor@sysoev.ru 62216Sigor@sysoev.ru static void 63216Sigor@sysoev.ru nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 64216Sigor@sysoev.ru { 65216Sigor@sysoev.ru nxt_mp_t *mp; 66216Sigor@sysoev.ru nxt_buf_t *b; 67216Sigor@sysoev.ru 68216Sigor@sysoev.ru b = obj; 69216Sigor@sysoev.ru mp = b->data; 70216Sigor@sysoev.ru 71216Sigor@sysoev.ru nxt_mp_destroy(mp); 72216Sigor@sysoev.ru 73216Sigor@sysoev.ru exit(0); 74216Sigor@sysoev.ru } 75216Sigor@sysoev.ru 76216Sigor@sysoev.ru 77216Sigor@sysoev.ru static nxt_buf_t * 78216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 79216Sigor@sysoev.ru { 80216Sigor@sysoev.ru char *name; 81216Sigor@sysoev.ru u_char *p, *end; 82216Sigor@sysoev.ru size_t size; 83216Sigor@sysoev.ru glob_t glb; 84216Sigor@sysoev.ru nxt_mp_t *mp; 85216Sigor@sysoev.ru nxt_buf_t *b; 86216Sigor@sysoev.ru nxt_int_t ret; 87216Sigor@sysoev.ru nxt_uint_t i, n; 88216Sigor@sysoev.ru nxt_array_t *modules; 89216Sigor@sysoev.ru nxt_module_t *module; 90216Sigor@sysoev.ru 91216Sigor@sysoev.ru b = NULL; 92216Sigor@sysoev.ru 93216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 94216Sigor@sysoev.ru if (mp == NULL) { 95216Sigor@sysoev.ru return b; 96216Sigor@sysoev.ru } 97216Sigor@sysoev.ru 98216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 99216Sigor@sysoev.ru 100216Sigor@sysoev.ru if (ret == 0) { 101216Sigor@sysoev.ru n = glb.gl_pathc; 102216Sigor@sysoev.ru 103216Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 104216Sigor@sysoev.ru if (modules == NULL) { 105216Sigor@sysoev.ru goto fail; 106216Sigor@sysoev.ru } 107216Sigor@sysoev.ru 108216Sigor@sysoev.ru for (i = 0; i < n; i++) { 109216Sigor@sysoev.ru name = glb.gl_pathv[i]; 110216Sigor@sysoev.ru 111216Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 112216Sigor@sysoev.ru if (ret != NXT_OK) { 113216Sigor@sysoev.ru goto fail; 114216Sigor@sysoev.ru } 115216Sigor@sysoev.ru } 116216Sigor@sysoev.ru 117216Sigor@sysoev.ru size = sizeof("[]") - 1; 118216Sigor@sysoev.ru module = modules->elts; 119216Sigor@sysoev.ru n = modules->nelts; 120216Sigor@sysoev.ru 121216Sigor@sysoev.ru for (i = 0; i < n; i++) { 122216Sigor@sysoev.ru nxt_debug(task, "module: %V %V %V", 123216Sigor@sysoev.ru &module[i].type, &module[i].version, &module[i].file); 124216Sigor@sysoev.ru 125216Sigor@sysoev.ru size += sizeof("{\"type\": \"\",") - 1; 126216Sigor@sysoev.ru size += sizeof(" \"version\": \"\",") - 1; 127216Sigor@sysoev.ru size += sizeof(" \"file\": \"\"},") - 1; 128216Sigor@sysoev.ru 129216Sigor@sysoev.ru size += module[i].type.length 130216Sigor@sysoev.ru + module[i].version.length 131216Sigor@sysoev.ru + module[i].file.length; 132216Sigor@sysoev.ru } 133216Sigor@sysoev.ru 134216Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 135216Sigor@sysoev.ru if (b == NULL) { 136216Sigor@sysoev.ru goto fail; 137216Sigor@sysoev.ru } 138216Sigor@sysoev.ru 139216Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 140216Sigor@sysoev.ru 141216Sigor@sysoev.ru p = b->mem.free; 142216Sigor@sysoev.ru end = b->mem.end; 143216Sigor@sysoev.ru *p++ = '['; 144216Sigor@sysoev.ru 145216Sigor@sysoev.ru for (i = 0; i < n; i++) { 146216Sigor@sysoev.ru p = nxt_sprintf(p, end, 147216Sigor@sysoev.ru "{\"type\": \"%V\", \"version\": \"%V\", \"file\": \"%V\"},", 148216Sigor@sysoev.ru &module[i].type, &module[i].version, &module[i].file); 149216Sigor@sysoev.ru } 150216Sigor@sysoev.ru 151216Sigor@sysoev.ru *p++ = ']'; 152216Sigor@sysoev.ru b->mem.free = p; 153216Sigor@sysoev.ru } 154216Sigor@sysoev.ru 155216Sigor@sysoev.ru fail: 156216Sigor@sysoev.ru 157216Sigor@sysoev.ru globfree(&glb); 158216Sigor@sysoev.ru 159216Sigor@sysoev.ru return b; 160216Sigor@sysoev.ru } 161216Sigor@sysoev.ru 162216Sigor@sysoev.ru 163216Sigor@sysoev.ru static nxt_int_t 164216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 165216Sigor@sysoev.ru const char *name) 166216Sigor@sysoev.ru { 167216Sigor@sysoev.ru void *dl; 168216Sigor@sysoev.ru nxt_str_t *s; 169216Sigor@sysoev.ru nxt_int_t ret; 170216Sigor@sysoev.ru nxt_uint_t i, n; 171216Sigor@sysoev.ru nxt_module_t *module; 172216Sigor@sysoev.ru nxt_application_module_t *app; 173216Sigor@sysoev.ru 174216Sigor@sysoev.ru /* 175216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 176216Sigor@sysoev.ru * Any module processing errors are ignored. 177216Sigor@sysoev.ru */ 178216Sigor@sysoev.ru ret = NXT_ERROR; 179216Sigor@sysoev.ru 180216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 181216Sigor@sysoev.ru 182216Sigor@sysoev.ru if (dl == NULL) { 183216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 184216Sigor@sysoev.ru name, dlerror()); 185216Sigor@sysoev.ru return NXT_OK; 186216Sigor@sysoev.ru } 187216Sigor@sysoev.ru 188216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 189216Sigor@sysoev.ru 190216Sigor@sysoev.ru if (app != NULL) { 191216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "module: %V \"%s\"", 192216Sigor@sysoev.ru &app->version, name); 193216Sigor@sysoev.ru 194216Sigor@sysoev.ru module = modules->elts; 195216Sigor@sysoev.ru n = modules->nelts; 196216Sigor@sysoev.ru 197216Sigor@sysoev.ru for (i = 0; i < n; i++) { 198216Sigor@sysoev.ru if (nxt_strstr_eq(&app->version, &module[i].version)) { 199216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 200216Sigor@sysoev.ru "ignoring %s module with the same " 201216Sigor@sysoev.ru "application language version %V as in %s", 202216Sigor@sysoev.ru name, &module[i].version, &module[i].file); 203216Sigor@sysoev.ru 204216Sigor@sysoev.ru goto done; 205216Sigor@sysoev.ru } 206216Sigor@sysoev.ru } 207216Sigor@sysoev.ru 208216Sigor@sysoev.ru module = nxt_array_add(modules); 209216Sigor@sysoev.ru if (module == NULL) { 210216Sigor@sysoev.ru goto fail; 211216Sigor@sysoev.ru } 212216Sigor@sysoev.ru 213216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->type, &app->type); 214216Sigor@sysoev.ru if (s == NULL) { 215216Sigor@sysoev.ru goto fail; 216216Sigor@sysoev.ru } 217216Sigor@sysoev.ru 218216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->version, &app->version); 219216Sigor@sysoev.ru if (s == NULL) { 220216Sigor@sysoev.ru goto fail; 221216Sigor@sysoev.ru } 222216Sigor@sysoev.ru 223216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 224216Sigor@sysoev.ru 225216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 226216Sigor@sysoev.ru if (module->file.start == NULL) { 227216Sigor@sysoev.ru goto fail; 228216Sigor@sysoev.ru } 229216Sigor@sysoev.ru 230216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 231216Sigor@sysoev.ru 232216Sigor@sysoev.ru } else { 233216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlsym(\"%s\"), failed: \"%s\"", 234216Sigor@sysoev.ru name, dlerror()); 235216Sigor@sysoev.ru } 236216Sigor@sysoev.ru 237216Sigor@sysoev.ru done: 238216Sigor@sysoev.ru 239216Sigor@sysoev.ru ret = NXT_OK; 240216Sigor@sysoev.ru 241216Sigor@sysoev.ru fail: 242216Sigor@sysoev.ru 243216Sigor@sysoev.ru if (dlclose(dl) != 0) { 244216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlclose(\"%s\"), failed: \"%s\"", 245216Sigor@sysoev.ru name, dlerror()); 246216Sigor@sysoev.ru } 247216Sigor@sysoev.ru 248216Sigor@sysoev.ru return ret; 249216Sigor@sysoev.ru } 250216Sigor@sysoev.ru 251216Sigor@sysoev.ru 2520Sigor@sysoev.ru nxt_int_t 253141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data) 2540Sigor@sysoev.ru { 255216Sigor@sysoev.ru nxt_int_t ret; 256216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 257216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 258141Smax.romanov@nginx.com 259141Smax.romanov@nginx.com app_conf = data; 260141Smax.romanov@nginx.com 261216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 262216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 263216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 264216Sigor@sysoev.ru &app_conf->type); 265216Sigor@sysoev.ru return NXT_ERROR; 266216Sigor@sysoev.ru } 267216Sigor@sysoev.ru 268216Sigor@sysoev.ru nxt_app = lang->module; 269216Sigor@sysoev.ru 270216Sigor@sysoev.ru if (nxt_app == NULL) { 271216Sigor@sysoev.ru nxt_debug(task, "application language module: %V \"%s\"", 272216Sigor@sysoev.ru &lang->version, lang->file); 273216Sigor@sysoev.ru 274216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 275216Sigor@sysoev.ru } 276216Sigor@sysoev.ru 2770Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) { 2780Sigor@sysoev.ru return NXT_ERROR; 2790Sigor@sysoev.ru } 2800Sigor@sysoev.ru 2810Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_cond_create(&nxt_app_cond) != NXT_OK)) { 2820Sigor@sysoev.ru return NXT_ERROR; 2830Sigor@sysoev.ru } 2840Sigor@sysoev.ru 285141Smax.romanov@nginx.com ret = nxt_app->init(task, data); 286141Smax.romanov@nginx.com 287141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 28884Smax.romanov@nginx.com nxt_debug(task, "application init failed"); 289141Smax.romanov@nginx.com 290141Smax.romanov@nginx.com } else { 291141Smax.romanov@nginx.com nxt_debug(task, "application init done"); 29220Sigor@sysoev.ru } 29320Sigor@sysoev.ru 294141Smax.romanov@nginx.com return ret; 29520Sigor@sysoev.ru } 29620Sigor@sysoev.ru 29720Sigor@sysoev.ru 298216Sigor@sysoev.ru static nxt_app_module_t * 299216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 300216Sigor@sysoev.ru { 301216Sigor@sysoev.ru void *dl; 302216Sigor@sysoev.ru 303216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 304216Sigor@sysoev.ru 305216Sigor@sysoev.ru if (dl != NULL) { 306216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 307216Sigor@sysoev.ru } 308216Sigor@sysoev.ru 309216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 310216Sigor@sysoev.ru name, dlerror()); 311216Sigor@sysoev.ru 312216Sigor@sysoev.ru return NULL; 313216Sigor@sysoev.ru } 314216Sigor@sysoev.ru 315216Sigor@sysoev.ru 31684Smax.romanov@nginx.com nxt_int_t 31784Smax.romanov@nginx.com nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt) 3180Sigor@sysoev.ru { 31984Smax.romanov@nginx.com nxt_http_fields_hash_t *hash; 3200Sigor@sysoev.ru 32184Smax.romanov@nginx.com hash = nxt_http_fields_hash_create(nxt_app_request_fields, rt->mem_pool); 32284Smax.romanov@nginx.com if (nxt_slow_path(hash == NULL)) { 32384Smax.romanov@nginx.com return NXT_ERROR; 3240Sigor@sysoev.ru } 3250Sigor@sysoev.ru 32684Smax.romanov@nginx.com nxt_app_request_fields_hash = hash; 3270Sigor@sysoev.ru 32884Smax.romanov@nginx.com return NXT_OK; 32984Smax.romanov@nginx.com } 3304Sigor@sysoev.ru 3310Sigor@sysoev.ru 33284Smax.romanov@nginx.com void 33384Smax.romanov@nginx.com nxt_port_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 33484Smax.romanov@nginx.com { 33584Smax.romanov@nginx.com size_t dump_size; 33684Smax.romanov@nginx.com nxt_buf_t *b; 33784Smax.romanov@nginx.com nxt_port_t *port; 33884Smax.romanov@nginx.com nxt_app_rmsg_t rmsg = { msg->buf }; 33984Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 3400Sigor@sysoev.ru 34184Smax.romanov@nginx.com b = msg->buf; 34284Smax.romanov@nginx.com dump_size = b->mem.free - b->mem.pos; 3430Sigor@sysoev.ru 34484Smax.romanov@nginx.com if (dump_size > 300) { 34584Smax.romanov@nginx.com dump_size = 300; 34684Smax.romanov@nginx.com } 3470Sigor@sysoev.ru 34884Smax.romanov@nginx.com nxt_debug(task, "app data: %*s ...", dump_size, b->mem.pos); 3490Sigor@sysoev.ru 35084Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 35184Smax.romanov@nginx.com msg->port_msg.reply_port); 35284Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 35384Smax.romanov@nginx.com // 35484Smax.romanov@nginx.com } 3554Sigor@sysoev.ru 35684Smax.romanov@nginx.com wmsg.port = port; 35784Smax.romanov@nginx.com wmsg.write = NULL; 35884Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 35984Smax.romanov@nginx.com wmsg.stream = msg->port_msg.stream; 3600Sigor@sysoev.ru 36184Smax.romanov@nginx.com nxt_app->run(task, &rmsg, &wmsg); 3620Sigor@sysoev.ru } 3630Sigor@sysoev.ru 3640Sigor@sysoev.ru 36584Smax.romanov@nginx.com nxt_inline nxt_port_t * 36684Smax.romanov@nginx.com nxt_app_msg_get_port(nxt_task_t *task, nxt_app_wmsg_t *msg) 3670Sigor@sysoev.ru { 36884Smax.romanov@nginx.com return msg->port; 36984Smax.romanov@nginx.com } 37084Smax.romanov@nginx.com 37184Smax.romanov@nginx.com 37284Smax.romanov@nginx.com u_char * 37384Smax.romanov@nginx.com nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, size_t size) 37484Smax.romanov@nginx.com { 37584Smax.romanov@nginx.com size_t free_size; 37684Smax.romanov@nginx.com u_char *res; 37784Smax.romanov@nginx.com nxt_buf_t *b; 37884Smax.romanov@nginx.com nxt_port_t *port; 3790Sigor@sysoev.ru 38084Smax.romanov@nginx.com res = NULL; 38184Smax.romanov@nginx.com 38284Smax.romanov@nginx.com do { 38384Smax.romanov@nginx.com b = *msg->buf; 3840Sigor@sysoev.ru 38584Smax.romanov@nginx.com if (b == NULL) { 38684Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 38784Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 38884Smax.romanov@nginx.com return NULL; 38984Smax.romanov@nginx.com } 39084Smax.romanov@nginx.com 39184Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 39284Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 39384Smax.romanov@nginx.com return NULL; 39484Smax.romanov@nginx.com } 3950Sigor@sysoev.ru 39684Smax.romanov@nginx.com *msg->buf = b; 39784Smax.romanov@nginx.com 39884Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 3990Sigor@sysoev.ru 40084Smax.romanov@nginx.com if (nxt_slow_path(free_size < size)) { 40184Smax.romanov@nginx.com nxt_debug(task, "requested buffer too big (%z < %z)", 40284Smax.romanov@nginx.com free_size, size); 40384Smax.romanov@nginx.com return NULL; 40484Smax.romanov@nginx.com } 40584Smax.romanov@nginx.com 40684Smax.romanov@nginx.com } 40784Smax.romanov@nginx.com 40884Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4090Sigor@sysoev.ru 41084Smax.romanov@nginx.com if (free_size >= size) { 41184Smax.romanov@nginx.com res = b->mem.free; 41284Smax.romanov@nginx.com b->mem.free += size; 41384Smax.romanov@nginx.com 41484Smax.romanov@nginx.com return res; 41584Smax.romanov@nginx.com } 4161Sigor@sysoev.ru 417206Smax.romanov@nginx.com if (nxt_port_mmap_increase_buf(task, b, size, size) == NXT_OK) { 41884Smax.romanov@nginx.com res = b->mem.free; 41984Smax.romanov@nginx.com b->mem.free += size; 4200Sigor@sysoev.ru 42184Smax.romanov@nginx.com return res; 42284Smax.romanov@nginx.com } 42384Smax.romanov@nginx.com 42484Smax.romanov@nginx.com msg->buf = &b->next; 42584Smax.romanov@nginx.com } while(1); 4260Sigor@sysoev.ru } 4270Sigor@sysoev.ru 4280Sigor@sysoev.ru 42984Smax.romanov@nginx.com nxt_int_t 43084Smax.romanov@nginx.com nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, u_char *c, size_t size) 4310Sigor@sysoev.ru { 43284Smax.romanov@nginx.com u_char *dst; 43384Smax.romanov@nginx.com size_t dst_length; 4340Sigor@sysoev.ru 43584Smax.romanov@nginx.com if (c != NULL) { 43684Smax.romanov@nginx.com dst_length = size + (size < 128 ? 1 : 4) + 1; 4370Sigor@sysoev.ru 43884Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 43984Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 44084Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 44184Smax.romanov@nginx.com dst_length); 44284Smax.romanov@nginx.com return NXT_ERROR; 4430Sigor@sysoev.ru } 4440Sigor@sysoev.ru 44584Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, size + 1); /* +1 for trailing 0 */ 4460Sigor@sysoev.ru 44784Smax.romanov@nginx.com nxt_memcpy(dst, c, size); 44884Smax.romanov@nginx.com dst[size] = 0; 4490Sigor@sysoev.ru 45084Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: %uz %*s", size, (int)size, c); 45184Smax.romanov@nginx.com } else { 45284Smax.romanov@nginx.com dst_length = 1; 4530Sigor@sysoev.ru 45484Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 45584Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 45684Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 45784Smax.romanov@nginx.com dst_length); 45884Smax.romanov@nginx.com return NXT_ERROR; 4590Sigor@sysoev.ru } 4600Sigor@sysoev.ru 46184Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, 0); 46284Smax.romanov@nginx.com 46384Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: NULL"); 4640Sigor@sysoev.ru } 4650Sigor@sysoev.ru 46684Smax.romanov@nginx.com return NXT_OK; 4670Sigor@sysoev.ru } 4680Sigor@sysoev.ru 4690Sigor@sysoev.ru 47084Smax.romanov@nginx.com nxt_int_t 47184Smax.romanov@nginx.com nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, nxt_app_wmsg_t *msg, 47284Smax.romanov@nginx.com const nxt_str_t *prefix, const nxt_str_t *v) 4730Sigor@sysoev.ru { 47484Smax.romanov@nginx.com u_char *dst, *src; 47584Smax.romanov@nginx.com size_t i, length, dst_length; 47684Smax.romanov@nginx.com 47784Smax.romanov@nginx.com length = prefix->length + v->length; 4780Sigor@sysoev.ru 47984Smax.romanov@nginx.com dst_length = length + (length < 128 ? 1 : 4) + 1; 48084Smax.romanov@nginx.com 48184Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 48284Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 48384Smax.romanov@nginx.com return NXT_ERROR; 4840Sigor@sysoev.ru } 4850Sigor@sysoev.ru 48684Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, length + 1); /* +1 for trailing 0 */ 48784Smax.romanov@nginx.com 48884Smax.romanov@nginx.com nxt_memcpy(dst, prefix->start, prefix->length); 48984Smax.romanov@nginx.com dst += prefix->length; 4900Sigor@sysoev.ru 49184Smax.romanov@nginx.com src = v->start; 49284Smax.romanov@nginx.com for (i = 0; i < v->length; i++, dst++, src++) { 49384Smax.romanov@nginx.com 49484Smax.romanov@nginx.com if (*src >= 'a' && *src <= 'z') { 49584Smax.romanov@nginx.com *dst = *src & ~0x20; 49684Smax.romanov@nginx.com continue; 4970Sigor@sysoev.ru } 4980Sigor@sysoev.ru 49984Smax.romanov@nginx.com if (*src == '-') { 50084Smax.romanov@nginx.com *dst = '_'; 50184Smax.romanov@nginx.com continue; 5020Sigor@sysoev.ru } 5030Sigor@sysoev.ru 50484Smax.romanov@nginx.com *dst = *src; 5050Sigor@sysoev.ru } 5060Sigor@sysoev.ru 50784Smax.romanov@nginx.com *dst = 0; 5080Sigor@sysoev.ru 50984Smax.romanov@nginx.com return NXT_OK; 5100Sigor@sysoev.ru } 5110Sigor@sysoev.ru 5120Sigor@sysoev.ru 51384Smax.romanov@nginx.com nxt_int_t 51484Smax.romanov@nginx.com nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, nxt_str_t *str) 5150Sigor@sysoev.ru { 51684Smax.romanov@nginx.com size_t length; 51784Smax.romanov@nginx.com nxt_buf_t *buf; 5180Sigor@sysoev.ru 51984Smax.romanov@nginx.com do { 52084Smax.romanov@nginx.com buf = msg->buf; 52184Smax.romanov@nginx.com 52284Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 52384Smax.romanov@nginx.com return NXT_DONE; 5240Sigor@sysoev.ru } 5250Sigor@sysoev.ru 52684Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 52784Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 52884Smax.romanov@nginx.com msg->buf = buf->next; 52984Smax.romanov@nginx.com continue; 53084Smax.romanov@nginx.com } 53184Smax.romanov@nginx.com return NXT_ERROR; 5320Sigor@sysoev.ru } 5330Sigor@sysoev.ru 53484Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 53584Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 53684Smax.romanov@nginx.com return NXT_ERROR; 53784Smax.romanov@nginx.com } 53884Smax.romanov@nginx.com } 5390Sigor@sysoev.ru 54084Smax.romanov@nginx.com break; 54184Smax.romanov@nginx.com } while (1); 5420Sigor@sysoev.ru 54384Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, &length); 54484Smax.romanov@nginx.com 54584Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < (intptr_t)length)) 54684Smax.romanov@nginx.com { 54784Smax.romanov@nginx.com return NXT_ERROR; 5480Sigor@sysoev.ru } 5490Sigor@sysoev.ru 55084Smax.romanov@nginx.com if (length > 0) { 55184Smax.romanov@nginx.com str->start = buf->mem.pos; 55284Smax.romanov@nginx.com str->length = length - 1; 5530Sigor@sysoev.ru 55484Smax.romanov@nginx.com buf->mem.pos += length; 5550Sigor@sysoev.ru 55684Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: %d %*s", (int)length - 1, 55784Smax.romanov@nginx.com (int)length - 1, str->start); 55884Smax.romanov@nginx.com } else { 55984Smax.romanov@nginx.com str->start = NULL; 56084Smax.romanov@nginx.com str->length = 0; 5610Sigor@sysoev.ru 56284Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: NULL"); 5630Sigor@sysoev.ru } 5640Sigor@sysoev.ru 5650Sigor@sysoev.ru return NXT_OK; 5660Sigor@sysoev.ru } 5670Sigor@sysoev.ru 5680Sigor@sysoev.ru 569206Smax.romanov@nginx.com size_t 570206Smax.romanov@nginx.com nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *dst, 571206Smax.romanov@nginx.com size_t size) 572206Smax.romanov@nginx.com { 573206Smax.romanov@nginx.com size_t res, read_size; 574206Smax.romanov@nginx.com nxt_buf_t *buf; 575206Smax.romanov@nginx.com 576206Smax.romanov@nginx.com res = 0; 577206Smax.romanov@nginx.com 578206Smax.romanov@nginx.com while (size > 0) { 579206Smax.romanov@nginx.com buf = msg->buf; 580206Smax.romanov@nginx.com 581206Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 582206Smax.romanov@nginx.com break; 583206Smax.romanov@nginx.com } 584206Smax.romanov@nginx.com 585206Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 586206Smax.romanov@nginx.com msg->buf = buf->next; 587206Smax.romanov@nginx.com continue; 588206Smax.romanov@nginx.com } 589206Smax.romanov@nginx.com 590206Smax.romanov@nginx.com read_size = nxt_buf_mem_used_size(&buf->mem); 591206Smax.romanov@nginx.com read_size = nxt_min(read_size, size); 592206Smax.romanov@nginx.com 593206Smax.romanov@nginx.com dst = nxt_cpymem(dst, buf->mem.pos, read_size); 594206Smax.romanov@nginx.com 595206Smax.romanov@nginx.com size -= read_size; 596206Smax.romanov@nginx.com buf->mem.pos += read_size; 597206Smax.romanov@nginx.com res += read_size; 598206Smax.romanov@nginx.com } 599206Smax.romanov@nginx.com 600206Smax.romanov@nginx.com nxt_debug(task, "nxt_read_raw: %uz", res); 601206Smax.romanov@nginx.com 602206Smax.romanov@nginx.com return res; 603206Smax.romanov@nginx.com } 604206Smax.romanov@nginx.com 605206Smax.romanov@nginx.com 60684Smax.romanov@nginx.com nxt_int_t 60784Smax.romanov@nginx.com nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_str_t *n, 60884Smax.romanov@nginx.com nxt_str_t *v) 6090Sigor@sysoev.ru { 61084Smax.romanov@nginx.com nxt_int_t rc; 6110Sigor@sysoev.ru 61284Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, n); 61384Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 61484Smax.romanov@nginx.com return rc; 6150Sigor@sysoev.ru } 6160Sigor@sysoev.ru 61784Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, v); 61884Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 61984Smax.romanov@nginx.com return rc; 62084Smax.romanov@nginx.com } 6210Sigor@sysoev.ru 62284Smax.romanov@nginx.com return rc; 6230Sigor@sysoev.ru } 6240Sigor@sysoev.ru 6250Sigor@sysoev.ru 6260Sigor@sysoev.ru nxt_int_t 62784Smax.romanov@nginx.com nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 6280Sigor@sysoev.ru { 62984Smax.romanov@nginx.com nxt_buf_t *buf; 6300Sigor@sysoev.ru 63184Smax.romanov@nginx.com do { 63284Smax.romanov@nginx.com buf = msg->buf; 6330Sigor@sysoev.ru 63484Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 63584Smax.romanov@nginx.com return NXT_DONE; 63684Smax.romanov@nginx.com } 6370Sigor@sysoev.ru 63884Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 63984Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 64084Smax.romanov@nginx.com msg->buf = buf->next; 64184Smax.romanov@nginx.com continue; 64284Smax.romanov@nginx.com } 6430Sigor@sysoev.ru return NXT_ERROR; 6440Sigor@sysoev.ru } 6450Sigor@sysoev.ru 64684Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 64784Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 64884Smax.romanov@nginx.com return NXT_ERROR; 64984Smax.romanov@nginx.com } 65084Smax.romanov@nginx.com } 6510Sigor@sysoev.ru 65284Smax.romanov@nginx.com break; 65384Smax.romanov@nginx.com } while (1); 6540Sigor@sysoev.ru 65584Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, size); 65684Smax.romanov@nginx.com 65784Smax.romanov@nginx.com nxt_debug(task, "nxt_read_size: %d", (int)*size); 6580Sigor@sysoev.ru 6590Sigor@sysoev.ru return NXT_OK; 6600Sigor@sysoev.ru } 6610Sigor@sysoev.ru 6620Sigor@sysoev.ru 66384Smax.romanov@nginx.com static nxt_int_t 66484Smax.romanov@nginx.com nxt_app_request_content_length(void *ctx, nxt_http_field_t *field, 66584Smax.romanov@nginx.com nxt_log_t *log) 6660Sigor@sysoev.ru { 66784Smax.romanov@nginx.com nxt_str_t *v; 66884Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 66984Smax.romanov@nginx.com nxt_app_request_header_t *h; 6700Sigor@sysoev.ru 67184Smax.romanov@nginx.com c = ctx; 67284Smax.romanov@nginx.com h = &c->r.header; 67384Smax.romanov@nginx.com v = &field->value; 6740Sigor@sysoev.ru 67584Smax.romanov@nginx.com h->content_length = *v; 67684Smax.romanov@nginx.com h->parsed_content_length = nxt_off_t_parse(v->start, v->length); 6770Sigor@sysoev.ru 67884Smax.romanov@nginx.com return NXT_OK; 67984Smax.romanov@nginx.com } 6800Sigor@sysoev.ru 6810Sigor@sysoev.ru 68284Smax.romanov@nginx.com static nxt_int_t 68384Smax.romanov@nginx.com nxt_app_request_content_type(void *ctx, nxt_http_field_t *field, 68484Smax.romanov@nginx.com nxt_log_t *log) 68584Smax.romanov@nginx.com { 68684Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 68784Smax.romanov@nginx.com nxt_app_request_header_t *h; 6880Sigor@sysoev.ru 68984Smax.romanov@nginx.com c = ctx; 69084Smax.romanov@nginx.com h = &c->r.header; 6910Sigor@sysoev.ru 69284Smax.romanov@nginx.com h->content_type = field->value; 6930Sigor@sysoev.ru 69484Smax.romanov@nginx.com return NXT_OK; 69584Smax.romanov@nginx.com } 6960Sigor@sysoev.ru 6974Sigor@sysoev.ru 69884Smax.romanov@nginx.com static nxt_int_t 69984Smax.romanov@nginx.com nxt_app_request_cookie(void *ctx, nxt_http_field_t *field, 70084Smax.romanov@nginx.com nxt_log_t *log) 70184Smax.romanov@nginx.com { 70284Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 70384Smax.romanov@nginx.com nxt_app_request_header_t *h; 7040Sigor@sysoev.ru 70584Smax.romanov@nginx.com c = ctx; 70684Smax.romanov@nginx.com h = &c->r.header; 7070Sigor@sysoev.ru 70884Smax.romanov@nginx.com h->cookie = field->value; 7090Sigor@sysoev.ru 7100Sigor@sysoev.ru return NXT_OK; 7110Sigor@sysoev.ru } 7120Sigor@sysoev.ru 7130Sigor@sysoev.ru 7140Sigor@sysoev.ru static nxt_int_t 71584Smax.romanov@nginx.com nxt_app_request_host(void *ctx, nxt_http_field_t *field, 71684Smax.romanov@nginx.com nxt_log_t *log) 7170Sigor@sysoev.ru { 71884Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 71984Smax.romanov@nginx.com nxt_app_request_header_t *h; 72084Smax.romanov@nginx.com 72184Smax.romanov@nginx.com c = ctx; 72284Smax.romanov@nginx.com h = &c->r.header; 72384Smax.romanov@nginx.com 72484Smax.romanov@nginx.com h->host = field->value; 72584Smax.romanov@nginx.com 72684Smax.romanov@nginx.com return NXT_OK; 72784Smax.romanov@nginx.com } 72884Smax.romanov@nginx.com 7290Sigor@sysoev.ru 73084Smax.romanov@nginx.com static nxt_http_fields_hash_entry_t nxt_app_request_fields[] = { 73184Smax.romanov@nginx.com { nxt_string("Content-Length"), &nxt_app_request_content_length, 0 }, 73284Smax.romanov@nginx.com { nxt_string("Content-Type"), &nxt_app_request_content_type, 0 }, 73384Smax.romanov@nginx.com { nxt_string("Cookie"), &nxt_app_request_cookie, 0 }, 73484Smax.romanov@nginx.com { nxt_string("Host"), &nxt_app_request_host, 0 }, 73584Smax.romanov@nginx.com 73684Smax.romanov@nginx.com { nxt_null_string, NULL, 0 } 73784Smax.romanov@nginx.com }; 73884Smax.romanov@nginx.com 73984Smax.romanov@nginx.com 74084Smax.romanov@nginx.com nxt_int_t 74184Smax.romanov@nginx.com nxt_app_http_req_init(nxt_task_t *task, nxt_app_parse_ctx_t *ctx) 74284Smax.romanov@nginx.com { 74384Smax.romanov@nginx.com nxt_int_t rc; 74484Smax.romanov@nginx.com 74584Smax.romanov@nginx.com ctx->mem_pool = nxt_mp_create(1024, 128, 256, 32); 74684Smax.romanov@nginx.com 74784Smax.romanov@nginx.com rc = nxt_http_parse_request_init(&ctx->parser, ctx->mem_pool); 74884Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 74984Smax.romanov@nginx.com return rc; 7500Sigor@sysoev.ru } 7510Sigor@sysoev.ru 75284Smax.romanov@nginx.com ctx->parser.fields_hash = nxt_app_request_fields_hash; 7530Sigor@sysoev.ru 7540Sigor@sysoev.ru return NXT_OK; 7550Sigor@sysoev.ru } 7560Sigor@sysoev.ru 7570Sigor@sysoev.ru 75884Smax.romanov@nginx.com nxt_int_t 759206Smax.romanov@nginx.com nxt_app_http_req_header_parse(nxt_task_t *task, nxt_app_parse_ctx_t *ctx, 76084Smax.romanov@nginx.com nxt_buf_t *buf) 7610Sigor@sysoev.ru { 76284Smax.romanov@nginx.com nxt_int_t rc; 76384Smax.romanov@nginx.com nxt_app_request_body_t *b; 76484Smax.romanov@nginx.com nxt_http_request_parse_t *p; 76584Smax.romanov@nginx.com nxt_app_request_header_t *h; 7660Sigor@sysoev.ru 76784Smax.romanov@nginx.com p = &ctx->parser; 76884Smax.romanov@nginx.com b = &ctx->r.body; 76984Smax.romanov@nginx.com h = &ctx->r.header; 7700Sigor@sysoev.ru 771206Smax.romanov@nginx.com nxt_assert(h->done == 0); 77284Smax.romanov@nginx.com 773206Smax.romanov@nginx.com rc = nxt_http_parse_request(p, &buf->mem); 7740Sigor@sysoev.ru 775206Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 776206Smax.romanov@nginx.com return rc; 777206Smax.romanov@nginx.com } 7780Sigor@sysoev.ru 779206Smax.romanov@nginx.com rc = nxt_http_fields_process(p->fields, ctx, task->log); 7800Sigor@sysoev.ru 781206Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 782206Smax.romanov@nginx.com return rc; 78313Sigor@sysoev.ru } 78413Sigor@sysoev.ru 785206Smax.romanov@nginx.com h->fields = p->fields; 786206Smax.romanov@nginx.com h->done = 1; 787206Smax.romanov@nginx.com 788206Smax.romanov@nginx.com h->version.start = p->version.str; 789206Smax.romanov@nginx.com h->version.length = nxt_strlen(p->version.str); 790206Smax.romanov@nginx.com 791206Smax.romanov@nginx.com h->method = p->method; 79284Smax.romanov@nginx.com 793206Smax.romanov@nginx.com h->target.start = p->target_start; 794206Smax.romanov@nginx.com h->target.length = p->target_end - p->target_start; 795206Smax.romanov@nginx.com 796206Smax.romanov@nginx.com h->path = p->path; 797206Smax.romanov@nginx.com h->query = p->args; 798206Smax.romanov@nginx.com 799206Smax.romanov@nginx.com if (h->parsed_content_length == 0) { 800206Smax.romanov@nginx.com b->done = 1; 801206Smax.romanov@nginx.com 80284Smax.romanov@nginx.com } 80384Smax.romanov@nginx.com 804206Smax.romanov@nginx.com if (buf->mem.free == buf->mem.pos) { 80584Smax.romanov@nginx.com return NXT_DONE; 80684Smax.romanov@nginx.com } 80784Smax.romanov@nginx.com 808206Smax.romanov@nginx.com b->buf = buf; 809206Smax.romanov@nginx.com b->done = nxt_buf_mem_used_size(&buf->mem) >= 810206Smax.romanov@nginx.com h->parsed_content_length; 811206Smax.romanov@nginx.com 812206Smax.romanov@nginx.com if (b->done == 1) { 813206Smax.romanov@nginx.com b->preread_size = nxt_buf_mem_used_size(&buf->mem); 814206Smax.romanov@nginx.com } 815206Smax.romanov@nginx.com 816206Smax.romanov@nginx.com return NXT_DONE; 817206Smax.romanov@nginx.com } 818206Smax.romanov@nginx.com 819206Smax.romanov@nginx.com 820206Smax.romanov@nginx.com nxt_int_t 821206Smax.romanov@nginx.com nxt_app_http_req_body_read(nxt_task_t *task, nxt_app_parse_ctx_t *ctx, 822206Smax.romanov@nginx.com nxt_buf_t *buf) 823206Smax.romanov@nginx.com { 824206Smax.romanov@nginx.com nxt_app_request_body_t *b; 825206Smax.romanov@nginx.com nxt_app_request_header_t *h; 826206Smax.romanov@nginx.com 827206Smax.romanov@nginx.com b = &ctx->r.body; 828206Smax.romanov@nginx.com h = &ctx->r.header; 829206Smax.romanov@nginx.com 830206Smax.romanov@nginx.com nxt_assert(h->done == 1); 831206Smax.romanov@nginx.com nxt_assert(b->done == 0); 832206Smax.romanov@nginx.com 833206Smax.romanov@nginx.com b->done = nxt_buf_mem_used_size(&buf->mem) + b->preread_size >= 834206Smax.romanov@nginx.com (size_t) h->parsed_content_length; 835206Smax.romanov@nginx.com 836206Smax.romanov@nginx.com if (b->done == 1) { 837206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 838206Smax.romanov@nginx.com } 839206Smax.romanov@nginx.com 840206Smax.romanov@nginx.com return b->done == 1 ? NXT_DONE : NXT_AGAIN; 8410Sigor@sysoev.ru } 8420Sigor@sysoev.ru 8430Sigor@sysoev.ru 84484Smax.romanov@nginx.com nxt_int_t 84584Smax.romanov@nginx.com nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ctx) 8460Sigor@sysoev.ru { 84784Smax.romanov@nginx.com nxt_mp_destroy(ctx->mem_pool); 8480Sigor@sysoev.ru 84984Smax.romanov@nginx.com return NXT_OK; 8500Sigor@sysoev.ru } 8510Sigor@sysoev.ru 8520Sigor@sysoev.ru 85384Smax.romanov@nginx.com nxt_int_t 85484Smax.romanov@nginx.com nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last) 8550Sigor@sysoev.ru { 85684Smax.romanov@nginx.com nxt_int_t rc; 85784Smax.romanov@nginx.com nxt_buf_t *b; 85884Smax.romanov@nginx.com nxt_port_t *port; 85984Smax.romanov@nginx.com 86084Smax.romanov@nginx.com rc = NXT_OK; 8610Sigor@sysoev.ru 86284Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 86384Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 86484Smax.romanov@nginx.com return NXT_ERROR; 86584Smax.romanov@nginx.com } 8660Sigor@sysoev.ru 86784Smax.romanov@nginx.com if (nxt_slow_path(last == 1)) { 86884Smax.romanov@nginx.com do { 86984Smax.romanov@nginx.com b = *msg->buf; 8700Sigor@sysoev.ru 87184Smax.romanov@nginx.com if (b == NULL) { 87284Smax.romanov@nginx.com b = nxt_buf_sync_alloc(port->mem_pool, NXT_BUF_SYNC_LAST); 87384Smax.romanov@nginx.com *msg->buf = b; 87484Smax.romanov@nginx.com break; 87584Smax.romanov@nginx.com } 8760Sigor@sysoev.ru 87784Smax.romanov@nginx.com msg->buf = &b->next; 87884Smax.romanov@nginx.com } while(1); 87984Smax.romanov@nginx.com } 8800Sigor@sysoev.ru 88184Smax.romanov@nginx.com if (nxt_slow_path(msg->write != NULL)) { 88284Smax.romanov@nginx.com rc = nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, 88384Smax.romanov@nginx.com -1, msg->stream, 0, msg->write); 88484Smax.romanov@nginx.com 88584Smax.romanov@nginx.com msg->write = NULL; 88684Smax.romanov@nginx.com msg->buf = &msg->write; 88784Smax.romanov@nginx.com } 88884Smax.romanov@nginx.com 88984Smax.romanov@nginx.com return rc; 8900Sigor@sysoev.ru } 8910Sigor@sysoev.ru 8920Sigor@sysoev.ru 89384Smax.romanov@nginx.com nxt_int_t 89484Smax.romanov@nginx.com nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c, 89584Smax.romanov@nginx.com size_t size) 8960Sigor@sysoev.ru { 897206Smax.romanov@nginx.com size_t free_size, copy_size; 898206Smax.romanov@nginx.com nxt_buf_t *b; 899206Smax.romanov@nginx.com nxt_port_t *port; 900206Smax.romanov@nginx.com 901206Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write_raw: %uz", size); 902206Smax.romanov@nginx.com 903206Smax.romanov@nginx.com while (size > 0) { 904206Smax.romanov@nginx.com b = *msg->buf; 905206Smax.romanov@nginx.com 906206Smax.romanov@nginx.com if (b == NULL) { 907206Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 908206Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 909206Smax.romanov@nginx.com return NXT_ERROR; 910206Smax.romanov@nginx.com } 911206Smax.romanov@nginx.com 912206Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 913206Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 914206Smax.romanov@nginx.com return NXT_ERROR; 915206Smax.romanov@nginx.com } 91684Smax.romanov@nginx.com 917206Smax.romanov@nginx.com *msg->buf = b; 918206Smax.romanov@nginx.com } 919206Smax.romanov@nginx.com 920206Smax.romanov@nginx.com do { 921206Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 922206Smax.romanov@nginx.com 923206Smax.romanov@nginx.com if (free_size > 0) { 924206Smax.romanov@nginx.com copy_size = nxt_min(free_size, size); 925206Smax.romanov@nginx.com 926206Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c, copy_size); 927206Smax.romanov@nginx.com 928206Smax.romanov@nginx.com size -= copy_size; 929206Smax.romanov@nginx.com c += copy_size; 930206Smax.romanov@nginx.com 931206Smax.romanov@nginx.com if (size == 0) { 932206Smax.romanov@nginx.com return NXT_OK; 933206Smax.romanov@nginx.com } 934206Smax.romanov@nginx.com } 935206Smax.romanov@nginx.com } while (nxt_port_mmap_increase_buf(task, b, size, 1) == NXT_OK); 936206Smax.romanov@nginx.com 937206Smax.romanov@nginx.com msg->buf = &b->next; 9380Sigor@sysoev.ru } 9390Sigor@sysoev.ru 94084Smax.romanov@nginx.com return NXT_OK; 9410Sigor@sysoev.ru } 942141Smax.romanov@nginx.com 943141Smax.romanov@nginx.com 944216Sigor@sysoev.ru nxt_app_lang_module_t * 945216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 946216Sigor@sysoev.ru { 947216Sigor@sysoev.ru u_char *p, *end, *version; 948216Sigor@sysoev.ru size_t type_length, version_length; 949216Sigor@sysoev.ru nxt_uint_t i, n; 950216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 951216Sigor@sysoev.ru 952216Sigor@sysoev.ru end = name->start + name->length; 953216Sigor@sysoev.ru version = end; 954216Sigor@sysoev.ru 955216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 956216Sigor@sysoev.ru if (*p == ' ') { 957216Sigor@sysoev.ru version = p + 1; 958216Sigor@sysoev.ru break; 959216Sigor@sysoev.ru } 960216Sigor@sysoev.ru 961216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 962216Sigor@sysoev.ru version = p; 963216Sigor@sysoev.ru break; 964216Sigor@sysoev.ru } 965216Sigor@sysoev.ru } 966216Sigor@sysoev.ru 967216Sigor@sysoev.ru type_length = p - name->start; 968216Sigor@sysoev.ru version_length = end - version; 969216Sigor@sysoev.ru 970216Sigor@sysoev.ru lang = rt->languages->elts; 971216Sigor@sysoev.ru n = rt->languages->nelts; 972216Sigor@sysoev.ru 973216Sigor@sysoev.ru for (i = 0; i < n; i++) { 974216Sigor@sysoev.ru if (nxt_str_eq(&lang[i].type, name->start, type_length) 975216Sigor@sysoev.ru && nxt_str_start(&lang[i].version, version, version_length)) 976216Sigor@sysoev.ru { 977216Sigor@sysoev.ru return &lang[i]; 978216Sigor@sysoev.ru } 979216Sigor@sysoev.ru } 980216Sigor@sysoev.ru 981216Sigor@sysoev.ru return NULL; 982216Sigor@sysoev.ru } 983216Sigor@sysoev.ru 984216Sigor@sysoev.ru 985141Smax.romanov@nginx.com nxt_app_type_t 986141Smax.romanov@nginx.com nxt_app_parse_type(nxt_str_t *str) 987141Smax.romanov@nginx.com { 988141Smax.romanov@nginx.com if (nxt_str_eq(str, "python", 6)) { 989141Smax.romanov@nginx.com return NXT_APP_PYTHON; 990141Smax.romanov@nginx.com 991141Smax.romanov@nginx.com } else if (nxt_str_eq(str, "php", 3)) { 992141Smax.romanov@nginx.com return NXT_APP_PHP; 993141Smax.romanov@nginx.com 994141Smax.romanov@nginx.com } else if (nxt_str_eq(str, "go", 2)) { 995141Smax.romanov@nginx.com return NXT_APP_GO; 996141Smax.romanov@nginx.com 997141Smax.romanov@nginx.com } 998141Smax.romanov@nginx.com 999141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 1000141Smax.romanov@nginx.com } 1001