web_main.c
changeset 3 675be0a45157
parent 2 69f8c0acaac7
child 4 49edbdf9ebe7
--- a/web_main.c	Sat May 31 19:35:21 2008 +0300
+++ b/web_main.c	Sun Jun 01 01:48:09 2008 +0300
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <netinet/ip.h>
 #include <arpa/inet.h>
+#include <signal.h>
 
 #include <event.h>
 #include <evhttp.h>
@@ -14,6 +15,9 @@
 #include "render_remote.h"
 #include "common.h"
 
+#define CHUNK_SIZE 4096
+#define OVERFLOW_BUFFER 4096
+
 // what render node to use
 static struct sockaddr_storage render_node;
 
@@ -22,11 +26,26 @@
     struct evhttp_request *http_request;
 
     int headers_sent;
+    
+    struct remote_render_ctx *remote_ctx;
+
+    size_t bytes_sent;
 };
 
+void _render_cleanup (struct render_request *ctx) {
+     // not interested anymore
+    evhttp_connection_set_closecb(ctx->http_request->evcon, NULL, NULL);
+
+    // clean up
+    free(ctx);
+}
+
 void _render_sent (void *arg) {
     struct render_request *ctx = arg;
 
+    // set chunk size
+    render_remote_set_chunk_size(ctx->remote_ctx, CHUNK_SIZE, OVERFLOW_BUFFER);
+
     // send headers
     evhttp_add_header(ctx->http_request->output_headers, "Content-Type", "image/png");
     evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
@@ -39,10 +58,14 @@
 void _render_data (struct evbuffer *buf, void *arg) {
     struct render_request *ctx = arg;
 
+    size_t buf_size = EVBUFFER_LENGTH(buf);
+
     // send chunk
     evhttp_send_reply_chunk(ctx->http_request, buf);
     
-    printf("render [%p]: sent chunk\n", ctx);
+    printf("render [%p]: enqueued chunk: %zu/%zu bytes\n", ctx, buf_size, ctx->bytes_sent);
+
+    ctx->bytes_sent += buf_size;
 }
 
 void _render_done (void *arg) {
@@ -51,10 +74,9 @@
     // send end
     evhttp_send_reply_end(ctx->http_request);
 
-    printf("render [%p]: done\n", ctx);
-
-    // clean up
-    free(ctx);
+    printf("render [%p]: done: %zu bytes\n", ctx, ctx->bytes_sent);
+    
+    _render_cleanup(ctx);
 }
 
 void _render_fail (void *arg) {
@@ -69,8 +91,18 @@
     
     printf("render [%p]: failed\n", ctx);
 
-    // clean up
-    free(ctx);
+    _render_cleanup(ctx);
+}
+
+void _render_http_lost (struct evhttp_connection *connection, void *arg) {
+    struct render_request *ctx = arg;
+
+    printf("render [%p]: lost http connection\n", ctx);
+
+    // cancel
+    render_remote_cancel(ctx->remote_ctx);
+
+    _render_cleanup(ctx);
 }
 
 void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
@@ -79,6 +111,7 @@
     
     req_ctx->http_request = request;
     req_ctx->headers_sent = 0;
+    req_ctx->bytes_sent = 0;
     
     // render context
     render_t rend_ctx;
@@ -87,17 +120,20 @@
     render_region_full(&rend_ctx);
     
     // initiate the remote render operation
-    if (render_remote(&rend_ctx, &render_node,
+    if ((req_ctx->remote_ctx = render_remote(&rend_ctx, &render_node,
         &_render_sent,
         &_render_data,
         &_render_done,
         &_render_fail,
         req_ctx
-    )) {
+    )) == NULL) {
         free(req_ctx);
         fprintf(stderr, "ERR: render_remote\n");
         return;
     }
+
+    // set close cb
+    evhttp_connection_set_closecb(request->evcon, &_render_http_lost, req_ctx);
     
     printf("render [%p]: started\n", req_ctx);
 }
@@ -131,19 +167,41 @@
     evhttp_clear_headers(&qargs);
 
     // request log
-    printf("REQ: [%s:%d] uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, uri, img_w, img_h);
+    printf("REQ: [%s:%d] method=%d, uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, request->type, uri, img_w, img_h);
     
     // do it
     _http_render_execute(request, img_w, img_h);
 }
 
+struct event ev_sigint;
+
+void sigint_handler (int signal, short event, void *arg) {
+    printf("SIGINT: shutting down\n");
+    
+    if (event_loopexit(NULL))
+        err_exit("event_loopexit");
+}
+
+void signals_init () {
+    signal_set(&ev_sigint, SIGINT, &sigint_handler, NULL);
+    signal_add(&ev_sigint, NULL);
+}
+
+void signals_deinit () {
+    signal_del(&ev_sigint);
+}
+
 int main (void) {
-    // libevent/http init
+    // libevent init
     struct event_base *ev_base = event_init();
 
     if (!ev_base)
         die("event_init");
-
+    
+    // handle signals
+    signals_init();
+    
+    // evhttp init
     struct evhttp *http_server = evhttp_new(ev_base);
 
     if (!http_server)
@@ -169,9 +227,13 @@
     // run the libevent mainloop
     if (event_dispatch())
         die("event_dispatch");
+
+    printf("SHUTDOWN\n");
     
     // clean up
+    signals_deinit();
     evhttp_free(http_server);
+    event_base_free(ev_base);
     
     // successfull exit
     return 0;