render_node.c
author Tero Marttila <terom@fixme.fi>
Sun, 01 Jun 2008 05:41:41 +0300
changeset 5 d4263f1f5b55
parent 3 675be0a45157
child 6 4252c27f2b72
permissions -rw-r--r--
remove a misplaced argument from render_remote.h (it still compiled and worked fine\!?)

committer: Tero Marttila <terom@fixme.fi>
#include <stdio.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

#include "render.h"
#include "render_remote.h"
#include "mandelbrot.h"
#include "common.h"

void sigpipe_handler (int signal) {
    /* ignore */
    fprintf(stderr, "SIGPIPE\n");
}

void sigpipe_ignore () {
    struct sigaction sigpipe_action;

    memset(&sigpipe_action, 0, sizeof(sigpipe_action));
    sigpipe_action.sa_handler = SIG_IGN;

    if (sigaction(SIGPIPE, &sigpipe_action, NULL))
        perr_exit("sigaction");
}

int my_fread(FILE *fh, void *ptr, size_t size) {
    int ret = fread(ptr, size, 1, fh);
    
    if (ret == 0) {
        error("EOF");
        return 0;

    } else if (ret != 1) {
        perror("fread");
        return 0;
    }

    return 1;
}

int read_byte (FILE *fh, u_int8_t *byte) {
    return my_fread(fh, byte, sizeof(*byte));
}

int read_int (FILE *fh, u_int32_t *i) {
    if (!my_fread(fh, i, sizeof(*i)))
        return 0;

    *i = ntohl(*i);

    return 1;
}

int read_double (FILE *fh, double *dbl) {
    if (!my_fread(fh, dbl, sizeof(*dbl)))
        return 0;

    return 1;
}

void handle_client (int sock) {
    // open it as a FILE*
    FILE *fh = fdopen(sock, "r+");
    
    // read the parameters
    u_int8_t mode;
    u_int32_t img_w, img_h;
    double x1, y1, x2, y2;

    if (
        !read_byte(fh, &mode) ||
        !read_int(fh, &img_w) ||
        !read_int(fh, &img_h) ||
        !read_double(fh, &x1) ||
        !read_double(fh, &y1) ||
        !read_double(fh, &x2) ||
        !read_double(fh, &y2)
    ) {
        error("ERR: invalid arguments");
        fclose(fh);
        return;
    }

    printf("RENDER: [%ux%u] (%f, %f) -> (%f, %f): ", img_w, img_h, x1, y1, x2, y2);

    double duration;

    // set up the render_ctx
    struct render_ctx ctx;
    render_init(&ctx, RENDER_PNG);
    render_set_size(&ctx, img_w, img_h);
    render_region_raw(&ctx, x1, y1, x2, y2);
    render_io_stream(&ctx, fh);
    
    sigpipe_ignore();
    
    // render!
    if (mandelbrot_render_timed(&ctx, &duration))
        printf("error\n");  // XXX: notify our client?
    else
        printf("time=%fs\n", duration);
    
    // close the FILE* and socket
    fclose(fh);
    
    return;
}


int main (int argc, char** argv) {
    int ssock, sock;
    struct sockaddr_in addr;
    socklen_t addr_len;


    // create the socket
    if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        perr_exit("socket");

    addr.sin_family = AF_INET;
    addr.sin_port = htons(RENDER_PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (argc > 1)
        addr.sin_port = htons(atoi(argv[1]));
    
    if (bind(ssock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1)
        perr_exit("bind");
    
    if (listen(ssock, 1) == -1)
        perr_exit("listen");
    
    printf("RUN: %s:%hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

    // main accept loop
    while (1) {
        addr_len = sizeof(struct sockaddr_in);

        // accept a new client
        if ((sock = accept(ssock, (struct sockaddr *) &addr, &addr_len)) == -1)
            perr_exit("accept");
        
        printf("ACCEPT: %s:%hu\n", inet_ntoa(addr.sin_addr), addr.sin_port);
        
        // handle their resquest
        handle_client(sock);
    }
}