forked from enlightenment/efl
parent
aa015979bb
commit
c20cd7715a
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue