diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-02-27 22:00:26 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-02-27 22:00:26 +0000 |
commit | c5bbb571d2a27d0b81bfe7a1d374ba965497f267 (patch) | |
tree | 81bf23633d8fe4a1da845f097bd52a6ae83340ae /src/or/connection.c | |
parent | 58a7bfab81eeb707b1251df8e525e5b7b7365272 (diff) | |
download | tor-c5bbb571d2a27d0b81bfe7a1d374ba965497f267.tar tor-c5bbb571d2a27d0b81bfe7a1d374ba965497f267.tar.gz |
Refactor mark_for_close, connection_edge_end and friends. Now, everybody
who wants to shut down a connection calls connection_mark_for_close instead
of setting marked_for_close to 1. This automatically removes the connection
from the DNS cache if needed, sends a RELAY END cell if appropriate, and can
be changed to do whatever else is needed.
Still to do:
- The same for circuits, maybe.
- Add some kind of hold_connection_open_until_flushed flag, maybe.
- Change stuff that closes connections with return -1 to use mark_for_close,
maybe.
svn:r1145
Diffstat (limited to 'src/or/connection.c')
-rw-r--r-- | src/or/connection.c | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index 1e9876f8c..5917c0a57 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -81,7 +81,6 @@ connection_t *connection_new(int type) { conn->magic = CONNECTION_MAGIC; conn->s = -1; /* give it a default of 'not used' */ - conn->type = type; if(!connection_is_listener(conn)) { /* listeners never use their buf */ conn->inbuf = buf_new(); @@ -142,6 +141,51 @@ void connection_free_all(void) { connection_free(carray[i]); } +int +_connection_mark_for_close(connection_t *conn, char reason) +{ + assert_connection_ok(conn,0); + + if (conn->marked_for_close) { + log(LOG_WARN, "Double mark-for-close on connection."); + return -1; + } + + switch (conn->type) + { + case CONN_TYPE_OR_LISTENER: + case CONN_TYPE_AP_LISTENER: + case CONN_TYPE_DIR_LISTENER: + case CONN_TYPE_CPUWORKER: + case CONN_TYPE_DIR: + /* No special processing needed. */ + break; + case CONN_TYPE_OR: + /* No special processing needed, I think. */ + break; + case CONN_TYPE_EXIT: + case CONN_TYPE_AP: + if (conn->state == EXIT_CONN_STATE_RESOLVING) + dns_cancel_pending_resolve(conn->address, conn); + if (reason < _MIN_END_STREAM_REASON || reason > _MAX_END_STREAM_REASON) + reason = END_STREAM_REASON_MISC; + if (!conn->has_sent_end && + connection_edge_end(conn, reason, conn->cpath_layer) < 0) + return -1; + break; + case CONN_TYPE_DNSWORKER: + if (conn->state == DNSWORKER_STATE_BUSY) { + dns_cancel_pending_resolve(conn->address, NULL); + } + break; + default: + log(LOG_ERR, "Unknown connection type %d", conn->type); + ; + } + conn->marked_for_close = 1; + return 0; +} + int connection_create_listener(char *bindaddress, uint16_t bindport, int type) { struct sockaddr_in bindaddr; /* where to bind */ struct hostent *rent; @@ -239,7 +283,7 @@ static int connection_handle_listener_read(connection_t *conn, int new_type) { } if(connection_init_accepted_conn(newconn) < 0) { - newconn->marked_for_close = 1; + connection_mark_for_close(newconn,0); return 0; } return 0; @@ -306,11 +350,14 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_ } static void listener_close_if_present(int type) { + assert(type == CONN_TYPE_OR_LISTENER || + type == CONN_TYPE_AP_LISTENER || + type == CONN_TYPE_DIR_LISTENER); connection_t *conn = connection_get_by_type(type); if (conn) { close(conn->s); conn->s = -1; - conn->marked_for_close = 1; + connection_mark_for_close(conn,0); } } @@ -523,7 +570,7 @@ void connection_write_to_buf(const char *string, int len, connection_t *conn) { if(write_to_buf(string, len, conn->outbuf) < 0) { log_fn(LOG_WARN,"write_to_buf failed. Closing connection (fd %d).", conn->s); - conn->marked_for_close = 1; + connection_mark_for_close(conn,0); return; } @@ -539,8 +586,8 @@ void connection_write_to_buf(const char *string, int len, connection_t *conn) { len -= (MIN_TLS_FLUSHLEN - conn->outbuf_flushlen); conn->outbuf_flushlen = MIN_TLS_FLUSHLEN; if(connection_handle_write(conn) < 0) { - conn->marked_for_close = 1; log_fn(LOG_WARN,"flushing failed."); + connection_mark_for_close(conn,0); } } if(len > 0) { /* if there's any left over */ @@ -693,9 +740,7 @@ int connection_send_destroy(uint16_t circ_id, connection_t *conn) { log_fn(LOG_INFO,"...and informing resolver we don't want the answer anymore."); dns_cancel_pending_resolve(conn->address, conn); } - if(connection_edge_end(conn, END_STREAM_REASON_DESTROY, conn->cpath_layer) < 0) - log_fn(LOG_WARN,"1: I called connection_edge_end redundantly."); - /* if they already sent a destroy, they know. XXX can just close? */ + connection_mark_for_close(conn, END_STREAM_REASON_DESTROY); return 0; } @@ -865,4 +910,3 @@ void assert_connection_ok(connection_t *conn, time_t now) c-basic-offset:2 End: */ - |