Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_con / ecore_con_eet.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <Eina.h>
6
7 #include "Ecore_Con_Eet.h"
8
9 #define ECORE_CON_EET_RAW_MAGIC 0xDEAD007
10
11 typedef struct _Ecore_Con_Eet_Data Ecore_Con_Eet_Data;
12 typedef struct _Ecore_Con_Eet_Raw_Data Ecore_Con_Eet_Raw_Data;
13 typedef struct _Ecore_Con_Eet_Client Ecore_Con_Eet_Client;
14 typedef struct _Ecore_Con_Eet_Server Ecore_Con_Eet_Server;
15
16 struct _Ecore_Con_Reply
17 {
18    Ecore_Con_Eet *ece;
19    Ecore_Con_Client *client;
20
21    Eet_Connection *econn;
22
23    char *buffer_section;
24    unsigned char *buffer;
25    unsigned int buffer_length;
26    unsigned int buffer_current;
27    Ecore_Con_Eet_Raw_Data *buffer_handler;
28 };
29
30 struct _Ecore_Con_Eet_Data
31 {
32    Ecore_Con_Eet_Data_Cb func;
33    const char *name;
34    const void *data;
35 };
36
37 struct _Ecore_Con_Eet_Raw_Data
38 {
39    Ecore_Con_Eet_Raw_Data_Cb func;
40    const char *name;
41    const void *data;
42 };
43
44 struct _Ecore_Con_Eet_Client
45 {
46    Ecore_Con_Eet_Client_Cb func;
47    const void *data;
48 };
49
50 struct _Ecore_Con_Eet_Server
51 {
52    Ecore_Con_Eet_Server_Cb func;
53    const void *data;
54 };
55
56 struct _Ecore_Con_Eet
57 {
58    Ecore_Con_Server *server;
59
60    Ecore_Event_Handler *handler_add;
61    Ecore_Event_Handler *handler_del;
62    Ecore_Event_Handler *handler_data;
63
64    Eet_Data_Descriptor *edd;
65    Eet_Data_Descriptor *matching;
66
67    Eina_Hash *data_callbacks;
68    Eina_Hash *raw_data_callbacks;
69
70    union {
71       struct {
72          Eina_List *connections;
73          Eina_List *client_connect_callbacks;
74          Eina_List *client_disconnect_callbacks;
75       } server;
76       struct {
77          Ecore_Con_Reply *r;
78          Eina_List *server_connect_callbacks;
79          Eina_List *server_disconnect_callbacks;
80       } client;
81    } u;
82
83    const void *data;
84
85    Eina_Bool client : 1;
86 };
87
88 static void
89 _ecore_con_eet_data_free(void *data)
90 {
91    Ecore_Con_Eet_Data *eced = data;
92
93    eina_stringshare_del(eced->name);
94    free(eced);
95 }
96
97 static void
98 _ecore_con_eet_raw_data_free(void *data)
99 {
100    Ecore_Con_Eet_Raw_Data *eced = data;
101
102    eina_stringshare_del(eced->name);
103    free(eced);
104 }
105 static void
106 _ecore_con_eet_reply_cleanup(Ecore_Con_Reply *n)
107 {
108    if (n->buffer_handler) free(n->buffer);
109    n->buffer = NULL;
110    n->buffer_handler = NULL;
111    free(n->buffer_section);
112    n->buffer_section = NULL;
113 }
114
115 typedef struct _Ecore_Con_Eet_Protocol Ecore_Con_Eet_Protocol;
116 struct _Ecore_Con_Eet_Protocol {
117    const char *type;
118    void *data;
119 };
120
121 static const char *
122 _ecore_con_eet_data_type_get(const void *data, Eina_Bool *unknow EINA_UNUSED)
123 {
124    const Ecore_Con_Eet_Protocol *p = data;
125
126    return p->type;
127 }
128
129 static Eina_Bool
130 _ecore_con_eet_data_type_set(const char *type, void *data, Eina_Bool unknow EINA_UNUSED)
131 {
132    Ecore_Con_Eet_Protocol *p = data;
133
134    p->type = type;
135    return EINA_TRUE;
136 }
137
138 static void
139 _ecore_con_eet_data_descriptor_setup(Ecore_Con_Eet *ece)
140 {
141    Eet_Data_Descriptor_Class eddc;
142
143    EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Ecore_Con_Eet_Protocol);
144    ece->edd = eet_data_descriptor_stream_new(&eddc);
145
146    eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
147    eddc.func.type_get = _ecore_con_eet_data_type_get;
148    eddc.func.type_set = _ecore_con_eet_data_type_set;
149    ece->matching = eet_data_descriptor_stream_new(&eddc);
150
151    EET_DATA_DESCRIPTOR_ADD_VARIANT(ece->edd, Ecore_Con_Eet_Protocol, "data", data, type, ece->matching);
152 }
153
154 /* Dealing with a server listening to connection */
155 static Eina_Bool
156 _ecore_con_eet_read_cb(const void *eet_data, size_t size, void *user_data)
157 {
158    Ecore_Con_Reply *n = user_data;
159    Ecore_Con_Eet_Protocol *protocol;
160    Ecore_Con_Eet_Data *cb;
161
162    protocol = eet_data_descriptor_decode(n->ece->edd, eet_data, size);
163    if (!protocol) return EINA_TRUE;
164
165    cb = eina_hash_find(n->ece->data_callbacks, protocol->type);
166    if (!cb) return EINA_TRUE; /* Should I report unknow protocol communication ? */
167
168    cb->func((void*)cb->data, n, cb->name, protocol->data);
169
170    eina_stringshare_del(protocol->type);
171    free(protocol);
172
173    return EINA_TRUE;
174 }
175
176 static Eina_Bool
177 _ecore_con_eet_server_write_cb(const void *data, size_t size, void *user_data)
178 {
179    Ecore_Con_Reply *n = user_data;
180
181    if (ecore_con_client_send(n->client, data, size) != (int) size)
182      return EINA_FALSE;
183    return EINA_TRUE;
184 }
185
186 static Eina_Bool
187 _ecore_con_eet_client_write_cb(const void *data, size_t size, void *user_data)
188 {
189    Ecore_Con_Reply *n = user_data;
190
191    if (ecore_con_server_send(n->ece->server, data, size) != (int) size)
192      return EINA_FALSE;
193    return EINA_TRUE;
194 }
195
196 static Eina_Bool
197 _ecore_con_eet_server_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Add *ev)
198 {
199    Ecore_Con_Eet_Client *ecec;
200    Eina_List *ll;
201    Ecore_Con_Eet *r = data;
202    Ecore_Con_Reply *n;
203
204    if (ecore_con_client_server_get(ev->client) != r->server)
205      return EINA_TRUE;
206
207    n = calloc(1, sizeof (Ecore_Con_Reply));
208    if (!n) return EINA_TRUE;
209
210    n->client = ev->client;
211    n->ece = r;
212    n->econn = eet_connection_new(_ecore_con_eet_read_cb, _ecore_con_eet_server_write_cb, n);
213    ecore_con_client_data_set(n->client, n);
214
215    EINA_LIST_FOREACH(r->u.server.client_connect_callbacks, ll, ecec)
216      if (!ecec->func((void*) ecec->data, n, n->client))
217        {
218           eet_connection_close(n->econn, NULL);
219           free(n);
220           return EINA_TRUE;
221        }
222
223    r->u.server.connections = eina_list_append(r->u.server.connections, n);
224
225    return EINA_TRUE;
226 }
227
228 static Eina_Bool
229 _ecore_con_eet_server_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Del *ev)
230 {
231    Ecore_Con_Eet *r = data;
232    Ecore_Con_Reply *n;
233    Eina_List *l;
234
235    if (ecore_con_client_server_get(ev->client) != r->server)
236      return EINA_TRUE;
237
238    EINA_LIST_FOREACH(r->u.server.connections, l, n)
239      if (n->client == ev->client)
240        {
241           Ecore_Con_Eet_Client *ecec;
242           Eina_List *ll;
243
244           EINA_LIST_FOREACH(r->u.server.client_disconnect_callbacks, ll, ecec)
245             ecec->func((void*) ecec->data, n, n->client);
246
247           eet_connection_close(n->econn, NULL);
248           free(n);
249           r->u.server.connections = eina_list_remove_list(r->u.server.connections, l);
250           return EINA_TRUE;
251        }
252
253    return EINA_TRUE;
254 }
255
256 static void
257 _ecore_con_eet_raw_data_push(Ecore_Con_Reply *n, void *data, int size)
258 {
259    if (n->buffer_handler)
260      memcpy(n->buffer + n->buffer_current, data, size);
261    n->buffer_current += size;
262
263    if (n->buffer_current == n->buffer_length)
264      {
265         if (n->buffer_handler)
266           n->buffer_handler->func((void*) n->buffer_handler->data, n, n->buffer_handler->name, n->buffer_section, n->buffer, n->buffer_length);
267         _ecore_con_eet_reply_cleanup(n);
268      }
269 }
270
271 static void
272 _ecore_con_eet_data(Ecore_Con_Reply *n, void *data, unsigned int size)
273 {
274    /* FIXME: Enforce detection of attack and kill connection on that case */
275    if (n->buffer)
276      {
277         if (n->buffer_current + size > n->buffer_length)
278           {
279              _ecore_con_eet_reply_cleanup(n);
280              return ;
281           }
282
283         _ecore_con_eet_raw_data_push(n, data, size);
284         return ;
285      }
286    else if (eet_connection_empty(n->econn) && size > (int) (4 * sizeof (unsigned int) + 2))
287      {
288         unsigned int *tmp = data;
289         size -= 4 * sizeof (unsigned int) + 2;
290
291         if (ntohl(tmp[0]) == ECORE_CON_EET_RAW_MAGIC)
292           {
293              unsigned int protocol_length = ntohl(tmp[1]);
294              unsigned int section_length = ntohl(tmp[2]);
295              unsigned int data_length = ntohl(tmp[3]);
296
297              if (protocol_length > 1 && section_length > 1 && protocol_length + section_length <= size && data_length < 10 * 1024 * 1024)
298                {
299                   char *buffer = (char*) &tmp[4];
300                   char *protocol;
301                   char *section;
302
303                   protocol = buffer;
304                   section = buffer + protocol_length;
305
306                   if (protocol[protocol_length - 1] == '\0' &&
307                       section[section_length - 1] == '\0')
308                     {
309                        size -= protocol_length + section_length;
310                        buffer = section + section_length;
311
312                        n->buffer_handler = eina_hash_find(n->ece->raw_data_callbacks, protocol);
313                        n->buffer_section = strdup(section);
314                        n->buffer_length = data_length;
315                        n->buffer_current = 0;
316                        if (n->buffer_handler)
317                          n->buffer = malloc(sizeof (data_length));
318                        else
319                          n->buffer = (void*) 1;
320                        if (n->buffer)
321                          {
322                             _ecore_con_eet_raw_data_push(n, buffer, size);
323                             return ;
324                          }
325                        _ecore_con_eet_reply_cleanup(n);
326
327                        size += protocol_length + section_length;
328                     }
329                }
330           }
331
332         size += 4 * sizeof (unsigned int) + 2;
333      }
334
335    eet_connection_received(n->econn, data, size);
336 }
337
338 static Eina_Bool
339 _ecore_con_eet_server_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Data *ev)
340 {
341    Ecore_Con_Eet *r = data;
342    Ecore_Con_Reply *n;
343
344    if (ecore_con_client_server_get(ev->client) != r->server)
345      return EINA_TRUE;
346
347    n = ecore_con_client_data_get(ev->client);
348
349    _ecore_con_eet_data(n, ev->data, ev->size);
350
351    return EINA_TRUE;
352 }
353
354 /* Dealing connection to a server */
355
356 static Eina_Bool
357 _ecore_con_eet_client_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev)
358 {
359    Ecore_Con_Eet_Server *eces;
360    Ecore_Con_Eet *r = data;
361    Ecore_Con_Reply *n;
362    Eina_List *ll;
363
364    /* Client did connect */
365    if (r->server != ev->server) return EINA_TRUE;
366    if (r->u.client.r) return EINA_TRUE;
367
368    n = calloc(1, sizeof (Ecore_Con_Reply));
369    if (!n) return EINA_TRUE;
370
371    n->client = NULL;
372    n->ece = r;
373    n->econn = eet_connection_new(_ecore_con_eet_read_cb, _ecore_con_eet_client_write_cb, n);
374
375    EINA_LIST_FOREACH(r->u.client.server_connect_callbacks, ll, eces)
376      if (!eces->func((void*) eces->data, n, n->ece->server))
377        {
378           eet_connection_close(n->econn, NULL);
379           free(n);
380           return EINA_TRUE;
381        }
382
383    r->u.client.r = n;
384
385    return EINA_TRUE;
386 }
387
388 static Eina_Bool
389 _ecore_con_eet_client_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev)
390 {
391    Ecore_Con_Eet *r = data;
392    Ecore_Con_Eet_Server *eces;
393    Eina_List *ll;
394
395    if (r->server != ev->server) return EINA_TRUE;
396    if (!r->u.client.r) return EINA_TRUE;
397
398    /* Client disconnected */
399    EINA_LIST_FOREACH(r->u.client.server_disconnect_callbacks, ll, eces)
400      eces->func((void*) eces->data, r->u.client.r, r->server);
401
402    eet_connection_close(r->u.client.r->econn, NULL);
403    free(r->u.client.r);
404    r->u.client.r = NULL;
405
406    return EINA_TRUE;
407 }
408
409 static Eina_Bool
410 _ecore_con_eet_client_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev)
411 {
412    Ecore_Con_Eet *r = data;
413
414    if (r->server != ev->server) return EINA_TRUE;
415    if (!r->u.client.r) return EINA_TRUE;
416
417    /* Got some data */
418    _ecore_con_eet_data(r->u.client.r, ev->data, ev->size);
419
420    return EINA_TRUE;
421 }
422
423 /**************
424  * Global API *
425  **************/
426
427 EAPI Ecore_Con_Eet *
428 ecore_con_eet_server_new(Ecore_Con_Server *server)
429 {
430    Ecore_Con_Eet *r;
431
432    if (!server) return NULL;
433
434    r = calloc(1, sizeof (Ecore_Con_Eet));
435    if (!r) return NULL;
436
437    r->server = server;
438    r->handler_add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD,
439                                             (Ecore_Event_Handler_Cb)_ecore_con_eet_server_connected, r);
440    r->handler_del = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL,
441                                             (Ecore_Event_Handler_Cb)_ecore_con_eet_server_disconnected, r);
442    r->handler_data = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA,
443                                              (Ecore_Event_Handler_Cb)_ecore_con_eet_server_data, r);
444    r->data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_data_free);
445    r->raw_data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_raw_data_free);
446
447    _ecore_con_eet_data_descriptor_setup(r);
448
449    return r;
450 }
451
452 EAPI Ecore_Con_Eet *
453 ecore_con_eet_client_new(Ecore_Con_Server *server)
454 {
455    Ecore_Con_Eet *r;
456
457    if (!server) return NULL;
458
459    r = calloc(1, sizeof (Ecore_Con_Eet));
460    if (!r) return NULL;
461
462    r->client = EINA_TRUE;
463    r->server = server;
464    r->handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD,
465                                             (Ecore_Event_Handler_Cb)_ecore_con_eet_client_connected, r);
466    r->handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
467                                             (Ecore_Event_Handler_Cb)_ecore_con_eet_client_disconnected, r);
468    r->handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
469                                              (Ecore_Event_Handler_Cb)_ecore_con_eet_client_data, r);
470    r->data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_data_free);
471    r->raw_data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_raw_data_free);
472
473    _ecore_con_eet_data_descriptor_setup(r);
474
475    return r;
476 }
477
478 EAPI void
479 ecore_con_eet_server_free(Ecore_Con_Eet *r)
480 {
481    if (!r) return ;
482
483    eet_data_descriptor_free(r->edd);
484    eet_data_descriptor_free(r->matching);
485    eina_hash_free(r->data_callbacks);
486    eina_hash_free(r->raw_data_callbacks);
487
488    if (r->client)
489      {
490         Ecore_Con_Eet_Server *s;
491
492         if (r->u.client.r)
493           {
494              _ecore_con_eet_reply_cleanup(r->u.client.r);
495              eet_connection_close(r->u.client.r->econn, NULL);
496              free(r->u.client.r);
497           }
498         EINA_LIST_FREE(r->u.client.server_connect_callbacks, s)
499           free(s);
500         EINA_LIST_FREE(r->u.client.server_disconnect_callbacks, s)
501           free(s);
502      }
503    else
504      {
505         Ecore_Con_Reply *n;
506         Ecore_Con_Eet_Client *c;
507
508         EINA_LIST_FREE(r->u.server.connections, n)
509           {
510              _ecore_con_eet_reply_cleanup(n);
511              eet_connection_close(n->econn, NULL);
512              free(n);
513           }
514         EINA_LIST_FREE(r->u.server.client_connect_callbacks, c)
515           free(c);
516         EINA_LIST_FREE(r->u.server.client_disconnect_callbacks, c)
517           free(c);
518      }
519
520    ecore_event_handler_del(r->handler_add);
521    ecore_event_handler_del(r->handler_del);
522    ecore_event_handler_del(r->handler_data);
523    free(r);
524 }
525
526 EAPI void
527 ecore_con_eet_register(Ecore_Con_Eet *ece, const char *name, Eet_Data_Descriptor *edd)
528 {
529    if (!ece) return ;
530
531    EET_DATA_DESCRIPTOR_ADD_MAPPING(ece->matching, name, edd);
532 }
533
534 EAPI void
535 ecore_con_eet_data_callback_add(Ecore_Con_Eet *ece, const char *name, Ecore_Con_Eet_Data_Cb func, const void *data)
536 {
537    Ecore_Con_Eet_Data *eced;
538
539    if (!ece) return ;
540
541    eced = calloc(1, sizeof (Ecore_Con_Eet_Data));;
542    if (!eced) return ;
543
544    eced->func = func;
545    eced->data = data;
546    eced->name = eina_stringshare_add(name);
547
548    eina_hash_direct_add(ece->data_callbacks, eced->name, eced);
549 }
550
551 EAPI void
552 ecore_con_eet_data_callback_del(Ecore_Con_Eet *ece, const char *name)
553 {
554    if (!ece) return ;
555    eina_hash_del(ece->data_callbacks, name, NULL);
556 }
557
558 EAPI void
559 ecore_con_eet_raw_data_callback_add(Ecore_Con_Eet *ece, const char *name, Ecore_Con_Eet_Raw_Data_Cb func, const void *data)
560 {
561    Ecore_Con_Eet_Raw_Data *eced;
562
563    if (!ece) return ;
564
565    eced = calloc(1, sizeof (Ecore_Con_Eet_Raw_Data));;
566    if (!eced) return ;
567
568    eced->func = func;
569    eced->data = data;
570    eced->name = eina_stringshare_add(name);
571
572    eina_hash_direct_add(ece->raw_data_callbacks, eced->name, eced);   
573 }
574
575 EAPI void
576 ecore_con_eet_raw_data_callback_del(Ecore_Con_Eet *ece, const char *name)
577 {
578    if (!ece) return ;
579
580    if (ece->client && ece->u.client.r->buffer_handler && !strcmp(ece->u.client.r->buffer_handler->name, name))
581      {
582         ece->u.client.r->buffer_handler = NULL;
583         free(ece->u.client.r->buffer);
584         ece->u.client.r->buffer = (void*) 1;
585      }
586    eina_hash_del(ece->raw_data_callbacks, name, NULL);
587 }
588
589 EAPI void
590 ecore_con_eet_client_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
591 {
592    Ecore_Con_Eet_Client *c;
593
594    if (!ece || !func) return ;
595
596    c = calloc(1, sizeof (Ecore_Con_Eet_Client));
597    if (!c) return ;
598
599    c->func = func;
600    c->data = data;
601
602    ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_connect_callbacks, c);
603 }
604
605 EAPI void
606 ecore_con_eet_client_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
607 {
608    Ecore_Con_Eet_Client *c;
609    Eina_List *l;
610
611    if (!ece || !func) return ;
612
613    EINA_LIST_FOREACH(ece->u.server.client_connect_callbacks, l, c)
614      if (c->func == func && c->data == data)
615        {
616           ece->u.server.client_connect_callbacks = eina_list_remove_list(ece->u.server.client_connect_callbacks, l);
617           free(c);
618           return ;
619        }
620 }
621
622 EAPI void
623 ecore_con_eet_client_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
624 {
625    Ecore_Con_Eet_Client *c;
626
627    if (!ece || !func) return ;
628
629    c = calloc(1, sizeof (Ecore_Con_Eet_Client));
630    if (!c) return ;
631
632    c->func = func;
633    c->data = data;
634
635    ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_disconnect_callbacks, c);
636 }
637
638 EAPI void
639 ecore_con_eet_client_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
640 {
641    Ecore_Con_Eet_Client *c;
642    Eina_List *l;
643
644    if (!ece || !func) return ;
645
646    EINA_LIST_FOREACH(ece->u.server.client_disconnect_callbacks, l, c)
647      if (c->func == func && c->data == data)
648        {
649           ece->u.server.client_disconnect_callbacks = eina_list_remove_list(ece->u.server.client_disconnect_callbacks,
650                                                                             l);
651           free(c);
652           return ;
653        }
654 }
655
656 EAPI void
657 ecore_con_eet_server_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
658 {
659    Ecore_Con_Eet_Server *s;
660
661    if (!ece || !func) return ;
662
663    s = calloc(1, sizeof (Ecore_Con_Eet_Server));
664    if (!s) return ;
665
666    s->func = func;
667    s->data = data;
668
669    ece->u.client.server_connect_callbacks = eina_list_append(ece->u.client.server_connect_callbacks, s);
670 }
671
672 EAPI void
673 ecore_con_eet_server_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
674 {
675    Ecore_Con_Eet_Server *s;
676    Eina_List *l;
677
678    if (!ece || !func) return ;
679
680    EINA_LIST_FOREACH(ece->u.client.server_connect_callbacks, l, s)
681      if (s->func == func && s->data == data)
682        {
683           ece->u.client.server_connect_callbacks = eina_list_remove_list(ece->u.client.server_connect_callbacks, l);
684           free(s);
685           return ;
686        }
687 }
688
689 EAPI void
690 ecore_con_eet_server_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
691 {
692    Ecore_Con_Eet_Server *s;
693
694    if (!ece || !func) return ;
695
696    s = calloc(1, sizeof (Ecore_Con_Eet_Server));
697    if (!s) return ;
698
699    s->func = func;
700    s->data = data;
701
702    ece->u.client.server_disconnect_callbacks = eina_list_append(ece->u.client.server_disconnect_callbacks, s);
703 }
704
705 EAPI void
706 ecore_con_eet_server_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
707 {
708    Ecore_Con_Eet_Server *s;
709    Eina_List *l;
710
711    if (!ece || !func) return ;
712
713    EINA_LIST_FOREACH(ece->u.client.server_disconnect_callbacks, l, s)
714      if (s->func == func && s->data == data)
715        {
716           ece->u.client.server_disconnect_callbacks = eina_list_remove_list(ece->u.client.server_disconnect_callbacks, l);
717           free(s);
718           return ;
719        }
720 }
721
722 EAPI void
723 ecore_con_eet_data_set(Ecore_Con_Eet *ece, const void *data)
724 {
725    if (!ece) return;
726
727    ece->data = data;
728 }
729
730 EAPI void *
731 ecore_con_eet_data_get(Ecore_Con_Eet *ece)
732 {
733    if (!ece) return NULL;
734    return (void*) ece->data;
735 }
736
737 EAPI Ecore_Con_Eet *
738 ecore_con_eet_reply(Ecore_Con_Reply *reply)
739 {
740    if (!reply) return NULL;
741    return reply->ece;
742 }
743
744 EAPI void
745 ecore_con_eet_send(Ecore_Con_Reply *reply, const char *name, void *value)
746 {
747    Ecore_Con_Eet_Protocol protocol;
748
749    if (!reply) return ;
750
751    protocol.type = name;
752    protocol.data = value;
753
754    eet_connection_send(reply->econn, reply->ece->edd, &protocol, NULL);
755 }
756
757 EAPI void
758 ecore_con_eet_raw_send(Ecore_Con_Reply *reply, const char *protocol_name, const char *section, void *value, unsigned int length)
759 {
760    unsigned int protocol[4];
761    unsigned int protocol_length;
762    unsigned int section_length;
763    unsigned int size;
764    char *tmp;
765
766    if (!reply) return ;
767    if (!protocol_name) return ;
768    if (!section) return ;
769
770    protocol_length = strlen(protocol_name) + 1;
771    if (protocol_length == 1) return ;
772    section_length = strlen(section) + 1;
773
774    protocol[0] = htonl(ECORE_CON_EET_RAW_MAGIC);
775    protocol[1] = htonl(protocol_length);
776    protocol[2] = htonl(section_length);
777    protocol[3] = htonl(length);
778
779    size = sizeof (protocol) + protocol_length + section_length;
780    tmp = alloca(size);
781    memcpy(tmp, protocol, sizeof (protocol));
782    memcpy(tmp + sizeof (protocol), protocol, protocol_length);
783    memcpy(tmp + sizeof (protocol) + protocol_length, section, section_length);
784
785    if (reply->client)
786      {
787         ecore_con_client_send(reply->client, tmp, size);
788         ecore_con_client_send(reply->client, value, length);
789      }
790    else
791      {
792         ecore_con_server_send(reply->ece->server, tmp, size);
793         ecore_con_server_send(reply->ece->server, value, length);
794      }
795 }
796