From 0423ca5a364fc9adbc2035b7201f1a4548115c8a Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 31 Aug 2012 03:11:24 +0000 Subject: [PATCH] ecore: Add Ecore_Con_Eet API. SVN revision: 75910 --- legacy/ecore/ChangeLog | 4 + legacy/ecore/NEWS | 13 + legacy/ecore/configure.ac | 20 +- legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h | 47 ++ legacy/ecore/src/lib/ecore_con/Makefile.am | 8 +- legacy/ecore/src/lib/ecore_con/ecore_con_eet.c | 785 +++++++++++++++++++++++++ 6 files changed, 871 insertions(+), 6 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h create mode 100644 legacy/ecore/src/lib/ecore_con/ecore_con_eet.c diff --git a/legacy/ecore/ChangeLog b/legacy/ecore/ChangeLog index c0e707b..894962c 100644 --- a/legacy/ecore/ChangeLog +++ b/legacy/ecore/ChangeLog @@ -891,3 +891,7 @@ 2012-08-30 Carsten Haitzler (The Rasterman) 1.7.0 release + +2012-08-31 Cedric Bail + + * Add Ecore_Con_Eet API to help using Eet_Data with Ecore_Con diff --git a/legacy/ecore/NEWS b/legacy/ecore/NEWS index e208cd3..10e349b 100644 --- a/legacy/ecore/NEWS +++ b/legacy/ecore/NEWS @@ -1,3 +1,16 @@ +Ecore 1.8.0 + +Changes since Ecore 1.7.0: +-------------------------- + +Additions: + * ecore_con: + - Add Ecore_Con_Eet API to help using Eet_Data with Ecore_Con. + +Fixes: + +Improvements: + Ecore 1.7.0 Changes since Ecore 1.2.0: diff --git a/legacy/ecore/configure.ac b/legacy/ecore/configure.ac index c3b6dbb..d2012a7 100644 --- a/legacy/ecore/configure.ac +++ b/legacy/ecore/configure.ac @@ -114,6 +114,7 @@ want_glib="no" # core modules want_ecore_con="yes" +want_ecore_con_eet="yes" want_ecore_ipc="yes" want_ecore_file="yes" #want_ecore_config="no" @@ -184,6 +185,7 @@ want_ecore_imf_ibus="no" case "$host_os" in mingw32ce*) want_ecore_con="no" + want_ecore_con_eet="no" want_ecore_ipc="no" want_ecore_wince="yes" want_ecore_evas_software_16_wince="yes" @@ -622,11 +624,10 @@ PKG_CHECK_MODULES([DIRECTFB], # Eet library (ecore_config) -#PKG_CHECK_MODULES([EET], -# [eet >= 1.6.99], -# [have_eet="yes"], -# [have_eet="no"]) - +PKG_CHECK_MODULES([EET], + [eet >= 1.6.99], + [have_eet="yes"], + [have_eet="no"]) # Xlib and XCB (ecore_x) @@ -1477,6 +1478,7 @@ have_openssl="no" have_cares="no" want_ipv6="yes" have_ipv6="no" +have_ecore_con_eet="no" AC_ARG_ENABLE([ipv6], [AC_HELP_STRING([--disable-ipv6], @@ -1511,6 +1513,13 @@ if test "x${have_ecore_con}" = "xyes" ; then fi AM_CONDITIONAL([HAVE_IPV6], [test "x${have_ipv6}" = "xyes"]) + if test "x${have_eet}" = "xyes" ; then + requirements_ecore_con="eet > 1.7 ${requirements_ecore_con}" + have_ecore_con_eet="yes" + AC_DEFINE(ECORE_HAVE_EET, 1, [Define if Ecore_Con Eet_Connection helper is supported]) + fi + AM_CONDITIONAL([ECORE_HAVE_EET], [test "x${have_ecore_con_eet}" = "xyes"]) + ECORE_CHECK_CURL([${want_curl}], [ have_curl="yes" @@ -2113,6 +2122,7 @@ fi echo " IPv6.......................: $have_ipv6" echo " GnuTLS.....................: $have_gnutls" echo " CURL.......................: $have_curl" + echo " Eet........................: $have_ecore_con_eet" echo " Local Sockets..............: $want_ecore_con_local_sockets" if test "x$want_ecore_con_local_sockets" = "xyes" ; then echo " Abstract Sockets.........: $want_ecore_con_abstract_sockets" diff --git a/legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h b/legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h new file mode 100644 index 0000000..9640e7b --- /dev/null +++ b/legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h @@ -0,0 +1,47 @@ +#ifndef _ECORE_CON_EET +# define _ECORE_CON_EET + +#include +#include +#include + +typedef struct _Ecore_Con_Eet Ecore_Con_Eet; +typedef struct _Ecore_Con_Reply Ecore_Con_Reply; + +typedef void (*Ecore_Con_Eet_Data_Cb)(void *data, Ecore_Con_Reply *reply, const char *protocol_name, void *value); +typedef void (*Ecore_Con_Eet_Raw_Data_Cb)(void *data, Ecore_Con_Reply *reply, const char *protocol_name, const char *section, void *value, size_t length); +typedef Eina_Bool (*Ecore_Con_Eet_Client_Cb)(void *data, Ecore_Con_Reply *reply, Ecore_Con_Client *conn); +typedef Eina_Bool (*Ecore_Con_Eet_Server_Cb)(void *data, Ecore_Con_Reply *reply, Ecore_Con_Server *conn); + +Ecore_Con_Eet *ecore_con_eet_server_new(Ecore_Con_Server *server); +Ecore_Con_Eet *ecore_con_eet_client_new(Ecore_Con_Server *server); +void ecore_con_eet_server_free(Ecore_Con_Eet *ece); + +void ecore_con_eet_register(Ecore_Con_Eet *ece, const char *name, Eet_Data_Descriptor *edd); + +void ecore_con_eet_data_callback_add(Ecore_Con_Eet *ece, const char *name, Ecore_Con_Eet_Data_Cb func, const void *data); +void ecore_con_eet_data_callback_del(Ecore_Con_Eet *ece, const char *name); + +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); +void ecore_con_eet_raw_data_callback_del(Ecore_Con_Eet *ece, const char *name); + +void ecore_con_eet_client_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data); +void ecore_con_eet_client_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data); + +void ecore_con_eet_client_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data); +void ecore_con_eet_client_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data); + +void ecore_con_eet_server_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data); +void ecore_con_eet_server_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data); + +void ecore_con_eet_server_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data); +void ecore_con_eet_server_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data); + +void ecore_con_eet_data_set(Ecore_Con_Eet *ece, const void *data); +void *ecore_con_eet_data_get(Ecore_Con_Eet *ece); + +Ecore_Con_Eet *ecore_con_eet_reply(Ecore_Con_Reply *reply); +void ecore_con_eet_send(Ecore_Con_Reply *reply, const char *protocol_name, void *value); +void ecore_con_eet_raw_send(Ecore_Con_Reply *reply, const char *protocol_name, const char *section, void *value, unsigned int length); + +#endif diff --git a/legacy/ecore/src/lib/ecore_con/Makefile.am b/legacy/ecore/src/lib/ecore_con/Makefile.am index 0e8e071..ce656f7 100644 --- a/legacy/ecore/src/lib/ecore_con/Makefile.am +++ b/legacy/ecore/src/lib/ecore_con/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = \ @EINA_CFLAGS@ \ @TLS_CFLAGS@ \ @CARES_CFLAGS@ \ +@EET_CFLAGS@ \ @WIN32_CPPFLAGS@ lib_LTLIBRARIES = libecore_con.la @@ -44,9 +45,14 @@ libecore_con_la_SOURCES += ecore_con_info.c endif endif +if ECORE_HAVE_EET +libecore_con_la_SOURCES += ecore_con_eet.c +includes_HEADERS += Ecore_Con_Eet.h +endif + libecore_con_la_LIBADD = \ $(top_builddir)/src/lib/ecore/libecore.la \ -@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @EVIL_LIBS@ @TLS_LIBS@ @CARES_LIBS@ @WIN32_LIBS@ +@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @EVIL_LIBS@ @TLS_LIBS@ @CARES_LIBS@ @WIN32_LIBS@ @EET_LIBS@ libecore_con_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@ diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_eet.c b/legacy/ecore/src/lib/ecore_con/ecore_con_eet.c new file mode 100644 index 0000000..1be212f --- /dev/null +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_eet.c @@ -0,0 +1,785 @@ +#include + +#include "Ecore_Con_Eet.h" + +#define ECORE_CON_EET_RAW_MAGIC 0xDEAD007 + +typedef struct _Ecore_Con_Eet_Data Ecore_Con_Eet_Data; +typedef struct _Ecore_Con_Eet_Raw_Data Ecore_Con_Eet_Raw_Data; +typedef struct _Ecore_Con_Eet_Client Ecore_Con_Eet_Client; +typedef struct _Ecore_Con_Eet_Server Ecore_Con_Eet_Server; + +struct _Ecore_Con_Reply +{ + Ecore_Con_Eet *ece; + Ecore_Con_Client *client; + + Eet_Connection *econn; + + char *buffer_section; + unsigned char *buffer; + unsigned int buffer_length; + unsigned int buffer_current; + Ecore_Con_Eet_Raw_Data *buffer_handler; +}; + +struct _Ecore_Con_Eet_Data +{ + Ecore_Con_Eet_Data_Cb func; + const char *name; + const void *data; +}; + +struct _Ecore_Con_Eet_Raw_Data +{ + Ecore_Con_Eet_Raw_Data_Cb func; + const char *name; + const void *data; +}; + +struct _Ecore_Con_Eet_Client +{ + Ecore_Con_Eet_Client_Cb func; + const void *data; +}; + +struct _Ecore_Con_Eet_Server +{ + Ecore_Con_Eet_Server_Cb func; + const void *data; +}; + +struct _Ecore_Con_Eet +{ + Ecore_Con_Server *server; + + Ecore_Event_Handler *handler_add; + Ecore_Event_Handler *handler_del; + Ecore_Event_Handler *handler_data; + + Eet_Data_Descriptor *edd; + Eet_Data_Descriptor *matching; + + Eina_Hash *data_callbacks; + Eina_Hash *raw_data_callbacks; + + union { + struct { + Eina_List *connections; + Eina_List *client_connect_callbacks; + Eina_List *client_disconnect_callbacks; + } server; + struct { + Ecore_Con_Reply *r; + Eina_List *server_connect_callbacks; + Eina_List *server_disconnect_callbacks; + } client; + } u; + + const void *data; + + Eina_Bool client : 1; +}; + +static void +_ecore_con_eet_data_free(void *data) +{ + Ecore_Con_Eet_Data *eced = data; + + eina_stringshare_del(eced->name); + free(eced); +} + +static void +_ecore_con_eet_raw_data_free(void *data) +{ + Ecore_Con_Eet_Raw_Data *eced = data; + + eina_stringshare_del(eced->name); + free(eced); +} +static void +_ecore_con_eet_reply_cleanup(Ecore_Con_Reply *n) +{ + if (n->buffer_handler) free(n->buffer); + n->buffer = NULL; + n->buffer_handler = NULL; + free(n->buffer_section); + n->buffer_section = NULL; +} + +typedef struct _Ecore_Con_Eet_Protocol Ecore_Con_Eet_Protocol; +struct _Ecore_Con_Eet_Protocol { + const char *type; + void *data; +}; + +static const char * +_ecore_con_eet_data_type_get(const void *data, Eina_Bool *unknow EINA_UNUSED) +{ + const Ecore_Con_Eet_Protocol *p = data; + + return p->type; +} + +static Eina_Bool +_ecore_con_eet_data_type_set(const char *type, void *data, Eina_Bool unknow EINA_UNUSED) +{ + Ecore_Con_Eet_Protocol *p = data; + + p->type = type; + return EINA_TRUE; +} + +static void +_ecore_con_eet_data_descriptor_setup(Ecore_Con_Eet *ece) +{ + Eet_Data_Descriptor_Class eddc; + + EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Ecore_Con_Eet_Protocol); + ece->edd = eet_data_descriptor_stream_new(&eddc); + + eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION; + eddc.func.type_get = _ecore_con_eet_data_type_get; + eddc.func.type_set = _ecore_con_eet_data_type_set; + ece->matching = eet_data_descriptor_stream_new(&eddc); + + EET_DATA_DESCRIPTOR_ADD_VARIANT(ece->edd, Ecore_Con_Eet_Protocol, "data", data, type, ece->matching); +} + +/* Dealing with a server listening to connection */ +static Eina_Bool +_ecore_con_eet_read_cb(const void *eet_data, size_t size, void *user_data) +{ + Ecore_Con_Reply *n = user_data; + Ecore_Con_Eet_Protocol *protocol; + Ecore_Con_Eet_Data *cb; + + protocol = eet_data_descriptor_decode(n->ece->edd, eet_data, size); + if (!protocol) return EINA_TRUE; + + cb = eina_hash_find(n->ece->data_callbacks, protocol->type); + if (!cb) return EINA_TRUE; /* Should I report unknow protocol communication ? */ + + cb->func((void*)cb->data, n, cb->name, protocol->data); + + eina_stringshare_del(protocol->type); + free(protocol); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_server_write_cb(const void *data, size_t size, void *user_data) +{ + Ecore_Con_Reply *n = user_data; + + if (ecore_con_client_send(n->client, data, size) != (int) size) + return EINA_FALSE; + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_client_write_cb(const void *data, size_t size, void *user_data) +{ + Ecore_Con_Reply *n = user_data; + + if (ecore_con_server_send(n->ece->server, data, size) != (int) size) + return EINA_FALSE; + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_server_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Add *ev) +{ + Ecore_Con_Eet_Client *ecec; + Eina_List *ll; + Ecore_Con_Eet *r = data; + Ecore_Con_Reply *n; + + if (ecore_con_client_server_get(ev->client) != r->server) + return EINA_TRUE; + + n = calloc(1, sizeof (Ecore_Con_Reply)); + if (!n) return EINA_TRUE; + + n->client = ev->client; + n->ece = r; + n->econn = eet_connection_new(_ecore_con_eet_read_cb, _ecore_con_eet_server_write_cb, n); + ecore_con_client_data_set(n->client, n); + + EINA_LIST_FOREACH(r->u.server.client_connect_callbacks, ll, ecec) + if (!ecec->func((void*) ecec->data, n, n->client)) + { + eet_connection_close(n->econn, NULL); + free(n); + return EINA_TRUE; + } + + r->u.server.connections = eina_list_append(r->u.server.connections, n); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_server_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Del *ev) +{ + Ecore_Con_Eet *r = data; + Ecore_Con_Reply *n; + Eina_List *l; + + if (ecore_con_client_server_get(ev->client) != r->server) + return EINA_TRUE; + + EINA_LIST_FOREACH(r->u.server.connections, l, n) + if (n->client == ev->client) + { + Ecore_Con_Eet_Client *ecec; + Eina_List *ll; + + EINA_LIST_FOREACH(r->u.server.client_disconnect_callbacks, ll, ecec) + ecec->func((void*) ecec->data, n, n->client); + + eet_connection_close(n->econn, NULL); + free(n); + r->u.server.connections = eina_list_remove_list(r->u.server.connections, l); + return EINA_TRUE; + } + + return EINA_TRUE; +} + +static void +_ecore_con_eet_raw_data_push(Ecore_Con_Reply *n, void *data, int size) +{ + if (n->buffer_handler) + memcpy(n->buffer + n->buffer_current, data, size); + n->buffer_current += size; + + if (n->buffer_current == n->buffer_length) + { + if (n->buffer_handler) + n->buffer_handler->func((void*) n->buffer_handler->data, n, n->buffer_handler->name, n->buffer_section, n->buffer, n->buffer_length); + _ecore_con_eet_reply_cleanup(n); + } +} + +static void +_ecore_con_eet_data(Ecore_Con_Reply *n, void *data, unsigned int size) +{ + /* FIXME: Enforce detection of attack and kill connection on that case */ + + if (n->buffer) + { + if (n->buffer_current + size > n->buffer_length) + { + _ecore_con_eet_reply_cleanup(n); + return ; + } + + _ecore_con_eet_raw_data_push(n, data, size); + return ; + } + else if (eet_connection_empty(n->econn) && size > (int) (4 * sizeof (unsigned int) + 2)) + { + unsigned int *tmp = data; + size -= 4 * sizeof (unsigned int) + 2; + + if (ntohl(tmp[0]) == ECORE_CON_EET_RAW_MAGIC) + { + unsigned int protocol_length = ntohl(tmp[1]); + unsigned int section_length = ntohl(tmp[2]); + unsigned int data_length = ntohl(tmp[3]); + + if (protocol_length > 1 && section_length > 1 && protocol_length + section_length <= size && data_length < 10 * 1024 * 1024) + { + char *buffer = (char*) &tmp[4]; + char *protocol; + char *section; + + protocol = buffer; + section = buffer + protocol_length; + + if (protocol[protocol_length - 1] == '\0' && + section[section_length - 1] == '\0') + { + size -= protocol_length + section_length; + buffer = section + section_length; + + n->buffer_handler = eina_hash_find(n->ece->raw_data_callbacks, protocol); + n->buffer_section = strdup(section); + n->buffer_length = data_length; + n->buffer_current = 0; + if (n->buffer_handler) + n->buffer = malloc(sizeof (data_length)); + else + n->buffer = (void*) 1; + if (n->buffer) + { + _ecore_con_eet_raw_data_push(n, buffer, size); + return ; + } + _ecore_con_eet_reply_cleanup(n); + } + } + } + } + + eet_connection_received(n->econn, data, size); +} + +static Eina_Bool +_ecore_con_eet_server_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Client_Data *ev) +{ + Ecore_Con_Eet *r = data; + Ecore_Con_Reply *n; + + if (ecore_con_client_server_get(ev->client) != r->server) + return EINA_TRUE; + + n = ecore_con_client_data_get(ev->client); + + _ecore_con_eet_data(n, ev->data, ev->size); + + return EINA_TRUE; +} + +/* Dealing connection to a server */ + +static Eina_Bool +_ecore_con_eet_client_connected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Add *ev) +{ + Ecore_Con_Eet_Server *eces; + Ecore_Con_Eet *r = data; + Ecore_Con_Reply *n; + Eina_List *ll; + + /* Client did connect */ + if (r->server != ev->server) return EINA_TRUE; + if (r->u.client.r) return EINA_TRUE; + + n = calloc(1, sizeof (Ecore_Con_Reply)); + if (!n) return EINA_TRUE; + + n->client = NULL; + n->ece = r; + n->econn = eet_connection_new(_ecore_con_eet_read_cb, _ecore_con_eet_client_write_cb, n); + + EINA_LIST_FOREACH(r->u.client.server_connect_callbacks, ll, eces) + if (!eces->func((void*) eces->data, n, n->ece->server)) + { + eet_connection_close(n->econn, NULL); + free(n); + return EINA_TRUE; + } + + r->u.client.r = n; + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_client_disconnected(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Del *ev) +{ + Ecore_Con_Eet *r = data; + Ecore_Con_Eet_Server *eces; + Eina_List *ll; + + if (r->server != ev->server) return EINA_TRUE; + if (!r->u.client.r) return EINA_TRUE; + + /* Client disconnected */ + EINA_LIST_FOREACH(r->u.client.server_disconnect_callbacks, ll, eces) + eces->func((void*) eces->data, r->u.client.r, r->server); + + eet_connection_close(r->u.client.r->econn, NULL); + free(r->u.client.r); + r->u.client.r = NULL; + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_con_eet_client_data(void *data, int type EINA_UNUSED, Ecore_Con_Event_Server_Data *ev) +{ + Ecore_Con_Eet *r = data; + + if (r->server != ev->server) return EINA_TRUE; + if (!r->u.client.r) return EINA_TRUE; + + /* Got some data */ + _ecore_con_eet_data(r->u.client.r, ev->data, ev->size); + + return EINA_TRUE; +} + +Ecore_Con_Eet * +ecore_con_eet_server_new(Ecore_Con_Server *server) +{ + Ecore_Con_Eet *r; + + if (!server) return NULL; + + r = calloc(1, sizeof (Ecore_Con_Eet)); + if (!r) return NULL; + + r->server = server; + r->handler_add = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, + (Ecore_Event_Handler_Cb)_ecore_con_eet_server_connected, r); + r->handler_del = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, + (Ecore_Event_Handler_Cb)_ecore_con_eet_server_disconnected, r); + r->handler_data = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, + (Ecore_Event_Handler_Cb)_ecore_con_eet_server_data, r); + r->data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_data_free); + r->raw_data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_raw_data_free); + + _ecore_con_eet_data_descriptor_setup(r); + + return r; +} + +Ecore_Con_Eet * +ecore_con_eet_client_new(Ecore_Con_Server *server) +{ + Ecore_Con_Eet *r; + + if (!server) return NULL; + + r = calloc(1, sizeof (Ecore_Con_Eet)); + if (!r) return NULL; + + r->client = EINA_TRUE; + r->server = server; + r->handler_add = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, + (Ecore_Event_Handler_Cb)_ecore_con_eet_client_connected, r); + r->handler_del = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, + (Ecore_Event_Handler_Cb)_ecore_con_eet_client_disconnected, r); + r->handler_data = ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, + (Ecore_Event_Handler_Cb)_ecore_con_eet_client_data, r); + r->data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_data_free); + r->raw_data_callbacks = eina_hash_stringshared_new(_ecore_con_eet_raw_data_free); + + _ecore_con_eet_data_descriptor_setup(r); + + return r; +} + +void +ecore_con_eet_server_free(Ecore_Con_Eet *r) +{ + if (!r) return ; + + eet_data_descriptor_free(r->edd); + eet_data_descriptor_free(r->matching); + eina_hash_free(r->data_callbacks); + eina_hash_free(r->raw_data_callbacks); + + if (r->client) + { + Ecore_Con_Eet_Server *s; + + if (r->u.client.r) + { + _ecore_con_eet_reply_cleanup(r->u.client.r); + eet_connection_close(r->u.client.r->econn, NULL); + free(r->u.client.r); + } + EINA_LIST_FREE(r->u.client.server_connect_callbacks, s) + free(s); + EINA_LIST_FREE(r->u.client.server_disconnect_callbacks, s) + free(s); + } + else + { + Ecore_Con_Reply *n; + Ecore_Con_Eet_Client *c; + + EINA_LIST_FREE(r->u.server.connections, n) + { + _ecore_con_eet_reply_cleanup(n); + eet_connection_close(n->econn, NULL); + free(n); + } + EINA_LIST_FREE(r->u.server.client_connect_callbacks, c) + free(c); + EINA_LIST_FREE(r->u.server.client_disconnect_callbacks, c) + free(c); + } + + ecore_event_handler_del(r->handler_add); + ecore_event_handler_del(r->handler_del); + ecore_event_handler_del(r->handler_data); + free(r); +} + +void +ecore_con_eet_register(Ecore_Con_Eet *ece, const char *name, Eet_Data_Descriptor *edd) +{ + if (!ece) return ; + + EET_DATA_DESCRIPTOR_ADD_MAPPING(ece->matching, name, edd); +} + +void +ecore_con_eet_data_callback_add(Ecore_Con_Eet *ece, const char *name, Ecore_Con_Eet_Data_Cb func, const void *data) +{ + Ecore_Con_Eet_Data *eced; + + if (!ece) return ; + + eced = calloc(1, sizeof (Ecore_Con_Eet_Data));; + if (!eced) return ; + + eced->func = func; + eced->data = data; + eced->name = eina_stringshare_add(name); + + eina_hash_direct_add(ece->data_callbacks, eced->name, eced); +} + +void +ecore_con_eet_data_callback_del(Ecore_Con_Eet *ece, const char *name) +{ + if (!ece) return ; + eina_hash_del(ece->data_callbacks, name, NULL); +} + +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) +{ + Ecore_Con_Eet_Raw_Data *eced; + + if (!ece) return ; + + eced = calloc(1, sizeof (Ecore_Con_Eet_Raw_Data));; + if (!eced) return ; + + eced->func = func; + eced->data = data; + eced->name = eina_stringshare_add(name); + + eina_hash_direct_add(ece->raw_data_callbacks, eced->name, eced); +} + +void +ecore_con_eet_raw_data_callback_del(Ecore_Con_Eet *ece, const char *name) +{ + if (!ece) return ; + + if (ece->client && ece->u.client.r->buffer_handler && !strcmp(ece->u.client.r->buffer_handler->name, name)) + { + ece->u.client.r->buffer_handler = NULL; + free(ece->u.client.r->buffer); + ece->u.client.r->buffer = (void*) 1; + } + eina_hash_del(ece->raw_data_callbacks, name, NULL); +} + +void +ecore_con_eet_client_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data) +{ + Ecore_Con_Eet_Client *c; + + if (!ece || !func) return ; + + c = calloc(1, sizeof (Ecore_Con_Eet_Client)); + if (!c) return ; + + c->func = func; + c->data = data; + + ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_connect_callbacks, c); +} + +void +ecore_con_eet_client_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data) +{ + Ecore_Con_Eet_Client *c; + Eina_List *l; + + if (!ece || !func) return ; + + EINA_LIST_FOREACH(ece->u.server.client_connect_callbacks, l, c) + if (c->func == func && c->data == data) + { + ece->u.server.client_connect_callbacks = eina_list_remove_list(ece->u.server.client_connect_callbacks, l); + free(c); + return ; + } +} + +void +ecore_con_eet_client_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data) +{ + Ecore_Con_Eet_Client *c; + + if (!ece || !func) return ; + + c = calloc(1, sizeof (Ecore_Con_Eet_Client)); + if (!c) return ; + + c->func = func; + c->data = data; + + ece->u.server.client_connect_callbacks = eina_list_append(ece->u.server.client_disconnect_callbacks, c); +} + +void +ecore_con_eet_client_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Client_Cb func, const void *data) +{ + Ecore_Con_Eet_Client *c; + Eina_List *l; + + if (!ece || !func) return ; + + EINA_LIST_FOREACH(ece->u.server.client_disconnect_callbacks, l, c) + if (c->func == func && c->data == data) + { + ece->u.server.client_disconnect_callbacks = eina_list_remove_list(ece->u.server.client_disconnect_callbacks, + l); + free(c); + return ; + } +} + +void +ecore_con_eet_server_connect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data) +{ + Ecore_Con_Eet_Server *s; + + if (!ece || !func) return ; + + s = calloc(1, sizeof (Ecore_Con_Eet_Server)); + if (!s) return ; + + s->func = func; + s->data = data; + + ece->u.client.server_connect_callbacks = eina_list_append(ece->u.client.server_connect_callbacks, s); +} + +void +ecore_con_eet_server_connect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data) +{ + Ecore_Con_Eet_Server *s; + Eina_List *l; + + if (!ece || !func) return ; + + EINA_LIST_FOREACH(ece->u.client.server_connect_callbacks, l, s) + if (s->func == func && s->data == data) + { + ece->u.client.server_connect_callbacks = eina_list_remove_list(ece->u.client.server_connect_callbacks, l); + free(s); + return ; + } +} + +void +ecore_con_eet_server_disconnect_callback_add(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data) +{ + Ecore_Con_Eet_Server *s; + + if (!ece || !func) return ; + + s = calloc(1, sizeof (Ecore_Con_Eet_Server)); + if (!s) return ; + + s->func = func; + s->data = data; + + ece->u.client.server_disconnect_callbacks = eina_list_append(ece->u.client.server_disconnect_callbacks, s); +} + +void +ecore_con_eet_server_disconnect_callback_del(Ecore_Con_Eet *ece, Ecore_Con_Eet_Server_Cb func, const void *data) +{ + Ecore_Con_Eet_Server *s; + Eina_List *l; + + if (!ece || !func) return ; + + EINA_LIST_FOREACH(ece->u.client.server_disconnect_callbacks, l, s) + if (s->func == func && s->data == data) + { + ece->u.client.server_disconnect_callbacks = eina_list_remove_list(ece->u.client.server_disconnect_callbacks, l); + free(s); + return ; + } +} + +void +ecore_con_eet_data_set(Ecore_Con_Eet *ece, const void *data) +{ + if (!ece) return; + + ece->data = data; +} + +void * +ecore_con_eet_data_get(Ecore_Con_Eet *ece) +{ + if (!ece) return NULL; + return (void*) ece->data; +} + +Ecore_Con_Eet * +ecore_con_eet_reply(Ecore_Con_Reply *reply) +{ + if (!reply) return NULL; + return reply->ece; +} + +void +ecore_con_eet_send(Ecore_Con_Reply *reply, const char *name, void *value) +{ + Ecore_Con_Eet_Protocol protocol; + + if (!reply) return ; + + protocol.type = name; + protocol.data = value; + + eet_connection_send(reply->econn, reply->ece->edd, &protocol, NULL); +} + +void +ecore_con_eet_raw_send(Ecore_Con_Reply *reply, const char *protocol_name, const char *section, void *value, unsigned int length) +{ + unsigned int protocol[4]; + unsigned int protocol_length; + unsigned int section_length; + unsigned int size; + char *tmp; + + if (!reply) return ; + if (!protocol_name) return ; + if (!section) return ; + + protocol_length = strlen(protocol_name) + 1; + if (protocol_length == 1) return ; + section_length = strlen(section) + 1; + + protocol[0] = htonl(ECORE_CON_EET_RAW_MAGIC); + protocol[1] = htonl(protocol_length); + protocol[2] = htonl(section_length); + protocol[3] = htonl(length); + + size = sizeof (protocol) + protocol_length + section_length; + tmp = alloca(size); + memcpy(tmp, protocol, sizeof (protocol)); + memcpy(tmp + sizeof (protocol), protocol, protocol_length); + memcpy(tmp + sizeof (protocol) + protocol_length, section, section_length); + + if (reply->client) + { + ecore_con_client_send(reply->client, tmp, size); + ecore_con_client_send(reply->client, value, length); + } + else + { + ecore_con_server_send(reply->ece->server, tmp, size); + ecore_con_server_send(reply->ece->server, value, length); + } +} + -- 2.7.4