xref: /unit/src/nxt_application.c (revision 233)
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>
12141Smax.romanov@nginx.com #include <nxt_master_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 
40216Sigor@sysoev.ru nxt_int_t
41216Sigor@sysoev.ru nxt_discovery_start(nxt_task_t *task, void *data)
42216Sigor@sysoev.ru {
43216Sigor@sysoev.ru     nxt_buf_t         *b;
44216Sigor@sysoev.ru     nxt_port_t        *main_port;
45216Sigor@sysoev.ru     nxt_runtime_t     *rt;
46216Sigor@sysoev.ru 
47216Sigor@sysoev.ru     nxt_debug(task, "DISCOVERY");
48216Sigor@sysoev.ru 
49*233Sigor@sysoev.ru     rt = task->thread->runtime;
50216Sigor@sysoev.ru 
51*233Sigor@sysoev.ru     b = nxt_discovery_modules(task, rt->modules);
52*233Sigor@sysoev.ru 
53216Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MASTER];
54216Sigor@sysoev.ru 
55216Sigor@sysoev.ru     nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1,
56216Sigor@sysoev.ru                           0, -1, b);
57216Sigor@sysoev.ru 
58216Sigor@sysoev.ru     return NXT_OK;
59216Sigor@sysoev.ru }
60216Sigor@sysoev.ru 
61216Sigor@sysoev.ru 
62216Sigor@sysoev.ru static void
63216Sigor@sysoev.ru nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data)
64216Sigor@sysoev.ru {
65216Sigor@sysoev.ru     nxt_mp_t   *mp;
66216Sigor@sysoev.ru     nxt_buf_t  *b;
67216Sigor@sysoev.ru 
68216Sigor@sysoev.ru     b = obj;
69216Sigor@sysoev.ru     mp = b->data;
70216Sigor@sysoev.ru 
71216Sigor@sysoev.ru     nxt_mp_destroy(mp);
72216Sigor@sysoev.ru 
73216Sigor@sysoev.ru     exit(0);
74216Sigor@sysoev.ru }
75216Sigor@sysoev.ru 
76216Sigor@sysoev.ru 
77216Sigor@sysoev.ru static nxt_buf_t *
78216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path)
79216Sigor@sysoev.ru {
80216Sigor@sysoev.ru     char          *name;
81216Sigor@sysoev.ru     u_char        *p, *end;
82216Sigor@sysoev.ru     size_t        size;
83216Sigor@sysoev.ru     glob_t        glb;
84216Sigor@sysoev.ru     nxt_mp_t      *mp;
85216Sigor@sysoev.ru     nxt_buf_t     *b;
86216Sigor@sysoev.ru     nxt_int_t     ret;
87216Sigor@sysoev.ru     nxt_uint_t    i, n;
88216Sigor@sysoev.ru     nxt_array_t   *modules;
89216Sigor@sysoev.ru     nxt_module_t  *module;
90216Sigor@sysoev.ru 
91216Sigor@sysoev.ru     b = NULL;
92216Sigor@sysoev.ru 
93216Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
94216Sigor@sysoev.ru     if (mp == NULL) {
95216Sigor@sysoev.ru         return b;
96216Sigor@sysoev.ru     }
97216Sigor@sysoev.ru 
98216Sigor@sysoev.ru     ret = glob(path, 0, NULL, &glb);
99216Sigor@sysoev.ru 
100216Sigor@sysoev.ru     if (ret == 0) {
101216Sigor@sysoev.ru         n = glb.gl_pathc;
102216Sigor@sysoev.ru 
103216Sigor@sysoev.ru         modules = nxt_array_create(mp, n, sizeof(nxt_module_t));
104216Sigor@sysoev.ru         if (modules == NULL) {
105216Sigor@sysoev.ru             goto fail;
106216Sigor@sysoev.ru         }
107216Sigor@sysoev.ru 
108216Sigor@sysoev.ru         for (i = 0; i < n; i++) {
109216Sigor@sysoev.ru             name = glb.gl_pathv[i];
110216Sigor@sysoev.ru 
111216Sigor@sysoev.ru             ret = nxt_discovery_module(task, mp, modules, name);
112216Sigor@sysoev.ru             if (ret != NXT_OK) {
113216Sigor@sysoev.ru                 goto fail;
114216Sigor@sysoev.ru             }
115216Sigor@sysoev.ru         }
116216Sigor@sysoev.ru 
117216Sigor@sysoev.ru         size = sizeof("[]") - 1;
118216Sigor@sysoev.ru         module = modules->elts;
119216Sigor@sysoev.ru         n = modules->nelts;
120216Sigor@sysoev.ru 
121216Sigor@sysoev.ru         for (i = 0; i < n; i++) {
122216Sigor@sysoev.ru             nxt_debug(task, "module: %V %V %V",
123216Sigor@sysoev.ru                       &module[i].type, &module[i].version, &module[i].file);
124216Sigor@sysoev.ru 
125216Sigor@sysoev.ru             size += sizeof("{\"type\": \"\",") - 1;
126216Sigor@sysoev.ru             size += sizeof(" \"version\": \"\",") - 1;
127216Sigor@sysoev.ru             size += sizeof(" \"file\": \"\"},") - 1;
128216Sigor@sysoev.ru 
129216Sigor@sysoev.ru             size += module[i].type.length
130216Sigor@sysoev.ru                     + module[i].version.length
131216Sigor@sysoev.ru                     + module[i].file.length;
132216Sigor@sysoev.ru         }
133216Sigor@sysoev.ru 
134216Sigor@sysoev.ru         b = nxt_buf_mem_alloc(mp, size, 0);
135216Sigor@sysoev.ru         if (b == NULL) {
136216Sigor@sysoev.ru             goto fail;
137216Sigor@sysoev.ru         }
138216Sigor@sysoev.ru 
139216Sigor@sysoev.ru         b->completion_handler = nxt_discovery_completion_handler;
140216Sigor@sysoev.ru 
141216Sigor@sysoev.ru         p = b->mem.free;
142216Sigor@sysoev.ru         end = b->mem.end;
143216Sigor@sysoev.ru         *p++ = '[';
144216Sigor@sysoev.ru 
145216Sigor@sysoev.ru         for (i = 0; i < n; i++) {
146216Sigor@sysoev.ru             p = nxt_sprintf(p, end,
147216Sigor@sysoev.ru                   "{\"type\": \"%V\", \"version\": \"%V\", \"file\": \"%V\"},",
148216Sigor@sysoev.ru                   &module[i].type, &module[i].version, &module[i].file);
149216Sigor@sysoev.ru         }
150216Sigor@sysoev.ru 
151216Sigor@sysoev.ru         *p++ = ']';
152216Sigor@sysoev.ru         b->mem.free = p;
153216Sigor@sysoev.ru     }
154216Sigor@sysoev.ru 
155216Sigor@sysoev.ru fail:
156216Sigor@sysoev.ru 
157216Sigor@sysoev.ru     globfree(&glb);
158216Sigor@sysoev.ru 
159216Sigor@sysoev.ru     return b;
160216Sigor@sysoev.ru }
161216Sigor@sysoev.ru 
162216Sigor@sysoev.ru 
163216Sigor@sysoev.ru static nxt_int_t
164216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
165216Sigor@sysoev.ru     const char *name)
166216Sigor@sysoev.ru {
167216Sigor@sysoev.ru     void                      *dl;
168216Sigor@sysoev.ru     nxt_str_t                 *s;
169216Sigor@sysoev.ru     nxt_int_t                 ret;
170216Sigor@sysoev.ru     nxt_uint_t                i, n;
171216Sigor@sysoev.ru     nxt_module_t              *module;
172216Sigor@sysoev.ru     nxt_application_module_t  *app;
173216Sigor@sysoev.ru 
174216Sigor@sysoev.ru     /*
175216Sigor@sysoev.ru      * Only memory allocation failure should return NXT_ERROR.
176216Sigor@sysoev.ru      * Any module processing errors are ignored.
177216Sigor@sysoev.ru      */
178216Sigor@sysoev.ru     ret = NXT_ERROR;
179216Sigor@sysoev.ru 
180216Sigor@sysoev.ru     dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
181216Sigor@sysoev.ru 
182216Sigor@sysoev.ru     if (dl == NULL) {
183216Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"",
184216Sigor@sysoev.ru                 name, dlerror());
185216Sigor@sysoev.ru         return NXT_OK;
186216Sigor@sysoev.ru     }
187216Sigor@sysoev.ru 
188216Sigor@sysoev.ru     app = dlsym(dl, "nxt_app_module");
189216Sigor@sysoev.ru 
190216Sigor@sysoev.ru     if (app != NULL) {
191216Sigor@sysoev.ru         nxt_log(task, NXT_LOG_NOTICE, "module: %V \"%s\"",
192216Sigor@sysoev.ru                 &app->version, name);
193216Sigor@sysoev.ru 
194216Sigor@sysoev.ru         module = modules->elts;
195216Sigor@sysoev.ru         n = modules->nelts;
196216Sigor@sysoev.ru 
197216Sigor@sysoev.ru         for (i = 0; i < n; i++) {
198216Sigor@sysoev.ru             if (nxt_strstr_eq(&app->version, &module[i].version)) {
199216Sigor@sysoev.ru                 nxt_log(task, NXT_LOG_NOTICE,
200216Sigor@sysoev.ru                         "ignoring %s module with the same "
201216Sigor@sysoev.ru                         "application language version %V as in %s",
202216Sigor@sysoev.ru                         name, &module[i].version, &module[i].file);
203216Sigor@sysoev.ru 
204216Sigor@sysoev.ru                 goto done;
205216Sigor@sysoev.ru             }
206216Sigor@sysoev.ru         }
207216Sigor@sysoev.ru 
208216Sigor@sysoev.ru         module = nxt_array_add(modules);
209216Sigor@sysoev.ru         if (module == NULL) {
210216Sigor@sysoev.ru             goto fail;
211216Sigor@sysoev.ru         }
212216Sigor@sysoev.ru 
213216Sigor@sysoev.ru         s = nxt_str_dup(mp, &module->type, &app->type);
214216Sigor@sysoev.ru         if (s == NULL) {
215216Sigor@sysoev.ru             goto fail;
216216Sigor@sysoev.ru         }
217216Sigor@sysoev.ru 
218216Sigor@sysoev.ru         s = nxt_str_dup(mp, &module->version, &app->version);
219216Sigor@sysoev.ru         if (s == NULL) {
220216Sigor@sysoev.ru             goto fail;
221216Sigor@sysoev.ru         }
222216Sigor@sysoev.ru 
223216Sigor@sysoev.ru         module->file.length = nxt_strlen(name);
224216Sigor@sysoev.ru 
225216Sigor@sysoev.ru         module->file.start = nxt_mp_alloc(mp, module->file.length);
226216Sigor@sysoev.ru         if (module->file.start == NULL) {
227216Sigor@sysoev.ru             goto fail;
228216Sigor@sysoev.ru         }
229216Sigor@sysoev.ru 
230216Sigor@sysoev.ru         nxt_memcpy(module->file.start, name, module->file.length);
231216Sigor@sysoev.ru 
232216Sigor@sysoev.ru     } else {
233216Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "dlsym(\"%s\"), failed: \"%s\"",
234216Sigor@sysoev.ru                 name, dlerror());
235216Sigor@sysoev.ru     }
236216Sigor@sysoev.ru 
237216Sigor@sysoev.ru done:
238216Sigor@sysoev.ru 
239216Sigor@sysoev.ru     ret = NXT_OK;
240216Sigor@sysoev.ru 
241216Sigor@sysoev.ru fail:
242216Sigor@sysoev.ru 
243216Sigor@sysoev.ru     if (dlclose(dl) != 0) {
244216Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "dlclose(\"%s\"), failed: \"%s\"",
245216Sigor@sysoev.ru                 name, dlerror());
246216Sigor@sysoev.ru     }
247216Sigor@sysoev.ru 
248216Sigor@sysoev.ru     return ret;
249216Sigor@sysoev.ru }
250216Sigor@sysoev.ru 
251216Sigor@sysoev.ru 
2520Sigor@sysoev.ru nxt_int_t
253141Smax.romanov@nginx.com nxt_app_start(nxt_task_t *task, void *data)
2540Sigor@sysoev.ru {
255216Sigor@sysoev.ru     nxt_int_t              ret;
256216Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
257216Sigor@sysoev.ru     nxt_common_app_conf_t  *app_conf;
258141Smax.romanov@nginx.com 
259141Smax.romanov@nginx.com     app_conf = data;
260141Smax.romanov@nginx.com 
261216Sigor@sysoev.ru     lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type);
262216Sigor@sysoev.ru     if (nxt_slow_path(lang == NULL)) {
263216Sigor@sysoev.ru         nxt_log(task, NXT_LOG_CRIT, "unknown application type: \"%V\"",
264216Sigor@sysoev.ru                 &app_conf->type);
265216Sigor@sysoev.ru         return NXT_ERROR;
266216Sigor@sysoev.ru     }
267216Sigor@sysoev.ru 
268216Sigor@sysoev.ru     nxt_app = lang->module;
269216Sigor@sysoev.ru 
270216Sigor@sysoev.ru     if (nxt_app == NULL) {
271216Sigor@sysoev.ru         nxt_debug(task, "application language module: %V \"%s\"",
272216Sigor@sysoev.ru                   &lang->version, lang->file);
273216Sigor@sysoev.ru 
274216Sigor@sysoev.ru         nxt_app = nxt_app_module_load(task, lang->file);
275216Sigor@sysoev.ru     }
276216Sigor@sysoev.ru 
2770Sigor@sysoev.ru     if (nxt_slow_path(nxt_thread_mutex_create(&nxt_app_mutex) != NXT_OK)) {
2780Sigor@sysoev.ru         return NXT_ERROR;
2790Sigor@sysoev.ru     }
2800Sigor@sysoev.ru 
2810Sigor@sysoev.ru     if (nxt_slow_path(nxt_thread_cond_create(&nxt_app_cond) != NXT_OK)) {
2820Sigor@sysoev.ru         return NXT_ERROR;
2830Sigor@sysoev.ru     }
2840Sigor@sysoev.ru 
285141Smax.romanov@nginx.com     ret = nxt_app->init(task, data);
286141Smax.romanov@nginx.com 
287141Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
28884Smax.romanov@nginx.com         nxt_debug(task, "application init failed");
289141Smax.romanov@nginx.com 
290141Smax.romanov@nginx.com     } else {
291141Smax.romanov@nginx.com         nxt_debug(task, "application init done");
29220Sigor@sysoev.ru     }
29320Sigor@sysoev.ru 
294141Smax.romanov@nginx.com     return ret;
29520Sigor@sysoev.ru }
29620Sigor@sysoev.ru 
29720Sigor@sysoev.ru 
298216Sigor@sysoev.ru static nxt_app_module_t *
299216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name)
300216Sigor@sysoev.ru {
301216Sigor@sysoev.ru     void  *dl;
302216Sigor@sysoev.ru 
303216Sigor@sysoev.ru     dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY);
304216Sigor@sysoev.ru 
305216Sigor@sysoev.ru     if (dl != NULL) {
306216Sigor@sysoev.ru         return dlsym(dl, "nxt_app_module");
307216Sigor@sysoev.ru     }
308216Sigor@sysoev.ru 
309216Sigor@sysoev.ru     nxt_log(task, NXT_LOG_CRIT, "dlopen(\"%s\"), failed: \"%s\"",
310216Sigor@sysoev.ru             name, dlerror());
311216Sigor@sysoev.ru 
312216Sigor@sysoev.ru     return NULL;
313216Sigor@sysoev.ru }
314216Sigor@sysoev.ru 
315216Sigor@sysoev.ru 
31684Smax.romanov@nginx.com nxt_int_t
31784Smax.romanov@nginx.com nxt_app_http_init(nxt_task_t *task, nxt_runtime_t *rt)
3180Sigor@sysoev.ru {
31984Smax.romanov@nginx.com     nxt_http_fields_hash_t  *hash;
3200Sigor@sysoev.ru 
32184Smax.romanov@nginx.com     hash = nxt_http_fields_hash_create(nxt_app_request_fields, rt->mem_pool);
32284Smax.romanov@nginx.com     if (nxt_slow_path(hash == NULL)) {
32384Smax.romanov@nginx.com         return NXT_ERROR;
3240Sigor@sysoev.ru     }
3250Sigor@sysoev.ru 
32684Smax.romanov@nginx.com     nxt_app_request_fields_hash = hash;
3270Sigor@sysoev.ru 
32884Smax.romanov@nginx.com     return NXT_OK;
32984Smax.romanov@nginx.com }
3304Sigor@sysoev.ru 
3310Sigor@sysoev.ru 
33284Smax.romanov@nginx.com void
33384Smax.romanov@nginx.com nxt_port_app_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
33484Smax.romanov@nginx.com {
33584Smax.romanov@nginx.com     size_t          dump_size;
33684Smax.romanov@nginx.com     nxt_buf_t       *b;
33784Smax.romanov@nginx.com     nxt_port_t      *port;
33884Smax.romanov@nginx.com     nxt_app_rmsg_t  rmsg = { msg->buf };
33984Smax.romanov@nginx.com     nxt_app_wmsg_t  wmsg;
3400Sigor@sysoev.ru 
34184Smax.romanov@nginx.com     b = msg->buf;
34284Smax.romanov@nginx.com     dump_size = b->mem.free - b->mem.pos;
3430Sigor@sysoev.ru 
34484Smax.romanov@nginx.com     if (dump_size > 300) {
34584Smax.romanov@nginx.com         dump_size = 300;
34684Smax.romanov@nginx.com     }
3470Sigor@sysoev.ru 
34884Smax.romanov@nginx.com     nxt_debug(task, "app data: %*s ...", dump_size, b->mem.pos);
3490Sigor@sysoev.ru 
35084Smax.romanov@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
35184Smax.romanov@nginx.com                                  msg->port_msg.reply_port);
35284Smax.romanov@nginx.com     if (nxt_slow_path(port == NULL)) {
35384Smax.romanov@nginx.com         //
35484Smax.romanov@nginx.com     }
3554Sigor@sysoev.ru 
35684Smax.romanov@nginx.com     wmsg.port = port;
35784Smax.romanov@nginx.com     wmsg.write = NULL;
35884Smax.romanov@nginx.com     wmsg.buf = &wmsg.write;
35984Smax.romanov@nginx.com     wmsg.stream = msg->port_msg.stream;
3600Sigor@sysoev.ru 
36184Smax.romanov@nginx.com     nxt_app->run(task, &rmsg, &wmsg);
3620Sigor@sysoev.ru }
3630Sigor@sysoev.ru 
3640Sigor@sysoev.ru 
36584Smax.romanov@nginx.com nxt_inline nxt_port_t *
36684Smax.romanov@nginx.com nxt_app_msg_get_port(nxt_task_t *task, nxt_app_wmsg_t *msg)
3670Sigor@sysoev.ru {
36884Smax.romanov@nginx.com     return msg->port;
36984Smax.romanov@nginx.com }
37084Smax.romanov@nginx.com 
37184Smax.romanov@nginx.com 
37284Smax.romanov@nginx.com u_char *
37384Smax.romanov@nginx.com nxt_app_msg_write_get_buf(nxt_task_t *task, nxt_app_wmsg_t *msg, size_t size)
37484Smax.romanov@nginx.com {
37584Smax.romanov@nginx.com     size_t      free_size;
37684Smax.romanov@nginx.com     u_char      *res;
37784Smax.romanov@nginx.com     nxt_buf_t   *b;
37884Smax.romanov@nginx.com     nxt_port_t  *port;
3790Sigor@sysoev.ru 
38084Smax.romanov@nginx.com     res = NULL;
38184Smax.romanov@nginx.com 
38284Smax.romanov@nginx.com     do {
38384Smax.romanov@nginx.com         b = *msg->buf;
3840Sigor@sysoev.ru 
38584Smax.romanov@nginx.com         if (b == NULL) {
38684Smax.romanov@nginx.com             port = nxt_app_msg_get_port(task, msg);
38784Smax.romanov@nginx.com             if (nxt_slow_path(port == NULL)) {
38884Smax.romanov@nginx.com                 return NULL;
38984Smax.romanov@nginx.com             }
39084Smax.romanov@nginx.com 
39184Smax.romanov@nginx.com             b = nxt_port_mmap_get_buf(task, port, size);
39284Smax.romanov@nginx.com             if (nxt_slow_path(b == NULL)) {
39384Smax.romanov@nginx.com                 return NULL;
39484Smax.romanov@nginx.com             }
3950Sigor@sysoev.ru 
39684Smax.romanov@nginx.com             *msg->buf = b;
39784Smax.romanov@nginx.com 
39884Smax.romanov@nginx.com             free_size = nxt_buf_mem_free_size(&b->mem);
3990Sigor@sysoev.ru 
40084Smax.romanov@nginx.com             if (nxt_slow_path(free_size < size)) {
40184Smax.romanov@nginx.com                 nxt_debug(task, "requested buffer too big (%z < %z)",
40284Smax.romanov@nginx.com                           free_size, size);
40384Smax.romanov@nginx.com                 return NULL;
40484Smax.romanov@nginx.com             }
40584Smax.romanov@nginx.com 
40684Smax.romanov@nginx.com         }
40784Smax.romanov@nginx.com 
40884Smax.romanov@nginx.com         free_size = nxt_buf_mem_free_size(&b->mem);
4090Sigor@sysoev.ru 
41084Smax.romanov@nginx.com         if (free_size >= size) {
41184Smax.romanov@nginx.com             res = b->mem.free;
41284Smax.romanov@nginx.com             b->mem.free += size;
41384Smax.romanov@nginx.com 
41484Smax.romanov@nginx.com             return res;
41584Smax.romanov@nginx.com         }
4161Sigor@sysoev.ru 
417206Smax.romanov@nginx.com         if (nxt_port_mmap_increase_buf(task, b, size, size) == NXT_OK) {
41884Smax.romanov@nginx.com             res = b->mem.free;
41984Smax.romanov@nginx.com             b->mem.free += size;
4200Sigor@sysoev.ru 
42184Smax.romanov@nginx.com             return res;
42284Smax.romanov@nginx.com         }
42384Smax.romanov@nginx.com 
42484Smax.romanov@nginx.com         msg->buf = &b->next;
42584Smax.romanov@nginx.com     } while(1);
4260Sigor@sysoev.ru }
4270Sigor@sysoev.ru 
4280Sigor@sysoev.ru 
42984Smax.romanov@nginx.com nxt_int_t
43084Smax.romanov@nginx.com nxt_app_msg_write(nxt_task_t *task, nxt_app_wmsg_t *msg, u_char *c, size_t size)
4310Sigor@sysoev.ru {
43284Smax.romanov@nginx.com     u_char  *dst;
43384Smax.romanov@nginx.com     size_t  dst_length;
4340Sigor@sysoev.ru 
43584Smax.romanov@nginx.com     if (c != NULL) {
43684Smax.romanov@nginx.com         dst_length = size + (size < 128 ? 1 : 4) + 1;
4370Sigor@sysoev.ru 
43884Smax.romanov@nginx.com         dst = nxt_app_msg_write_get_buf(task, msg, dst_length);
43984Smax.romanov@nginx.com         if (nxt_slow_path(dst == NULL)) {
44084Smax.romanov@nginx.com             nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed",
44184Smax.romanov@nginx.com                       dst_length);
44284Smax.romanov@nginx.com             return NXT_ERROR;
4430Sigor@sysoev.ru         }
4440Sigor@sysoev.ru 
44584Smax.romanov@nginx.com         dst = nxt_app_msg_write_length(dst, size + 1); /* +1 for trailing 0 */
4460Sigor@sysoev.ru 
44784Smax.romanov@nginx.com         nxt_memcpy(dst, c, size);
44884Smax.romanov@nginx.com         dst[size] = 0;
4490Sigor@sysoev.ru 
45084Smax.romanov@nginx.com         nxt_debug(task, "nxt_app_msg_write: %uz %*s", size, (int)size, c);
45184Smax.romanov@nginx.com     } else {
45284Smax.romanov@nginx.com         dst_length = 1;
4530Sigor@sysoev.ru 
45484Smax.romanov@nginx.com         dst = nxt_app_msg_write_get_buf(task, msg, dst_length);
45584Smax.romanov@nginx.com         if (nxt_slow_path(dst == NULL)) {
45684Smax.romanov@nginx.com             nxt_debug(task, "nxt_app_msg_write: get_buf(%uz) failed",
45784Smax.romanov@nginx.com                       dst_length);
45884Smax.romanov@nginx.com             return NXT_ERROR;
4590Sigor@sysoev.ru         }
4600Sigor@sysoev.ru 
46184Smax.romanov@nginx.com         dst = nxt_app_msg_write_length(dst, 0);
46284Smax.romanov@nginx.com 
46384Smax.romanov@nginx.com         nxt_debug(task, "nxt_app_msg_write: NULL");
4640Sigor@sysoev.ru     }
4650Sigor@sysoev.ru 
46684Smax.romanov@nginx.com     return NXT_OK;
4670Sigor@sysoev.ru }
4680Sigor@sysoev.ru 
4690Sigor@sysoev.ru 
47084Smax.romanov@nginx.com nxt_int_t
47184Smax.romanov@nginx.com nxt_app_msg_write_prefixed_upcase(nxt_task_t *task, nxt_app_wmsg_t *msg,
47284Smax.romanov@nginx.com     const nxt_str_t *prefix, const nxt_str_t *v)
4730Sigor@sysoev.ru {
47484Smax.romanov@nginx.com     u_char  *dst, *src;
47584Smax.romanov@nginx.com     size_t  i, length, dst_length;
47684Smax.romanov@nginx.com 
47784Smax.romanov@nginx.com     length = prefix->length + v->length;
4780Sigor@sysoev.ru 
47984Smax.romanov@nginx.com     dst_length = length + (length < 128 ? 1 : 4) + 1;
48084Smax.romanov@nginx.com 
48184Smax.romanov@nginx.com     dst = nxt_app_msg_write_get_buf(task, msg, dst_length);
48284Smax.romanov@nginx.com     if (nxt_slow_path(dst == NULL)) {
48384Smax.romanov@nginx.com         return NXT_ERROR;
4840Sigor@sysoev.ru     }
4850Sigor@sysoev.ru 
48684Smax.romanov@nginx.com     dst = nxt_app_msg_write_length(dst, length + 1); /* +1 for trailing 0 */
48784Smax.romanov@nginx.com 
48884Smax.romanov@nginx.com     nxt_memcpy(dst, prefix->start, prefix->length);
48984Smax.romanov@nginx.com     dst += prefix->length;
4900Sigor@sysoev.ru 
49184Smax.romanov@nginx.com     src = v->start;
49284Smax.romanov@nginx.com     for (i = 0; i < v->length; i++, dst++, src++) {
49384Smax.romanov@nginx.com 
49484Smax.romanov@nginx.com         if (*src >= 'a' && *src <= 'z') {
49584Smax.romanov@nginx.com             *dst = *src & ~0x20;
49684Smax.romanov@nginx.com             continue;
4970Sigor@sysoev.ru         }
4980Sigor@sysoev.ru 
49984Smax.romanov@nginx.com         if (*src == '-') {
50084Smax.romanov@nginx.com             *dst = '_';
50184Smax.romanov@nginx.com             continue;
5020Sigor@sysoev.ru         }
5030Sigor@sysoev.ru 
50484Smax.romanov@nginx.com         *dst = *src;
5050Sigor@sysoev.ru     }
5060Sigor@sysoev.ru 
50784Smax.romanov@nginx.com     *dst = 0;
5080Sigor@sysoev.ru 
50984Smax.romanov@nginx.com     return NXT_OK;
5100Sigor@sysoev.ru }
5110Sigor@sysoev.ru 
5120Sigor@sysoev.ru 
51384Smax.romanov@nginx.com nxt_int_t
51484Smax.romanov@nginx.com nxt_app_msg_read_str(nxt_task_t *task, nxt_app_rmsg_t *msg, nxt_str_t *str)
5150Sigor@sysoev.ru {
51684Smax.romanov@nginx.com     size_t     length;
51784Smax.romanov@nginx.com     nxt_buf_t  *buf;
5180Sigor@sysoev.ru 
51984Smax.romanov@nginx.com     do {
52084Smax.romanov@nginx.com         buf = msg->buf;
52184Smax.romanov@nginx.com 
52284Smax.romanov@nginx.com         if (nxt_slow_path(buf == NULL)) {
52384Smax.romanov@nginx.com             return NXT_DONE;
5240Sigor@sysoev.ru         }
5250Sigor@sysoev.ru 
52684Smax.romanov@nginx.com         if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) {
52784Smax.romanov@nginx.com             if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) {
52884Smax.romanov@nginx.com                 msg->buf = buf->next;
52984Smax.romanov@nginx.com                 continue;
53084Smax.romanov@nginx.com             }
53184Smax.romanov@nginx.com             return NXT_ERROR;
5320Sigor@sysoev.ru         }
5330Sigor@sysoev.ru 
53484Smax.romanov@nginx.com         if (buf->mem.pos[0] >= 128) {
53584Smax.romanov@nginx.com             if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) {
53684Smax.romanov@nginx.com                 return NXT_ERROR;
53784Smax.romanov@nginx.com             }
53884Smax.romanov@nginx.com         }
5390Sigor@sysoev.ru 
54084Smax.romanov@nginx.com         break;
54184Smax.romanov@nginx.com     } while (1);
5420Sigor@sysoev.ru 
54384Smax.romanov@nginx.com     buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, &length);
54484Smax.romanov@nginx.com 
54584Smax.romanov@nginx.com     if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < (intptr_t)length))
54684Smax.romanov@nginx.com     {
54784Smax.romanov@nginx.com         return NXT_ERROR;
5480Sigor@sysoev.ru     }
5490Sigor@sysoev.ru 
55084Smax.romanov@nginx.com     if (length > 0) {
55184Smax.romanov@nginx.com         str->start = buf->mem.pos;
55284Smax.romanov@nginx.com         str->length = length - 1;
5530Sigor@sysoev.ru 
55484Smax.romanov@nginx.com         buf->mem.pos += length;
5550Sigor@sysoev.ru 
55684Smax.romanov@nginx.com         nxt_debug(task, "nxt_read_str: %d %*s", (int)length - 1,
55784Smax.romanov@nginx.com                         (int)length - 1, str->start);
55884Smax.romanov@nginx.com     } else {
55984Smax.romanov@nginx.com         str->start = NULL;
56084Smax.romanov@nginx.com         str->length = 0;
5610Sigor@sysoev.ru 
56284Smax.romanov@nginx.com         nxt_debug(task, "nxt_read_str: NULL");
5630Sigor@sysoev.ru     }
5640Sigor@sysoev.ru 
5650Sigor@sysoev.ru     return NXT_OK;
5660Sigor@sysoev.ru }
5670Sigor@sysoev.ru 
5680Sigor@sysoev.ru 
569206Smax.romanov@nginx.com size_t
570206Smax.romanov@nginx.com nxt_app_msg_read_raw(nxt_task_t *task, nxt_app_rmsg_t *msg, void *dst,
571206Smax.romanov@nginx.com     size_t size)
572206Smax.romanov@nginx.com {
573206Smax.romanov@nginx.com     size_t     res, read_size;
574206Smax.romanov@nginx.com     nxt_buf_t  *buf;
575206Smax.romanov@nginx.com 
576206Smax.romanov@nginx.com     res = 0;
577206Smax.romanov@nginx.com 
578206Smax.romanov@nginx.com     while (size > 0) {
579206Smax.romanov@nginx.com         buf = msg->buf;
580206Smax.romanov@nginx.com 
581206Smax.romanov@nginx.com         if (nxt_slow_path(buf == NULL)) {
582206Smax.romanov@nginx.com             break;
583206Smax.romanov@nginx.com         }
584206Smax.romanov@nginx.com 
585206Smax.romanov@nginx.com         if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) == 0)) {
586206Smax.romanov@nginx.com             msg->buf = buf->next;
587206Smax.romanov@nginx.com             continue;
588206Smax.romanov@nginx.com         }
589206Smax.romanov@nginx.com 
590206Smax.romanov@nginx.com         read_size = nxt_buf_mem_used_size(&buf->mem);
591206Smax.romanov@nginx.com         read_size = nxt_min(read_size, size);
592206Smax.romanov@nginx.com 
593206Smax.romanov@nginx.com         dst = nxt_cpymem(dst, buf->mem.pos, read_size);
594206Smax.romanov@nginx.com 
595206Smax.romanov@nginx.com         size -= read_size;
596206Smax.romanov@nginx.com         buf->mem.pos += read_size;
597206Smax.romanov@nginx.com         res += read_size;
598206Smax.romanov@nginx.com     }
599206Smax.romanov@nginx.com 
600206Smax.romanov@nginx.com     nxt_debug(task, "nxt_read_raw: %uz", res);
601206Smax.romanov@nginx.com 
602206Smax.romanov@nginx.com     return res;
603206Smax.romanov@nginx.com }
604206Smax.romanov@nginx.com 
605206Smax.romanov@nginx.com 
60684Smax.romanov@nginx.com nxt_int_t
60784Smax.romanov@nginx.com nxt_app_msg_read_nvp(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_str_t *n,
60884Smax.romanov@nginx.com     nxt_str_t *v)
6090Sigor@sysoev.ru {
61084Smax.romanov@nginx.com     nxt_int_t rc;
6110Sigor@sysoev.ru 
61284Smax.romanov@nginx.com     rc = nxt_app_msg_read_str(task, rmsg, n);
61384Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_OK)) {
61484Smax.romanov@nginx.com         return rc;
6150Sigor@sysoev.ru     }
6160Sigor@sysoev.ru 
61784Smax.romanov@nginx.com     rc = nxt_app_msg_read_str(task, rmsg, v);
61884Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_OK)) {
61984Smax.romanov@nginx.com         return rc;
62084Smax.romanov@nginx.com     }
6210Sigor@sysoev.ru 
62284Smax.romanov@nginx.com     return rc;
6230Sigor@sysoev.ru }
6240Sigor@sysoev.ru 
6250Sigor@sysoev.ru 
6260Sigor@sysoev.ru nxt_int_t
62784Smax.romanov@nginx.com nxt_app_msg_read_size(nxt_task_t *task, nxt_app_rmsg_t *msg, size_t *size)
6280Sigor@sysoev.ru {
62984Smax.romanov@nginx.com     nxt_buf_t  *buf;
6300Sigor@sysoev.ru 
63184Smax.romanov@nginx.com     do {
63284Smax.romanov@nginx.com         buf = msg->buf;
6330Sigor@sysoev.ru 
63484Smax.romanov@nginx.com         if (nxt_slow_path(buf == NULL)) {
63584Smax.romanov@nginx.com             return NXT_DONE;
63684Smax.romanov@nginx.com         }
6370Sigor@sysoev.ru 
63884Smax.romanov@nginx.com         if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 1)) {
63984Smax.romanov@nginx.com             if (nxt_fast_path(nxt_buf_mem_used_size(&buf->mem) == 0)) {
64084Smax.romanov@nginx.com                 msg->buf = buf->next;
64184Smax.romanov@nginx.com                 continue;
64284Smax.romanov@nginx.com             }
6430Sigor@sysoev.ru             return NXT_ERROR;
6440Sigor@sysoev.ru         }
6450Sigor@sysoev.ru 
64684Smax.romanov@nginx.com         if (buf->mem.pos[0] >= 128) {
64784Smax.romanov@nginx.com             if (nxt_slow_path(nxt_buf_mem_used_size(&buf->mem) < 4)) {
64884Smax.romanov@nginx.com                 return NXT_ERROR;
64984Smax.romanov@nginx.com             }
65084Smax.romanov@nginx.com         }
6510Sigor@sysoev.ru 
65284Smax.romanov@nginx.com         break;
65384Smax.romanov@nginx.com     } while (1);
6540Sigor@sysoev.ru 
65584Smax.romanov@nginx.com     buf->mem.pos = nxt_app_msg_read_length(buf->mem.pos, size);
65684Smax.romanov@nginx.com 
65784Smax.romanov@nginx.com     nxt_debug(task, "nxt_read_size: %d", (int)*size);
6580Sigor@sysoev.ru 
6590Sigor@sysoev.ru     return NXT_OK;
6600Sigor@sysoev.ru }
6610Sigor@sysoev.ru 
6620Sigor@sysoev.ru 
66384Smax.romanov@nginx.com static nxt_int_t
66484Smax.romanov@nginx.com nxt_app_request_content_length(void *ctx, nxt_http_field_t *field,
66584Smax.romanov@nginx.com     nxt_log_t *log)
6660Sigor@sysoev.ru {
66784Smax.romanov@nginx.com     nxt_str_t                 *v;
66884Smax.romanov@nginx.com     nxt_app_parse_ctx_t       *c;
66984Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
6700Sigor@sysoev.ru 
67184Smax.romanov@nginx.com     c = ctx;
67284Smax.romanov@nginx.com     h = &c->r.header;
67384Smax.romanov@nginx.com     v = &field->value;
6740Sigor@sysoev.ru 
67584Smax.romanov@nginx.com     h->content_length = *v;
67684Smax.romanov@nginx.com     h->parsed_content_length = nxt_off_t_parse(v->start, v->length);
6770Sigor@sysoev.ru 
67884Smax.romanov@nginx.com     return NXT_OK;
67984Smax.romanov@nginx.com }
6800Sigor@sysoev.ru 
6810Sigor@sysoev.ru 
68284Smax.romanov@nginx.com static nxt_int_t
68384Smax.romanov@nginx.com nxt_app_request_content_type(void *ctx, nxt_http_field_t *field,
68484Smax.romanov@nginx.com     nxt_log_t *log)
68584Smax.romanov@nginx.com {
68684Smax.romanov@nginx.com     nxt_app_parse_ctx_t       *c;
68784Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
6880Sigor@sysoev.ru 
68984Smax.romanov@nginx.com     c = ctx;
69084Smax.romanov@nginx.com     h = &c->r.header;
6910Sigor@sysoev.ru 
69284Smax.romanov@nginx.com     h->content_type = field->value;
6930Sigor@sysoev.ru 
69484Smax.romanov@nginx.com     return NXT_OK;
69584Smax.romanov@nginx.com }
6960Sigor@sysoev.ru 
6974Sigor@sysoev.ru 
69884Smax.romanov@nginx.com static nxt_int_t
69984Smax.romanov@nginx.com nxt_app_request_cookie(void *ctx, nxt_http_field_t *field,
70084Smax.romanov@nginx.com     nxt_log_t *log)
70184Smax.romanov@nginx.com {
70284Smax.romanov@nginx.com     nxt_app_parse_ctx_t       *c;
70384Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
7040Sigor@sysoev.ru 
70584Smax.romanov@nginx.com     c = ctx;
70684Smax.romanov@nginx.com     h = &c->r.header;
7070Sigor@sysoev.ru 
70884Smax.romanov@nginx.com     h->cookie = field->value;
7090Sigor@sysoev.ru 
7100Sigor@sysoev.ru     return NXT_OK;
7110Sigor@sysoev.ru }
7120Sigor@sysoev.ru 
7130Sigor@sysoev.ru 
7140Sigor@sysoev.ru static nxt_int_t
71584Smax.romanov@nginx.com nxt_app_request_host(void *ctx, nxt_http_field_t *field,
71684Smax.romanov@nginx.com     nxt_log_t *log)
7170Sigor@sysoev.ru {
71884Smax.romanov@nginx.com     nxt_app_parse_ctx_t       *c;
71984Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
72084Smax.romanov@nginx.com 
72184Smax.romanov@nginx.com     c = ctx;
72284Smax.romanov@nginx.com     h = &c->r.header;
72384Smax.romanov@nginx.com 
72484Smax.romanov@nginx.com     h->host = field->value;
72584Smax.romanov@nginx.com 
72684Smax.romanov@nginx.com     return NXT_OK;
72784Smax.romanov@nginx.com }
72884Smax.romanov@nginx.com 
7290Sigor@sysoev.ru 
73084Smax.romanov@nginx.com static nxt_http_fields_hash_entry_t  nxt_app_request_fields[] = {
73184Smax.romanov@nginx.com     { nxt_string("Content-Length"), &nxt_app_request_content_length, 0 },
73284Smax.romanov@nginx.com     { nxt_string("Content-Type"), &nxt_app_request_content_type, 0 },
73384Smax.romanov@nginx.com     { nxt_string("Cookie"), &nxt_app_request_cookie, 0 },
73484Smax.romanov@nginx.com     { nxt_string("Host"), &nxt_app_request_host, 0 },
73584Smax.romanov@nginx.com 
73684Smax.romanov@nginx.com     { nxt_null_string, NULL, 0 }
73784Smax.romanov@nginx.com };
73884Smax.romanov@nginx.com 
73984Smax.romanov@nginx.com 
74084Smax.romanov@nginx.com nxt_int_t
74184Smax.romanov@nginx.com nxt_app_http_req_init(nxt_task_t *task, nxt_app_parse_ctx_t *ctx)
74284Smax.romanov@nginx.com {
74384Smax.romanov@nginx.com     nxt_int_t  rc;
74484Smax.romanov@nginx.com 
74584Smax.romanov@nginx.com     ctx->mem_pool = nxt_mp_create(1024, 128, 256, 32);
74684Smax.romanov@nginx.com 
74784Smax.romanov@nginx.com     rc = nxt_http_parse_request_init(&ctx->parser, ctx->mem_pool);
74884Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_OK)) {
74984Smax.romanov@nginx.com         return rc;
7500Sigor@sysoev.ru     }
7510Sigor@sysoev.ru 
75284Smax.romanov@nginx.com     ctx->parser.fields_hash = nxt_app_request_fields_hash;
7530Sigor@sysoev.ru 
7540Sigor@sysoev.ru     return NXT_OK;
7550Sigor@sysoev.ru }
7560Sigor@sysoev.ru 
7570Sigor@sysoev.ru 
75884Smax.romanov@nginx.com nxt_int_t
759206Smax.romanov@nginx.com nxt_app_http_req_header_parse(nxt_task_t *task, nxt_app_parse_ctx_t *ctx,
76084Smax.romanov@nginx.com     nxt_buf_t *buf)
7610Sigor@sysoev.ru {
76284Smax.romanov@nginx.com     nxt_int_t                 rc;
76384Smax.romanov@nginx.com     nxt_app_request_body_t    *b;
76484Smax.romanov@nginx.com     nxt_http_request_parse_t  *p;
76584Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
7660Sigor@sysoev.ru 
76784Smax.romanov@nginx.com     p = &ctx->parser;
76884Smax.romanov@nginx.com     b = &ctx->r.body;
76984Smax.romanov@nginx.com     h = &ctx->r.header;
7700Sigor@sysoev.ru 
771206Smax.romanov@nginx.com     nxt_assert(h->done == 0);
77284Smax.romanov@nginx.com 
773206Smax.romanov@nginx.com     rc = nxt_http_parse_request(p, &buf->mem);
7740Sigor@sysoev.ru 
775206Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_DONE)) {
776206Smax.romanov@nginx.com         return rc;
777206Smax.romanov@nginx.com     }
7780Sigor@sysoev.ru 
779206Smax.romanov@nginx.com     rc = nxt_http_fields_process(p->fields, ctx, task->log);
7800Sigor@sysoev.ru 
781206Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_OK)) {
782206Smax.romanov@nginx.com         return rc;
78313Sigor@sysoev.ru     }
78413Sigor@sysoev.ru 
785206Smax.romanov@nginx.com     h->fields = p->fields;
786206Smax.romanov@nginx.com     h->done = 1;
787206Smax.romanov@nginx.com 
788206Smax.romanov@nginx.com     h->version.start = p->version.str;
789206Smax.romanov@nginx.com     h->version.length = nxt_strlen(p->version.str);
790206Smax.romanov@nginx.com 
791206Smax.romanov@nginx.com     h->method = p->method;
79284Smax.romanov@nginx.com 
793206Smax.romanov@nginx.com     h->target.start = p->target_start;
794206Smax.romanov@nginx.com     h->target.length = p->target_end - p->target_start;
795206Smax.romanov@nginx.com 
796206Smax.romanov@nginx.com     h->path = p->path;
797206Smax.romanov@nginx.com     h->query = p->args;
798206Smax.romanov@nginx.com 
799206Smax.romanov@nginx.com     if (h->parsed_content_length == 0) {
800206Smax.romanov@nginx.com         b->done = 1;
801206Smax.romanov@nginx.com 
80284Smax.romanov@nginx.com     }
80384Smax.romanov@nginx.com 
804206Smax.romanov@nginx.com     if (buf->mem.free == buf->mem.pos) {
80584Smax.romanov@nginx.com         return NXT_DONE;
80684Smax.romanov@nginx.com     }
80784Smax.romanov@nginx.com 
808206Smax.romanov@nginx.com     b->buf = buf;
809206Smax.romanov@nginx.com     b->done = nxt_buf_mem_used_size(&buf->mem) >=
810206Smax.romanov@nginx.com               h->parsed_content_length;
811206Smax.romanov@nginx.com 
812206Smax.romanov@nginx.com     if (b->done == 1) {
813206Smax.romanov@nginx.com         b->preread_size = nxt_buf_mem_used_size(&buf->mem);
814206Smax.romanov@nginx.com     }
815206Smax.romanov@nginx.com 
816206Smax.romanov@nginx.com     return NXT_DONE;
817206Smax.romanov@nginx.com }
818206Smax.romanov@nginx.com 
819206Smax.romanov@nginx.com 
820206Smax.romanov@nginx.com nxt_int_t
821206Smax.romanov@nginx.com nxt_app_http_req_body_read(nxt_task_t *task, nxt_app_parse_ctx_t *ctx,
822206Smax.romanov@nginx.com     nxt_buf_t *buf)
823206Smax.romanov@nginx.com {
824206Smax.romanov@nginx.com     nxt_app_request_body_t    *b;
825206Smax.romanov@nginx.com     nxt_app_request_header_t  *h;
826206Smax.romanov@nginx.com 
827206Smax.romanov@nginx.com     b = &ctx->r.body;
828206Smax.romanov@nginx.com     h = &ctx->r.header;
829206Smax.romanov@nginx.com 
830206Smax.romanov@nginx.com     nxt_assert(h->done == 1);
831206Smax.romanov@nginx.com     nxt_assert(b->done == 0);
832206Smax.romanov@nginx.com 
833206Smax.romanov@nginx.com     b->done = nxt_buf_mem_used_size(&buf->mem) + b->preread_size >=
834206Smax.romanov@nginx.com               (size_t) h->parsed_content_length;
835206Smax.romanov@nginx.com 
836206Smax.romanov@nginx.com     if (b->done == 1) {
837206Smax.romanov@nginx.com         b->preread_size += nxt_buf_mem_used_size(&buf->mem);
838206Smax.romanov@nginx.com     }
839206Smax.romanov@nginx.com 
840206Smax.romanov@nginx.com     return b->done == 1 ? NXT_DONE : NXT_AGAIN;
8410Sigor@sysoev.ru }
8420Sigor@sysoev.ru 
8430Sigor@sysoev.ru 
84484Smax.romanov@nginx.com nxt_int_t
84584Smax.romanov@nginx.com nxt_app_http_req_done(nxt_task_t *task, nxt_app_parse_ctx_t *ctx)
8460Sigor@sysoev.ru {
84784Smax.romanov@nginx.com     nxt_mp_destroy(ctx->mem_pool);
8480Sigor@sysoev.ru 
84984Smax.romanov@nginx.com     return NXT_OK;
8500Sigor@sysoev.ru }
8510Sigor@sysoev.ru 
8520Sigor@sysoev.ru 
85384Smax.romanov@nginx.com nxt_int_t
85484Smax.romanov@nginx.com nxt_app_msg_flush(nxt_task_t *task, nxt_app_wmsg_t *msg, nxt_bool_t last)
8550Sigor@sysoev.ru {
85684Smax.romanov@nginx.com     nxt_int_t   rc;
85784Smax.romanov@nginx.com     nxt_buf_t   *b;
85884Smax.romanov@nginx.com     nxt_port_t  *port;
85984Smax.romanov@nginx.com 
86084Smax.romanov@nginx.com     rc = NXT_OK;
8610Sigor@sysoev.ru 
86284Smax.romanov@nginx.com     port = nxt_app_msg_get_port(task, msg);
86384Smax.romanov@nginx.com     if (nxt_slow_path(port == NULL)) {
86484Smax.romanov@nginx.com         return NXT_ERROR;
86584Smax.romanov@nginx.com     }
8660Sigor@sysoev.ru 
86784Smax.romanov@nginx.com     if (nxt_slow_path(last == 1)) {
86884Smax.romanov@nginx.com         do {
86984Smax.romanov@nginx.com             b = *msg->buf;
8700Sigor@sysoev.ru 
87184Smax.romanov@nginx.com             if (b == NULL) {
87284Smax.romanov@nginx.com                 b = nxt_buf_sync_alloc(port->mem_pool, NXT_BUF_SYNC_LAST);
87384Smax.romanov@nginx.com                 *msg->buf = b;
87484Smax.romanov@nginx.com                 break;
87584Smax.romanov@nginx.com             }
8760Sigor@sysoev.ru 
87784Smax.romanov@nginx.com             msg->buf = &b->next;
87884Smax.romanov@nginx.com         } while(1);
87984Smax.romanov@nginx.com     }
8800Sigor@sysoev.ru 
88184Smax.romanov@nginx.com     if (nxt_slow_path(msg->write != NULL)) {
88284Smax.romanov@nginx.com         rc = nxt_port_socket_write(task, port, NXT_PORT_MSG_DATA,
88384Smax.romanov@nginx.com                                    -1, msg->stream, 0, msg->write);
88484Smax.romanov@nginx.com 
88584Smax.romanov@nginx.com         msg->write = NULL;
88684Smax.romanov@nginx.com         msg->buf = &msg->write;
88784Smax.romanov@nginx.com     }
88884Smax.romanov@nginx.com 
88984Smax.romanov@nginx.com     return rc;
8900Sigor@sysoev.ru }
8910Sigor@sysoev.ru 
8920Sigor@sysoev.ru 
89384Smax.romanov@nginx.com nxt_int_t
89484Smax.romanov@nginx.com nxt_app_msg_write_raw(nxt_task_t *task, nxt_app_wmsg_t *msg, const u_char *c,
89584Smax.romanov@nginx.com     size_t size)
8960Sigor@sysoev.ru {
897206Smax.romanov@nginx.com     size_t      free_size, copy_size;
898206Smax.romanov@nginx.com     nxt_buf_t   *b;
899206Smax.romanov@nginx.com     nxt_port_t  *port;
900206Smax.romanov@nginx.com 
901206Smax.romanov@nginx.com     nxt_debug(task, "nxt_app_msg_write_raw: %uz", size);
902206Smax.romanov@nginx.com 
903206Smax.romanov@nginx.com     while (size > 0) {
904206Smax.romanov@nginx.com         b = *msg->buf;
905206Smax.romanov@nginx.com 
906206Smax.romanov@nginx.com         if (b == NULL) {
907206Smax.romanov@nginx.com             port = nxt_app_msg_get_port(task, msg);
908206Smax.romanov@nginx.com             if (nxt_slow_path(port == NULL)) {
909206Smax.romanov@nginx.com                 return NXT_ERROR;
910206Smax.romanov@nginx.com             }
911206Smax.romanov@nginx.com 
912206Smax.romanov@nginx.com             b = nxt_port_mmap_get_buf(task, port, size);
913206Smax.romanov@nginx.com             if (nxt_slow_path(b == NULL)) {
914206Smax.romanov@nginx.com                 return NXT_ERROR;
915206Smax.romanov@nginx.com             }
91684Smax.romanov@nginx.com 
917206Smax.romanov@nginx.com             *msg->buf = b;
918206Smax.romanov@nginx.com         }
919206Smax.romanov@nginx.com 
920206Smax.romanov@nginx.com         do {
921206Smax.romanov@nginx.com             free_size = nxt_buf_mem_free_size(&b->mem);
922206Smax.romanov@nginx.com 
923206Smax.romanov@nginx.com             if (free_size > 0) {
924206Smax.romanov@nginx.com                 copy_size = nxt_min(free_size, size);
925206Smax.romanov@nginx.com 
926206Smax.romanov@nginx.com                 b->mem.free = nxt_cpymem(b->mem.free, c, copy_size);
927206Smax.romanov@nginx.com 
928206Smax.romanov@nginx.com                 size -= copy_size;
929206Smax.romanov@nginx.com                 c += copy_size;
930206Smax.romanov@nginx.com 
931206Smax.romanov@nginx.com                 if (size == 0) {
932206Smax.romanov@nginx.com                     return NXT_OK;
933206Smax.romanov@nginx.com                 }
934206Smax.romanov@nginx.com             }
935206Smax.romanov@nginx.com         } while (nxt_port_mmap_increase_buf(task, b, size, 1) == NXT_OK);
936206Smax.romanov@nginx.com 
937206Smax.romanov@nginx.com         msg->buf = &b->next;
9380Sigor@sysoev.ru     }
9390Sigor@sysoev.ru 
94084Smax.romanov@nginx.com     return NXT_OK;
9410Sigor@sysoev.ru }
942141Smax.romanov@nginx.com 
943141Smax.romanov@nginx.com 
944216Sigor@sysoev.ru nxt_app_lang_module_t *
945216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
946216Sigor@sysoev.ru {
947216Sigor@sysoev.ru     u_char                 *p, *end, *version;
948216Sigor@sysoev.ru     size_t                 type_length, version_length;
949216Sigor@sysoev.ru     nxt_uint_t             i, n;
950216Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
951216Sigor@sysoev.ru 
952216Sigor@sysoev.ru     end = name->start + name->length;
953216Sigor@sysoev.ru     version = end;
954216Sigor@sysoev.ru 
955216Sigor@sysoev.ru     for (p = name->start; p < end; p++) {
956216Sigor@sysoev.ru         if (*p == ' ') {
957216Sigor@sysoev.ru             version = p + 1;
958216Sigor@sysoev.ru             break;
959216Sigor@sysoev.ru         }
960216Sigor@sysoev.ru 
961216Sigor@sysoev.ru         if (*p >= '0' && *p <= '9') {
962216Sigor@sysoev.ru             version = p;
963216Sigor@sysoev.ru             break;
964216Sigor@sysoev.ru         }
965216Sigor@sysoev.ru     }
966216Sigor@sysoev.ru 
967216Sigor@sysoev.ru     type_length = p - name->start;
968216Sigor@sysoev.ru     version_length = end - version;
969216Sigor@sysoev.ru 
970216Sigor@sysoev.ru     lang = rt->languages->elts;
971216Sigor@sysoev.ru     n = rt->languages->nelts;
972216Sigor@sysoev.ru 
973216Sigor@sysoev.ru     for (i = 0; i < n; i++) {
974216Sigor@sysoev.ru         if (nxt_str_eq(&lang[i].type, name->start, type_length)
975216Sigor@sysoev.ru             && nxt_str_start(&lang[i].version, version, version_length))
976216Sigor@sysoev.ru         {
977216Sigor@sysoev.ru             return &lang[i];
978216Sigor@sysoev.ru         }
979216Sigor@sysoev.ru     }
980216Sigor@sysoev.ru 
981216Sigor@sysoev.ru     return NULL;
982216Sigor@sysoev.ru }
983216Sigor@sysoev.ru 
984216Sigor@sysoev.ru 
985141Smax.romanov@nginx.com nxt_app_type_t
986141Smax.romanov@nginx.com nxt_app_parse_type(nxt_str_t *str)
987141Smax.romanov@nginx.com {
988141Smax.romanov@nginx.com     if (nxt_str_eq(str, "python", 6)) {
989141Smax.romanov@nginx.com         return NXT_APP_PYTHON;
990141Smax.romanov@nginx.com 
991141Smax.romanov@nginx.com     } else if (nxt_str_eq(str, "php", 3)) {
992141Smax.romanov@nginx.com         return NXT_APP_PHP;
993141Smax.romanov@nginx.com 
994141Smax.romanov@nginx.com     } else if (nxt_str_eq(str, "go", 2)) {
995141Smax.romanov@nginx.com         return NXT_APP_GO;
996141Smax.romanov@nginx.com 
997141Smax.romanov@nginx.com     }
998141Smax.romanov@nginx.com 
999141Smax.romanov@nginx.com     return NXT_APP_UNKNOWN;
1000141Smax.romanov@nginx.com }
1001