2 * getaddrinfo with callback
14 #elif defined __GNUC__
15 # define alloca __builtin_alloca
17 # define alloca __alloca
18 #elif defined _MSC_VER
20 # define alloca _alloca
26 void *alloca (size_t);
30 #include <sys/types.h>
34 # include <sys/types.h>
37 #ifdef HAVE_ARPA_INET_H
38 # include <arpa/inet.h>
41 #ifdef HAVE_ARPA_NAMESER_H
42 # include <arpa/nameser.h>
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
49 #ifdef HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
58 #include "ecore_private.h"
59 #include "ecore_con_private.h"
61 typedef struct _CB_Data CB_Data;
66 Ecore_Con_Info_Cb cb_done;
68 Ecore_Fd_Handler *fdh;
70 Ecore_Event_Handler *handler;
75 static void _ecore_con_info_readdata(CB_Data *cbdata);
76 static void _ecore_con_info_slave_free(CB_Data *cbdata);
77 static Eina_Bool _ecore_con_info_data_handler(void *data,
78 Ecore_Fd_Handler *fd_handler);
79 static Eina_Bool _ecore_con_info_exit_handler(void *data, int type __UNUSED__,
82 static int info_init = 0;
83 static CB_Data *info_slaves = NULL;
86 ecore_con_info_init(void)
93 ecore_con_info_shutdown(void)
97 while (info_slaves) _ecore_con_info_slave_free(info_slaves);
103 ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
104 Ecore_Con_Info_Cb done_cb,
107 struct addrinfo hints;
109 memset(&hints, 0, sizeof(struct addrinfo));
110 hints.ai_family = AF_UNSPEC;
111 hints.ai_socktype = SOCK_STREAM;
112 hints.ai_flags = AI_CANONNAME;
113 hints.ai_protocol = IPPROTO_TCP;
114 hints.ai_canonname = NULL;
115 hints.ai_next = NULL;
116 hints.ai_addr = NULL;
118 return ecore_con_info_get(svr, done_cb, data, &hints);
122 ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
123 Ecore_Con_Info_Cb done_cb,
126 struct addrinfo hints;
128 memset(&hints, 0, sizeof(struct addrinfo));
129 hints.ai_family = AF_UNSPEC;
130 hints.ai_socktype = SOCK_STREAM;
131 hints.ai_flags = AI_PASSIVE;
132 hints.ai_protocol = IPPROTO_TCP;
133 hints.ai_canonname = NULL;
134 hints.ai_next = NULL;
135 hints.ai_addr = NULL;
137 return ecore_con_info_get(svr, done_cb, data, &hints);
141 ecore_con_info_udp_connect(Ecore_Con_Server *svr,
142 Ecore_Con_Info_Cb done_cb,
145 struct addrinfo hints;
147 memset(&hints, 0, sizeof(struct addrinfo));
148 hints.ai_family = AF_UNSPEC;
149 hints.ai_socktype = SOCK_DGRAM;
150 hints.ai_flags = AI_CANONNAME;
151 hints.ai_protocol = IPPROTO_UDP;
152 hints.ai_canonname = NULL;
153 hints.ai_next = NULL;
154 hints.ai_addr = NULL;
156 return ecore_con_info_get(svr, done_cb, data, &hints);
160 ecore_con_info_udp_listen(Ecore_Con_Server *svr,
161 Ecore_Con_Info_Cb done_cb,
164 struct addrinfo hints;
166 memset(&hints, 0, sizeof(struct addrinfo));
167 hints.ai_family = AF_UNSPEC;
168 hints.ai_socktype = SOCK_DGRAM;
169 hints.ai_flags = AI_PASSIVE;
170 hints.ai_protocol = IPPROTO_UDP;
171 hints.ai_canonname = NULL;
172 hints.ai_next = NULL;
173 hints.ai_addr = NULL;
175 return ecore_con_info_get(svr, done_cb, data, &hints);
179 ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
180 Ecore_Con_Info_Cb done_cb,
183 struct addrinfo hints;
185 memset(&hints, 0, sizeof(struct addrinfo));
186 hints.ai_family = AF_UNSPEC;
187 hints.ai_socktype = SOCK_DGRAM;
189 hints.ai_protocol = IPPROTO_UDP;
190 hints.ai_canonname = NULL;
191 hints.ai_next = NULL;
192 hints.ai_addr = NULL;
194 return ecore_con_info_get(svr, done_cb, data, &hints);
198 ecore_con_info_get(Ecore_Con_Server *svr,
199 Ecore_Con_Info_Cb done_cb,
201 struct addrinfo *hints)
209 cbdata = calloc(1, sizeof(CB_Data));
217 cbdata->cb_done = done_cb;
220 if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
221 _ecore_con_info_data_handler,
231 if ((cbdata->pid = fork()) == 0)
233 Ecore_Con_Info *container;
234 struct addrinfo *result = NULL;
235 char service[NI_MAXSERV] = {0};
236 char hbuf[NI_MAXHOST] = {0};
237 char sbuf[NI_MAXSERV] = {0};
238 unsigned char *tosend = NULL;
240 int canonname_len = 0;
243 eina_convert_itoa(svr->port, service);
245 if (!getaddrinfo(svr->name, service, hints, &result) && result)
247 if (result->ai_canonname)
248 canonname_len = strlen(result->ai_canonname) + 1;
250 tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen +
253 if (!(tosend = alloca(tosend_len))) goto on_error;
254 memset(tosend, 0, tosend_len);
256 container = (Ecore_Con_Info *)tosend;
257 container->size = tosend_len;
259 memcpy(&container->info,
261 sizeof(struct addrinfo));
262 memcpy(tosend + sizeof(Ecore_Con_Info),
265 memcpy(tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen,
266 result->ai_canonname,
269 if (!getnameinfo(result->ai_addr, result->ai_addrlen,
270 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
271 NI_NUMERICHOST | NI_NUMERICSERV))
273 memcpy(container->ip, hbuf, sizeof(container->ip));
274 memcpy(container->service, sbuf, sizeof(container->service));
277 err = write(fd[1], tosend, tosend_len);
282 freeaddrinfo(result);
284 err = write(fd[1], "", 1);
295 ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler,
298 if (!cbdata->handler)
300 ecore_main_fd_handler_del(cbdata->fdh);
306 info_slaves = (CB_Data *)eina_inlist_append(EINA_INLIST_GET(
308 EINA_INLIST_GET(cbdata));
313 _ecore_con_info_readdata(CB_Data *cbdata)
315 Ecore_Con_Info container;
316 Ecore_Con_Info *recv;
317 unsigned char *torecv;
322 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
323 sizeof(Ecore_Con_Info));
324 if (size == sizeof(Ecore_Con_Info))
326 torecv_len = container.size;
327 torecv = malloc(torecv_len);
329 memcpy(torecv, &container, sizeof(Ecore_Con_Info));
331 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh),
332 torecv + sizeof(Ecore_Con_Info),
333 torecv_len - sizeof(Ecore_Con_Info));
335 ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
337 recv = (Ecore_Con_Info *)torecv;
340 (struct sockaddr *)(torecv + sizeof(Ecore_Con_Info));
341 if ((size_t)torecv_len !=
342 (sizeof(Ecore_Con_Info) + recv->info.ai_addrlen))
343 recv->info.ai_canonname = (char *)
344 (torecv + sizeof(Ecore_Con_Info) + recv->info.ai_addrlen);
346 recv->info.ai_canonname = NULL;
348 recv->info.ai_next = NULL;
350 cbdata->cb_done(cbdata->data, recv);
355 cbdata->cb_done(cbdata->data, NULL);
358 cbdata->cb_done(cbdata->data, NULL);
360 cbdata->cb_done = NULL;
364 _ecore_con_info_slave_free(CB_Data *cbdata)
366 info_slaves = (CB_Data *)eina_inlist_remove(EINA_INLIST_GET(info_slaves),
367 EINA_INLIST_GET(cbdata));
368 ecore_main_fd_handler_del(cbdata->fdh);
369 close(ecore_main_fd_handler_fd_get(cbdata->fdh));
370 ecore_event_handler_del(cbdata->handler);
375 _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
382 if (ecore_main_fd_handler_active_get(fd_handler,
384 _ecore_con_info_readdata(cbdata);
387 cbdata->cb_done(cbdata->data, NULL);
388 cbdata->cb_done = NULL;
392 _ecore_con_info_slave_free(cbdata);
393 return ECORE_CALLBACK_CANCEL;
397 _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event)
400 Ecore_Exe_Event_Del *ev;
404 if (cbdata->pid != ev->pid)
405 return ECORE_CALLBACK_RENEW;
407 return ECORE_CALLBACK_CANCEL; /* FIXME: Woot ??? */
408 _ecore_con_info_slave_free(cbdata);
409 return ECORE_CALLBACK_CANCEL;