aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/or/connection.c4
-rw-r--r--src/or/connection_edge.c16
-rw-r--r--src/or/control.c52
-rw-r--r--src/or/or.h11
4 files changed, 69 insertions, 14 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index d60291253e..25b633a065 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -458,9 +458,9 @@ connection_about_to_close_connection(connection_t *conn)
log_warn(LD_BUG,"Bug: Closing stream (marked at %s:%d) without sending"
" back a socks reply.",
conn->marked_for_close_file, conn->marked_for_close);
- } else {
- control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED);
}
+ control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
+ END_STREAM_REASON_FIXME_XXXX);
break;
case CONN_TYPE_EXIT:
edge_conn = TO_EDGE_CONN(conn);
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ad88e4153e..5a415bb04f 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -498,7 +498,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
int
connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ)
{
- control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
+ control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE,
+ END_STREAM_REASON_FIXME_XXXX);
conn->_base.timestamp_lastread = time(NULL);
if (! get_options()->LeaveStreamsUnattached) {
conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
@@ -1436,9 +1437,9 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
} /* else socks handshake is done, continue processing */
if (socks->command == SOCKS_COMMAND_CONNECT)
- control_event_stream_status(conn, STREAM_EVENT_NEW);
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
else
- control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
+ control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE, 0);
if (options->LeaveStreamsUnattached) {
conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
@@ -1480,7 +1481,7 @@ connection_ap_process_transparent(edge_connection_t *conn)
}
/* we have the original destination */
- control_event_stream_status(conn, STREAM_EVENT_NEW);
+ control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
if (options->LeaveStreamsUnattached) {
conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
@@ -1557,7 +1558,7 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
ap_conn->_base.s, circ->_base.n_circ_id);
- control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
+ control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
return 0;
}
@@ -1623,7 +1624,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
ap_conn->_base.s, circ->_base.n_circ_id);
- control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
+ control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
return 0;
}
@@ -1781,7 +1782,8 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
tor_assert(conn->socks_request); /* make sure it's an AP stream */
control_event_stream_status(conn,
- status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED);
+ status==SOCKS5_SUCCEEDED ? STREAM_EVENT_SUCCEEDED : STREAM_EVENT_FAILED,
+ END_STREAM_REASON_FIXME_XXXX);
if (conn->socks_request->has_finished) {
log_warn(LD_BUG, "Harmless bug: duplicate calls to "
diff --git a/src/or/control.c b/src/or/control.c
index 84d4ee4d56..562c7c64ab 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2946,10 +2946,34 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
return 0;
}
+/* DOCDOC */
+static const char *
+stream_end_reason_to_string(int reason)
+{
+ reason &= ~END_CIRC_REASON_FLAG_REMOTE;
+ switch (reason) {
+ case END_STREAM_REASON_MISC: return "MISC";
+ case END_STREAM_REASON_RESOLVEFAILED: return "RESOLVEFAILED";
+ case END_STREAM_REASON_CONNECTREFUSED: return "CONNECTREFUSED";
+ case END_STREAM_REASON_EXITPOLICY: return "EXITPOLICY";
+ case END_STREAM_REASON_DESTROY: return "DESTROY";
+ case END_STREAM_REASON_DONE: return "DONE";
+ case END_STREAM_REASON_TIMEOUT: return "TIMEOUT";
+ case END_STREAM_REASON_HIBERNATING: return "HIBERNATING";
+ case END_STREAM_REASON_INTERNAL: return "INTERNAL";
+ case END_STREAM_REASON_RESOURCELIMIT: return "RESOURCELIMIT";
+ case END_STREAM_REASON_CONNRESET: return "CONNRESET";
+ case END_STREAM_REASON_TORPROTOCOL: return "TORPROTOCOL";
+ case END_STREAM_REASON_NOTDIRECTORY: return "NOTDIRECTORY";
+ default: return NULL;
+ }
+}
+
/** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */
int
-control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
+control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
+ int reason_code)
{
char *msg;
size_t len;
@@ -2971,9 +2995,11 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
tor_free(msg);
}
if (EVENT_IS_INTERESTING1(EVENT_STREAM_STATUS)) {
+ char reason_buf[64];
const char *status;
circuit_t *circ;
origin_circuit_t *origin_circ = NULL;
+ reason_buf[0] = '\0';
switch (tp)
{
case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
@@ -2988,15 +3014,33 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
return 0;
}
+ if (reason_code && (tp == STREAM_EVENT_FAILED ||
+ tp == STREAM_EVENT_CLOSED ||
+ tp == STREAM_EVENT_FAILED_RETRIABLE)) {
+ const char *reason_str = stream_end_reason_to_string(reason_code);
+ char *r = NULL;
+ if (!reason_str) {
+ r = tor_malloc(16);
+ tor_snprintf(r, 16, "UNKNOWN_%d", reason_code);
+ reason_str = r;
+ }
+ if (reason_code & END_STREAM_REASON_FLAG_REMOTE)
+ tor_snprintf(reason_buf, sizeof(reason_buf),
+ "REASON=END REMOTE_REASON=%s", reason_str);
+ else
+ tor_snprintf(reason_buf, sizeof(reason_buf),
+ "REASON=%s", reason_str);
+ tor_free(r);
+ }
circ = circuit_get_by_edge_conn(conn);
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
- send_control1_event(EVENT_STREAM_STATUS, ALL_NAMES,
- "650 STREAM %lu %s %lu %s\r\n",
+ send_control1_event_extended(EVENT_STREAM_STATUS, ALL_NAMES,
+ "650 STREAM %lu %s %lu %s@%s\r\n",
(unsigned long)conn->global_identifier, status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
- buf);
+ buf, reason_buf);
/* XXX need to specify its intended exit, etc? */
}
return 0;
diff --git a/src/or/or.h b/src/or/or.h
index 86c626a779..ae116d0440 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -464,6 +464,10 @@ typedef enum {
#define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
#define RELAY_COMMAND_INTRODUCE_ACK 40
+/* XXXX Placeholder: remove me as soon as we have correct reasons sent
+ * everywhere. */
+#define END_STREAM_REASON_FIXME_XXXX 0
+
#define END_STREAM_REASON_MISC 1
#define END_STREAM_REASON_RESOLVEFAILED 2
#define END_STREAM_REASON_CONNECTREFUSED 3
@@ -479,6 +483,10 @@ typedef enum {
#define END_STREAM_REASON_TORPROTOCOL 13
#define END_STREAM_REASON_NOTDIRECTORY 14
+/* OR this with the argument to control_event_stream_status to indicate that
+ * the reason came from an END cell. */
+#define END_STREAM_REASON_FLAG_REMOTE 512
+
/* These high-numbered end reasons are not part of the official spec,
* and are not intended to be put in relay end cells. They are here
* to be more informative when sending back socks replies to the
@@ -2089,7 +2097,8 @@ int connection_control_process_inbuf(control_connection_t *conn);
int control_event_circuit_status(origin_circuit_t *circ,
circuit_status_event_t e, int reason);
int control_event_stream_status(edge_connection_t *conn,
- stream_status_event_t e);
+ stream_status_event_t e,
+ int reason);
int control_event_or_conn_status(or_connection_t *conn,
or_conn_status_event_t e);
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);