diff options
author | Nick Mathewson <nickm@torproject.org> | 2003-10-09 18:45:14 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2003-10-09 18:45:14 +0000 |
commit | ecfb36823e2daadbf44fcb2c9f108acc2cfcd511 (patch) | |
tree | 9de870a21a9b5524e991123fc00f23153fb3bbab /src/or/main.c | |
parent | c098d7769f564b635d979df40029d06117ae11a1 (diff) | |
download | tor-ecfb36823e2daadbf44fcb2c9f108acc2cfcd511.tar tor-ecfb36823e2daadbf44fcb2c9f108acc2cfcd511.tar.gz |
Refactor, rename, and clarify
svn:r569
Diffstat (limited to 'src/or/main.c')
-rw-r--r-- | src/or/main.c | 214 |
1 files changed, 120 insertions, 94 deletions
diff --git a/src/or/main.c b/src/or/main.c index 83a979e0c..11bbe3396 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -103,6 +103,10 @@ void connection_set_poll_socket(connection_t *conn) { poll_array[conn->poll_index].fd = conn->s; } +/* Remove the current function from the global list, and remove the + * corresponding poll entry. Calling this function will shift the last + * connection (if any) into the position occupied by conn. + */ int connection_remove(connection_t *conn) { int current_index; @@ -185,10 +189,8 @@ static void conn_read(int i) { /* see http://www.greenend.org.uk/rjk/2001/06/poll.html for * discussion of POLLIN vs POLLHUP */ if(!(poll_array[i].revents & (POLLIN|POLLHUP|POLLERR))) - if(!connection_speaks_cells(conn) || - conn->state != OR_CONN_STATE_OPEN || - !connection_is_reading(conn) || - !tor_tls_get_pending_bytes(conn->tls)) + if(!connection_is_reading(conn) || + !connection_has_pending_tls_data(conn)) return; /* this conn should not read */ log_fn(LOG_DEBUG,"socket %d wants to read.",conn->s); @@ -233,7 +235,7 @@ static void conn_write(int i) { } else assert_connection_ok(conn, time(NULL)); } -static void check_conn_marked(int i) { +static void conn_close_if_marked(int i) { connection_t *conn; conn = connection_array[i]; @@ -255,115 +257,139 @@ static void check_conn_marked(int i) { connection_free(conn); if(i<nfds) { /* we just replaced the one at i with a new one. process it too. */ - check_conn_marked(i); + conn_close_if_marked(i); } } } -static int prepare_for_poll(void) { - int i; - connection_t *conn; - struct timeval now; - static long current_second = 0; /* from previous calls to gettimeofday */ +/* Perform regulare maintenance tasks for a single connection. This + * function gets run once per second per connection by run_housekeeping. + */ +static void run_connection_housekeeping(int i, time_t now) { + cell_t cell; + connection_t *conn = connection_array[i]; + if(connection_receiver_bucket_should_increase(conn)) { + conn->receiver_bucket += conn->bandwidth; + // log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket); + } + + if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */ + && global_read_bucket > 0 /* and we're allowed to read */ + && (!connection_speaks_cells(conn) || conn->receiver_bucket > 0)) { + /* and either a non-cell conn or a cell conn with non-empty bucket */ + conn->wants_to_read = 0; + connection_start_reading(conn); + if(conn->wants_to_write == 1) { + conn->wants_to_write = 0; + connection_start_writing(conn); + } + } + + /* check connections to see whether we should send a keepalive, expire, or wait */ + if(!connection_speaks_cells(conn)) + return; + + if(now >= conn->timestamp_lastwritten + options.KeepalivePeriod) { + if((!options.OnionRouter && !circuit_get_by_conn(conn)) || + (!connection_state_is_open(conn))) { + /* we're an onion proxy, with no circuits; or our handshake has expired. kill it. */ + log_fn(LOG_INFO,"Expiring connection to %d (%s:%d).", + i,conn->address, conn->port); + conn->marked_for_close = 1; + } else { + /* either a full router, or we've got a circuit. send a padding cell. */ + log_fn(LOG_DEBUG,"Sending keepalive to (%s:%d)", + conn->address, conn->port); + memset(&cell,0,sizeof(cell_t)); + cell.command = CELL_PADDING; + connection_or_write_cell_to_buf(&cell, conn); + } + } +} + +/* Perform regular maintenance tasks. This function gets run once per + * second by prepare_for_poll. + */ +static void run_scheduled_events(time_t now) { static long time_to_fetch_directory = 0; static long time_to_new_circuit = 0; - cell_t cell; circuit_t *circ; + int i; - tor_gettimeofday(&now); + /* 1. Every DirFetchPostPeriod seconds, we get a new directory and upload + * our descriptor (if any). */ + if(time_to_fetch_directory < now) { + /* it's time to fetch a new directory and/or post our descriptor */ + if(options.OnionRouter) { + router_rebuild_descriptor(); + router_upload_desc_to_dirservers(); + } + if(!options.DirPort) { + /* NOTE directory servers do not currently fetch directories. + * Hope this doesn't bite us later. */ + directory_initiate_command(router_pick_directory_server(), + DIR_CONN_STATE_CONNECTING_FETCH); + } + time_to_fetch_directory = now + options.DirFetchPostPeriod; + } - if(now.tv_sec > current_second) { /* the second has rolled over. check more stuff. */ + /* 2. Every NewCircuitPeriod seconds, we expire old ciruits and make a + * new one as needed. + */ + if(options.APPort && time_to_new_circuit < now) { + circuit_expire_unused_circuits(); + circuit_launch_new(-1); /* tell it to forget about previous failures */ + circ = circuit_get_newest_open(); + if(!circ || circ->dirty) { + log_fn(LOG_INFO,"Youngest circuit %s; launching replacement.", circ ? "dirty" : "missing"); + circuit_launch_new(0); /* make an onion and lay the circuit */ + } + time_to_new_circuit = now + options.NewCircuitPeriod; + } + + /* 3. Every second, we check how much bandwidth we've consumed and + * increment global_read_bucket. + */ + stats_n_bytes_read += stats_prev_global_read_bucket-global_read_bucket; + if(global_read_bucket < 9*options.TotalBandwidth) { + global_read_bucket += options.TotalBandwidth; + log_fn(LOG_DEBUG,"global_read_bucket now %d.", global_read_bucket); + } + stats_prev_global_read_bucket = global_read_bucket; + - ++stats_n_seconds_reading; + /* 4. We do houskeeping for each connection... */ + for(i=0;i<nfds;i++) { + run_connection_housekeeping(i, now); + } - if(time_to_fetch_directory < now.tv_sec) { - /* it's time to fetch a new directory and/or post our descriptor */ - if(options.OnionRouter) { - router_rebuild_descriptor(); - router_upload_desc_to_dirservers(); - } - if(!options.DirPort) { - /* NOTE directory servers do not currently fetch directories. - * Hope this doesn't bite us later. */ - directory_initiate_command(router_pick_directory_server(), - DIR_CONN_STATE_CONNECTING_FETCH); - } - time_to_fetch_directory = now.tv_sec + options.DirFetchPostPeriod; - } + /* 5. and blow away any connections that need to die. can't do this later + * because we might open up a circuit and not realize we're about to cull + * the connection it's running over. + */ + for(i=0;i<nfds;i++) + conn_close_if_marked(i); +} - if(options.APPort && time_to_new_circuit < now.tv_sec) { - circuit_expire_unused_circuits(); - circuit_launch_new(-1); /* tell it to forget about previous failures */ - circ = circuit_get_newest_open(); - if(!circ || circ->dirty) { - log_fn(LOG_INFO,"Youngest circuit %s; launching replacement.", circ ? "dirty" : "missing"); - circuit_launch_new(0); /* make an onion and lay the circuit */ - } - time_to_new_circuit = now.tv_sec + options.NewCircuitPeriod; - } +static int prepare_for_poll(void) { + static long current_second = 0; /* from previous calls to gettimeofday */ + connection_t *conn; + struct timeval now; + int i; - stats_n_bytes_read += stats_prev_global_read_bucket-global_read_bucket; - if(global_read_bucket < 9*options.TotalBandwidth) { - global_read_bucket += options.TotalBandwidth; - log_fn(LOG_DEBUG,"global_read_bucket now %d.", global_read_bucket); - } - stats_prev_global_read_bucket = global_read_bucket; - - /* do housekeeping for each connection */ - for(i=0;i<nfds;i++) { - conn = connection_array[i]; - if(connection_receiver_bucket_should_increase(conn)) { - conn->receiver_bucket += conn->bandwidth; -// log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, conn->receiver_bucket); - } + tor_gettimeofday(&now); - if(conn->wants_to_read == 1 /* it's marked to turn reading back on now */ - && global_read_bucket > 0 /* and we're allowed to read */ - && (!connection_speaks_cells(conn) || conn->receiver_bucket > 0)) { - /* and either a non-cell conn or a cell conn with non-empty bucket */ - conn->wants_to_read = 0; - connection_start_reading(conn); - if(conn->wants_to_write == 1) { - conn->wants_to_write = 0; - connection_start_writing(conn); - } - } + if(now.tv_sec > current_second) { /* the second has rolled over. check more stuff. */ - /* check connections to see whether we should send a keepalive, expire, or wait */ - if(!connection_speaks_cells(conn)) - continue; /* this conn type doesn't send cells */ - if(now.tv_sec >= conn->timestamp_lastwritten + options.KeepalivePeriod) { - if((!options.OnionRouter && !circuit_get_by_conn(conn)) || - (!connection_state_is_open(conn))) { - /* we're an onion proxy, with no circuits; or our handshake has expired. kill it. */ - log_fn(LOG_INFO,"Expiring connection to %d (%s:%d).", - i,conn->address, conn->port); - conn->marked_for_close = 1; - } else { - /* either a full router, or we've got a circuit. send a padding cell. */ - log_fn(LOG_DEBUG,"Sending keepalive to (%s:%d)", - conn->address, conn->port); - memset(&cell,0,sizeof(cell_t)); - cell.command = CELL_PADDING; - connection_write_cell_to_buf(&cell, conn); - } - } - } - /* blow away any connections that need to die. can't do this later - * because we might open up a circuit and not realize we're about to cull - * the connection it's running over. - */ - for(i=0;i<nfds;i++) - check_conn_marked(i); + ++stats_n_seconds_reading; + run_scheduled_events(now.tv_sec); current_second = now.tv_sec; /* remember which second it is, for next time */ } for(i=0;i<nfds;i++) { conn = connection_array[i]; - if(connection_speaks_cells(conn) && - connection_state_is_open(conn) && - tor_tls_get_pending_bytes(conn->tls)) { + if(connection_has_pending_tls_data(conn)) { log_fn(LOG_DEBUG,"sock %d has pending bytes.",conn->s); return 0; /* has pending bytes to read; don't let poll wait. */ } @@ -621,7 +647,7 @@ static int do_main_loop(void) { /* any of the conns need to be closed now? */ for(i=0;i<nfds;i++) - check_conn_marked(i); + conn_close_if_marked(i); /* refilling buckets and sending cells happens at the beginning of the * next iteration of the loop, inside prepare_for_poll() |