aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eet/src/lib/eet_connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eet/src/lib/eet_connection.c')
-rw-r--r--libraries/eet/src/lib/eet_connection.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/libraries/eet/src/lib/eet_connection.c b/libraries/eet/src/lib/eet_connection.c
new file mode 100644
index 0000000..6171b7e
--- /dev/null
+++ b/libraries/eet/src/lib/eet_connection.c
@@ -0,0 +1,249 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif /* ifdef HAVE_CONFIG_H */
4
5#ifdef HAVE_ALLOCA_H
6# include <alloca.h>
7#elif defined __GNUC__
8# define alloca __builtin_alloca
9#elif defined _AIX
10# define alloca __alloca
11#elif defined _MSC_VER
12# include <malloc.h>
13# define alloca _alloca
14#else /* ifdef HAVE_ALLOCA_H */
15# include <stddef.h>
16# ifdef __cplusplus
17extern "C"
18# endif /* ifdef __cplusplus */
19void *alloca(size_t);
20#endif /* ifdef HAVE_ALLOCA_H */
21
22#include <string.h>
23#include <stdlib.h>
24
25#ifdef HAVE_NETINET_IN_H
26# include <netinet/in.h>
27#endif /* ifdef HAVE_NETINET_IN_H */
28
29#ifdef _WIN32
30# include <winsock2.h>
31#endif /* ifdef _WIN32 */
32
33#include <Eina.h>
34
35#include "Eet.h"
36#include "Eet_private.h"
37
38#define MAGIC_EET_DATA_PACKET 0x4270ACE1
39
40struct _Eet_Connection
41{
42 Eet_Read_Cb *eet_read_cb;
43 Eet_Write_Cb *eet_write_cb;
44 void *user_data;
45
46 size_t allocated;
47 size_t size;
48 size_t received;
49
50 void *buffer;
51};
52
53EAPI Eet_Connection *
54eet_connection_new(Eet_Read_Cb *eet_read_cb,
55 Eet_Write_Cb *eet_write_cb,
56 const void *user_data)
57{
58 Eet_Connection *conn;
59
60 if (!eet_read_cb || !eet_write_cb)
61 return NULL;
62
63 conn = calloc(1, sizeof (Eet_Connection));
64 if (!conn)
65 return NULL;
66
67 conn->eet_read_cb = eet_read_cb;
68 conn->eet_write_cb = eet_write_cb;
69 conn->user_data = (void *)user_data;
70
71 return conn;
72} /* eet_connection_new */
73
74EAPI int
75eet_connection_received(Eet_Connection *conn,
76 const void *data,
77 size_t size)
78{
79 if ((!conn) || (!data) || (!size))
80 return size;
81
82 do {
83 size_t copy_size;
84
85 if (conn->size == 0)
86 {
87 const int *msg;
88 size_t packet_size;
89
90 if (size < sizeof (int) * 2)
91 break;
92
93 msg = data;
94 /* Check the magic */
95 if (ntohl(msg[0]) != MAGIC_EET_DATA_PACKET)
96 break;
97
98 packet_size = ntohl(msg[1]);
99 /* Message should always be under 64K */
100 if (packet_size > 64 * 1024)
101 break;
102
103 data = (void *)(msg + 2);
104 size -= sizeof (int) * 2;
105 if ((size_t)packet_size <= size)
106 {
107 /* Not a partial receive, go the quick way. */
108 if (!conn->eet_read_cb(data, packet_size, conn->user_data))
109 break;
110
111 data = (void *)((char *)data + packet_size);
112 size -= packet_size;
113
114 conn->received = 0;
115 continue;
116 }
117
118 conn->size = packet_size;
119 if (conn->allocated < conn->size)
120 {
121 void *tmp;
122
123 tmp = realloc(conn->buffer, conn->size);
124 if (!tmp)
125 break;
126
127 conn->buffer = tmp;
128 conn->allocated = conn->size;
129 }
130 }
131
132 /* Partial receive */
133 copy_size =
134 (conn->size - conn->received >=
135 size) ? size : conn->size - conn->received;
136 memcpy((char *)conn->buffer + conn->received, data, copy_size);
137
138 conn->received += copy_size;
139 data = (void *)((char *)data + copy_size);
140 size -= copy_size;
141
142 if (conn->received == conn->size)
143 {
144 size_t data_size;
145
146 data_size = conn->size;
147 conn->size = 0;
148 conn->received = 0;
149
150 /* Completed a packet. */
151 if (!conn->eet_read_cb(conn->buffer, data_size, conn->user_data))
152 {
153 /* Something goes wrong. Stop now. */
154 size += data_size;
155 break;
156 }
157 }
158 } while (size > 0);
159
160 return size;
161} /* eet_connection_received */
162
163static Eina_Bool
164_eet_connection_raw_send(Eet_Connection *conn,
165 void *data,
166 int data_size)
167{
168 int *message;
169
170 /* Message should never be above 64K */
171 if (data_size > 64 * 1024)
172 return EINA_FALSE;
173
174 message = alloca(data_size + sizeof (int) * 2);
175 message[0] = htonl(MAGIC_EET_DATA_PACKET);
176 message[1] = htonl(data_size);
177
178 memcpy(message + 2, data, data_size);
179
180 conn->eet_write_cb(message,
181 data_size + sizeof (int) * 2,
182 conn->user_data);
183 return EINA_TRUE;
184} /* _eet_connection_raw_send */
185
186EAPI Eina_Bool
187eet_connection_send(Eet_Connection *conn,
188 Eet_Data_Descriptor *edd,
189 const void *data_in,
190 const char *cipher_key)
191{
192 void *flat_data;
193 int data_size;
194 Eina_Bool ret = EINA_FALSE;
195
196 flat_data = eet_data_descriptor_encode_cipher(edd,
197 data_in,
198 cipher_key,
199 &data_size);
200 if (!flat_data)
201 return EINA_FALSE;
202
203 if (_eet_connection_raw_send(conn, flat_data, data_size))
204 ret = EINA_TRUE;
205
206 free(flat_data);
207 return ret;
208} /* eet_connection_send */
209
210EAPI Eina_Bool
211eet_connection_node_send(Eet_Connection *conn,
212 Eet_Node *node,
213 const char *cipher_key)
214{
215 void *data;
216 int data_size;
217 Eina_Bool ret = EINA_FALSE;
218
219 data = eet_data_node_encode_cipher(node, cipher_key, &data_size);
220 if (!data)
221 return EINA_FALSE;
222
223 if (_eet_connection_raw_send(conn, data, data_size))
224 ret = EINA_TRUE;
225
226 free(data);
227 return ret;
228} /* eet_connection_node_send */
229
230EAPI void *
231eet_connection_close(Eet_Connection *conn,
232 Eina_Bool *on_going)
233{
234 void *user_data;
235
236 if (!conn)
237 return NULL;
238
239 if (on_going)
240 *on_going = conn->received == 0 ? EINA_FALSE : EINA_TRUE;
241
242 user_data = conn->user_data;
243
244 free(conn->buffer);
245 free(conn);
246
247 return user_data;
248} /* eet_connection_close */
249