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