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