From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- libraries/evas/src/lib/cserve/evas_cs_client.c | 528 +++++++++++++++++++++++++ 1 file changed, 528 insertions(+) create mode 100644 libraries/evas/src/lib/cserve/evas_cs_client.c (limited to 'libraries/evas/src/lib/cserve/evas_cs_client.c') diff --git a/libraries/evas/src/lib/cserve/evas_cs_client.c b/libraries/evas/src/lib/cserve/evas_cs_client.c new file mode 100644 index 0000000..b24848d --- /dev/null +++ b/libraries/evas/src/lib/cserve/evas_cs_client.c @@ -0,0 +1,528 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "evas_cs.h" + +#ifdef EVAS_CSERVE + +static Server *cserve = NULL; +static int csrve_init = 0; +static int connect_num = 0; +static int cserve_discon = 0; + +static void +pipe_handler(int x __UNUSED__, siginfo_t *info __UNUSED__, void *data __UNUSED__) +{ +} + +static void +pipe_handle(int push) +{ + static struct sigaction old_action; + struct sigaction action; + + if (push) + { + action.sa_handler = NULL; + action.sa_sigaction = pipe_handler; + action.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGPIPE, &action, &old_action); + } + else + { + sigaction(SIGPIPE, &old_action, &action); + } +} + +static Server * +server_connect(void) +{ + Server *s; + char buf[PATH_MAX]; + int curstate = 0; + struct sockaddr_un socket_unix; + int socket_unix_len; + + s = calloc(1, sizeof(Server)); + if (!s) return NULL; + s->ch[0].fd = -1; + s->ch[1].fd = -1; + snprintf(buf, sizeof(buf), "/tmp/.evas-cserve-%x", getuid()); + s->socket_path = strdup(buf); + if (!s->socket_path) + { + free(s); + return NULL; + } + s->ch[0].fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (s->ch[0].fd < 0) goto error; + if (fcntl(s->ch[0].fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(s->ch[0].fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) + goto error; + socket_unix.sun_family = AF_UNIX; + strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path)); + socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix); + if (connect(s->ch[0].fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) goto error; + + s->ch[1].fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (s->ch[1].fd < 0) goto error; + if (fcntl(s->ch[1].fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(s->ch[1].fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) + goto error; + socket_unix.sun_family = AF_UNIX; + strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path)); + socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix); + if (connect(s->ch[1].fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) goto error; + + return s; + error: + if (s->ch[0].fd >= 0) close(s->ch[0].fd); + if (s->ch[1].fd >= 0) close(s->ch[1].fd); + free(s->socket_path); + free(s); + return NULL; +} + +static void +server_disconnect(Server *s) +{ + close(s->ch[0].fd); + close(s->ch[1].fd); + free(s->socket_path); + free(s); +} + +static int +server_send(Server *s, int channel, int opcode, int size, unsigned char *data) +{ + int ints[3]; + int num; + + pipe_handle(1); + ints[0] = size; + ints[1] = opcode; + s->ch[channel].req_to++; + ints[2] = s->ch[channel].req_to; + num = write(s->ch[channel].fd, ints, (sizeof(int) * 3)); + if (num < 0) + { + pipe_handle(0); + if (cserve) server_disconnect(cserve); + cserve = NULL; + return 0; + } + num = write(s->ch[channel].fd, data, size); + if (num < 0) + { + pipe_handle(0); + if (cserve) server_disconnect(cserve); + cserve = NULL; + return 0; + } + pipe_handle(0); + return 1; +} + +static unsigned char * +server_read(Server *s, int channel, int *opcode, int *size) +{ + int ints[3], num, left; + unsigned char *data; + + num = read(s->ch[channel].fd, ints, sizeof(int) * 3); + if (num != (sizeof(int) * 3)) + { + if (cserve) server_disconnect(cserve); + cserve = NULL; + return NULL; + } + *size = ints[0]; + *opcode = ints[1]; + if ((*size < 0) || (*size > (1024 * 1024))) return NULL; + if (ints[2] != (s->ch[channel].req_from + 1)) + { + ERR("EEK! sequence number mismatch from serer with pid: %i. " + "---- num %i is not 1 more than %i" + , + s->pid, ints[2], s->ch[channel].req_from); + return NULL; + } + s->ch[channel].req_from++; + data = malloc(*size); + if (!data) return NULL; + num = read(s->ch[channel].fd, data, *size); + if (num < 0) + { + free(data); + return NULL; + } + left = *size - num; + while (left > 0) + { + num = read(s->ch[channel].fd, data + (*size - left), left); + if (num < 0) + { + free(data); + return NULL; + } + left -= num; + } + return data; +} + +static int +server_init(Server *s) +{ + Op_Init msg, *rep; + int opcode; + int size; + + msg.pid = getpid(); + msg.server_id = 0; + msg.handle = NULL; + if (!server_send(s, 0, OP_INIT, sizeof(msg), (unsigned char *)(&msg))) + return 0; + rep = (Op_Init *)server_read(s, 0, &opcode, &size); + if ((rep) && (opcode == OP_INIT) && (size == sizeof(Op_Init))) + { + s->pid = rep->pid; + s->server_id = rep->server_id; + s->main_handle = rep->handle; + connect_num++; + msg.pid = getpid(); + msg.server_id = 1; + msg.handle = rep->handle; + free(rep); + if (!server_send(s, 1, OP_INIT, sizeof(msg), (unsigned char *)(&msg))) + return 0; + rep = (Op_Init *)server_read(s, 1, &opcode, &size); + if ((rep) && (opcode == OP_INIT) && (size == sizeof(Op_Init))) + { + free(rep); + return 1; + } + if (rep) free(rep); + return 0; + } + if (rep) free(rep); + return 0; +} + +EAPI Eina_Bool +evas_cserve_init(void) +{ + csrve_init++; + if (cserve) return 1; + cserve = server_connect(); + if (!cserve) return 0; + if (!server_init(cserve)) + { + if (cserve) server_disconnect(cserve); + cserve = NULL; + return 0; + } + return 1; +} + +EAPI int +evas_cserve_use_get(void) +{ + return csrve_init; +} + +EAPI Eina_Bool +evas_cserve_have_get(void) +{ + if (cserve) return 1; + return 0; +} + +EAPI void +evas_cserve_shutdown(void) +{ + csrve_init--; + if (csrve_init > 0) return; + if (!cserve) return; + server_disconnect(cserve); + cserve = NULL; +} + +EAPI void +evas_cserve_discon(void) +{ + if (cserve) + { + server_disconnect(cserve); + cserve = NULL; + cserve_discon = 1; + } +} + +static void +server_reinit(void) +{ + if (cserve) return; + if (cserve_discon) return; + cserve = server_connect(); + if (cserve) + { + if (!server_init(cserve)) + { + if (cserve) server_disconnect(cserve); + cserve = NULL; + } + } +} + +EAPI Eina_Bool +evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt) +{ + Op_Load msg; + Op_Load_Reply *rep; + unsigned char *buf; + char fbuf[PATH_MAX], wdb[PATH_MAX]; + int flen, klen; + int opcode; + int size; + + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!key) key = ""; + memset(&msg, 0, sizeof(msg)); + msg.lopt.scale_down_by = lopt->scale_down_by; + msg.lopt.dpi = lopt->dpi; + msg.lopt.w = lopt->w; + msg.lopt.h = lopt->h; + msg.lopt.region.x = lopt->region.x; + msg.lopt.region.y = lopt->region.y; + msg.lopt.region.w = lopt->region.w; + msg.lopt.region.h = lopt->region.h; + msg.lopt.orientation = lopt->orientation; + if (file[0] != '/') + { + if (getcwd(wdb, sizeof(wdb))) + { + snprintf(fbuf, sizeof(buf), "%s/%s", wdb, file); + file = fbuf; + } + } + if (!realpath(file, wdb)) file = wdb; + flen = strlen(file) + 1; + klen = strlen(key) + 1; + buf = malloc(sizeof(msg) + flen + klen); + if (!buf) return 0; + memcpy(buf, &msg, sizeof(msg)); + memcpy(buf + sizeof(msg), file, flen); + memcpy(buf + sizeof(msg) + flen, key, klen); + if (!server_send(cserve, ie->channel, OP_LOAD, + sizeof(msg) + flen + klen, + buf)) + { + free(buf); + return 0; + } + free(buf); + if (!cserve) return 0; + rep = (Op_Load_Reply *)server_read(cserve, ie->channel, &opcode, &size); + if ((rep) && (opcode == OP_LOAD) && (size == sizeof(Op_Load_Reply))) + { + ie->w = rep->image.w; + ie->h = rep->image.h; + ie->flags.alpha = rep->image.alpha; + ie->data1 = rep->handle; + } + if (rep) free(rep); + if (!ie->data1) return 0; + ie->connect_num = connect_num; + if (cserve) + ie->server_id = cserve->server_id; + return 1; +} + +EAPI Eina_Bool +evas_cserve_image_data_load(Image_Entry *ie) +{ + Op_Loaddata msg; + Op_Loaddata_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!ie->data1) return 0; + if (cserve->server_id != ie->server_id) + { + ie->data1 = NULL; + if (!evas_cserve_image_load(ie, ie->file, ie->key, &(ie->load_opts))) + return 0; + } + if (ie->connect_num != connect_num) return 0; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + msg.server_id = cserve->server_id; + if (!server_send(cserve, ie->channel, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg))) + return 0; + if (!cserve) return 0; + rep = (Op_Loaddata_Reply *)server_read(cserve, ie->channel, &opcode, &size); + if ((rep) && (opcode == OP_LOADDATA) && (size == sizeof(Op_Loaddata_Reply))) + { + if (rep->mem.size <= 0) + { + free(rep); + return 0; + } + ie->data2 = evas_cserve_mem_open(cserve->pid, rep->mem.id, NULL, rep->mem.size, 0); + free(rep); + return 1; + } + if (rep) free(rep); + return 0; +} + +EAPI void +evas_cserve_image_free(Image_Entry *ie) +{ + Op_Unload msg; + + if (csrve_init > 0) server_reinit(); + else return; + if (!cserve) return; + if (!ie->data1) return; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + msg.server_id = cserve->server_id; + if (ie->data2) evas_cserve_image_unload(ie); + if (cserve) + { + if (ie->connect_num == connect_num) + { + if (ie->server_id == cserve->server_id) + server_send(cserve, ie->channel, OP_UNLOAD, sizeof(msg), (unsigned char *)(&msg)); + } + } + ie->data1 = NULL; + ie->data2 = NULL; +} + +EAPI void +evas_cserve_image_unload(Image_Entry *ie) +{ + Op_Unloaddata msg; + + if (csrve_init > 0) server_reinit(); + else return; + if (!cserve) return; + if (!ie->data1) return; + if (ie->connect_num != connect_num) return; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + msg.server_id = cserve->server_id; + if (ie->data2) evas_cserve_mem_close(ie->data2); + ie->data2 = NULL; + if (ie->connect_num == connect_num) + { + if (ie->server_id == cserve->server_id) + server_send(cserve, ie->channel, OP_UNLOADDATA, sizeof(msg), (unsigned char *)(&msg)); + } +} + +EAPI void +evas_cserve_image_useless(Image_Entry *ie) +{ + Op_Unloaddata msg; + + if (csrve_init > 0) server_reinit(); + else return; + if (!cserve) return; + if (!ie->data1) return; + if (ie->connect_num != connect_num) return; + memset(&msg, 0, sizeof(msg)); + msg.handle = ie->data1; + msg.server_id = cserve->server_id; + if (ie->data2) evas_cserve_mem_close(ie->data2); + ie->data2 = NULL; + if (ie->connect_num == connect_num) + { + if (ie->server_id == cserve->server_id) + server_send(cserve, ie->channel, OP_USELESSDATA, sizeof(msg), (unsigned char *)(&msg)); + } +} + +EAPI Eina_Bool +evas_cserve_raw_config_get(Op_Getconfig_Reply *config) +{ + Op_Getconfig_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, 0, OP_GETCONFIG, 0, NULL)) return 0; + rep = (Op_Getconfig_Reply *)server_read(cserve, 0, &opcode, &size); + if ((rep) && (opcode == OP_GETCONFIG) && (size == sizeof(Op_Getconfig_Reply))) + { + memcpy(config, rep, sizeof(Op_Getconfig_Reply)); + free(rep); + return 1; + } + if (rep) free(rep); + return 0; +} + +EAPI Eina_Bool +evas_cserve_raw_config_set(Op_Setconfig *config) +{ + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, 0, OP_SETCONFIG, sizeof(Op_Setconfig), (unsigned char *)config)) return 0; + return 1; +} + +EAPI Eina_Bool +evas_cserve_raw_stats_get(Op_Getstats_Reply *stats) +{ + Op_Getstats_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return 0; + if (!cserve) return 0; + if (!server_send(cserve, 0, OP_GETSTATS, 0, NULL)) return 0; + rep = (Op_Getstats_Reply *)server_read(cserve, 0, &opcode, &size); + if ((rep) && (opcode == OP_GETSTATS) && (size == sizeof(Op_Getstats_Reply))) + { + memcpy(stats, rep, sizeof(Op_Getstats_Reply)); + free(rep); + return 1; + } + if (rep) free(rep); + return 0; +} + +EAPI Op_Getinfo_Reply * +evas_cserve_raw_info_get(void) +{ + Op_Getinfo_Reply *rep; + int opcode; + int size; + if (csrve_init > 0) server_reinit(); + else return NULL; + if (!cserve) return NULL; + if (!server_send(cserve, 0, OP_GETINFO, 0, NULL)) return NULL; + rep = (Op_Getinfo_Reply *)server_read(cserve, 0, &opcode, &size); + if ((rep) && (opcode == OP_GETINFO) && + (size >= (int)sizeof(Op_Getinfo_Reply))) + { + return rep; + } + if (rep) free(rep); + return NULL; +} + +#endif -- cgit v1.1