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