6 * This version of ecore_con_info uses dns.c to provide asynchronous dns lookup.
8 * dns.c is written by William Ahern:
9 * http://25thandclement.com/~william/projects/dns.c.html
13 #include <sys/types.h>
16 # include <errno.h> /* for EAGAIN */
19 #ifdef HAVE_NETINET_IN_H
20 # include <netinet/in.h>
23 #ifdef HAVE_ARPA_INET_H
24 # include <arpa/inet.h>
34 #include "Ecore_Con.h"
35 #include "ecore_con_private.h"
37 typedef struct dns_addrinfo dns_addrinfo;
38 typedef struct dns_resolv_conf dns_resolv_conf;
39 typedef struct dns_resolver dns_resolver;
40 typedef struct dns_hosts dns_hosts;
42 typedef struct _Ecore_Con_DNS Ecore_Con_DNS;
46 Ecore_Con_Server *svr;
47 Ecore_Con_Info_Cb done_cb;
51 struct addrinfo hints;
52 Ecore_Fd_Handler *fdh;
56 static int _ecore_con_dns_init = 0;
57 static dns_resolv_conf *resconf = NULL;
58 static dns_hosts *hosts = NULL;
61 _ecore_con_dns_free(Ecore_Con_DNS *dns)
63 if (dns->svr->infos) dns->svr->infos = eina_list_remove(dns->svr->infos, dns);
64 if (dns->timer) ecore_timer_del(dns->timer);
65 if (dns->fdh) ecore_main_fd_handler_del(dns->fdh);
66 dns_res_close(dns_res_mortal(dns->resolv));
71 _dns_addrinfo_get(Ecore_Con_DNS *dns, const char *addr, int port)
74 char service[NI_MAXSERV];
76 snprintf(service, sizeof(service), "%d", port);
77 dns->ai = dns_ai_open(addr, service, DNS_T_A, (const struct addrinfo *)&dns->hints, dns->resolv, &error);
82 _ecore_con_dns_check(Ecore_Con_DNS *dns)
84 struct addrinfo *ent = NULL;
87 error = dns_ai_nextent(&ent, dns->ai);
96 ERR("resolve failed: %s", dns_strerror(error));
101 Ecore_Con_Info result = {0, .ip = {0}, .service = {0}};
104 dns_ai_print(pretty, sizeof(pretty), ent, dns->ai);
105 printf("%s\n", pretty);
108 dns_inet_ntop(dns_sa_family(ent->ai_addr), dns_sa_addr(dns_sa_family(ent->ai_addr), ent->ai_addr), result.ip, sizeof(result.ip));
109 snprintf(result.service, sizeof(result.service), "%u", ntohs(*dns_sa_port(dns_sa_family(ent->ai_addr), ent->ai_addr)));
110 memcpy(&result.info, ent, sizeof(result.info));
111 if (dns->fdh) ecore_main_fd_handler_del(dns->fdh);
113 dns->done_cb(dns->data, &result);
115 _ecore_con_dns_free(dns);
120 dns->done_cb(dns->data, NULL);
121 _ecore_con_dns_free(dns);
126 _dns_fd_cb(Ecore_Con_DNS *dns, Ecore_Fd_Handler *fdh __UNUSED__)
128 if (_ecore_con_dns_check(dns) != 1) return ECORE_CALLBACK_RENEW;
129 if (ecore_main_fd_handler_fd_get(dns->fdh) != dns_ai_pollfd(dns->ai))
131 ecore_main_fd_handler_del(dns->fdh);
132 dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL);
135 ecore_main_fd_handler_active_set(dns->fdh, dns_ai_events(dns->ai));
136 return ECORE_CALLBACK_RENEW;
140 _dns_timer_cb(Ecore_Con_DNS *dns)
142 dns->done_cb(dns->data, NULL);
143 _ecore_con_dns_free(dns);
149 ecore_con_info_init(void)
152 if (_ecore_con_dns_init) return ++_ecore_con_dns_init;
154 resconf = dns_resconf_local(&err);
157 ERR("resconf_open: %s", dns_strerror(err));
160 hosts = dns_hosts_local(&err);
163 ERR("hosts_open: %s", dns_strerror(err));
164 dns_resconf_close(resconf);
168 /* this is super slow don't do it */
169 //resconf->options.recurse = 1;
170 return ++_ecore_con_dns_init;
174 ecore_con_info_shutdown(void)
176 if (!_ecore_con_dns_init) return 0;
177 if (--_ecore_con_dns_init) return _ecore_con_dns_init;
178 dns_resconf_close(resconf);
180 dns_hosts_close(hosts);
186 ecore_con_info_data_clear(void *info)
188 Ecore_Con_DNS *dns = info;
189 if (dns) dns->data = NULL;
193 ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
194 Ecore_Con_Info_Cb done_cb,
197 struct addrinfo hints;
199 memset(&hints, 0, sizeof(struct addrinfo));
201 hints.ai_family = AF_INET6;
203 hints.ai_family = AF_INET;
205 hints.ai_socktype = SOCK_STREAM;
206 hints.ai_flags = AI_CANONNAME;
207 hints.ai_protocol = IPPROTO_TCP;
209 return ecore_con_info_get(svr, done_cb, data, &hints);
213 ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
214 Ecore_Con_Info_Cb done_cb,
217 struct addrinfo hints;
219 memset(&hints, 0, sizeof(struct addrinfo));
221 hints.ai_family = AF_INET6;
223 hints.ai_family = AF_INET;
225 hints.ai_socktype = SOCK_STREAM;
226 hints.ai_flags = AI_PASSIVE;
227 hints.ai_protocol = IPPROTO_TCP;
229 return ecore_con_info_get(svr, done_cb, data, &hints);
233 ecore_con_info_udp_connect(Ecore_Con_Server *svr,
234 Ecore_Con_Info_Cb done_cb,
237 struct addrinfo hints;
239 memset(&hints, 0, sizeof(struct addrinfo));
241 hints.ai_family = AF_INET6;
243 hints.ai_family = AF_INET;
245 hints.ai_socktype = SOCK_DGRAM;
246 hints.ai_flags = AI_CANONNAME;
247 hints.ai_protocol = IPPROTO_UDP;
249 return ecore_con_info_get(svr, done_cb, data, &hints);
253 ecore_con_info_udp_listen(Ecore_Con_Server *svr,
254 Ecore_Con_Info_Cb done_cb,
257 struct addrinfo hints;
259 memset(&hints, 0, sizeof(struct addrinfo));
261 hints.ai_family = AF_INET6;
263 hints.ai_family = AF_INET;
265 hints.ai_socktype = SOCK_DGRAM;
266 hints.ai_flags = AI_PASSIVE;
267 hints.ai_protocol = IPPROTO_UDP;
269 return ecore_con_info_get(svr, done_cb, data, &hints);
273 ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
274 Ecore_Con_Info_Cb done_cb,
277 struct addrinfo hints;
279 memset(&hints, 0, sizeof(struct addrinfo));
281 hints.ai_family = AF_INET6;
283 hints.ai_family = AF_INET;
285 hints.ai_socktype = SOCK_DGRAM;
286 hints.ai_protocol = IPPROTO_UDP;
288 return ecore_con_info_get(svr, done_cb, data, &hints);
292 ecore_con_info_get(Ecore_Con_Server *svr,
293 Ecore_Con_Info_Cb done_cb,
295 struct addrinfo *hints)
300 dns = calloc(1, sizeof(Ecore_Con_DNS));
304 dns->done_cb = done_cb;
308 memcpy(&dns->hints, hints, sizeof(struct addrinfo));
310 if (!(dns->resolv = dns_res_open(resconf, hosts, dns_hints_mortal(dns_hints_local(resconf, &error)), NULL, dns_opts(), &error)))
312 ERR("res_open: %s", dns_strerror(error));
317 error = _dns_addrinfo_get(dns, svr->ecs ? svr->ecs->ip : svr->name, dns->svr->ecs ? dns->svr->ecs->port : dns->svr->port);
318 if (error && (error != EAGAIN))
320 ERR("resolver: %s", dns_strerror(error));
324 switch (_ecore_con_dns_check(dns))
329 dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL);
330 svr->infos = eina_list_append(svr->infos, dns);
331 dns->timer = ecore_timer_add(5.0, (Ecore_Task_Cb)_dns_timer_cb, dns);
339 if (dns->resolv) dns_res_close(dns_res_mortal(dns->resolv));