r9307@Kushana: nickm | 2006-10-20 13:53:54 -0400

Have connection_about_to_close use an end_reason field in edge_connection_t to tell what reason to tell the controller for closing the stream.  Set end_reason in connection_edge_end, connection_mark_unattached_ap, and everwhere we set edge_has_sent_end.  Add a changelog entry.


svn:r8779
This commit is contained in:
Nick Mathewson 2006-10-20 17:54:48 +00:00
parent 8e94097edb
commit b27cb38dee
8 changed files with 31 additions and 6 deletions

View file

@ -22,6 +22,8 @@ Changes in version 0.1.2.3-alpha - 2006-10-??
why a remote OR told us to close a circuit. why a remote OR told us to close a circuit.
- There's now a GETINFO ns/... field so that controllers can ask Tor - There's now a GETINFO ns/... field so that controllers can ask Tor
about the current state of a router. about the current state of a router.
- Stream events also have REASON and REMOTE_REASON fields, working much
like those for circuit events.
o Security bugfixes: o Security bugfixes:
- When the user sends a NEWNYM signal, clear the client-side DNS - When the user sends a NEWNYM signal, clear the client-side DNS

View file

@ -909,6 +909,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
* are closing because the circuit is getting torn down. No need * are closing because the circuit is getting torn down. No need
* to send an end cell. */ * to send an end cell. */
conn->_base.edge_has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
connection_mark_for_close(TO_CONN(conn)); connection_mark_for_close(TO_CONN(conn));
} }
conn->on_circuit = NULL; conn->on_circuit = NULL;

View file

@ -459,8 +459,14 @@ connection_about_to_close_connection(connection_t *conn)
" back a socks reply.", " back a socks reply.",
conn->marked_for_close_file, conn->marked_for_close); conn->marked_for_close_file, conn->marked_for_close);
} }
if (!edge_conn->end_reason) {
// XXXX Disable this before 0.1.2.x-final ships.
log_warn(LD_BUG,"Bug: Closing stream (marked at %s:%d) without having"
" set end_reason. Please tell Nick.",
conn->marked_for_close_file, conn->marked_for_close);
}
control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED, control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
END_STREAM_REASON_FIXME_XXXX); edge_conn->end_reason);
break; break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
edge_conn = TO_EDGE_CONN(conn); edge_conn = TO_EDGE_CONN(conn);

View file

@ -63,6 +63,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
_connection_mark_for_close(TO_CONN(conn), line, file); _connection_mark_for_close(TO_CONN(conn), line, file);
conn->_base.hold_open_until_flushed = 1; conn->_base.hold_open_until_flushed = 1;
conn->end_reason = endreason;
} }
/** There was an EOF. Send an end and mark the connection for close. /** There was an EOF. Send an end and mark the connection for close.
@ -155,6 +156,7 @@ connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn)
} else { } else {
/* closing the circuit, nothing to send an END to */ /* closing the circuit, nothing to send an END to */
conn->_base.edge_has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
connection_mark_for_close(TO_CONN(conn)); connection_mark_for_close(TO_CONN(conn));
conn->_base.hold_open_until_flushed = 1; conn->_base.hold_open_until_flushed = 1;
} }
@ -213,6 +215,7 @@ connection_edge_end(edge_connection_t *conn, char reason,
} }
conn->_base.edge_has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
conn->end_reason = reason;
return 0; return 0;
} }
@ -408,6 +411,7 @@ connection_ap_expire_beginning(void)
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
/* un-mark it as ending, since we're going to reuse it */ /* un-mark it as ending, since we're going to reuse it */
conn->_base.edge_has_sent_end = 0; conn->_base.edge_has_sent_end = 0;
conn->end_reason = 0;
/* kludge to make us not try this circuit again, yet to allow /* kludge to make us not try this circuit again, yet to allow
* current streams on it to survive if they can: make it * current streams on it to survive if they can: make it
* unattractive to use for new streams */ * unattractive to use for new streams */

View file

@ -2101,6 +2101,7 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
ap_conn->cpath_layer); ap_conn->cpath_layer);
/* Un-mark it as ending, since we're going to reuse it. */ /* Un-mark it as ending, since we're going to reuse it. */
ap_conn->_base.edge_has_sent_end = 0; ap_conn->_base.edge_has_sent_end = 0;
ap_conn->end_reason = 0;
if (tmpcirc) if (tmpcirc)
circuit_detach_stream(tmpcirc,ap_conn); circuit_detach_stream(tmpcirc,ap_conn);
ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;

View file

@ -447,6 +447,9 @@ conn_write_callback(int fd, short events, void *_conn)
tor_fragile_assert(); tor_fragile_assert();
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
/* otherwise we cry wolf about duplicate close */ /* otherwise we cry wolf about duplicate close */
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
if (!edge_conn->end_reason)
edge_conn->end_reason = END_STREAM_REASON_INTERNAL;
conn->edge_has_sent_end = 1; conn->edge_has_sent_end = 1;
} }
/* XXX do we need a close-immediate here, so we don't try to flush? */ /* XXX do we need a close-immediate here, so we don't try to flush? */

View file

@ -756,6 +756,9 @@ typedef struct edge_connection_t {
uint16_t stream_id; /**< The stream ID used for this edge connection on its uint16_t stream_id; /**< The stream ID used for this edge connection on its
* circuit */ * circuit */
/** The reason why this connection is closing; passed to the controller. */
uint16_t end_reason;
/** Quasi-global identifier for this connection; used for control.c */ /** Quasi-global identifier for this connection; used for control.c */
/* XXXX NM This can get re-used after 2**32 streams */ /* XXXX NM This can get re-used after 2**32 streams */
uint32_t global_identifier; uint32_t global_identifier;

View file

@ -533,6 +533,7 @@ connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
} else { } else {
log_info(LD_EXIT,"no circ. Closing conn."); log_info(LD_EXIT,"no circ. Closing conn.");
fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */ fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */
fromconn->end_reason = END_STREAM_REASON_INTERNAL;
connection_mark_for_close(TO_CONN(fromconn)); connection_mark_for_close(TO_CONN(fromconn));
} }
return -1; return -1;
@ -817,10 +818,11 @@ connection_edge_process_end_not_open(
connection_edge_end_reason_str(rh->length > 0 ? reason : -1)); connection_edge_end_reason_str(rh->length > 0 ? reason : -1));
if (conn->_base.type == CONN_TYPE_AP) { if (conn->_base.type == CONN_TYPE_AP) {
circuit_log_path(LOG_INFO,LD_APP,circ); circuit_log_path(LOG_INFO,LD_APP,circ);
connection_mark_unattached_ap(conn, reason); connection_mark_unattached_ap(conn, control_reason);
} else { } else {
/* we just got an 'end', don't need to send one */ /* we just got an 'end', don't need to send one */
conn->_base.edge_has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
conn->end_reason = control_reason;
connection_mark_for_close(TO_CONN(conn)); connection_mark_for_close(TO_CONN(conn));
} }
return 0; return 0;
@ -1024,23 +1026,25 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_edge_consider_sending_sendme(conn); connection_edge_consider_sending_sendme(conn);
return 0; return 0;
case RELAY_COMMAND_END: case RELAY_COMMAND_END:
reason = rh.length > 0 ?
*(uint8_t *)(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC;
if (!conn) { if (!conn) {
log_info(domain,"end cell (%s) dropped, unknown stream.", log_info(domain,"end cell (%s) dropped, unknown stream.",
connection_edge_end_reason_str(rh.length > 0 ? connection_edge_end_reason_str(reason));
*(char *)(cell->payload+RELAY_HEADER_SIZE) : -1));
return 0; return 0;
} }
/* XXX add to this log_fn the exit node's nickname? */ /* XXX add to this log_fn the exit node's nickname? */
log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.", log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.",
conn->_base.s, conn->_base.s,
connection_edge_end_reason_str(rh.length > 0 ? connection_edge_end_reason_str(reason),
*(char *)(cell->payload+RELAY_HEADER_SIZE) : -1),
conn->stream_id); conn->stream_id);
if (conn->socks_request && !conn->socks_request->has_finished) if (conn->socks_request && !conn->socks_request->has_finished)
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: open stream hasn't sent socks answer yet? Closing."); "Bug: open stream hasn't sent socks answer yet? Closing.");
/* We just *got* an end; no reason to send one. */ /* We just *got* an end; no reason to send one. */
conn->_base.edge_has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
if (!conn->end_reason)
conn->end_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
if (!conn->_base.marked_for_close) { if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to /* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */ * get the 'end' right around when the client hangs up on us. */
@ -1216,6 +1220,7 @@ repeat_connection_edge_package_raw_inbuf:
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(conn);
if (!circ) { if (!circ) {
log_info(domain,"conn has no circuit! Closing."); log_info(domain,"conn has no circuit! Closing.");
conn->end_reason = END_STREAM_REASON_CANT_ATTACH;
return -1; return -1;
} }