ecore: Add Ecore_Con_Eet API.
authorCedric BAIL <cedric.bail@free.fr>
Fri, 31 Aug 2012 03:11:24 +0000 (03:11 +0000)
committerCedric BAIL <cedric.bail@free.fr>
Fri, 31 Aug 2012 03:11:24 +0000 (03:11 +0000)
SVN revision: 75910

legacy/ecore/ChangeLog
legacy/ecore/NEWS
legacy/ecore/configure.ac
legacy/ecore/src/lib/ecore_con/Ecore_Con_Eet.h [new file with mode: 0644]
legacy/ecore/src/lib/ecore_con/Makefile.am
legacy/ecore/src/lib/ecore_con/ecore_con_eet.c [new file with mode: 0644]

index c0e707b..894962c 100644 (file)
 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
index e208cd3..10e349b 100644 (file)
@@ -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:
index c3b6dbb..d2012a7 100644 (file)
@@ -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 (file)
index 0000000..9640e7b
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _ECORE_CON_EET
+# define _ECORE_CON_EET
+
+#include <Eet.h>
+#include <Ecore.h>
+#include <Ecore_Con.h>
+
+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
index 0e8e071..ce656f7 100644 (file)
@@ -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 (file)
index 0000000..1be212f
--- /dev/null
@@ -0,0 +1,785 @@
+#include <Eina.h>
+
+#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);
+     }
+}
+