Fix evdns_cancel to alert callback and free associated RAM.

Also, we add a test to make sure evdns_cancel is working properly.

svn:r1139
This commit is contained in:
Nick Mathewson 2009-04-06 20:38:19 +00:00
parent 0f3c0983c0
commit d2e9caa6fc
3 changed files with 51 additions and 16 deletions

22
evdns.c
View File

@ -595,15 +595,19 @@ request_trans_id_set(struct evdns_request *const req, const u16 trans_id) {
static void static void
request_finished(struct evdns_request *const req, struct evdns_request **head) { request_finished(struct evdns_request *const req, struct evdns_request **head) {
struct evdns_base *base = req->base; struct evdns_base *base = req->base;
int was_inflight = (head != &base->req_waiting_head);
if (head) if (head)
evdns_request_remove(req, head); evdns_request_remove(req, head);
log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx", log(EVDNS_LOG_DEBUG, "Removing timeout for request %lx",
(unsigned long) req); (unsigned long) req);
evtimer_del(&req->timeout_event);
search_request_finished(req); 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) { if (!req->request_appended) {
/* need to free the request data on it's own */ /* need to free the request data on it's own */
@ -2471,15 +2475,16 @@ request_submit(struct evdns_request *const req) {
void void
evdns_cancel_request(struct evdns_base *base, struct evdns_request *req) 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) { if (req->ns) {
/* remove from inflight queue */ /* remove from inflight queue */
evdns_request_remove(req, &REQ_HEAD(base, req->trans_id)); request_finished(req, &REQ_HEAD(base, req->trans_id));
--base->global_requests_inflight;
} else { } else {
/* remove from global_waiting head */ /* remove from global_waiting head */
evdns_request_remove(req, &base->req_waiting_head); request_finished(req, &base->req_waiting_head);
--base->global_requests_waiting;
} }
} }
@ -3374,6 +3379,7 @@ evdns_err_to_string(int err)
case DNS_ERR_UNKNOWN: return "unknown"; case DNS_ERR_UNKNOWN: return "unknown";
case DNS_ERR_TIMEOUT: return "request timed out"; case DNS_ERR_TIMEOUT: return "request timed out";
case DNS_ERR_SHUTDOWN: return "dns subsystem shut down"; case DNS_ERR_SHUTDOWN: return "dns subsystem shut down";
case DNS_ERR_CANCEL: return "dns request canceled";
default: return "[Unknown error code]"; default: return "[Unknown error code]";
} }
} }

View File

@ -187,8 +187,10 @@ extern "C" {
#define DNS_ERR_UNKNOWN 66 #define DNS_ERR_UNKNOWN 66
/** Communication with the server timed out */ /** Communication with the server timed out */
#define DNS_ERR_TIMEOUT 67 #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 #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_IPv4_A 1
#define DNS_PTR 2 #define DNS_PTR 2

View File

@ -66,6 +66,7 @@
#include "regress.h" #include "regress.h"
static int dns_ok = 0; static int dns_ok = 0;
static int dns_got_cancel = 0;
static int dns_err = 0; static int dns_err = 0;
static void static void
@ -244,6 +245,12 @@ dns_server_request_cb(struct evdns_server_request *req, void *data)
"ZZ.EXAMPLE.COM", 54321); "ZZ.EXAMPLE.COM", 54321);
if (r<0) if (r<0)
dns_ok = 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 { } else {
fprintf(stdout, "Unexpected question %d %d \"%s\" ", fprintf(stdout, "Unexpected question %d %d \"%s\" ",
req->questions[i]->type, req->questions[i]->type,
@ -261,8 +268,16 @@ dns_server_request_cb(struct evdns_server_request *req, void *data)
static void static void
dns_server_gethostbyname_cb(int result, char type, int count, int ttl, 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) { if (result != DNS_ERR_NONE) {
fprintf(stdout, "Unexpected result %d. ", result); fprintf(stdout, "Unexpected result %d. ", result);
dns_ok = 0; dns_ok = 0;
@ -326,14 +341,18 @@ dns_server(void)
struct sockaddr_in my_addr; struct sockaddr_in my_addr;
struct evdns_server_port *port=NULL; struct evdns_server_port *port=NULL;
struct in_addr resolve_addr; struct in_addr resolve_addr;
struct evdns_base *base=NULL;
struct evdns_request *req=NULL;
dns_ok = 1; dns_ok = 1;
base = evdns_base_new(NULL, 0);
/* Add ourself as the only nameserver, and make sure we really are /* Add ourself as the only nameserver, and make sure we really are
* the only nameserver. */ * 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. */ /* Now configure a nameserver port. */
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock<=0) { if (sock<=0) {
@ -351,17 +370,23 @@ dns_server(void)
} }
port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);
/* Send two queries. */ /* Send some queries. */
evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH, evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
dns_server_gethostbyname_cb, NULL); 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); dns_server_gethostbyname_cb, NULL);
resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ 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); 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(); event_dispatch();
tt_assert(dns_got_cancel);
test_ok = dns_ok; test_ok = dns_ok;
end: end:
@ -370,6 +395,8 @@ end:
evdns_shutdown(0); /* remove ourself as nameserver. */ evdns_shutdown(0); /* remove ourself as nameserver. */
if (sock >= 0) if (sock >= 0)
EVUTIL_CLOSESOCKET(sock); EVUTIL_CLOSESOCKET(sock);
if (base)
evdns_base_free(base, 0);
} }