From e53bca15e7fd66aea802d657030e14ad5eb3b0d5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 12 Dec 2006 02:56:23 +0000 Subject: [PATCH] r11492@Kushana: nickm | 2006-12-11 12:30:23 -0500 Implement dns server reply retry logic. svn:r9081 --- doc/TODO | 10 ++++++---- src/or/eventdns.c | 46 +++++++++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/doc/TODO b/doc/TODO index 30cdafdb70..6a63c6b163 100644 --- a/doc/TODO +++ b/doc/TODO @@ -95,16 +95,18 @@ N - DNS improvements - Teach evdns to be able to listen for requests to be processed. . Design interface. - Rename stuff; current names suck. - . Design backend. - - Implement - . Listen for questions + o Design backend. + . Implement + o Listen for questions o Parse questions, tell user code o Let user code tell us the answer o Generate responses o Send responses to client o Queue responses when we see EAGAIN - - Retry responses after a while + o Retry responses after a while o Be efficient about labels. + - Comment everything. + - Clean up XXXX items - Test d - Be more memory-efficient - Add some kind of general question/response API so libevent can be diff --git a/src/or/eventdns.c b/src/or/eventdns.c index da4f952a4e..8fd09a1a15 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -1243,8 +1243,19 @@ server_port_read(struct evdns_server_port *s) { static void server_port_flush(struct evdns_server_port *port) { - // XXXX Writeme. - (void)port; + while (port->pending_replies) { + struct server_request *req = port->pending_replies; + int r = sendto(port->socket, req->response, req->response_len, 0, + (struct sockaddr*) &req->addr, req->addrlen); + if (r < 0) // handle errror XXXX + return; + evdns_server_request_free(req); + } + + (void) event_del(&port->event); + event_set(&port->event, port->socket, EV_READ | EV_PERSIST, + server_port_ready_callback, port); + event_add(&port->event, NULL); // handle error. XXXX } // set if we are waiting for the ability to write to this server. @@ -1671,34 +1682,43 @@ int evdns_request_respond(struct evdns_server_request *_req, int flags) { struct server_request *req = TO_SERVER_REQUEST(_req); + struct evdns_server_port *port = req->port; int r; if (!req->response) { if ((r = evdns_request_response_format(req, flags))<0) return r; } - r = sendto(req->port->socket, req->response, req->response_len, 0, + r = sendto(port->socket, req->response, req->response_len, 0, (struct sockaddr*) &req->addr, req->addrlen); if (r<0) { - int err = last_error(req->port->socket); + int err = last_error(port->socket); if (! error_is_eagain(err)) return -1; - if (req->port->pending_replies) { - req->prev_pending = req->port->pending_replies->prev_pending; - req->next_pending = req->port->pending_replies; + if (port->pending_replies) { + req->prev_pending = port->pending_replies->prev_pending; + req->next_pending = port->pending_replies; req->prev_pending->next_pending = req->next_pending->prev_pending = req; } else { req->prev_pending = req->next_pending = req; - req->port->pending_replies = req; - req->port->choaked = 1; - } - return 0; - } - // XXXX process pending replies. + port->pending_replies = req; + port->choaked = 1; + (void) event_del(&port->event); + event_set(&port->event, port->socket, EV_READ | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); + + event_add(&port->event, NULL); // handle error. XXXX + } + + return 1; + } evdns_server_request_free(req); + + if (req->port->pending_replies) + server_port_flush(port); + return 0; }