diff --git a/ChangeLog b/ChangeLog index d4e663cc8..d0fe22c5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Changes in version 0.1.2.8-alpha - 2007-??-?? + o Minor bugfixes (controller): + - Give the controller END_STREAM_REASON_DESTROY events _before_ we + clear the corresponding on_circuit variable, and remember later that + we don't need to send a redundant CLOSED event. (Resolves part 3 of + bug 367.) + + Changes in version 0.1.2.7-alpha - 2007-02-06 o Major bugfixes (rate limiting): - Servers decline directory requests much more aggressively when diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index acbea4748..93784a485 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 21143ac09..4d329e2e3 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 cbea14f22..402ca267d 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 26998c272..e0c680983 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