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> 14444Sigor@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); 29549Svbart@nginx.com static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj, 30549Svbart@nginx.com void *data); 31549Svbart@nginx.com static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, 32549Svbart@nginx.com void *data); 33216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, 34216Sigor@sysoev.ru const char *name); 350Sigor@sysoev.ru 36431Sigor@sysoev.ru static void nxt_app_http_release(nxt_task_t *task, void *obj, void *data); 370Sigor@sysoev.ru 38216Sigor@sysoev.ru 39258Sigor@sysoev.ru static uint32_t compat[] = { 40360Sigor@sysoev.ru NXT_VERNUM, NXT_DEBUG, 41258Sigor@sysoev.ru }; 42258Sigor@sysoev.ru 43258Sigor@sysoev.ru 44417Svbart@nginx.com static nxt_thread_mutex_t nxt_app_mutex; 45417Svbart@nginx.com static nxt_thread_cond_t nxt_app_cond; 46417Svbart@nginx.com 47417Svbart@nginx.com static nxt_application_module_t *nxt_app; 48417Svbart@nginx.com 49417Svbart@nginx.com 50216Sigor@sysoev.ru nxt_int_t 51216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data) 52216Sigor@sysoev.ru { 53549Svbart@nginx.com uint32_t stream; 54549Svbart@nginx.com nxt_buf_t *b; 55549Svbart@nginx.com nxt_int_t ret; 56549Svbart@nginx.com nxt_port_t *main_port, *discovery_port; 57549Svbart@nginx.com nxt_runtime_t *rt; 58216Sigor@sysoev.ru 59216Sigor@sysoev.ru nxt_debug(task, "DISCOVERY"); 60216Sigor@sysoev.ru 61233Sigor@sysoev.ru rt = task->thread->runtime; 62216Sigor@sysoev.ru 63233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 64250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 65549Svbart@nginx.com return NXT_ERROR; 66250Sigor@sysoev.ru } 67233Sigor@sysoev.ru 68240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 69549Svbart@nginx.com discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; 70216Sigor@sysoev.ru 71549Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, discovery_port, 72549Svbart@nginx.com nxt_discovery_quit, 73549Svbart@nginx.com nxt_discovery_quit, 74549Svbart@nginx.com main_port->pid, NULL); 75549Svbart@nginx.com 76549Svbart@nginx.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 77549Svbart@nginx.com stream, discovery_port->id, b); 78549Svbart@nginx.com 79549Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 80549Svbart@nginx.com nxt_port_rpc_cancel(task, discovery_port, stream); 81549Svbart@nginx.com return NXT_ERROR; 82549Svbart@nginx.com } 83216Sigor@sysoev.ru 84216Sigor@sysoev.ru return NXT_OK; 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) { 199*564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 200216Sigor@sysoev.ru return NXT_OK; 201216Sigor@sysoev.ru } 202216Sigor@sysoev.ru 203216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 204216Sigor@sysoev.ru 205216Sigor@sysoev.ru if (app != NULL) { 206258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "module: %V %V \"%s\"", 207258Sigor@sysoev.ru &app->type, &app->version, name); 208258Sigor@sysoev.ru 209258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 210258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 211258Sigor@sysoev.ru { 212258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 213258Sigor@sysoev.ru 214258Sigor@sysoev.ru goto done; 215258Sigor@sysoev.ru } 216216Sigor@sysoev.ru 217356Svbart@nginx.com type = nxt_app_parse_type(app->type.start, app->type.length); 218356Svbart@nginx.com 219356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 220494Spluknet@nginx.com nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); 221356Svbart@nginx.com 222356Svbart@nginx.com goto done; 223356Svbart@nginx.com } 224356Svbart@nginx.com 225216Sigor@sysoev.ru module = modules->elts; 226216Sigor@sysoev.ru n = modules->nelts; 227216Sigor@sysoev.ru 228216Sigor@sysoev.ru for (i = 0; i < n; i++) { 229356Svbart@nginx.com if (type == module[i].type 230258Sigor@sysoev.ru && nxt_strstr_eq(&app->version, &module[i].version)) 231258Sigor@sysoev.ru { 232216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 233216Sigor@sysoev.ru "ignoring %s module with the same " 234267Sigor@sysoev.ru "application language version %V %V as in %V", 235356Svbart@nginx.com name, &app->type, &app->version, 236258Sigor@sysoev.ru &module[i].file); 237216Sigor@sysoev.ru 238216Sigor@sysoev.ru goto done; 239216Sigor@sysoev.ru } 240216Sigor@sysoev.ru } 241216Sigor@sysoev.ru 242216Sigor@sysoev.ru module = nxt_array_add(modules); 243216Sigor@sysoev.ru if (module == NULL) { 244216Sigor@sysoev.ru goto fail; 245216Sigor@sysoev.ru } 246216Sigor@sysoev.ru 247356Svbart@nginx.com module->type = type; 248216Sigor@sysoev.ru 249216Sigor@sysoev.ru s = nxt_str_dup(mp, &module->version, &app->version); 250216Sigor@sysoev.ru if (s == NULL) { 251216Sigor@sysoev.ru goto fail; 252216Sigor@sysoev.ru } 253216Sigor@sysoev.ru 254216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 255216Sigor@sysoev.ru 256216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 257216Sigor@sysoev.ru if (module->file.start == NULL) { 258216Sigor@sysoev.ru goto fail; 259216Sigor@sysoev.ru } 260216Sigor@sysoev.ru 261216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 262216Sigor@sysoev.ru 263216Sigor@sysoev.ru } else { 264*564Svbart@nginx.com nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); 265216Sigor@sysoev.ru } 266216Sigor@sysoev.ru 267216Sigor@sysoev.ru done: 268216Sigor@sysoev.ru 269216Sigor@sysoev.ru ret = NXT_OK; 270216Sigor@sysoev.ru 271216Sigor@sysoev.ru fail: 272216Sigor@sysoev.ru 273216Sigor@sysoev.ru if (dlclose(dl) != 0) { 274*564Svbart@nginx.com nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); 275216Sigor@sysoev.ru } 276216Sigor@sysoev.ru 277216Sigor@sysoev.ru return ret; 278216Sigor@sysoev.ru } 279216Sigor@sysoev.ru 280216Sigor@sysoev.ru 281549Svbart@nginx.com static void 282549Svbart@nginx.com nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 283549Svbart@nginx.com { 284549Svbart@nginx.com nxt_mp_t *mp; 285549Svbart@nginx.com nxt_buf_t *b; 286549Svbart@nginx.com 287549Svbart@nginx.com b = obj; 288549Svbart@nginx.com mp = b->data; 289549Svbart@nginx.com 290549Svbart@nginx.com nxt_mp_destroy(mp); 291549Svbart@nginx.com } 292549Svbart@nginx.com 293549Svbart@nginx.com 294549Svbart@nginx.com static void 295549Svbart@nginx.com nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 296549Svbart@nginx.com { 297549Svbart@nginx.com nxt_worker_process_quit_handler(task, msg); 298549Svbart@nginx.com } 299549Svbart@nginx.com 300549Svbart@nginx.com 3010Sigor@sysoev.ru nxt_int_t 302141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data) 3030Sigor@sysoev.ru { 304216Sigor@sysoev.ru nxt_int_t ret; 305216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 306216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 307141Smax.romanov@nginx.com 308141Smax.romanov@nginx.com app_conf = data; 309141Smax.romanov@nginx.com 310216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 311216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 312*564Svbart@nginx.com nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); 313216Sigor@sysoev.ru return NXT_ERROR; 314216Sigor@sysoev.ru } 315216Sigor@sysoev.ru 316216Sigor@sysoev.ru nxt_app = lang->module; 317216Sigor@sysoev.ru 318216Sigor@sysoev.ru if (nxt_app == NULL) { 319354Svbart@nginx.com nxt_debug(task, "application language module: %s \"%s\"", 320354Svbart@nginx.com lang->version, lang->file); 321216Sigor@sysoev.ru 322216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 323216Sigor@sysoev.ru } 324216Sigor@sysoev.ru 325277Sigor@sysoev.ru if (app_conf->working_directory != NULL 326277Sigor@sysoev.ru && app_conf->working_directory[0] != 0) 327271Smax.romanov@nginx.com { 328271Smax.romanov@nginx.com ret = chdir(app_conf->working_directory); 329271Smax.romanov@nginx.com 330271Smax.romanov@nginx.com if (nxt_slow_path(ret != 0)) { 331271Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", 332271Smax.romanov@nginx.com app_conf->working_directory, nxt_errno); 333271Smax.romanov@nginx.com 334271Smax.romanov@nginx.com return NXT_ERROR; 335271Smax.romanov@nginx.com } 336271Smax.romanov@nginx.com } 337271Smax.romanov@nginx.com 3380Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) { 3390Sigor@sysoev.ru return NXT_ERROR; 3400Sigor@sysoev.ru } 3410Sigor@sysoev.ru 3420Sigor@sysoev.ru if (nxt_slow_path(nxt_thread_cond_create(&nxt_app_cond) != NXT_OK)) { 3430Sigor@sysoev.ru return NXT_ERROR; 3440Sigor@sysoev.ru } 3450Sigor@sysoev.ru 346141Smax.romanov@nginx.com ret = nxt_app->init(task, data); 347141Smax.romanov@nginx.com 348141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 34984Smax.romanov@nginx.com nxt_debug(task, "application init failed"); 350141Smax.romanov@nginx.com 351141Smax.romanov@nginx.com } else { 352141Smax.romanov@nginx.com nxt_debug(task, "application init done"); 35320Sigor@sysoev.ru } 35420Sigor@sysoev.ru 355141Smax.romanov@nginx.com return ret; 35620Sigor@sysoev.ru } 35720Sigor@sysoev.ru 35820Sigor@sysoev.ru 359216Sigor@sysoev.ru static nxt_app_module_t * 360216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 361216Sigor@sysoev.ru { 362216Sigor@sysoev.ru void *dl; 363216Sigor@sysoev.ru 364216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 365216Sigor@sysoev.ru 366216Sigor@sysoev.ru if (dl != NULL) { 367216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 368216Sigor@sysoev.ru } 369216Sigor@sysoev.ru 370*564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 371216Sigor@sysoev.ru 372216Sigor@sysoev.ru return NULL; 373216Sigor@sysoev.ru } 374216Sigor@sysoev.ru 375216Sigor@sysoev.ru 37684Smax.romanov@nginx.com void 377421Smax.romanov@nginx.com nxt_app_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 378421Smax.romanov@nginx.com { 379421Smax.romanov@nginx.com if (nxt_app->atexit != NULL) { 380421Smax.romanov@nginx.com nxt_app->atexit(task); 381421Smax.romanov@nginx.com } 382421Smax.romanov@nginx.com 383421Smax.romanov@nginx.com nxt_worker_process_quit_handler(task, msg); 384421Smax.romanov@nginx.com } 385421Smax.romanov@nginx.com 386421Smax.romanov@nginx.com 387421Smax.romanov@nginx.com void 388421Smax.romanov@nginx.com nxt_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 38984Smax.romanov@nginx.com { 39084Smax.romanov@nginx.com size_t dump_size; 39184Smax.romanov@nginx.com nxt_buf_t *b; 39284Smax.romanov@nginx.com nxt_port_t *port; 39384Smax.romanov@nginx.com nxt_app_rmsg_t rmsg = { msg->buf }; 39484Smax.romanov@nginx.com nxt_app_wmsg_t wmsg; 3950Sigor@sysoev.ru 39684Smax.romanov@nginx.com b = msg->buf; 39784Smax.romanov@nginx.com dump_size = b->mem.free - b->mem.pos; 3980Sigor@sysoev.ru 39984Smax.romanov@nginx.com if (dump_size > 300) { 40084Smax.romanov@nginx.com dump_size = 300; 40184Smax.romanov@nginx.com } 4020Sigor@sysoev.ru 40384Smax.romanov@nginx.com nxt_debug(task, "app data: %*s ...", dump_size, b->mem.pos); 4040Sigor@sysoev.ru 40584Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 40684Smax.romanov@nginx.com msg->port_msg.reply_port); 40784Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 408423Smax.romanov@nginx.com nxt_debug(task, "stream #%uD: reply port %d not found", 409423Smax.romanov@nginx.com msg->port_msg.stream, msg->port_msg.reply_port); 410423Smax.romanov@nginx.com return; 41184Smax.romanov@nginx.com } 4124Sigor@sysoev.ru 41384Smax.romanov@nginx.com wmsg.port = port; 41484Smax.romanov@nginx.com wmsg.write = NULL; 41584Smax.romanov@nginx.com wmsg.buf = &wmsg.write; 41684Smax.romanov@nginx.com wmsg.stream = msg->port_msg.stream; 4170Sigor@sysoev.ru 41884Smax.romanov@nginx.com nxt_app->run(task, &rmsg, &wmsg); 4190Sigor@sysoev.ru } 4200Sigor@sysoev.ru 4210Sigor@sysoev.ru 42284Smax.romanov@nginx.com u_char * 42384Smax.romanov@nginx.com nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, size_t size) 42484Smax.romanov@nginx.com { 42584Smax.romanov@nginx.com size_t free_size; 42684Smax.romanov@nginx.com u_char *res; 42784Smax.romanov@nginx.com nxt_buf_t *b; 4280Sigor@sysoev.ru 42984Smax.romanov@nginx.com res = NULL; 43084Smax.romanov@nginx.com 43184Smax.romanov@nginx.com do { 43284Smax.romanov@nginx.com b = *msg->buf; 4330Sigor@sysoev.ru 43484Smax.romanov@nginx.com if (b == NULL) { 435423Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, msg->port, size); 43684Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 43784Smax.romanov@nginx.com return NULL; 43884Smax.romanov@nginx.com } 4390Sigor@sysoev.ru 44084Smax.romanov@nginx.com *msg->buf = b; 44184Smax.romanov@nginx.com 44284Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4430Sigor@sysoev.ru 44484Smax.romanov@nginx.com if (nxt_slow_path(free_size < size)) { 445273Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "requested buffer too big " 446273Smax.romanov@nginx.com "(%z < %z)", free_size, size); 44784Smax.romanov@nginx.com return NULL; 44884Smax.romanov@nginx.com } 44984Smax.romanov@nginx.com 45084Smax.romanov@nginx.com } 45184Smax.romanov@nginx.com 45284Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 4530Sigor@sysoev.ru 45484Smax.romanov@nginx.com if (free_size >= size) { 45584Smax.romanov@nginx.com res = b->mem.free; 45684Smax.romanov@nginx.com b->mem.free += size; 45784Smax.romanov@nginx.com 45884Smax.romanov@nginx.com return res; 45984Smax.romanov@nginx.com } 4601Sigor@sysoev.ru 461206Smax.romanov@nginx.com if (nxt_port_mmap_increase_buf(task, b, size, size) == NXT_OK) { 46284Smax.romanov@nginx.com res = b->mem.free; 46384Smax.romanov@nginx.com b->mem.free += size; 4640Sigor@sysoev.ru 46584Smax.romanov@nginx.com return res; 46684Smax.romanov@nginx.com } 46784Smax.romanov@nginx.com 46884Smax.romanov@nginx.com msg->buf = &b->next; 46984Smax.romanov@nginx.com } while(1); 4700Sigor@sysoev.ru } 4710Sigor@sysoev.ru 4720Sigor@sysoev.ru 47384Smax.romanov@nginx.com nxt_int_t 47484Smax.romanov@nginx.com nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, u_char *c, size_t size) 4750Sigor@sysoev.ru { 47684Smax.romanov@nginx.com u_char *dst; 47784Smax.romanov@nginx.com size_t dst_length; 4780Sigor@sysoev.ru 47984Smax.romanov@nginx.com if (c != NULL) { 48084Smax.romanov@nginx.com dst_length = size + (size < 128 ? 1 : 4) + 1; 4810Sigor@sysoev.ru 48284Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 48384Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 48484Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 48584Smax.romanov@nginx.com dst_length); 48684Smax.romanov@nginx.com return NXT_ERROR; 4870Sigor@sysoev.ru } 4880Sigor@sysoev.ru 48984Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, size + 1); /* +1 for trailing 0 */ 4900Sigor@sysoev.ru 49184Smax.romanov@nginx.com nxt_memcpy(dst, c, size); 49284Smax.romanov@nginx.com dst[size] = 0; 4930Sigor@sysoev.ru 494493Spluknet@nginx.com nxt_debug(task, "nxt_app_msg_write: %uz %*s", size, size, c); 495493Spluknet@nginx.com 49684Smax.romanov@nginx.com } else { 49784Smax.romanov@nginx.com dst_length = 1; 4980Sigor@sysoev.ru 49984Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 50084Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 50184Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed", 50284Smax.romanov@nginx.com dst_length); 50384Smax.romanov@nginx.com return NXT_ERROR; 5040Sigor@sysoev.ru } 5050Sigor@sysoev.ru 50684Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, 0); 50784Smax.romanov@nginx.com 50884Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write: NULL"); 5090Sigor@sysoev.ru } 5100Sigor@sysoev.ru 51184Smax.romanov@nginx.com return NXT_OK; 5120Sigor@sysoev.ru } 5130Sigor@sysoev.ru 5140Sigor@sysoev.ru 51584Smax.romanov@nginx.com nxt_int_t 51684Smax.romanov@nginx.com nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, nxt_app_wmsg_t *msg, 517417Svbart@nginx.com const nxt_str_t *prefix, u_char *c, size_t size) 5180Sigor@sysoev.ru { 51984Smax.romanov@nginx.com u_char *dst, *src; 52084Smax.romanov@nginx.com size_t i, length, dst_length; 52184Smax.romanov@nginx.com 522417Svbart@nginx.com length = prefix->length + size; 5230Sigor@sysoev.ru 52484Smax.romanov@nginx.com dst_length = length + (length < 128 ? 1 : 4) + 1; 52584Smax.romanov@nginx.com 52684Smax.romanov@nginx.com dst = nxt_app_msg_write_get_buf(task, msg, dst_length); 52784Smax.romanov@nginx.com if (nxt_slow_path(dst == NULL)) { 52884Smax.romanov@nginx.com return NXT_ERROR; 5290Sigor@sysoev.ru } 5300Sigor@sysoev.ru 53184Smax.romanov@nginx.com dst = nxt_app_msg_write_length(dst, length + 1); /* +1 for trailing 0 */ 53284Smax.romanov@nginx.com 53384Smax.romanov@nginx.com nxt_memcpy(dst, prefix->start, prefix->length); 53484Smax.romanov@nginx.com dst += prefix->length; 5350Sigor@sysoev.ru 536417Svbart@nginx.com src = c; 537417Svbart@nginx.com for (i = 0; i < size; i++, dst++, src++) { 53884Smax.romanov@nginx.com 53984Smax.romanov@nginx.com if (*src >= 'a' && *src <= 'z') { 54084Smax.romanov@nginx.com *dst = *src & ~0x20; 54184Smax.romanov@nginx.com continue; 5420Sigor@sysoev.ru } 5430Sigor@sysoev.ru 54484Smax.romanov@nginx.com if (*src == '-') { 54584Smax.romanov@nginx.com *dst = '_'; 54684Smax.romanov@nginx.com continue; 5470Sigor@sysoev.ru } 5480Sigor@sysoev.ru 54984Smax.romanov@nginx.com *dst = *src; 5500Sigor@sysoev.ru } 5510Sigor@sysoev.ru 55284Smax.romanov@nginx.com *dst = 0; 5530Sigor@sysoev.ru 55484Smax.romanov@nginx.com return NXT_OK; 5550Sigor@sysoev.ru } 5560Sigor@sysoev.ru 5570Sigor@sysoev.ru 558423Smax.romanov@nginx.com nxt_inline nxt_int_t 559423Smax.romanov@nginx.com nxt_app_msg_read_size_(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 5600Sigor@sysoev.ru { 56184Smax.romanov@nginx.com nxt_buf_t *buf; 5620Sigor@sysoev.ru 56384Smax.romanov@nginx.com do { 56484Smax.romanov@nginx.com buf = msg->buf; 56584Smax.romanov@nginx.com 56684Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 56784Smax.romanov@nginx.com return NXT_DONE; 5680Sigor@sysoev.ru } 5690Sigor@sysoev.ru 57084Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) { 57184Smax.romanov@nginx.com if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 57284Smax.romanov@nginx.com msg->buf = buf->next; 57384Smax.romanov@nginx.com continue; 57484Smax.romanov@nginx.com } 57584Smax.romanov@nginx.com return NXT_ERROR; 5760Sigor@sysoev.ru } 5770Sigor@sysoev.ru 57884Smax.romanov@nginx.com if (buf->mem.pos[0] >= 128) { 57984Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) { 58084Smax.romanov@nginx.com return NXT_ERROR; 58184Smax.romanov@nginx.com } 58284Smax.romanov@nginx.com } 5830Sigor@sysoev.ru 58484Smax.romanov@nginx.com break; 58584Smax.romanov@nginx.com } while (1); 5860Sigor@sysoev.ru 587423Smax.romanov@nginx.com buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, size); 588423Smax.romanov@nginx.com 589423Smax.romanov@nginx.com return NXT_OK; 590423Smax.romanov@nginx.com } 591423Smax.romanov@nginx.com 592423Smax.romanov@nginx.com 593423Smax.romanov@nginx.com nxt_int_t 594423Smax.romanov@nginx.com nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, nxt_str_t *str) 595423Smax.romanov@nginx.com { 596423Smax.romanov@nginx.com size_t length; 597423Smax.romanov@nginx.com nxt_int_t ret; 598423Smax.romanov@nginx.com nxt_buf_t *buf; 599423Smax.romanov@nginx.com 600423Smax.romanov@nginx.com ret = nxt_app_msg_read_size_(task, msg, &length); 601423Smax.romanov@nginx.com if (ret != NXT_OK) { 602423Smax.romanov@nginx.com return ret; 603423Smax.romanov@nginx.com } 604423Smax.romanov@nginx.com 605423Smax.romanov@nginx.com buf = msg->buf; 60684Smax.romanov@nginx.com 607277Sigor@sysoev.ru if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < (intptr_t) length)) { 60884Smax.romanov@nginx.com return NXT_ERROR; 6090Sigor@sysoev.ru } 6100Sigor@sysoev.ru 61184Smax.romanov@nginx.com if (length > 0) { 61284Smax.romanov@nginx.com str->start = buf->mem.pos; 61384Smax.romanov@nginx.com str->length = length - 1; 6140Sigor@sysoev.ru 61584Smax.romanov@nginx.com buf->mem.pos += length; 6160Sigor@sysoev.ru 617493Spluknet@nginx.com nxt_debug(task, "nxt_read_str: %uz %*s", length - 1, 618493Spluknet@nginx.com length - 1, str->start); 619493Spluknet@nginx.com 62084Smax.romanov@nginx.com } else { 62184Smax.romanov@nginx.com str->start = NULL; 62284Smax.romanov@nginx.com str->length = 0; 6230Sigor@sysoev.ru 62484Smax.romanov@nginx.com nxt_debug(task, "nxt_read_str: NULL"); 6250Sigor@sysoev.ru } 6260Sigor@sysoev.ru 6270Sigor@sysoev.ru return NXT_OK; 6280Sigor@sysoev.ru } 6290Sigor@sysoev.ru 6300Sigor@sysoev.ru 631206Smax.romanov@nginx.com size_t 632206Smax.romanov@nginx.com nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *dst, 633206Smax.romanov@nginx.com size_t size) 634206Smax.romanov@nginx.com { 635206Smax.romanov@nginx.com size_t res, read_size; 636206Smax.romanov@nginx.com nxt_buf_t *buf; 637206Smax.romanov@nginx.com 638206Smax.romanov@nginx.com res = 0; 639206Smax.romanov@nginx.com 640206Smax.romanov@nginx.com while (size > 0) { 641206Smax.romanov@nginx.com buf = msg->buf; 642206Smax.romanov@nginx.com 643206Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 644206Smax.romanov@nginx.com break; 645206Smax.romanov@nginx.com } 646206Smax.romanov@nginx.com 647206Smax.romanov@nginx.com if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) == 0)) { 648206Smax.romanov@nginx.com msg->buf = buf->next; 649206Smax.romanov@nginx.com continue; 650206Smax.romanov@nginx.com } 651206Smax.romanov@nginx.com 652206Smax.romanov@nginx.com read_size = nxt_buf_mem_used_size(&buf->mem); 653206Smax.romanov@nginx.com read_size = nxt_min(read_size, size); 654206Smax.romanov@nginx.com 655206Smax.romanov@nginx.com dst = nxt_cpymem(dst, buf->mem.pos, read_size); 656206Smax.romanov@nginx.com 657206Smax.romanov@nginx.com size -= read_size; 658206Smax.romanov@nginx.com buf->mem.pos += read_size; 659206Smax.romanov@nginx.com res += read_size; 660206Smax.romanov@nginx.com } 661206Smax.romanov@nginx.com 662206Smax.romanov@nginx.com nxt_debug(task, "nxt_read_raw: %uz", res); 663206Smax.romanov@nginx.com 664206Smax.romanov@nginx.com return res; 665206Smax.romanov@nginx.com } 666206Smax.romanov@nginx.com 667206Smax.romanov@nginx.com 66884Smax.romanov@nginx.com nxt_int_t 66984Smax.romanov@nginx.com nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_str_t *n, 67084Smax.romanov@nginx.com nxt_str_t *v) 6710Sigor@sysoev.ru { 67284Smax.romanov@nginx.com nxt_int_t rc; 6730Sigor@sysoev.ru 67484Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, n); 67584Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 67684Smax.romanov@nginx.com return rc; 6770Sigor@sysoev.ru } 6780Sigor@sysoev.ru 67984Smax.romanov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, v); 68084Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 68184Smax.romanov@nginx.com return rc; 68284Smax.romanov@nginx.com } 6830Sigor@sysoev.ru 68484Smax.romanov@nginx.com return rc; 6850Sigor@sysoev.ru } 6860Sigor@sysoev.ru 6870Sigor@sysoev.ru 6880Sigor@sysoev.ru nxt_int_t 68984Smax.romanov@nginx.com nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size) 6900Sigor@sysoev.ru { 691423Smax.romanov@nginx.com nxt_int_t ret; 6920Sigor@sysoev.ru 693423Smax.romanov@nginx.com ret = nxt_app_msg_read_size_(task, msg, size); 69484Smax.romanov@nginx.com 695277Sigor@sysoev.ru nxt_debug(task, "nxt_read_size: %d", (int) *size); 6960Sigor@sysoev.ru 697423Smax.romanov@nginx.com return ret; 6980Sigor@sysoev.ru } 6990Sigor@sysoev.ru 7000Sigor@sysoev.ru 701431Sigor@sysoev.ru nxt_int_t 702431Sigor@sysoev.ru nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ar) 70384Smax.romanov@nginx.com { 704431Sigor@sysoev.ru ar->timer.handler = nxt_app_http_release; 705431Sigor@sysoev.ru nxt_timer_add(task->thread->engine, &ar->timer, 0); 70684Smax.romanov@nginx.com 70784Smax.romanov@nginx.com return NXT_OK; 70884Smax.romanov@nginx.com } 70984Smax.romanov@nginx.com 7100Sigor@sysoev.ru 711431Sigor@sysoev.ru static void 712431Sigor@sysoev.ru nxt_app_http_release(nxt_task_t *task, void *obj, void *data) 71384Smax.romanov@nginx.com { 714431Sigor@sysoev.ru nxt_timer_t *timer; 715431Sigor@sysoev.ru nxt_app_parse_ctx_t *ar; 716206Smax.romanov@nginx.com 717431Sigor@sysoev.ru timer = obj; 718206Smax.romanov@nginx.com 719431Sigor@sysoev.ru nxt_debug(task, "http app release"); 720206Smax.romanov@nginx.com 721431Sigor@sysoev.ru ar = nxt_timer_data(timer, nxt_app_parse_ctx_t, timer); 722206Smax.romanov@nginx.com 723431Sigor@sysoev.ru nxt_mp_release(ar->request->mem_pool); 7240Sigor@sysoev.ru } 7250Sigor@sysoev.ru 7260Sigor@sysoev.ru 72784Smax.romanov@nginx.com nxt_int_t 72884Smax.romanov@nginx.com nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last) 7290Sigor@sysoev.ru { 73084Smax.romanov@nginx.com nxt_int_t rc; 73184Smax.romanov@nginx.com nxt_buf_t *b; 73284Smax.romanov@nginx.com 73384Smax.romanov@nginx.com rc = NXT_OK; 7340Sigor@sysoev.ru 73584Smax.romanov@nginx.com if (nxt_slow_path(last == 1)) { 73684Smax.romanov@nginx.com do { 73784Smax.romanov@nginx.com b = *msg->buf; 7380Sigor@sysoev.ru 73984Smax.romanov@nginx.com if (b == NULL) { 740423Smax.romanov@nginx.com b = nxt_buf_sync_alloc(msg->port->mem_pool, NXT_BUF_SYNC_LAST); 74184Smax.romanov@nginx.com *msg->buf = b; 74284Smax.romanov@nginx.com break; 74384Smax.romanov@nginx.com } 7440Sigor@sysoev.ru 74584Smax.romanov@nginx.com msg->buf = &b->next; 74684Smax.romanov@nginx.com } while(1); 74784Smax.romanov@nginx.com } 7480Sigor@sysoev.ru 74984Smax.romanov@nginx.com if (nxt_slow_path(msg->write != NULL)) { 750423Smax.romanov@nginx.com rc = nxt_port_socket_write(task, msg->port, NXT_PORT_MSG_DATA, 75184Smax.romanov@nginx.com -1, msg->stream, 0, msg->write); 75284Smax.romanov@nginx.com 75384Smax.romanov@nginx.com msg->write = NULL; 75484Smax.romanov@nginx.com msg->buf = &msg->write; 75584Smax.romanov@nginx.com } 75684Smax.romanov@nginx.com 75784Smax.romanov@nginx.com return rc; 7580Sigor@sysoev.ru } 7590Sigor@sysoev.ru 7600Sigor@sysoev.ru 76184Smax.romanov@nginx.com nxt_int_t 76284Smax.romanov@nginx.com nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c, 76384Smax.romanov@nginx.com size_t size) 7640Sigor@sysoev.ru { 765206Smax.romanov@nginx.com size_t free_size, copy_size; 766206Smax.romanov@nginx.com nxt_buf_t *b; 767206Smax.romanov@nginx.com 768206Smax.romanov@nginx.com nxt_debug(task, "nxt_app_msg_write_raw: %uz", size); 769206Smax.romanov@nginx.com 770206Smax.romanov@nginx.com while (size > 0) { 771206Smax.romanov@nginx.com b = *msg->buf; 772206Smax.romanov@nginx.com 773206Smax.romanov@nginx.com if (b == NULL) { 774423Smax.romanov@nginx.com b = nxt_port_mmap_get_buf(task, msg->port, size); 775206Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 776206Smax.romanov@nginx.com return NXT_ERROR; 777206Smax.romanov@nginx.com } 77884Smax.romanov@nginx.com 779206Smax.romanov@nginx.com *msg->buf = b; 780206Smax.romanov@nginx.com } 781206Smax.romanov@nginx.com 782206Smax.romanov@nginx.com do { 783206Smax.romanov@nginx.com free_size = nxt_buf_mem_free_size(&b->mem); 784206Smax.romanov@nginx.com 785206Smax.romanov@nginx.com if (free_size > 0) { 786206Smax.romanov@nginx.com copy_size = nxt_min(free_size, size); 787206Smax.romanov@nginx.com 788206Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, c, copy_size); 789206Smax.romanov@nginx.com 790206Smax.romanov@nginx.com size -= copy_size; 791206Smax.romanov@nginx.com c += copy_size; 792206Smax.romanov@nginx.com 793206Smax.romanov@nginx.com if (size == 0) { 794206Smax.romanov@nginx.com return NXT_OK; 795206Smax.romanov@nginx.com } 796206Smax.romanov@nginx.com } 797206Smax.romanov@nginx.com } while (nxt_port_mmap_increase_buf(task, b, size, 1) == NXT_OK); 798206Smax.romanov@nginx.com 799206Smax.romanov@nginx.com msg->buf = &b->next; 8000Sigor@sysoev.ru } 8010Sigor@sysoev.ru 80284Smax.romanov@nginx.com return NXT_OK; 8030Sigor@sysoev.ru } 804141Smax.romanov@nginx.com 805141Smax.romanov@nginx.com 806216Sigor@sysoev.ru nxt_app_lang_module_t * 807216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 808216Sigor@sysoev.ru { 809216Sigor@sysoev.ru u_char *p, *end, *version; 810356Svbart@nginx.com size_t version_length; 811216Sigor@sysoev.ru nxt_uint_t i, n; 812356Svbart@nginx.com nxt_app_type_t type; 813216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 814216Sigor@sysoev.ru 815216Sigor@sysoev.ru end = name->start + name->length; 816216Sigor@sysoev.ru version = end; 817216Sigor@sysoev.ru 818216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 819216Sigor@sysoev.ru if (*p == ' ') { 820216Sigor@sysoev.ru version = p + 1; 821216Sigor@sysoev.ru break; 822216Sigor@sysoev.ru } 823216Sigor@sysoev.ru 824216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 825216Sigor@sysoev.ru version = p; 826216Sigor@sysoev.ru break; 827216Sigor@sysoev.ru } 828216Sigor@sysoev.ru } 829216Sigor@sysoev.ru 830356Svbart@nginx.com type = nxt_app_parse_type(name->start, p - name->start); 831356Svbart@nginx.com 832356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 833356Svbart@nginx.com return NULL; 834356Svbart@nginx.com } 835356Svbart@nginx.com 836216Sigor@sysoev.ru version_length = end - version; 837216Sigor@sysoev.ru 838216Sigor@sysoev.ru lang = rt->languages->elts; 839216Sigor@sysoev.ru n = rt->languages->nelts; 840216Sigor@sysoev.ru 841216Sigor@sysoev.ru for (i = 0; i < n; i++) { 842354Svbart@nginx.com 843354Svbart@nginx.com /* 844354Svbart@nginx.com * Versions are sorted in descending order 845354Svbart@nginx.com * so first match chooses the highest version. 846354Svbart@nginx.com */ 847354Svbart@nginx.com 848356Svbart@nginx.com if (lang[i].type == type 849354Svbart@nginx.com && nxt_strvers_match(lang[i].version, version, version_length)) 850216Sigor@sysoev.ru { 851216Sigor@sysoev.ru return &lang[i]; 852216Sigor@sysoev.ru } 853216Sigor@sysoev.ru } 854216Sigor@sysoev.ru 855216Sigor@sysoev.ru return NULL; 856216Sigor@sysoev.ru } 857216Sigor@sysoev.ru 858216Sigor@sysoev.ru 859510Salexander.borisov@nginx.com nxt_app_type_t 860356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length) 861141Smax.romanov@nginx.com { 862356Svbart@nginx.com nxt_str_t str; 863356Svbart@nginx.com 864356Svbart@nginx.com str.length = length; 865356Svbart@nginx.com str.start = p; 866356Svbart@nginx.com 867356Svbart@nginx.com if (nxt_str_eq(&str, "python", 6)) { 868141Smax.romanov@nginx.com return NXT_APP_PYTHON; 869141Smax.romanov@nginx.com 870356Svbart@nginx.com } else if (nxt_str_eq(&str, "php", 3)) { 871141Smax.romanov@nginx.com return NXT_APP_PHP; 872141Smax.romanov@nginx.com 873356Svbart@nginx.com } else if (nxt_str_eq(&str, "go", 2)) { 874141Smax.romanov@nginx.com return NXT_APP_GO; 875141Smax.romanov@nginx.com 876510Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "perl", 4)) { 877510Salexander.borisov@nginx.com return NXT_APP_PERL; 878141Smax.romanov@nginx.com } 879141Smax.romanov@nginx.com 880141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 881141Smax.romanov@nginx.com } 882