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