7 #include "Ecore_Con_Eet.h"
9 #define ECORE_CON_EET_RAW_MAGIC 0xDEAD007
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;
16 struct _Ecore_Con_Reply
19 Ecore_Con_Client *client;
21 Eet_Connection *econn;
24 unsigned char *buffer;
25 unsigned int buffer_length;
26 unsigned int buffer_current;
27 Ecore_Con_Eet_Raw_Data *buffer_handler;
30 struct _Ecore_Con_Eet_Data
32 Ecore_Con_Eet_Data_Cb func;
37 struct _Ecore_Con_Eet_Raw_Data
39 Ecore_Con_Eet_Raw_Data_Cb func;
44 struct _Ecore_Con_Eet_Client
46 Ecore_Con_Eet_Client_Cb func;
50 struct _Ecore_Con_Eet_Server
52 Ecore_Con_Eet_Server_Cb func;
58 Ecore_Con_Server *server;
60 Ecore_Event_Handler *handler_add;
61 Ecore_Event_Handler *handler_del;
62 Ecore_Event_Handler *handler_data;
64 Eet_Data_Descriptor *edd;
65 Eet_Data_Descriptor *matching;
67 Eina_Hash *data_callbacks;
68 Eina_Hash *raw_data_callbacks;
72 Eina_List *connections;
73 Eina_List *client_connect_callbacks;
74 Eina_List *client_disconnect_callbacks;
78 Eina_List *server_connect_callbacks;
79 Eina_List *server_disconnect_callbacks;
89 _ecore_con_eet_data_free(void *data)
91 Ecore_Con_Eet_Data *eced = data;
93 eina_stringshare_del(eced->name);
98 _ecore_con_eet_raw_data_free(void *data)
100 Ecore_Con_Eet_Raw_Data *eced = data;
102 eina_stringshare_del(eced->name);
106 _ecore_con_eet_reply_cleanup(Ecore_Con_Reply *n)
108 if (n->buffer_handler) free(n->buffer);
110 n->buffer_handler = NULL;
111 free(n->buffer_section);
112 n->buffer_section = NULL;
115 typedef struct _Ecore_Con_Eet_Protocol Ecore_Con_Eet_Protocol;
116 struct _Ecore_Con_Eet_Protocol {
122 _ecore_con_eet_data_type_get(const void *data, Eina_Bool *unknow EINA_UNUSED)
124 const Ecore_Con_Eet_Protocol *p = data;
130 _ecore_con_eet_data_type_set(const char *type, void *data, Eina_Bool unknow EINA_UNUSED)
132 Ecore_Con_Eet_Protocol *p = data;
139 _ecore_con_eet_data_descriptor_setup(Ecore_Con_Eet *ece)
141 Eet_Data_Descriptor_Class eddc;
143 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Ecore_Con_Eet_Protocol);
144 ece->edd = eet_data_descriptor_stream_new(&eddc);
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);
151 EET_DATA_DESCRIPTOR_ADD_VARIANT(ece->edd, Ecore_Con_Eet_Protocol, "data", data, type, ece->matching);
154 /* Dealing with a server listening to connection */
156 _ecore_con_eet_read_cb(const void *eet_data, size_t size, void *user_data)
158 Ecore_Con_Reply *n = user_data;
159 Ecore_Con_Eet_Protocol *protocol;
160 Ecore_Con_Eet_Data *cb;
162 protocol = eet_data_descriptor_decode(n->ece->edd, eet_data, size);
163 if (!protocol) return EINA_TRUE;
165 cb = eina_hash_find(n->ece->data_callbacks, protocol->type);
166 if (!cb) return EINA_TRUE; /* Should I report unknow protocol communication ? */
168 cb->func((void*)cb->data, n, cb->name, protocol->data);
170 eina_stringshare_del(protocol->type);
177 _ecore_con_eet_server_write_cb(const void *data, size_t size, void *user_data)
179 Ecore_Con_Reply *n = user_data;
181 if (ecore_con_client_send(n->client, data, size) != (int) size)
187 _ecore_con_eet_client_write_cb(const void *data, size_t size, void *user_data)
189 Ecore_Con_Reply *n = user_data;
191 if (ecore_con_server_send(n->ece->server, data, size) != (int) size)
197 _ecore_con_eet_server_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Add *ev)
199 Ecore_Con_Eet_Client *ecec;
201 Ecore_Con_Eet *r = data;
204 if (ecore_con_client_server_get(ev->client) != r->server)
207 n = calloc(1, sizeof (Ecore_Con_Reply));
208 if (!n) return EINA_TRUE;
210 n->client = ev->client;
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);
215 EINA_LIST_FOREACH(r->u.server.client_connect_callbacks, ll, ecec)
216 if (!ecec->func((void*) ecec->data, n, n->client))
218 eet_connection_close(n->econn, NULL);
223 r->u.server.connections = eina_list_append(r->u.server.connections, n);
229 _ecore_con_eet_server_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Del *ev)
231 Ecore_Con_Eet *r = data;
235 if (ecore_con_client_server_get(ev->client) != r->server)
238 EINA_LIST_FOREACH(r->u.server.connections, l, n)
239 if (n->client == ev->client)
241 Ecore_Con_Eet_Client *ecec;
244 EINA_LIST_FOREACH(r->u.server.client_disconnect_callbacks, ll, ecec)
245 ecec->func((void*) ecec->data, n, n->client);
247 eet_connection_close(n->econn, NULL);
249 r->u.server.connections = eina_list_remove_list(r->u.server.connections, l);
257 _ecore_con_eet_raw_data_push(Ecore_Con_Reply *n, void *data, int size)
259 if (n->buffer_handler)
260 memcpy(n->buffer + n->buffer_current, data, size);
261 n->buffer_current += size;
263 if (n->buffer_current == n->buffer_length)
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);
272 _ecore_con_eet_data(Ecore_Con_Reply *n, void *data, unsigned int size)
274 /* FIXME: Enforce detection of attack and kill connection on that case */
277 if (n->buffer_current + size > n->buffer_length)
279 _ecore_con_eet_reply_cleanup(n);
283 _ecore_con_eet_raw_data_push(n, data, size);
286 else if (eet_connection_empty(n->econn) && size > (int) (4 * sizeof (unsigned int) + 2))
288 unsigned int *tmp = data;
289 size -= 4 * sizeof (unsigned int) + 2;
291 if (ntohl(tmp[0]) == ECORE_CON_EET_RAW_MAGIC)
293 unsigned int protocol_length = ntohl(tmp[1]);
294 unsigned int section_length = ntohl(tmp[2]);
295 unsigned int data_length = ntohl(tmp[3]);
297 if (protocol_length > 1 && section_length > 1 && protocol_length + section_length <= size && data_length < 10 * 1024 * 1024)
299 char *buffer = (char*) &tmp[4];
304 section = buffer + protocol_length;
306 if (protocol[protocol_length - 1] == '\0' &&
307 section[section_length - 1] == '\0')
309 size -= protocol_length + section_length;
310 buffer = section + section_length;
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));
319 n->buffer = (void*) 1;
322 _ecore_con_eet_raw_data_push(n, buffer, size);
325 _ecore_con_eet_reply_cleanup(n);
327 size += protocol_length + section_length;
332 size += 4 * sizeof (unsigned int) + 2;
335 eet_connection_received(n->econn, data, size);
339 _ecore_con_eet_server_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Data *ev)
341 Ecore_Con_Eet *r = data;
344 if (ecore_con_client_server_get(ev->client) != r->server)
347 n = ecore_con_client_data_get(ev->client);
349 _ecore_con_eet_data(n, ev->data, ev->size);
354 /* Dealing connection to a server */
357 _ecore_con_eet_client_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev)
359 Ecore_Con_Eet_Server *eces;
360 Ecore_Con_Eet *r = data;
364 /* Client did connect */
365 if (r->server != ev->server) return EINA_TRUE;
366 if (r->u.client.r) return EINA_TRUE;
368 n = calloc(1, sizeof (Ecore_Con_Reply));
369 if (!n) return EINA_TRUE;
373 n->econn = eet_connection_new(_ecore_con_eet_read_cb, _ecore_con_eet_client_write_cb, n);
375 EINA_LIST_FOREACH(r->u.client.server_connect_callbacks, ll, eces)
376 if (!eces->func((void*) eces->data, n, n->ece->server))
378 eet_connection_close(n->econn, NULL);
389 _ecore_con_eet_client_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev)
391 Ecore_Con_Eet *r = data;
392 Ecore_Con_Eet_Server *eces;
395 if (r->server != ev->server) return EINA_TRUE;
396 if (!r->u.client.r) return EINA_TRUE;
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);
402 eet_connection_close(r->u.client.r->econn, NULL);
404 r->u.client.r = NULL;
410 _ecore_con_eet_client_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev)
412 Ecore_Con_Eet *r = data;
414 if (r->server != ev->server) return EINA_TRUE;
415 if (!r->u.client.r) return EINA_TRUE;
418 _ecore_con_eet_data(r->u.client.r, ev->data, ev->size);
428 ecore_con_eet_server_new(Ecore_Con_Server *server)
432 if (!server) return NULL;
434 r = calloc(1, sizeof (Ecore_Con_Eet));
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);
447 _ecore_con_eet_data_descriptor_setup(r);
453 ecore_con_eet_client_new(Ecore_Con_Server *server)
457 if (!server) return NULL;
459 r = calloc(1, sizeof (Ecore_Con_Eet));
462 r->client = EINA_TRUE;
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);
473 _ecore_con_eet_data_descriptor_setup(r);
479 ecore_con_eet_server_free(Ecore_Con_Eet *r)
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);
490 Ecore_Con_Eet_Server *s;
494 _ecore_con_eet_reply_cleanup(r->u.client.r);
495 eet_connection_close(r->u.client.r->econn, NULL);
498 EINA_LIST_FREE(r->u.client.server_connect_callbacks, s)
500 EINA_LIST_FREE(r->u.client.server_disconnect_callbacks, s)
506 Ecore_Con_Eet_Client *c;
508 EINA_LIST_FREE(r->u.server.connections, n)
510 _ecore_con_eet_reply_cleanup(n);
511 eet_connection_close(n->econn, NULL);
514 EINA_LIST_FREE(r->u.server.client_connect_callbacks, c)
516 EINA_LIST_FREE(r->u.server.client_disconnect_callbacks, c)
520 ecore_event_handler_del(r->handler_add);
521 ecore_event_handler_del(r->handler_del);
522 ecore_event_handler_del(r->handler_data);
527 ecore_con_eet_register(Ecore_Con_Eet *ece, const char *name, Eet_Data_Descriptor *edd)
531 EET_DATA_DESCRIPTOR_ADD_MAPPING(ece->matching, name, edd);
535 ecore_con_eet_data_callback_add(Ecore_Con_Eet *ece, const char *name, Ecore_Con_Eet_Data_Cb func, const void *data)
537 Ecore_Con_Eet_Data *eced;
541 eced = calloc(1, sizeof (Ecore_Con_Eet_Data));;
546 eced->name = eina_stringshare_add(name);
548 eina_hash_direct_add(ece->data_callbacks, eced->name, eced);
552 ecore_con_eet_data_callback_del(Ecore_Con_Eet *ece, const char *name)
555 eina_hash_del(ece->data_callbacks, name, NULL);
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)
561 Ecore_Con_Eet_Raw_Data *eced;
565 eced = calloc(1, sizeof (Ecore_Con_Eet_Raw_Data));;
570 eced->name = eina_stringshare_add(name);
572 eina_hash_direct_add(ece->raw_data_callbacks, eced->name, eced);
576 ecore_con_eet_raw_data_callback_del(Ecore_Con_Eet *ece, const char *name)
580 if (ece->client && ece->u.client.r->buffer_handler && !strcmp(ece->u.client.r->buffer_handler->name, name))
582 ece->u.client.r->buffer_handler = NULL;
583 free(ece->u.client.r->buffer);
584 ece->u.client.r->buffer = (void*) 1;
586 eina_hash_del(ece->raw_data_callbacks, name, NULL);
590 ecore_con_eet_client_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
592 Ecore_Con_Eet_Client *c;
594 if (!ece || !func) return ;
596 c = calloc(1, sizeof (Ecore_Con_Eet_Client));
602 ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_connect_callbacks, c);
606 ecore_con_eet_client_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
608 Ecore_Con_Eet_Client *c;
611 if (!ece || !func) return ;
613 EINA_LIST_FOREACH(ece->u.server.client_connect_callbacks, l, c)
614 if (c->func == func && c->data == data)
616 ece->u.server.client_connect_callbacks = eina_list_remove_list(ece->u.server.client_connect_callbacks, l);
623 ecore_con_eet_client_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
625 Ecore_Con_Eet_Client *c;
627 if (!ece || !func) return ;
629 c = calloc(1, sizeof (Ecore_Con_Eet_Client));
635 ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_disconnect_callbacks, c);
639 ecore_con_eet_client_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data)
641 Ecore_Con_Eet_Client *c;
644 if (!ece || !func) return ;
646 EINA_LIST_FOREACH(ece->u.server.client_disconnect_callbacks, l, c)
647 if (c->func == func && c->data == data)
649 ece->u.server.client_disconnect_callbacks = eina_list_remove_list(ece->u.server.client_disconnect_callbacks,
657 ecore_con_eet_server_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
659 Ecore_Con_Eet_Server *s;
661 if (!ece || !func) return ;
663 s = calloc(1, sizeof (Ecore_Con_Eet_Server));
669 ece->u.client.server_connect_callbacks = eina_list_append(ece->u.client.server_connect_callbacks, s);
673 ecore_con_eet_server_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
675 Ecore_Con_Eet_Server *s;
678 if (!ece || !func) return ;
680 EINA_LIST_FOREACH(ece->u.client.server_connect_callbacks, l, s)
681 if (s->func == func && s->data == data)
683 ece->u.client.server_connect_callbacks = eina_list_remove_list(ece->u.client.server_connect_callbacks, l);
690 ecore_con_eet_server_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
692 Ecore_Con_Eet_Server *s;
694 if (!ece || !func) return ;
696 s = calloc(1, sizeof (Ecore_Con_Eet_Server));
702 ece->u.client.server_disconnect_callbacks = eina_list_append(ece->u.client.server_disconnect_callbacks, s);
706 ecore_con_eet_server_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data)
708 Ecore_Con_Eet_Server *s;
711 if (!ece || !func) return ;
713 EINA_LIST_FOREACH(ece->u.client.server_disconnect_callbacks, l, s)
714 if (s->func == func && s->data == data)
716 ece->u.client.server_disconnect_callbacks = eina_list_remove_list(ece->u.client.server_disconnect_callbacks, l);
723 ecore_con_eet_data_set(Ecore_Con_Eet *ece, const void *data)
731 ecore_con_eet_data_get(Ecore_Con_Eet *ece)
733 if (!ece) return NULL;
734 return (void*) ece->data;
738 ecore_con_eet_reply(Ecore_Con_Reply *reply)
740 if (!reply) return NULL;
745 ecore_con_eet_send(Ecore_Con_Reply *reply, const char *name, void *value)
747 Ecore_Con_Eet_Protocol protocol;
751 protocol.type = name;
752 protocol.data = value;
754 eet_connection_send(reply->econn, reply->ece->edd, &protocol, NULL);
758 ecore_con_eet_raw_send(Ecore_Con_Reply *reply, const char *protocol_name, const char *section, void *value, unsigned int length)
760 unsigned int protocol[4];
761 unsigned int protocol_length;
762 unsigned int section_length;
767 if (!protocol_name) return ;
768 if (!section) return ;
770 protocol_length = strlen(protocol_name) + 1;
771 if (protocol_length == 1) return ;
772 section_length = strlen(section) + 1;
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);
779 size = sizeof (protocol) + protocol_length + section_length;
781 memcpy(tmp, protocol, sizeof (protocol));
782 memcpy(tmp + sizeof (protocol), protocol, protocol_length);
783 memcpy(tmp + sizeof (protocol) + protocol_length, section, section_length);
787 ecore_con_client_send(reply->client, tmp, size);
788 ecore_con_client_send(reply->client, value, length);
792 ecore_con_server_send(reply->ece->server, tmp, size);
793 ecore_con_server_send(reply->ece->server, value, length);