From 1891eb36032b4593c20fe162e93a44bf0d4ee72b Mon Sep 17 00:00:00 2001 From: cedric Date: Fri, 2 Apr 2010 14:30:06 +0000 Subject: [PATCH] * eet: oops, forgot to add the file. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eet@47690 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/eet_connection.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/lib/eet_connection.c diff --git a/src/lib/eet_connection.c b/src/lib/eet_connection.c new file mode 100644 index 0000000..ed90d75 --- /dev/null +++ b/src/lib/eet_connection.c @@ -0,0 +1,229 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if HAVE___ATTRIBUTE__ +# define __UNUSED__ __attribute__((unused)) +#else +# define __UNUSED__ +#endif + +#include +#include + +#ifdef HAVE_NETINET_IN_H +# include +#endif + +#if defined(_WIN32) && ! defined(__CEGCC__) +# include +#endif +#include + +#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; +} -- 2.7.4