aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_con/ecore_con_info.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-04 18:41:13 +1000
committerDavid Walter Seikel2012-01-04 18:41:13 +1000
commitdd7595a3475407a7fa96a97393bae8c5220e8762 (patch)
treee341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/ecore/src/lib/ecore_con/ecore_con_info.c
parentAdd the skeleton. (diff)
downloadSledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to '')
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_info.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_info.c b/libraries/ecore/src/lib/ecore_con/ecore_con_info.c
new file mode 100644
index 0000000..4ece6b0
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_info.c
@@ -0,0 +1,450 @@
1/*
2 * getaddrinfo with callback
3 *
4 * man getaddrinfo
5 *
6 */
7
8#ifdef HAVE_CONFIG_H
9# include <config.h>
10#endif
11
12#ifdef HAVE_ALLOCA_H
13# include <alloca.h>
14#elif defined __GNUC__
15# define alloca __builtin_alloca
16#elif defined _AIX
17# define alloca __alloca
18#elif defined _MSC_VER
19# include <malloc.h>
20# define alloca _alloca
21#else
22# include <stddef.h>
23# ifdef __cplusplus
24extern "C"
25# endif
26void *alloca(size_t);
27#endif
28
29#include <string.h>
30#include <sys/types.h>
31#include <unistd.h>
32#include <ctype.h>
33#ifdef __OpenBSD__
34# include <sys/types.h>
35#endif
36
37#ifdef HAVE_NETINET_IN_H
38# include <netinet/in.h>
39#endif
40
41#ifdef HAVE_ARPA_INET_H
42# include <arpa/inet.h>
43#endif
44
45#ifdef HAVE_ARPA_NAMESER_H
46# include <arpa/nameser.h>
47#endif
48
49#ifdef HAVE_SYS_SOCKET_H
50# include <sys/socket.h>
51#endif
52
53#ifdef HAVE_NETDB_H
54# include <netdb.h>
55#endif
56
57#include <errno.h>
58
59#include "Ecore.h"
60#include "ecore_private.h"
61#include "ecore_con_private.h"
62
63typedef struct _CB_Data CB_Data;
64
65struct _CB_Data
66{
67 EINA_INLIST;
68 Ecore_Con_Info_Cb cb_done;
69 void *data;
70 Ecore_Fd_Handler *fdh;
71 pid_t pid;
72 Ecore_Event_Handler *handler;
73 int fd2;
74};
75
76static void _ecore_con_info_readdata(CB_Data *cbdata);
77static void _ecore_con_info_slave_free(CB_Data *cbdata);
78static Eina_Bool _ecore_con_info_data_handler(void *data,
79 Ecore_Fd_Handler *fd_handler);
80static Eina_Bool _ecore_con_info_exit_handler(void *data,
81 int type __UNUSED__,
82 void *event);
83
84static int info_init = 0;
85static CB_Data *info_slaves = NULL;
86
87int
88ecore_con_info_init(void)
89{
90 info_init++;
91 return info_init;
92}
93
94int
95ecore_con_info_shutdown(void)
96{
97 info_init--;
98 if (info_init == 0)
99 while (info_slaves) _ecore_con_info_slave_free(info_slaves);
100
101 return info_init;
102}
103
104int
105ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
106 Ecore_Con_Info_Cb done_cb,
107 void *data)
108{
109 struct addrinfo hints;
110
111 memset(&hints, 0, sizeof(struct addrinfo));
112 hints.ai_family = AF_UNSPEC;
113 hints.ai_socktype = SOCK_STREAM;
114 hints.ai_flags = AI_CANONNAME;
115 hints.ai_protocol = IPPROTO_TCP;
116 hints.ai_canonname = NULL;
117 hints.ai_next = NULL;
118 hints.ai_addr = NULL;
119
120 return ecore_con_info_get(svr, done_cb, data, &hints);
121}
122
123int
124ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
125 Ecore_Con_Info_Cb done_cb,
126 void *data)
127{
128 struct addrinfo hints;
129
130 memset(&hints, 0, sizeof(struct addrinfo));
131 hints.ai_family = AF_UNSPEC;
132 hints.ai_socktype = SOCK_STREAM;
133 hints.ai_flags = AI_PASSIVE;
134 hints.ai_protocol = IPPROTO_TCP;
135 hints.ai_canonname = NULL;
136 hints.ai_next = NULL;
137 hints.ai_addr = NULL;
138
139 return ecore_con_info_get(svr, done_cb, data, &hints);
140}
141
142int
143ecore_con_info_udp_connect(Ecore_Con_Server *svr,
144 Ecore_Con_Info_Cb done_cb,
145 void *data)
146{
147 struct addrinfo hints;
148
149 memset(&hints, 0, sizeof(struct addrinfo));
150 hints.ai_family = AF_UNSPEC;
151 hints.ai_socktype = SOCK_DGRAM;
152 hints.ai_flags = AI_CANONNAME;
153 hints.ai_protocol = IPPROTO_UDP;
154 hints.ai_canonname = NULL;
155 hints.ai_next = NULL;
156 hints.ai_addr = NULL;
157
158 return ecore_con_info_get(svr, done_cb, data, &hints);
159}
160
161int
162ecore_con_info_udp_listen(Ecore_Con_Server *svr,
163 Ecore_Con_Info_Cb done_cb,
164 void *data)
165{
166 struct addrinfo hints;
167
168 memset(&hints, 0, sizeof(struct addrinfo));
169 hints.ai_family = AF_UNSPEC;
170 hints.ai_socktype = SOCK_DGRAM;
171 hints.ai_flags = AI_PASSIVE;
172 hints.ai_protocol = IPPROTO_UDP;
173 hints.ai_canonname = NULL;
174 hints.ai_next = NULL;
175 hints.ai_addr = NULL;
176
177 return ecore_con_info_get(svr, done_cb, data, &hints);
178}
179
180int
181ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
182 Ecore_Con_Info_Cb done_cb,
183 void *data)
184{
185 struct addrinfo hints;
186
187 memset(&hints, 0, sizeof(struct addrinfo));
188 hints.ai_family = AF_UNSPEC;
189 hints.ai_socktype = SOCK_DGRAM;
190 hints.ai_flags = 0;
191 hints.ai_protocol = IPPROTO_UDP;
192 hints.ai_canonname = NULL;
193 hints.ai_next = NULL;
194 hints.ai_addr = NULL;
195
196 return ecore_con_info_get(svr, done_cb, data, &hints);
197}
198
199EAPI int
200ecore_con_info_get(Ecore_Con_Server *svr,
201 Ecore_Con_Info_Cb done_cb,
202 void *data,
203 struct addrinfo *hints)
204{
205 CB_Data *cbdata;
206 int fd[2];
207
208 if (pipe(fd) < 0)
209 {
210 ecore_con_event_server_error(svr, strerror(errno));
211 return 0;
212 }
213
214 cbdata = calloc(1, sizeof(CB_Data));
215 if (!cbdata)
216 {
217 close(fd[0]);
218 close(fd[1]);
219 return 0;
220 }
221
222 cbdata->cb_done = done_cb;
223 cbdata->data = data;
224 cbdata->fd2 = fd[1];
225 if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
226 _ecore_con_info_data_handler,
227 cbdata,
228 NULL, NULL)))
229 {
230 ecore_con_event_server_error(svr, "Memory allocation failure");
231 free(cbdata);
232 close(fd[0]);
233 close(fd[1]);
234 return 0;
235 }
236
237 if ((cbdata->pid = fork()) == 0)
238 {
239 Ecore_Con_Info *container;
240 struct addrinfo *result = NULL;
241 char service[NI_MAXSERV] = {0};
242 char hbuf[NI_MAXHOST] = {0};
243 char sbuf[NI_MAXSERV] = {0};
244 unsigned char *tosend = NULL;
245 int tosend_len;
246 int canonname_len = 0;
247 int err;
248
249 eina_convert_itoa(svr->port, service);
250 /* CHILD */
251 if (!getaddrinfo(svr->name, service, hints, &result) && result)
252 {
253 if (result->ai_canonname)
254 canonname_len = strlen(result->ai_canonname) + 1;
255
256 tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen +
257 canonname_len;
258
259 tosend = alloca(tosend_len);
260 memset(tosend, 0, tosend_len);
261
262 container = (Ecore_Con_Info *)tosend;
263 container->size = tosend_len;
264
265 memcpy(&container->info,
266 result,
267 sizeof(struct addrinfo));
268 memcpy(tosend + sizeof(Ecore_Con_Info),
269 result->ai_addr,
270 result->ai_addrlen);
271 if (result->ai_canonname) /* FIXME: else... */
272 memcpy(tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen,
273 result->ai_canonname,
274 canonname_len);
275
276 if (!getnameinfo(result->ai_addr, result->ai_addrlen,
277 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
278 NI_NUMERICHOST | NI_NUMERICSERV))
279 {
280 memcpy(container->ip, hbuf, sizeof(container->ip));
281 memcpy(container->service, sbuf, sizeof(container->service));
282 }
283
284 err = write(fd[1], tosend, tosend_len);
285 }
286
287 if (result)
288 freeaddrinfo(result);
289
290 err = write(fd[1], "", 1);
291 close(fd[1]);
292#if defined(__USE_ISOC99) && !defined(__UCLIBC__)
293 _Exit(0);
294#else
295 _exit(0);
296#endif
297 }
298
299 /* PARENT */
300 cbdata->handler =
301 ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler,
302 cbdata);
303 close(fd[1]);
304 if (!cbdata->handler)
305 {
306 ecore_main_fd_handler_del(cbdata->fdh);
307 free(cbdata);
308 close(fd[0]);
309 return 0;
310 }
311
312 info_slaves = (CB_Data *)eina_inlist_append(EINA_INLIST_GET(
313 info_slaves),
314 EINA_INLIST_GET(cbdata));
315 svr->infos = eina_list_append(svr->infos, cbdata);
316 return 1;
317}
318
319void
320ecore_con_info_data_clear(void *info)
321{
322 CB_Data *cbdata = info;
323 cbdata->data = NULL;
324}
325
326static void
327_ecore_con_info_readdata(CB_Data *cbdata)
328{
329 Ecore_Con_Info container;
330 Ecore_Con_Info *recv_info;
331 unsigned char *torecv;
332 int torecv_len;
333
334 ssize_t size;
335
336 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
337 sizeof(Ecore_Con_Info));
338 if (size == sizeof(Ecore_Con_Info))
339 {
340 torecv_len = container.size;
341 torecv = malloc(torecv_len);
342
343 memcpy(torecv, &container, sizeof(Ecore_Con_Info));
344
345 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh),
346 torecv + sizeof(Ecore_Con_Info),
347 torecv_len - sizeof(Ecore_Con_Info));
348 if ((size > 0) &&
349 ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
350 {
351 recv_info = (Ecore_Con_Info *)torecv;
352
353 recv_info->info.ai_addr =
354 (struct sockaddr *)(torecv + sizeof(Ecore_Con_Info));
355 if ((size_t)torecv_len !=
356 (sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen))
357 recv_info->info.ai_canonname = (char *)
358 (torecv + sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen);
359 else
360 recv_info->info.ai_canonname = NULL;
361
362 recv_info->info.ai_next = NULL;
363
364 if (cbdata->data)
365 {
366 cbdata->cb_done(cbdata->data, recv_info);
367 ecore_con_server_infos_del(cbdata->data, cbdata);
368 }
369
370 free(torecv);
371 }
372 else
373 {
374 if (cbdata->data)
375 {
376 cbdata->cb_done(cbdata->data, NULL);
377 ecore_con_server_infos_del(cbdata->data, cbdata);
378 }
379 }
380 }
381 else
382 {
383 if (cbdata->data)
384 {
385 ecore_con_event_server_error(cbdata->data, strerror(errno));
386 cbdata->cb_done(cbdata->data, NULL);
387 ecore_con_server_infos_del(cbdata->data, cbdata);
388 }
389 }
390
391 cbdata->cb_done = NULL;
392}
393
394static void
395_ecore_con_info_slave_free(CB_Data *cbdata)
396{
397 info_slaves = (CB_Data *)eina_inlist_remove(EINA_INLIST_GET(info_slaves),
398 EINA_INLIST_GET(cbdata));
399 ecore_main_fd_handler_del(cbdata->fdh);
400 ecore_event_handler_del(cbdata->handler);
401 close(ecore_main_fd_handler_fd_get(cbdata->fdh));
402 if (cbdata->data) ecore_con_server_infos_del(cbdata->data, cbdata);
403 free(cbdata);
404}
405
406static Eina_Bool
407_ecore_con_info_data_handler(void *data,
408 Ecore_Fd_Handler *fd_handler)
409{
410 CB_Data *cbdata;
411
412 cbdata = data;
413 if (cbdata->cb_done)
414 {
415 if (ecore_main_fd_handler_active_get(fd_handler,
416 ECORE_FD_READ))
417 _ecore_con_info_readdata(cbdata);
418 else
419 {
420 if (cbdata->data)
421 {
422 cbdata->cb_done(cbdata->data, NULL);
423 cbdata->cb_done = NULL;
424 ecore_con_server_infos_del(cbdata->data, cbdata);
425 }
426 }
427 }
428
429 _ecore_con_info_slave_free(cbdata);
430 return ECORE_CALLBACK_CANCEL;
431}
432
433static Eina_Bool
434_ecore_con_info_exit_handler(void *data,
435 int type __UNUSED__,
436 void *event)
437{
438 CB_Data *cbdata;
439 Ecore_Exe_Event_Del *ev;
440
441 ev = event;
442 cbdata = data;
443 if (cbdata->pid != ev->pid)
444 return ECORE_CALLBACK_RENEW;
445
446 return ECORE_CALLBACK_CANCEL; /* FIXME: Woot ??? */
447 _ecore_con_info_slave_free(cbdata);
448 return ECORE_CALLBACK_CANCEL;
449}
450