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