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