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