* estickies,
[framework/uifw/ecore.git] / src / lib / ecore_ipc / ecore_ipc.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include "Ecore.h"
10 #include "Ecore_Con.h"
11 #include "ecore_private.h"
12 #include "ecore_ipc_private.h"
13 #include "Ecore_Ipc.h"
14
15 #ifdef HAVE_NETINET_IN_H
16 # include <netinet/in.h>
17 #endif
18
19 #ifdef HAVE_WINSOCK2_H
20 # include <winsock2.h>
21 #endif
22
23 #define DLT_ZERO   0
24 #define DLT_ONE    1
25 #define DLT_SAME   2
26 #define DLT_SHL    3
27 #define DLT_SHR    4
28 #define DLT_ADD8   5
29 #define DLT_DEL8   6
30 #define DLT_ADDU8  7
31 #define DLT_DELU8  8
32 #define DLT_ADD16  9
33 #define DLT_DEL16  10
34 #define DLT_ADDU16 11
35 #define DLT_DELU16 12
36 #define DLT_SET    13
37 #define DLT_R1     14
38 #define DLT_R2     15
39
40 /* byte swappers - for dealing with big vs little endian machines */
41 EAPI unsigned short
42 _ecore_ipc_swap_16(unsigned short v)
43 {
44    unsigned char *s, t;
45
46    s = (unsigned char *)(&v);
47    t = s[0]; s[0] = s[1]; s[1] = t;
48    return v;
49 }
50
51 EAPI unsigned int
52 _ecore_ipc_swap_32(unsigned int v)
53 {
54    unsigned char *s, t;
55
56    s = (unsigned char *)(&v);
57    t = s[0]; s[0] = s[3]; s[3] = t;
58    t = s[1]; s[1] = s[2]; s[2] = t;
59    return v;
60 }
61
62 EAPI unsigned long long
63 _ecore_ipc_swap_64(unsigned long long v)
64 {
65    unsigned char *s, t;
66
67    s = (unsigned char *)(&v);
68    t = s[0]; s[0] = s[7]; s[7] = t;
69    t = s[1]; s[1] = s[6]; s[6] = t;
70    t = s[2]; s[2] = s[5]; s[5] = t;
71    t = s[3]; s[3] = s[4]; s[4] = t;
72    return v;
73 }
74
75 static int _ecore_ipc_dlt_int(int out, int prev, int *mode);
76 static int _ecore_ipc_ddlt_int(int in, int prev, int mode);
77
78 static int
79 _ecore_ipc_dlt_int(int out, int prev, int *mode)
80 {
81    int dlt;
82
83    /* 0 byte */
84    if (out == 0)
85      {
86         *mode = DLT_ZERO;
87         return 0;
88      }
89    if (out == (int)0xffffffff)
90      {
91         *mode = DLT_ONE;
92         return 0;
93      }
94    if (out == prev)
95      {
96         *mode = DLT_SAME;
97         return 0;
98      }
99    if (out == prev << 1)
100      {
101         *mode = DLT_SHL;
102         return 0;
103      }
104    if (out == prev >> 1)
105      {
106         *mode = DLT_SHR;
107         return 0;
108      }
109    /* 1 byte */
110    dlt = out - prev;
111    if (!(dlt & 0xffffff00))
112      {
113         *mode = DLT_ADD8;
114         return dlt & 0xff;
115      }
116    dlt = prev - out;
117    if (!(dlt & 0xffffff00))
118      {
119         *mode = DLT_DEL8;
120         return dlt & 0xff;
121      }
122    dlt = out - prev;
123    if (!(dlt & 0x00ffffff))
124      {
125         *mode = DLT_ADDU8;
126         return (dlt >> 24) & 0xff;
127      }
128    dlt = prev - out;
129    if (!(dlt & 0x00ffffff))
130      {
131         *mode = DLT_DELU8;
132         return (dlt >> 24) & 0xff;
133      }
134    /* 2 byte */
135    dlt = out - prev;
136    if (!(dlt & 0xffff0000))
137      {
138         *mode = DLT_ADD16;
139         return dlt & 0xffff;
140      }
141    dlt = prev - out;
142    if (!(dlt & 0xffff0000))
143      {
144         *mode = DLT_DEL16;
145         return dlt & 0xffff;
146      }
147    dlt = out - prev;
148    if (!(dlt & 0x0000ffff))
149      {
150         *mode = DLT_ADDU16;
151         return (dlt >> 16) & 0xffff;
152      }
153    dlt = prev - out;
154    if (!(dlt & 0x0000ffff))
155      {
156         *mode = DLT_DELU16;
157         return (dlt >> 16) & 0xffff;
158      }
159    /* 4 byte */
160    *mode = DLT_SET;
161    return out;
162 }
163
164 static int
165 _ecore_ipc_ddlt_int(int in, int prev, int mode)
166 {
167    switch (mode)
168      {
169       case DLT_ZERO:
170         return 0;
171         break;
172       case DLT_ONE:
173         return 0xffffffff;
174         break;
175       case DLT_SAME:
176         return prev;
177         break;
178       case DLT_SHL:
179         return prev << 1;
180         break;
181       case DLT_SHR:
182         return prev >> 1;
183         break;
184       case DLT_ADD8:
185         return prev + in;
186         break;
187       case DLT_DEL8:
188         return prev - in;
189         break;
190       case DLT_ADDU8:
191         return prev + (in << 24);
192         break;
193       case DLT_DELU8:
194         return prev - (in << 24);
195         break;
196       case DLT_ADD16:
197         return prev + in;
198         break;
199       case DLT_DEL16:
200         return prev - in;
201         break;
202       case DLT_ADDU16:
203         return prev + (in << 16);
204         break;
205       case DLT_DELU16:
206         return prev - (in << 16);
207         break;
208       case DLT_SET:
209         return in;
210         break;
211       case DLT_R1:
212         return 0;
213         break;
214       case DLT_R2:
215         return 0;
216         break;
217       default:
218         break;
219      }
220    return 0;
221 }
222
223 static int _ecore_ipc_event_client_add(void *data, int ev_type, void *ev);
224 static int _ecore_ipc_event_client_del(void *data, int ev_type, void *ev);
225 static int _ecore_ipc_event_server_add(void *data, int ev_type, void *ev);
226 static int _ecore_ipc_event_server_del(void *data, int ev_type, void *ev);
227 static int _ecore_ipc_event_client_data(void *data, int ev_type, void *ev);
228 static int _ecore_ipc_event_server_data(void *data, int ev_type, void *ev);
229 static void _ecore_ipc_event_client_add_free(void *data, void *ev);
230 static void _ecore_ipc_event_client_del_free(void *data, void *ev);
231 static void _ecore_ipc_event_client_data_free(void *data, void *ev);
232 static void _ecore_ipc_event_server_add_free(void *data, void *ev);
233 static void _ecore_ipc_event_server_del_free(void *data, void *ev);
234 static void _ecore_ipc_event_server_data_free(void *data, void *ev);
235
236 EAPI int ECORE_IPC_EVENT_CLIENT_ADD = 0;
237 EAPI int ECORE_IPC_EVENT_CLIENT_DEL = 0;
238 EAPI int ECORE_IPC_EVENT_SERVER_ADD = 0;
239 EAPI int ECORE_IPC_EVENT_SERVER_DEL = 0;
240 EAPI int ECORE_IPC_EVENT_CLIENT_DATA = 0;
241 EAPI int ECORE_IPC_EVENT_SERVER_DATA = 0;
242
243 static int                  init_count = 0;
244 static Eina_List           *servers = NULL;
245 static Ecore_Event_Handler *handler[6];
246
247 /**
248  * @defgroup Ecore_IPC_Library_Group IPC Library Functions
249  *
250  * Functions that set up and shut down the Ecore IPC Library.
251  */
252
253 /**
254  * Initialises the Ecore IPC library.
255  * @return  Number of times the library has been initialised without
256  *          being shut down.
257  * @ingroup Ecore_IPC_Library_Group
258  */
259 EAPI int
260 ecore_ipc_init(void)
261 {
262    int i = 0;
263
264    if (++init_count != 1) return init_count;
265
266    ecore_con_init();
267
268    ECORE_IPC_EVENT_CLIENT_ADD = ecore_event_type_new();
269    ECORE_IPC_EVENT_CLIENT_DEL = ecore_event_type_new();
270    ECORE_IPC_EVENT_SERVER_ADD = ecore_event_type_new();
271    ECORE_IPC_EVENT_SERVER_DEL = ecore_event_type_new();
272    ECORE_IPC_EVENT_CLIENT_DATA = ecore_event_type_new();
273    ECORE_IPC_EVENT_SERVER_DATA = ecore_event_type_new();
274
275    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD,
276                                           _ecore_ipc_event_client_add, NULL);
277    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL,
278                                           _ecore_ipc_event_client_del, NULL);
279    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
280                                           _ecore_ipc_event_server_add, NULL);
281    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
282                                           _ecore_ipc_event_server_del, NULL);
283    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA,
284                                           _ecore_ipc_event_client_data, NULL);
285    handler[i++] = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
286                                           _ecore_ipc_event_server_data, NULL);
287    return init_count;
288 }
289
290 /**
291  * Shuts down the Ecore IPC library.
292  * @return  Number of times the library has been initialised without being
293  *          shut down.
294  * @ingroup Ecore_IPC_Library_Group
295  */
296 EAPI int
297 ecore_ipc_shutdown(void)
298 {
299    int i;
300
301    if (--init_count != 0) return init_count;
302
303    while (servers) ecore_ipc_server_del(eina_list_data_get(servers));
304
305    for (i = 0; i < 6; i++)
306      ecore_event_handler_del(handler[i]);
307
308    ecore_con_shutdown();
309
310    return init_count;
311 }
312
313 /**
314  * @defgroup Ecore_IPC_Server_Group IPC Server Functions
315  *
316  * Functions the deal with IPC server objects.
317  */
318
319 /**
320  * Creates an IPC server that listens for connections.
321  *
322  * For more details about the @p compl_type, @p name and @p port
323  * parameters, see the @ref ecore_con_server_add documentation.
324  *
325  * @param   compl_type The connection type.
326  * @param   name       Name to associate with the socket used for connection.
327  * @param   port       Number to identify with socket used for connection.
328  * @param   data       Data to associate with the IPC server.
329  * @return  New IPC server.  If there is an error, @c NULL is returned.
330  * @ingroup Ecore_IPC_Server_Group
331  * @todo    Need to add protocol type parameter to this function.
332  */
333 EAPI Ecore_Ipc_Server *
334 ecore_ipc_server_add(Ecore_Ipc_Type compl_type, const char *name, int port, const void *data)
335 {
336    Ecore_Ipc_Server *svr;
337    Ecore_Ipc_Type type;
338    Ecore_Con_Type extra = 0;
339
340    svr = calloc(1, sizeof(Ecore_Ipc_Server));
341    if (!svr) return NULL;
342    type = compl_type;
343    type &= ~ECORE_IPC_USE_SSL;
344    if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL;
345    switch (type)
346      {
347       case ECORE_IPC_LOCAL_USER:
348         svr->server = ecore_con_server_add(ECORE_CON_LOCAL_USER | extra, name, port, svr);
349         break;
350       case ECORE_IPC_LOCAL_SYSTEM:
351         svr->server = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr);
352         break;
353       case ECORE_IPC_REMOTE_SYSTEM:
354         svr->server = ecore_con_server_add(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr);
355         break;
356       default:
357         free(svr);
358         return NULL;
359      }
360    if (!svr->server)
361      {
362         free(svr);
363         return NULL;
364      }
365    svr->max_buf_size = 32 * 1024;
366    svr->data = (void *)data;
367    servers = eina_list_append(servers, svr);
368    ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER);
369    return svr;
370 }
371
372 /**
373  * Creates an IPC server object to represent the IPC server listening
374  * on the given port.
375  *
376  * For more details about the @p compl_type, @p name and @p port
377  * parameters, see the @ref ecore_con_server_connect documentation.
378  *
379  * @param   compl_type The IPC connection type.
380  * @param   name       Name used to determine which socket to use for the
381  *                     IPC connection.
382  * @param   port       Number used to identify the socket to use for the
383  *                     IPC connection.
384  * @param   data       Data to associate with the server.
385  * @return  A new IPC server.  @c NULL is returned on error.
386  * @ingroup Ecore_IPC_Server_Group
387  * @todo    Need to add protocol type parameter.
388  */
389 EAPI Ecore_Ipc_Server *
390 ecore_ipc_server_connect(Ecore_Ipc_Type compl_type, char *name, int port, const void *data)
391 {
392    Ecore_Ipc_Server *svr;
393    Ecore_Ipc_Type type;
394    Ecore_Con_Type extra = 0;
395
396    svr = calloc(1, sizeof(Ecore_Ipc_Server));
397    if (!svr) return NULL;
398    type = compl_type;
399    type &= ~ECORE_IPC_USE_SSL;
400    if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL;
401    switch (type)
402      {
403       case ECORE_IPC_LOCAL_USER:
404         svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_USER | extra, name, port, svr);
405         break;
406       case ECORE_IPC_LOCAL_SYSTEM:
407         svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr);
408         break;
409       case ECORE_IPC_REMOTE_SYSTEM:
410         svr->server = ecore_con_server_connect(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr);
411         break;
412       default:
413         free(svr);
414         return NULL;
415      }
416    if (!svr->server)
417      {
418         free(svr);
419         return NULL;
420      }
421    svr->max_buf_size = -1;
422    svr->data = (void *)data;
423    servers = eina_list_append(servers, svr);
424    ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER);
425    return svr;
426 }
427
428 /**
429  * Closes the connection and frees the given IPC server.
430  * @param   svr The given IPC server.
431  * @return  The data associated with the server when it was created.
432  * @ingroup Ecore_IPC_Server_Group
433  */
434 EAPI void *
435 ecore_ipc_server_del(Ecore_Ipc_Server *svr)
436 {
437    void *data;
438
439    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
440      {
441         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
442                          "ecore_ipc_server_del");
443         return NULL;
444      }
445    if (svr->delete_me) return NULL;
446
447    data = svr->data;
448    svr->data = NULL;
449    svr->delete_me = 1;
450    if (svr->event_count == 0)
451      {
452         Ecore_Ipc_Client *cl;
453
454         EINA_LIST_FREE(svr->clients, cl)
455           ecore_ipc_client_del(cl);
456         ecore_con_server_del(svr->server);
457         servers = eina_list_remove(servers, svr);
458
459         if (svr->buf) free(svr->buf);
460         ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE);
461         free(svr);
462      }
463    return data;
464 }
465
466 /**
467  * Retrieves the data associated with the given IPC server.
468  * @param   svr The given IPC server.
469  * @return  The associated data.
470  * @ingroup Ecore_IPC_Server_Group
471  */
472 EAPI void *
473 ecore_ipc_server_data_get(Ecore_Ipc_Server *svr)
474 {
475    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
476      {
477         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
478                          "ecore_ipc_server_data_get");
479         return NULL;
480      }
481    return svr->data;
482 }
483
484 /**
485  * Retrieves whether the given IPC server is currently connected.
486  * @param   svr The given IPC server.
487  * @return  @c 1 if the server is connected.  @c 0 otherwise.
488  * @ingroup Ecore_IPC_Server_Group
489  */
490 EAPI int
491 ecore_ipc_server_connected_get(Ecore_Ipc_Server *svr)
492 {
493    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
494      {
495         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
496                          "ecore_ipc_server_connected_get");
497         return 0;
498      }
499    return ecore_con_server_connected_get(svr->server);
500 }
501
502 /**
503  * Retrieves the list of clients for this server.
504  * @param   svr The given IPC server.
505  * @return  An Eina_List with the clients.
506  * @ingroup Ecore_IPC_Server_Group
507  */
508 EAPI Eina_List *
509 ecore_ipc_server_clients_get(Ecore_Ipc_Server *svr)
510 {
511    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
512      {
513         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
514                          "ecore_ipc_server_clients_get");
515         return NULL;
516      }
517    return svr->client_list;
518 }
519
520 #define SVENC(_member) \
521    d = _ecore_ipc_dlt_int(msg._member, svr->prev.o._member, &md); \
522    if (md >= DLT_SET) \
523      { \
524         unsigned int v; \
525         unsigned char *dd; \
526         dd = (unsigned char *)&v; \
527         v = d; \
528         v = htonl(v); \
529         *(dat + s + 0) = dd[0]; \
530         *(dat + s + 1) = dd[1]; \
531         *(dat + s + 2) = dd[2]; \
532         *(dat + s + 3) = dd[3]; \
533         s += 4; \
534      } \
535    else if (md >= DLT_ADD16) \
536      { \
537         unsigned short v; \
538         unsigned char *dd; \
539         dd = (unsigned char *)&v; \
540         v = d; \
541         v = htons(v); \
542         *(dat + s + 0) = dd[0]; \
543         *(dat + s + 1) = dd[1]; \
544         s += 2; \
545      } \
546    else if (md >= DLT_ADD8) \
547      { \
548         *(dat + s + 0) = (unsigned char)d; \
549         s += 1; \
550      }
551
552 /**
553  * Sends a message to the given IPC server.
554  *
555  * The content of the parameters, excluding the @p svr paramter, is up to
556  * the client.
557  *
558  * @param   svr      The given IPC server.
559  * @param   major    Major opcode of the message.
560  * @param   minor    Minor opcode of the message.
561  * @param   ref      Message reference number.
562  * @param   ref_to   Reference number of the message this message refers to.
563  * @param   response Requires response.
564  * @param   data     The data to send as part of the message.
565  * @param   size     Length of the data, in bytes, to send.
566  * @return  Number of bytes sent.  @c 0 is returned if there is an error.
567  * @ingroup Ecore_IPC_Server_Group
568  * @todo    This function needs to become an IPC message.
569  * @todo Fix up the documentation: Make sure what ref_to and response are.
570  */
571 EAPI int
572 ecore_ipc_server_send(Ecore_Ipc_Server *svr, int major, int minor, int ref, int ref_to, int response, const void *data, int size)
573 {
574    Ecore_Ipc_Msg_Head msg;
575    int ret;
576    int *head, md = 0, d, s;
577    unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)];
578
579    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
580      {
581         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
582                          "ecore_ipc_server_send");
583         return 0;
584      }
585    if (size < 0) size = 0;
586    msg.major    = major;
587    msg.minor    = minor;
588    msg.ref      = ref;
589    msg.ref_to   = ref_to;
590    msg.response = response;
591    msg.size     = size;
592    head = (int *)dat;
593    s = 4;
594    SVENC(major);
595    *head = md;
596    SVENC(minor);
597    *head |= md << (4 * 1);
598    SVENC(ref);
599    *head |= md << (4 * 2);
600    SVENC(ref_to);
601    *head |= md << (4 * 3);
602    SVENC(response);
603    *head |= md << (4 * 4);
604    SVENC(size);
605    *head |= md << (4 * 5);
606    *head = htonl(*head);
607    svr->prev.o = msg;
608    ret = ecore_con_server_send(svr->server, dat, s);
609    if (size > 0) ret += ecore_con_server_send(svr->server, data, size);
610    return ret;
611 }
612
613 /**
614  * Sets a limit on the number of clients that can be handled concurrently
615  * by the given server, and a policy on what to do if excess clients try to
616  * connect.
617  * Beware that if you set this once ecore is already running, you may
618  * already have pending CLIENT_ADD events in your event queue.  Those
619  * clients have already connected and will not be affected by this call.
620  * Only clients subsequently trying to connect will be affected.
621  * @param   svr           The given server.
622  * @param   client_limit  The maximum number of clients to handle
623  *                        concurrently.  -1 means unlimited (default).  0
624  *                        effectively disables the server.
625  * @param   reject_excess_clients  Set to 1 to automatically disconnect
626  *                        excess clients as soon as they connect if you are
627  *                        already handling client_limit clients.  Set to 0
628  *                        (default) to just hold off on the "accept()"
629  *                        system call until the number of active clients
630  *                        drops. This causes the kernel to queue up to 4096
631  *                        connections (or your kernel's limit, whichever is
632  *                        lower).
633  * @ingroup Ecore_Ipc_Server_Group
634  */
635 EAPI void
636 ecore_ipc_server_client_limit_set(Ecore_Ipc_Server *svr, int client_limit, char reject_excess_clients)
637 {
638    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
639      {
640         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
641                          "ecore_ipc_server_client_limit_set");
642         return;
643      }
644    ecore_con_server_client_limit_set(svr->server, client_limit, reject_excess_clients);
645 }
646
647 /**
648  * Sets the max data payload size for an Ipc message in bytes
649  *
650  * @param   svr           The given server.
651  * @param   size          The maximum data payload size in bytes.
652  * @ingroup Ecore_Ipc_Server_Group
653  */
654 EAPI void
655 ecore_ipc_server_data_size_max_set(Ecore_Ipc_Server *svr, int size)
656 {
657    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
658      {
659         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
660                          "ecore_ipc_server_data_size_max_set");
661         return;
662      }
663    svr->max_buf_size = size;
664 }
665
666 /**
667  * Gets the max data payload size for an Ipc message in bytes
668  *
669  * @param   svr           The given server.
670  * @return The maximum data payload in bytes.
671  * @ingroup Ecore_Ipc_Server_Group
672  */
673 EAPI int
674 ecore_ipc_server_data_size_max_get(Ecore_Ipc_Server *svr)
675 {
676    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
677      {
678         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
679                          "ecore_ipc_server_data_size_max_get");
680         return -1;
681      }
682    return svr->max_buf_size;
683 }
684
685 /**
686  * Gets the IP address of a server that has been connected to.
687  *
688  * @param   svr           The given server.
689  * @return  A pointer to an internal string that contains the IP address of
690  *          the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
691  *          This string should not be modified or trusted to stay valid after
692  *          deletion for the @p svr object. If no IP is known NULL is returned.
693  * @ingroup Ecore_Ipc_Server_Group
694  */
695 EAPI char *
696 ecore_ipc_server_ip_get(Ecore_Ipc_Server *svr)
697 {
698    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
699      {
700         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
701                          "ecore_ipc_server_ip_get");
702         return NULL;
703      }
704    return ecore_con_server_ip_get(svr->server);
705 }
706
707 /**
708  * Flushes all pending data to the given server. Will return when done.
709  *
710  * @param   svr           The given server.
711  * @ingroup Ecore_Ipc_Server_Group
712  */
713 EAPI void
714 ecore_ipc_server_flush(Ecore_Ipc_Server *svr)
715 {
716    if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER))
717      {
718         ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER,
719                          "ecore_ipc_server_server_flush");
720         return;
721      }
722    ecore_con_server_flush(svr->server);
723 }
724
725 #define CLENC(_member) \
726    d = _ecore_ipc_dlt_int(msg._member, cl->prev.o._member, &md); \
727    if (md >= DLT_SET) \
728      { \
729         unsigned int v; \
730         unsigned char *dd; \
731         dd = (unsigned char *)&v; \
732         v = d; \
733         v = htonl(v); \
734         *(dat + s + 0) = dd[0]; \
735         *(dat + s + 1) = dd[1]; \
736         *(dat + s + 2) = dd[2]; \
737         *(dat + s + 3) = dd[3]; \
738         s += 4; \
739      } \
740    else if (md >= DLT_ADD16) \
741      { \
742         unsigned short v; \
743         unsigned char *dd; \
744         dd = (unsigned char *)&v; \
745         v = d; \
746         v = htons(v); \
747         *(dat + s + 0) = dd[0]; \
748         *(dat + s + 1) = dd[1]; \
749         s += 2; \
750      } \
751    else if (md >= DLT_ADD8) \
752      { \
753         *(dat + s) = (unsigned char)d; \
754         s += 1; \
755      }
756
757 /**
758  * @defgroup Ecore_IPC_Client_Group IPC Client Functions
759  *
760  * Functions that deal with IPC client objects.
761  */
762
763 /**
764  * Sends a message to the given IPC client.
765  * @param   cl       The given IPC client.
766  * @param   major    Major opcode of the message.
767  * @param   minor    Minor opcode of the message.
768  * @param   ref      Reference number of the message.
769  * @param   ref_to   Reference number of the message this message refers to.
770  * @param   response Requires response.
771  * @param   data     The data to send as part of the message.
772  * @param   size     Length of the data, in bytes, to send.
773  * @return  The number of bytes sent.  @c 0 will be returned if there is
774  *          an error.
775  * @ingroup Ecore_IPC_Client_Group
776  * @todo    This function needs to become an IPC message.
777  * @todo    Make sure ref_to and response parameters are described correctly.
778  */
779 EAPI int
780 ecore_ipc_client_send(Ecore_Ipc_Client *cl, int major, int minor, int ref, int ref_to, int response, const void *data, int size)
781 {
782    Ecore_Ipc_Msg_Head msg;
783    int ret;
784    int *head, md = 0, d, s;
785    unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)];
786
787    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
788      {
789         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
790                          "ecore_ipc_client_send");
791         return 0;
792      }
793    if (size < 0) size = 0;
794    msg.major    = major;
795    msg.minor    = minor;
796    msg.ref      = ref;
797    msg.ref_to   = ref_to;
798    msg.response = response;
799    msg.size     = size;
800    head = (int *)dat;
801    s = 4;
802    CLENC(major);
803    *head = md;
804    CLENC(minor);
805    *head |= md << (4 * 1);
806    CLENC(ref);
807    *head |= md << (4 * 2);
808    CLENC(ref_to);
809    *head |= md << (4 * 3);
810    CLENC(response);
811    *head |= md << (4 * 4);
812    CLENC(size);
813    *head |= md << (4 * 5);
814    *head = htonl(*head);
815    cl->prev.o = msg;
816    ret = ecore_con_client_send(cl->client, dat, s);
817    if (size > 0) ret += ecore_con_client_send(cl->client, data, size);
818    return ret;
819 }
820
821 /**
822  * Retrieves the IPC server that the given IPC client is connected to.
823  * @param   cl The given IPC client.
824  * @return  The IPC server the IPC client is connected to.
825  * @ingroup Ecore_IPC_Client_Group
826  */
827 EAPI Ecore_Ipc_Server *
828 ecore_ipc_client_server_get(Ecore_Ipc_Client *cl)
829 {
830    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
831      {
832         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
833                          "ecore_ipc_client_server_get");
834         return NULL;
835      }
836    return (ecore_con_server_data_get(ecore_con_client_server_get(cl->client)));
837 }
838
839 /**
840  * Closes the connection and frees memory allocated to the given IPC
841  * client.
842  * @param   cl The given client.
843  * @return  Data associated with the client.
844  * @ingroup Ecore_IPC_Client_Group
845  */
846 EAPI void *
847 ecore_ipc_client_del(Ecore_Ipc_Client *cl)
848 {
849    void *data;
850    Ecore_Ipc_Server *svr;
851
852    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
853      {
854         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
855                          "ecore_ipc_client_del");
856         return NULL;
857      }
858    data = cl->data;
859    cl->data = NULL;
860    cl->delete_me = 1;
861    if (cl->event_count == 0)
862      {
863         svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client));
864         ecore_con_client_del(cl->client);
865         svr->clients = _ecore_list2_remove(svr->clients, cl);
866         if (cl->buf) free(cl->buf);
867         ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE);
868         free(cl);
869      }
870    return data;
871 }
872
873 /**
874  * Sets the IPC data associated with the given IPC client to @p data.
875  * @param   cl   The given IPC client.
876  * @param   data The data to associate with the IPC client.
877  * @ingroup Ecore_IPC_Client_Group
878  */
879 EAPI void
880 ecore_ipc_client_data_set(Ecore_Ipc_Client *cl, const void *data)
881 {
882    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
883      {
884         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
885                          "ecore_ipc_client_data_set");
886         return;
887      }
888    cl->data = (void *)data;
889 }
890
891 /**
892  * Retrieves the data that has been associated with the given IPC client.
893  * @param   cl The given client.
894  * @return  The data associated with the IPC client.
895  * @ingroup Ecore_IPC_Client_Group
896  */
897 EAPI void *
898 ecore_ipc_client_data_get(Ecore_Ipc_Client *cl)
899 {
900    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
901      {
902         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
903                          "ecore_ipc_client_data_get");
904         return NULL;
905      }
906    return cl->data;
907 }
908
909 /**
910  * Sets the max data payload size for an Ipc message in bytes
911  *
912  * @param   client        The given client.
913  * @param   size          The maximum data payload size in bytes.
914  * @ingroup Ecore_Ipc_Client_Group
915  */
916 EAPI void
917 ecore_ipc_client_data_size_max_set(Ecore_Ipc_Client *cl, int size)
918 {
919    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
920      {
921         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
922                          "ecore_ipc_client_data_size_max_set");
923         return;
924      }
925    cl->max_buf_size = size;
926 }
927
928 /**
929  * Sets the max data payload size for an Ipc message in bytes
930  *
931  * @param   cl            The given client.
932  * @param   size          The maximum data payload size in bytes.
933  * @ingroup Ecore_Ipc_Client_Group
934  */
935 EAPI int
936 ecore_ipc_client_data_size_max_get(Ecore_Ipc_Client *cl)
937 {
938    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
939      {
940         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
941                          "ecore_ipc_client_data_size_max_get");
942         return -1;
943      }
944    return cl->max_buf_size;
945 }
946
947 /**
948  * Gets the IP address of a client that has been connected to.
949  *
950  * @param   cl            The given client.
951  * @return  A pointer to an internal string that contains the IP address of
952  *          the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
953  *          This string should not be modified or trusted to stay valid after
954  *          deletion for the @p cl object. If no IP is known NULL is returned.
955  * @ingroup Ecore_Ipc_Client_Group
956  */
957 EAPI char *
958 ecore_ipc_client_ip_get(Ecore_Ipc_Client *cl)
959 {
960    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
961      {
962         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
963                          "ecore_ipc_client_ip_get");
964         return NULL;
965      }
966    return ecore_con_client_ip_get(cl->client);
967 }
968
969 /**
970  * Flushes all pending data to the given client. Will return when done.
971  *
972  * @param   cl            The given client.
973  * @ingroup Ecore_Ipc_Client_Group
974  */
975 EAPI void
976 ecore_ipc_client_flush(Ecore_Ipc_Client *cl)
977 {
978    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT))
979      {
980         ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT,
981                          "ecore_ipc_client_flush");
982         return;
983      }
984    ecore_con_client_flush(cl->client);
985 }
986
987 /**
988  * Returns if SSL support is available
989  * @return  1 if SSL is available, 0 if it is not.
990  * @ingroup Ecore_Con_Client_Group
991  */
992 EAPI int
993 ecore_ipc_ssl_available_get(void)
994 {
995    return ecore_con_ssl_available_get();
996 }
997
998
999 static int
1000 _ecore_ipc_event_client_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1001 {
1002    Ecore_Con_Event_Client_Add *e;
1003
1004    e = ev;
1005    if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
1006    /* handling code here */
1007      {
1008         Ecore_Ipc_Client *cl;
1009         Ecore_Ipc_Server *svr;
1010
1011         cl = calloc(1, sizeof(Ecore_Ipc_Client));
1012         if (!cl) return 0;
1013         svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client));
1014         ECORE_MAGIC_SET(cl, ECORE_MAGIC_IPC_CLIENT);
1015         cl->client = e->client;
1016         cl->max_buf_size = 32 * 1024;
1017         ecore_con_client_data_set(cl->client, (void *)cl);
1018         svr->clients = _ecore_list2_append(svr->clients, cl);
1019         svr->client_list = eina_list_append(svr->client_list, cl);
1020         if (!cl->delete_me)
1021           {
1022              Ecore_Ipc_Event_Client_Add *e2;
1023
1024              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Add));
1025              if (e2)
1026                {
1027                   cl->event_count++;
1028                   e2->client = cl;
1029                   ecore_event_add(ECORE_IPC_EVENT_CLIENT_ADD, e2,
1030                                   _ecore_ipc_event_client_add_free, NULL);
1031                }
1032           }
1033      }
1034    return 0;
1035 }
1036
1037 static int
1038 _ecore_ipc_event_client_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1039 {
1040    Ecore_Con_Event_Client_Del *e;
1041
1042    e = ev;
1043    if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
1044    /* handling code here */
1045      {
1046         Ecore_Ipc_Client *cl;
1047
1048         cl = ecore_con_client_data_get(e->client);
1049           {
1050              Ecore_Ipc_Event_Client_Del *e2;
1051              Ecore_Ipc_Server *svr;
1052
1053              svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client));
1054              svr->client_list = eina_list_remove(svr->client_list, cl);
1055              if (!cl->delete_me)
1056                {
1057                   e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Del));
1058                   if (e2)
1059                     {
1060                        cl->event_count++;
1061                        e2->client = cl;
1062                        ecore_event_add(ECORE_IPC_EVENT_CLIENT_DEL, e2,
1063                                        _ecore_ipc_event_client_del_free, NULL);
1064                     }
1065                }
1066           }
1067      }
1068    return 0;
1069 }
1070
1071 static int
1072 _ecore_ipc_event_server_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1073 {
1074    Ecore_Con_Event_Server_Add *e;
1075
1076    e = ev;
1077    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
1078    /* handling code here */
1079      {
1080         Ecore_Ipc_Server *svr;
1081
1082         svr = ecore_con_server_data_get(e->server);
1083         if (!svr->delete_me)
1084           {
1085              Ecore_Ipc_Event_Server_Add *e2;
1086
1087              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Add));
1088              if (e2)
1089                {
1090                   svr->event_count++;
1091                   e2->server = svr;
1092                   ecore_event_add(ECORE_IPC_EVENT_SERVER_ADD, e2,
1093                                   _ecore_ipc_event_server_add_free, NULL);
1094                }
1095           }
1096      }
1097    return 0;
1098 }
1099
1100 static int
1101 _ecore_ipc_event_server_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1102 {
1103    Ecore_Con_Event_Server_Del *e;
1104
1105    e = ev;
1106    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
1107    /* handling code here */
1108      {
1109         Ecore_Ipc_Server *svr;
1110
1111         svr = ecore_con_server_data_get(e->server);
1112         if (!svr->delete_me)
1113           {
1114              Ecore_Ipc_Event_Server_Del *e2;
1115
1116              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Del));
1117              if (e2)
1118                {
1119                   svr->event_count++;
1120                   e2->server = svr;
1121                   ecore_event_add(ECORE_IPC_EVENT_SERVER_DEL, e2,
1122                                   _ecore_ipc_event_server_del_free, NULL);
1123                }
1124           }
1125      }
1126    return 0;
1127 }
1128
1129 #define CLSZ(_n) \
1130    md = ((head >> (4 * _n)) & 0xf); \
1131    if (md >= DLT_SET) s += 4; \
1132    else if (md >= DLT_ADD16) s += 2; \
1133    else if (md >= DLT_ADD8) s += 1;
1134
1135 #define CLDEC(_n, _member) \
1136    md = ((head >> (4 * _n)) & 0xf); \
1137    if (md >= DLT_SET) \
1138      { \
1139         unsigned int v; \
1140         unsigned char *dv; \
1141         dv = (unsigned char *)&v; \
1142         dv[0] = *(cl->buf + offset + s + 0); \
1143         dv[1] = *(cl->buf + offset + s + 1); \
1144         dv[2] = *(cl->buf + offset + s + 2); \
1145         dv[3] = *(cl->buf + offset + s + 3); \
1146         d = (int)ntohl(v); \
1147         s += 4; \
1148      } \
1149    else if (md >= DLT_ADD16) \
1150      { \
1151         unsigned short v; \
1152         unsigned char *dv; \
1153         dv = (unsigned char *)&v; \
1154         dv[0] = *(cl->buf + offset + s + 0); \
1155         dv[1] = *(cl->buf + offset + s + 1); \
1156         d = (int)ntohs(v); \
1157         s += 2; \
1158      } \
1159    else if (md >= DLT_ADD8) \
1160      { \
1161         unsigned char v; \
1162         unsigned char *dv; \
1163         dv = (unsigned char *)&v; \
1164         dv[0] = *(cl->buf + offset + s + 0); \
1165         d = (int)v; \
1166         s += 1; \
1167      } \
1168    msg._member = _ecore_ipc_ddlt_int(d, cl->prev.i._member, md);
1169
1170 static int
1171 _ecore_ipc_event_client_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1172 {
1173    Ecore_Con_Event_Client_Data *e;
1174
1175    e = ev;
1176    if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1;
1177    /* handling code here */
1178      {
1179         Ecore_Ipc_Client *cl;
1180         Ecore_Ipc_Msg_Head msg;
1181         int offset = 0;
1182         unsigned char *buf;
1183
1184         cl = ecore_con_client_data_get(e->client);
1185
1186         if (!cl->buf)
1187           {
1188              cl->buf_size = e->size;
1189              cl->buf = e->data;
1190              e->data = NULL; /* take it out of the old event */
1191           }
1192         else
1193           {
1194              buf = realloc(cl->buf, cl->buf_size + e->size);
1195              if (!buf)
1196                {
1197                   free(cl->buf);
1198                   cl->buf = 0;
1199                   cl->buf_size  = 0;
1200                   return 0;
1201                }
1202              cl->buf = buf;
1203              memcpy(cl->buf + cl->buf_size, e->data, e->size);
1204              cl->buf_size += e->size;
1205           }
1206         /* examine header */
1207         redo:
1208         if ((cl->buf_size - offset) >= (int)sizeof(int))
1209           {
1210              int s, md, d = 0, head;
1211              unsigned char *dd;
1212
1213              dd = (unsigned char *)&head;
1214              dd[0] = *(cl->buf + offset + 0);
1215              dd[1] = *(cl->buf + offset + 1);
1216              dd[2] = *(cl->buf + offset + 2);
1217              dd[3] = *(cl->buf + offset + 3);
1218              head = ntohl(head);
1219              dd = (unsigned char *)&d;
1220              s = 4;
1221              CLSZ(0);
1222              CLSZ(1);
1223              CLSZ(2);
1224              CLSZ(3);
1225              CLSZ(4);
1226              CLSZ(5);
1227              if ((cl->buf_size - offset) < s)
1228                {
1229                   if (offset > 0) goto scroll;
1230                   return 0;
1231                }
1232
1233              s = 4;
1234              CLDEC(0, major);
1235              CLDEC(1, minor);
1236              CLDEC(2, ref);
1237              CLDEC(3, ref_to);
1238              CLDEC(4, response);
1239              CLDEC(5, size);
1240              if (msg.size < 0) msg.size = 0;
1241              /* there is enough data in the buffer for a full message */
1242              if ((cl->buf_size - offset) >= (s + msg.size))
1243                {
1244                   Ecore_Ipc_Event_Client_Data *e2;
1245                   Ecore_Ipc_Server *svr;
1246                   int max, max2;
1247
1248                   buf = NULL;
1249                   svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client));
1250                   max = svr->max_buf_size;
1251                   max2 = cl->max_buf_size;
1252                   if ((max >= 0) && (max2 >= 0))
1253                     {
1254                        if (max2 < max) max = max2;
1255                     }
1256                   else
1257                     {
1258                        if (max < 0) max = max2;
1259                     }
1260                   if ((max < 0) || (msg.size <= max))
1261                     {
1262                        if (msg.size > 0)
1263                          {
1264                             buf = malloc(msg.size);
1265                             if (!buf) return 0;
1266                             memcpy(buf, cl->buf + offset + s, msg.size);
1267                          }
1268                        if (!cl->delete_me)
1269                          {
1270                             e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Data));
1271                             if (e2)
1272                               {
1273                                  cl->event_count++;
1274                                  e2->client   = cl;
1275                                  e2->major    = msg.major;
1276                                  e2->minor    = msg.minor;
1277                                  e2->ref      = msg.ref;
1278                                  e2->ref_to   = msg.ref_to;
1279                                  e2->response = msg.response;
1280                                  e2->size     = msg.size;
1281                                  e2->data     = buf;
1282                                  ecore_event_add(ECORE_IPC_EVENT_CLIENT_DATA, e2,
1283                                                  _ecore_ipc_event_client_data_free,
1284                                                  NULL);
1285                               }
1286                          }
1287                     }
1288                   cl->prev.i = msg;
1289                   offset += (s + msg.size);
1290                   if (cl->buf_size == offset)
1291                     {
1292                        free(cl->buf);
1293                        cl->buf = NULL;
1294                        cl->buf_size = 0;
1295                        return 0;
1296                     }
1297                   goto redo;
1298                }
1299              else goto scroll;
1300           }
1301         else
1302           {
1303              scroll:
1304              buf = malloc(cl->buf_size - offset);
1305              if (!buf)
1306                {
1307                   free(cl->buf);
1308                   cl->buf = NULL;
1309                   cl->buf_size = 0;
1310                   return 0;
1311                }
1312              memcpy(buf, cl->buf + offset, cl->buf_size - offset);
1313              free(cl->buf);
1314              cl->buf = buf;
1315              cl->buf_size -= offset;
1316           }
1317      }
1318    return 0;
1319 }
1320
1321 #define SVSZ(_n) \
1322    md = ((head >> (4 * _n)) & 0xf); \
1323    if (md >= DLT_SET) s += 4; \
1324    else if (md >= DLT_ADD16) s += 2; \
1325    else if (md >= DLT_ADD8) s += 1;
1326
1327 #define SVDEC(_n, _member) \
1328    md = ((head >> (4 * _n)) & 0xf); \
1329    if (md >= DLT_SET) \
1330      { \
1331         unsigned int v; \
1332         unsigned char *dv; \
1333         dv = (unsigned char *)&v; \
1334         dv[0] = *(svr->buf + offset + s + 0); \
1335         dv[1] = *(svr->buf + offset + s + 1); \
1336         dv[2] = *(svr->buf + offset + s + 2); \
1337         dv[3] = *(svr->buf + offset + s + 3); \
1338         d = (int)ntohl(v); \
1339         s += 4; \
1340      } \
1341    else if (md >= DLT_ADD16) \
1342      { \
1343         unsigned short v; \
1344         unsigned char *dv; \
1345         dv = (unsigned char *)&v; \
1346         dv[0] = *(svr->buf + offset + s + 0); \
1347         dv[1] = *(svr->buf + offset + s + 1); \
1348         d = (int)ntohs(v); \
1349         s += 2; \
1350      } \
1351    else if (md >= DLT_ADD8) \
1352      { \
1353         unsigned char v; \
1354         unsigned char *dv; \
1355         dv = (unsigned char *)&v; \
1356         dv[0] = *(svr->buf + offset + s + 0); \
1357         d = (int)v; \
1358         s += 1; \
1359      } \
1360    msg._member = _ecore_ipc_ddlt_int(d, svr->prev.i._member, md);
1361
1362 static int
1363 _ecore_ipc_event_server_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1364 {
1365    Ecore_Con_Event_Server_Data *e;
1366
1367    e = ev;
1368    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return 1;
1369    /* handling code here */
1370      {
1371         Ecore_Ipc_Server *svr;
1372         Ecore_Ipc_Msg_Head msg;
1373         int offset = 0;
1374         unsigned char *buf;
1375
1376         svr = ecore_con_server_data_get(e->server);
1377
1378         if (!svr->buf)
1379           {
1380              svr->buf_size = e->size;
1381              svr->buf = e->data;
1382              e->data = NULL; /* take it out of the old event */
1383           }
1384         else
1385           {
1386              buf = realloc(svr->buf, svr->buf_size + e->size);
1387              if (!buf)
1388                {
1389                   free(svr->buf);
1390                   svr->buf = 0;
1391                   svr->buf_size  = 0;
1392                   return 0;
1393                }
1394              svr->buf = buf;
1395              memcpy(svr->buf + svr->buf_size, e->data, e->size);
1396              svr->buf_size += e->size;
1397           }
1398         /* examine header */
1399         redo:
1400         if ((svr->buf_size - offset) >= (int)sizeof(int))
1401           {
1402              int s, md, d = 0, head;
1403              unsigned char *dd;
1404
1405              dd = (unsigned char *)&head;
1406              dd[0] = *(svr->buf + offset + 0);
1407              dd[1] = *(svr->buf + offset + 1);
1408              dd[2] = *(svr->buf + offset + 2);
1409              dd[3] = *(svr->buf + offset + 3);
1410              head = ntohl(head);
1411              dd = (unsigned char *)&d;
1412              s = 4;
1413              SVSZ(0);
1414              SVSZ(1);
1415              SVSZ(2);
1416              SVSZ(3);
1417              SVSZ(4);
1418              SVSZ(5);
1419              if ((svr->buf_size - offset) < s)
1420                {
1421                   if (offset > 0) goto scroll;
1422                   return 0;
1423                }
1424
1425              s = 4;
1426              SVDEC(0, major);
1427              SVDEC(1, minor);
1428              SVDEC(2, ref);
1429              SVDEC(3, ref_to);
1430              SVDEC(4, response);
1431              SVDEC(5, size);
1432              if (msg.size < 0) msg.size = 0;
1433              /* there is enough data in the buffer for a full message */
1434              if ((svr->buf_size - offset) >= (s + msg.size))
1435                {
1436                   Ecore_Ipc_Event_Server_Data *e2;
1437                   int max;
1438
1439                   buf = NULL;
1440                   max = svr->max_buf_size;
1441                   if ((max < 0) || (msg.size <= max))
1442                     {
1443                        if (msg.size > 0)
1444                          {
1445                             buf = malloc(msg.size);
1446                             if (!buf) return 0;
1447                             memcpy(buf, svr->buf + offset + s, msg.size);
1448                          }
1449                        if (!svr->delete_me)
1450                          {
1451                             e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Data));
1452                             if (e2)
1453                               {
1454                                  svr->event_count++;
1455                                  e2->server   = svr;
1456                                  e2->major    = msg.major;
1457                                  e2->minor    = msg.minor;
1458                                  e2->ref      = msg.ref;
1459                                  e2->ref_to   = msg.ref_to;
1460                                  e2->response = msg.response;
1461                                  e2->size     = msg.size;
1462                                  e2->data     = buf;
1463                                  ecore_event_add(ECORE_IPC_EVENT_SERVER_DATA, e2,
1464                                                  _ecore_ipc_event_server_data_free,
1465                                                  NULL);
1466                               }
1467                          }
1468                     }
1469                   svr->prev.i = msg;
1470                   offset += (s + msg.size);
1471                   if (svr->buf_size == offset)
1472                     {
1473                        free(svr->buf);
1474                        svr->buf = NULL;
1475                        svr->buf_size = 0;
1476                        return 0;
1477                     }
1478                   goto redo;
1479                }
1480              else goto scroll;
1481           }
1482         else
1483           {
1484              scroll:
1485              buf = malloc(svr->buf_size - offset);
1486              if (!buf)
1487                {
1488                   free(svr->buf);
1489                   svr->buf = NULL;
1490                   svr->buf_size = 0;
1491                   return 0;
1492                }
1493              memcpy(buf, svr->buf + offset, svr->buf_size - offset);
1494              free(svr->buf);
1495              svr->buf = buf;
1496              svr->buf_size -= offset;
1497           }
1498      }
1499    return 0;
1500 }
1501
1502 static void
1503 _ecore_ipc_event_client_add_free(void *data __UNUSED__, void *ev)
1504 {
1505    Ecore_Ipc_Event_Client_Add *e;
1506
1507    e = ev;
1508    e->client->event_count--;
1509    if ((e->client->event_count == 0) && (e->client->delete_me))
1510      ecore_ipc_client_del(e->client);
1511    free(e);
1512 }
1513
1514 static void
1515 _ecore_ipc_event_client_del_free(void *data __UNUSED__, void *ev)
1516 {
1517    Ecore_Ipc_Event_Client_Del *e;
1518
1519    e = ev;
1520    e->client->event_count--;
1521    if ((e->client->event_count == 0) && (e->client->delete_me))
1522      ecore_ipc_client_del(e->client);
1523    free(e);
1524 }
1525
1526 static void
1527 _ecore_ipc_event_client_data_free(void *data __UNUSED__, void *ev)
1528 {
1529    Ecore_Ipc_Event_Client_Data *e;
1530
1531    e = ev;
1532    e->client->event_count--;
1533    if (e->data) free(e->data);
1534    if ((e->client->event_count == 0) && (e->client->delete_me))
1535      ecore_ipc_client_del(e->client);
1536    free(e);
1537 }
1538
1539 static void
1540 _ecore_ipc_event_server_add_free(void *data __UNUSED__, void *ev)
1541 {
1542    Ecore_Ipc_Event_Server_Add *e;
1543
1544    e = ev;
1545    e->server->event_count--;
1546    if ((e->server->event_count == 0) && (e->server->delete_me))
1547      ecore_ipc_server_del(e->server);
1548    free(e);
1549 }
1550
1551 static void
1552 _ecore_ipc_event_server_del_free(void *data __UNUSED__, void *ev)
1553 {
1554    Ecore_Ipc_Event_Server_Add *e;
1555
1556    e = ev;
1557    e->server->event_count--;
1558    if ((e->server->event_count == 0) && (e->server->delete_me))
1559      ecore_ipc_server_del(e->server);
1560    free(e);
1561 }
1562
1563 static void
1564 _ecore_ipc_event_server_data_free(void *data __UNUSED__, void *ev)
1565 {
1566    Ecore_Ipc_Event_Server_Data *e;
1567
1568    e = ev;
1569    if (e->data) free(e->data);
1570    e->server->event_count--;
1571    if ((e->server->event_count == 0) && (e->server->delete_me))
1572      ecore_ipc_server_del(e->server);
1573    free(e);
1574 }