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