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> 12240Sigor@sysoev.ru #include <nxt_main_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 40*258Sigor@sysoev.ru static uint32_t compat[] = { 41*258Sigor@sysoev.ru NXT_VERNUM, 42*258Sigor@sysoev.ru }; 43*258Sigor@sysoev.ru 44*258Sigor@sysoev.ru 45216Sigor@sysoev.ru nxt_int_t 46216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data) 47216Sigor@sysoev.ru { 48216Sigor@sysoev.ru nxt_buf_t *b; 49216Sigor@sysoev.ru nxt_port_t *main_port; 50216Sigor@sysoev.ru nxt_runtime_t *rt; 51216Sigor@sysoev.ru 52216Sigor@sysoev.ru nxt_debug(task, "DISCOVERY"); 53216Sigor@sysoev.ru 54233Sigor@sysoev.ru rt = task->thread->runtime; 55216Sigor@sysoev.ru 56233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 57250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 58250Sigor@sysoev.ru exit(1); 59250Sigor@sysoev.ru } 60233Sigor@sysoev.ru 61240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 62216Sigor@sysoev.ru 63216Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 64216Sigor@sysoev.ru 0, -1, b); 65216Sigor@sysoev.ru 66216Sigor@sysoev.ru return NXT_OK; 67216Sigor@sysoev.ru } 68216Sigor@sysoev.ru 69216Sigor@sysoev.ru 70216Sigor@sysoev.ru static void 71216Sigor@sysoev.ru nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 72216Sigor@sysoev.ru { 73216Sigor@sysoev.ru nxt_mp_t *mp; 74216Sigor@sysoev.ru nxt_buf_t *b; 75216Sigor@sysoev.ru 76216Sigor@sysoev.ru b = obj; 77216Sigor@sysoev.ru mp = b->data; 78216Sigor@sysoev.ru 79216Sigor@sysoev.ru nxt_mp_destroy(mp); 80216Sigor@sysoev.ru 81216Sigor@sysoev.ru exit(0); 82216Sigor@sysoev.ru } 83216Sigor@sysoev.ru 84216Sigor@sysoev.ru 85216Sigor@sysoev.ru static nxt_buf_t * 86216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 87216Sigor@sysoev.ru { 88216Sigor@sysoev.ru char *name; 89216Sigor@sysoev.ru u_char *p, *end; 90216Sigor@sysoev.ru size_t size; 91216Sigor@sysoev.ru glob_t glb; 92216Sigor@sysoev.ru nxt_mp_t *mp; 93216Sigor@sysoev.ru nxt_buf_t *b; 94216Sigor@sysoev.ru nxt_int_t ret; 95216Sigor@sysoev.ru nxt_uint_t i, n; 96216Sigor@sysoev.ru nxt_array_t *modules; 97216Sigor@sysoev.ru nxt_module_t *module; 98216Sigor@sysoev.ru 99216Sigor@sysoev.ru b = NULL; 100216Sigor@sysoev.ru 101216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 102216Sigor@sysoev.ru if (mp == NULL) { 103216Sigor@sysoev.ru return b; 104216Sigor@sysoev.ru } 105216Sigor@sysoev.ru 106216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 107216Sigor@sysoev.ru 108250Sigor@sysoev.ru n = glb.gl_pathc; 109250Sigor@sysoev.ru 110250Sigor@sysoev.ru if (ret != 0) { 111250Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 112250Sigor@sysoev.ru "no modules matching: \"%s\" found", path); 113250Sigor@sysoev.ru n = 0; 114250Sigor@sysoev.ru } 115216Sigor@sysoev.ru 116250Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 117250Sigor@sysoev.ru if (modules == NULL) { 118250Sigor@sysoev.ru goto fail; 119250Sigor@sysoev.ru } 120250Sigor@sysoev.ru 121250Sigor@sysoev.ru for (i = 0; i < n; i++) { 122250Sigor@sysoev.ru name = glb.gl_pathv[i]; 123250Sigor@sysoev.ru 124250Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 125250Sigor@sysoev.ru if (ret != NXT_OK) { 126216Sigor@sysoev.ru goto fail; 127216Sigor@sysoev.ru } 128250Sigor@sysoev.ru } 129216Sigor@sysoev.ru 130250Sigor@sysoev.ru size = sizeof("[]") - 1; 131250Sigor@sysoev.ru module = modules->elts; 132250Sigor@sysoev.ru n = modules->nelts; 133216Sigor@sysoev.ru 134250Sigor@sysoev.ru for (i = 0; i < n; i++) { 135250Sigor@sysoev.ru nxt_debug(task, "module: %V %V %V", 136250Sigor@sysoev.ru &module[i].type, &module[i].version, &module[i].file); 137216Sigor@sysoev.ru 138250Sigor@sysoev.ru size += sizeof("{\"type\": \"\",") - 1; 139250Sigor@sysoev.ru size += sizeof(" \"version\": \"\",") - 1; 140250Sigor@sysoev.ru size += sizeof(" \"file\": \"\"},") - 1; 141216Sigor@sysoev.ru 142250Sigor@sysoev.ru size += module[i].type.length 143250Sigor@sysoev.ru + module[i].version.length 144250Sigor@sysoev.ru + module[i].file.length; 145250Sigor@sysoev.ru } 146216Sigor@sysoev.ru 147250Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 148250Sigor@sysoev.ru if (b == NULL) { 149250Sigor@sysoev.ru goto fail; 150250Sigor@sysoev.ru } 151216Sigor@sysoev.ru 152250Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 153216Sigor@sysoev.ru 154250Sigor@sysoev.ru p = b->mem.free; 155250Sigor@sysoev.ru end = b->mem.end; 156250Sigor@sysoev.ru *p++ = '['; 157216Sigor@sysoev.ru 158250Sigor@sysoev.ru for (i = 0; i < n; i++) { 159250Sigor@sysoev.ru p = nxt_sprintf(p, end, 160250Sigor@sysoev.ru "{\"type\": \"%V\", \"version\": \"%V\", \"file\": \"%V\"},", 161250Sigor@sysoev.ru &module[i].type, &module[i].version, &module[i].file); 162250Sigor@sysoev.ru } 163216Sigor@sysoev.ru 164250Sigor@sysoev.ru *p++ = ']'; 165250Sigor@sysoev.ru b->mem.free = p; 166216Sigor@sysoev.ru 167216Sigor@sysoev.ru fail: 168216Sigor@sysoev.ru 169216Sigor@sysoev.ru globfree(&glb); 170216Sigor@sysoev.ru 171216Sigor@sysoev.ru return b; 172216Sigor@sysoev.ru } 173216Sigor@sysoev.ru 174216Sigor@sysoev.ru 175216Sigor@sysoev.ru static nxt_int_t 176216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 177216Sigor@sysoev.ru const char *name) 178216Sigor@sysoev.ru { 179216Sigor@sysoev.ru void *dl; 180216Sigor@sysoev.ru nxt_str_t *s; 181216Sigor@sysoev.ru nxt_int_t ret; 182216Sigor@sysoev.ru nxt_uint_t i, n; 183216Sigor@sysoev.ru nxt_module_t *module; 184216Sigor@sysoev.ru nxt_application_module_t *app; 185216Sigor@sysoev.ru 186216Sigor@sysoev.ru /* 187216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 188216Sigor@sysoev.ru * Any module processing errors are ignored. 189216Sigor@sysoev.ru */ 190216Sigor@sysoev.ru ret = NXT_ERROR; 191216Sigor@sysoev.ru 192216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 193216Sigor@sysoev.ru 194216Sigor@sysoev.ru if (dl == NULL) { 195216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 196216Sigor@sysoev.ru name, dlerror()); 197216Sigor@sysoev.ru return NXT_OK; 198216Sigor@sysoev.ru } 199216Sigor@sysoev.ru 200216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 201216Sigor@sysoev.ru 202216Sigor@sysoev.ru if (app != NULL) { 203*258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "module: %V %V \"%s\"", 204*258Sigor@sysoev.ru &app->type, &app->version, name); 205*258Sigor@sysoev.ru 206*258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 207*258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 208*258Sigor@sysoev.ru { 209*258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 210*258Sigor@sysoev.ru 211*258Sigor@sysoev.ru goto done; 212*258Sigor@sysoev.ru } 213216Sigor@sysoev.ru 214216Sigor@sysoev.ru module = modules->elts; 215216Sigor@sysoev.ru n = modules->nelts; 216216Sigor@sysoev.ru 217216Sigor@sysoev.ru for (i = 0; i < n; i++) { 218*258Sigor@sysoev.ru if (nxt_strstr_eq(&app->type, &module[i].type) 219*258Sigor@sysoev.ru && nxt_strstr_eq(&app->version, &module[i].version)) 220*258Sigor@sysoev.ru { 221216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 222216Sigor@sysoev.ru "ignoring %s module with the same " 223*258Sigor@sysoev.ru "application language version %V %V as in %s", 224*258Sigor@sysoev.ru name, &module[i].type, &module[i].version, 225*258Sigor@sysoev.ru &module[i].file); 226216Sigor@sysoev.ru 227216Sigor@sysoev.ru goto done; 228216Sigor@sysoev.ru } 229216Sigor@sysoev.ru } 230216Sigor@sysoev.ru 231216Sigor@sysoev.ru module = nxt_array_add(modules); 232216Sigor@sysoev.ru if (module == NULL) { 233216Sigor@sysoev.ru goto fail; 234216Sigor@sysoev.ru } 235216Sigor@sysoev.ru 236216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->type, &app->type); 237216Sigor@sysoev.ru if (s == NULL) { 238216Sigor@sysoev.ru goto fail; 239216Sigor@sysoev.ru } 240216Sigor@sysoev.ru 241216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->version, &app->version); 242216Sigor@sysoev.ru if (s == NULL) { 243216Sigor@sysoev.ru goto fail; 244216Sigor@sysoev.ru } 245216Sigor@sysoev.ru 246216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 247216Sigor@sysoev.ru 248216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 249216Sigor@sysoev.ru if (module->file.start == NULL) { 250216Sigor@sysoev.ru goto fail; 251216Sigor@sysoev.ru } 252216Sigor@sysoev.ru 253216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 254216Sigor@sysoev.ru 255216Sigor@sysoev.ru } else { 256216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlsym(\"%s\"), failed: \"%s\"", 257216Sigor@sysoev.ru name, dlerror()); 258216Sigor@sysoev.ru } 259216Sigor@sysoev.ru 260216Sigor@sysoev.ru done: 261216Sigor@sysoev.ru 262216Sigor@sysoev.ru ret = NXT_OK; 263216Sigor@sysoev.ru 264216Sigor@sysoev.ru fail: 265216Sigor@sysoev.ru 266216Sigor@sysoev.ru if (dlclose(dl) != 0) { 267216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlclose(\"%s\"), failed: \"%s\"", 268216Sigor@sysoev.ru name, dlerror()); 269216Sigor@sysoev.ru } 270216Sigor@sysoev.ru 271216Sigor@sysoev.ru return ret; 272216Sigor@sysoev.ru } 273216Sigor@sysoev.ru 274216Sigor@sysoev.ru 2750Sigor@sysoev.ru nxt_int_t 276141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data) 2770Sigor@sysoev.ru { 278216Sigor@sysoev.ru nxt_int_t ret; 279216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 280216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 281141Smax.romanov@nginx.com 282141Smax.romanov@nginx.com app_conf = data; 283141Smax.romanov@nginx.com 284216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 285216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 286216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 287216Sigor@sysoev.ru &app_conf->type); 288216Sigor@sysoev.ru return NXT_ERROR; 289216Sigor@sysoev.ru } 290216Sigor@sysoev.ru 291216Sigor@sysoev.ru nxt_app = lang->module; 292216Sigor@sysoev.ru 293216Sigor@sysoev.ru if (nxt_app == NULL) { 294216Sigor@sysoev.ru nxt_debug(task, "application language module: %V \"%s\"", 295216Sigor@sysoev.ru &lang->version, lang->file); 296216Sigor@sysoev.ru 297216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 298216Sigor@sysoev.ru } 299216Sigor@sysoev.ru 3000Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) { 3010Sigor@sysoev.ru return NXT_ERROR; 3020Sigor@sysoev.ru } 3030Sigor@sysoev.ru 3040Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_cond_create(&nxt_app_cond) != NXT_OK)) { 3050Sigor@sysoev.ru return NXT_ERROR; 3060Sigor@sysoev.ru } 3070Sigor@sysoev.ru 308141Smax.romanov@nginx.com ret = nxt_app->init(task, data); 309141Smax.romanov@nginx.com 310141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 31184Smax.romanov@nginx.com nxt_debug(task, "application init failed"); 312141Smax.romanov@nginx.com 313141Smax.romanov@nginx.com } else { 314141Smax.romanov@nginx.com nxt_debug(task, "application init done"); 31520Sigor@sysoev.ru } 31620Sigor@sysoev.ru 317141Smax.romanov@nginx.com return ret; 31820Sigor@sysoev.ru } 31920Sigor@sysoev.ru 32020Sigor@sysoev.ru 321216Sigor@sysoev.ru static nxt_app_module_t * 322216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 323216Sigor@sysoev.ru { 324216Sigor@sysoev.ru void *dl; 325216Sigor@sysoev.ru 326216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 327216Sigor@sysoev.ru 328216Sigor@sysoev.ru if (dl != NULL) { 329216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 330216Sigor@sysoev.ru } 331216Sigor@sysoev.ru 332216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 333216Sigor@sysoev.ru name, dlerror()); 334216Sigor@sysoev.ru 335216Sigor@sysoev.ru return NULL; 336216Sigor@sysoev.ru } 337216Sigor@sysoev.ru 338216Sigor@sysoev.ru 33984Smax.romanov@nginx.com nxt_int_t 34084Smax.romanov@nginx.com nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt) 3410Sigor@sysoev.ru { 34284Smax.romanov@nginx.com nxt_http_fields_hash_t *hash; 3430Sigor@sysoev.ru 34484Smax.romanov@nginx.com hash = nxt_http_fields_hash_create(nxt_app_request_fields, rt->mem_pool); 34584Smax.romanov@nginx.com if (nxt_slow_path(hash == NULL)) { 34684Smax.romanov@nginx.com return NXT_ERROR; 3470Sigor@sysoev.ru } 3480Sigor@sysoev.ru 34984Smax.romanov@nginx.com nxt_app_request_fields_hash = hash; 3500Sigor@sysoev.ru 35184Smax.romanov@nginx.com return NXT_OK; 35284Smax.romanov@nginx.com } 3534Sigor@sysoev.ru 3540Sigor@sysoev.ru 35584Smax.romanov@nginx.com void 35684Smax.romanov@nginx.com nxt_port_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 35784Smax.romanov@nginx.com { 35884Smax.romanov@nginx.com size_t dump_size; 35984Smax.romanov@nginx.com nxt_buf_t *b; 36084Smax.romanov@nginx.com nxt_port_t *port; 36184Smax.romanov@nginx.com nxt_app_rmsg_t rmsg = { msg->buf }; 36284Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 3630Sigor@sysoev.ru 36484Smax.romanov@nginx.com b = msg->buf; 36584Smax.romanov@nginx.com dump_size = b->mem.free - b->mem.pos; 3660Sigor@sysoev.ru 36784Smax.romanov@nginx.com if (dump_size > 300) { 36884Smax.romanov@nginx.com dump_size = 300; 36984Smax.romanov@nginx.com } 3700Sigor@sysoev.ru 37184Smax.romanov@nginx.com nxt_debug(task, "app data: %*s ...", dump_size, b->mem.pos); 3720Sigor@sysoev.ru 37384Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 37484Smax.romanov@nginx.com msg->port_msg.reply_port); 37584Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 37684Smax.romanov@nginx.com // 37784Smax.romanov@nginx.com } 3784Sigor@sysoev.ru 37984Smax.romanov@nginx.com wmsg.port = port; 38084Smax.romanov@nginx.com wmsg.write = NULL; 38184Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 38284Smax.romanov@nginx.com wmsg.stream = msg->port_msg.stream; 3830Sigor@sysoev.ru 38484Smax.romanov@nginx.com nxt_app->run(task, &rmsg, &wmsg); 3850Sigor@sysoev.ru } 3860Sigor@sysoev.ru 3870Sigor@sysoev.ru 38884Smax.romanov@nginx.com nxt_inline nxt_port_t * 38984Smax.romanov@nginx.com nxt_app_msg_get_port(nxt_task_t *task, nxt_app_wmsg_t *msg) 3900Sigor@sysoev.ru { 39184Smax.romanov@nginx.com return msg->port; 39284Smax.romanov@nginx.com } 39384Smax.romanov@nginx.com 39484Smax.romanov@nginx.com 39584Smax.romanov@nginx.com u_char * 39684Smax.romanov@nginx.com nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, size_t size) 39784Smax.romanov@nginx.com { 39884Smax.romanov@nginx.com size_t free_size; 39984Smax.romanov@nginx.com u_char *res; 40084Smax.romanov@nginx.com nxt_buf_t *b; 40184Smax.romanov@nginx.com nxt_port_t *port; 4020Sigor@sysoev.ru 40384Smax.romanov@nginx.com res = NULL; 40484Smax.romanov@nginx.com 40584Smax.romanov@nginx.com do { 40684Smax.romanov@nginx.com b = *msg->buf; 4070Sigor@sysoev.ru 40884Smax.romanov@nginx.com if (b == NULL) { 40984Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 41084Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 41184Smax.romanov@nginx.com return NULL; 41284Smax.romanov@nginx.com } 41384Smax.romanov@nginx.com 41484Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 41584Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 41684Smax.romanov@nginx.com return NULL; 41784Smax.romanov@nginx.com } 4180Sigor@sysoev.ru 41984Smax.romanov@nginx.com *msg->buf = b; 42084Smax.romanov@nginx.com 42184Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4220Sigor@sysoev.ru 42384Smax.romanov@nginx.com if (nxt_slow_path(free_size < size)) { 42484Smax.romanov@nginx.com nxt_debug(task, "requested buffer too big (%z < %z)", 42584Smax.romanov@nginx.com free_size, size); 42684Smax.romanov@nginx.com return NULL; 42784Smax.romanov@nginx.com } 42884Smax.romanov@nginx.com 42984Smax.romanov@nginx.com } 43084Smax.romanov@nginx.com 43184Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4320Sigor@sysoev.ru 43384Smax.romanov@nginx.com if (free_size >= size) { 43484Smax.romanov@nginx.com res = b->mem.free; 43584Smax.romanov@nginx.com b->mem.free += size; 43684Smax.romanov@nginx.com 43784Smax.romanov@nginx.com return res; 43884Smax.romanov@nginx.com } 4391Sigor@sysoev.ru 440206Smax.romanov@nginx.com if (nxt_port_mmap_increase_buf(task, b, size, size) == NXT_OK) { 44184Smax.romanov@nginx.com res = b->mem.free; 44284Smax.romanov@nginx.com b->mem.free += size; 4430Sigor@sysoev.ru 44484Smax.romanov@nginx.com return res; 44584Smax.romanov@nginx.com } 44684Smax.romanov@nginx.com 44784Smax.romanov@nginx.com msg->buf = &b->next; 44884Smax.romanov@nginx.com } while(1); 4490Sigor@sysoev.ru } 4500Sigor@sysoev.ru 4510Sigor@sysoev.ru 45284Smax.romanov@nginx.com nxt_int_t 45384Smax.romanov@nginx.com nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, u_char *c, size_t size) 4540Sigor@sysoev.ru { 45584Smax.romanov@nginx.com u_char *dst; 45684Smax.romanov@nginx.com size_t dst_length; 4570Sigor@sysoev.ru 45884Smax.romanov@nginx.com if (c != NULL) { 45984Smax.romanov@nginx.com dst_length = size + (size < 128 ? 1 : 4) + 1; 4600Sigor@sysoev.ru 46184Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 46284Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 46384Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 46484Smax.romanov@nginx.com dst_length); 46584Smax.romanov@nginx.com return NXT_ERROR; 4660Sigor@sysoev.ru } 4670Sigor@sysoev.ru 46884Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, size + 1); /* +1 for trailing 0 */ 4690Sigor@sysoev.ru 47084Smax.romanov@nginx.com nxt_memcpy(dst, c, size); 47184Smax.romanov@nginx.com dst[size] = 0; 4720Sigor@sysoev.ru 47384Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: %uz %*s", size, (int)size, c); 47484Smax.romanov@nginx.com } else { 47584Smax.romanov@nginx.com dst_length = 1; 4760Sigor@sysoev.ru 47784Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 47884Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 47984Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 48084Smax.romanov@nginx.com dst_length); 48184Smax.romanov@nginx.com return NXT_ERROR; 4820Sigor@sysoev.ru } 4830Sigor@sysoev.ru 48484Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, 0); 48584Smax.romanov@nginx.com 48684Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: NULL"); 4870Sigor@sysoev.ru } 4880Sigor@sysoev.ru 48984Smax.romanov@nginx.com return NXT_OK; 4900Sigor@sysoev.ru } 4910Sigor@sysoev.ru 4920Sigor@sysoev.ru 49384Smax.romanov@nginx.com nxt_int_t 49484Smax.romanov@nginx.com nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, nxt_app_wmsg_t *msg, 49584Smax.romanov@nginx.com const nxt_str_t *prefix, const nxt_str_t *v) 4960Sigor@sysoev.ru { 49784Smax.romanov@nginx.com u_char *dst, *src; 49884Smax.romanov@nginx.com size_t i, length, dst_length; 49984Smax.romanov@nginx.com 50084Smax.romanov@nginx.com length = prefix->length + v->length; 5010Sigor@sysoev.ru 50284Smax.romanov@nginx.com dst_length = length + (length < 128 ? 1 : 4) + 1; 50384Smax.romanov@nginx.com 50484Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 50584Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 50684Smax.romanov@nginx.com return NXT_ERROR; 5070Sigor@sysoev.ru } 5080Sigor@sysoev.ru 50984Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, length + 1); /* +1 for trailing 0 */ 51084Smax.romanov@nginx.com 51184Smax.romanov@nginx.com nxt_memcpy(dst, prefix->start, prefix->length); 51284Smax.romanov@nginx.com dst += prefix->length; 5130Sigor@sysoev.ru 51484Smax.romanov@nginx.com src = v->start; 51584Smax.romanov@nginx.com for (i = 0; i < v->length; i++, dst++, src++) { 51684Smax.romanov@nginx.com 51784Smax.romanov@nginx.com if (*src >= 'a' && *src <= 'z') { 51884Smax.romanov@nginx.com *dst = *src & ~0x20; 51984Smax.romanov@nginx.com continue; 5200Sigor@sysoev.ru } 5210Sigor@sysoev.ru 52284Smax.romanov@nginx.com if (*src == '-') { 52384Smax.romanov@nginx.com *dst = '_'; 52484Smax.romanov@nginx.com continue; 5250Sigor@sysoev.ru } 5260Sigor@sysoev.ru 52784Smax.romanov@nginx.com *dst = *src; 5280Sigor@sysoev.ru } 5290Sigor@sysoev.ru 53084Smax.romanov@nginx.com *dst = 0; 5310Sigor@sysoev.ru 53284Smax.romanov@nginx.com return NXT_OK; 5330Sigor@sysoev.ru } 5340Sigor@sysoev.ru 5350Sigor@sysoev.ru 53684Smax.romanov@nginx.com nxt_int_t 53784Smax.romanov@nginx.com nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, nxt_str_t *str) 5380Sigor@sysoev.ru { 53984Smax.romanov@nginx.com size_t length; 54084Smax.romanov@nginx.com nxt_buf_t *buf; 5410Sigor@sysoev.ru 54284Smax.romanov@nginx.com do { 54384Smax.romanov@nginx.com buf = msg->buf; 54484Smax.romanov@nginx.com 54584Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 54684Smax.romanov@nginx.com return NXT_DONE; 5470Sigor@sysoev.ru } 5480Sigor@sysoev.ru 54984Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 55084Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 55184Smax.romanov@nginx.com msg->buf = buf->next; 55284Smax.romanov@nginx.com continue; 55384Smax.romanov@nginx.com } 55484Smax.romanov@nginx.com return NXT_ERROR; 5550Sigor@sysoev.ru } 5560Sigor@sysoev.ru 55784Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 55884Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 55984Smax.romanov@nginx.com return NXT_ERROR; 56084Smax.romanov@nginx.com } 56184Smax.romanov@nginx.com } 5620Sigor@sysoev.ru 56384Smax.romanov@nginx.com break; 56484Smax.romanov@nginx.com } while (1); 5650Sigor@sysoev.ru 56684Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, &length); 56784Smax.romanov@nginx.com 56884Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < (intptr_t)length)) 56984Smax.romanov@nginx.com { 57084Smax.romanov@nginx.com return NXT_ERROR; 5710Sigor@sysoev.ru } 5720Sigor@sysoev.ru 57384Smax.romanov@nginx.com if (length > 0) { 57484Smax.romanov@nginx.com str->start = buf->mem.pos; 57584Smax.romanov@nginx.com str->length = length - 1; 5760Sigor@sysoev.ru 57784Smax.romanov@nginx.com buf->mem.pos += length; 5780Sigor@sysoev.ru 57984Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: %d %*s", (int)length - 1, 58084Smax.romanov@nginx.com (int)length - 1, str->start); 58184Smax.romanov@nginx.com } else { 58284Smax.romanov@nginx.com str->start = NULL; 58384Smax.romanov@nginx.com str->length = 0; 5840Sigor@sysoev.ru 58584Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: NULL"); 5860Sigor@sysoev.ru } 5870Sigor@sysoev.ru 5880Sigor@sysoev.ru return NXT_OK; 5890Sigor@sysoev.ru } 5900Sigor@sysoev.ru 5910Sigor@sysoev.ru 592206Smax.romanov@nginx.com size_t 593206Smax.romanov@nginx.com nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *dst, 594206Smax.romanov@nginx.com size_t size) 595206Smax.romanov@nginx.com { 596206Smax.romanov@nginx.com size_t res, read_size; 597206Smax.romanov@nginx.com nxt_buf_t *buf; 598206Smax.romanov@nginx.com 599206Smax.romanov@nginx.com res = 0; 600206Smax.romanov@nginx.com 601206Smax.romanov@nginx.com while (size > 0) { 602206Smax.romanov@nginx.com buf = msg->buf; 603206Smax.romanov@nginx.com 604206Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 605206Smax.romanov@nginx.com break; 606206Smax.romanov@nginx.com } 607206Smax.romanov@nginx.com 608206Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 609206Smax.romanov@nginx.com msg->buf = buf->next; 610206Smax.romanov@nginx.com continue; 611206Smax.romanov@nginx.com } 612206Smax.romanov@nginx.com 613206Smax.romanov@nginx.com read_size = nxt_buf_mem_used_size(&buf->mem); 614206Smax.romanov@nginx.com read_size = nxt_min(read_size, size); 615206Smax.romanov@nginx.com 616206Smax.romanov@nginx.com dst = nxt_cpymem(dst, buf->mem.pos, read_size); 617206Smax.romanov@nginx.com 618206Smax.romanov@nginx.com size -= read_size; 619206Smax.romanov@nginx.com buf->mem.pos += read_size; 620206Smax.romanov@nginx.com res += read_size; 621206Smax.romanov@nginx.com } 622206Smax.romanov@nginx.com 623206Smax.romanov@nginx.com nxt_debug(task, "nxt_read_raw: %uz", res); 624206Smax.romanov@nginx.com 625206Smax.romanov@nginx.com return res; 626206Smax.romanov@nginx.com } 627206Smax.romanov@nginx.com 628206Smax.romanov@nginx.com 62984Smax.romanov@nginx.com nxt_int_t 63084Smax.romanov@nginx.com nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_str_t *n, 63184Smax.romanov@nginx.com nxt_str_t *v) 6320Sigor@sysoev.ru { 63384Smax.romanov@nginx.com nxt_int_t rc; 6340Sigor@sysoev.ru 63584Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, n); 63684Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 63784Smax.romanov@nginx.com return rc; 6380Sigor@sysoev.ru } 6390Sigor@sysoev.ru 64084Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, v); 64184Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 64284Smax.romanov@nginx.com return rc; 64384Smax.romanov@nginx.com } 6440Sigor@sysoev.ru 64584Smax.romanov@nginx.com return rc; 6460Sigor@sysoev.ru } 6470Sigor@sysoev.ru 6480Sigor@sysoev.ru 6490Sigor@sysoev.ru nxt_int_t 65084Smax.romanov@nginx.com nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 6510Sigor@sysoev.ru { 65284Smax.romanov@nginx.com nxt_buf_t *buf; 6530Sigor@sysoev.ru 65484Smax.romanov@nginx.com do { 65584Smax.romanov@nginx.com buf = msg->buf; 6560Sigor@sysoev.ru 65784Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 65884Smax.romanov@nginx.com return NXT_DONE; 65984Smax.romanov@nginx.com } 6600Sigor@sysoev.ru 66184Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 66284Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 66384Smax.romanov@nginx.com msg->buf = buf->next; 66484Smax.romanov@nginx.com continue; 66584Smax.romanov@nginx.com } 6660Sigor@sysoev.ru return NXT_ERROR; 6670Sigor@sysoev.ru } 6680Sigor@sysoev.ru 66984Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 67084Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 67184Smax.romanov@nginx.com return NXT_ERROR; 67284Smax.romanov@nginx.com } 67384Smax.romanov@nginx.com } 6740Sigor@sysoev.ru 67584Smax.romanov@nginx.com break; 67684Smax.romanov@nginx.com } while (1); 6770Sigor@sysoev.ru 67884Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, size); 67984Smax.romanov@nginx.com 68084Smax.romanov@nginx.com nxt_debug(task, "nxt_read_size: %d", (int)*size); 6810Sigor@sysoev.ru 6820Sigor@sysoev.ru return NXT_OK; 6830Sigor@sysoev.ru } 6840Sigor@sysoev.ru 6850Sigor@sysoev.ru 68684Smax.romanov@nginx.com static nxt_int_t 68784Smax.romanov@nginx.com nxt_app_request_content_length(void *ctx, nxt_http_field_t *field, 68884Smax.romanov@nginx.com nxt_log_t *log) 6890Sigor@sysoev.ru { 69084Smax.romanov@nginx.com nxt_str_t *v; 69184Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 69284Smax.romanov@nginx.com nxt_app_request_header_t *h; 6930Sigor@sysoev.ru 69484Smax.romanov@nginx.com c = ctx; 69584Smax.romanov@nginx.com h = &c->r.header; 69684Smax.romanov@nginx.com v = &field->value; 6970Sigor@sysoev.ru 69884Smax.romanov@nginx.com h->content_length = *v; 69984Smax.romanov@nginx.com h->parsed_content_length = nxt_off_t_parse(v->start, v->length); 7000Sigor@sysoev.ru 70184Smax.romanov@nginx.com return NXT_OK; 70284Smax.romanov@nginx.com } 7030Sigor@sysoev.ru 7040Sigor@sysoev.ru 70584Smax.romanov@nginx.com static nxt_int_t 70684Smax.romanov@nginx.com nxt_app_request_content_type(void *ctx, nxt_http_field_t *field, 70784Smax.romanov@nginx.com nxt_log_t *log) 70884Smax.romanov@nginx.com { 70984Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 71084Smax.romanov@nginx.com nxt_app_request_header_t *h; 7110Sigor@sysoev.ru 71284Smax.romanov@nginx.com c = ctx; 71384Smax.romanov@nginx.com h = &c->r.header; 7140Sigor@sysoev.ru 71584Smax.romanov@nginx.com h->content_type = field->value; 7160Sigor@sysoev.ru 71784Smax.romanov@nginx.com return NXT_OK; 71884Smax.romanov@nginx.com } 7190Sigor@sysoev.ru 7204Sigor@sysoev.ru 72184Smax.romanov@nginx.com static nxt_int_t 72284Smax.romanov@nginx.com nxt_app_request_cookie(void *ctx, nxt_http_field_t *field, 72384Smax.romanov@nginx.com nxt_log_t *log) 72484Smax.romanov@nginx.com { 72584Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 72684Smax.romanov@nginx.com nxt_app_request_header_t *h; 7270Sigor@sysoev.ru 72884Smax.romanov@nginx.com c = ctx; 72984Smax.romanov@nginx.com h = &c->r.header; 7300Sigor@sysoev.ru 73184Smax.romanov@nginx.com h->cookie = field->value; 7320Sigor@sysoev.ru 7330Sigor@sysoev.ru return NXT_OK; 7340Sigor@sysoev.ru } 7350Sigor@sysoev.ru 7360Sigor@sysoev.ru 7370Sigor@sysoev.ru static nxt_int_t 73884Smax.romanov@nginx.com nxt_app_request_host(void *ctx, nxt_http_field_t *field, 73984Smax.romanov@nginx.com nxt_log_t *log) 7400Sigor@sysoev.ru { 74184Smax.romanov@nginx.com nxt_app_parse_ctx_t *c; 74284Smax.romanov@nginx.com nxt_app_request_header_t *h; 74384Smax.romanov@nginx.com 74484Smax.romanov@nginx.com c = ctx; 74584Smax.romanov@nginx.com h = &c->r.header; 74684Smax.romanov@nginx.com 74784Smax.romanov@nginx.com h->host = field->value; 74884Smax.romanov@nginx.com 74984Smax.romanov@nginx.com return NXT_OK; 75084Smax.romanov@nginx.com } 75184Smax.romanov@nginx.com 7520Sigor@sysoev.ru 75384Smax.romanov@nginx.com static nxt_http_fields_hash_entry_t nxt_app_request_fields[] = { 75484Smax.romanov@nginx.com { nxt_string("Content-Length"), &nxt_app_request_content_length, 0 }, 75584Smax.romanov@nginx.com { nxt_string("Content-Type"), &nxt_app_request_content_type, 0 }, 75684Smax.romanov@nginx.com { nxt_string("Cookie"), &nxt_app_request_cookie, 0 }, 75784Smax.romanov@nginx.com { nxt_string("Host"), &nxt_app_request_host, 0 }, 75884Smax.romanov@nginx.com 75984Smax.romanov@nginx.com { nxt_null_string, NULL, 0 } 76084Smax.romanov@nginx.com }; 76184Smax.romanov@nginx.com 76284Smax.romanov@nginx.com 76384Smax.romanov@nginx.com nxt_int_t 76484Smax.romanov@nginx.com nxt_app_http_req_init(nxt_task_t *task, nxt_app_parse_ctx_t *ctx) 76584Smax.romanov@nginx.com { 76684Smax.romanov@nginx.com nxt_int_t rc; 76784Smax.romanov@nginx.com 76884Smax.romanov@nginx.com ctx->mem_pool = nxt_mp_create(1024, 128, 256, 32); 76984Smax.romanov@nginx.com 77084Smax.romanov@nginx.com rc = nxt_http_parse_request_init(&ctx->parser, ctx->mem_pool); 77184Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 77284Smax.romanov@nginx.com return rc; 7730Sigor@sysoev.ru } 7740Sigor@sysoev.ru 77584Smax.romanov@nginx.com ctx->parser.fields_hash = nxt_app_request_fields_hash; 7760Sigor@sysoev.ru 7770Sigor@sysoev.ru return NXT_OK; 7780Sigor@sysoev.ru } 7790Sigor@sysoev.ru 7800Sigor@sysoev.ru 78184Smax.romanov@nginx.com nxt_int_t 782206Smax.romanov@nginx.com nxt_app_http_req_header_parse(nxt_task_t *task, nxt_app_parse_ctx_t *ctx, 78384Smax.romanov@nginx.com nxt_buf_t *buf) 7840Sigor@sysoev.ru { 78584Smax.romanov@nginx.com nxt_int_t rc; 78684Smax.romanov@nginx.com nxt_app_request_body_t *b; 78784Smax.romanov@nginx.com nxt_http_request_parse_t *p; 78884Smax.romanov@nginx.com nxt_app_request_header_t *h; 7890Sigor@sysoev.ru 79084Smax.romanov@nginx.com p = &ctx->parser; 79184Smax.romanov@nginx.com b = &ctx->r.body; 79284Smax.romanov@nginx.com h = &ctx->r.header; 7930Sigor@sysoev.ru 794206Smax.romanov@nginx.com nxt_assert(h->done == 0); 79584Smax.romanov@nginx.com 796206Smax.romanov@nginx.com rc = nxt_http_parse_request(p, &buf->mem); 7970Sigor@sysoev.ru 798206Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_DONE)) { 799206Smax.romanov@nginx.com return rc; 800206Smax.romanov@nginx.com } 8010Sigor@sysoev.ru 802206Smax.romanov@nginx.com rc = nxt_http_fields_process(p->fields, ctx, task->log); 8030Sigor@sysoev.ru 804206Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 805206Smax.romanov@nginx.com return rc; 80613Sigor@sysoev.ru } 80713Sigor@sysoev.ru 808206Smax.romanov@nginx.com h->fields = p->fields; 809206Smax.romanov@nginx.com h->done = 1; 810206Smax.romanov@nginx.com 811206Smax.romanov@nginx.com h->version.start = p->version.str; 812206Smax.romanov@nginx.com h->version.length = nxt_strlen(p->version.str); 813206Smax.romanov@nginx.com 814206Smax.romanov@nginx.com h->method = p->method; 81584Smax.romanov@nginx.com 816206Smax.romanov@nginx.com h->target.start = p->target_start; 817206Smax.romanov@nginx.com h->target.length = p->target_end - p->target_start; 818206Smax.romanov@nginx.com 819206Smax.romanov@nginx.com h->path = p->path; 820206Smax.romanov@nginx.com h->query = p->args; 821206Smax.romanov@nginx.com 822206Smax.romanov@nginx.com if (h->parsed_content_length == 0) { 823206Smax.romanov@nginx.com b->done = 1; 824206Smax.romanov@nginx.com 82584Smax.romanov@nginx.com } 82684Smax.romanov@nginx.com 827206Smax.romanov@nginx.com if (buf->mem.free == buf->mem.pos) { 82884Smax.romanov@nginx.com return NXT_DONE; 82984Smax.romanov@nginx.com } 83084Smax.romanov@nginx.com 831206Smax.romanov@nginx.com b->buf = buf; 832206Smax.romanov@nginx.com b->done = nxt_buf_mem_used_size(&buf->mem) >= 833206Smax.romanov@nginx.com h->parsed_content_length; 834206Smax.romanov@nginx.com 835206Smax.romanov@nginx.com if (b->done == 1) { 836206Smax.romanov@nginx.com b->preread_size = nxt_buf_mem_used_size(&buf->mem); 837206Smax.romanov@nginx.com } 838206Smax.romanov@nginx.com 839206Smax.romanov@nginx.com return NXT_DONE; 840206Smax.romanov@nginx.com } 841206Smax.romanov@nginx.com 842206Smax.romanov@nginx.com 843206Smax.romanov@nginx.com nxt_int_t 844206Smax.romanov@nginx.com nxt_app_http_req_body_read(nxt_task_t *task, nxt_app_parse_ctx_t *ctx, 845206Smax.romanov@nginx.com nxt_buf_t *buf) 846206Smax.romanov@nginx.com { 847206Smax.romanov@nginx.com nxt_app_request_body_t *b; 848206Smax.romanov@nginx.com nxt_app_request_header_t *h; 849206Smax.romanov@nginx.com 850206Smax.romanov@nginx.com b = &ctx->r.body; 851206Smax.romanov@nginx.com h = &ctx->r.header; 852206Smax.romanov@nginx.com 853206Smax.romanov@nginx.com nxt_assert(h->done == 1); 854206Smax.romanov@nginx.com nxt_assert(b->done == 0); 855206Smax.romanov@nginx.com 856206Smax.romanov@nginx.com b->done = nxt_buf_mem_used_size(&buf->mem) + b->preread_size >= 857206Smax.romanov@nginx.com (size_t) h->parsed_content_length; 858206Smax.romanov@nginx.com 859206Smax.romanov@nginx.com if (b->done == 1) { 860206Smax.romanov@nginx.com b->preread_size += nxt_buf_mem_used_size(&buf->mem); 861206Smax.romanov@nginx.com } 862206Smax.romanov@nginx.com 863206Smax.romanov@nginx.com return b->done == 1 ? NXT_DONE : NXT_AGAIN; 8640Sigor@sysoev.ru } 8650Sigor@sysoev.ru 8660Sigor@sysoev.ru 86784Smax.romanov@nginx.com nxt_int_t 86884Smax.romanov@nginx.com nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ctx) 8690Sigor@sysoev.ru { 87084Smax.romanov@nginx.com nxt_mp_destroy(ctx->mem_pool); 8710Sigor@sysoev.ru 87284Smax.romanov@nginx.com return NXT_OK; 8730Sigor@sysoev.ru } 8740Sigor@sysoev.ru 8750Sigor@sysoev.ru 87684Smax.romanov@nginx.com nxt_int_t 87784Smax.romanov@nginx.com nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last) 8780Sigor@sysoev.ru { 87984Smax.romanov@nginx.com nxt_int_t rc; 88084Smax.romanov@nginx.com nxt_buf_t *b; 88184Smax.romanov@nginx.com nxt_port_t *port; 88284Smax.romanov@nginx.com 88384Smax.romanov@nginx.com rc = NXT_OK; 8840Sigor@sysoev.ru 88584Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 88684Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 88784Smax.romanov@nginx.com return NXT_ERROR; 88884Smax.romanov@nginx.com } 8890Sigor@sysoev.ru 89084Smax.romanov@nginx.com if (nxt_slow_path(last == 1)) { 89184Smax.romanov@nginx.com do { 89284Smax.romanov@nginx.com b = *msg->buf; 8930Sigor@sysoev.ru 89484Smax.romanov@nginx.com if (b == NULL) { 89584Smax.romanov@nginx.com b = nxt_buf_sync_alloc(port->mem_pool, NXT_BUF_SYNC_LAST); 89684Smax.romanov@nginx.com *msg->buf = b; 89784Smax.romanov@nginx.com break; 89884Smax.romanov@nginx.com } 8990Sigor@sysoev.ru 90084Smax.romanov@nginx.com msg->buf = &b->next; 90184Smax.romanov@nginx.com } while(1); 90284Smax.romanov@nginx.com } 9030Sigor@sysoev.ru 90484Smax.romanov@nginx.com if (nxt_slow_path(msg->write != NULL)) { 90584Smax.romanov@nginx.com rc = nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA, 90684Smax.romanov@nginx.com -1, msg->stream, 0, msg->write); 90784Smax.romanov@nginx.com 90884Smax.romanov@nginx.com msg->write = NULL; 90984Smax.romanov@nginx.com msg->buf = &msg->write; 91084Smax.romanov@nginx.com } 91184Smax.romanov@nginx.com 91284Smax.romanov@nginx.com return rc; 9130Sigor@sysoev.ru } 9140Sigor@sysoev.ru 9150Sigor@sysoev.ru 91684Smax.romanov@nginx.com nxt_int_t 91784Smax.romanov@nginx.com nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c, 91884Smax.romanov@nginx.com size_t size) 9190Sigor@sysoev.ru { 920206Smax.romanov@nginx.com size_t free_size, copy_size; 921206Smax.romanov@nginx.com nxt_buf_t *b; 922206Smax.romanov@nginx.com nxt_port_t *port; 923206Smax.romanov@nginx.com 924206Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write_raw: %uz", size); 925206Smax.romanov@nginx.com 926206Smax.romanov@nginx.com while (size > 0) { 927206Smax.romanov@nginx.com b = *msg->buf; 928206Smax.romanov@nginx.com 929206Smax.romanov@nginx.com if (b == NULL) { 930206Smax.romanov@nginx.com port = nxt_app_msg_get_port(task, msg); 931206Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 932206Smax.romanov@nginx.com return NXT_ERROR; 933206Smax.romanov@nginx.com } 934206Smax.romanov@nginx.com 935206Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, port, size); 936206Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 937206Smax.romanov@nginx.com return NXT_ERROR; 938206Smax.romanov@nginx.com } 93984Smax.romanov@nginx.com 940206Smax.romanov@nginx.com *msg->buf = b; 941206Smax.romanov@nginx.com } 942206Smax.romanov@nginx.com 943206Smax.romanov@nginx.com do { 944206Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 945206Smax.romanov@nginx.com 946206Smax.romanov@nginx.com if (free_size > 0) { 947206Smax.romanov@nginx.com copy_size = nxt_min(free_size, size); 948206Smax.romanov@nginx.com 949206Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c, copy_size); 950206Smax.romanov@nginx.com 951206Smax.romanov@nginx.com size -= copy_size; 952206Smax.romanov@nginx.com c += copy_size; 953206Smax.romanov@nginx.com 954206Smax.romanov@nginx.com if (size == 0) { 955206Smax.romanov@nginx.com return NXT_OK; 956206Smax.romanov@nginx.com } 957206Smax.romanov@nginx.com } 958206Smax.romanov@nginx.com } while (nxt_port_mmap_increase_buf(task, b, size, 1) == NXT_OK); 959206Smax.romanov@nginx.com 960206Smax.romanov@nginx.com msg->buf = &b->next; 9610Sigor@sysoev.ru } 9620Sigor@sysoev.ru 96384Smax.romanov@nginx.com return NXT_OK; 9640Sigor@sysoev.ru } 965141Smax.romanov@nginx.com 966141Smax.romanov@nginx.com 967216Sigor@sysoev.ru nxt_app_lang_module_t * 968216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 969216Sigor@sysoev.ru { 970216Sigor@sysoev.ru u_char *p, *end, *version; 971216Sigor@sysoev.ru size_t type_length, version_length; 972216Sigor@sysoev.ru nxt_uint_t i, n; 973216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 974216Sigor@sysoev.ru 975216Sigor@sysoev.ru end = name->start + name->length; 976216Sigor@sysoev.ru version = end; 977216Sigor@sysoev.ru 978216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 979216Sigor@sysoev.ru if (*p == ' ') { 980216Sigor@sysoev.ru version = p + 1; 981216Sigor@sysoev.ru break; 982216Sigor@sysoev.ru } 983216Sigor@sysoev.ru 984216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 985216Sigor@sysoev.ru version = p; 986216Sigor@sysoev.ru break; 987216Sigor@sysoev.ru } 988216Sigor@sysoev.ru } 989216Sigor@sysoev.ru 990216Sigor@sysoev.ru type_length = p - name->start; 991216Sigor@sysoev.ru version_length = end - version; 992216Sigor@sysoev.ru 993216Sigor@sysoev.ru lang = rt->languages->elts; 994216Sigor@sysoev.ru n = rt->languages->nelts; 995216Sigor@sysoev.ru 996216Sigor@sysoev.ru for (i = 0; i < n; i++) { 997216Sigor@sysoev.ru if (nxt_str_eq(&lang[i].type, name->start, type_length) 998216Sigor@sysoev.ru && nxt_str_start(&lang[i].version, version, version_length)) 999216Sigor@sysoev.ru { 1000216Sigor@sysoev.ru return &lang[i]; 1001216Sigor@sysoev.ru } 1002216Sigor@sysoev.ru } 1003216Sigor@sysoev.ru 1004216Sigor@sysoev.ru return NULL; 1005216Sigor@sysoev.ru } 1006216Sigor@sysoev.ru 1007216Sigor@sysoev.ru 1008141Smax.romanov@nginx.com nxt_app_type_t 1009141Smax.romanov@nginx.com nxt_app_parse_type(nxt_str_t *str) 1010141Smax.romanov@nginx.com { 1011141Smax.romanov@nginx.com if (nxt_str_eq(str, "python", 6)) { 1012141Smax.romanov@nginx.com return NXT_APP_PYTHON; 1013141Smax.romanov@nginx.com 1014141Smax.romanov@nginx.com } else if (nxt_str_eq(str, "php", 3)) { 1015141Smax.romanov@nginx.com return NXT_APP_PHP; 1016141Smax.romanov@nginx.com 1017141Smax.romanov@nginx.com } else if (nxt_str_eq(str, "go", 2)) { 1018141Smax.romanov@nginx.com return NXT_APP_GO; 1019141Smax.romanov@nginx.com 1020141Smax.romanov@nginx.com } 1021141Smax.romanov@nginx.com 1022141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 1023141Smax.romanov@nginx.com } 1024