summaryrefslogtreecommitdiff
path: root/ecore/src/e_ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecore/src/e_ipc.c')
-rw-r--r--ecore/src/e_ipc.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/ecore/src/e_ipc.c b/ecore/src/e_ipc.c
new file mode 100644
index 0000000..2a6de2b
--- /dev/null
+++ b/ecore/src/e_ipc.c
@@ -0,0 +1,187 @@
+#include "Ecore.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+void ecore_ipc_init(char *path);
+void ecore_ipc_cleanup(void);
+static void ecore_ipc_connect_handler(int fd);
+static void ecore_ipc_client_handler(int fd);
+void ecore_ipc_get_data(int fd, void *buf);
+void ecore_ipc_send_data(int fd, void *buf, int size);
+void ecore_add_ipc_service(int service, void (*func) (int fd));
+void ecore_del_ipc_service(int service);
+
+Ecore_Event_Ipc_Service *ipc_services = NULL;
+
+void
+ecore_ev_ipc_init(char *path)
+{
+ int fd, len;
+ struct sockaddr_un saun;
+
+ if (path == NULL)
+ return;
+
+ /* a UNIX domain, stream socket */
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ printf("Cannot create ipc socket... disabling ipc.\n");
+ return;
+ }
+
+ /* create the address we will be binding to */
+ saun.sun_family = AF_UNIX;
+ strcpy(saun.sun_path, path);
+
+ /* unlink the address so the bind won't fail */
+ unlink(path);
+ len = sizeof(saun.sun_family) + strlen(saun.sun_path);
+
+ if (bind(fd, (struct sockaddr *)&saun, len) < 0)
+ {
+ printf("Cannot bind ipc socket... disabling ipc.\n");
+ return;
+ }
+
+ /* listen on the socket */
+ if (listen(fd, 5) < 0)
+ {
+ printf("Cannot listen on ipc socket... disabling ipc.\n");
+ return;
+ }
+
+ /* add ipc listener */
+ ecore_add_event_ipc(fd, ecore_ipc_connect_handler);
+}
+
+void
+ecore_ev_ipc_cleanup(void)
+{
+ Ecore_Event_Ipc_Service *ipc_s;
+
+ /* cleanup services list */
+ for (ipc_s = ipc_services; ipc_s; ipc_s = ipc_s->next)
+ {
+ ecore_del_ipc_service(ipc_s->service);
+ }
+}
+
+static void
+ecore_ipc_connect_handler(int fd)
+{
+ struct sockaddr_un fsaun;
+ int fromlen, nfd;
+
+ /* accept ipc connection */
+ fromlen = sizeof(fsaun);
+
+ if ((nfd = accept(fd, (struct sockaddr *)&fsaun, &fromlen)) < 0)
+ {
+ printf("Cannot accept ipc connection... ignoring connection attempt.\n");
+ return;
+ }
+
+ /* add ipc client */
+ ecore_add_event_ipc(nfd, ecore_ipc_client_handler);
+}
+
+static void
+ecore_ipc_client_handler(int fd)
+{
+ int nread, service;
+ Ecore_Event_Ipc_Service *ipc_s;
+
+ if ((nread = read(fd, &service, sizeof(service))) == 0)
+ {
+ close(fd);
+ ecore_del_event_ipc(fd);
+ }
+ else if (nread > 0)
+ {
+ /* call the service function */
+ for (ipc_s = ipc_services; ipc_s; ipc_s = ipc_s->next)
+ {
+ if (ipc_s->service == service)
+ {
+ ipc_s->func(fd);
+ break;
+ }
+ }
+ }
+ else
+ {
+ printf("ipc error in read service.\n");
+ fflush(stdout);
+ }
+}
+
+void
+ecore_ipc_get_data(int fd, void *buf)
+{
+ int readn, nread;
+
+ /* read number of bytes being sent */
+ if ((nread = read(fd, &readn, sizeof(readn))) == -1)
+ {
+ printf("ipc error in get data.\n");
+ fflush(stdout);
+ return;
+ }
+
+ /* get data structure */
+ if ((nread = read(fd, buf, readn)) == -1)
+ {
+ printf("ipc error in get data.\n");
+ fflush(stdout);
+ return;
+ }
+}
+
+void
+ecore_ipc_send_data(int fd, void *buf, int size)
+{
+ int n;
+
+ /* send length of data being sent */
+ if ((n = write(fd, &size, sizeof(size))) == -1)
+ {
+ printf("ipc error in send data length.\n");
+ fflush(stdout);
+ return;
+ }
+
+ /* send data */
+ if ((n = write(fd, buf, size)) == -1)
+ {
+ printf("ipc error in send data.\n");
+ fflush(stdout);
+ return;
+ }
+}
+
+void
+ecore_add_ipc_service(int service, void (*func) (int fd))
+{
+ Ecore_Event_Ipc_Service *ipc_s;
+
+ /* delete the old service */
+ ecore_del_ipc_service(service);
+ /* new service struct */
+ ipc_s = NEW(Ecore_Event_Ipc_Service, 1);
+ ipc_s->next = ipc_services;
+ ipc_s->service = service;
+ ipc_s->func = func;
+ ipc_services = ipc_s;
+}
+
+void
+ecore_del_ipc_service(int service)
+{
+ START_LIST_DEL(Ecore_Event_Ipc_Service, ipc_services,
+ (_p->service == service));
+ FREE(_p);
+ END_LIST_DEL;
+}