#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);
fflush(stdout);
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);
}
}