summaryrefslogtreecommitdiff
path: root/src/or/connection.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-01-27 08:55:06 +0000
committerNick Mathewson <nickm@torproject.org>2007-01-27 08:55:06 +0000
commit9984cad6e86d65f4685fd1283bf1f1b4a4602f22 (patch)
treece97ea208a1650414535881a16c5dce4dab40f87 /src/or/connection.c
parent2525c44d176feb5227910ccc63e39622774086dc (diff)
downloadtor-9984cad6e86d65f4685fd1283bf1f1b4a4602f22.tar.gz
tor-9984cad6e86d65f4685fd1283bf1f1b4a4602f22.zip
r11552@catbus: nickm | 2007-01-27 03:55:02 -0500
This one is a little tricky. Our BEGIN_DIR implementation has a problem: the dirserv conns will decide they can flush all their data immediately, since the edge_conns will read greedily. For our 0.1.2 workaround, we track which or_conn a bridged dirserv conn is attached to, and stop writing when its outbuf is too full, and start writing again when the or_conn's outbuf empties out a little. This requires a bit of pointer management. Let's hope it works. svn:r9432
Diffstat (limited to 'src/or/connection.c')
-rw-r--r--src/or/connection.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index 188bfc75ee..f1962d9614 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -426,6 +426,10 @@ connection_about_to_close_connection(connection_t *conn)
}
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
rend_client_desc_here(dir_conn->rend_query); /* give it a try */
+ /* If this is from BEGIN_DIR, unlink it from the edge_conn and
+ * the or_conn. */
+ if (dir_conn->bridge_conn)
+ connection_dirserv_unlink_from_bridge(dir_conn);
break;
case CONN_TYPE_OR:
or_conn = TO_OR_CONN(conn);
@@ -452,6 +456,13 @@ connection_about_to_close_connection(connection_t *conn)
control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
control_tls_error_to_reason(or_conn->tls_error));
}
+ /* Remove any dir_conns that are blocked on this one. Non-blocked
+ * ones will die when the circuits do. */
+ while (or_conn->blocked_dir_connections) {
+ dir_connection_t *dir_conn = or_conn->blocked_dir_connections;
+ connection_dirserv_unlink_from_bridge(dir_conn);
+ tor_assert(or_conn->blocked_dir_connections != dir_conn);
+ }
/* Now close all the attached circuits on it. */
circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
END_CIRC_REASON_OR_CONN_CLOSED);
@@ -485,6 +496,9 @@ connection_about_to_close_connection(connection_t *conn)
if (conn->state == EXIT_CONN_STATE_RESOLVING) {
connection_dns_remove(edge_conn);
}
+ /* If we're relaying a dirserv connection, clean up any pointers */
+ if (edge_conn->bridge_for_conn)
+ connection_dirserv_unlink_from_bridge(edge_conn->bridge_for_conn);
break;
case CONN_TYPE_DNSWORKER:
if (conn->state == DNSWORKER_STATE_BUSY) {
@@ -2243,6 +2257,8 @@ connection_flushed_some(connection_t *conn)
if (conn->type == CONN_TYPE_DIR &&
conn->state == DIR_CONN_STATE_SERVER_WRITING)
return connection_dirserv_flushed_some(TO_DIR_CONN(conn));
+ else if (conn->type == CONN_TYPE_OR)
+ return connection_or_flushed_some(TO_OR_CONN(conn));
else
return 0;
}
@@ -2425,7 +2441,35 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
conn->purpose == EXIT_PURPOSE_RESOLVE);
}
- } else if (conn->type != CONN_TYPE_DIR) {
+ if (edge_conn->bridge_for_conn) {
+ tor_assert(conn->type == CONN_TYPE_EXIT);
+ tor_assert(edge_conn->bridge_for_conn->bridge_conn == edge_conn);
+ }
+ } else if (conn->type == CONN_TYPE_DIR) {
+ dir_connection_t *dir_conn = TO_DIR_CONN(conn);
+
+ if (dir_conn->bridge_conn) {
+ tor_assert(DIR_CONN_IS_SERVER(conn));
+ tor_assert(dir_conn->bridge_conn->bridge_for_conn == dir_conn);
+ if (dir_conn->bridge_conn->on_circuit) {
+ dir_connection_t *d;
+ or_connection_t *or_conn;
+ tor_assert(!CIRCUIT_IS_ORIGIN(dir_conn->bridge_conn->on_circuit));
+ or_conn = TO_OR_CIRCUIT(dir_conn->bridge_conn->on_circuit)->p_conn;
+ if (dir_conn->is_blocked_on_or_conn)
+ tor_assert(or_conn);
+ for (d = or_conn->blocked_dir_connections; d;
+ d = d->next_blocked_on_same_or_conn) {
+ if (d == dir_conn) {
+ tor_assert(dir_conn->is_blocked_on_or_conn == 1);
+ break;
+ }
+ }
+ if (!d)
+ tor_assert(!dir_conn->is_blocked_on_or_conn);
+ }
+ }
+ } else {
/* Purpose is only used for dir and exit types currently */
tor_assert(!conn->purpose);
}