Catch and report a few more bootstrapping failure cases when Tor

fails to establish a TCP connection. Cleanup on 0.2.1.x.


svn:r16803
This commit is contained in:
Roger Dingledine 2008-09-09 06:25:39 +00:00
parent aacda9cd8e
commit d37fae2f4e
6 changed files with 42 additions and 25 deletions

View File

@ -1,10 +1,12 @@
Changes in version 0.2.1.6-alpha - 2008-09-xx
o Major bugfixes:
- Fix a bug when parsing ports in tor_addr_port_parse() that caused
Tor to fail to start if you had it configured to use a bridge
relay. Fixes bug 809. Bugfix on 0.2.1.5-alpha.
o Minor bugfixes:
- Fix compile on OpenBSD 4.4-current. Bugfix on 0.2.1.5-alpha.
Reported by Tas.
- When parsing ports in tor_addr_port_parse(), yield the port if
the port variable is provided, not just if it's nonzero. Fixes
bug 809. Bugfix on 0.2.1.5-alpha.
- Fixed some memory leaks --some quite frequent, some almost impossible
to trigger-- based on results of a static analysis tool. (XXX Can we
say which? -NM)
@ -12,6 +14,8 @@ Changes in version 0.2.1.6-alpha - 2008-09-xx
correctly. (Found by Riastradh.)
- Fix an assertion bug in parsing policy-related options; possible fix
for bug 811.
- Catch and report a few more bootstrapping failure cases when Tor
fails to establish a TCP connection. Cleanup on 0.2.1.x.
o Minor features:
- Use a lockfile to make sure that two Tor processes are not

View File

@ -756,9 +756,6 @@ circuit_build_failed(origin_circuit_t *circ)
"(%s:%d). I'm going to try to rotate to a better connection.",
n_conn->_base.address, n_conn->_base.port);
n_conn->_base.or_is_obsolete = 1;
if (n_conn->_base.state < OR_CONN_STATE_TLS_HANDSHAKING &&
!n_conn->socket_error)
n_conn->socket_error = END_OR_CONN_REASON_TIMEOUT;
entry_guard_register_connect_status(n_conn->identity_digest, 0,
time(NULL));
}

View File

@ -547,14 +547,7 @@ connection_about_to_close_connection(connection_t *conn)
entry_guard_register_connect_status(or_conn->identity_digest,0,now);
if (!options->HttpsProxy)
router_set_status(or_conn->identity_digest, 0);
if (conn->state == OR_CONN_STATE_CONNECTING) {
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
errno_to_orconn_end_reason(or_conn->socket_error));
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_problem(
tor_socket_strerror(or_conn->socket_error),
errno_to_orconn_end_reason(or_conn->socket_error));
} else {
if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
reason);
@ -1947,8 +1940,13 @@ loop_again:
before = buf_datalen(conn->inbuf);
if (connection_read_to_buf(conn, &max_to_read) < 0) {
/* There's a read error; kill the connection.*/
if (conn->type == CONN_TYPE_OR)
TO_OR_CONN(conn)->socket_error = tor_socket_errno(conn->s);
if (conn->type == CONN_TYPE_OR &&
conn->state == OR_CONN_STATE_CONNECTING) {
int socket_error = tor_socket_errno(conn->s);
connection_or_connect_failed(TO_OR_CONN(conn),
errno_to_orconn_end_reason(socket_error),
tor_socket_strerror(socket_error));
}
if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
connection_edge_end_errno(edge_conn);
@ -2254,7 +2252,9 @@ connection_handle_write(connection_t *conn, int force)
if (CONN_IS_EDGE(conn))
connection_edge_end_errno(TO_EDGE_CONN(conn));
if (conn->type == CONN_TYPE_OR)
TO_OR_CONN(conn)->socket_error = e;
connection_or_connect_failed(TO_OR_CONN(conn),
errno_to_orconn_end_reason(e),
tor_socket_strerror(e));
connection_close_immediate(conn);
connection_mark_for_close(conn);

View File

@ -492,6 +492,21 @@ connection_or_get_by_identity_digest(const char *digest)
return best;
}
/** <b>conn</b> is in the 'connecting' state, and it failed to complete
* a TCP connection. Send notifications appropriately.
*
* <b>reason</b> specifies the or_conn_end_reason for the failure;
* <b>msg</b> specifies the strerror-style error message.
*/
void
connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg)
{
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
if (!authdir_mode_tests_reachability(get_options()))
control_event_bootstrap_problem(msg, reason);
}
/** Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to
* handshake with an OR with identity digest <b>id_digest</b>.
*
@ -548,11 +563,9 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
time(NULL));
router_set_status(conn->identity_digest, 0);
}
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
errno_to_orconn_end_reason(socket_error));
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_problem(tor_socket_strerror(socket_error),
errno_to_orconn_end_reason(socket_error));
connection_or_connect_failed(conn,
errno_to_orconn_end_reason(socket_error),
tor_socket_strerror(socket_error));
connection_free(TO_CONN(conn));
return NULL;
case 0:

View File

@ -743,6 +743,10 @@ run_connection_housekeeping(int i, time_t now)
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].",
conn->s, conn->address, conn->port);
if (conn->state == OR_CONN_STATE_CONNECTING)
connection_or_connect_failed(TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
"Tor gave up on the connection");
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
return;

View File

@ -941,9 +941,6 @@ typedef struct or_connection_t {
tor_tls_t *tls; /**< TLS connection state. */
int tls_error; /**< Last tor_tls error code. */
/* XXX either merge this with tls_error, or do all our activity right
* when we compute this value so we don't have to store it. */
int socket_error; /**< If conn dies, remember why. */
/** When we last used this conn for any client traffic. If not
* recent, we can rate limit it further. */
time_t client_used;
@ -2991,6 +2988,8 @@ int connection_or_flushed_some(or_connection_t *conn);
int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(or_connection_t *conn);
void connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg);
or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest);