web_main.c
changeset 13 ee426f453cf5
parent 12 43297144f196
child 15 e7f0697814dc
equal deleted inserted replaced
12:43297144f196 13:ee426f453cf5
    14 #include <event2/http.h>
    14 #include <event2/http.h>
    15 #include <event2/event_struct.h>
    15 #include <event2/event_struct.h>
    16 
    16 
    17 #include "common.h"
    17 #include "common.h"
    18 #include "http.h"
    18 #include "http.h"
       
    19 #include "render_internal.h"
    19 #include "render.h"
    20 #include "render.h"
    20 #include "render_remote.h"
       
    21 #include "remote_node.h"
    21 #include "remote_node.h"
    22 #include "remote_pool.h"
    22 #include "remote_pool.h"
       
    23 
       
    24 // XXX: replace with a common one
       
    25 #include "render_remote.h"
       
    26 #include "render_multi.h"
    23 
    27 
    24 #define MIN_CHUNK_SIZE 4096
    28 #define MIN_CHUNK_SIZE 4096
    25 #define OVERFLOW_BUFFER 4096
    29 #define OVERFLOW_BUFFER 4096
    26 
    30 
    27 // do not do any userland socket output buffering
    31 // do not do any userland socket output buffering
    37 struct render_request {
    41 struct render_request {
    38     struct evhttp_request *http_request;
    42     struct evhttp_request *http_request;
    39 
    43 
    40     int headers_sent;
    44     int headers_sent;
    41     
    45     
    42     struct remote_render_ctx *remote_ctx;
    46     struct render_multi *render_info;
    43 
    47 
    44     size_t bytes_sent;
    48     size_t bytes_sent;
    45 
    49 
    46     int paused;
    50     int paused;
    47 };
    51 };
    48 
    52 
    49 // cb func prototypes
    53 // cb func prototypes
    50 void _render_http_written (struct evhttp_request *request, void *arg);
    54 static void _render_http_written (struct evhttp_request *request, void *arg);
    51 
    55 
    52 void _render_cleanup (struct render_request *ctx) {
    56 static void _render_cleanup (struct render_request *ctx) {
    53     // clean up
    57     // clean up
    54     free(ctx);
    58     free(ctx);
    55 }
    59 }
    56 
    60 
    57 void _render_sent (void *arg) {
    61 static void _render_sent (void *arg) {
    58     struct render_request *ctx = arg;
    62     struct render_request *ctx = arg;
    59 
    63 
    60     // set chunk size
    64     // set chunk size
    61     render_remote_set_recv(ctx->remote_ctx, MIN_CHUNK_SIZE, OVERFLOW_BUFFER);
    65     render_multi_set_recv(ctx->render_info, MIN_CHUNK_SIZE, OVERFLOW_BUFFER);
    62 
    66 
    63     // send headers
    67     // send headers
    64     evhttp_add_header(evhttp_request_get_output_headers(ctx->http_request), "Content-Type", "image/png");
    68     evhttp_add_header(evhttp_request_get_output_headers(ctx->http_request), "Content-Type", "image/png");
    65     evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
    69     evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK");
    66     
    70     
    70     ctx->headers_sent = 1;
    74     ctx->headers_sent = 1;
    71 
    75 
    72     printf("render [%p]: sent headers\n", ctx);
    76     printf("render [%p]: sent headers\n", ctx);
    73 }
    77 }
    74 
    78 
    75 void _render_data (struct evbuffer *buf, void *arg) {
    79 static void _render_data (struct evbuffer *buf, void *arg) {
    76     struct render_request *ctx = arg;
    80     struct render_request *ctx = arg;
    77 
    81 
    78     size_t buf_size = EVBUFFER_LENGTH(buf);
    82     size_t buf_size = EVBUFFER_LENGTH(buf);
    79 
    83 
    80     // ignore empty buffers, a result of render_remote_shake()
    84     // ignore empty buffers, a result of render_remote_shake()
   102     
   106     
   103     // keep a tally of total sent bytes
   107     // keep a tally of total sent bytes
   104     ctx->bytes_sent += buf_size;
   108     ctx->bytes_sent += buf_size;
   105 }
   109 }
   106 
   110 
   107 void _render_done (void *arg) {
   111 static void _render_done (void *arg) {
   108     struct render_request *ctx = arg;
   112     struct render_request *ctx = arg;
   109 
   113 
   110     // if we are paused, just shove the data into the http buffers, they might become larger than they should be, but it's easier to just move the data there and let render_remote complete
   114     // if we are paused, just shove the data into the http buffers, they might become larger than they should be, but it's easier to just move the data there and let render_remote complete
   111     if (ctx->paused) {
   115     if (ctx->paused) {
   112         printf("render [%p]: done: flushing the rest of our data\n", ctx);
   116         printf("render [%p]: done: flushing the rest of our data\n", ctx);
   113         ctx->paused = 0;
   117         ctx->paused = 0;
   114 
   118 
   115         render_remote_shake(ctx->remote_ctx);
   119         render_multi_shake(ctx->render_info);
   116     }
   120     }
   117 
   121 
   118     // send end
   122     // send end
   119     evhttp_send_reply_end(ctx->http_request);
   123     evhttp_send_reply_end(ctx->http_request);
   120 
   124 
   122         
   126         
   123     // the request is now done, clean up
   127     // the request is now done, clean up
   124     _render_cleanup(ctx);
   128     _render_cleanup(ctx);
   125 }
   129 }
   126 
   130 
   127 void _render_fail (void *arg) {
   131 static void _render_fail (void *arg) {
   128     struct render_request *ctx = arg;
   132     struct render_request *ctx = arg;
   129 
   133 
   130     if (ctx->headers_sent) {
   134     if (ctx->headers_sent) {
   131         // just terminate the PNG stream where it is
   135         // just terminate the PNG stream where it is
   132         evhttp_send_reply_end(ctx->http_request);
   136         evhttp_send_reply_end(ctx->http_request);
   137     printf("render [%p]: failed\n", ctx);
   141     printf("render [%p]: failed\n", ctx);
   138 
   142 
   139     _render_cleanup(ctx);
   143     _render_cleanup(ctx);
   140 }
   144 }
   141 
   145 
   142 void _render_http_lost (struct evhttp_request *req, void *arg) {
   146 static void _render_http_lost (struct evhttp_request *req, void *arg) {
   143     struct render_request *ctx = arg;
   147     struct render_request *ctx = arg;
   144 
   148 
   145     printf("render [%p]: lost http connection\n", ctx);
   149     printf("render [%p]: lost http connection\n", ctx);
   146 
   150 
   147     // cancel
   151     // cancel
   148     render_remote_cancel(ctx->remote_ctx);
   152     render_multi_cancel(ctx->render_info);
   149 
   153 
   150     _render_cleanup(ctx);
   154     _render_cleanup(ctx);
   151 }
   155 }
   152 
   156 
   153 void _render_http_written (struct evhttp_request *request, void *arg) {
   157 static void _render_http_written (struct evhttp_request *request, void *arg) {
   154     struct render_request *ctx = arg;
   158     struct render_request *ctx = arg;
   155     
   159     
   156     printf("render [%p]: http available for write\n", ctx);
   160     printf("render [%p]: http available for write\n", ctx);
   157     
   161     
   158     // unpause ourself
   162     // unpause ourself
   159     ctx->paused = 0;
   163     ctx->paused = 0;
   160 
   164 
   161     // shake out the buffers
   165     // shake out the buffers
   162     render_remote_shake(ctx->remote_ctx);
   166     render_multi_shake(ctx->render_info);
   163 }
   167 }
   164 
   168 
   165 void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
   169 static void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) {
   166     // render request context
   170     // render request context
   167     struct render_request *req_ctx = calloc(1, sizeof(struct render_request));
   171     struct render_request *req_ctx = calloc(1, sizeof(struct render_request));
   168 
   172 
   169     if (!req_ctx)
   173     if (!req_ctx)
   170         ERROR("calloc");
   174         ERROR("calloc");
   172     req_ctx->http_request = request;
   176     req_ctx->http_request = request;
   173     req_ctx->headers_sent = 0;
   177     req_ctx->headers_sent = 0;
   174     req_ctx->bytes_sent = 0;
   178     req_ctx->bytes_sent = 0;
   175     
   179     
   176     // render context
   180     // render context
   177     struct render *render;
   181     struct render render;
   178     
   182     
   179     if (!(render = render_alloc()))
   183     if (render_init(&render, RENDER_PNG))
   180         ERROR("render_alloc");
   184         ERROR("render_alloc");
   181 
   185 
   182     if (render_set_mode(render, RENDER_PNG))
   186     if (render_set_size(&render, img_w, img_h))
   183         ERROR("render_set_mode");
       
   184 
       
   185     if (render_set_size(render, img_w, img_h))
       
   186         ERROR("render_set_size");
   187         ERROR("render_set_size");
   187 
   188 
   188     if (render_region_full(render))
   189     if (render_region_full(&render))
   189         ERROR("render_region_full");
   190         ERROR("render_region_full");
   190 
   191 
       
   192 /*
   191     // pick a render_node
   193     // pick a render_node
   192     struct remote_node *node_info;
   194     struct remote_node *node_info;
   193 
   195 
   194     if ((node_info = remote_pool_get(&remote_pool)) == NULL)
   196     if ((node_info = remote_pool_get(&remote_pool)) == NULL)
   195         ERROR("remote_pool_get");
   197         ERROR("remote_pool_get");
       
   198 */
   196 
   199 
   197     // initiate the remote render operation
   200     // initiate the remote render operation
   198     if ((req_ctx->remote_ctx = render_remote(render, node_info,
   201     if ((req_ctx->render_info = render_multi(&render, &remote_pool,
   199         &_render_sent,
   202         &_render_sent,
   200         &_render_data,
   203         &_render_data,
   201         &_render_done,
   204         &_render_done,
   202         &_render_fail,
   205         &_render_fail,
   203         req_ctx
   206         req_ctx
   204     )) == NULL)
   207     )) == NULL)
   205         ERROR("render_remote");
   208         ERROR("render_multi");
   206 
   209 
   207     // set close cb
   210     // set close cb
   208     evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx);
   211     evhttp_set_reply_abortcb(request, &_render_http_lost, req_ctx);
   209     
   212     
   210     printf("render [%p]: started\n", req_ctx);
   213     printf("render [%p]: started\n", req_ctx);
   227     char *peer_address;
   230     char *peer_address;
   228     u_short peer_port;
   231     u_short peer_port;
   229 
   232 
   230     evhttp_request_get_peer(request, &peer_address, &peer_port);
   233     evhttp_request_get_peer(request, &peer_address, &peer_port);
   231     
   234     
   232     u_int32_t img_w = 256, img_h = 256;
   235     unsigned long int img_w = 256, img_h = 256;
   233 
   236 
   234     // parse request arguments
   237     // parse request arguments
   235     struct http_qarg qarg_spec[] = {
   238     struct http_qarg qarg_spec[] = {
   236         { "w",      QARG_UINT,  &img_w  },
   239         { "w",      QARG_UINT,  &img_w  },
   237         { "h",      QARG_UINT,  &img_h  },
   240         { "h",      QARG_UINT,  &img_h  },
   239     };
   242     };
   240 
   243 
   241     http_qarg_parse(request, qarg_spec);
   244     http_qarg_parse(request, qarg_spec);
   242 
   245 
   243     // request log
   246     // request log
   244     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);
   247     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);
   245     
   248     
   246     // do it
   249     // do it
   247     _http_render_execute(request, img_w, img_h);
   250     _http_render_execute(request, img_w, img_h);
   248 }
   251 }
   249 
   252