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