summaryrefslogtreecommitdiff
path: root/trunk/src
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src')
-rw-r--r--trunk/src/or/circuituse.c35
-rw-r--r--trunk/src/or/connection_edge.c1
-rw-r--r--trunk/src/or/or.h2
-rw-r--r--trunk/src/or/relay.c18
4 files changed, 47 insertions, 9 deletions
diff --git a/trunk/src/or/circuituse.c b/trunk/src/or/circuituse.c
index b6ceafd700..0c7198a7bf 100644
--- a/trunk/src/or/circuituse.c
+++ b/trunk/src/or/circuituse.c
@@ -963,10 +963,16 @@ circuit_get_open_circ_or_launch(connection_t *conn,
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
routerinfo_t *r;
+ int opt = conn->chosen_exit_optional;
if (!(r = router_get_by_nickname(conn->chosen_exit_name, 1))) {
- log_notice(LD_APP,
- "Requested exit point '%s' is not known. Closing.",
- conn->chosen_exit_name);
+ log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
+ "Requested exit point '%s' is not known. %s.",
+ conn->chosen_exit_name, opt ? "Trying others" : "Closing");
+ if (opt) {
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ return 0;
+ }
return -1;
}
extend_info = extend_info_from_router(r);
@@ -1151,16 +1157,27 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
if (conn->chosen_exit_name) {
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ int opt = conn->chosen_exit_optional;
if (!router) {
- log_warn(LD_APP,
- "Requested exit point '%s' is not known. Closing.",
- conn->chosen_exit_name);
+ log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
+ "Requested exit point '%s' is not known. %s.",
+ conn->chosen_exit_name, opt ? "Trying others" : "Closing");
+ if (opt) {
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ return 0;
+ }
return -1;
}
if (!connection_ap_can_use_exit(conn, router)) {
- log_warn(LD_APP,
- "Requested exit point '%s' would refuse request. Closing.",
- conn->chosen_exit_name);
+ log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
+ "Requested exit point '%s' would refuse request. %s.",
+ conn->chosen_exit_name, opt ? "Trying others" : "Closing");
+ if (opt) {
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ return 0;
+ }
return -1;
}
}
diff --git a/trunk/src/or/connection_edge.c b/trunk/src/or/connection_edge.c
index 41948e055c..45620e2a3b 100644
--- a/trunk/src/or/connection_edge.c
+++ b/trunk/src/or/connection_edge.c
@@ -1126,6 +1126,7 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn,
routers with this nickname */
conn->chosen_exit_name =
tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+ conn->chosen_exit_optional = 1;
}
}
diff --git a/trunk/src/or/or.h b/trunk/src/or/or.h
index 5700221fa1..ff3a26e65b 100644
--- a/trunk/src/or/or.h
+++ b/trunk/src/or/or.h
@@ -656,6 +656,8 @@ struct connection_t {
/** Nickname of planned exit node -- used with .exit support. */
char *chosen_exit_name;
+ /** If 1, and we fail to reach the chosen exit, stop requiring it. */
+ unsigned int chosen_exit_optional:1;
/* Used only by OR connections: */
tor_tls_t *tls; /**< TLS connection state (OR only.) */
diff --git a/trunk/src/or/relay.c b/trunk/src/or/relay.c
index 95b999c726..7dc7d3b7b5 100644
--- a/trunk/src/or/relay.c
+++ b/trunk/src/or/relay.c
@@ -696,11 +696,21 @@ connection_edge_process_end_not_open(
/* rewrite it to an IP if we learned one. */
addressmap_rewrite(conn->socks_request->address,
sizeof(conn->socks_request->address));
+ if (conn->chosen_exit_optional) { /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, conn will get closed below */
break;
+ case END_STREAM_REASON_CONNECTREFUSED:
+ if (!conn->chosen_exit_optional)
+ break; /* break means it'll close, below */
+ /* Else fall through: expire this circuit, clear the
+ * chosen_exit_name field, and try again. */
case END_STREAM_REASON_RESOLVEFAILED:
+ case END_STREAM_REASON_TIMEOUT:
case END_STREAM_REASON_MISC:
if (client_dns_incr_failures(conn->socks_request->address)
< MAX_RESOLVE_FAILURES) {
@@ -709,6 +719,10 @@ connection_edge_process_end_not_open(
tor_assert(circ->timestamp_dirty);
circ->timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ if (conn->chosen_exit_optional) { /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, conn will get closed below */
@@ -729,6 +743,10 @@ connection_edge_process_end_not_open(
exitrouter->exit_policy =
router_parse_addr_policy_from_string("reject *:*", -1);
}
+ if (conn->chosen_exit_optional) { /* stop wanting a specific exit */
+ conn->chosen_exit_optional = 0;
+ tor_free(conn->chosen_exit_name);
+ }
if (connection_ap_detach_retriable(conn, circ) >= 0)
return 0;
/* else, will close below */