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
30 #include <sys/types.h>
34 # include <sys/types.h>
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
41 #ifdef HAVE_ARPA_INET_H
42 # include <arpa/inet.h>
45 #ifdef HAVE_ARPA_NAMESER_H
46 # include <arpa/nameser.h>
49 #ifdef HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
60 #include "ecore_private.h"
61 #include "ecore_con_private.h"
63 typedef struct _CB_Data CB_Data;
68 Ecore_Con_Info_Cb cb_done;
70 Ecore_Fd_Handler *fdh;
72 Ecore_Event_Handler *handler;
76 static void _ecore_con_info_readdata(CB_Data *cbdata);
77 static void _ecore_con_info_slave_free(CB_Data *cbdata);
78 static Eina_Bool _ecore_con_info_data_handler(void *data,
79 Ecore_Fd_Handler *fd_handler);
80 static Eina_Bool _ecore_con_info_exit_handler(void *data,
84 static int info_init = 0;
85 static CB_Data *info_slaves = NULL;
88 ecore_con_info_init(void)
95 ecore_con_info_shutdown(void)
99 while (info_slaves) _ecore_con_info_slave_free(info_slaves);
105 ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
106 Ecore_Con_Info_Cb done_cb,
109 struct addrinfo hints;
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;
120 return ecore_con_info_get(svr, done_cb, data, &hints);
124 ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
125 Ecore_Con_Info_Cb done_cb,
128 struct addrinfo hints;
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;
139 return ecore_con_info_get(svr, done_cb, data, &hints);
143 ecore_con_info_udp_connect(Ecore_Con_Server *svr,
144 Ecore_Con_Info_Cb done_cb,
147 struct addrinfo hints;
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;
158 return ecore_con_info_get(svr, done_cb, data, &hints);
162 ecore_con_info_udp_listen(Ecore_Con_Server *svr,
163 Ecore_Con_Info_Cb done_cb,
166 struct addrinfo hints;
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;
177 return ecore_con_info_get(svr, done_cb, data, &hints);
181 ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
182 Ecore_Con_Info_Cb done_cb,
185 struct addrinfo hints;
187 memset(&hints, 0, sizeof(struct addrinfo));
188 hints.ai_family = AF_UNSPEC;
189 hints.ai_socktype = SOCK_DGRAM;
191 hints.ai_protocol = IPPROTO_UDP;
192 hints.ai_canonname = NULL;
193 hints.ai_next = NULL;
194 hints.ai_addr = NULL;
196 return ecore_con_info_get(svr, done_cb, data, &hints);
200 _ecore_fd_close_on_exec(int fd)
205 flags = fcntl(fd, F_GETFD);
210 if (fcntl(fd, F_SETFD, flags) == -1)
220 ecore_con_info_get(Ecore_Con_Server *svr,
221 Ecore_Con_Info_Cb done_cb,
223 struct addrinfo *hints)
230 ecore_con_event_server_error(svr, strerror(errno));
234 _ecore_fd_close_on_exec(fd[0]);
235 _ecore_fd_close_on_exec(fd[1]);
237 cbdata = calloc(1, sizeof(CB_Data));
245 cbdata->cb_done = done_cb;
248 if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
249 _ecore_con_info_data_handler,
253 ecore_con_event_server_error(svr, "Memory allocation failure");
260 if ((cbdata->pid = fork()) == 0)
262 Ecore_Con_Info *container;
263 struct addrinfo *result = NULL;
264 char service[NI_MAXSERV] = {0};
265 char hbuf[NI_MAXHOST] = {0};
266 char sbuf[NI_MAXSERV] = {0};
267 unsigned char *tosend = NULL;
269 int canonname_len = 0;
271 eina_convert_itoa(svr->ecs ? svr->ecs->port : svr->port, service);
273 if (!getaddrinfo(svr->ecs ? svr->ecs->ip : svr->name, service, hints, &result) && result)
275 if (result->ai_canonname)
276 canonname_len = strlen(result->ai_canonname) + 1;
278 tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen +
281 tosend = alloca(tosend_len);
282 memset(tosend, 0, tosend_len);
284 container = (Ecore_Con_Info *)tosend;
285 container->size = tosend_len;
287 memcpy(&container->info,
289 sizeof(struct addrinfo));
290 memcpy(tosend + sizeof(Ecore_Con_Info),
293 if (result->ai_canonname) /* FIXME: else... */
294 memcpy(tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen,
295 result->ai_canonname,
298 if (!getnameinfo(result->ai_addr, result->ai_addrlen,
299 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
300 NI_NUMERICHOST | NI_NUMERICSERV))
302 memcpy(container->ip, hbuf, sizeof(container->ip));
303 memcpy(container->service, sbuf, sizeof(container->service));
306 if (write(fd[1], tosend, tosend_len) < 0) perror("write");
310 freeaddrinfo(result);
312 if (write(fd[1], "", 1) < 0) perror("write");
314 #if defined(__USE_ISOC99) && !defined(__UCLIBC__)
323 ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler,
326 if (!cbdata->handler)
328 ecore_main_fd_handler_del(cbdata->fdh);
334 info_slaves = (CB_Data *)eina_inlist_append(EINA_INLIST_GET(
336 EINA_INLIST_GET(cbdata));
337 svr->infos = eina_list_append(svr->infos, cbdata);
342 ecore_con_info_data_clear(void *info)
344 CB_Data *cbdata = info;
349 _ecore_con_info_readdata(CB_Data *cbdata)
351 Ecore_Con_Info container;
352 Ecore_Con_Info *recv_info;
353 unsigned char *torecv;
358 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
359 sizeof(Ecore_Con_Info));
360 if (size == sizeof(Ecore_Con_Info))
362 torecv_len = container.size;
363 torecv = malloc(torecv_len);
365 memcpy(torecv, &container, sizeof(Ecore_Con_Info));
367 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh),
368 torecv + sizeof(Ecore_Con_Info),
369 torecv_len - sizeof(Ecore_Con_Info));
371 ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
373 recv_info = (Ecore_Con_Info *)torecv;
375 recv_info->info.ai_addr =
376 (struct sockaddr *)(torecv + sizeof(Ecore_Con_Info));
377 if ((size_t)torecv_len !=
378 (sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen))
379 recv_info->info.ai_canonname = (char *)
380 (torecv + sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen);
382 recv_info->info.ai_canonname = NULL;
384 recv_info->info.ai_next = NULL;
388 cbdata->cb_done(cbdata->data, recv_info);
389 ecore_con_server_infos_del(cbdata->data, cbdata);
398 cbdata->cb_done(cbdata->data, NULL);
399 ecore_con_server_infos_del(cbdata->data, cbdata);
407 ecore_con_event_server_error(cbdata->data, strerror(errno));
408 cbdata->cb_done(cbdata->data, NULL);
409 ecore_con_server_infos_del(cbdata->data, cbdata);
413 cbdata->cb_done = NULL;
417 _ecore_con_info_slave_free(CB_Data *cbdata)
419 info_slaves = (CB_Data *)eina_inlist_remove(EINA_INLIST_GET(info_slaves),
420 EINA_INLIST_GET(cbdata));
421 ecore_main_fd_handler_del(cbdata->fdh);
422 ecore_event_handler_del(cbdata->handler);
423 close(ecore_main_fd_handler_fd_get(cbdata->fdh));
424 if (cbdata->data) ecore_con_server_infos_del(cbdata->data, cbdata);
429 _ecore_con_info_data_handler(void *data,
430 Ecore_Fd_Handler *fd_handler)
437 if (ecore_main_fd_handler_active_get(fd_handler,
439 _ecore_con_info_readdata(cbdata);
444 cbdata->cb_done(cbdata->data, NULL);
445 cbdata->cb_done = NULL;
446 ecore_con_server_infos_del(cbdata->data, cbdata);
451 _ecore_con_info_slave_free(cbdata);
452 return ECORE_CALLBACK_CANCEL;
456 _ecore_con_info_exit_handler(void *data,
461 Ecore_Exe_Event_Del *ev;
465 if (cbdata->pid != ev->pid)
466 return ECORE_CALLBACK_RENEW;
468 return ECORE_CALLBACK_CANCEL; /* FIXME: Woot ??? */
469 _ecore_con_info_slave_free(cbdata);
470 return ECORE_CALLBACK_CANCEL;