182 ZERO(writeev, sizeof(Event)); |
182 ZERO(writeev, sizeof(Event)); |
183 writeev->cookie = handler; |
183 writeev->cookie = handler; |
184 writeev->fn = cgi_writeevent; |
184 writeev->fn = cgi_writeevent; |
185 writeev->finish = cgi_event_finish; |
185 writeev->finish = cgi_event_finish; |
186 |
186 |
187 |
187 handler->readev = readev; |
188 handler->writeev = writeev; |
188 handler->writeev = writeev; |
189 |
189 |
190 net_setnonblock(sn->csd, 1); |
190 net_setnonblock(sn->csd, 1); |
191 |
191 |
192 // add poll events for cgi stdout/stderr |
192 // add poll events for cgi stdout/stderr |
261 } |
261 } |
262 memcpy(handler->writebuf, buf+pos, remaining); |
262 memcpy(handler->writebuf, buf+pos, remaining); |
263 handler->writebuf_size = remaining; |
263 handler->writebuf_size = remaining; |
264 handler->writebuf_pos = 0; |
264 handler->writebuf_pos = 0; |
265 |
265 |
|
266 /* |
266 // initialize poll, if it isn't already active |
267 // initialize poll, if it isn't already active |
267 if(!handler->poll_out) { |
268 if(!handler->poll_out) { |
268 if(event_pollout(ev, sn->csd, handler->writeev)) { |
269 if(event_pollout(ev, sn->csd, handler->writeev)) { |
269 handler->result = REQ_ABORTED; |
270 handler->result = REQ_ABORTED; |
270 return 0; |
271 return 0; |
271 } |
272 } |
272 handler->events++; |
273 handler->events++; |
273 handler->poll_out = TRUE; |
274 handler->poll_out = TRUE; |
274 } |
275 } |
|
276 */ |
275 } else { |
277 } else { |
276 handler->result = REQ_ABORTED; |
278 handler->result = REQ_ABORTED; |
277 log_ereport(LOG_FAILURE, "cgi_try_write: %s", strerror(net_errno(sn->csd))); |
279 log_ereport(LOG_FAILURE, "cgi_try_write: %s", strerror(net_errno(sn->csd))); |
278 } |
280 } |
279 return 1; |
281 return 1; |
283 } |
285 } |
284 |
286 |
285 int cgi_stdout_readevent(EventHandler *ev, Event *event) { |
287 int cgi_stdout_readevent(EventHandler *ev, Event *event) { |
286 CGIHandler *handler = event->cookie; |
288 CGIHandler *handler = event->cookie; |
287 |
289 |
288 int ret = cgi_read_output(handler, ev); |
290 CgiIOResult ret = cgi_read_output(handler, ev); |
289 if(ret == 0) { |
291 switch(ret) { |
290 handler->wait_read = FALSE; |
292 case CGI_IO_COMPLETE: { |
291 } |
293 break; |
292 return ret; |
294 } |
|
295 case CGI_IO_NEED_READ: { |
|
296 return 1; |
|
297 } |
|
298 case CGI_IO_NEED_WRITE: { |
|
299 if(event_pollout(ev, handler->parser->sn->csd, handler->readev)) { |
|
300 handler->result = REQ_ABORTED; |
|
301 } else { |
|
302 handler->poll_out = TRUE; |
|
303 } |
|
304 break; |
|
305 } |
|
306 case CGI_IO_ERROR: { |
|
307 break; |
|
308 } |
|
309 } |
|
310 |
|
311 handler->wait_read = FALSE; |
|
312 return 0; |
293 } |
313 } |
294 |
314 |
295 int cgi_writeevent(EventHandler *ev, Event *event) { |
315 int cgi_writeevent(EventHandler *ev, Event *event) { |
296 CGIHandler *handler = event->cookie; |
316 CGIHandler *handler = event->cookie; |
297 |
317 |
298 // cgi_read_output will try to flush the buffer |
318 // cgi_read_output will try to flush the buffer |
299 int ret = cgi_read_output(handler, ev); |
319 CgiIOResult ret = cgi_read_output(handler, ev); |
300 if(ret == 0) { |
320 switch(ret) { |
301 handler->poll_out = FALSE; |
321 case CGI_IO_COMPLETE: { |
302 } |
322 break; |
303 return ret; |
323 } |
304 } |
324 case CGI_IO_NEED_READ: { |
305 |
325 if(ev_pollin(ev, handler->process.out[0], event)) { |
306 |
326 handler->result = REQ_ABORTED; |
307 |
327 } else { |
308 int cgi_read_output(CGIHandler *handler, EventHandler *ev) { |
328 handler->wait_read = TRUE; |
|
329 } |
|
330 } |
|
331 case CGI_IO_NEED_WRITE: { |
|
332 return 1; |
|
333 } |
|
334 case CGI_IO_ERROR: { |
|
335 break; |
|
336 } |
|
337 } |
|
338 |
|
339 handler->poll_out = FALSE; |
|
340 return 0; |
|
341 } |
|
342 |
|
343 |
|
344 |
|
345 CgiIOResult cgi_read_output(CGIHandler *handler, EventHandler *ev) { |
309 CGIResponseParser *parser = handler->parser; |
346 CGIResponseParser *parser = handler->parser; |
310 Session *sn = parser->sn; |
347 Session *sn = parser->sn; |
311 Request *rq = parser->rq; |
348 Request *rq = parser->rq; |
312 |
349 |
313 // try to flush handler->writebuf |
350 // try to flush handler->writebuf |
314 // if writebuf is empty, this does nothing and returns 0 |
351 // if writebuf is empty, this does nothing and returns 0 |
315 if(cgi_try_write_flush(handler, sn)) { |
352 if(cgi_try_write_flush(handler, sn)) { |
316 if(handler->result == REQ_ABORTED) { |
353 if(handler->result == REQ_ABORTED) { |
317 log_ereport(LOG_DEBUG, "cgi-send: req: %p write failed: %s: abort", handler->parser->rq, strerror(net_errno(sn->csd)), rq); |
354 log_ereport(LOG_DEBUG, "cgi-send: req: %p write failed: %s: abort", handler->parser->rq, strerror(net_errno(sn->csd)), rq); |
318 return 0; |
355 return CGI_IO_ERROR; |
319 } else { |
356 } else { |
320 return 1; |
357 return CGI_IO_NEED_WRITE; |
321 } |
358 } |
322 } |
359 } |
323 |
360 |
324 char buf[4096]; // I/O buffer |
361 char buf[4096]; // I/O buffer |
325 ssize_t r; |
362 ssize_t r; |
326 |
363 |
|
364 int ret = CGI_IO_COMPLETE; |
327 handler->result = REQ_PROCEED; |
365 handler->result = REQ_PROCEED; |
328 while((r = read(handler->process.out[0], buf, 4096)) > 0) { |
366 while((r = read(handler->process.out[0], buf, 4096)) > 0) { |
329 if(parser->cgiheader) { |
367 if(parser->cgiheader) { |
330 size_t pos; |
368 size_t pos; |
331 int ret = cgi_parse_response(parser, buf, r, &pos); |
369 int ret = cgi_parse_response(parser, buf, r, &pos); |
347 } |
385 } |
348 |
386 |
349 handler->response = http_create_response(sn, rq); |
387 handler->response = http_create_response(sn, rq); |
350 if(!handler->response) { |
388 if(!handler->response) { |
351 handler->result = REQ_ABORTED; |
389 handler->result = REQ_ABORTED; |
352 return 0; |
390 return CGI_IO_ERROR; |
353 } |
391 } |
354 |
392 |
355 int send_response = http_send_response(handler->response); |
393 int send_response = http_send_response(handler->response); |
356 if(send_response < 0) { |
394 if(send_response < 0) { |
357 handler->result = REQ_ABORTED; |
395 handler->result = REQ_ABORTED; |
|
396 ret = CGI_IO_ERROR; |
358 break; |
397 break; |
359 } else if(send_response == 1) { |
398 } else if(send_response == 1) { |
360 // EWOULDBLOCK |
399 // EWOULDBLOCK |
361 if(!handler->poll_out) { |
400 if(!handler->poll_out) { |
362 if(event_pollout(ev, sn->csd, handler->writeev)) { |
401 if(event_pollout(ev, sn->csd, handler->writeev)) { |
363 handler->result = REQ_ABORTED; |
402 handler->result = REQ_ABORTED; |
364 return 0; |
403 return CGI_IO_ERROR; |
365 } |
404 } |
366 handler->poll_out = TRUE; |
405 handler->poll_out = TRUE; |
367 return 1; |
406 return CGI_IO_NEED_WRITE; |
368 } |
407 } |
369 } else { |
408 } else { |
370 handler->response = NULL; |
409 handler->response = NULL; |
371 } |
410 } |
372 |
411 |
373 if(pos < r) { |
412 if(pos < r) { |
374 if(cgi_try_write(handler, ev, sn, &buf[pos], r-pos)) { |
413 if(cgi_try_write(handler, ev, sn, &buf[pos], r-pos)) { |
375 return handler->result == REQ_ABORTED ? 0 : 1; |
414 return handler->result == REQ_ABORTED ? CGI_IO_ERROR : CGI_IO_NEED_WRITE; |
376 } |
415 } |
377 } |
416 } |
378 } |
417 } |
379 } else { |
418 } else { |
380 parser->response_length += r; |
419 parser->response_length += r; |
381 if(cgi_try_write(handler, ev, sn, buf, r)) { |
420 if(cgi_try_write(handler, ev, sn, buf, r)) { |
382 return handler->result == REQ_ABORTED ? 0 : 1; |
421 return handler->result == REQ_ABORTED ? CGI_IO_ERROR : CGI_IO_NEED_WRITE; |
383 } |
422 } |
384 } |
423 } |
385 } |
424 } |
386 if(r < 0 && errno == EWOULDBLOCK) { |
425 if(r < 0 && errno == EWOULDBLOCK) { |
387 return 1; |
426 return CGI_IO_NEED_READ; |
388 } |
427 } |
389 handler->cgi_eof = TRUE; |
428 handler->cgi_eof = TRUE; |
390 return 0; |
429 return ret; |
391 } |
430 } |
392 |
431 |
393 int cgi_stderr_readevent(EventHandler *ev, Event *event) { |
432 int cgi_stderr_readevent(EventHandler *ev, Event *event) { |
394 CGIHandler *handler = event->cookie; |
433 CGIHandler *handler = event->cookie; |
395 pool_handle_t *pool = handler->parser->sn->pool; |
434 pool_handle_t *pool = handler->parser->sn->pool; |