comparison src/c/fastcgi.c @ 861:bd153951c794

Fix env-reading bug in fastcgi; a bunch of non-AJAXy demos working
author Adam Chlipala <adamc@hcoop.net>
date Sat, 27 Jun 2009 15:36:56 -0400
parents a738002d5b4d
children 66dbf3953758
comparison
equal deleted inserted replaced
860:a738002d5b4d 861:bd153951c794
68 unsigned short contentLength) { 68 unsigned short contentLength) {
69 o->r.type = type; 69 o->r.type = type;
70 o->r.requestIdB1 = o->r.requestIdB0 = 0; 70 o->r.requestIdB1 = o->r.requestIdB0 = 0;
71 o->r.contentLengthB1 = contentLength >> 8; 71 o->r.contentLengthB1 = contentLength >> 8;
72 o->r.contentLengthB0 = contentLength & 255; 72 o->r.contentLengthB0 = contentLength & 255;
73 return uw_really_send(o->sock, &o->r, sizeof(o->r) - (65535 - contentLength)); 73 return uw_really_send(o->sock, &o->r, sizeof(o->r) - 65535 + contentLength);
74 } 74 }
75 75
76 #define LATEST(i) ((FCGI_Record *)(i->buf + i->used)) 76 #define LATEST(i) ((FCGI_Record *)(i->buf + i->used))
77 77
78 static FCGI_Record *fastcgi_recv(FCGI_Input *i) { 78 static FCGI_Record *fastcgi_recv(FCGI_Input *i) {
164 } 164 }
165 165
166 static void log_debug(void *data, const char *fmt, ...) { 166 static void log_debug(void *data, const char *fmt, ...) {
167 } 167 }
168 168
169 typedef struct {
170 char *name, *value;
171 unsigned name_len, value_len;
172 } nvp;
173
174 static char *search_nvps(nvp *nvps, const char *h) {
175 for (; nvps->name; ++nvps)
176 if (!strcmp(h, nvps->name))
177 return nvps->value;
178
179 return NULL;
180 }
181
182 typedef struct {
183 nvp *nvps;
184 char *uppercased;
185 int n_nvps, uppercased_len;
186 } headers;
187
188 static char *get_header(void *data, const char *h) {
189 headers *hs = (headers *)data;
190 size_t len = strlen(h);
191 char *s, *r;
192 const char *saved_h = h;
193
194 if (len > hs->uppercased_len) {
195 hs->uppercased_len = len;
196 hs->uppercased = realloc(hs->uppercased, len + 6);
197 }
198
199 strcpy(hs->uppercased, "HTTP_");
200 for (s = hs->uppercased+5; *h; ++h)
201 *s++ = *h == '-' ? '_' : toupper(*h);
202 *s = 0;
203
204 if (!strcasecmp(saved_h, "Content-length")
205 || !strcasecmp(saved_h, "Content-type"))
206 return search_nvps(hs->nvps, hs->uppercased + 5);
207 else
208 return search_nvps(hs->nvps, hs->uppercased);
209 }
210
169 static int read_funny_len(char **buf, int *len) { 211 static int read_funny_len(char **buf, int *len) {
170 if (*len <= 0) 212 if (*len <= 0)
171 return -1; 213 return -1;
172 214
173 if ((*buf)[0] >> 7 == 0) { 215 if ((*buf)[0] >> 7 == 0) {
184 *len -= 4; 226 *len -= 4;
185 return r; 227 return r;
186 } 228 }
187 } 229 }
188 230
189 typedef struct {
190 char *name, *value;
191 unsigned name_len, value_len;
192 } nvp;
193
194 static char *search_nvps(nvp *nvps, const char *h) {
195 for (; nvps->name; ++nvps)
196 if (!strcmp(h, nvps->name))
197 return nvps->value;
198
199 return NULL;
200 }
201
202 typedef struct {
203 nvp *nvps;
204 char *uppercased;
205 int n_nvps, uppercased_len;
206 } headers;
207
208 static char *get_header(void *data, const char *h) {
209 headers *hs = (headers *)data;
210 size_t len = strlen(h);
211 char *s, *r;
212 const char *saved_h = h;
213
214 if (len > hs->uppercased_len) {
215 hs->uppercased_len = len;
216 hs->uppercased = realloc(hs->uppercased, len + 6);
217 }
218
219 strcpy(hs->uppercased, "HTTP_");
220 for (s = hs->uppercased+5; *h; ++h)
221 *s++ = *h == '-' ? '_' : toupper(*h);
222 *s = 0;
223
224 if (!strcasecmp(saved_h, "Content-length")
225 || !strcasecmp(saved_h, "Content-type"))
226 return search_nvps(hs->nvps, hs->uppercased + 5);
227 else
228 return search_nvps(hs->nvps, hs->uppercased);
229 }
230
231 static int read_nvp(char *buf, int len, nvp *nv) { 231 static int read_nvp(char *buf, int len, nvp *nv) {
232 int nameLength, valueLength; 232 int nameLength, valueLength;
233 233
234 if ((nameLength = read_funny_len(&buf, &len)) < 0) 234 if ((nameLength = read_funny_len(&buf, &len)) < 0)
235 return -1; 235 return -1;
236 if ((valueLength = read_funny_len(&buf, &len)) < 0) 236 if ((valueLength = read_funny_len(&buf, &len)) < 0)
237 return -1; 237 return -1;
238 if (len < nameLength + valueLength) 238 if (len < nameLength + valueLength)
239 return -1; 239 return -1;
240 240
241 if (nameLength+1 > nv->name_len) { 241 if (!nv->name || nameLength+1 > nv->name_len) {
242 nv->name_len = nameLength+1; 242 nv->name_len = nameLength+1;
243 nv->name = realloc(nv->name, nv->name_len); 243 nv->name = nv->name ? realloc(nv->name, nv->name_len) : malloc(nv->name_len);
244 } 244 }
245 if (valueLength+1 > nv->value_len) { 245 if (!nv->value || valueLength+1 > nv->value_len) {
246 nv->value_len = valueLength+1; 246 nv->value_len = valueLength+1;
247 nv->value = realloc(nv->value, nv->value_len); 247 nv->value = nv->value ? realloc(nv->value, nv->value_len) : malloc(nv->value_len);
248 } 248 }
249 249
250 memcpy(nv->name, buf, nameLength); 250 memcpy(nv->name, buf, nameLength);
251 nv->name[nameLength] = 0; 251 nv->name[nameLength] = 0;
252 252
265 headers hs; 265 headers hs;
266 size_t body_size = 0; 266 size_t body_size = 0;
267 char *body = malloc(0); 267 char *body = malloc(0);
268 size_t path_size = 0; 268 size_t path_size = 0;
269 char *path_buf = malloc(0); 269 char *path_buf = malloc(0);
270 int tries = 0;
270 271
271 hs.uppercased = malloc(0); 272 hs.uppercased = malloc(0);
272 hs.uppercased_len = 0; 273 hs.uppercased_len = 0;
273 hs.nvps = malloc(sizeof(nvp)); 274 hs.nvps = malloc(sizeof(nvp));
274 hs.n_nvps = 1; 275 hs.n_nvps = 1;
284 285
285 if (!(r = fastcgi_recv(in))) { 286 if (!(r = fastcgi_recv(in))) {
286 fprintf(stderr, "Error receiving initial message\n"); 287 fprintf(stderr, "Error receiving initial message\n");
287 goto done; 288 goto done;
288 } 289 }
289 290
290 if (r->type != FCGI_BEGIN_REQUEST) { 291 if (r->type != FCGI_BEGIN_REQUEST) {
291 write_stderr(out, "First message is not BEGIN_REQUEST\n"); 292 write_stderr(out, "First message is not BEGIN_REQUEST\n");
292 goto done; 293 goto done;
293 } else if (((FCGI_BeginRequestBody *)&r->contentData)->roleB0 != FCGI_RESPONDER) { 294 } else if (((FCGI_BeginRequestBody *)&r->contentData)->roleB0 != FCGI_RESPONDER) {
294 write_stderr(out, "First message is not BEGIN_REQUEST\n"); 295 write_stderr(out, "First message is not BEGIN_REQUEST\n");
337 goto done; 338 goto done;
338 } 339 }
339 } else 340 } else
340 body_len = 0; 341 body_len = 0;
341 342
342 if (body_len > body_size) { 343 if (body_len+1 > body_size) {
343 body_size = body_len; 344 body_size = body_len+1;
344 body = realloc(body, body_size); 345 body = realloc(body, body_size);
345 } 346 }
346 347
347 for (body_read = 0; body_read < body_len; ) { 348 for (body_read = 0; body_read < body_len; ) {
348 char *buf; 349 char *buf;
372 373
373 memcpy(&body[body_read], r->contentData, this_len); 374 memcpy(&body[body_read], r->contentData, this_len);
374 body_read += this_len; 375 body_read += this_len;
375 } 376 }
376 377
378 body[body_read] = 0;
379
377 if (!(method = search_nvps(hs.nvps, "REQUEST_METHOD"))) { 380 if (!(method = search_nvps(hs.nvps, "REQUEST_METHOD"))) {
378 write_stderr(out, "REQUEST_METHOD not set\n"); 381 write_stderr(out, "REQUEST_METHOD not set\n");
379 goto done; 382 goto done;
380 } 383 }
381 384
382 if (!(path = search_nvps(hs.nvps, "SCRIPT_NAME"))) { 385 if (!(path = search_nvps(hs.nvps, "SCRIPT_NAME"))) {
383 write_stderr(out, "SCRIPT_NAME not set\n"); 386 write_stderr(out, "SCRIPT_NAME not set\n");
384 goto done; 387 goto done;
385 } 388 }
386 389
387 if (path_info = search_nvps(hs.nvps, "PATH_INFO")) { 390 if (path_info = search_nvps(hs.nvps, "PATH_INFO")) {
388 int len1 = strlen(path), len2 = strlen(path_info); 391 int len1 = strlen(path), len2 = strlen(path_info);
389 int len = len1 + len2 + 1; 392 int len = len1 + len2 + 1;
390 393
391 if (len > path_size) { 394 if (len > path_size) {
399 402
400 if (!(query_string = search_nvps(hs.nvps, "QUERY_STRING"))) 403 if (!(query_string = search_nvps(hs.nvps, "QUERY_STRING")))
401 query_string = ""; 404 query_string = "";
402 405
403 uw_set_headers(ctx, get_header, &hs); 406 uw_set_headers(ctx, get_header, &hs);
407
404 { 408 {
405 request_result rr; 409 request_result rr;
406 FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData; 410 FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData;
407 411
408 rr = uw_request(rc, ctx, method, path, query_string, body, body_read, 412 rr = uw_request(rc, ctx, method, path, query_string, body, body_read,