3518be222427af2cf04cbb4516a38539808bbbea
[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_del(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         cl->max_buf_size = 32 * 1024;
1038         ecore_con_client_data_set(cl->client, (void *)cl);
1039         svr->clients = eina_list_append(svr->clients, cl);
1040         svr->client_list = eina_list_append(svr->client_list, cl);
1041         if (!cl->delete_me)
1042           {
1043              Ecore_Ipc_Event_Client_Add *e2;
1044
1045              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Add));
1046              if (e2)
1047                {
1048                   cl->event_count++;
1049                   e2->client = cl;
1050                   ecore_event_add(ECORE_IPC_EVENT_CLIENT_ADD, e2,
1051                                   _ecore_ipc_event_client_add_free, NULL);
1052                }
1053           }
1054      }
1055    return ECORE_CALLBACK_CANCEL;
1056 }
1057
1058 static Eina_Bool
1059 _ecore_ipc_event_client_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1060 {
1061    Ecore_Con_Event_Client_Del *e;
1062
1063    e = ev;
1064    if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return ECORE_CALLBACK_RENEW;
1065    /* handling code here */
1066      {
1067         Ecore_Ipc_Client *cl;
1068
1069         cl = ecore_con_client_data_get(e->client);
1070           {
1071              Ecore_Ipc_Event_Client_Del *e2;
1072              Ecore_Ipc_Server *svr;
1073
1074              svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client));
1075              svr->client_list = eina_list_remove(svr->client_list, cl);
1076              if (!cl->delete_me)
1077                {
1078                   e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Del));
1079                   if (e2)
1080                     {
1081                        cl->event_count++;
1082                        e2->client = cl;
1083                        ecore_event_add(ECORE_IPC_EVENT_CLIENT_DEL, e2,
1084                                        _ecore_ipc_event_client_del_free, NULL);
1085                     }
1086                }
1087           }
1088      }
1089    return ECORE_CALLBACK_CANCEL;
1090 }
1091
1092 static Eina_Bool
1093 _ecore_ipc_event_server_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1094 {
1095    Ecore_Con_Event_Server_Add *e;
1096
1097    e = ev;
1098    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return ECORE_CALLBACK_RENEW;
1099    /* handling code here */
1100      {
1101         Ecore_Ipc_Server *svr;
1102
1103         svr = ecore_con_server_data_get(e->server);
1104         if (!svr->delete_me)
1105           {
1106              Ecore_Ipc_Event_Server_Add *e2;
1107
1108              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Add));
1109              if (e2)
1110                {
1111                   svr->event_count++;
1112                   e2->server = svr;
1113                   ecore_event_add(ECORE_IPC_EVENT_SERVER_ADD, e2,
1114                                   _ecore_ipc_event_server_add_free, NULL);
1115                }
1116           }
1117      }
1118    return ECORE_CALLBACK_CANCEL;
1119 }
1120
1121 static Eina_Bool
1122 _ecore_ipc_event_server_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1123 {
1124    Ecore_Con_Event_Server_Del *e;
1125
1126    e = ev;
1127    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return ECORE_CALLBACK_RENEW;
1128    /* handling code here */
1129      {
1130         Ecore_Ipc_Server *svr;
1131
1132         svr = ecore_con_server_data_get(e->server);
1133         if (!svr->delete_me)
1134           {
1135              Ecore_Ipc_Event_Server_Del *e2;
1136
1137              e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Del));
1138              if (e2)
1139                {
1140                   svr->event_count++;
1141                   e2->server = svr;
1142                   ecore_event_add(ECORE_IPC_EVENT_SERVER_DEL, e2,
1143                                   _ecore_ipc_event_server_del_free, NULL);
1144                }
1145           }
1146      }
1147    return ECORE_CALLBACK_CANCEL;
1148 }
1149
1150 #define CLSZ(_n) \
1151    md = ((head >> (4 * _n)) & 0xf); \
1152    if (md >= DLT_SET) s += 4; \
1153    else if (md >= DLT_ADD16) s += 2; \
1154    else if (md >= DLT_ADD8) s += 1;
1155
1156 #define CLDEC(_n, _member) \
1157    md = ((head >> (4 * _n)) & 0xf); \
1158    if (md >= DLT_SET) \
1159      { \
1160         unsigned int v; \
1161         unsigned char *dv; \
1162         dv = (unsigned char *)&v; \
1163         dv[0] = *(cl->buf + offset + s + 0); \
1164         dv[1] = *(cl->buf + offset + s + 1); \
1165         dv[2] = *(cl->buf + offset + s + 2); \
1166         dv[3] = *(cl->buf + offset + s + 3); \
1167         d = (int)ntohl(v); \
1168         s += 4; \
1169      } \
1170    else if (md >= DLT_ADD16) \
1171      { \
1172         unsigned short v; \
1173         unsigned char *dv; \
1174         dv = (unsigned char *)&v; \
1175         dv[0] = *(cl->buf + offset + s + 0); \
1176         dv[1] = *(cl->buf + offset + s + 1); \
1177         d = (int)ntohs(v); \
1178         s += 2; \
1179      } \
1180    else if (md >= DLT_ADD8) \
1181      { \
1182         unsigned char v; \
1183         unsigned char *dv; \
1184         dv = (unsigned char *)&v; \
1185         dv[0] = *(cl->buf + offset + s + 0); \
1186         d = (int)v; \
1187         s += 1; \
1188      } \
1189    msg._member = _ecore_ipc_ddlt_int(d, cl->prev.i._member, md);
1190
1191 static Eina_Bool
1192 _ecore_ipc_event_client_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1193 {
1194    Ecore_Con_Event_Client_Data *e;
1195
1196    e = ev;
1197    if (!eina_list_data_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return ECORE_CALLBACK_RENEW;
1198    /* handling code here */
1199      {
1200         Ecore_Ipc_Client *cl;
1201         Ecore_Ipc_Msg_Head msg;
1202         int offset = 0;
1203         unsigned char *buf;
1204
1205         cl = ecore_con_client_data_get(e->client);
1206
1207         if (!cl->buf)
1208           {
1209              cl->buf_size = e->size;
1210              cl->buf = e->data;
1211              e->data = NULL; /* take it out of the old event */
1212           }
1213         else
1214           {
1215              buf = realloc(cl->buf, cl->buf_size + e->size);
1216              if (!buf)
1217                {
1218                   free(cl->buf);
1219                   cl->buf = 0;
1220                   cl->buf_size  = 0;
1221                   return ECORE_CALLBACK_CANCEL;
1222                }
1223              cl->buf = buf;
1224              memcpy(cl->buf + cl->buf_size, e->data, e->size);
1225              cl->buf_size += e->size;
1226           }
1227         /* examine header */
1228         redo:
1229         if ((cl->buf_size - offset) >= (int)sizeof(int))
1230           {
1231              int s, md, d = 0, head;
1232              unsigned char *dd;
1233
1234              dd = (unsigned char *)&head;
1235              dd[0] = *(cl->buf + offset + 0);
1236              dd[1] = *(cl->buf + offset + 1);
1237              dd[2] = *(cl->buf + offset + 2);
1238              dd[3] = *(cl->buf + offset + 3);
1239              head = ntohl(head);
1240              dd = (unsigned char *)&d;
1241              s = 4;
1242              CLSZ(0);
1243              CLSZ(1);
1244              CLSZ(2);
1245              CLSZ(3);
1246              CLSZ(4);
1247              CLSZ(5);
1248              if ((cl->buf_size - offset) < s)
1249                {
1250                   if (offset > 0) goto scroll;
1251                   return ECORE_CALLBACK_CANCEL;
1252                }
1253
1254              s = 4;
1255              CLDEC(0, major);
1256              CLDEC(1, minor);
1257              CLDEC(2, ref);
1258              CLDEC(3, ref_to);
1259              CLDEC(4, response);
1260              CLDEC(5, size);
1261              if (msg.size < 0) msg.size = 0;
1262              /* there is enough data in the buffer for a full message */
1263              if ((cl->buf_size - offset) >= (s + msg.size))
1264                {
1265                   Ecore_Ipc_Event_Client_Data *e2;
1266                   Ecore_Ipc_Server *svr;
1267                   int max, max2;
1268
1269                   buf = NULL;
1270                   svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client));
1271                   max = svr->max_buf_size;
1272                   max2 = cl->max_buf_size;
1273                   if ((max >= 0) && (max2 >= 0))
1274                     {
1275                        if (max2 < max) max = max2;
1276                     }
1277                   else
1278                     {
1279                        if (max < 0) max = max2;
1280                     }
1281                   if ((max < 0) || (msg.size <= max))
1282                     {
1283                        if (msg.size > 0)
1284                          {
1285                             buf = malloc(msg.size);
1286                             if (!buf) return ECORE_CALLBACK_CANCEL;
1287                             memcpy(buf, cl->buf + offset + s, msg.size);
1288                          }
1289                        if (!cl->delete_me)
1290                          {
1291                             e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Data));
1292                             if (e2)
1293                               {
1294                                  cl->event_count++;
1295                                  e2->client   = cl;
1296                                  e2->major    = msg.major;
1297                                  e2->minor    = msg.minor;
1298                                  e2->ref      = msg.ref;
1299                                  e2->ref_to   = msg.ref_to;
1300                                  e2->response = msg.response;
1301                                  e2->size     = msg.size;
1302                                  e2->data     = buf;
1303                                  ecore_event_add(ECORE_IPC_EVENT_CLIENT_DATA, e2,
1304                                                  _ecore_ipc_event_client_data_free,
1305                                                  NULL);
1306                               }
1307                          }
1308                     }
1309                   cl->prev.i = msg;
1310                   offset += (s + msg.size);
1311                   if (cl->buf_size == offset)
1312                     {
1313                        free(cl->buf);
1314                        cl->buf = NULL;
1315                        cl->buf_size = 0;
1316                        return ECORE_CALLBACK_CANCEL;
1317                     }
1318                   goto redo;
1319                }
1320              else goto scroll;
1321           }
1322         else
1323           {
1324              scroll:
1325              buf = malloc(cl->buf_size - offset);
1326              if (!buf)
1327                {
1328                   free(cl->buf);
1329                   cl->buf = NULL;
1330                   cl->buf_size = 0;
1331                   return ECORE_CALLBACK_CANCEL;
1332                }
1333              memcpy(buf, cl->buf + offset, cl->buf_size - offset);
1334              free(cl->buf);
1335              cl->buf = buf;
1336              cl->buf_size -= offset;
1337           }
1338      }
1339    return ECORE_CALLBACK_CANCEL;
1340 }
1341
1342 #define SVSZ(_n) \
1343    md = ((head >> (4 * _n)) & 0xf); \
1344    if (md >= DLT_SET) s += 4; \
1345    else if (md >= DLT_ADD16) s += 2; \
1346    else if (md >= DLT_ADD8) s += 1;
1347
1348 #define SVDEC(_n, _member) \
1349    md = ((head >> (4 * _n)) & 0xf); \
1350    if (md >= DLT_SET) \
1351      { \
1352         unsigned int v; \
1353         unsigned char *dv; \
1354         dv = (unsigned char *)&v; \
1355         dv[0] = *(svr->buf + offset + s + 0); \
1356         dv[1] = *(svr->buf + offset + s + 1); \
1357         dv[2] = *(svr->buf + offset + s + 2); \
1358         dv[3] = *(svr->buf + offset + s + 3); \
1359         d = (int)ntohl(v); \
1360         s += 4; \
1361      } \
1362    else if (md >= DLT_ADD16) \
1363      { \
1364         unsigned short v; \
1365         unsigned char *dv; \
1366         dv = (unsigned char *)&v; \
1367         dv[0] = *(svr->buf + offset + s + 0); \
1368         dv[1] = *(svr->buf + offset + s + 1); \
1369         d = (int)ntohs(v); \
1370         s += 2; \
1371      } \
1372    else if (md >= DLT_ADD8) \
1373      { \
1374         unsigned char v; \
1375         unsigned char *dv; \
1376         dv = (unsigned char *)&v; \
1377         dv[0] = *(svr->buf + offset + s + 0); \
1378         d = (int)v; \
1379         s += 1; \
1380      } \
1381    msg._member = _ecore_ipc_ddlt_int(d, svr->prev.i._member, md);
1382
1383 static Eina_Bool
1384 _ecore_ipc_event_server_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1385 {
1386    Ecore_Con_Event_Server_Data *e;
1387
1388    e = ev;
1389    if (!eina_list_data_find(servers, ecore_con_server_data_get(e->server))) return ECORE_CALLBACK_RENEW;
1390    /* handling code here */
1391      {
1392         Ecore_Ipc_Server *svr;
1393         Ecore_Ipc_Msg_Head msg;
1394         int offset = 0;
1395         unsigned char *buf;
1396
1397         svr = ecore_con_server_data_get(e->server);
1398
1399         if (!svr->buf)
1400           {
1401              svr->buf_size = e->size;
1402              svr->buf = e->data;
1403              e->data = NULL; /* take it out of the old event */
1404           }
1405         else
1406           {
1407              buf = realloc(svr->buf, svr->buf_size + e->size);
1408              if (!buf)
1409                {
1410                   free(svr->buf);
1411                   svr->buf = 0;
1412                   svr->buf_size  = 0;
1413                   return ECORE_CALLBACK_CANCEL;
1414                }
1415              svr->buf = buf;
1416              memcpy(svr->buf + svr->buf_size, e->data, e->size);
1417              svr->buf_size += e->size;
1418           }
1419         /* examine header */
1420         redo:
1421         if ((svr->buf_size - offset) >= (int)sizeof(int))
1422           {
1423              int s, md, d = 0, head;
1424              unsigned char *dd;
1425
1426              dd = (unsigned char *)&head;
1427              dd[0] = *(svr->buf + offset + 0);
1428              dd[1] = *(svr->buf + offset + 1);
1429              dd[2] = *(svr->buf + offset + 2);
1430              dd[3] = *(svr->buf + offset + 3);
1431              head = ntohl(head);
1432              dd = (unsigned char *)&d;
1433              s = 4;
1434              SVSZ(0);
1435              SVSZ(1);
1436              SVSZ(2);
1437              SVSZ(3);
1438              SVSZ(4);
1439              SVSZ(5);
1440              if ((svr->buf_size - offset) < s)
1441                {
1442                   if (offset > 0) goto scroll;
1443                   return ECORE_CALLBACK_CANCEL;
1444                }
1445
1446              s = 4;
1447              SVDEC(0, major);
1448              SVDEC(1, minor);
1449              SVDEC(2, ref);
1450              SVDEC(3, ref_to);
1451              SVDEC(4, response);
1452              SVDEC(5, size);
1453              if (msg.size < 0) msg.size = 0;
1454              /* there is enough data in the buffer for a full message */
1455              if ((svr->buf_size - offset) >= (s + msg.size))
1456                {
1457                   Ecore_Ipc_Event_Server_Data *e2;
1458                   int max;
1459
1460                   buf = NULL;
1461                   max = svr->max_buf_size;
1462                   if ((max < 0) || (msg.size <= max))
1463                     {
1464                        if (msg.size > 0)
1465                          {
1466                             buf = malloc(msg.size);
1467                             if (!buf) return ECORE_CALLBACK_CANCEL;
1468                             memcpy(buf, svr->buf + offset + s, msg.size);
1469                          }
1470                        if (!svr->delete_me)
1471                          {
1472                             e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Data));
1473                             if (e2)
1474                               {
1475                                  svr->event_count++;
1476                                  e2->server   = svr;
1477                                  e2->major    = msg.major;
1478                                  e2->minor    = msg.minor;
1479                                  e2->ref      = msg.ref;
1480                                  e2->ref_to   = msg.ref_to;
1481                                  e2->response = msg.response;
1482                                  e2->size     = msg.size;
1483                                  e2->data     = buf;
1484                                  ecore_event_add(ECORE_IPC_EVENT_SERVER_DATA, e2,
1485                                                  _ecore_ipc_event_server_data_free,
1486                                                  NULL);
1487                               }
1488                          }
1489                     }
1490                   svr->prev.i = msg;
1491                   offset += (s + msg.size);
1492                   if (svr->buf_size == offset)
1493                     {
1494                        free(svr->buf);
1495                        svr->buf = NULL;
1496                        svr->buf_size = 0;
1497                        return ECORE_CALLBACK_CANCEL;
1498                     }
1499                   goto redo;
1500                }
1501              else goto scroll;
1502           }
1503         else
1504           {
1505              scroll:
1506              buf = malloc(svr->buf_size - offset);
1507              if (!buf)
1508                {
1509                   free(svr->buf);
1510                   svr->buf = NULL;
1511                   svr->buf_size = 0;
1512                   return ECORE_CALLBACK_CANCEL;
1513                }
1514              memcpy(buf, svr->buf + offset, svr->buf_size - offset);
1515              free(svr->buf);
1516              svr->buf = buf;
1517              svr->buf_size -= offset;
1518           }
1519      }
1520    return ECORE_CALLBACK_CANCEL;
1521 }
1522
1523 static void
1524 _ecore_ipc_event_client_add_free(void *data __UNUSED__, void *ev)
1525 {
1526    Ecore_Ipc_Event_Client_Add *e;
1527
1528    e = ev;
1529    e->client->event_count--;
1530    if ((e->client->event_count == 0) && (e->client->delete_me))
1531      ecore_ipc_client_del(e->client);
1532    free(e);
1533 }
1534
1535 static void
1536 _ecore_ipc_event_client_del_free(void *data __UNUSED__, void *ev)
1537 {
1538    Ecore_Ipc_Event_Client_Del *e;
1539
1540    e = ev;
1541    e->client->event_count--;
1542    if ((e->client->event_count == 0) && (e->client->delete_me))
1543      ecore_ipc_client_del(e->client);
1544    free(e);
1545 }
1546
1547 static void
1548 _ecore_ipc_event_client_data_free(void *data __UNUSED__, void *ev)
1549 {
1550    Ecore_Ipc_Event_Client_Data *e;
1551
1552    e = ev;
1553    e->client->event_count--;
1554    if (e->data) free(e->data);
1555    if ((e->client->event_count == 0) && (e->client->delete_me))
1556      ecore_ipc_client_del(e->client);
1557    free(e);
1558 }
1559
1560 static void
1561 _ecore_ipc_event_server_add_free(void *data __UNUSED__, void *ev)
1562 {
1563    Ecore_Ipc_Event_Server_Add *e;
1564
1565    e = ev;
1566    e->server->event_count--;
1567    if ((e->server->event_count == 0) && (e->server->delete_me))
1568      ecore_ipc_server_del(e->server);
1569    free(e);
1570 }
1571
1572 static void
1573 _ecore_ipc_event_server_del_free(void *data __UNUSED__, void *ev)
1574 {
1575    Ecore_Ipc_Event_Server_Add *e;
1576
1577    e = ev;
1578    e->server->event_count--;
1579    if ((e->server->event_count == 0) && (e->server->delete_me))
1580      ecore_ipc_server_del(e->server);
1581    free(e);
1582 }
1583
1584 static void
1585 _ecore_ipc_event_server_data_free(void *data __UNUSED__, void *ev)
1586 {
1587    Ecore_Ipc_Event_Server_Data *e;
1588
1589    e = ev;
1590    if (e->data) free(e->data);
1591    e->server->event_count--;
1592    if ((e->server->event_count == 0) && (e->server->delete_me))
1593      ecore_ipc_server_del(e->server);
1594    free(e);
1595 }