diff -r 6aa1a0d1f88d -r 69f8c0acaac7 web_main.c --- a/web_main.c Sat May 31 02:22:27 2008 +0300 +++ b/web_main.c Sat May 31 19:35:21 2008 +0300 @@ -1,48 +1,110 @@ #include #include +#include #include #include #include +#include +#include #include #include -#include "mandelbrot.h" +#include "render.h" +#include "render_remote.h" #include "common.h" -struct http_render_state { - struct evbuffer *buf; - -} _http_render_state = { NULL }; +// what render node to use +static struct sockaddr_storage render_node; -int _http_render_cb (const unsigned char *data, size_t length, void *arg) { +// info on a render request +struct render_request { + struct evhttp_request *http_request; - // create a buffer - struct evbuffer *buf = evbuffer_new(); + int headers_sent; +}; - if (!buf) { - error("_http_render_cb: evbuffer_new failed"); - return RENDER_CB_ERR; +void _render_sent (void *arg) { + struct render_request *ctx = arg; + + // send headers + evhttp_add_header(ctx->http_request->output_headers, "Content-Type", "image/png"); + evhttp_send_reply_start(ctx->http_request, HTTP_OK, "OK"); + + ctx->headers_sent = 1; + + printf("render [%p]: sent headers\n", ctx); +} + +void _render_data (struct evbuffer *buf, void *arg) { + struct render_request *ctx = arg; + + // send chunk + evhttp_send_reply_chunk(ctx->http_request, buf); + + printf("render [%p]: sent chunk\n", ctx); +} + +void _render_done (void *arg) { + struct render_request *ctx = arg; + + // send end + evhttp_send_reply_end(ctx->http_request); + + printf("render [%p]: done\n", ctx); + + // clean up + free(ctx); +} + +void _render_fail (void *arg) { + struct render_request *ctx = arg; + + if (ctx->headers_sent) { + // just terminate the PNG stream where it is + evhttp_send_reply_end(ctx->http_request); + } else { + evhttp_send_error(ctx->http_request, 500, "Internal Server Error"); } - // add the data to it - if (evbuffer_add(buf, data, length)) { - error("_http_render_cb: evbuffer_add(%d) failed", length); - return RENDER_CB_ERR; + printf("render [%p]: failed\n", ctx); + + // clean up + free(ctx); +} + +void _http_render_execute (struct evhttp_request *request, u_int32_t img_w, u_int32_t img_h) { + // render request context + struct render_request *req_ctx = calloc(1, sizeof(struct render_request)); + + req_ctx->http_request = request; + req_ctx->headers_sent = 0; + + // render context + render_t rend_ctx; + render_init(&rend_ctx, RENDER_PNG); + render_set_size(&rend_ctx, img_w, img_h); + render_region_full(&rend_ctx); + + // initiate the remote render operation + if (render_remote(&rend_ctx, &render_node, + &_render_sent, + &_render_data, + &_render_done, + &_render_fail, + req_ctx + )) { + free(req_ctx); + fprintf(stderr, "ERR: render_remote\n"); + return; } - // send it - evhttp_send_reply_chunk((struct evhttp_request *) arg, buf); - - printf("_http_render_cb: sent chunk: %zu\n", length); - - // free the buffer (!!!) - evbuffer_free(buf); - - // return ok - return RENDER_CB_OK; + printf("render [%p]: started\n", req_ctx); } +/* + * HTTP request handler + */ void http_render (struct evhttp_request *request, void *arg) { // gather some info about the request const char *uri = evhttp_request_uri(request); @@ -71,22 +133,8 @@ // request log printf("REQ: [%s:%d] uri=%s, img_w=%d, img_h=%d\n", peer_address, peer_port, uri, img_w, img_h); - // set headers - evhttp_add_header(request->output_headers, "Content-Type", "image/png"); - evhttp_send_reply_start(request, HTTP_OK, "OK"); - - // render - struct render_ctx ctx; - render_ctx_set(&ctx, &_http_render_cb, NULL, request); - - int err = mandelbrot_render_full(&ctx, img_w, img_h); - - if (err) { - fprintf(stderr, "ERR: mandelbrot_render_full(%d, %d): %d\n", img_w, img_h, err); - } - - // reply end - evhttp_send_reply_end(request); + // do it + _http_render_execute(request, img_w, img_h); } int main (void) { @@ -107,7 +155,14 @@ // add our http request handler evhttp_set_cb(http_server, "/render", &http_render, NULL); - + + // hack in our render node + struct sockaddr_in *render_node_addr = (struct sockaddr_in *) &render_node; + + render_node_addr->sin_family = AF_INET; + render_node_addr->sin_port = htons(RENDER_PORT); + inet_aton("127.0.0.1", &render_node_addr->sin_addr); + // we shall now run printf("RUN 0.0.0.0:8117\n");