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