* eet: oops, forgot to add the file.
authorcedric <cedric>
Fri, 2 Apr 2010 14:30:06 +0000 (14:30 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 2 Apr 2010 14:30:06 +0000 (14:30 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eet@47690 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/eet_connection.c [new file with mode: 0644]

diff --git a/src/lib/eet_connection.c b/src/lib/eet_connection.c
new file mode 100644 (file)
index 0000000..ed90d75
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE___ATTRIBUTE__
+# define __UNUSED__ __attribute__((unused))
+#else
+# define __UNUSED__
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#if defined(_WIN32) && ! defined(__CEGCC__)
+# include <winsock2.h>
+#endif
+#include <Eina.h>
+
+#include "Eet.h"
+#include "Eet_private.h"
+
+#define MAGIC_EET_DATA_PACKET 0x4270ACE1
+
+typedef struct _Eet_Message Eet_Message;
+struct _Eet_Message {
+   int magic;
+   int size;
+};
+
+struct _Eet_Connection
+{
+   Eet_Read_Cb *eet_read_cb;
+   Eet_Write_Cb *eet_write_cb;
+   void *user_data;
+
+   size_t allocated;
+   size_t size;
+   size_t received;
+
+   void *buffer;
+};
+
+Eet_Connection *
+eet_connection_new(Eet_Read_Cb *eet_read_cb,
+                  Eet_Write_Cb *eet_write_cb,
+                  const void *user_data)
+{
+   Eet_Connection *conn;
+
+   if (!eet_read_cb || !eet_write_cb)
+     return NULL;
+
+   conn = calloc(1, sizeof (Eet_Connection));
+   if (!conn)
+     return NULL;
+
+   conn->eet_read_cb = eet_read_cb;
+   conn->eet_write_cb = eet_write_cb;
+   conn->user_data = (void*) user_data;
+
+   return conn;
+}
+
+int
+eet_connection_received(Eet_Connection *conn, const void *data, size_t size)
+{
+   if (!conn || !data || !size)
+     return size;
+
+   do {
+      size_t copy_size;
+
+      if (conn->size == 0)
+       {
+          const Eet_Message *msg;
+          size_t packet_size;
+
+          if (size < sizeof (Eet_Message))
+            break;
+
+          msg = data;
+          /* Check the magic */
+          if (ntohl(msg->magic) != MAGIC_EET_DATA_PACKET)
+            break;
+
+          packet_size = ntohl(msg->size);
+          /* Message should always be under 64K */
+          if (packet_size > 64 * 1024)
+            break;
+
+          data = (void*) (msg + 1);
+          size -= sizeof (msg);
+          if ((size_t) packet_size <= size)
+            {
+               /* Not a partial receive, go the quick way. */
+               if (!conn->eet_read_cb(data, packet_size, conn->user_data))
+                 break;
+
+               data = (void*) ((char *) data + packet_size);
+               size -= packet_size;
+
+               conn->received = 0;
+               continue;
+            }
+
+          conn->size = packet_size;
+          if (conn->allocated < conn->size)
+            {
+               void *tmp;
+
+               tmp = realloc(conn->buffer, conn->size);
+               if (!tmp)
+                 break;
+
+               conn->buffer = tmp;
+               conn->allocated = conn->size;
+            }
+       }
+
+      /* Partial receive */
+      copy_size = (conn->size - conn->received >= size) ? size : conn->size - conn->received;
+      memcpy((char*) conn->buffer + conn->received, data, copy_size);
+
+      conn->received += copy_size;
+      data = (void*)((char *) data + copy_size);
+      size -= copy_size;
+
+      if (conn->received == conn->size)
+       {
+          size_t data_size;
+
+          data_size = conn->size;
+          conn->size = 0;
+          conn->received = 0;
+
+          /* Completed a packet. */
+          if (!conn->eet_read_cb(conn->buffer, data_size, conn->user_data))
+            {
+               /* Something goes wrong. Stop now. */
+               size += data_size;
+               break;
+            }
+       }
+   } while (size > 0);
+
+   return size;
+}
+
+static Eina_Bool
+_eet_connection_raw_send(Eet_Connection *conn, void *data, int data_size)
+{
+   Eet_Message *message;
+
+   /* Message should never be above 64K */
+   if (data_size > 64 * 1024)
+     return EINA_FALSE;
+
+   message = alloca(data_size + sizeof (Eet_Message));
+   message->magic = htonl(MAGIC_EET_DATA_PACKET);
+   message->size = htonl(data_size);
+
+   memcpy(message + 1, data, data_size);
+
+   conn->eet_write_cb(message, data_size + sizeof (Eet_Message), conn->user_data);
+   return EINA_TRUE;
+}
+
+Eina_Bool
+eet_connection_send(Eet_Connection *conn, Eet_Data_Descriptor *edd, const void *data_in, const char *cipher_key)
+{
+   void *flat_data;
+   int data_size;
+   Eina_Bool ret = EINA_FALSE;
+
+   flat_data = eet_data_descriptor_encode_cipher(edd, data_in, cipher_key, &data_size);
+   if (!flat_data)
+     return EINA_FALSE;
+
+   if (_eet_connection_raw_send(conn, flat_data, data_size))
+     ret = EINA_TRUE;
+
+   free(flat_data);
+   return ret;
+}
+
+Eina_Bool
+eet_connection_node_send(Eet_Connection *conn, Eet_Node *node, const char *cipher_key)
+{
+   void *data;
+   int data_size;
+   Eina_Bool ret = EINA_FALSE;
+
+   data = eet_data_node_encode_cipher(node, cipher_key, &data_size);
+   if (!data)
+     return EINA_FALSE;
+
+   if (_eet_connection_raw_send(conn, data, data_size))
+     ret = EINA_TRUE;
+
+   free(data);
+   return ret;
+}
+
+void *
+eet_connection_close(Eet_Connection *conn, Eina_Bool *on_going)
+{
+   void *user_data;
+
+   if (!conn)
+     return NULL;
+
+   if (on_going)
+     *on_going = conn->received == 0 ? EINA_FALSE : EINA_TRUE;
+
+   user_data = conn->user_data;
+
+   free(conn->buffer);
+   free(conn);
+
+   return user_data;
+}