web_main.c
changeset 3 675be0a45157
parent 2 69f8c0acaac7
child 4 49edbdf9ebe7
equal deleted inserted replaced
2:69f8c0acaac7 3:675be0a45157
     4 #include <stdlib.h>
     4 #include <stdlib.h>
     5 #include <stdio.h>
     5 #include <stdio.h>
     6 #include <string.h>
     6 #include <string.h>
     7 #include <netinet/ip.h>
     7 #include <netinet/ip.h>
     8 #include <arpa/inet.h>
     8 #include <arpa/inet.h>
       
     9 #include <signal.h>
     9 
    10 
    10 #include <event.h>
    11 #include <event.h>
    11 #include <evhttp.h>
    12 #include <evhttp.h>
    12 
    13 
    13 #include "render.h"
    14 #include "render.h"
    14 #include "render_remote.h"
    15 #include "render_remote.h"
    15 #include "common.h"
    16 #include "common.h"
    16 
    17 
       
    18 #define CHUNK_SIZE 4096
       
    19 #define OVERFLOW_BUFFER 4096
       
    20 
    17 // what render node to use
    21 // what render node to use
    18 static struct sockaddr_storage render_node;
    22 static struct sockaddr_storage render_node;
    19 
    23 
    20 // info on a render request
    24 // info on a render request
    21 struct render_request {
    25 struct render_request {
    22     struct evhttp_request *http_request;
    26     struct evhttp_request *http_request;
    23 
    27 
    24     int headers_sent;
    28     int headers_sent;
       
    29     
       
    30     struct remote_render_ctx *remote_ctx;
       
    31 
       
    32     size_t bytes_sent;
    25 };
    33 };
    26 
    34 
       
    35 void _render_cleanup (struct render_request *ctx) {
       
    36      // not interested anymore
       
    37     evhttp_connection_set_closecb(ctx->http_request->evcon, NULL, NULL);
       
    38 
       
    39     // clean up
       
    40     free(ctx);
       
    41 }
       
    42 
    27 void _render_sent (void *arg) {
    43 void _render_sent (void *arg) {
    28     struct render_request *ctx = arg;
    44     struct render_request *ctx = arg;
       
    45 
       
    46     // set chunk size
       
    47     render_remote_set_chunk_size(ctx->remote_ctx, CHUNK_SIZE, OVERFLOW_BUFFER);
    29 
    48 
    30     // send headers
    49     // send headers
    31     evhttp_add_header(ctx->http_request->output_headers, "Content-Type", "image/png");
    50     evhttp_add_header(ctx->http_request->output_headers, "Content-Type", "image/png");
    32     evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
    51     evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
    33 
    52 
    37 }
    56 }
    38 
    57 
    39 void _render_data (struct evbuffer *buf, void *arg) {
    58 void _render_data (struct evbuffer *buf, void *arg) {
    40     struct render_request *ctx = arg;
    59     struct render_request *ctx = arg;
    41 
    60 
       
    61     size_t buf_size = EVBUFFER_LENGTH(buf);
       
    62 
    42     // send chunk
    63     // send chunk
    43     evhttp_send_reply_chunk(ctx->http_request, buf);
    64     evhttp_send_reply_chunk(ctx->http_request, buf);
    44     
    65     
    45     printf("render [%p]: sent chunk\n", ctx);
    66     printf("render [%p]: enqueued chunk: %zu/%zu bytes\n", ctx, buf_size, ctx->bytes_sent);
       
    67 
       
    68     ctx->bytes_sent += buf_size;
    46 }
    69 }
    47 
    70 
    48 void _render_done (void *arg) {
    71 void _render_done (void *arg) {
    49     struct render_request *ctx = arg;
    72     struct render_request *ctx = arg;
    50 
    73 
    51     // send end
    74     // send end
    52     evhttp_send_reply_end(ctx->http_request);
    75     evhttp_send_reply_end(ctx->http_request);
    53 
    76 
    54     printf("render [%p]: done\n", ctx);
    77     printf("render [%p]: done: %zu bytes\n", ctx, ctx->bytes_sent);
    55 
    78     
    56     // clean up
    79     _render_cleanup(ctx);
    57     free(ctx);
       
    58 }
    80 }
    59 
    81 
    60 void _render_fail (void *arg) {
    82 void _render_fail (void *arg) {
    61     struct render_request *ctx = arg;
    83     struct render_request *ctx = arg;
    62 
    84 
    67         evhttp_send_error(ctx->http_request, 500, "Internal Server Error");
    89         evhttp_send_error(ctx->http_request, 500, "Internal Server Error");
    68     }
    90     }
    69     
    91     
    70     printf("render [%p]: failed\n", ctx);
    92     printf("render [%p]: failed\n", ctx);
    71 
    93 
    72     // clean up
    94     _render_cleanup(ctx);
    73     free(ctx);
    95 }
       
    96 
       
    97 void _render_http_lost (struct evhttp_connection *connection, void *arg) {
       
    98     struct render_request *ctx = arg;
       
    99 
       
   100     printf("render [%p]: lost http connection\n", ctx);
       
   101 
       
   102     // cancel
       
   103     render_remote_cancel(ctx->remote_ctx);
       
   104 
       
   105     _render_cleanup(ctx);
    74 }
   106 }
    75 
   107 
    76 void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
   108 void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
    77     // render request context
   109     // render request context
    78     struct render_request *req_ctx = calloc(1, sizeof(struct render_request));
   110     struct render_request *req_ctx = calloc(1, sizeof(struct render_request));
    79     
   111     
    80     req_ctx->http_request = request;
   112     req_ctx->http_request = request;
    81     req_ctx->headers_sent = 0;
   113     req_ctx->headers_sent = 0;
       
   114     req_ctx->bytes_sent = 0;
    82     
   115     
    83     // render context
   116     // render context
    84     render_t rend_ctx;
   117     render_t rend_ctx;
    85     render_init(&rend_ctx, RENDER_PNG);
   118     render_init(&rend_ctx, RENDER_PNG);
    86     render_set_size(&rend_ctx, img_w, img_h);
   119     render_set_size(&rend_ctx, img_w, img_h);
    87     render_region_full(&rend_ctx);
   120     render_region_full(&rend_ctx);
    88     
   121     
    89     // initiate the remote render operation
   122     // initiate the remote render operation
    90     if (render_remote(&rend_ctx, &render_node,
   123     if ((req_ctx->remote_ctx = render_remote(&rend_ctx, &render_node,
    91         &_render_sent,
   124         &_render_sent,
    92         &_render_data,
   125         &_render_data,
    93         &_render_done,
   126         &_render_done,
    94         &_render_fail,
   127         &_render_fail,
    95         req_ctx
   128         req_ctx
    96     )) {
   129     )) == NULL) {
    97         free(req_ctx);
   130         free(req_ctx);
    98         fprintf(stderr, "ERR: render_remote\n");
   131         fprintf(stderr, "ERR: render_remote\n");
    99         return;
   132         return;
   100     }
   133     }
       
   134 
       
   135     // set close cb
       
   136     evhttp_connection_set_closecb(request->evcon, &_render_http_lost, req_ctx);
   101     
   137     
   102     printf("render [%p]: started\n", req_ctx);
   138     printf("render [%p]: started\n", req_ctx);
   103 }
   139 }
   104 
   140 
   105 /*
   141 /*
   129 
   165 
   130     // clean up the qargs (badly named functions :< )
   166     // clean up the qargs (badly named functions :< )
   131     evhttp_clear_headers(&qargs);
   167     evhttp_clear_headers(&qargs);
   132 
   168 
   133     // request log
   169     // request log
   134     printf("REQ: [%s:%d] uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, uri, img_w, img_h);
   170     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);
   135     
   171     
   136     // do it
   172     // do it
   137     _http_render_execute(request, img_w, img_h);
   173     _http_render_execute(request, img_w, img_h);
   138 }
   174 }
   139 
   175 
       
   176 struct event ev_sigint;
       
   177 
       
   178 void sigint_handler (int signal, short event, void *arg) {
       
   179     printf("SIGINT: shutting down\n");
       
   180     
       
   181     if (event_loopexit(NULL))
       
   182         err_exit("event_loopexit");
       
   183 }
       
   184 
       
   185 void signals_init () {
       
   186     signal_set(&ev_sigint, SIGINT, &sigint_handler, NULL);
       
   187     signal_add(&ev_sigint, NULL);
       
   188 }
       
   189 
       
   190 void signals_deinit () {
       
   191     signal_del(&ev_sigint);
       
   192 }
       
   193 
   140 int main (void) {
   194 int main (void) {
   141     // libevent/http init
   195     // libevent init
   142     struct event_base *ev_base = event_init();
   196     struct event_base *ev_base = event_init();
   143 
   197 
   144     if (!ev_base)
   198     if (!ev_base)
   145         die("event_init");
   199         die("event_init");
   146 
   200     
       
   201     // handle signals
       
   202     signals_init();
       
   203     
       
   204     // evhttp init
   147     struct evhttp *http_server = evhttp_new(ev_base);
   205     struct evhttp *http_server = evhttp_new(ev_base);
   148 
   206 
   149     if (!http_server)
   207     if (!http_server)
   150         die("evhttp_new");
   208         die("evhttp_new");
   151     
   209     
   167     printf("RUN 0.0.0.0:8117\n");
   225     printf("RUN 0.0.0.0:8117\n");
   168     
   226     
   169     // run the libevent mainloop
   227     // run the libevent mainloop
   170     if (event_dispatch())
   228     if (event_dispatch())
   171         die("event_dispatch");
   229         die("event_dispatch");
       
   230 
       
   231     printf("SHUTDOWN\n");
   172     
   232     
   173     // clean up
   233     // clean up
       
   234     signals_deinit();
   174     evhttp_free(http_server);
   235     evhttp_free(http_server);
       
   236     event_base_free(ev_base);
   175     
   237     
   176     // successfull exit
   238     // successfull exit
   177     return 0;
   239     return 0;
   178 }
   240 }