Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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