using non blocking IO for request input

Sat, 18 Aug 2012 11:39:34 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 18 Aug 2012 11:39:34 +0200
changeset 35
4417619a9bbd
parent 34
2b4574e617c0
child 36
450d2d5f4735

using non blocking IO for request input

src/server/daemon/event.c file | annotate | diff | comparison | revisions
src/server/daemon/event.h file | annotate | diff | comparison | revisions
src/server/daemon/event_solaris.c file | annotate | diff | comparison | revisions
src/server/daemon/httplistener.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.c file | annotate | diff | comparison | revisions
src/server/daemon/httprequest.h file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/event.c	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/event.c	Sat Aug 18 11:39:34 2012 +0200
@@ -94,3 +94,11 @@
     return create_event_handler(&cfg);
 }
 
+
+event_handler_t* get_default_event_handler() {
+    return default_event_handler;
+}
+
+event_handler_t* get_event_handler(char *name) {
+    return ucx_map_cstr_get(event_handler_map, name);
+}
--- a/src/server/daemon/event.h	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/event.h	Sat Aug 18 11:39:34 2012 +0200
@@ -65,6 +65,10 @@
 
 int check_event_handler_cfg();
 
+event_handler_t* get_default_event_handler();
+
+event_handler_t* get_event_handler(char *name);
+
 /* implementation in event_$platform */
 event_handler_t* evhandler_create(int numthreads);
 
--- a/src/server/daemon/event_solaris.c	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/event_solaris.c	Sat Aug 18 11:39:34 2012 +0200
@@ -69,7 +69,10 @@
         conf->handler = ev;
         conf->port = ev->ports[i];
         
-        systhread_start(0, 0, (thrstartfunc)ev_handle_events, ev);
+        ev_thr_conf_t *thrconf = malloc(sizeof(ev_thr_conf_t));
+        thrconf->handler = ev;
+        thrconf->port = ev->ports[i];
+        systhread_start(0, 0, (thrstartfunc)ev_handle_events, thrconf);
         /* TODO: error handling */
     }
     
@@ -93,6 +96,7 @@
         int ret = port_getn(port, events, 16, &nev, &timeout);
         if(ret == -1) {
             /* TODO: check for error */
+            perror("port_getn");
             continue;
         }
         
@@ -109,7 +113,7 @@
 int ev_get_port(event_handler_t *h) {
     int nps = h->nports;
     if(nps == 1) {
-        return 0;
+        return h->ports[0];
     }
     
     int cp = h->lp % nps;
--- a/src/server/daemon/httplistener.c	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/httplistener.c	Sat Aug 18 11:39:34 2012 +0200
@@ -80,7 +80,8 @@
 
     HttpListener *listener = malloc(sizeof(HttpListener));
     listener->name = conf->name;
-    listener->session_handler = create_basic_session_handler();
+    //listener->session_handler = create_basic_session_handler();
+    listener->session_handler = create_event_session_handler();
     listener->nacceptors = conf->nacceptors;
     listener->port = conf->port;
     ucx_map_sstr_put(listener_map, listener->name, listener);
--- a/src/server/daemon/httprequest.c	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/httprequest.c	Sat Aug 18 11:39:34 2012 +0200
@@ -28,6 +28,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+
 #include <arpa/inet.h>
 
 #include "../public/nsapi.h"
@@ -64,7 +65,13 @@
 
     // create nsapi data structures
     NSAPISession *sn = malloc(sizeof(NSAPISession));
+    if(sn == NULL) {
+        /* TODO: error */
+    }
     NSAPIRequest *rq = malloc(sizeof(NSAPIRequest));
+    if(rq == NULL) {
+        /* TODO: error */
+    }
     request->rq = rq;
     rq->phase = NSAPIAuthTrans;
 
@@ -336,6 +343,11 @@
                 r = nsapi_finish_request(sn, rq);
             }
         }
+        
+        if(r == REQ_ABORTED) {
+            nsapi_error_request(sn, rq);
+        }
+        
     } while (r == REQ_RESTART);
 
     r = nsapi_finish_request(sn, rq);
@@ -350,6 +362,12 @@
     return 0;
 }
 
+int nsapi_error_request(NSAPISession *sn, NSAPIRequest *rq) {
+    // TODO
+    
+    return REQ_PROCEED;
+}
+
 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) {
     HTTPObjectConfig *objconf = rq->vs->objects;
     httpd_object *obj = objconf->objects[0];
--- a/src/server/daemon/httprequest.h	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/httprequest.h	Sat Aug 18 11:39:34 2012 +0200
@@ -79,6 +79,7 @@
 
 int nsapi_handle_request(NSAPISession *sn, NSAPIRequest *rq);
 int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq);
+int nsapi_error_request(NSAPISession *sn, NSAPIRequest *rq);
 
 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq);
 int nsapi_nametrans(NSAPISession *sn, NSAPIRequest *rq);
--- a/src/server/daemon/sessionhandler.c	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/sessionhandler.c	Sat Aug 18 11:39:34 2012 +0200
@@ -35,6 +35,11 @@
 #include "httprequest.h"
 #include "httpparser.h"
 
+typedef struct _event_http_io {
+    HTTPRequest *request;
+    HttpParser  *parser;
+} EventHttpIO;
+
 SessionHandler* create_basic_session_handler() {
     BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler));
     handler->threadpool = threadpool_new(8);
@@ -100,4 +105,111 @@
     return NULL;
 }
 
+/* ----- event session handler ----- */
 
+SessionHandler* create_event_session_handler() {
+    EventSessionHandler *handler = malloc(sizeof(EventSessionHandler));
+    handler->eventhandler = get_default_event_handler();
+    handler->sh.enqueue_connection = evt_enq_conn;
+    return (SessionHandler*)handler;
+}
+
+void evt_enq_conn(SessionHandler *handler, Connection *conn) {
+    HTTPRequest *request = http_request_new();
+    request->connection = conn;
+    
+    // set socket non blocking
+    int flags;
+    if (-1 == (flags = fcntl(conn->fd, F_GETFL, 0))) {
+        flags = 0;
+    }
+    if (fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK) != 0) {
+        perror("Error: start_event_session: fcntl");
+        // TODO: error
+    }
+    
+    // TODO: remove code redundancy (basic_run_session)
+    
+    // read request
+    netbuf *buf = malloc(sizeof(netbuf));
+    buf->rdtimeout = 120;
+    buf->pos = 0;
+    buf->cursize = 0;
+    buf->maxsize = 2048;
+    buf->sd = &conn->fd;
+    buf->inbuf = malloc(2048);
+    buf->errmsg = NULL;
+
+    request->netbuf = buf;
+    
+    HttpParser *parser = http_parser_new(request);
+    
+    EventHttpIO *io = malloc(sizeof(EventHttpIO));
+    if(io == NULL) {
+        // TODO: error handling
+    }
+    io->request = request;
+    io->parser  = parser;
+    
+    /*
+     * to start the request handling, we begin with a poll on the socket,
+     * 
+     * evt_enq_conn() --> event handler --> handle_request()
+     */
+    
+    event_handler_t *ev = ((EventSessionHandler*)handler)->eventhandler;
+    
+    event_t *event = malloc(sizeof(event_t));
+    event->fn = evt_request_input;
+    event->cookie = io;
+    
+    if(ev_pollin(ev, conn->fd, event) != 0) {
+        perror("poll");
+    }
+}
+
+void evt_request_input(event_handler_t *handler, event_t *event) {
+    EventHttpIO *io = event->cookie;
+    HttpParser  *parser  = io->parser;
+    HTTPRequest *request = io->request;
+    netbuf      *buf     = request->netbuf;
+    
+    int state;
+    int r;
+    r = read(
+            request->connection->fd,
+            buf->inbuf + buf->pos,
+            buf->maxsize - buf->pos);
+    if(r == -1) {
+        // TODO: error handling
+        fprintf(stderr, "%s\n", "Error: Cannot read from socket");
+        return;
+    }
+    
+    buf->cursize += r;
+    state = http_parser_process(parser);
+    if(state == 2) {
+        // TODO: error handling
+        fprintf(stderr, "%s\n", "Error: Cannot parse http request");
+        return;
+    } else if(state == 1) {
+        // we need more data -> begin poll, which repeats this function
+        ev_pollin(handler, request->connection->fd, event);
+        // TODO: check ev_pollin return value for errors
+        return;
+    }
+    
+    // we are done with reading
+    
+    // set socket blocking
+    int flags;
+    if (-1 == (flags = fcntl(request->connection->fd, F_GETFL, 0))) {
+        flags = 0;
+    }
+    if (fcntl(request->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) {
+        perror("Error: evt_request_input: fcntl");
+        // TODO: critical error
+    }
+    
+    r = handle_request(request);
+}
--- a/src/server/daemon/sessionhandler.h	Thu Aug 09 11:08:49 2012 +0200
+++ b/src/server/daemon/sessionhandler.h	Sat Aug 18 11:39:34 2012 +0200
@@ -31,6 +31,7 @@
 
 #include "../util/thrpool.h"
 #include "../public/nsapi.h"
+#include "event.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -54,8 +55,8 @@
 /*
  * BasicSessionHandler
  *
- * The BasicSessionHandler enqueues the connections to a threadpool. IO and
- * request processing is handled by one thread.
+ * The BasicSessionHandler enqueues the connections to a threadpool. IO is
+ * handled by the threadpool.
  */
 typedef struct _basic_session_handler {
     SessionHandler sh;
@@ -63,6 +64,22 @@
     
 } BasicSessionHandler;
 
+/*
+ * EventSessionHandler
+ * 
+ * The EventSessionHandler uses a event handler to handle request inputs.
+ */
+typedef struct _event_session_handler {
+    SessionHandler  sh;
+    event_handler_t *eventhandler;
+} EventSessionHandler;
+
+/*
+ * EventHttpIO
+ * 
+ * defined in sesionhandler.c
+ */
+
 
 SessionHandler* create_basic_session_handler();
 
@@ -71,6 +88,12 @@
 void* basic_run_session(void *data);
 
 
+SessionHandler* create_event_session_handler();
+
+void evt_enq_conn(SessionHandler *handler, Connection *conn);
+
+void evt_request_input(event_handler_t *h, event_t *event);
+
 
 #ifdef	__cplusplus
 }

mercurial