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> 15*743Smax.romanov@nginx.com #include <nxt_unit.h> 16723Smax.romanov@nginx.com #include <nxt_port_memory_int.h> 170Sigor@sysoev.ru 18216Sigor@sysoev.ru #include <glob.h> 190Sigor@sysoev.ru 20216Sigor@sysoev.ru 21216Sigor@sysoev.ru typedef struct { 22356Svbart@nginx.com nxt_app_type_t type; 23356Svbart@nginx.com nxt_str_t version; 24356Svbart@nginx.com nxt_str_t file; 25216Sigor@sysoev.ru } nxt_module_t; 26216Sigor@sysoev.ru 27216Sigor@sysoev.ru 28216Sigor@sysoev.ru static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path); 29216Sigor@sysoev.ru static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, 30216Sigor@sysoev.ru nxt_array_t *modules, const char *name); 31549Svbart@nginx.com static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj, 32549Svbart@nginx.com void *data); 33549Svbart@nginx.com static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, 34549Svbart@nginx.com void *data); 35216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, 36216Sigor@sysoev.ru const char *name); 37678Svbart@nginx.com static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment); 380Sigor@sysoev.ru 39431Sigor@sysoev.ru static void nxt_app_http_release(nxt_task_t *task, void *obj, void *data); 400Sigor@sysoev.ru 41216Sigor@sysoev.ru 42258Sigor@sysoev.ru static uint32_t compat[] = { 43360Sigor@sysoev.ru NXT_VERNUM, NXT_DEBUG, 44258Sigor@sysoev.ru }; 45258Sigor@sysoev.ru 46258Sigor@sysoev.ru 47673Svbart@nginx.com nxt_str_t nxt_server = nxt_string(NXT_SERVER); 48673Svbart@nginx.com 49673Svbart@nginx.com 50*743Smax.romanov@nginx.com static nxt_app_module_t *nxt_app; 51417Svbart@nginx.com 52417Svbart@nginx.com 53216Sigor@sysoev.ru nxt_int_t 54216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data) 55216Sigor@sysoev.ru { 56549Svbart@nginx.com uint32_t stream; 57549Svbart@nginx.com nxt_buf_t *b; 58549Svbart@nginx.com nxt_int_t ret; 59549Svbart@nginx.com nxt_port_t *main_port, *discovery_port; 60549Svbart@nginx.com nxt_runtime_t *rt; 61216Sigor@sysoev.ru 62216Sigor@sysoev.ru nxt_debug(task, "DISCOVERY"); 63216Sigor@sysoev.ru 64233Sigor@sysoev.ru rt = task->thread->runtime; 65216Sigor@sysoev.ru 66233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 67250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 68549Svbart@nginx.com return NXT_ERROR; 69250Sigor@sysoev.ru } 70233Sigor@sysoev.ru 71240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 72549Svbart@nginx.com discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; 73216Sigor@sysoev.ru 74549Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, discovery_port, 75549Svbart@nginx.com nxt_discovery_quit, 76549Svbart@nginx.com nxt_discovery_quit, 77549Svbart@nginx.com main_port->pid, NULL); 78549Svbart@nginx.com 79645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 80645Svbart@nginx.com return NXT_ERROR; 81645Svbart@nginx.com } 82645Svbart@nginx.com 83549Svbart@nginx.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 84549Svbart@nginx.com stream, discovery_port->id, b); 85549Svbart@nginx.com 86549Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 87549Svbart@nginx.com nxt_port_rpc_cancel(task, discovery_port, stream); 88549Svbart@nginx.com return NXT_ERROR; 89549Svbart@nginx.com } 90216Sigor@sysoev.ru 91216Sigor@sysoev.ru return NXT_OK; 92216Sigor@sysoev.ru } 93216Sigor@sysoev.ru 94216Sigor@sysoev.ru 95216Sigor@sysoev.ru static nxt_buf_t * 96216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 97216Sigor@sysoev.ru { 98216Sigor@sysoev.ru char *name; 99216Sigor@sysoev.ru u_char *p, *end; 100216Sigor@sysoev.ru size_t size; 101216Sigor@sysoev.ru glob_t glb; 102216Sigor@sysoev.ru nxt_mp_t *mp; 103216Sigor@sysoev.ru nxt_buf_t *b; 104216Sigor@sysoev.ru nxt_int_t ret; 105216Sigor@sysoev.ru nxt_uint_t i, n; 106216Sigor@sysoev.ru nxt_array_t *modules; 107216Sigor@sysoev.ru nxt_module_t *module; 108216Sigor@sysoev.ru 109216Sigor@sysoev.ru b = NULL; 110216Sigor@sysoev.ru 111216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 112216Sigor@sysoev.ru if (mp == NULL) { 113216Sigor@sysoev.ru return b; 114216Sigor@sysoev.ru } 115216Sigor@sysoev.ru 116216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 117216Sigor@sysoev.ru 118250Sigor@sysoev.ru n = glb.gl_pathc; 119250Sigor@sysoev.ru 120250Sigor@sysoev.ru if (ret != 0) { 121250Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 122250Sigor@sysoev.ru "no modules matching: \"%s\" found", path); 123250Sigor@sysoev.ru n = 0; 124250Sigor@sysoev.ru } 125216Sigor@sysoev.ru 126250Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 127250Sigor@sysoev.ru if (modules == NULL) { 128250Sigor@sysoev.ru goto fail; 129250Sigor@sysoev.ru } 130250Sigor@sysoev.ru 131250Sigor@sysoev.ru for (i = 0; i < n; i++) { 132250Sigor@sysoev.ru name = glb.gl_pathv[i]; 133250Sigor@sysoev.ru 134250Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 135250Sigor@sysoev.ru if (ret != NXT_OK) { 136216Sigor@sysoev.ru goto fail; 137216Sigor@sysoev.ru } 138250Sigor@sysoev.ru } 139216Sigor@sysoev.ru 140703Svbart@nginx.com size = nxt_length("[]"); 141250Sigor@sysoev.ru module = modules->elts; 142250Sigor@sysoev.ru n = modules->nelts; 143216Sigor@sysoev.ru 144250Sigor@sysoev.ru for (i = 0; i < n; i++) { 145356Svbart@nginx.com nxt_debug(task, "module: %d %V %V", 146356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 147216Sigor@sysoev.ru 148703Svbart@nginx.com size += nxt_length("{\"type\": ,"); 149703Svbart@nginx.com size += nxt_length(" \"version\": \"\","); 150703Svbart@nginx.com size += nxt_length(" \"file\": \"\"},"); 151216Sigor@sysoev.ru 152356Svbart@nginx.com size += NXT_INT_T_LEN 153250Sigor@sysoev.ru + module[i].version.length 154250Sigor@sysoev.ru + module[i].file.length; 155250Sigor@sysoev.ru } 156216Sigor@sysoev.ru 157250Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 158250Sigor@sysoev.ru if (b == NULL) { 159250Sigor@sysoev.ru goto fail; 160250Sigor@sysoev.ru } 161216Sigor@sysoev.ru 162250Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 163216Sigor@sysoev.ru 164250Sigor@sysoev.ru p = b->mem.free; 165250Sigor@sysoev.ru end = b->mem.end; 166250Sigor@sysoev.ru *p++ = '['; 167216Sigor@sysoev.ru 168250Sigor@sysoev.ru for (i = 0; i < n; i++) { 169250Sigor@sysoev.ru p = nxt_sprintf(p, end, 170356Svbart@nginx.com "{\"type\": %d, \"version\": \"%V\", \"file\": \"%V\"},", 171356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 172250Sigor@sysoev.ru } 173216Sigor@sysoev.ru 174250Sigor@sysoev.ru *p++ = ']'; 175250Sigor@sysoev.ru b->mem.free = p; 176216Sigor@sysoev.ru 177216Sigor@sysoev.ru fail: 178216Sigor@sysoev.ru 179216Sigor@sysoev.ru globfree(&glb); 180216Sigor@sysoev.ru 181216Sigor@sysoev.ru return b; 182216Sigor@sysoev.ru } 183216Sigor@sysoev.ru 184216Sigor@sysoev.ru 185216Sigor@sysoev.ru static nxt_int_t 186216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 187216Sigor@sysoev.ru const char *name) 188216Sigor@sysoev.ru { 189*743Smax.romanov@nginx.com void *dl; 190*743Smax.romanov@nginx.com nxt_str_t version; 191*743Smax.romanov@nginx.com nxt_int_t ret; 192*743Smax.romanov@nginx.com nxt_uint_t i, n; 193*743Smax.romanov@nginx.com nxt_module_t *module; 194*743Smax.romanov@nginx.com nxt_app_type_t type; 195*743Smax.romanov@nginx.com nxt_app_module_t *app; 196216Sigor@sysoev.ru 197216Sigor@sysoev.ru /* 198216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 199216Sigor@sysoev.ru * Any module processing errors are ignored. 200216Sigor@sysoev.ru */ 201216Sigor@sysoev.ru ret = NXT_ERROR; 202216Sigor@sysoev.ru 203216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 204216Sigor@sysoev.ru 205216Sigor@sysoev.ru if (dl == NULL) { 206564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 207216Sigor@sysoev.ru return NXT_OK; 208216Sigor@sysoev.ru } 209216Sigor@sysoev.ru 210216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 211216Sigor@sysoev.ru 212216Sigor@sysoev.ru if (app != NULL) { 213612Salexander.borisov@nginx.com nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"", 214612Salexander.borisov@nginx.com &app->type, app->version, name); 215258Sigor@sysoev.ru 216258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 217258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 218258Sigor@sysoev.ru { 219258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 220258Sigor@sysoev.ru 221258Sigor@sysoev.ru goto done; 222258Sigor@sysoev.ru } 223216Sigor@sysoev.ru 224356Svbart@nginx.com type = nxt_app_parse_type(app->type.start, app->type.length); 225356Svbart@nginx.com 226356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 227494Spluknet@nginx.com nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); 228356Svbart@nginx.com 229356Svbart@nginx.com goto done; 230356Svbart@nginx.com } 231356Svbart@nginx.com 232216Sigor@sysoev.ru module = modules->elts; 233216Sigor@sysoev.ru n = modules->nelts; 234216Sigor@sysoev.ru 235612Salexander.borisov@nginx.com version.start = (u_char *) app->version; 236612Salexander.borisov@nginx.com version.length = nxt_strlen(app->version); 237612Salexander.borisov@nginx.com 238216Sigor@sysoev.ru for (i = 0; i < n; i++) { 239356Svbart@nginx.com if (type == module[i].type 240612Salexander.borisov@nginx.com && nxt_strstr_eq(&module[i].version, &version)) 241258Sigor@sysoev.ru { 242216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 243216Sigor@sysoev.ru "ignoring %s module with the same " 244267Sigor@sysoev.ru "application language version %V %V as in %V", 245655Svbart@nginx.com name, &app->type, &version, &module[i].file); 246216Sigor@sysoev.ru 247216Sigor@sysoev.ru goto done; 248216Sigor@sysoev.ru } 249216Sigor@sysoev.ru } 250216Sigor@sysoev.ru 251216Sigor@sysoev.ru module = nxt_array_add(modules); 252216Sigor@sysoev.ru if (module == NULL) { 253216Sigor@sysoev.ru goto fail; 254216Sigor@sysoev.ru } 255216Sigor@sysoev.ru 256356Svbart@nginx.com module->type = type; 257216Sigor@sysoev.ru 258612Salexander.borisov@nginx.com nxt_str_dup(mp, &module->version, &version); 259612Salexander.borisov@nginx.com if (module->version.start == NULL) { 260216Sigor@sysoev.ru goto fail; 261216Sigor@sysoev.ru } 262216Sigor@sysoev.ru 263216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 264216Sigor@sysoev.ru 265216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 266216Sigor@sysoev.ru if (module->file.start == NULL) { 267216Sigor@sysoev.ru goto fail; 268216Sigor@sysoev.ru } 269216Sigor@sysoev.ru 270216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 271216Sigor@sysoev.ru 272216Sigor@sysoev.ru } else { 273564Svbart@nginx.com nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); 274216Sigor@sysoev.ru } 275216Sigor@sysoev.ru 276216Sigor@sysoev.ru done: 277216Sigor@sysoev.ru 278216Sigor@sysoev.ru ret = NXT_OK; 279216Sigor@sysoev.ru 280216Sigor@sysoev.ru fail: 281216Sigor@sysoev.ru 282216Sigor@sysoev.ru if (dlclose(dl) != 0) { 283564Svbart@nginx.com nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); 284216Sigor@sysoev.ru } 285216Sigor@sysoev.ru 286216Sigor@sysoev.ru return ret; 287216Sigor@sysoev.ru } 288216Sigor@sysoev.ru 289216Sigor@sysoev.ru 290549Svbart@nginx.com static void 291549Svbart@nginx.com nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 292549Svbart@nginx.com { 293549Svbart@nginx.com nxt_mp_t *mp; 294549Svbart@nginx.com nxt_buf_t *b; 295549Svbart@nginx.com 296549Svbart@nginx.com b = obj; 297549Svbart@nginx.com mp = b->data; 298549Svbart@nginx.com 299549Svbart@nginx.com nxt_mp_destroy(mp); 300549Svbart@nginx.com } 301549Svbart@nginx.com 302549Svbart@nginx.com 303549Svbart@nginx.com static void 304549Svbart@nginx.com nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 305549Svbart@nginx.com { 306549Svbart@nginx.com nxt_worker_process_quit_handler(task, msg); 307549Svbart@nginx.com } 308549Svbart@nginx.com 309549Svbart@nginx.com 3100Sigor@sysoev.ru nxt_int_t 311141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data) 3120Sigor@sysoev.ru { 313216Sigor@sysoev.ru nxt_int_t ret; 314216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 315216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 316141Smax.romanov@nginx.com 317141Smax.romanov@nginx.com app_conf = data; 318141Smax.romanov@nginx.com 319216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 320216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 321564Svbart@nginx.com nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); 322216Sigor@sysoev.ru return NXT_ERROR; 323216Sigor@sysoev.ru } 324216Sigor@sysoev.ru 325216Sigor@sysoev.ru nxt_app = lang->module; 326216Sigor@sysoev.ru 327216Sigor@sysoev.ru if (nxt_app == NULL) { 328354Svbart@nginx.com nxt_debug(task, "application language module: %s \"%s\"", 329354Svbart@nginx.com lang->version, lang->file); 330216Sigor@sysoev.ru 331216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 332216Sigor@sysoev.ru } 333216Sigor@sysoev.ru 334277Sigor@sysoev.ru if (app_conf->working_directory != NULL 335277Sigor@sysoev.ru && app_conf->working_directory[0] != 0) 336271Smax.romanov@nginx.com { 337271Smax.romanov@nginx.com ret = chdir(app_conf->working_directory); 338271Smax.romanov@nginx.com 339271Smax.romanov@nginx.com if (nxt_slow_path(ret != 0)) { 340271Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", 341271Smax.romanov@nginx.com app_conf->working_directory, nxt_errno); 342271Smax.romanov@nginx.com 343271Smax.romanov@nginx.com return NXT_ERROR; 344271Smax.romanov@nginx.com } 345271Smax.romanov@nginx.com } 346271Smax.romanov@nginx.com 347678Svbart@nginx.com if (nxt_slow_path(nxt_app_set_environment(app_conf->environment) 348678Svbart@nginx.com != NXT_OK)) 349678Svbart@nginx.com { 350678Svbart@nginx.com nxt_alert(task, "failed to set environment"); 351678Svbart@nginx.com return NXT_ERROR; 352678Svbart@nginx.com } 353678Svbart@nginx.com 354141Smax.romanov@nginx.com ret = nxt_app->init(task, data); 355141Smax.romanov@nginx.com 356141Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 35784Smax.romanov@nginx.com nxt_debug(task, "application init failed"); 358141Smax.romanov@nginx.com 359141Smax.romanov@nginx.com } else { 360141Smax.romanov@nginx.com nxt_debug(task, "application init done"); 36120Sigor@sysoev.ru } 36220Sigor@sysoev.ru 363141Smax.romanov@nginx.com return ret; 36420Sigor@sysoev.ru } 36520Sigor@sysoev.ru 36620Sigor@sysoev.ru 367216Sigor@sysoev.ru static nxt_app_module_t * 368216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 369216Sigor@sysoev.ru { 370216Sigor@sysoev.ru void *dl; 371216Sigor@sysoev.ru 372216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 373216Sigor@sysoev.ru 374216Sigor@sysoev.ru if (dl != NULL) { 375216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 376216Sigor@sysoev.ru } 377216Sigor@sysoev.ru 378564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 379216Sigor@sysoev.ru 380216Sigor@sysoev.ru return NULL; 381216Sigor@sysoev.ru } 382216Sigor@sysoev.ru 383216Sigor@sysoev.ru 384678Svbart@nginx.com static nxt_int_t 385678Svbart@nginx.com nxt_app_set_environment(nxt_conf_value_t *environment) 386678Svbart@nginx.com { 387678Svbart@nginx.com char *env, *p; 388678Svbart@nginx.com uint32_t next; 389678Svbart@nginx.com nxt_str_t name, value; 390678Svbart@nginx.com nxt_conf_value_t *value_obj; 391678Svbart@nginx.com 392678Svbart@nginx.com if (environment != NULL) { 393678Svbart@nginx.com next = 0; 394678Svbart@nginx.com 395678Svbart@nginx.com for ( ;; ) { 396678Svbart@nginx.com value_obj = nxt_conf_next_object_member(environment, &name, &next); 397678Svbart@nginx.com if (value_obj == NULL) { 398678Svbart@nginx.com break; 399678Svbart@nginx.com } 400678Svbart@nginx.com 401678Svbart@nginx.com nxt_conf_get_string(value_obj, &value); 402678Svbart@nginx.com 403678Svbart@nginx.com env = nxt_malloc(name.length + value.length + 2); 404678Svbart@nginx.com if (nxt_slow_path(env == NULL)) { 405678Svbart@nginx.com return NXT_ERROR; 406678Svbart@nginx.com } 407678Svbart@nginx.com 408678Svbart@nginx.com p = nxt_cpymem(env, name.start, name.length); 409678Svbart@nginx.com *p++ = '='; 410678Svbart@nginx.com p = nxt_cpymem(p, value.start, value.length); 411678Svbart@nginx.com *p = '\0'; 412678Svbart@nginx.com 413678Svbart@nginx.com if (nxt_slow_path(putenv(env) != 0)) { 414678Svbart@nginx.com return NXT_ERROR; 415678Svbart@nginx.com } 416678Svbart@nginx.com } 417678Svbart@nginx.com } 418678Svbart@nginx.com 419678Svbart@nginx.com return NXT_OK; 420678Svbart@nginx.com } 421678Svbart@nginx.com 422678Svbart@nginx.com 423431Sigor@sysoev.ru nxt_int_t 424431Sigor@sysoev.ru nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ar) 42584Smax.romanov@nginx.com { 426431Sigor@sysoev.ru ar->timer.handler = nxt_app_http_release; 427431Sigor@sysoev.ru nxt_timer_add(task->thread->engine, &ar->timer, 0); 42884Smax.romanov@nginx.com 42984Smax.romanov@nginx.com return NXT_OK; 43084Smax.romanov@nginx.com } 43184Smax.romanov@nginx.com 4320Sigor@sysoev.ru 433431Sigor@sysoev.ru static void 434431Sigor@sysoev.ru nxt_app_http_release(nxt_task_t *task, void *obj, void *data) 43584Smax.romanov@nginx.com { 436431Sigor@sysoev.ru nxt_timer_t *timer; 437431Sigor@sysoev.ru nxt_app_parse_ctx_t *ar; 438206Smax.romanov@nginx.com 439431Sigor@sysoev.ru timer = obj; 440206Smax.romanov@nginx.com 441431Sigor@sysoev.ru nxt_debug(task, "http app release"); 442206Smax.romanov@nginx.com 443431Sigor@sysoev.ru ar = nxt_timer_data(timer, nxt_app_parse_ctx_t, timer); 444206Smax.romanov@nginx.com 445431Sigor@sysoev.ru nxt_mp_release(ar->request->mem_pool); 4460Sigor@sysoev.ru } 4470Sigor@sysoev.ru 4480Sigor@sysoev.ru 449216Sigor@sysoev.ru nxt_app_lang_module_t * 450216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 451216Sigor@sysoev.ru { 452216Sigor@sysoev.ru u_char *p, *end, *version; 453356Svbart@nginx.com size_t version_length; 454216Sigor@sysoev.ru nxt_uint_t i, n; 455356Svbart@nginx.com nxt_app_type_t type; 456216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 457216Sigor@sysoev.ru 458216Sigor@sysoev.ru end = name->start + name->length; 459216Sigor@sysoev.ru version = end; 460216Sigor@sysoev.ru 461216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 462216Sigor@sysoev.ru if (*p == ' ') { 463216Sigor@sysoev.ru version = p + 1; 464216Sigor@sysoev.ru break; 465216Sigor@sysoev.ru } 466216Sigor@sysoev.ru 467216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 468216Sigor@sysoev.ru version = p; 469216Sigor@sysoev.ru break; 470216Sigor@sysoev.ru } 471216Sigor@sysoev.ru } 472216Sigor@sysoev.ru 473356Svbart@nginx.com type = nxt_app_parse_type(name->start, p - name->start); 474356Svbart@nginx.com 475356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 476356Svbart@nginx.com return NULL; 477356Svbart@nginx.com } 478356Svbart@nginx.com 479216Sigor@sysoev.ru version_length = end - version; 480216Sigor@sysoev.ru 481216Sigor@sysoev.ru lang = rt->languages->elts; 482216Sigor@sysoev.ru n = rt->languages->nelts; 483216Sigor@sysoev.ru 484216Sigor@sysoev.ru for (i = 0; i < n; i++) { 485354Svbart@nginx.com 486354Svbart@nginx.com /* 487354Svbart@nginx.com * Versions are sorted in descending order 488354Svbart@nginx.com * so first match chooses the highest version. 489354Svbart@nginx.com */ 490354Svbart@nginx.com 491356Svbart@nginx.com if (lang[i].type == type 492354Svbart@nginx.com && nxt_strvers_match(lang[i].version, version, version_length)) 493216Sigor@sysoev.ru { 494216Sigor@sysoev.ru return &lang[i]; 495216Sigor@sysoev.ru } 496216Sigor@sysoev.ru } 497216Sigor@sysoev.ru 498216Sigor@sysoev.ru return NULL; 499216Sigor@sysoev.ru } 500216Sigor@sysoev.ru 501216Sigor@sysoev.ru 502510Salexander.borisov@nginx.com nxt_app_type_t 503356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length) 504141Smax.romanov@nginx.com { 505356Svbart@nginx.com nxt_str_t str; 506356Svbart@nginx.com 507356Svbart@nginx.com str.length = length; 508356Svbart@nginx.com str.start = p; 509356Svbart@nginx.com 510356Svbart@nginx.com if (nxt_str_eq(&str, "python", 6)) { 511141Smax.romanov@nginx.com return NXT_APP_PYTHON; 512141Smax.romanov@nginx.com 513356Svbart@nginx.com } else if (nxt_str_eq(&str, "php", 3)) { 514141Smax.romanov@nginx.com return NXT_APP_PHP; 515141Smax.romanov@nginx.com 516356Svbart@nginx.com } else if (nxt_str_eq(&str, "go", 2)) { 517141Smax.romanov@nginx.com return NXT_APP_GO; 518141Smax.romanov@nginx.com 519510Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "perl", 4)) { 520510Salexander.borisov@nginx.com return NXT_APP_PERL; 521584Salexander.borisov@nginx.com 522584Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "ruby", 4)) { 523584Salexander.borisov@nginx.com return NXT_APP_RUBY; 524141Smax.romanov@nginx.com } 525141Smax.romanov@nginx.com 526141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 527141Smax.romanov@nginx.com } 528*743Smax.romanov@nginx.com 529*743Smax.romanov@nginx.com 530*743Smax.romanov@nginx.com nxt_int_t 531*743Smax.romanov@nginx.com nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init) 532*743Smax.romanov@nginx.com { 533*743Smax.romanov@nginx.com nxt_port_t *my_port, *main_port; 534*743Smax.romanov@nginx.com nxt_runtime_t *rt; 535*743Smax.romanov@nginx.com 536*743Smax.romanov@nginx.com nxt_memzero(init, sizeof(nxt_unit_init_t)); 537*743Smax.romanov@nginx.com 538*743Smax.romanov@nginx.com rt = task->thread->runtime; 539*743Smax.romanov@nginx.com 540*743Smax.romanov@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 541*743Smax.romanov@nginx.com if (nxt_slow_path(main_port == NULL)) { 542*743Smax.romanov@nginx.com return NXT_ERROR; 543*743Smax.romanov@nginx.com } 544*743Smax.romanov@nginx.com 545*743Smax.romanov@nginx.com my_port = nxt_runtime_port_find(rt, nxt_pid, 0); 546*743Smax.romanov@nginx.com if (nxt_slow_path(my_port == NULL)) { 547*743Smax.romanov@nginx.com return NXT_ERROR; 548*743Smax.romanov@nginx.com } 549*743Smax.romanov@nginx.com 550*743Smax.romanov@nginx.com init->ready_port.id.pid = main_port->pid; 551*743Smax.romanov@nginx.com init->ready_port.id.id = main_port->id; 552*743Smax.romanov@nginx.com init->ready_port.out_fd = main_port->pair[1]; 553*743Smax.romanov@nginx.com 554*743Smax.romanov@nginx.com nxt_fd_blocking(task, main_port->pair[1]); 555*743Smax.romanov@nginx.com 556*743Smax.romanov@nginx.com init->ready_stream = my_port->process->init->stream; 557*743Smax.romanov@nginx.com 558*743Smax.romanov@nginx.com init->read_port.id.pid = my_port->pid; 559*743Smax.romanov@nginx.com init->read_port.id.id = my_port->id; 560*743Smax.romanov@nginx.com init->read_port.in_fd = my_port->pair[0]; 561*743Smax.romanov@nginx.com 562*743Smax.romanov@nginx.com nxt_fd_blocking(task, my_port->pair[0]); 563*743Smax.romanov@nginx.com 564*743Smax.romanov@nginx.com init->log_fd = 2; 565*743Smax.romanov@nginx.com 566*743Smax.romanov@nginx.com return NXT_OK; 567*743Smax.romanov@nginx.com } 568