Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 743 lines (582 sloc) 19.8 kb
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* Cherokee
4 *
5 * Authors:
6 * Alvaro Lopez Ortega <alvaro@alobbs.com>
7 *
8 * Copyright (C) 2001-2006 Alvaro Lopez Ortega
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 */
24
25 #include "common-internal.h"
26 #include "handler_fcgi.h"
27 #include "header.h"
28 #include "connection-protected.h"
29 #include "util.h"
30 #include "thread.h"
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
31 #include "source_interpreter.h"
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
32
33 #include "fastcgi.h"
34
35 #define POST_PACKAGE_LEN 32600
36 #define ENTRIES "fcgi,handler"
37
38
39 #define set_env(cgi,key,val,len) \
40 set_env_pair (cgi, key, sizeof(key)-1, val, len)
41
42
43 static void set_env_pair (cherokee_handler_cgi_base_t *cgi_base,
44 char *key, int key_len,
45 char *val, int val_len);
46
47 static ret_t
48 process_package (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *inbuf, cherokee_buffer_t *outbuf)
49 {
50 FCGI_Header *header;
51 FCGI_EndRequestBody *ending;
52 cherokee_connection_t *conn = HANDLER_CONN(hdl);
53
54 cuint_t len;
55 char *data;
56 cint_t return_val;
57 cuint_t type;
58 cuint_t id;
59 cuint_t padding;
60
61 /* Is there enough information?
62 */
63 if (inbuf->len < sizeof(FCGI_Header))
64 return ret_ok;
65
66 /* At least there is a header
67 */
68 header = (FCGI_Header *)inbuf->buf;
69
70 if (header->version != 1) {
71 cherokee_buffer_print_debug (inbuf, -1);
72 PRINT_ERROR_S ("Parsing error: unknown version\n");
73 return ret_error;
74 }
75
76 if (header->type != FCGI_STDERR &&
77 header->type != FCGI_STDOUT &&
78 header->type != FCGI_END_REQUEST)
79 {
80 cherokee_buffer_print_debug (inbuf, -1);
81 PRINT_ERROR_S ("Parsing error: unknown type\n");
82 return ret_error;
83 }
84
85 /* Read the header
86 */
87 type = header->type;
88 padding = header->paddingLength;
89 id = (header->requestIdB0 | (header->requestIdB1 << 8));
90 len = (header->contentLengthB0 | (header->contentLengthB1 << 8));
91 data = inbuf->buf + FCGI_HEADER_LEN;
92
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
93 /* printf ("have %d, hdr=%d exp_len=%d pad=%d\n", inbuf->len, FCGI_HEADER_LEN, len, padding); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
94
95 /* Is the package complete?
96 */
97 if (len + padding > inbuf->len - FCGI_HEADER_LEN) {
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
98 /* printf ("Incomplete: %d < %d\n", len + padding, inbuf->len - FCGI_HEADER_LEN); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
99 return ret_ok;
100 }
101
102 /* It has received the full package content
103 */
104 switch (type) {
105 case FCGI_STDERR:
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
106 /* printf ("READ:STDERR (%d): %s", len, data?data:""); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
107
108 if (CONN_VSRV(conn)->logger != NULL) {
109 cherokee_buffer_t tmp = CHEROKEE_BUF_INIT;
110
111 cherokee_buffer_add (&tmp, data, len);
112 cherokee_logger_write_string (CONN_VSRV(conn)->logger, "%s", tmp.buf);
113 PRINT_ERROR ("%s\n", tmp.buf);
114 cherokee_buffer_mrproper (&tmp);
115 }
116 break;
117
118 case FCGI_STDOUT:
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
119 /* printf ("READ:STDOUT eof=%d: %d", CGI_BASE(hdl)->got_eof, len); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
120 cherokee_buffer_add (outbuf, data, len);
121 break;
122
123 case FCGI_END_REQUEST:
124 ending = (FCGI_EndRequestBody *)data;
125
126 return_val = ((ending->appStatusB0) |
127 (ending->appStatusB0 << 8) |
128 (ending->appStatusB0 << 16) |
129 (ending->appStatusB0 << 24));
130
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
131 HDL_CGI_BASE(hdl)->got_eof = true;
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
132 /* printf ("READ:END"); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
133 break;
134
135 default:
136 SHOULDNT_HAPPEN;
137 }
138
139 cherokee_buffer_move_to_begin (inbuf, len + FCGI_HEADER_LEN + padding);
b13f4bf @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@446 5dc97367-97…
alobbs authored
140 /* printf ("- FCGI quedan %d\n", inbuf->len); */
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
141 return ret_eagain;
142 }
143
144
145 static ret_t
146 process_buffer (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *inbuf, cherokee_buffer_t *outbuf)
147 {
148 ret_t ret;
149
150 do {
151 ret = process_package (hdl, inbuf, outbuf);
152 } while (ret == ret_eagain);
153
154 if (ret == ret_ok) {
155 if (cherokee_buffer_is_empty (outbuf))
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
156 return (HDL_CGI_BASE(hdl)->got_eof) ? ret_eof : ret_eagain;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
157 }
158
159 return ret;
160 }
161
162 static ret_t
163 read_from_fcgi (cherokee_handler_cgi_base_t *cgi, cherokee_buffer_t *buffer)
164 {
165 ret_t ret;
166 size_t read = 0;
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
167 cherokee_handler_fcgi_t *fcgi = HDL_FCGI(cgi);
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
168
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
169 ret = cherokee_socket_read (&fcgi->socket, &fcgi->write_buffer, DEFAULT_READ_SIZE, &read);
170
171 switch (ret) {
172 case ret_eagain:
173 cherokee_thread_deactive_to_polling (HANDLER_THREAD(cgi), HANDLER_CONN(cgi),
174 fcgi->socket.socket, 0, false);
175 return ret_eagain;
176
177 case ret_ok:
178 ret = process_buffer (fcgi, &fcgi->write_buffer, buffer);
179 TRACE (ENTRIES, "%d bytes readed, buffer.len %d\n", read, buffer->len);
180 if ((ret == ret_ok) && cgi->got_eof && (buffer->len > 0))
181 return ret_eof_have_data;
182 return ret;
183
184 case ret_eof:
185 case ret_error:
186 cgi->got_eof = true;
187 return ret;
188
189 default:
190 RET_UNKNOWN(ret);
191 }
192
193 SHOULDNT_HAPPEN;
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
194 return ret_error;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
195 }
196
197
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
198 static ret_t
be04810 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@283 5dc97367-97…
alobbs authored
199 props_free (cherokee_handler_fcgi_props_t *props)
200 {
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
201 if (props->balancer != NULL)
202 cherokee_balancer_free (props->balancer);
623deda @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@294 5dc97367-97…
alobbs authored
203
204 return cherokee_handler_cgi_base_props_free (PROP_CGI_BASE(props));
be04810 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@283 5dc97367-97…
alobbs authored
205 }
206
207
208 static ret_t
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
209 cherokee_handler_fcgi_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
210 {
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
211 ret_t ret;
ee8023f @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@384 5dc97367-97…
alobbs authored
212 cherokee_list_t *i;
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
213 cherokee_handler_fcgi_props_t *props;
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
214
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
215 /* Instance a new property object
216 */
217 if (*_props == NULL) {
218 CHEROKEE_NEW_STRUCT (n, handler_fcgi_props);
be04810 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@283 5dc97367-97…
alobbs authored
219
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
220 cherokee_module_props_init_base (MODULE_PROPS(n),
221 MODULE_PROPS_FREE(props_free));
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
222 INIT_LIST_HEAD(&n->server_list);
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
223 n->balancer = NULL;
224
225 *_props = MODULE_PROPS(n);
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
226 }
227
228 props = PROP_FCGI(*_props);
229
230 /* Parse the configuration tree
231 */
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
232 cherokee_config_node_foreach (i, conf) {
233 cherokee_config_node_t *subconf = CONFIG_NODE(i);
234
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
235 if (equal_buf_str (&subconf->key, "balancer")) {
236 ret = cherokee_balancer_instance (&subconf->val, subconf, srv, &props->balancer);
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
237 if (ret != ret_ok) return ret;
238 }
239 }
240
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
241 /* Init base class
242 */
243 ret = cherokee_handler_cgi_base_configure (conf, srv, _props);
244 if (ret != ret_ok) return ret;
245
246 /* Final checks
247 */
248 if (props->balancer == NULL) {
249 PRINT_ERROR_S ("ERROR: fcgi handler needs a balancer\n");
250 return ret_error;
251 }
252
253 return ret_ok;
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
254 }
255
256
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
257 ret_t
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
258 cherokee_handler_fcgi_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props)
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
259 {
260 CHEROKEE_NEW_STRUCT (n, handler_fcgi);
261
262 /* Init the base class
263 */
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
264 cherokee_handler_cgi_base_init (HDL_CGI_BASE(n), cnt, props, set_env_pair, read_from_fcgi);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
265
266 /* Virtual methods
267 */
268 MODULE(n)->init = (handler_func_init_t) cherokee_handler_fcgi_init;
423d6fa @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@370 5dc97367-97…
alobbs authored
269 MODULE(n)->free = (module_func_free_t) cherokee_handler_fcgi_free;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
270
271 /* Virtual methods: implemented by handler_cgi_base
272 */
273 HANDLER(n)->step = (handler_func_step_t) cherokee_handler_cgi_base_step;
274 HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_cgi_base_add_headers;
275
276 /* Properties
277 */
278 n->post_phase = fcgi_post_init;
279 n->post_len = 0;
280
281 cherokee_socket_init (&n->socket);
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
282 cherokee_socket_set_nodelay (&n->socket);
283
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
284 cherokee_buffer_init (&n->write_buffer);
285 cherokee_buffer_ensure_size (&n->write_buffer, 512);
286
287 /* Return the object
288 */
289 *hdl = HANDLER(n);
290 return ret_ok;
291 }
292
293
294 ret_t
295 cherokee_handler_fcgi_free (cherokee_handler_fcgi_t *hdl)
296 {
483759d @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@466 5dc97367-97…
alobbs authored
297 TRACE (ENTRIES, "fcgi handler free: %p\n", hdl);
298
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
299 cherokee_socket_close (&hdl->socket);
300 cherokee_socket_mrproper (&hdl->socket);
301
302 cherokee_buffer_mrproper (&hdl->write_buffer);
303
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
304 return cherokee_handler_cgi_base_free (HDL_CGI_BASE(hdl));
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
305 }
306
307
308 static void
309 fcgi_build_header (FCGI_Header *hdr, cuchar_t type, cushort_t request_id, cuint_t content_length, cuchar_t padding)
310 {
311 hdr->version = FCGI_VERSION_1;
312 hdr->type = type;
313 hdr->requestIdB0 = (cuchar_t) request_id;
314 hdr->requestIdB1 = (cuchar_t) (request_id >> 8) & 0xff;
315 hdr->contentLengthB0 = (cuchar_t) (content_length % 256);
316 hdr->contentLengthB1 = (cuchar_t) (content_length / 256);
317 hdr->paddingLength = padding;
318 hdr->reserved = 0;
319 }
320
321 static void
322 fcgi_build_request_body (FCGI_BeginRequestRecord *request)
323 {
324 request->body.roleB0 = FCGI_RESPONDER;
325 request->body.roleB1 = 0;
326 request->body.flags = 0;
327 request->body.reserved[0] = 0;
328 request->body.reserved[1] = 0;
329 request->body.reserved[2] = 0;
330 request->body.reserved[3] = 0;
331 request->body.reserved[4] = 0;
332 }
333
334 static void
335 set_env_pair (cherokee_handler_cgi_base_t *cgi_base,
336 char *key, int key_len,
337 char *val, int val_len)
338 {
339 int len;
340 FCGI_BeginRequestRecord request;
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
341 cherokee_handler_fcgi_t *hdl = HDL_FCGI(cgi_base);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
342 cherokee_buffer_t *buf = &hdl->write_buffer;
343
344 len = key_len + val_len;
345 len += key_len > 127 ? 4 : 1;
346 len += val_len > 127 ? 4 : 1;
347
348 fcgi_build_header (&request.header, FCGI_PARAMS, 1, len, 0);
349
350 cherokee_buffer_ensure_size (buf, buf->len + sizeof(FCGI_Header) + key_len + val_len);
351 cherokee_buffer_add (buf, (void *)&request.header, sizeof(FCGI_Header));
352
353 if (key_len <= 127) {
354 buf->buf[buf->len++] = key_len;
355 } else {
356 buf->buf[buf->len++] = ((key_len >> 24) & 0xff) | 0x80;
357 buf->buf[buf->len++] = (key_len >> 16) & 0xff;
358 buf->buf[buf->len++] = (key_len >> 8) & 0xff;
359 buf->buf[buf->len++] = (key_len >> 0) & 0xff;
360 }
361
362 if (val_len <= 127) {
363 buf->buf[buf->len++] = val_len;
364 } else {
365 buf->buf[buf->len++] = ((val_len >> 24) & 0xff) | 0x80;
366 buf->buf[buf->len++] = (val_len >> 16) & 0xff;
367 buf->buf[buf->len++] = (val_len >> 8) & 0xff;
368 buf->buf[buf->len++] = (val_len >> 0) & 0xff;
369 }
370
371 cherokee_buffer_add (buf, key, key_len);
372 cherokee_buffer_add (buf, val, val_len);
373 }
374
375
376 static ret_t
377 add_extra_fcgi_env (cherokee_handler_fcgi_t *hdl, cuint_t *last_header_offset)
378 {
379 ret_t ret;
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
380 cherokee_handler_cgi_base_t *cgi_base = HDL_CGI_BASE(hdl);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
381 cherokee_buffer_t buffer = CHEROKEE_BUF_INIT;
382 cherokee_connection_t *conn = HANDLER_CONN(hdl);
383
384 /* CONTENT_LENGTH
385 */
386 ret = cherokee_header_copy_known (&conn->header, header_content_length, &buffer);
387 if (ret == ret_ok)
388 set_env (cgi_base, "CONTENT_LENGTH", buffer.buf, buffer.len);
389
390 /* Add PATH_TRANSLATED only it there is pathinfo
391 */
392 #if 0
393 if (! cherokee_buffer_is_empty (&conn->pathinfo)) {
394 cherokee_buffer_add_buffer (&buffer, &conn->local_directory);
395 cherokee_buffer_add_buffer (&buffer, &conn->pathinfo);
396
397 set_env (cgi_base, "PATH_TRANSLATED", buffer.buf, buffer.len);
398 TRACE (ENTRIES, "PATH_TRANSLATED '%s'\n", cgi_base->executable.buf);
399 }
400 #endif
401
402 /* The last one
403 */
404 *last_header_offset = hdl->write_buffer.len;
405
406 set_env (cgi_base, "SCRIPT_FILENAME", cgi_base->executable.buf, cgi_base->executable.len);
407 TRACE (ENTRIES, "SCRIPT_FILENAME '%s'\n", cgi_base->executable.buf);
408
409 cherokee_buffer_mrproper (&buffer);
410 return ret_ok;
411 }
412
413
414 static void
415 fixup_padding (cherokee_buffer_t *buf, cuint_t last_header_offset)
416 {
417 cuint_t rest;
418 cuint_t pad;
419 static char padding[8] = {0, 0, 0, 0, 0, 0, 0, 0};
420 FCGI_Header *last_header;
421
422 if (buf->len <= 0)
423 return;
424 last_header = (FCGI_Header *) (buf->buf + last_header_offset);
425 rest = buf->len % 8;
426 pad = 8 - rest;
427
428 if (rest == 0)
429 return;
430
431 last_header->paddingLength = pad;
432
433 cherokee_buffer_ensure_size (buf, buf->len + pad);
434 cherokee_buffer_add (buf, padding, pad);
435 }
436
437 static void
438 add_empty_packet (cherokee_handler_fcgi_t *hdl, cuint_t type)
439 {
440 FCGI_BeginRequestRecord request;
441
442 fcgi_build_header (&request.header, type, 1, 0, 0);
443 cherokee_buffer_add (&hdl->write_buffer, (void *)&request.header, sizeof(FCGI_Header));
444
445 TRACE (ENTRIES, "empty packet type=%d, len=%d\n", type, hdl->write_buffer.len);
446 }
447
448
449 static ret_t
450 build_header (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *buffer)
451 {
452 FCGI_BeginRequestRecord request;
453 cuint_t last_header_offset;
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
454 cherokee_connection_t *conn = HANDLER_CONN(hdl);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
455
456 /* Take care here, if the connection is reinjected, it
457 * shouldn't parse the arguments again.
458 */
459 if (conn->arguments == NULL)
460 cherokee_connection_parse_args (conn);
461
462 cherokee_buffer_clean (buffer);
463
464 /* FCGI_BEGIN_REQUEST
465 */
466 fcgi_build_header (&request.header, FCGI_BEGIN_REQUEST, 1, sizeof(request.body), 0);
467 fcgi_build_request_body (&request);
468
469 cherokee_buffer_add (buffer, (void *)&request, sizeof(FCGI_BeginRequestRecord));
470 TRACE (ENTRIES, "Added FCGI_BEGIN_REQUEST, len=%d\n", buffer->len);
471
472 /* Add enviroment variables
473 */
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
474 cherokee_handler_cgi_base_build_envp (HDL_CGI_BASE(hdl), conn);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
475
476 add_extra_fcgi_env (hdl, &last_header_offset);
477 fixup_padding (buffer, last_header_offset);
478
479 /* There are not more parameters
480 */
481 add_empty_packet (hdl, FCGI_PARAMS);
482
483 TRACE (ENTRIES, "Added FCGI_PARAMS, len=%d\n", buffer->len);
484 return ret_ok;
485 }
486
487
488 static ret_t
489 connect_to_server (cherokee_handler_fcgi_t *hdl)
490 {
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
491 ret_t ret;
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
492 int try = 0;
493 cherokee_source_t *src = NULL;
494 cherokee_connection_t *conn = HANDLER_CONN(hdl);
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
495 cherokee_handler_fcgi_props_t *props = HDL_FCGI_PROPS(hdl);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
496
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
497 ret = cherokee_balancer_dispatch (props->balancer, conn, &src);
498 if (ret != ret_ok) return ret;
499
500 ret = cherokee_source_connect (src, &hdl->socket);
501 if (ret != ret_ok) {
502 cherokee_source_interpreter_t *src_int = SOURCE_INT(src);
503
504 ret = cherokee_source_interpreter_spawn (src_int);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
505 if (ret != ret_ok) {
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
506 TRACE (ENTRIES, "Couldn't spawn: %s\n", src->host.buf ? src->host.buf : src->unix_socket.buf);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
507 return ret;
508 }
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
509
510 while (true) {
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
511 ret = cherokee_source_connect (src, &hdl->socket);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
512 if (ret == ret_ok) break;
513
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
514 TRACE (ENTRIES, "Couldn't connect: %s, try %d\n", src->host.buf ? src->host.buf : src->unix_socket.buf, try);
45ead25 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@428 5dc97367-97…
alobbs authored
515
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
516 if (try++ >= 3)
45ead25 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@428 5dc97367-97…
alobbs authored
517 return ret;
518
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
519 sleep (1);
520 }
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
521
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
522 }
7b0e48a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@387 5dc97367-97…
alobbs authored
523
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
524 TRACE (ENTRIES, "Connected sucessfully try=%d, fd=%d\n", try, hdl->socket.socket);
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
525
526 cherokee_fd_set_nonblocking (SOCKET_FD(&hdl->socket));
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
527 return ret_ok;
528 }
529
530
531 static ret_t
532 do_send (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *buffer)
533 {
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
534 ret_t ret;
535 size_t written = 0;
536 cherokee_connection_t *conn = HANDLER_CONN(hdl);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
537
538 ret = cherokee_socket_write (&hdl->socket, buffer, &written);
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
539 switch (ret) {
540 case ret_ok:
3cbd17a @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@475 5dc97367-97…
alobbs authored
541 break;
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
542 case ret_eagain:
543 cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), HANDLER_CONN(hdl),
544 hdl->socket.socket, 1, false);
545 return ret_eagain;
546 default:
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
547 conn->error_code = http_bad_gateway;
ba212a4 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@467 5dc97367-97…
alobbs authored
548 return ret_error;
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
549 }
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
550
551 cherokee_buffer_move_to_begin (buffer, written);
552
553 TRACE (ENTRIES, "sent remaining=%d\n", buffer->len);
554
555 if (! cherokee_buffer_is_empty (buffer))
556 return ret_eagain;
557
558 return ret_ok;
559 }
560
561
562 static ret_t
563 send_post (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *buf)
564 {
565 ret_t ret;
566 cherokee_connection_t *conn = HANDLER_CONN(hdl);
567 static FCGI_Header empty_header = {0,0,0,0,0,0,0,0};
568
569 switch (hdl->post_phase) {
570 case fcgi_post_init:
571 TRACE (ENTRIES, "Post %s\n", "init");
572
573 /* Init the POST storing object
574 */
575 cherokee_post_walk_reset (&conn->post);
576 cherokee_post_get_len (&conn->post, &hdl->post_len);
577
578 if (hdl->post_len <= 0)
579 return ret_ok;
580
581 hdl->post_phase = fcgi_post_read;
582
583 case fcgi_post_read:
584 TRACE (ENTRIES, "Post %s\n", "read");
585
586 /* Add space for the header, it'll filled out later on..
587 */
588 if (cherokee_buffer_is_empty (buf)) {
589 cherokee_buffer_add (buf, (char *)&empty_header, sizeof (FCGI_Header));
590 }
591
592 /* Take a chunck of post
593 */
594 ret = cherokee_post_walk_read (&conn->post, buf, POST_PACKAGE_LEN);
595 switch (ret) {
596 case ret_ok:
597 case ret_eagain:
598 break;
599 case ret_error:
600 return ret;
601 default:
602 RET_UNKNOWN(ret);
603 return ret_error;
604 }
605
606 TRACE (ENTRIES, "Post buffer.len %d\n", buf->len);
607
608 /* Complete the header
609 */
610 if (buf->len > sizeof(FCGI_Header)) {
611 fcgi_build_header ((FCGI_Header *)buf->buf, FCGI_STDIN, 1,
612 buf->len - sizeof(FCGI_Header), 0);
613 }
614
615 /* Close STDIN if it was the last chunck
616 */
617 ret = cherokee_post_walk_finished (&conn->post);
618 if (ret == ret_ok) {
619 add_empty_packet (hdl, FCGI_STDIN);
620 }
621
622 hdl->post_phase = fcgi_post_write;
623
624 case fcgi_post_write:
625 TRACE (ENTRIES, "Post write, buf.len=%d (header len %d)\n", buf->len, sizeof(FCGI_Header));
626
627 if (! cherokee_buffer_is_empty (buf)) {
628 ret = do_send (hdl, buf);
629 switch (ret) {
630 case ret_ok:
631 break;
632 case ret_eagain:
633 return ret_eagain;
634 case ret_eof:
635 case ret_error:
636 return ret_error;
637 default:
638 RET_UNKNOWN(ret);
639 return ret_error;
640 }
641 }
642
643 if (! cherokee_buffer_is_empty (buf))
644 return ret_eagain;
645
646 ret = cherokee_post_walk_finished (&conn->post);
647 switch (ret) {
648 case ret_ok:
649 break;
650 case ret_error:
651 return ret_error;
652 case ret_eagain:
653 hdl->post_phase = fcgi_post_read;
654 return ret_eagain;
655 default:
656 RET_UNKNOWN(ret);
657 return ret_error;
658 }
659
660 TRACE (ENTRIES, "Post %s\n", "finished");
661 return ret_ok;
662
663 default:
664 SHOULDNT_HAPPEN;
665 }
666
667 return ret_error;
668 }
669
670
671 ret_t
672 cherokee_handler_fcgi_init (cherokee_handler_fcgi_t *hdl)
673 {
674 ret_t ret;
675 cherokee_connection_t *conn = HANDLER_CONN(hdl);
676
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
677 switch (HDL_CGI_BASE(hdl)->init_phase) {
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
678 case hcgi_phase_build_headers:
679 TRACE (ENTRIES, "Init %s\n", "begins");
680
681 /* Prepare Post
682 */
683 if (! cherokee_post_is_empty (&conn->post)) {
684 cherokee_post_walk_reset (&conn->post);
685 cherokee_post_get_len (&conn->post, &hdl->post_len);
686 }
687
688 /* Extracts PATH_INFO and filename from request uri
689 */
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
690 ret = cherokee_handler_cgi_base_extract_path (HDL_CGI_BASE(hdl), false);
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
691 if (unlikely (ret < ret_ok)) return ret;
692
693 /* Build the headers
694 */
695 ret = build_header (hdl, &hdl->write_buffer);
696 if (unlikely (ret != ret_ok)) return ret;
697
698 /* Connect
699 */
700 ret = connect_to_server (hdl);
701 if (unlikely (ret != ret_ok)) {
2e0ea0e @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@430 5dc97367-97…
alobbs authored
702 conn->error_code = http_service_unavailable;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
703 return ret;
704 }
705
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
706 HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_headers;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
707
708 case hcgi_phase_send_headers:
709 TRACE (ENTRIES, "Init %s\n", "send_headers");
710
711 /* Send the header
712 */
713 ret = do_send (hdl, &hdl->write_buffer);
714 if (ret != ret_ok) return ret;
715
3509796 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@282 5dc97367-97…
alobbs authored
716 HDL_CGI_BASE(hdl)->init_phase = hcgi_phase_send_post;
ae9d971 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@243 5dc97367-97…
alobbs authored
717
718 case hcgi_phase_send_post:
719 /* Send the Post
720 */
721 if (hdl->post_len > 0) {
722 return send_post (hdl, &hdl->write_buffer);
723 }
724 break;
725 }
726
727 TRACE (ENTRIES, "Init %s\n", "finishes");
728
729 cherokee_buffer_clean (&hdl->write_buffer);
730 return ret_ok;
731 }
732
733
734 /* Module init
735 */
736 void
737 MODULE_INIT(fcgi) (cherokee_module_loader_t *loader)
738 {
739 }
740
83fd835 @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@333 5dc97367-97…
alobbs authored
741 HANDLER_MODULE_INFO_INIT_EASY (fcgi, http_get | http_post | http_head);
b6c69ad @alobbs git-svn-id: svn://cherokee-project.com/cherokee/trunk@269 5dc97367-97…
alobbs authored
742
Something went wrong with that request. Please try again.