4 #include <sys/socket.h>
14 #include "evas_cs2_private.h"
18 typedef void (*Op_Callback)(void *data, const void *msg);
24 struct _Client_Request {
31 typedef struct _File_Entry File_Entry;
32 typedef struct _Client_Request Client_Request;
34 static int cserve2_init = 0;
35 static int socketfd = -1;
37 static unsigned int _rid_count = 0;
38 static unsigned int _file_id = 0;
39 static unsigned int _data_id = 0;
41 static Eina_List *_requests = NULL;
43 static struct sockaddr_un socksize;
45 #define UNIX_PATH_MAX sizeof(socksize.sun_path)
49 _socket_path_set(char *path)
52 char buf[UNIX_PATH_MAX];
54 env = getenv("EVAS_CSERVE2_SOCKET");
57 strncpy(path, env, UNIX_PATH_MAX - 1);
61 snprintf(buf, sizeof(buf), "/tmp/.evas-cserve2-%x.socket", (int)getuid());
62 /* FIXME: check we can actually create this socket */
65 env = getenv("XDG_RUNTIME_DIR");
71 env = getenv("TMPDIR");
77 snprintf(buf, sizeof(buf), "%s/evas-cserve2-%x.socket", env, getuid());
78 /* FIXME: check we can actually create this socket */
87 struct sockaddr_un remote;
89 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
95 remote.sun_family = AF_UNIX;
96 _socket_path_set(remote.sun_path);
97 len = strlen(remote.sun_path) + sizeof(remote.sun_family);
98 if (connect(s, (struct sockaddr *)&remote, len) == -1)
104 fcntl(s, F_SETFL, O_NONBLOCK);
108 DBG("connected to cserve2 server.");
113 _server_disconnect(void)
120 _request_answer_add(Message_Type type, unsigned int rid, Op_Callback cb, void *data)
122 Client_Request *cr = calloc(1, sizeof(*cr));
129 _requests = eina_list_append(_requests, cr);
133 _server_send(const void *buf, int size, Op_Callback cb, void *data)
136 if (send(socketfd, &size, sizeof(size), MSG_NOSIGNAL) == -1)
138 ERR("Couldn't send message size to server.");
141 if (send(socketfd, buf, size, MSG_NOSIGNAL) == -1)
143 ERR("Couldn't send message body to server.");
151 case CSERVE2_SETOPTS:
153 case CSERVE2_PRELOAD:
154 _request_answer_add(msg->type, msg->rid, cb, data);
163 static int sr_size = 0;
164 static int sr_got = 0;
165 static char *sr_buf = NULL;
168 _server_read(int *size)
176 n = recv(socketfd, &sr_size, sizeof(sr_size), 0);
180 sr_buf = malloc(sr_size);
183 n = recv(socketfd, sr_buf + sr_got, sr_size - sr_got, 0);
188 if (sr_got < sr_size)
201 evas_cserve2_init(void)
206 DBG("Connecting to cserve2.");
207 if (!_server_connect())
217 evas_cserve2_shutdown(void)
219 if ((--cserve2_init) > 0)
222 DBG("Disconnecting from cserve2.");
223 _server_disconnect();
229 evas_cserve2_use_get(void)
244 _server_dispatch(void)
248 Eina_List *l, *l_next;
252 msg = _server_read(&size);
256 EINA_LIST_FOREACH_SAFE(_requests, l, l_next, cr)
258 if (cr->rid != msg->rid) // dispatch this answer
261 _requests = eina_list_remove_list(_requests, l);
263 cr->cb(cr->data, msg);
274 _server_dispatch_until(unsigned int rid)
276 Eina_Bool done = EINA_FALSE;
280 if (_server_dispatch() == rid)
286 _image_opened_cb(void *data, const void *msg_received)
288 const Msg_Base *answer = msg_received;
289 const Msg_Opened *msg = msg_received;
290 Image_Entry *ie = data;
294 if (answer->type == CSERVE2_ERROR)
296 const Msg_Error *msg_error = msg_received;
297 ERR("Couldn't open image: '%s':'%s'; error: %d",
298 ie->file, ie->key, msg_error->error);
304 ie->w = msg->image.w;
305 ie->h = msg->image.h;
306 ie->flags.alpha = msg->image.alpha;
307 ie->loop_hint = msg->image.loop_hint;
308 ie->loop_count = msg->image.loop_count;
309 ie->frame_count = msg->image.frame_count;
313 _image_loaded_cb(void *data, const void *msg_received)
315 const Msg_Base *answer = msg_received;
316 const Msg_Loaded *msg = msg_received;
317 Image_Entry *ie = data;
318 Data_Entry *dentry = ie->data2;
326 if (answer->type == CSERVE2_ERROR)
328 const Msg_Error *msg_error = msg_received;
329 ERR("Couldn't load image: '%s':'%s'; error: %d",
330 ie->file, ie->key, msg_error->error);
336 shmpath = ((const char *)msg) + sizeof(*msg);
338 // dentry->shm.path = strdup(shmpath);
339 dentry->shm.mmap_offset = msg->shm.mmap_offset;
340 dentry->shm.use_offset = msg->shm.use_offset;
341 dentry->shm.mmap_size = msg->shm.mmap_size;
342 dentry->shm.image_size = msg->shm.image_size;
344 dentry->shm.f = eina_file_open(shmpath, EINA_TRUE);
352 dentry->shm.data = eina_file_map_new(dentry->shm.f, EINA_FILE_WILLNEED,
353 dentry->shm.mmap_offset,
354 dentry->shm.mmap_size);
356 if (!dentry->shm.data)
358 eina_file_close(dentry->shm.f);
365 ie->flags.loaded = EINA_TRUE;
366 ie->flags.alpha_sparse = msg->alpha_sparse;
371 _image_preloaded_cb(void *data, const void *msg_received)
373 const Msg_Base *answer = msg_received;
374 Image_Entry *ie = data;
375 Data_Entry *dentry = ie->data2;
377 DBG("Received PRELOADED for RID: %d", answer->rid);
380 if (answer->type == CSERVE2_ERROR)
382 const Msg_Error *msg_error = msg_received;
383 ERR("Couldn't preload image: '%s':'%s'; error: %d",
384 ie->file, ie->key, msg_error->error);
385 dentry->preloaded_cb(data, EINA_FALSE);
386 dentry->preloaded_cb = NULL;
390 if (dentry && (dentry->preloaded_cb))
392 dentry->preloaded_cb(data, EINA_TRUE);
393 dentry->preloaded_cb = NULL;
398 _build_absolute_path(const char *path, char buf[], int size)
409 strncpy(p, path, size);
410 else if (path[0] == '~')
412 const char *home = getenv("HOME");
415 strncpy(p, home, size);
421 strncpy(p, path + 2, size);
425 if (!getcwd(p, size))
432 strncpy(p, path, size);
439 _image_open_server_send(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt __UNUSED__)
444 char filebuf[PATH_MAX];
448 if (cserve2_init == 0)
450 ERR("Server not initialized.");
456 _build_absolute_path(file, filebuf, sizeof(filebuf));
458 fentry = calloc(1, sizeof(*fentry));
460 memset(&msg_open, 0, sizeof(msg_open));
462 fentry->file_id = ++_file_id;
463 if (fentry->file_id == 0)
464 fentry->file_id = ++_file_id;
466 flen = strlen(filebuf) + 1;
467 klen = strlen(key) + 1;
469 msg_open.base.rid = _next_rid();
470 msg_open.base.type = CSERVE2_OPEN;
471 msg_open.file_id = fentry->file_id;
472 msg_open.path_offset = 0;
473 msg_open.key_offset = flen;
475 size = sizeof(msg_open) + flen + klen;
477 if (!buf) return EINA_FALSE;
478 memcpy(buf, &msg_open, sizeof(msg_open));
479 memcpy(buf + sizeof(msg_open), filebuf, flen);
480 memcpy(buf + sizeof(msg_open) + flen, key, klen);
482 if (!_server_send(buf, size, _image_opened_cb, ie))
484 ERR("Couldn't send message to server.");
492 return msg_open.base.rid;
496 _image_setopts_server_send(Image_Entry *ie)
502 if (cserve2_init == 0)
507 dentry = calloc(1, sizeof(*dentry));
509 memset(&msg, 0, sizeof(msg));
510 dentry->image_id = ++_data_id;
511 if (dentry->image_id == 0)
512 dentry->image_id = ++_data_id;
514 msg.base.rid = _next_rid();
515 msg.base.type = CSERVE2_SETOPTS;
516 msg.file_id = fentry->file_id;
517 msg.image_id = dentry->image_id;
519 if (!_server_send(&msg, sizeof(msg), 0, NULL))
528 _image_load_server_send(Image_Entry *ie)
533 if (cserve2_init == 0)
538 ERR("No data for opened file.");
544 memset(&msg, 0, sizeof(msg));
546 msg.base.rid = _next_rid();
547 msg.base.type = CSERVE2_LOAD;
548 msg.image_id = dentry->image_id;
550 if (!_server_send(&msg, sizeof(msg), _image_loaded_cb, ie))
557 _image_preload_server_send(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_Bool success))
562 if (cserve2_init == 0)
566 dentry->preloaded_cb = preloaded_cb;
568 memset(&msg, 0, sizeof(msg));
570 msg.base.rid = _next_rid();
571 msg.base.type = CSERVE2_PRELOAD;
572 msg.image_id = dentry->image_id;
574 if (!_server_send(&msg, sizeof(msg), _image_preloaded_cb, ie))
581 _image_close_server_send(Image_Entry *ie)
586 if (cserve2_init == 0)
596 Data_Entry *dentry = ie->data2;
597 if (dentry->shm.data)
598 eina_file_map_free(dentry->shm.f, dentry->shm.data);
600 eina_file_close(dentry->shm.f);
605 memset(&msg, 0, sizeof(msg));
606 msg.base.rid = _next_rid();
607 msg.base.type = CSERVE2_CLOSE;
608 msg.file_id = fentry->file_id;
613 if (!_server_send(&msg, sizeof(msg), NULL, NULL))
620 _image_unload_server_send(Image_Entry *ie)
625 if (cserve2_init == 0)
633 if (dentry->shm.data)
634 eina_file_map_free(dentry->shm.f, dentry->shm.data);
636 eina_file_close(dentry->shm.f);
638 // if (dentry->shm.path)
639 // free(dentry->shm.path);
640 memset(&msg, 0, sizeof(msg));
641 msg.base.rid = _next_rid();
642 msg.base.type = CSERVE2_UNLOAD;
643 msg.image_id = dentry->image_id;
648 if (!_server_send(&msg, sizeof(msg), NULL, NULL))
655 evas_cserve2_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt)
659 rid = _image_open_server_send(ie, file, key, lopt);
665 _image_setopts_server_send(ie);
667 // _server_dispatch_until(rid);
676 evas_cserve2_image_load_wait(Image_Entry *ie)
680 _server_dispatch_until(ie->open_rid);
682 return CSERVE2_GENERIC;
686 return CSERVE2_GENERIC;
690 evas_cserve2_image_data_load(Image_Entry *ie)
694 rid = _image_load_server_send(ie);
707 evas_cserve2_image_load_data_wait(Image_Entry *ie)
710 _server_dispatch_until(ie->load_rid);
714 evas_cserve2_image_preload(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_Bool success))
721 rid = _image_preload_server_send(ie, preloaded_cb);
725 ie->preload_rid = rid;
731 evas_cserve2_image_free(Image_Entry *ie)
736 if (!_image_close_server_send(ie))
737 WRN("Couldn't send close message to cserve2.");
741 evas_cserve2_image_unload(Image_Entry *ie)
746 if (!_image_unload_server_send(ie))
747 WRN("Couldn't send unload message to cserve2.");
751 evas_cserve2_dispatch(void)
753 _server_dispatch_until(0);