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