separate http query argument parsing into a new http module, and clean up unused headers from web_main.c
authorTero Marttila <terom@fixme.fi>
Fri, 06 Jun 2008 16:05:26 +0300
changeset 10 9daa832ab9c4
parent 9 fb6632e6c1bb
child 11 082bfaf38cf0
separate http query argument parsing into a new http module, and clean up unused headers from web_main.c

committer: Tero Marttila <terom@fixme.fi>
Makefile
http.c
http.h
web_main.c
--- a/Makefile	Fri Jun 06 03:24:55 2008 +0300
+++ b/Makefile	Fri Jun 06 16:05:26 2008 +0300
@@ -6,6 +6,7 @@
 all: render_file render_node web_main
 
 common.o: common.c common.h
+http.o: http.c http.h
 remote_node.o: remote_node.c remote_node.h
 remote_pool.o: remote_pool.c remote_pool.h
 render.o: render.c render.h
@@ -17,7 +18,7 @@
 
 render_file: render_file.o common.o render.o mandelbrot.o
 render_node: render_node.o common.o render.o mandelbrot.o
-web_main: web_main.o common.o render.o remote_node.o remote_pool.o render_remote.o
+web_main: web_main.o common.o http.o render.o remote_node.o remote_pool.o render_remote.o
 
 clean :
 	rm *.o ${EXECS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/http.c	Fri Jun 06 16:05:26 2008 +0300
@@ -0,0 +1,67 @@
+#include <sys/queue.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <event2/event_struct.h>
+
+#include "http.h"
+#include "common.h"
+
+int http_qarg_parse (struct evhttp_request *request, struct http_qarg *qarg_spec) {
+    // our return code
+    int error_flag = 0;
+
+#define ERROR(msg, ...) do { error("http_qarg_parse: " msg, __VA_ARGS__); error_flag = -1; goto error; } while (0)
+    
+    // get the uri from the request
+    const char *uri = evhttp_request_get_uri(request);
+    
+    // the keyval list that we get from evhttp_parse_query
+    struct evkeyval *qarg;
+    struct evkeyvalq qargs;
+    
+    // parse the uri into a list
+    evhttp_parse_query(uri, &qargs);
+    
+    // iterate over the list of given query arugments
+    TAILQ_FOREACH(qarg, &qargs, next) {
+        struct http_qarg *qarg_info;
+        
+        // match them against our http_qarg structs
+        for (qarg_info = qarg_spec; qarg_info->hqa_type != QARG_END; qarg_info++) {
+            if (strcmp(qarg->key, qarg_info->hqa_key) == 0) {
+                // found a match
+                
+                // extract a value from the qarg
+                char *cptr = NULL;
+                signed long int int_val;
+
+                switch (qarg_info->hqa_type) {
+                    case QARG_UINT :
+                        int_val = strtol(qarg->value, &cptr, 10);
+
+                        if (*qarg->value == '\0' || *cptr != '\0' || int_val < 0)
+                            ERROR("Invalid QARG_UINT: %s: %s -> %d", qarg->key, qarg->value, int_val);
+
+                        *((unsigned long int *) qarg_info->hqa_addr) = (unsigned long int) int_val;
+
+                        break;
+                    
+                    case QARG_INVALID :
+                        ERROR("QARG_INVALID: %s: %s", qarg->key, qarg->value);
+
+                    default :
+                        err_exit("http_qarg_parse: Invalid qarg_info->hqa_type: %d", qarg_info->hqa_type);
+                }
+            }
+        }
+    }
+
+#undef ERROR    
+error:    
+
+    // clean up the qargs (badly named functions :< )
+    evhttp_clear_headers(&qargs);
+    
+    return error_flag;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/http.h	Fri Jun 06 16:05:26 2008 +0300
@@ -0,0 +1,36 @@
+/*
+ * The HTTP interface code
+ */
+
+#ifndef HTTP_H
+#define HTTP_H
+
+#include <event2/http.h>
+
+enum http_qarg_type {
+    QARG_INVALID,   // hqa_addr is NULL, abort parsing
+    QARG_INT,       // hqa_addr is a `signed long int`
+    QARG_UINT,      // hqa_addr is an `unsigned long int`
+
+    QARG_END,       // last item in the qarg_spec
+};
+
+struct http_qarg {
+    // the key to look for
+    const char          *hqa_key;
+
+    // the type of value
+    enum http_qarg_type  hqa_type;
+
+    // where to store the value, left unchanged if not found
+    void                *hqa_addr;
+};
+
+/*
+ * Parse the query args in the given evhttp_request according to the given http_arg specification.
+ *
+ * Returns zero if all matching fields were succesfully parsed, nonzero if any field was invalid
+ */
+int http_qarg_parse (struct evhttp_request *request, struct http_qarg *qarg_spec);
+
+#endif /* HTTP_H */
--- a/web_main.c	Fri Jun 06 03:24:55 2008 +0300
+++ b/web_main.c	Fri Jun 06 16:05:26 2008 +0300
@@ -1,23 +1,17 @@
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
 #include <stdlib.h>
-#include <stdio.h>
+#include <signal.h>
 #include <string.h>
-#include <netinet/ip.h>
-#include <arpa/inet.h>
-#include <signal.h>
 #include <unistd.h>
 
 #include <event2/event.h>
 #include <event2/event_compat.h>
-#include <event2/http.h>
 #include <event2/event_struct.h>
 
 #include "render.h"
 #include "render_remote.h"
 #include "remote_node.h"
 #include "remote_pool.h"
+#include "http.h"
 #include "common.h"
 
 #define MIN_CHUNK_SIZE 4096
@@ -233,41 +227,19 @@
     evhttp_request_get_peer(request, &peer_address, &peer_port);
     
     // request arguments
-    u_int32_t img_w = 256, img_h = 256;
-    struct evkeyval *qarg;
-    struct evkeyvalq qargs;
-
-/*
-    enum query_arg_type {
-        QARG_END,
-        QARG_INT,
+    unsigned long int img_w = 256, img_h = 256;
+    
+    struct http_qarg qarg_spec[] = {
+        { "w",      QARG_UINT,  &img_w  },
+        { "h",      QARG_UINT,  &img_h  },
+        { NULL,     QARG_END,   NULL    }
     };
 
-    struct query_arg {
-        const char          *qa_key;
-        enum query_arg_type  qa_type;
-        void                *qa_addr;
-    } arg_def[] = {
-        { "w",      QARG_INT,   &img_w  },
-        { "h",      QARG_INT,   &img_h  },
-        { NULL,     QARG_END,   NULL    }
-    };
-*/
-
-    evhttp_parse_query(uri, &qargs);
-
-    TAILQ_FOREACH(qarg, &qargs, next) {
-        if (strcmp(qarg->key, "w") == 0)
-            img_w = strtol(qarg->value, NULL, 10);
-        else if (strcmp(qarg->key, "h") == 0)
-            img_h = strtol(qarg->value, NULL, 10);
-    }
-
-    // clean up the qargs (badly named functions :< )
-    evhttp_clear_headers(&qargs);
+    // parse them
+    http_qarg_parse(request, qarg_spec);
 
     // request log
-    printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h);
+    printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%lu, img_h=%lu\n", peer_address, peer_port, evhttp_request_get_type(request), uri, img_w, img_h);
     
     // do it
     _http_render_execute(request, img_w, img_h);