src/server/daemon/sessionhandler.c

changeset 542
1327febf99c4
parent 438
22eca559aded
child 543
3335f431a91b
equal deleted inserted replaced
541:1e1fca11aaff 542:1327febf99c4
37 #include "httpparser.h" 37 #include "httpparser.h"
38 #include "log.h" 38 #include "log.h"
39 #include "error.h" 39 #include "error.h"
40 #include "httplistener.h" 40 #include "httplistener.h"
41 41
42 typedef struct _event_http_io { 42 struct EventHttpIO {
43 HTTPRequest *request; 43 HTTPRequest *request;
44 HttpParser *parser; 44 HttpParser *parser;
45 int error; 45 int error;
46 } EventHttpIO; 46 };
47 47
48 48
49 int connection_read(Connection *conn, void *buf, int len) { 49 int connection_read(Connection *conn, void *buf, int len) {
50 return (int)read(conn->fd, buf, len); 50 return (int)read(conn->fd, buf, len);
51 } 51 }
220 handler->sh.create_iostream = create_connection_iostream; 220 handler->sh.create_iostream = create_connection_iostream;
221 return (SessionHandler*)handler; 221 return (SessionHandler*)handler;
222 } 222 }
223 223
224 void evt_enq_conn(SessionHandler *handler, Connection *conn) { 224 void evt_enq_conn(SessionHandler *handler, Connection *conn) {
225 Event *event = malloc(sizeof(Event));
226 if(!event) {
227 connection_destroy(conn);
228 return;
229 }
230
231 EventHttpIO *io = evt_req_init(handler, conn);
232 if(!io) {
233 connection_destroy(conn);
234 free(event);
235 return;
236 }
237
238 /*
239 * to start the request handling, we begin with a poll on the socket,
240 *
241 * evt_enq_conn() --> event handler --> handle_request()
242 */
243
244 ZERO(event, sizeof(Event));
245 event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input;
246 event->finish = evt_request_finish;
247 event->cookie = io;
248
249 EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler);
250
251 if(ev_pollin(ev, conn->fd, event) != 0) {
252 // TODO: ev_pollin should log, intercept some errors here
253 log_ereport(LOG_FAILURE, "Cannot enqueue connection");
254 evt_request_error(ev, event);
255 }
256 }
257
258 EventHttpIO* evt_req_init(SessionHandler *handler, Connection *conn) {
225 // set socket non blocking 259 // set socket non blocking
226 int flags; 260 int flags;
227 if ((flags = fcntl(conn->fd, F_GETFL, 0)) == -1) { 261 if ((flags = fcntl(conn->fd, F_GETFL, 0)) == -1) {
228 flags = 0; 262 flags = 0;
229 } 263 }
230 if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) { 264 if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) {
231 log_ereport(LOG_FAILURE, "sessionhandler: fcntl failed: %s", strerror(errno)); 265 log_ereport(LOG_FAILURE, "sessionhandler: fcntl failed: %s", strerror(errno));
232 connection_destroy(conn); 266 return NULL;
233 return;
234 } 267 }
235 268
236 HTTPRequest *request = malloc(sizeof(HTTPRequest)); 269 HTTPRequest *request = malloc(sizeof(HTTPRequest));
237 if(!request) { 270 if(!request) {
238 connection_destroy(conn); 271 return NULL;
239 return;
240 } 272 }
241 http_request_init(request); 273 http_request_init(request);
242 request->connection = conn; 274 request->connection = conn;
243 conn->session_handler = handler; 275 conn->session_handler = handler;
244 276
245 // TODO: remove code redundancy (basic_run_session) 277 // TODO: remove code redundancy (basic_run_session)
246 278
247 // read request 279 // read request
248 netbuf *buf = malloc(sizeof(netbuf)); 280 netbuf *buf = malloc(sizeof(netbuf));
249 if(!buf) { 281 if(!buf) {
250 connection_destroy(conn);
251 http_request_cleanup(request); 282 http_request_cleanup(request);
252 return; 283 return NULL;
253 } 284 }
254 buf->rdtimeout = 120; 285 buf->rdtimeout = 120;
255 buf->pos = 0; 286 buf->pos = 0;
256 buf->cursize = 0; 287 buf->cursize = 0;
257 buf->maxsize = 2048; 288 buf->maxsize = 2048;
258 buf->sd = &conn->fd; 289 buf->sd = &conn->fd;
259 buf->errmsg = NULL; 290 buf->errmsg = NULL;
260 buf->inbuf = malloc(2048); 291 buf->inbuf = malloc(2048);
261 if(!buf->inbuf) { 292 if(!buf->inbuf) {
262 connection_destroy(conn);
263 http_request_cleanup(request); 293 http_request_cleanup(request);
264 free(buf); 294 free(buf);
265 return; 295 return NULL;
266 } 296 }
267 297
268 request->netbuf = buf; 298 request->netbuf = buf;
269 299
270 HttpParser *parser = http_parser_new(request); 300 HttpParser *parser = http_parser_new(request);
271 if(!parser) { 301 if(!parser) {
272 connection_destroy(conn);
273 http_request_cleanup(request); 302 http_request_cleanup(request);
274 free(buf->inbuf); 303 free(buf->inbuf);
275 free(buf); 304 free(buf);
276 return; 305 return NULL;
277 } 306 }
278 307
279 EventHttpIO *io = malloc(sizeof(EventHttpIO)); 308 EventHttpIO *io = malloc(sizeof(EventHttpIO));
280 if(io == NULL) { 309 if(io == NULL) {
281 connection_destroy(conn);
282 http_request_cleanup(request); 310 http_request_cleanup(request);
283 free(buf->inbuf); 311 free(buf->inbuf);
284 free(buf); 312 free(buf);
285 http_parser_free(parser); 313 http_parser_free(parser);
286 return; 314 return NULL;
287 } 315 }
288 io->request = request; 316 io->request = request;
289 io->parser = parser; 317 io->parser = parser;
290 io->error = 0; 318 io->error = 0;
291 319
292 /* 320 return io;
293 * to start the request handling, we begin with a poll on the socket,
294 *
295 * evt_enq_conn() --> event handler --> handle_request()
296 */
297
298 Event *event = malloc(sizeof(Event));
299 ZERO(event, sizeof(Event));
300 event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input;
301 event->finish = evt_request_finish;
302 event->cookie = io;
303
304 EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler);
305
306 if(ev_pollin(ev, conn->fd, event) != 0) {
307 // TODO: ev_pollin should log, intercept some errors here
308 log_ereport(LOG_FAILURE, "Cannot enqueue connection");
309 evt_request_error(ev, event);
310 }
311 } 321 }
312 322
313 int evt_request_ssl_accept(EventHandler *handler, Event *event) { 323 int evt_request_ssl_accept(EventHandler *handler, Event *event) {
314 EventHttpIO *io = event->cookie; 324 EventHttpIO *io = event->cookie;
315 Connection *conn = io->request->connection; 325 Connection *conn = io->request->connection;
479 489
480 return 0; 490 return 0;
481 } 491 }
482 492
483 void evt_keep_alive(SessionHandler *handler, Connection *conn) { 493 void evt_keep_alive(SessionHandler *handler, Connection *conn) {
484 // TODO: set timeout 494 Event *event = malloc(sizeof(Event));
485 495 if(!event) {
486 /* TODO: 496 connection_destroy(conn);
487 * Don't just re-enqueue the connection 497 return;
488 * create a evt_req_init function which does most of the evt_enq_conn stuff 498 }
489 * but don't poll. 499
490 * evt_keep_alive should poll and if an event occurs: 500 EVWatchList *keepalive = malloc(sizeof(EVWatchList));
491 * evt_req_init 501 if(!keepalive) {
492 * evt_request_input 502 free(event);
493 * evt_enq_conn should do: 503 connection_destroy(conn);
494 * evt_req_init 504 return;
495 * ev_pollin 505 }
496 */ 506
497 evt_enq_conn(handler, conn); 507 ZERO(keepalive, sizeof(EVWatchList));
498 } 508 keepalive->destroy = evt_keep_alive_destroy;
509 keepalive->data = conn;
510
511 ZERO(event, sizeof(Event));
512 event->fn = evt_keep_alive_enqueue;
513 event->finish = ev_free_event; // this will free the event obj at the end
514 event->cookie = keepalive;
515
516 EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler);
517 if(event_send(ev, event)) {
518 log_ereport(LOG_FAILURE, "Keep-Alive: ev_send failed");
519 connection_destroy(conn);
520 free(event);
521 free(keepalive);
522 }
523 }
524
525 int evt_keep_alive_enqueue(EventHandler *h, Event *event) {
526 EVWatchList *keepalive = event->cookie;
527 Connection *conn = keepalive->data;
528
529 Event *ioevent = malloc(sizeof(Event));
530 if(!ioevent) {
531 connection_destroy(conn);
532 free(keepalive);
533 return 0;
534 }
535
536 // add keepalive object to the eventhandler watchlist
537 // the watchlist will check the timeout
538 keepalive->created = time(NULL);
539 keepalive->expire = keepalive->created + 60; // TODO: config
540 ev_watchlist_add(h, keepalive);
541
542 // wait for input
543 ZERO(ioevent, sizeof(Event));
544 ioevent->fn = evt_keep_alive_input_event;
545 ioevent->finish = ev_free_event;
546 ioevent->cookie = keepalive;
547 if(ev_pollin(h, conn->fd, ioevent) != 0) {
548 log_ereport(LOG_FAILURE, "Cannot enqueue connection");
549 ev_watchlist_remove(h, keepalive);
550 connection_destroy(conn);
551 free(keepalive);
552 free(ioevent);
553 }
554
555 return 0;
556 }
557
558 int evt_keep_alive_input_event(EventHandler *h, Event *event) {
559 EVWatchList *keepalive = event->cookie;
560 Connection *conn = keepalive->data;
561
562 // remove connection from the keep-alive list
563 ev_watchlist_remove(h, keepalive);
564 free(keepalive);
565
566 // prepare http io
567 EventHttpIO *io = evt_req_init(conn->session_handler, conn);
568 if(!io) {
569 connection_destroy(conn);
570 return 0;
571 }
572
573 // pass this event to the request input function
574 // the event object needs some adjustments for this (see evt_enq_conn)
575 event->cookie = io;
576 event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input;
577 event->finish = evt_request_finish;
578 return event->fn(h, event);
579 }
580
581 void evt_keep_alive_destroy(EventHandler *h, EVWatchList *item) {
582
583 }

mercurial