]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/c-ares-dns/serv_c-ares-dns.c
libev/c-ares migration: unstack out ouf c-ares before querying new requests
[citadel.git] / citadel / modules / c-ares-dns / serv_c-ares-dns.c
index ae26751b068da5db78985235d1c61bca1c6e414d..de124f64b2191c4776785dcad3cfc42e2c447ee1 100644 (file)
@@ -59,8 +59,6 @@
 
 
 extern struct ev_loop *event_base;
-struct ares_options options;
-ares_channel Channel;
 
 void SockStateCb(void *data, int sock, int read, int write);
 
@@ -209,7 +207,6 @@ static void ParseAnswerTXT(AsyncIO *IO, unsigned char* abuf, int alen)
        IO->DNSReplyFree = (FreeDNSReply) ares_free_data;
 }
 
-
 void QueryCb(void *arg,
             int status,
             int timeouts,
@@ -221,23 +218,38 @@ void QueryCb(void *arg,
        IO->DNSStatus = status;
        if (status == ARES_SUCCESS)
                IO->DNS_CB(arg, abuf, alen);
-       IO->PostDNS(IO);
+       else
+               IO->DNSStatus = status;
+///    ev_io_stop(event_base, &IO->dns_io_event);
+       
+       ev_timer_init(&IO->unwind_stack_timeout,
+                     IO_postdns_callback, 0.0, 0);
+       IO->unwind_stack_timeout.data = IO;
+       ev_timer_start(event_base, &IO->unwind_stack_timeout);
 }
 
-int QueueQuery(ns_type Type, char *name, AsyncIO *IO, IO_CallBack PostDNS)
+void QueryCbDone(AsyncIO *IO)
 {
-       int length, family;
-       char address_b[sizeof(struct in6_addr)];
-       int optmask = 0;
-       fd_set rfd, wfd;
+       ev_timer_stop(event_base, &IO->unwind_stack_timeout);
+}
 
+
+void InitC_ares_dns(AsyncIO *IO)
+{
+       int optmask = 0;
        if (IO->DNSChannel == NULL) {
                optmask |= ARES_OPT_SOCK_STATE_CB;
                IO->DNSOptions.sock_state_cb = SockStateCb;
                IO->DNSOptions.sock_state_cb_data = IO;
                ares_init_options(&IO->DNSChannel, &IO->DNSOptions, optmask);
        }
+}
+int QueueQuery(ns_type Type, char *name, AsyncIO *IO, IO_CallBack PostDNS)
+{
+       int length, family;
+       char address_b[sizeof(struct in6_addr)];
 
+       InitC_ares_dns(IO);
        IO->PostDNS = PostDNS;
        switch(Type) {
        case ns_t_a:
@@ -289,70 +301,85 @@ int QueueQuery(ns_type Type, char *name, AsyncIO *IO, IO_CallBack PostDNS)
                return 0;
        }
        ares_query(IO->DNSChannel, name, ns_c_in, Type, QueryCb, IO);
-       ares_fds(IO->DNSChannel, &rfd, &wfd);
        return 1;
 }
 
-static void DNS_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents)
+static void DNS_send_callback(struct ev_loop *loop, ev_io *watcher, int revents)
 {
        AsyncIO *IO = watcher->data;
        
-       ares_process_fd(IO->DNSChannel, IO->sock, 0);
+       ares_process_fd(IO->DNSChannel, ARES_SOCKET_BAD, IO->dns_send_event.fd);
 }
-
-static void DNS_send_callback(struct ev_loop *loop, ev_io *watcher, int revents)
+static void DNS_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents)
 {
        AsyncIO *IO = watcher->data;
        
-       ares_process_fd(IO->DNSChannel, 0, IO->sock);
+       ares_process_fd(IO->DNSChannel, IO->dns_recv_event.fd, ARES_SOCKET_BAD);
 }
 
 void SockStateCb(void *data, int sock, int read, int write) 
 {
+/*
        struct timeval tvbuf, maxtv, *ret;
        
        int64_t time = 10;
+*/
        AsyncIO *IO = data;
 /* already inside of the event queue. */       
-       IO->sock = sock;
-       ev_io_init(&IO->recv_event, DNS_recv_callback, IO->sock, EV_READ);
-       IO->recv_event.data = IO;
-       ev_io_init(&IO->send_event, DNS_send_callback, IO->sock, EV_WRITE);
-       IO->send_event.data = IO;
-       if (write)
-               ev_io_start(event_base, &IO->send_event);
-       else
-               ev_io_start(event_base, &IO->recv_event);
-       
 
-       maxtv.tv_sec = time/1000;
-       maxtv.tv_usec = (time % 1000) * 1000;
-
-       ret = ares_timeout(IO->DNSChannel, &maxtv, &tvbuf);
+       if (read) {
+               if ((IO->dns_recv_event.fd != sock) &&
+                   (IO->dns_recv_event.fd != 0) && 
+                   ((IO->active_dns_event & EV_READ) != 0)) {
+                       ev_io_stop(event_base, &IO->dns_recv_event);
+               }
+               IO->dns_recv_event.fd = sock;
+               ev_io_init(&IO->dns_recv_event, DNS_recv_callback, IO->dns_recv_event.fd, EV_READ);
+               IO->dns_recv_event.data = IO;
+               ev_io_start(event_base, &IO->dns_recv_event);
+               IO->active_dns_event = IO->active_dns_event | EV_READ;
+       } 
+       if (write) {
+               if ((IO->dns_send_event.fd != sock) &&
+                   (IO->dns_send_event.fd != 0) && 
+                   ((IO->active_dns_event & EV_WRITE) != 0)) {
+                       ev_io_stop(event_base, &IO->dns_send_event);
+               }
+               IO->dns_send_event.fd = sock;
+               ev_io_init(&IO->dns_send_event, DNS_send_callback, IO->dns_send_event.fd, EV_WRITE);
+               IO->dns_send_event.data = IO;
+               ev_io_start(event_base, &IO->dns_send_event);
+               IO->active_dns_event = IO->active_dns_event | EV_WRITE;
+       }
+/*
 
+               ev_io_start(event_base, &IO->dns_io_event);
        
+               maxtv.tv_sec = time/1000;
+               maxtv.tv_usec = (time % 1000) * 1000;
+               
+               ret = ares_timeout(IO->DNSChannel, &maxtv, &tvbuf);
+       }
+*/
+       if ((read == 0) && (write == 0)) {
+               if ((IO->active_dns_event & EV_READ) != 0)
+                       ev_io_stop(event_base, &IO->dns_recv_event);
+               if ((IO->active_dns_event & EV_WRITE) != 0)
+                       ev_io_stop(event_base, &IO->dns_send_event);
+               IO->active_dns_event = 0;
+       }
 }
 
 CTDL_MODULE_INIT(c_ares_client)
 {
        if (!threading)
        {
-               int optmask = 0;
-               
-
                int r = ares_library_init(ARES_LIB_INIT_ALL);
                if (0 != r) {
                        // TODO
                        // ThrowException(Exception::Error(String::New(ares_strerror(r))));
 ////                   assert(r == 0);
                }
-
-               optmask |= ARES_OPT_SOCK_STATE_CB;
-               memset(&options, 0, sizeof(struct ares_options));
-               options.sock_state_cb = SockStateCb;
-               
-               ares_init_options(&Channel, &options, optmask);
-
        }
        return "c-ares";
 }