fix memory alloc/free bugs, and one in render_threads where the last row was left out
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 <unistd.h>
#include "common.h"
#include "render.h"
#include "render_remote.h" // for RENDER_PORT_NAME
#include "render_local.h"
#include "render_threads.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) {
double duration;
struct render *ctx = NULL;
FILE *fh;
u_int8_t mode;
u_int32_t img_w, img_h;
double x1, y1, x2, y2;
struct render_threads *threads_info = NULL;
// open it as a FILE*
if (!(fh = fdopen(sock, "r+")))
ERROR("fdopen");
// read the parameters
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("read_{byte,int,double}");
printf("RENDER: [%ux%u] (%f, %f) -> (%f, %f): ... ", img_w, img_h, x1, y1, x2, y2);
fflush(stdout);
// set up the render_ctx
if (!(ctx = render_alloc()))
ERROR("render_alloc");
if (render_set_mode(ctx, mode))
ERROR("render_set_mode");
if (render_set_size(ctx, img_w, img_h))
ERROR("render_set_size");
if (render_region_raw(ctx, x1, y1, x2, y2))
ERROR("render_region_raw");
if (render_io_stream(ctx, fh))
ERROR("render_io_stream");
// render threaded \o/
if (!(threads_info = render_threads_alloc(ctx)))
goto error;
if (render_threads_wait(threads_info))
goto error;
printf("done!\n");
/*
// render!
if (render_local(ctx, &duration))
ERROR("render_local");
printf("time=%fs\n", duration);
*/
// fall through to just clean up normally
error:
if (ctx)
render_free(ctx);
if (threads_info)
render_threads_free(threads_info);
// 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;
// parse arguments
int opt;
const char *port_name = NULL;
unsigned short port;
while ((opt = getopt(argc, argv, "l:")) != -1) {
switch (opt) {
case 'l':
if (port_name)
ERROR("only specify -l once");
port_name = optarg;
break;
default:
err_exit("Usage: %s [-l port]", argv[0]);
}
}
// post-process arguments
if (!port_name)
port_name = RENDER_PORT_NAME;
if (!(port = atoi(port_name)))
ERROR("invalid port: %s", port_name);
// create the socket
if ((ssock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
PERROR("socket");
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(ssock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1)
PERROR("bind");
if (listen(ssock, 1) == -1)
PERROR("listen");
// ignore sigpipe
sigpipe_ignore();
// main accept loop
printf("RUN: %s:%hu\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
while (1) {
addr_len = sizeof(struct sockaddr_in);
// accept a new client
if ((sock = accept(ssock, (struct sockaddr *) &addr, &addr_len)) == -1)
PERROR("accept");
printf("ACCEPT: %s:%hu\n", inet_ntoa(addr.sin_addr), addr.sin_port);
// handle their resquest
handle_client(sock);
}
error:
return 1;
}