Skip to content

Instantly share code, notes, and snippets.

@Mons
Created September 22, 2013 11:42
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mons/6659163 to your computer and use it in GitHub Desktop.
Save Mons/6659163 to your computer and use it in GitHub Desktop.
c-ares + libev gcc -lev -lcares async_dns.c
#include <ev.h>
#include <ares.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#define cwarn(fmt, ...) do{ \
fprintf(stderr, "[WARN] %s:%d: ", __FILE__, __LINE__); \
fprintf(stderr, fmt, ##__VA_ARGS__); \
if (fmt[strlen(fmt) - 1] != 0x0a) { fprintf(stderr, "\n"); } \
} while(0)
//#define ctx_by_t(ptr) (ctx*)( (char*)ptr - (int) &( (ctx *)0 )->t )
#define EVARES_MAXIO 8
typedef struct {
ev_io io;
ev_timer tw;
struct ev_loop * loop;
struct {
ares_channel channel;
struct ares_options options;
} ares;
struct timeval timeout;
} ev_ares;
static void io_cb (EV_P_ ev_io *w, int revents) {
cwarn("io cb");
ev_ares * eares = (ev_ares *) w;
ares_socket_t rfd = ARES_SOCKET_BAD, wfd = ARES_SOCKET_BAD;
if (revents & EV_READ)
rfd = w->fd;
if (revents & EV_WRITE)
wfd = w->fd;
ares_process_fd(eares->ares.channel, rfd, wfd);
}
static void ev_ares_sock_state_cb(void *data, int s, int read, int write) {
struct timeval *tvp, tv;
memset(&tv,0,sizeof(tv));
ev_ares * eares = (ev_ares *) data;
//if( !ev_is_active( &eares->tw ) && (tvp = ares_timeout(eares->ares.channel, &eares->timeout, &tv)) ) {
if( !ev_is_active( &eares->tw ) && (tvp = ares_timeout(eares->ares.channel, NULL, &tv)) ) {
double timeout = (double)tvp->tv_sec+(double)tvp->tv_usec/1.0e6;
cwarn("Set timeout to %0.8lf",timeout);
if (timeout > 0) {
//ev_timer_set(&eares->tw,timeout,0.);
//ev_timer_start()
}
}
cwarn("[%p] Change state fd %d read:%d write:%d; max time: %u.%u (%p)", data, s, read, write, tv.tv_sec, tv.tv_usec, tvp);
if (ev_is_active(&eares->io) && eares->io.fd != s) return;
if (read || write) {
ev_io_set( &eares->io, s, (read ? EV_READ : 0) | (write ? EV_WRITE : 0) );
ev_io_start( eares->loop, &eares->io );
}
else {
ev_io_stop(eares->loop, &eares->io);
ev_io_set( &eares->io, -1, 0);
}
}
static void
callback1(void *arg, int status, int timeouts, struct hostent *host)
{
cwarn("arg: %p",arg);
if(!host || status != ARES_SUCCESS){
printf("Failed to lookup %s\n", ares_strerror(status));
return;
}
printf("Found address name %s\n", host->h_name);
char ip[INET6_ADDRSTRLEN];
int i = 0;
for (i = 0; host->h_addr_list[i]; ++i) {
inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
printf("%s\n", ip);
}
}
// ev_gethostbyname( ev_ares * eares, char *host )
int
main(void)
{
struct ev_loop * loop = EV_DEFAULT;
ev_ares eares;
memset(&eares,0,sizeof(eares));
int status, i;
if ((status = ares_library_init(ARES_LIB_INIT_ALL) )!= ARES_SUCCESS) {
cwarn("Ares error: %s",ares_strerror(status));
return 1;
}
eares.loop = loop;
eares.ares.options.sock_state_cb_data = &eares;
eares.timeout.tv_sec = 1;
eares.timeout.tv_usec = 0;
eares.ares.options.sock_state_cb = ev_ares_sock_state_cb;
ev_init( &eares.io, io_cb );
if ( (status = ares_init_options(&eares.ares.channel, &eares.ares.options, ARES_OPT_SOCK_STATE_CB) ) != ARES_SUCCESS ) {
cwarn("Ares init error: %s",ares_strerror(status));
return 1;
}
ares_gethostbyname(eares.ares.channel, "google.com", AF_INET, callback1, NULL);
ares_gethostbyname(eares.ares.channel, "google.com", AF_INET, callback1, NULL);
ares_gethostbyname(eares.ares.channel, "google.com", AF_INET6, callback1, NULL);
ev_loop(loop,0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment