start sending "bootstrap problem" status events when we're having troubles

reaching relays.


svn:r15116
This commit is contained in:
Roger Dingledine 2008-06-11 01:14:23 +00:00
parent 42f21007a3
commit 8c85eef9b0
7 changed files with 95 additions and 41 deletions

View File

@ -1070,7 +1070,7 @@ $Id$
Reason = "MISC" / "DONE" / "CONNECTREFUSED" /
"IDENTITY" / "CONNECTRESET" / "TIMEOUT" / "NOROUTE" /
"IOERROR"
"IOERROR" / "RESOURCELIMIT"
NumCircuits counts both established and pending circuits.

View File

@ -500,14 +500,18 @@ connection_about_to_close_connection(connection_t *conn)
if (!get_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, 0);
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
errno_to_orconn_end_reason(or_conn->socket_error));
control_event_bootstrap_problem(
tor_socket_strerror(or_conn->socket_error), 0);
tor_socket_strerror(or_conn->socket_error),
errno_to_orconn_end_reason(or_conn->socket_error));
} else {
int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
reason);
control_event_bootstrap_problem("foo", reason);
/* XXX021 come up with a better string for the first arg */
control_event_bootstrap_problem(
orconn_end_reason_to_control_string(reason), reason);
}
}
/* Inform any pending (not attached) circs that they should
@ -1097,8 +1101,9 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
}
/** Take conn, make a nonblocking socket; try to connect to
* addr:port (they arrive in *host order*). If fail, return -1. Else
* assign s to conn-\>s: if connected return 1, if EAGAIN return 0.
* addr:port (they arrive in *host order*). If fail, return -1 and if
* applicable put your best guess about errno into *<b>socket_error</b>.
* Else assign s to conn-\>s: if connected return 1, if EAGAIN return 0.
*
* address is used to make the logs useful.
*
@ -1106,7 +1111,7 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
*/
int
connection_connect(connection_t *conn, const char *address,
uint32_t addr, uint16_t port)
uint32_t addr, uint16_t port, int *socket_error)
{
int s, inprogress = 0;
struct sockaddr_in dest_addr;
@ -1123,8 +1128,9 @@ connection_connect(connection_t *conn, const char *address,
s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (s < 0) {
*socket_error = tor_socket_errno(-1);
log_warn(LD_NET,"Error creating network socket: %s",
tor_socket_strerror(tor_socket_errno(-1)));
tor_socket_strerror(*socket_error));
return -1;
}
@ -1140,8 +1146,9 @@ connection_connect(connection_t *conn, const char *address,
} else {
if (bind(s, (struct sockaddr*)&ext_addr,
(socklen_t)sizeof(ext_addr)) < 0) {
*socket_error = tor_socket_errno(s);
log_warn(LD_NET,"Error binding network socket: %s",
tor_socket_strerror(tor_socket_errno(s)));
tor_socket_strerror(*socket_error));
tor_close_socket(s);
return -1;
}
@ -1165,6 +1172,7 @@ connection_connect(connection_t *conn, const char *address,
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
/* yuck. kill it. */
*socket_error = e;
log_info(LD_NET,
"connect() to %s:%u failed: %s",escaped_safe_str(address),
port, tor_socket_strerror(e));

View File

@ -236,7 +236,7 @@ connection_edge_end_errno(edge_connection_t *conn)
{
uint8_t reason;
tor_assert(conn);
reason = (uint8_t)errno_to_stream_end_reason(tor_socket_errno(conn->_base.s));
reason = errno_to_stream_end_reason(tor_socket_errno(conn->_base.s));
return connection_edge_end(conn, reason);
}
@ -2609,6 +2609,7 @@ connection_exit_connect(edge_connection_t *edge_conn)
uint32_t addr;
uint16_t port;
connection_t *conn = TO_CONN(edge_conn);
int socket_error = 0;
if (!connection_edge_is_rendezvous_stream(edge_conn) &&
router_compare_to_my_exit_policy(edge_conn)) {
@ -2644,8 +2645,10 @@ connection_exit_connect(edge_connection_t *edge_conn)
}
log_debug(LD_EXIT,"about to try connecting");
switch (connection_connect(conn, conn->address, addr, port)) {
switch (connection_connect(conn, conn->address, addr, port, &socket_error)) {
case -1:
/* XXX021 use socket_error below rather than trying to piece things
* together from the current errno, which may have been clobbered. */
connection_edge_end_errno(edge_conn);
circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
connection_free(conn);

View File

@ -513,6 +513,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
{
or_connection_t *conn;
or_options_t *options = get_options();
int socket_error = 0;
tor_assert(id_digest);
@ -534,7 +535,8 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
port = options->HttpsProxyPort;
}
switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, port)) {
switch (connection_connect(TO_CONN(conn), conn->_base.address,
addr, port, &socket_error)) {
case -1:
/* If the connection failed immediately, and we're using
* an https proxy, our https proxy is down. Don't blame the
@ -545,9 +547,9 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
router_set_status(conn->identity_digest, 0);
}
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
END_OR_CONN_REASON_TCP_REFUSED);
/* XXX connection_connect() can fail for all sorts of other reasons */
control_event_bootstrap_problem("foo", END_OR_CONN_REASON_TCP_REFUSED);
errno_to_orconn_end_reason(socket_error));
control_event_bootstrap_problem(tor_socket_strerror(socket_error),
errno_to_orconn_end_reason(socket_error));
connection_free(TO_CONN(conn));
return NULL;
case 0:

View File

@ -659,6 +659,7 @@ directory_initiate_command(const char *address, uint32_t addr,
{
dir_connection_t *conn;
or_options_t *options = get_options();
int socket_error = 0;
int use_begindir = supports_begindir &&
directory_command_should_use_begindir(options, addr,
or_port, router_purpose, anonymized_connection);
@ -699,7 +700,7 @@ directory_initiate_command(const char *address, uint32_t addr,
}
switch (connection_connect(TO_CONN(conn), conn->_base.address, addr,
dir_port)) {
dir_port, &socket_error)) {
case -1:
connection_dir_request_failed(conn); /* retry if we want */
/* XXX we only pass 'conn' above, not 'resource', 'payload',

View File

@ -502,13 +502,14 @@ typedef enum {
/* Reasons why an OR connection is closed */
#define END_OR_CONN_REASON_DONE 1
#define END_OR_CONN_REASON_TCP_REFUSED 2
#define END_OR_CONN_REASON_REFUSED 2 /* connection refused */
#define END_OR_CONN_REASON_OR_IDENTITY 3
#define END_OR_CONN_REASON_TLS_CONNRESET 4 /* tls connection reset by peer */
#define END_OR_CONN_REASON_TLS_TIMEOUT 5
#define END_OR_CONN_REASON_TLS_NO_ROUTE 6 /* no route to host/net */
#define END_OR_CONN_REASON_TLS_IO_ERROR 7 /* tls read/write error */
#define END_OR_CONN_REASON_TLS_MISC 8
#define END_OR_CONN_REASON_CONNRESET 4 /* connection reset by peer */
#define END_OR_CONN_REASON_TIMEOUT 5
#define END_OR_CONN_REASON_NO_ROUTE 6 /* no route to host/net */
#define END_OR_CONN_REASON_IO_ERROR 7 /* read/write error */
#define END_OR_CONN_REASON_RESOURCE_LIMIT 8 /* sockets, buffers, etc */
#define END_OR_CONN_REASON_MISC 9
/* Reasons why we (or a remote OR) might close a stream. See tor-spec.txt for
* documentation of these. */
@ -2742,7 +2743,7 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file);
void connection_expire_held_open(void);
int connection_connect(connection_t *conn, const char *address, uint32_t addr,
uint16_t port);
uint16_t port, int *socket_error);
int retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns);
@ -3589,10 +3590,11 @@ void policies_free_all(void);
const char *stream_end_reason_to_control_string(int reason);
const char *stream_end_reason_to_string(int reason);
socks5_reply_status_t stream_end_reason_to_socks5_response(int reason);
int errno_to_stream_end_reason(int e);
uint8_t errno_to_stream_end_reason(int e);
const char *orconn_end_reason_to_control_string(int r);
int tls_error_to_orconn_end_reason(int e);
int errno_to_orconn_end_reason(int e);
const char *circuit_end_reason_to_control_string(int reason);

View File

@ -144,9 +144,8 @@ stream_end_reason_to_socks5_response(int reason)
#endif
/** Given an errno from a failed exit connection, return a reason code
* appropriate for use in a RELAY END cell.
*/
int
* appropriate for use in a RELAY END cell. */
uint8_t
errno_to_stream_end_reason(int e)
{
switch (e) {
@ -192,19 +191,21 @@ orconn_end_reason_to_control_string(int r)
switch (r) {
case END_OR_CONN_REASON_DONE:
return "DONE";
case END_OR_CONN_REASON_TCP_REFUSED:
case END_OR_CONN_REASON_REFUSED:
return "CONNECTREFUSED";
case END_OR_CONN_REASON_OR_IDENTITY:
return "IDENTITY";
case END_OR_CONN_REASON_TLS_CONNRESET:
case END_OR_CONN_REASON_CONNRESET:
return "CONNECTRESET";
case END_OR_CONN_REASON_TLS_TIMEOUT:
case END_OR_CONN_REASON_TIMEOUT:
return "TIMEOUT";
case END_OR_CONN_REASON_TLS_NO_ROUTE:
case END_OR_CONN_REASON_NO_ROUTE:
return "NOROUTE";
case END_OR_CONN_REASON_TLS_IO_ERROR:
case END_OR_CONN_REASON_IO_ERROR:
return "IOERROR";
case END_OR_CONN_REASON_TLS_MISC:
case END_OR_CONN_REASON_RESOURCE_LIMIT:
return "RESOURCELIMIT";
case END_OR_CONN_REASON_MISC:
return "MISC";
case 0:
return "";
@ -220,22 +221,59 @@ tls_error_to_orconn_end_reason(int e)
{
switch (e) {
case TOR_TLS_ERROR_IO:
return END_OR_CONN_REASON_TLS_IO_ERROR;
return END_OR_CONN_REASON_IO_ERROR;
case TOR_TLS_ERROR_CONNREFUSED:
return END_OR_CONN_REASON_TCP_REFUSED;
return END_OR_CONN_REASON_REFUSED;
case TOR_TLS_ERROR_CONNRESET:
return END_OR_CONN_REASON_TLS_CONNRESET;
return END_OR_CONN_REASON_CONNRESET;
case TOR_TLS_ERROR_NO_ROUTE:
return END_OR_CONN_REASON_TLS_NO_ROUTE;
return END_OR_CONN_REASON_NO_ROUTE;
case TOR_TLS_ERROR_TIMEOUT:
return END_OR_CONN_REASON_TLS_TIMEOUT;
return END_OR_CONN_REASON_TIMEOUT;
case TOR_TLS_WANTREAD:
case TOR_TLS_WANTWRITE:
case TOR_TLS_CLOSE:
case TOR_TLS_DONE:
return END_OR_CONN_REASON_DONE;
default:
return END_OR_CONN_REASON_TLS_MISC;
return END_OR_CONN_REASON_MISC;
}
}
/** Given an errno from a failed ORConn connection, return a reason code
* appropriate for use in the controller orconn events. */
/* XXX021 somebody should think about whether the assignments I've made
* are accurate or useful. -RD */
int
errno_to_orconn_end_reason(int e)
{
switch (e) {
case EPIPE:
return END_OR_CONN_REASON_DONE;
S_CASE(ENOTCONN):
S_CASE(ENETUNREACH):
case ENETDOWN: /* << somebody should look into the Windows equiv */
case EHOSTUNREACH:
return END_OR_CONN_REASON_NO_ROUTE;
S_CASE(ECONNREFUSED):
return END_OR_CONN_REASON_REFUSED;
S_CASE(ECONNRESET):
return END_OR_CONN_REASON_CONNRESET;
S_CASE(ETIMEDOUT):
return END_OR_CONN_REASON_TIMEOUT;
S_CASE(ENOBUFS):
case ENOMEM:
case ENFILE:
E_CASE(EMFILE):
E_CASE(EACCES):
E_CASE(EBADF):
E_CASE(EFAULT):
E_CASE(EINVAL):
return END_OR_CONN_REASON_RESOURCE_LIMIT;
default:
log_info(LD_OR, "Didn't recognize errno %d (%s).",
e, tor_socket_strerror(e));
return END_OR_CONN_REASON_MISC;
}
}