]> granicus.if.org Git - libevent/commitdiff
Fix evdns_cancel to alert callback and free associated RAM.
authorNick Mathewson <nickm@torproject.org>
Mon, 6 Apr 2009 20:38:19 +0000 (20:38 +0000)
committerNick Mathewson <nickm@torproject.org>
Mon, 6 Apr 2009 20:38:19 +0000 (20:38 +0000)
Also, we add a test to make sure evdns_cancel is working properly.

svn:r1139

evdns.c
include/event2/dns.h
test/regress_dns.c

diff --git a/evdns.c b/evdns.c
index bd8dbf3f273577f116aba9b937b8d49b5239b556..18e4b122bf048ea6ee0bf0010cc8d48654198859 100644 (file)
--- a/evdns.c
+++ b/evdns.c
@@ -595,15 +595,19 @@ request_trans_id_set(struct evdns_request *const req, const u16 trans_id) {
 static void
 request_finished(struct evdns_request *const req, struct evdns_request **head) {
        struct evdns_base *base = req->base;
+       int was_inflight = (head != &base->req_waiting_head);
        if (head)
                evdns_request_remove(req, head);
 
        log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx",
            (unsigned long) req);
-       evtimer_del(&req->timeout_event);
-
        search_request_finished(req);
-       base->global_requests_inflight--;
+       if (was_inflight) {
+               evtimer_del(&req->timeout_event);
+               base->global_requests_inflight--;
+       } else {
+               base->global_requests_waiting--;
+       }
 
        if (!req->request_appended) {
                /* need to free the request data on it's own */
@@ -2471,15 +2475,16 @@ request_submit(struct evdns_request *const req) {
 void
 evdns_cancel_request(struct evdns_base *base, struct evdns_request *req)
 {
-        /* XXX Does anything ever free the request */
+       if (!base)
+               base = req->base;
+
+       reply_callback(req, 0, DNS_ERR_CANCEL, NULL);
        if (req->ns) {
                /* remove from inflight queue */
-               evdns_request_remove(req, &REQ_HEAD(base, req->trans_id));
-               --base->global_requests_inflight;
+               request_finished(req, &REQ_HEAD(base, req->trans_id));
        } else {
                /* remove from global_waiting head */
-               evdns_request_remove(req, &base->req_waiting_head);
-               --base->global_requests_waiting;
+               request_finished(req, &base->req_waiting_head);
        }
 }
 
@@ -3374,6 +3379,7 @@ evdns_err_to_string(int err)
        case DNS_ERR_UNKNOWN: return "unknown";
        case DNS_ERR_TIMEOUT: return "request timed out";
        case DNS_ERR_SHUTDOWN: return "dns subsystem shut down";
+       case DNS_ERR_CANCEL: return "dns request canceled";
        default: return "[Unknown error code]";
     }
 }
index 7920c3e9f79870276e66777dc4c6aeb49ace802d..28f5c80b502481f86be2bcffc58ade150c4ff92e 100644 (file)
@@ -187,8 +187,10 @@ extern "C" {
 #define DNS_ERR_UNKNOWN 66
 /** Communication with the server timed out */
 #define DNS_ERR_TIMEOUT 67
-/** The request was canceled because the DNS subsystem was shut down. */
+/** The request was cancelled because the DNS subsystem was shut down. */
 #define DNS_ERR_SHUTDOWN 68
+/** The request was cancelled via a call to evdns_cancel_request */
+#define DNS_ERR_CANCEL 69
 
 #define DNS_IPv4_A 1
 #define DNS_PTR 2
index 02a46ceb4d0fe1b8b5ffad82a7f054cf9998afd0..09994b90a20c2a49fe18a89b86c430ba54440b0e 100644 (file)
@@ -66,6 +66,7 @@
 #include "regress.h"
 
 static int dns_ok = 0;
+static int dns_got_cancel = 0;
 static int dns_err = 0;
 
 static void
@@ -244,6 +245,12 @@ dns_server_request_cb(struct evdns_server_request *req, void *data)
                                                                                                   "ZZ.EXAMPLE.COM", 54321);
                        if (r<0)
                                dns_ok = 0;
+                } else if (req->questions[i]->type == EVDNS_TYPE_A &&
+                   req->questions[i]->dns_question_class == EVDNS_CLASS_INET &&
+                   !strcasecmp(req->questions[i]->name, "drop.example.com")) {
+                       if (evdns_server_request_drop(req)<0)
+                               dns_ok = 0;
+                       return;
                } else {
                        fprintf(stdout, "Unexpected question %d %d \"%s\" ",
                                        req->questions[i]->type,
@@ -261,8 +268,16 @@ dns_server_request_cb(struct evdns_server_request *req, void *data)
 
 static void
 dns_server_gethostbyname_cb(int result, char type, int count, int ttl,
-                                                       void *addresses, void *arg)
+    void *addresses, void *arg)
 {
+       if (result == DNS_ERR_CANCEL) {
+               if (arg != (void*)(char*)90909) {
+                       fprintf(stdout, "Unexpected cancelation");
+                       dns_ok = 0;
+               }
+               dns_got_cancel = 1;
+               goto out;
+       }
        if (result != DNS_ERR_NONE) {
                fprintf(stdout, "Unexpected result %d. ", result);
                dns_ok = 0;
@@ -326,14 +341,18 @@ dns_server(void)
        struct sockaddr_in my_addr;
        struct evdns_server_port *port=NULL;
        struct in_addr resolve_addr;
+       struct evdns_base *base=NULL;
+       struct evdns_request *req=NULL;
 
        dns_ok = 1;
 
+       base = evdns_base_new(NULL, 0);
+
        /* Add ourself as the only nameserver, and make sure we really are
         * the only nameserver. */
-       evdns_nameserver_ip_add("127.0.0.1:35353");
+       evdns_base_nameserver_ip_add(base, "127.0.0.1:35353");
 
-       tt_int_op(evdns_count_nameservers(), ==, 1);
+       tt_int_op(evdns_base_count_nameservers(base), ==, 1);
        /* Now configure a nameserver port. */
        sock = socket(AF_INET, SOCK_DGRAM, 0);
         if (sock<=0) {
@@ -351,17 +370,23 @@ dns_server(void)
        }
        port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);
 
-       /* Send two queries. */
-       evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH,
+       /* Send some queries. */
+       evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
                                           dns_server_gethostbyname_cb, NULL);
-       evdns_resolve_ipv6("zz.example.com", DNS_QUERY_NO_SEARCH,
+       evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
                                           dns_server_gethostbyname_cb, NULL);
        resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
-       evdns_resolve_reverse(&resolve_addr, 0,
+       evdns_base_resolve_reverse(base, &resolve_addr, 0,
             dns_server_gethostbyname_cb, NULL);
+       req = evdns_base_resolve_ipv4(base,
+           "drop.example.com", DNS_QUERY_NO_SEARCH,
+           dns_server_gethostbyname_cb, (void*)(char*)90909);
+
+       evdns_cancel_request(base, req);
 
        event_dispatch();
 
+       tt_assert(dns_got_cancel);
         test_ok = dns_ok;
 
 end:
@@ -370,6 +395,8 @@ end:
        evdns_shutdown(0); /* remove ourself as nameserver. */
         if (sock >= 0)
                 EVUTIL_CLOSESOCKET(sock);
+       if (base)
+               evdns_base_free(base, 0);
 }