* eet: oops, forgot to add the file.

SVN revision: 47690
This commit is contained in:
Cedric BAIL 2010-04-02 14:30:06 +00:00
parent aa015979bb
commit c20cd7715a
1 changed files with 229 additions and 0 deletions

View File

@ -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;
}