2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
6 * getaddrinfo with callback
18 #elif defined __GNUC__
19 # define alloca __builtin_alloca
21 # define alloca __alloca
22 #elif defined _MSC_VER
24 # define alloca _alloca
30 void *alloca (size_t);
34 #include <sys/types.h>
38 # include <sys/types.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_NETINET_IN_H
50 # include <netinet/in.h>
53 #ifdef HAVE_SYS_SOCKET_H
54 # include <sys/socket.h>
62 #include "ecore_private.h"
63 #include "ecore_con_private.h"
65 typedef struct _CB_Data CB_Data;
70 Ecore_Con_Info_Cb cb_done;
72 Ecore_Fd_Handler *fdh;
74 Ecore_Event_Handler *handler;
79 static void _ecore_con_info_readdata(CB_Data *cbdata);
80 static void _ecore_con_info_slave_free(CB_Data *cbdata);
81 static int _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler);
82 static int _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event);
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)
100 while (info_slaves) _ecore_con_info_slave_free(info_slaves);
106 ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
107 Ecore_Con_Info_Cb done_cb,
110 struct addrinfo hints;
112 memset(&hints, 0, sizeof(struct addrinfo));
113 hints.ai_family = AF_UNSPEC;
114 hints.ai_socktype = SOCK_STREAM;
115 hints.ai_flags = AI_CANONNAME;
116 hints.ai_protocol = IPPROTO_TCP;
117 hints.ai_canonname = NULL;
118 hints.ai_next = NULL;
119 hints.ai_addr = NULL;
121 return ecore_con_info_get(svr, done_cb, data, &hints);
125 ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
126 Ecore_Con_Info_Cb done_cb,
129 struct addrinfo hints;
131 memset(&hints, 0, sizeof(struct addrinfo));
132 hints.ai_family = AF_UNSPEC;
133 hints.ai_socktype = SOCK_STREAM;
134 hints.ai_flags = AI_PASSIVE;
135 hints.ai_protocol = IPPROTO_TCP;
136 hints.ai_canonname = NULL;
137 hints.ai_next = NULL;
138 hints.ai_addr = NULL;
140 return ecore_con_info_get(svr, done_cb, data, &hints);
144 ecore_con_info_udp_connect(Ecore_Con_Server *svr,
145 Ecore_Con_Info_Cb done_cb,
148 struct addrinfo hints;
150 memset(&hints, 0, sizeof(struct addrinfo));
151 hints.ai_family = AF_UNSPEC;
152 hints.ai_socktype = SOCK_DGRAM;
153 hints.ai_flags = AI_CANONNAME;
154 hints.ai_protocol = IPPROTO_UDP;
155 hints.ai_canonname = NULL;
156 hints.ai_next = NULL;
157 hints.ai_addr = NULL;
159 return ecore_con_info_get(svr, done_cb, data, &hints);
163 ecore_con_info_udp_listen(Ecore_Con_Server *svr,
164 Ecore_Con_Info_Cb done_cb,
167 struct addrinfo hints;
169 memset(&hints, 0, sizeof(struct addrinfo));
170 hints.ai_family = AF_UNSPEC;
171 hints.ai_socktype = SOCK_DGRAM;
172 hints.ai_flags = AI_PASSIVE;
173 hints.ai_protocol = IPPROTO_UDP;
174 hints.ai_canonname = NULL;
175 hints.ai_next = NULL;
176 hints.ai_addr = NULL;
178 return ecore_con_info_get(svr, done_cb, data, &hints);
182 ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
183 Ecore_Con_Info_Cb done_cb,
186 struct addrinfo hints;
188 memset(&hints, 0, sizeof(struct addrinfo));
189 hints.ai_family = AF_UNSPEC;
190 hints.ai_socktype = SOCK_DGRAM;
192 hints.ai_protocol = IPPROTO_UDP;
193 hints.ai_canonname = NULL;
194 hints.ai_next = NULL;
195 hints.ai_addr = NULL;
197 return ecore_con_info_get(svr, done_cb, data, &hints);
201 ecore_con_info_get(Ecore_Con_Server *svr,
202 Ecore_Con_Info_Cb done_cb,
204 struct addrinfo *hints)
209 if (pipe(fd) < 0) return 0;
210 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];
236 char hbuf[NI_MAXHOST];
237 char sbuf[NI_MAXSERV];
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;
249 tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen + canonname_len;
251 if (!(tosend = alloca(tosend_len)))
254 container = (Ecore_Con_Info *)tosend;
256 container->size = tosend_len;
258 memcpy(&container->info, result, sizeof(struct addrinfo));
259 memcpy((char *)tosend + sizeof(Ecore_Con_Info), result->ai_addr, result->ai_addrlen);
260 memcpy((char *)tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen, result->ai_canonname, canonname_len);
262 if (!getnameinfo(result->ai_addr, result->ai_addrlen,
263 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
264 NI_NUMERICHOST | NI_NUMERICSERV))
266 memcpy(container->ip, hbuf, sizeof(container->ip));
267 memcpy(container->service, sbuf, sizeof(container->service));
269 err = write(fd[1], tosend, tosend_len);
274 freeaddrinfo(result);
275 err = write(fd[1], "", 1);
284 cbdata->handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler, cbdata);
286 if (!cbdata->handler)
288 ecore_main_fd_handler_del(cbdata->fdh);
293 info_slaves = (CB_Data *) eina_inlist_append(EINA_INLIST_GET(info_slaves), EINA_INLIST_GET(cbdata));
298 _ecore_con_info_readdata(CB_Data *cbdata)
300 Ecore_Con_Info container;
301 Ecore_Con_Info *recv;
307 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
308 sizeof(Ecore_Con_Info));
309 if (size == sizeof(Ecore_Con_Info))
311 torecv_len = container.size;
312 torecv = malloc(torecv_len);
314 memcpy(torecv, &container, sizeof(Ecore_Con_Info));
316 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), (char *)torecv + sizeof(Ecore_Con_Info),
317 torecv_len - sizeof(Ecore_Con_Info));
318 if ((size > 0) && ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
320 recv = (Ecore_Con_Info *)torecv;
322 recv->info.ai_addr = (struct sockaddr *)((char *)torecv + sizeof(Ecore_Con_Info));
323 if ((size_t)torecv_len != (sizeof(Ecore_Con_Info) + recv->info.ai_addrlen))
324 recv->info.ai_canonname = (char *)torecv + sizeof(Ecore_Con_Info) + recv->info.ai_addrlen;
326 recv->info.ai_canonname = NULL;
327 recv->info.ai_next = NULL;
329 cbdata->cb_done(cbdata->data, recv);
334 cbdata->cb_done(cbdata->data, NULL);
337 cbdata->cb_done(cbdata->data, NULL);
338 cbdata->cb_done = NULL;
342 _ecore_con_info_slave_free(CB_Data *cbdata)
344 info_slaves = (CB_Data *) eina_inlist_remove(EINA_INLIST_GET(info_slaves), EINA_INLIST_GET(cbdata));
345 close(ecore_main_fd_handler_fd_get(cbdata->fdh));
346 ecore_main_fd_handler_del(cbdata->fdh);
347 ecore_event_handler_del(cbdata->handler);
352 _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
359 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
360 _ecore_con_info_readdata(cbdata);
363 cbdata->cb_done(cbdata->data, NULL);
364 cbdata->cb_done = NULL;
367 _ecore_con_info_slave_free(cbdata);
372 _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event)
375 Ecore_Exe_Event_Del *ev;
379 if (cbdata->pid != ev->pid) return 1;
381 _ecore_con_info_slave_free(cbdata);