xref: /unit/src/nxt_application.c (revision 444)
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