forked from enlightenment/efl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
6.1 KiB
232 lines
6.1 KiB
#ifdef HAVE_CONFIG_H |
|
# include <config.h> |
|
#endif /* ifdef HAVE_CONFIG_H */ |
|
|
|
#ifdef HAVE_ALLOCA_H |
|
# include <alloca.h> |
|
#elif defined __GNUC__ |
|
# define alloca __builtin_alloca |
|
#elif defined _AIX |
|
# define alloca __alloca |
|
#elif defined _MSC_VER |
|
# include <malloc.h> |
|
# define alloca _alloca |
|
#else /* ifdef HAVE_ALLOCA_H */ |
|
# include <stddef.h> |
|
# ifdef __cplusplus |
|
extern "C" |
|
# endif /* ifdef __cplusplus */ |
|
void *alloca(size_t); |
|
#endif /* ifdef HAVE_ALLOCA_H */ |
|
|
|
#include <string.h> |
|
#include <stdlib.h> |
|
|
|
#ifdef HAVE_NETINET_IN_H |
|
# include <netinet/in.h> |
|
#endif /* ifdef HAVE_NETINET_IN_H */ |
|
|
|
#ifdef _WIN32 |
|
# include <winsock2.h> |
|
#endif /* ifdef _WIN32 */ |
|
|
|
#include <Eina.h> |
|
|
|
#include "Eet.h" |
|
#include "Eet_private.h" |
|
|
|
/* max message size: 1Gb - raised from original 64Kb */ |
|
#define MAX_MSG_SIZE (1024 * 1024 * 1024) |
|
#define MAGIC_EET_DATA_PACKET 0x4270ACE1 |
|
|
|
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; |
|
}; |
|
|
|
EAPI 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; |
|
} |
|
|
|
EAPI 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 int *msg; |
|
size_t packet_size; |
|
|
|
if (size < (sizeof(int) * 2)) break; |
|
|
|
msg = data; |
|
/* Check the magic */ |
|
if (ntohl(msg[0]) != MAGIC_EET_DATA_PACKET) break; |
|
|
|
packet_size = ntohl(msg[1]); |
|
/* Message should always be under MAX_MSG_SIZE */ |
|
if (packet_size > MAX_MSG_SIZE) break; |
|
|
|
data = (void *)(msg + 2); |
|
size -= sizeof(int) * 2; |
|
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) |
|
{ |
|
int *message; |
|
|
|
/* Message should always be under MAX_MSG_SIZE */ |
|
if (data_size > MAX_MSG_SIZE) return EINA_FALSE; |
|
message = alloca(data_size + (sizeof(int) * 2)); |
|
message[0] = htonl(MAGIC_EET_DATA_PACKET); |
|
message[1] = htonl(data_size); |
|
memcpy(message + 2, data, data_size); |
|
conn->eet_write_cb(message, |
|
data_size + (sizeof(int) * 2), |
|
conn->user_data); |
|
return EINA_TRUE; |
|
} |
|
|
|
EAPI Eina_Bool |
|
eet_connection_empty(Eet_Connection *conn) |
|
{ |
|
return conn->size ? EINA_FALSE : EINA_TRUE; |
|
} |
|
|
|
EAPI 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; |
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, 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; |
|
} |
|
|
|
EAPI 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; |
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(conn, 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; |
|
} |
|
|
|
EAPI 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; |
|
} |
|
|
|
|