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> 11240Sigor@sysoev.ru #include <nxt_main_process.h> 12431Sigor@sysoev.ru #include <nxt_router.h> 13431Sigor@sysoev.ru #include <nxt_http.h> 14*444Sigor@sysoev.ru #include <nxt_application.h> 150Sigor@sysoev.ru 16216Sigor@sysoev.ru #include <glob.h> 170Sigor@sysoev.ru 18216Sigor@sysoev.ru 19216Sigor@sysoev.ru typedef struct { 20356Svbart@nginx.com nxt_app_type_t type; 21356Svbart@nginx.com nxt_str_t version; 22356Svbart@nginx.com nxt_str_t file; 23216Sigor@sysoev.ru } nxt_module_t; 24216Sigor@sysoev.ru 25216Sigor@sysoev.ru 26216Sigor@sysoev.ru static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path); 27216Sigor@sysoev.ru static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, 28216Sigor@sysoev.ru nxt_array_t *modules, const char *name); 29216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, 30216Sigor@sysoev.ru const char *name); 31356Svbart@nginx.com static nxt_app_type_t nxt_app_parse_type(u_char *p, size_t length); 32216Sigor@sysoev.ru 330Sigor@sysoev.ru 34431Sigor@sysoev.ru static void nxt_app_http_release(nxt_task_t *task, void *obj, void *data); 350Sigor@sysoev.ru 36216Sigor@sysoev.ru 37258Sigor@sysoev.ru static uint32_t compat[] = { 38360Sigor@sysoev.ru NXT_VERNUM, NXT_DEBUG, 39258Sigor@sysoev.ru }; 40258Sigor@sysoev.ru 41258Sigor@sysoev.ru 42417Svbart@nginx.com static nxt_thread_mutex_t nxt_app_mutex; 43417Svbart@nginx.com static nxt_thread_cond_t nxt_app_cond; 44417Svbart@nginx.com 45417Svbart@nginx.com static nxt_application_module_t *nxt_app; 46417Svbart@nginx.com 47417Svbart@nginx.com 48216Sigor@sysoev.ru nxt_int_t 49216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data) 50216Sigor@sysoev.ru { 51216Sigor@sysoev.ru nxt_buf_t *b; 52216Sigor@sysoev.ru nxt_port_t *main_port; 53216Sigor@sysoev.ru nxt_runtime_t *rt; 54216Sigor@sysoev.ru 55216Sigor@sysoev.ru nxt_debug(task, "DISCOVERY"); 56216Sigor@sysoev.ru 57233Sigor@sysoev.ru rt = task->thread->runtime; 58216Sigor@sysoev.ru 59233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 60250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 61250Sigor@sysoev.ru exit(1); 62250Sigor@sysoev.ru } 63233Sigor@sysoev.ru 64240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 65216Sigor@sysoev.ru 66216Sigor@sysoev.ru nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 67216Sigor@sysoev.ru 0, -1, b); 68216Sigor@sysoev.ru 69216Sigor@sysoev.ru return NXT_OK; 70216Sigor@sysoev.ru } 71216Sigor@sysoev.ru 72216Sigor@sysoev.ru 73216Sigor@sysoev.ru static void 74216Sigor@sysoev.ru nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 75216Sigor@sysoev.ru { 76216Sigor@sysoev.ru nxt_mp_t *mp; 77216Sigor@sysoev.ru nxt_buf_t *b; 78216Sigor@sysoev.ru 79216Sigor@sysoev.ru b = obj; 80216Sigor@sysoev.ru mp = b->data; 81216Sigor@sysoev.ru 82216Sigor@sysoev.ru nxt_mp_destroy(mp); 83216Sigor@sysoev.ru 84216Sigor@sysoev.ru exit(0); 85216Sigor@sysoev.ru } 86216Sigor@sysoev.ru 87216Sigor@sysoev.ru 88216Sigor@sysoev.ru static nxt_buf_t * 89216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 90216Sigor@sysoev.ru { 91216Sigor@sysoev.ru char *name; 92216Sigor@sysoev.ru u_char *p, *end; 93216Sigor@sysoev.ru size_t size; 94216Sigor@sysoev.ru glob_t glb; 95216Sigor@sysoev.ru nxt_mp_t *mp; 96216Sigor@sysoev.ru nxt_buf_t *b; 97216Sigor@sysoev.ru nxt_int_t ret; 98216Sigor@sysoev.ru nxt_uint_t i, n; 99216Sigor@sysoev.ru nxt_array_t *modules; 100216Sigor@sysoev.ru nxt_module_t *module; 101216Sigor@sysoev.ru 102216Sigor@sysoev.ru b = NULL; 103216Sigor@sysoev.ru 104216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 105216Sigor@sysoev.ru if (mp == NULL) { 106216Sigor@sysoev.ru return b; 107216Sigor@sysoev.ru } 108216Sigor@sysoev.ru 109216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 110216Sigor@sysoev.ru 111250Sigor@sysoev.ru n = glb.gl_pathc; 112250Sigor@sysoev.ru 113250Sigor@sysoev.ru if (ret != 0) { 114250Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 115250Sigor@sysoev.ru "no modules matching: \"%s\" found", path); 116250Sigor@sysoev.ru n = 0; 117250Sigor@sysoev.ru } 118216Sigor@sysoev.ru 119250Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 120250Sigor@sysoev.ru if (modules == NULL) { 121250Sigor@sysoev.ru goto fail; 122250Sigor@sysoev.ru } 123250Sigor@sysoev.ru 124250Sigor@sysoev.ru for (i = 0; i < n; i++) { 125250Sigor@sysoev.ru name = glb.gl_pathv[i]; 126250Sigor@sysoev.ru 127250Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 128250Sigor@sysoev.ru if (ret != NXT_OK) { 129216Sigor@sysoev.ru goto fail; 130216Sigor@sysoev.ru } 131250Sigor@sysoev.ru } 132216Sigor@sysoev.ru 133250Sigor@sysoev.ru size = sizeof("[]") - 1; 134250Sigor@sysoev.ru module = modules->elts; 135250Sigor@sysoev.ru n = modules->nelts; 136216Sigor@sysoev.ru 137250Sigor@sysoev.ru for (i = 0; i < n; i++) { 138356Svbart@nginx.com nxt_debug(task, "module: %d %V %V", 139356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 140216Sigor@sysoev.ru 141356Svbart@nginx.com size += sizeof("{\"type\": ,") - 1; 142250Sigor@sysoev.ru size += sizeof(" \"version\": \"\",") - 1; 143250Sigor@sysoev.ru size += sizeof(" \"file\": \"\"},") - 1; 144216Sigor@sysoev.ru 145356Svbart@nginx.com size += NXT_INT_T_LEN 146250Sigor@sysoev.ru + module[i].version.length 147250Sigor@sysoev.ru + module[i].file.length; 148250Sigor@sysoev.ru } 149216Sigor@sysoev.ru 150250Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 151250Sigor@sysoev.ru if (b == NULL) { 152250Sigor@sysoev.ru goto fail; 153250Sigor@sysoev.ru } 154216Sigor@sysoev.ru 155250Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 156216Sigor@sysoev.ru 157250Sigor@sysoev.ru p = b->mem.free; 158250Sigor@sysoev.ru end = b->mem.end; 159250Sigor@sysoev.ru *p++ = '['; 160216Sigor@sysoev.ru 161250Sigor@sysoev.ru for (i = 0; i < n; i++) { 162250Sigor@sysoev.ru p = nxt_sprintf(p, end, 163356Svbart@nginx.com "{\"type\": %d, \"version\": \"%V\", \"file\": \"%V\"},", 164356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 165250Sigor@sysoev.ru } 166216Sigor@sysoev.ru 167250Sigor@sysoev.ru *p++ = ']'; 168250Sigor@sysoev.ru b->mem.free = p; 169216Sigor@sysoev.ru 170216Sigor@sysoev.ru fail: 171216Sigor@sysoev.ru 172216Sigor@sysoev.ru globfree(&glb); 173216Sigor@sysoev.ru 174216Sigor@sysoev.ru return b; 175216Sigor@sysoev.ru } 176216Sigor@sysoev.ru 177216Sigor@sysoev.ru 178216Sigor@sysoev.ru static nxt_int_t 179216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 180216Sigor@sysoev.ru const char *name) 181216Sigor@sysoev.ru { 182216Sigor@sysoev.ru void *dl; 183216Sigor@sysoev.ru nxt_str_t *s; 184216Sigor@sysoev.ru nxt_int_t ret; 185216Sigor@sysoev.ru nxt_uint_t i, n; 186216Sigor@sysoev.ru nxt_module_t *module; 187356Svbart@nginx.com nxt_app_type_t type; 188216Sigor@sysoev.ru nxt_application_module_t *app; 189216Sigor@sysoev.ru 190216Sigor@sysoev.ru /* 191216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 192216Sigor@sysoev.ru * Any module processing errors are ignored. 193216Sigor@sysoev.ru */ 194216Sigor@sysoev.ru ret = NXT_ERROR; 195216Sigor@sysoev.ru 196216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 197216Sigor@sysoev.ru 198216Sigor@sysoev.ru if (dl == NULL) { 199216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 200216Sigor@sysoev.ru name, dlerror()); 201216Sigor@sysoev.ru return NXT_OK; 202216Sigor@sysoev.ru } 203216Sigor@sysoev.ru 204216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 205216Sigor@sysoev.ru 206216Sigor@sysoev.ru if (app != NULL) { 207258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "module: %V %V \"%s\"", 208258Sigor@sysoev.ru &app->type, &app->version, name); 209258Sigor@sysoev.ru 210258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 211258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 212258Sigor@sysoev.ru { 213258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 214258Sigor@sysoev.ru 215258Sigor@sysoev.ru goto done; 216258Sigor@sysoev.ru } 217216Sigor@sysoev.ru 218356Svbart@nginx.com type = nxt_app_parse_type(app->type.start, app->type.length); 219356Svbart@nginx.com 220356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 221356Svbart@nginx.com nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", app->type); 222356Svbart@nginx.com 223356Svbart@nginx.com goto done; 224356Svbart@nginx.com } 225356Svbart@nginx.com 226216Sigor@sysoev.ru module = modules->elts; 227216Sigor@sysoev.ru n = modules->nelts; 228216Sigor@sysoev.ru 229216Sigor@sysoev.ru for (i = 0; i < n; i++) { 230356Svbart@nginx.com if (type == module[i].type 231258Sigor@sysoev.ru && nxt_strstr_eq(&app->version, &module[i].version)) 232258Sigor@sysoev.ru { 233216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 234216Sigor@sysoev.ru "ignoring %s module with the same " 235267Sigor@sysoev.ru "application language version %V %V as in %V", 236356Svbart@nginx.com name, &app->type, &app->version, 237258Sigor@sysoev.ru &module[i].file); 238216Sigor@sysoev.ru 239216Sigor@sysoev.ru goto done; 240216Sigor@sysoev.ru } 241216Sigor@sysoev.ru } 242216Sigor@sysoev.ru 243216Sigor@sysoev.ru module = nxt_array_add(modules); 244216Sigor@sysoev.ru if (module == NULL) { 245216Sigor@sysoev.ru goto fail; 246216Sigor@sysoev.ru } 247216Sigor@sysoev.ru 248356Svbart@nginx.com module->type = type; 249216Sigor@sysoev.ru 250216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->version, &app->version); 251216Sigor@sysoev.ru if (s == NULL) { 252216Sigor@sysoev.ru goto fail; 253216Sigor@sysoev.ru } 254216Sigor@sysoev.ru 255216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 256216Sigor@sysoev.ru 257216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 258216Sigor@sysoev.ru if (module->file.start == NULL) { 259216Sigor@sysoev.ru goto fail; 260216Sigor@sysoev.ru } 261216Sigor@sysoev.ru 262216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 263216Sigor@sysoev.ru 264216Sigor@sysoev.ru } else { 265216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlsym(\"%s\"), failed: \"%s\"", 266216Sigor@sysoev.ru name, dlerror()); 267216Sigor@sysoev.ru } 268216Sigor@sysoev.ru 269216Sigor@sysoev.ru done: 270216Sigor@sysoev.ru 271216Sigor@sysoev.ru ret = NXT_OK; 272216Sigor@sysoev.ru 273216Sigor@sysoev.ru fail: 274216Sigor@sysoev.ru 275216Sigor@sysoev.ru if (dlclose(dl) != 0) { 276216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlclose(\"%s\"), failed: \"%s\"", 277216Sigor@sysoev.ru name, dlerror()); 278216Sigor@sysoev.ru } 279216Sigor@sysoev.ru 280216Sigor@sysoev.ru return ret; 281216Sigor@sysoev.ru } 282216Sigor@sysoev.ru 283216Sigor@sysoev.ru 2840Sigor@sysoev.ru nxt_int_t 285141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data) 2860Sigor@sysoev.ru { 287216Sigor@sysoev.ru nxt_int_t ret; 288216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 289216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 290141Smax.romanov@nginx.com 291141Smax.romanov@nginx.com app_conf = data; 292141Smax.romanov@nginx.com 293216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 294216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 295216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"", 296216Sigor@sysoev.ru &app_conf->type); 297216Sigor@sysoev.ru return NXT_ERROR; 298216Sigor@sysoev.ru } 299216Sigor@sysoev.ru 300216Sigor@sysoev.ru nxt_app = lang->module; 301216Sigor@sysoev.ru 302216Sigor@sysoev.ru if (nxt_app == NULL) { 303354Svbart@nginx.com nxt_debug(task, "application language module: %s \"%s\"", 304354Svbart@nginx.com lang->version, lang->file); 305216Sigor@sysoev.ru 306216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 307216Sigor@sysoev.ru } 308216Sigor@sysoev.ru 309277Sigor@sysoev.ru if (app_conf->working_directory != NULL 310277Sigor@sysoev.ru && app_conf->working_directory[0] != 0) 311271Smax.romanov@nginx.com { 312271Smax.romanov@nginx.com ret = chdir(app_conf->working_directory); 313271Smax.romanov@nginx.com 314271Smax.romanov@nginx.com if (nxt_slow_path(ret != 0)) { 315271Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", 316271Smax.romanov@nginx.com app_conf->working_directory, nxt_errno); 317271Smax.romanov@nginx.com 318271Smax.romanov@nginx.com return NXT_ERROR; 319271Smax.romanov@nginx.com } 320271Smax.romanov@nginx.com } 321271Smax.romanov@nginx.com 3220Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) { 3230Sigor@sysoev.ru return NXT_ERROR; 3240Sigor@sysoev.ru } 3250Sigor@sysoev.ru 3260Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_cond_create(&nxt_app_cond) != NXT_OK)) { 3270Sigor@sysoev.ru return NXT_ERROR; 3280Sigor@sysoev.ru } 3290Sigor@sysoev.ru 330141Smax.romanov@nginx.com ret = nxt_app->init(task, data); 331141Smax.romanov@nginx.com 332141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 33384Smax.romanov@nginx.com nxt_debug(task, "application init failed"); 334141Smax.romanov@nginx.com 335141Smax.romanov@nginx.com } else { 336141Smax.romanov@nginx.com nxt_debug(task, "application init done"); 33720Sigor@sysoev.ru } 33820Sigor@sysoev.ru 339141Smax.romanov@nginx.com return ret; 34020Sigor@sysoev.ru } 34120Sigor@sysoev.ru 34220Sigor@sysoev.ru 343216Sigor@sysoev.ru static nxt_app_module_t * 344216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 345216Sigor@sysoev.ru { 346216Sigor@sysoev.ru void *dl; 347216Sigor@sysoev.ru 348216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 349216Sigor@sysoev.ru 350216Sigor@sysoev.ru if (dl != NULL) { 351216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 352216Sigor@sysoev.ru } 353216Sigor@sysoev.ru 354216Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"", 355216Sigor@sysoev.ru name, dlerror()); 356216Sigor@sysoev.ru 357216Sigor@sysoev.ru return NULL; 358216Sigor@sysoev.ru } 359216Sigor@sysoev.ru 360216Sigor@sysoev.ru 36184Smax.romanov@nginx.com void 362421Smax.romanov@nginx.com nxt_app_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 363421Smax.romanov@nginx.com { 364421Smax.romanov@nginx.com if (nxt_app->atexit != NULL) { 365421Smax.romanov@nginx.com nxt_app->atexit(task); 366421Smax.romanov@nginx.com } 367421Smax.romanov@nginx.com 368421Smax.romanov@nginx.com nxt_worker_process_quit_handler(task, msg); 369421Smax.romanov@nginx.com } 370421Smax.romanov@nginx.com 371421Smax.romanov@nginx.com 372421Smax.romanov@nginx.com void 373421Smax.romanov@nginx.com nxt_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 37484Smax.romanov@nginx.com { 37584Smax.romanov@nginx.com size_t dump_size; 37684Smax.romanov@nginx.com nxt_buf_t *b; 37784Smax.romanov@nginx.com nxt_port_t *port; 37884Smax.romanov@nginx.com nxt_app_rmsg_t rmsg = { msg->buf }; 37984Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 3800Sigor@sysoev.ru 38184Smax.romanov@nginx.com b = msg->buf; 38284Smax.romanov@nginx.com dump_size = b->mem.free - b->mem.pos; 3830Sigor@sysoev.ru 38484Smax.romanov@nginx.com if (dump_size > 300) { 38584Smax.romanov@nginx.com dump_size = 300; 38684Smax.romanov@nginx.com } 3870Sigor@sysoev.ru 38884Smax.romanov@nginx.com nxt_debug(task, "app data: %*s ...", dump_size, b->mem.pos); 3890Sigor@sysoev.ru 39084Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 39184Smax.romanov@nginx.com msg->port_msg.reply_port); 39284Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 393423Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: reply port %d not found", 394423Smax.romanov@nginx.com msg->port_msg.stream, msg->port_msg.reply_port); 395423Smax.romanov@nginx.com return; 39684Smax.romanov@nginx.com } 3974Sigor@sysoev.ru 39884Smax.romanov@nginx.com wmsg.port = port; 39984Smax.romanov@nginx.com wmsg.write = NULL; 40084Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 40184Smax.romanov@nginx.com wmsg.stream = msg->port_msg.stream; 4020Sigor@sysoev.ru 40384Smax.romanov@nginx.com nxt_app->run(task, &rmsg, &wmsg); 4040Sigor@sysoev.ru } 4050Sigor@sysoev.ru 4060Sigor@sysoev.ru 40784Smax.romanov@nginx.com u_char * 40884Smax.romanov@nginx.com nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, size_t size) 40984Smax.romanov@nginx.com { 41084Smax.romanov@nginx.com size_t free_size; 41184Smax.romanov@nginx.com u_char *res; 41284Smax.romanov@nginx.com nxt_buf_t *b; 4130Sigor@sysoev.ru 41484Smax.romanov@nginx.com res = NULL; 41584Smax.romanov@nginx.com 41684Smax.romanov@nginx.com do { 41784Smax.romanov@nginx.com b = *msg->buf; 4180Sigor@sysoev.ru 41984Smax.romanov@nginx.com if (b == NULL) { 420423Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, msg->port, size); 42184Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 42284Smax.romanov@nginx.com return NULL; 42384Smax.romanov@nginx.com } 4240Sigor@sysoev.ru 42584Smax.romanov@nginx.com *msg->buf = b; 42684Smax.romanov@nginx.com 42784Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4280Sigor@sysoev.ru 42984Smax.romanov@nginx.com if (nxt_slow_path(free_size < size)) { 430273Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "requested buffer too big " 431273Smax.romanov@nginx.com "(%z < %z)", free_size, size); 43284Smax.romanov@nginx.com return NULL; 43384Smax.romanov@nginx.com } 43484Smax.romanov@nginx.com 43584Smax.romanov@nginx.com } 43684Smax.romanov@nginx.com 43784Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4380Sigor@sysoev.ru 43984Smax.romanov@nginx.com if (free_size >= size) { 44084Smax.romanov@nginx.com res = b->mem.free; 44184Smax.romanov@nginx.com b->mem.free += size; 44284Smax.romanov@nginx.com 44384Smax.romanov@nginx.com return res; 44484Smax.romanov@nginx.com } 4451Sigor@sysoev.ru 446206Smax.romanov@nginx.com if (nxt_port_mmap_increase_buf(task, b, size, size) == NXT_OK) { 44784Smax.romanov@nginx.com res = b->mem.free; 44884Smax.romanov@nginx.com b->mem.free += size; 4490Sigor@sysoev.ru 45084Smax.romanov@nginx.com return res; 45184Smax.romanov@nginx.com } 45284Smax.romanov@nginx.com 45384Smax.romanov@nginx.com msg->buf = &b->next; 45484Smax.romanov@nginx.com } while(1); 4550Sigor@sysoev.ru } 4560Sigor@sysoev.ru 4570Sigor@sysoev.ru 45884Smax.romanov@nginx.com nxt_int_t 45984Smax.romanov@nginx.com nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, u_char *c, size_t size) 4600Sigor@sysoev.ru { 46184Smax.romanov@nginx.com u_char *dst; 46284Smax.romanov@nginx.com size_t dst_length; 4630Sigor@sysoev.ru 46484Smax.romanov@nginx.com if (c != NULL) { 46584Smax.romanov@nginx.com dst_length = size + (size < 128 ? 1 : 4) + 1; 4660Sigor@sysoev.ru 46784Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 46884Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 46984Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 47084Smax.romanov@nginx.com dst_length); 47184Smax.romanov@nginx.com return NXT_ERROR; 4720Sigor@sysoev.ru } 4730Sigor@sysoev.ru 47484Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, size + 1); /* +1 for trailing 0 */ 4750Sigor@sysoev.ru 47684Smax.romanov@nginx.com nxt_memcpy(dst, c, size); 47784Smax.romanov@nginx.com dst[size] = 0; 4780Sigor@sysoev.ru 479277Sigor@sysoev.ru nxt_debug(task, "nxt_app_msg_write: %uz %*s", size, (int) size, c); 48084Smax.romanov@nginx.com } else { 48184Smax.romanov@nginx.com dst_length = 1; 4820Sigor@sysoev.ru 48384Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 48484Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 48584Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 48684Smax.romanov@nginx.com dst_length); 48784Smax.romanov@nginx.com return NXT_ERROR; 4880Sigor@sysoev.ru } 4890Sigor@sysoev.ru 49084Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, 0); 49184Smax.romanov@nginx.com 49284Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: NULL"); 4930Sigor@sysoev.ru } 4940Sigor@sysoev.ru 49584Smax.romanov@nginx.com return NXT_OK; 4960Sigor@sysoev.ru } 4970Sigor@sysoev.ru 4980Sigor@sysoev.ru 49984Smax.romanov@nginx.com nxt_int_t 50084Smax.romanov@nginx.com nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, nxt_app_wmsg_t *msg, 501417Svbart@nginx.com const nxt_str_t *prefix, u_char *c, size_t size) 5020Sigor@sysoev.ru { 50384Smax.romanov@nginx.com u_char *dst, *src; 50484Smax.romanov@nginx.com size_t i, length, dst_length; 50584Smax.romanov@nginx.com 506417Svbart@nginx.com length = prefix->length + size; 5070Sigor@sysoev.ru 50884Smax.romanov@nginx.com dst_length = length + (length < 128 ? 1 : 4) + 1; 50984Smax.romanov@nginx.com 51084Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 51184Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 51284Smax.romanov@nginx.com return NXT_ERROR; 5130Sigor@sysoev.ru } 5140Sigor@sysoev.ru 51584Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, length + 1); /* +1 for trailing 0 */ 51684Smax.romanov@nginx.com 51784Smax.romanov@nginx.com nxt_memcpy(dst, prefix->start, prefix->length); 51884Smax.romanov@nginx.com dst += prefix->length; 5190Sigor@sysoev.ru 520417Svbart@nginx.com src = c; 521417Svbart@nginx.com for (i = 0; i < size; i++, dst++, src++) { 52284Smax.romanov@nginx.com 52384Smax.romanov@nginx.com if (*src >= 'a' && *src <= 'z') { 52484Smax.romanov@nginx.com *dst = *src & ~0x20; 52584Smax.romanov@nginx.com continue; 5260Sigor@sysoev.ru } 5270Sigor@sysoev.ru 52884Smax.romanov@nginx.com if (*src == '-') { 52984Smax.romanov@nginx.com *dst = '_'; 53084Smax.romanov@nginx.com continue; 5310Sigor@sysoev.ru } 5320Sigor@sysoev.ru 53384Smax.romanov@nginx.com *dst = *src; 5340Sigor@sysoev.ru } 5350Sigor@sysoev.ru 53684Smax.romanov@nginx.com *dst = 0; 5370Sigor@sysoev.ru 53884Smax.romanov@nginx.com return NXT_OK; 5390Sigor@sysoev.ru } 5400Sigor@sysoev.ru 5410Sigor@sysoev.ru 542423Smax.romanov@nginx.com nxt_inline nxt_int_t 543423Smax.romanov@nginx.com nxt_app_msg_read_size_(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 5440Sigor@sysoev.ru { 54584Smax.romanov@nginx.com nxt_buf_t *buf; 5460Sigor@sysoev.ru 54784Smax.romanov@nginx.com do { 54884Smax.romanov@nginx.com buf = msg->buf; 54984Smax.romanov@nginx.com 55084Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 55184Smax.romanov@nginx.com return NXT_DONE; 5520Sigor@sysoev.ru } 5530Sigor@sysoev.ru 55484Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 55584Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 55684Smax.romanov@nginx.com msg->buf = buf->next; 55784Smax.romanov@nginx.com continue; 55884Smax.romanov@nginx.com } 55984Smax.romanov@nginx.com return NXT_ERROR; 5600Sigor@sysoev.ru } 5610Sigor@sysoev.ru 56284Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 56384Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 56484Smax.romanov@nginx.com return NXT_ERROR; 56584Smax.romanov@nginx.com } 56684Smax.romanov@nginx.com } 5670Sigor@sysoev.ru 56884Smax.romanov@nginx.com break; 56984Smax.romanov@nginx.com } while (1); 5700Sigor@sysoev.ru 571423Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, size); 572423Smax.romanov@nginx.com 573423Smax.romanov@nginx.com return NXT_OK; 574423Smax.romanov@nginx.com } 575423Smax.romanov@nginx.com 576423Smax.romanov@nginx.com 577423Smax.romanov@nginx.com nxt_int_t 578423Smax.romanov@nginx.com nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, nxt_str_t *str) 579423Smax.romanov@nginx.com { 580423Smax.romanov@nginx.com size_t length; 581423Smax.romanov@nginx.com nxt_int_t ret; 582423Smax.romanov@nginx.com nxt_buf_t *buf; 583423Smax.romanov@nginx.com 584423Smax.romanov@nginx.com ret = nxt_app_msg_read_size_(task, msg, &length); 585423Smax.romanov@nginx.com if (ret != NXT_OK) { 586423Smax.romanov@nginx.com return ret; 587423Smax.romanov@nginx.com } 588423Smax.romanov@nginx.com 589423Smax.romanov@nginx.com buf = msg->buf; 59084Smax.romanov@nginx.com 591277Sigor@sysoev.ru if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < (intptr_t) length)) { 59284Smax.romanov@nginx.com return NXT_ERROR; 5930Sigor@sysoev.ru } 5940Sigor@sysoev.ru 59584Smax.romanov@nginx.com if (length > 0) { 59684Smax.romanov@nginx.com str->start = buf->mem.pos; 59784Smax.romanov@nginx.com str->length = length - 1; 5980Sigor@sysoev.ru 59984Smax.romanov@nginx.com buf->mem.pos += length; 6000Sigor@sysoev.ru 601277Sigor@sysoev.ru nxt_debug(task, "nxt_read_str: %d %*s", (int) length - 1, 602277Sigor@sysoev.ru (int) length - 1, str->start); 60384Smax.romanov@nginx.com } else { 60484Smax.romanov@nginx.com str->start = NULL; 60584Smax.romanov@nginx.com str->length = 0; 6060Sigor@sysoev.ru 60784Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: NULL"); 6080Sigor@sysoev.ru } 6090Sigor@sysoev.ru 6100Sigor@sysoev.ru return NXT_OK; 6110Sigor@sysoev.ru } 6120Sigor@sysoev.ru 6130Sigor@sysoev.ru 614206Smax.romanov@nginx.com size_t 615206Smax.romanov@nginx.com nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *dst, 616206Smax.romanov@nginx.com size_t size) 617206Smax.romanov@nginx.com { 618206Smax.romanov@nginx.com size_t res, read_size; 619206Smax.romanov@nginx.com nxt_buf_t *buf; 620206Smax.romanov@nginx.com 621206Smax.romanov@nginx.com res = 0; 622206Smax.romanov@nginx.com 623206Smax.romanov@nginx.com while (size > 0) { 624206Smax.romanov@nginx.com buf = msg->buf; 625206Smax.romanov@nginx.com 626206Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 627206Smax.romanov@nginx.com break; 628206Smax.romanov@nginx.com } 629206Smax.romanov@nginx.com 630206Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 631206Smax.romanov@nginx.com msg->buf = buf->next; 632206Smax.romanov@nginx.com continue; 633206Smax.romanov@nginx.com } 634206Smax.romanov@nginx.com 635206Smax.romanov@nginx.com read_size = nxt_buf_mem_used_size(&buf->mem); 636206Smax.romanov@nginx.com read_size = nxt_min(read_size, size); 637206Smax.romanov@nginx.com 638206Smax.romanov@nginx.com dst = nxt_cpymem(dst, buf->mem.pos, read_size); 639206Smax.romanov@nginx.com 640206Smax.romanov@nginx.com size -= read_size; 641206Smax.romanov@nginx.com buf->mem.pos += read_size; 642206Smax.romanov@nginx.com res += read_size; 643206Smax.romanov@nginx.com } 644206Smax.romanov@nginx.com 645206Smax.romanov@nginx.com nxt_debug(task, "nxt_read_raw: %uz", res); 646206Smax.romanov@nginx.com 647206Smax.romanov@nginx.com return res; 648206Smax.romanov@nginx.com } 649206Smax.romanov@nginx.com 650206Smax.romanov@nginx.com 65184Smax.romanov@nginx.com nxt_int_t 65284Smax.romanov@nginx.com nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_str_t *n, 65384Smax.romanov@nginx.com nxt_str_t *v) 6540Sigor@sysoev.ru { 65584Smax.romanov@nginx.com nxt_int_t rc; 6560Sigor@sysoev.ru 65784Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, n); 65884Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 65984Smax.romanov@nginx.com return rc; 6600Sigor@sysoev.ru } 6610Sigor@sysoev.ru 66284Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, v); 66384Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 66484Smax.romanov@nginx.com return rc; 66584Smax.romanov@nginx.com } 6660Sigor@sysoev.ru 66784Smax.romanov@nginx.com return rc; 6680Sigor@sysoev.ru } 6690Sigor@sysoev.ru 6700Sigor@sysoev.ru 6710Sigor@sysoev.ru nxt_int_t 67284Smax.romanov@nginx.com nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 6730Sigor@sysoev.ru { 674423Smax.romanov@nginx.com nxt_int_t ret; 6750Sigor@sysoev.ru 676423Smax.romanov@nginx.com ret = nxt_app_msg_read_size_(task, msg, size); 67784Smax.romanov@nginx.com 678277Sigor@sysoev.ru nxt_debug(task, "nxt_read_size: %d", (int) *size); 6790Sigor@sysoev.ru 680423Smax.romanov@nginx.com return ret; 6810Sigor@sysoev.ru } 6820Sigor@sysoev.ru 6830Sigor@sysoev.ru 684431Sigor@sysoev.ru nxt_int_t 685431Sigor@sysoev.ru nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ar) 68684Smax.romanov@nginx.com { 687431Sigor@sysoev.ru ar->timer.handler = nxt_app_http_release; 688431Sigor@sysoev.ru nxt_timer_add(task->thread->engine, &ar->timer, 0); 68984Smax.romanov@nginx.com 69084Smax.romanov@nginx.com return NXT_OK; 69184Smax.romanov@nginx.com } 69284Smax.romanov@nginx.com 6930Sigor@sysoev.ru 694431Sigor@sysoev.ru static void 695431Sigor@sysoev.ru nxt_app_http_release(nxt_task_t *task, void *obj, void *data) 69684Smax.romanov@nginx.com { 697431Sigor@sysoev.ru nxt_timer_t *timer; 698431Sigor@sysoev.ru nxt_app_parse_ctx_t *ar; 699206Smax.romanov@nginx.com 700431Sigor@sysoev.ru timer = obj; 701206Smax.romanov@nginx.com 702431Sigor@sysoev.ru nxt_debug(task, "http app release"); 703206Smax.romanov@nginx.com 704431Sigor@sysoev.ru ar = nxt_timer_data(timer, nxt_app_parse_ctx_t, timer); 705206Smax.romanov@nginx.com 706431Sigor@sysoev.ru nxt_mp_release(ar->request->mem_pool); 7070Sigor@sysoev.ru } 7080Sigor@sysoev.ru 7090Sigor@sysoev.ru 71084Smax.romanov@nginx.com nxt_int_t 71184Smax.romanov@nginx.com nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last) 7120Sigor@sysoev.ru { 71384Smax.romanov@nginx.com nxt_int_t rc; 71484Smax.romanov@nginx.com nxt_buf_t *b; 71584Smax.romanov@nginx.com 71684Smax.romanov@nginx.com rc = NXT_OK; 7170Sigor@sysoev.ru 71884Smax.romanov@nginx.com if (nxt_slow_path(last == 1)) { 71984Smax.romanov@nginx.com do { 72084Smax.romanov@nginx.com b = *msg->buf; 7210Sigor@sysoev.ru 72284Smax.romanov@nginx.com if (b == NULL) { 723423Smax.romanov@nginx.com b = nxt_buf_sync_alloc(msg->port->mem_pool, NXT_BUF_SYNC_LAST); 72484Smax.romanov@nginx.com *msg->buf = b; 72584Smax.romanov@nginx.com break; 72684Smax.romanov@nginx.com } 7270Sigor@sysoev.ru 72884Smax.romanov@nginx.com msg->buf = &b->next; 72984Smax.romanov@nginx.com } while(1); 73084Smax.romanov@nginx.com } 7310Sigor@sysoev.ru 73284Smax.romanov@nginx.com if (nxt_slow_path(msg->write != NULL)) { 733423Smax.romanov@nginx.com rc = nxt_port_socket_write(task, msg->port, NXT_PORT_MSG_DATA, 73484Smax.romanov@nginx.com -1, msg->stream, 0, msg->write); 73584Smax.romanov@nginx.com 73684Smax.romanov@nginx.com msg->write = NULL; 73784Smax.romanov@nginx.com msg->buf = &msg->write; 73884Smax.romanov@nginx.com } 73984Smax.romanov@nginx.com 74084Smax.romanov@nginx.com return rc; 7410Sigor@sysoev.ru } 7420Sigor@sysoev.ru 7430Sigor@sysoev.ru 74484Smax.romanov@nginx.com nxt_int_t 74584Smax.romanov@nginx.com nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c, 74684Smax.romanov@nginx.com size_t size) 7470Sigor@sysoev.ru { 748206Smax.romanov@nginx.com size_t free_size, copy_size; 749206Smax.romanov@nginx.com nxt_buf_t *b; 750206Smax.romanov@nginx.com 751206Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write_raw: %uz", size); 752206Smax.romanov@nginx.com 753206Smax.romanov@nginx.com while (size > 0) { 754206Smax.romanov@nginx.com b = *msg->buf; 755206Smax.romanov@nginx.com 756206Smax.romanov@nginx.com if (b == NULL) { 757423Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, msg->port, size); 758206Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 759206Smax.romanov@nginx.com return NXT_ERROR; 760206Smax.romanov@nginx.com } 76184Smax.romanov@nginx.com 762206Smax.romanov@nginx.com *msg->buf = b; 763206Smax.romanov@nginx.com } 764206Smax.romanov@nginx.com 765206Smax.romanov@nginx.com do { 766206Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 767206Smax.romanov@nginx.com 768206Smax.romanov@nginx.com if (free_size > 0) { 769206Smax.romanov@nginx.com copy_size = nxt_min(free_size, size); 770206Smax.romanov@nginx.com 771206Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c, copy_size); 772206Smax.romanov@nginx.com 773206Smax.romanov@nginx.com size -= copy_size; 774206Smax.romanov@nginx.com c += copy_size; 775206Smax.romanov@nginx.com 776206Smax.romanov@nginx.com if (size == 0) { 777206Smax.romanov@nginx.com return NXT_OK; 778206Smax.romanov@nginx.com } 779206Smax.romanov@nginx.com } 780206Smax.romanov@nginx.com } while (nxt_port_mmap_increase_buf(task, b, size, 1) == NXT_OK); 781206Smax.romanov@nginx.com 782206Smax.romanov@nginx.com msg->buf = &b->next; 7830Sigor@sysoev.ru } 7840Sigor@sysoev.ru 78584Smax.romanov@nginx.com return NXT_OK; 7860Sigor@sysoev.ru } 787141Smax.romanov@nginx.com 788141Smax.romanov@nginx.com 789216Sigor@sysoev.ru nxt_app_lang_module_t * 790216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 791216Sigor@sysoev.ru { 792216Sigor@sysoev.ru u_char *p, *end, *version; 793356Svbart@nginx.com size_t version_length; 794216Sigor@sysoev.ru nxt_uint_t i, n; 795356Svbart@nginx.com nxt_app_type_t type; 796216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 797216Sigor@sysoev.ru 798216Sigor@sysoev.ru end = name->start + name->length; 799216Sigor@sysoev.ru version = end; 800216Sigor@sysoev.ru 801216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 802216Sigor@sysoev.ru if (*p == ' ') { 803216Sigor@sysoev.ru version = p + 1; 804216Sigor@sysoev.ru break; 805216Sigor@sysoev.ru } 806216Sigor@sysoev.ru 807216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 808216Sigor@sysoev.ru version = p; 809216Sigor@sysoev.ru break; 810216Sigor@sysoev.ru } 811216Sigor@sysoev.ru } 812216Sigor@sysoev.ru 813356Svbart@nginx.com type = nxt_app_parse_type(name->start, p - name->start); 814356Svbart@nginx.com 815356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 816356Svbart@nginx.com return NULL; 817356Svbart@nginx.com } 818356Svbart@nginx.com 819216Sigor@sysoev.ru version_length = end - version; 820216Sigor@sysoev.ru 821216Sigor@sysoev.ru lang = rt->languages->elts; 822216Sigor@sysoev.ru n = rt->languages->nelts; 823216Sigor@sysoev.ru 824216Sigor@sysoev.ru for (i = 0; i < n; i++) { 825354Svbart@nginx.com 826354Svbart@nginx.com /* 827354Svbart@nginx.com * Versions are sorted in descending order 828354Svbart@nginx.com * so first match chooses the highest version. 829354Svbart@nginx.com */ 830354Svbart@nginx.com 831356Svbart@nginx.com if (lang[i].type == type 832354Svbart@nginx.com && nxt_strvers_match(lang[i].version, version, version_length)) 833216Sigor@sysoev.ru { 834216Sigor@sysoev.ru return &lang[i]; 835216Sigor@sysoev.ru } 836216Sigor@sysoev.ru } 837216Sigor@sysoev.ru 838216Sigor@sysoev.ru return NULL; 839216Sigor@sysoev.ru } 840216Sigor@sysoev.ru 841216Sigor@sysoev.ru 842356Svbart@nginx.com static nxt_app_type_t 843356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length) 844141Smax.romanov@nginx.com { 845356Svbart@nginx.com nxt_str_t str; 846356Svbart@nginx.com 847356Svbart@nginx.com str.length = length; 848356Svbart@nginx.com str.start = p; 849356Svbart@nginx.com 850356Svbart@nginx.com if (nxt_str_eq(&str, "python", 6)) { 851141Smax.romanov@nginx.com return NXT_APP_PYTHON; 852141Smax.romanov@nginx.com 853356Svbart@nginx.com } else if (nxt_str_eq(&str, "php", 3)) { 854141Smax.romanov@nginx.com return NXT_APP_PHP; 855141Smax.romanov@nginx.com 856356Svbart@nginx.com } else if (nxt_str_eq(&str, "go", 2)) { 857141Smax.romanov@nginx.com return NXT_APP_GO; 858141Smax.romanov@nginx.com 859141Smax.romanov@nginx.com } 860141Smax.romanov@nginx.com 861141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 862141Smax.romanov@nginx.com } 863