summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/or/circuitlist.c3
-rw-r--r--src/or/connection_edge.c3
-rw-r--r--src/or/control.c6
-rw-r--r--src/or/or.h8
4 files changed, 18 insertions, 2 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index acbea47487..93784a485d 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -953,6 +953,9 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
* to send an end cell. */
conn->_base.edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
+ conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
+ control_event_stream_status(conn, STREAM_EVENT_CLOSED,
+ END_STREAM_REASON_DESTROY);
connection_mark_for_close(TO_CONN(conn));
}
conn->on_circuit = NULL;
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 21143ac09d..4d329e2e3f 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -158,6 +158,9 @@ connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn)
/* closing the circuit, nothing to send an END to */
conn->_base.edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
+ conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
+ control_event_stream_status(conn, STREAM_EVENT_CLOSED,
+ END_STREAM_REASON_DESTROY);
connection_mark_for_close(TO_CONN(conn));
conn->_base.hold_open_until_flushed = 1;
}
diff --git a/src/or/control.c b/src/or/control.c
index cbea14f22c..402ca267d8 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -3140,7 +3140,7 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
static const char *
stream_end_reason_to_string(int reason)
{
- reason &= ~END_CIRC_REASON_FLAG_REMOTE;
+ reason &= END_STREAM_REASON_MASK;
switch (reason) {
case END_STREAM_REASON_MISC: return "MISC";
case END_STREAM_REASON_RESOLVEFAILED: return "RESOLVEFAILED";
@@ -3179,6 +3179,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
return 0;
+ if (tp == STREAM_EVENT_CLOSED &&
+ (reason_code & END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED))
+ return 0;
+
write_stream_target_to_buf(conn, buf, sizeof(buf));
if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) {
len = strlen(buf);
diff --git a/src/or/or.h b/src/or/or.h
index 26998c272d..e0c680983d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -531,9 +531,15 @@ typedef enum {
/** DOCDOC */
#define END_STREAM_REASON_INVALID_NATD_DEST 261
+/** Bitwise-and this value with endreason to mask out all flags. */
+#define END_STREAM_REASON_MASK 511
+
/** Bitwise-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
+#define END_STREAM_REASON_FLAG_REMOTE 512
+/** Bitwise-or this with the argument to control_event_stream_status
+ * to indicate that we already sent a CLOSED stream event. */
+#define END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED 1024
/* DOCDOC */
#define RESOLVED_TYPE_HOSTNAME 0