From 9c3df07b56ac2f3c1272d6234726c0b6e263e359 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Apr 2007 21:34:03 +0000 Subject: r12687@Kushana: nickm | 2007-04-09 17:05:57 -0400 Try to fix bug 410: move responsibility for attaching/detaching initial streams from circuits into dns_resolve. Needs refactoring a little. svn:r9931 --- src/or/dns.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'src/or/dns.c') diff --git a/src/or/dns.c b/src/or/dns.c index 9ca91bd76..512d2ae2e 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -509,14 +509,22 @@ parse_inaddr_arpa_address(const char *address, struct in_addr *in) * do that for us.) * * If we have a cached answer, send the answer back along exitconn's - * attached circuit. + * circuit. * * Else, if seen before and pending, add conn to the pending list, * and return 0. * * Else, if not seen before, add conn to pending list, hand to * dns farm, and return 0. + * + * Exitconn's on_circuit field must be set, but exitconn should not + * yet be linked onto the n_streams/resolving_streams list of that circuit. + * On success, link the connection to n_streams if it's an exit connection. + * On "pending", link the connection to resolving streams. Otherwise, + * clear its on_circuit field. */ +/* XXXX020 Split this into a helper that checks whether there is an answer, + * and a caller that takes appropriate action based on what happened. */ int dns_resolve(edge_connection_t *exitconn) { @@ -530,6 +538,7 @@ dns_resolve(edge_connection_t *exitconn) assert_connection_ok(TO_CONN(exitconn), 0); tor_assert(exitconn->_base.s == -1); assert_cache_ok(); + tor_assert(oncirc); is_resolve = exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE; @@ -538,8 +547,12 @@ dns_resolve(edge_connection_t *exitconn) if (tor_inet_aton(exitconn->_base.address, &in) != 0) { exitconn->_base.addr = ntohl(in.s_addr); exitconn->address_ttl = DEFAULT_DNS_TTL; - if (is_resolve) + if (is_resolve) { send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); + } else { + exitconn->next_stream = oncirc->n_streams; + oncirc->n_streams = exitconn; + } return 1; } if (address_is_invalid_destination(exitconn->_base.address, 0)) { @@ -548,7 +561,8 @@ dns_resolve(edge_connection_t *exitconn) escaped_safe_str(exitconn->_base.address)); if (is_resolve) send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); - circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + //circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + exitconn->on_circuit = NULL; if (!exitconn->_base.marked_for_close) connection_free(TO_CONN(exitconn)); return -1; @@ -581,7 +595,8 @@ dns_resolve(edge_connection_t *exitconn) if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); - circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + //circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + exitconn->on_circuit = NULL; if (!exitconn->_base.marked_for_close) connection_free(TO_CONN(exitconn)); return -1; @@ -606,6 +621,9 @@ dns_resolve(edge_connection_t *exitconn) "resolve of %s", exitconn->_base.s, escaped_safe_str(exitconn->_base.address)); exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; + + exitconn->next_stream = oncirc->resolving_streams; + oncirc->resolving_streams = exitconn; return 0; case CACHE_STATE_CACHED_VALID: log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", @@ -621,6 +639,12 @@ dns_resolve(edge_connection_t *exitconn) if (is_resolve) send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); } + if (!is_resolve) { + /* It's a connect; add it into the linked list of n_streams on this + circuit */ + exitconn->next_stream = oncirc->n_streams; + oncirc->n_streams = exitconn; + } return 1; case CACHE_STATE_CACHED_FAILED: log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", @@ -628,7 +652,8 @@ dns_resolve(edge_connection_t *exitconn) escaped_safe_str(exitconn->_base.address)); if (is_resolve) send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); - circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + // circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); + exitconn->on_circuit = NULL; if (!exitconn->_base.marked_for_close) connection_free(TO_CONN(exitconn)); return -1; @@ -658,7 +683,18 @@ dns_resolve(edge_connection_t *exitconn) log_debug(LD_EXIT,"Launching %s.", escaped_safe_str(exitconn->_base.address)); assert_cache_ok(); - return launch_resolve(exitconn); + + r = launch_resolve(exitconn); + if (r == 0) { + exitconn->next_stream = oncirc->resolving_streams; + oncirc->resolving_streams = exitconn; + } else { + tor_assert(r<0); + exitconn->on_circuit = NULL; + if (!exitconn->_base.marked_for_close) + connection_free(TO_CONN(exitconn)); + } + return r; } /** Log an error and abort if conn is waiting for a DNS resolve. @@ -1160,7 +1196,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, } /** For eventdns: start resolving as necessary to find the target for - * exitconn */ + * exitconn. Returns -1 on error, 0 on "resolve launched." */ static int launch_resolve(edge_connection_t *exitconn) { -- cgit v1.2.3