diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/or/channel.c | 4 | ||||
-rw-r--r-- | src/or/circuitlist.c | 1 | ||||
-rw-r--r-- | src/or/main.c | 43 | ||||
-rw-r--r-- | src/or/main.h | 1 | ||||
-rw-r--r-- | src/test/geoip_dummy | 0 | ||||
-rw-r--r-- | src/test/test_geoip.c | 84 |
6 files changed, 120 insertions, 13 deletions
diff --git a/src/or/channel.c b/src/or/channel.c index 68245db497..c30e508018 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -69,6 +69,7 @@ #include "circuitmux.h" #include "entrynodes.h" #include "geoip.h" +#include "main.h" #include "nodelist.h" #include "relay.h" #include "rephist.h" @@ -404,6 +405,7 @@ channel_register(channel_t *chan) /* Put it in the finished list, creating it if necessary */ if (!finished_channels) finished_channels = smartlist_new(); smartlist_add(finished_channels, chan); + mainloop_schedule_postloop_cleanup(); } else { /* Put it in the active list, creating it if necessary */ if (!active_channels) active_channels = smartlist_new(); @@ -1548,6 +1550,7 @@ channel_change_state_(channel_t *chan, channel_state_t to_state) if (active_channels) smartlist_remove(active_channels, chan); if (!finished_channels) finished_channels = smartlist_new(); smartlist_add(finished_channels, chan); + mainloop_schedule_postloop_cleanup(); } /* Need to put on active list? */ else if (!was_active && is_active) { @@ -1666,6 +1669,7 @@ channel_listener_change_state(channel_listener_t *chan_l, if (active_listeners) smartlist_remove(active_listeners, chan_l); if (!finished_listeners) finished_listeners = smartlist_new(); smartlist_add(finished_listeners, chan_l); + mainloop_schedule_postloop_cleanup(); } /* Need to put on active list? */ else if (!was_active && is_active) { diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 9a82713cbe..ea2f2c15c5 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -2067,6 +2067,7 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line, circuits_pending_close = smartlist_new(); smartlist_add(circuits_pending_close, circ); + mainloop_schedule_postloop_cleanup(); log_info(LD_GENERAL, "Circuit %u (id: %" PRIu32 ") marked for close at " "%s:%d (orig reason: %d, new reason: %d)", diff --git a/src/or/main.c b/src/or/main.c index 7e489a9991..83d1e6a41a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -446,6 +446,7 @@ add_connection_to_closeable_list(connection_t *conn) tor_assert(conn->marked_for_close); assert_connection_ok(conn, time(NULL)); smartlist_add(closeable_connection_lst, conn); + mainloop_schedule_postloop_cleanup(); } /** Return 1 if conn is on the closeable list, else return 0. */ @@ -1599,6 +1600,30 @@ reschedule_directory_downloads(void) periodic_event_reschedule(launch_descriptor_fetches_event); } +/** Mainloop callback: clean up circuits, channels, and connections + * that are pending close. */ +static void +postloop_cleanup_cb(mainloop_event_t *ev, void *arg) +{ + (void)ev; + (void)arg; + circuit_close_all_marked(); + close_closeable_connections(); + channel_run_cleanup(); + channel_listener_run_cleanup(); +} + +/** Event to run postloop_cleanup_cb */ +static mainloop_event_t *postloop_cleanup_ev=NULL; + +/** Schedule a post-loop event to clean up marked channels, connections, and + * circuits. */ +void +mainloop_schedule_postloop_cleanup(void) +{ + mainloop_event_activate(postloop_cleanup_ev); +} + #define LONGEST_TIMER_PERIOD (30 * 86400) /** Helper: Return the number of seconds between <b>now</b> and <b>next</b>, * clipped to the range [1 second, LONGEST_TIMER_PERIOD]. */ @@ -1710,23 +1735,10 @@ run_scheduled_events(time_t now) run_connection_housekeeping(i, now); } - /* 6. And remove any marked circuits... */ - circuit_close_all_marked(); - - /* 8. and blow away any connections that need to die. have to do this now, - * because if we marked a conn for close and left its socket -1, then - * we'll pass it to poll/select and bad things will happen. - */ - close_closeable_connections(); - /* 8b. And if anything in our state is ready to get flushed to disk, we * flush it. */ or_state_save(now); - /* 8c. Do channel cleanup just like for connections */ - channel_run_cleanup(); - channel_listener_run_cleanup(); - /* 11b. check pending unconfigured managed proxies */ if (!net_is_disabled() && pt_proxies_configuration_pending()) pt_configure_remaining_proxies(); @@ -2622,6 +2634,10 @@ do_main_loop(void) schedule_active_linked_connections_event = mainloop_event_postloop_new(schedule_active_linked_connections_cb, NULL); } + if (!postloop_cleanup_ev) { + postloop_cleanup_ev = + mainloop_event_postloop_new(postloop_cleanup_cb, NULL); + } /* initialize dns resolve map, spawn workers if needed */ if (dns_init() < 0) { @@ -3506,6 +3522,7 @@ tor_free_all(int postfork) tor_event_free(initialize_periodic_events_event); mainloop_event_free(directory_all_unreachable_cb_event); mainloop_event_free(schedule_active_linked_connections_event); + mainloop_event_free(postloop_cleanup_ev); #ifdef HAVE_SYSTEMD_209 periodic_timer_free(systemd_watchdog_timer); diff --git a/src/or/main.h b/src/or/main.h index 0e3de7d4be..4f3b84e302 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -61,6 +61,7 @@ void dns_servers_relaunch_checks(void); void reset_all_main_loop_timers(void); void reschedule_descriptor_update_check(void); void reschedule_directory_downloads(void); +void mainloop_schedule_postloop_cleanup(void); MOCK_DECL(long,get_uptime,(void)); MOCK_DECL(void,reset_uptime,(void)); diff --git a/src/test/geoip_dummy b/src/test/geoip_dummy new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/geoip_dummy diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c index 20f6114dc0..0711a113eb 100644 --- a/src/test/test_geoip.c +++ b/src/test/test_geoip.c @@ -444,6 +444,86 @@ test_geoip_load_file(void *arg) tor_free(dhex); } +static void +test_geoip6_load_file(void *arg) +{ + (void)arg; + struct in6_addr iaddr6; + char *contents = NULL; + char *dhex = NULL; + + /* A nonexistant filename should fail. */ + tt_int_op(-1, OP_EQ, + geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope")); + + /* Any lookup attempt should say "-1" because we have no info */ + tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6); + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6)); + + /* Load geiop6 file */ + const char FNAME6[] = SRCDIR "/src/config/geoip6"; + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, FNAME6)); + + /* Check that we loaded some countries; this will fail if there are ever + * fewer than 50 countries in the world. */ + tt_int_op(geoip_get_n_countries(), OP_GE, 50); + + /* Let's see where 2001:4860:4860::8888 (google dns) is. */ + const char *caddr6 = "2001:4860:4860::8888"; + tor_inet_pton(AF_INET6, caddr6, &iaddr6); + int country6 = geoip_get_country_by_ipv6(&iaddr6); + tt_int_op(country6, OP_GE, 1); + + const char *cc6 = geoip_get_country_name(country6); + tt_int_op(strlen(cc6), OP_EQ, 2); + + /* The digest should be set.... */ + tt_str_op("0000000000000000000000000000000000000000", OP_NE, + geoip_db_digest(AF_INET6)); + + /* And it should be set correctly */ + contents = read_file_to_str(FNAME6, RFTS_BIN, NULL); + uint8_t d[DIGEST_LEN]; + crypto_digest((char*)d, contents, strlen(contents)); + dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN)); + tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6)); + + /* Make sure geoip_free_all() works. */ + geoip_free_all(); + tt_int_op(1, OP_EQ, geoip_get_n_countries()); + tt_str_op("??", OP_EQ, geoip_get_country_name(0)); + tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6); + tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6)); + tt_str_op("0000000000000000000000000000000000000000", OP_EQ, + geoip_db_digest(AF_INET6)); + + done: + tor_free(contents); + tor_free(dhex); +} + +static void +test_geoip_load_2nd_file(void *arg) +{ + (void)arg; + + /* Load 1st geoip file */ + const char FNAME[] = SRCDIR "/src/config/geoip"; + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, FNAME)); + + /* Load 2nd geoip (empty) file */ + /* It has to be the same IP address family */ + const char FNAME2[] = SRCDIR "/src/test/geoip_dummy"; + tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, FNAME2)); + + /* Check that there is no geoip information for 8.8.8.8, */ + /* since loading the empty 2nd file should have delete it. */ + int country = geoip_get_country_by_ipv4(0x08080808); + tt_int_op(country, OP_EQ, 0); + + done: ; +} + #define ENT(name) \ { #name, test_ ## name , 0, NULL, NULL } #define FORK(name) \ @@ -459,6 +539,10 @@ struct testcase_t geoip_tests[] = { { "geoip", test_geoip, TT_FORK, NULL, NULL }, { "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL }, { "load_file", test_geoip_load_file, TT_FORK|SKIP_ON_WINDOWS, NULL, NULL }, + { "load_file6", test_geoip6_load_file, TT_FORK | SKIP_ON_WINDOWS, + NULL, NULL }, + { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK | SKIP_ON_WINDOWS, + NULL, NULL }, END_OF_TESTCASES }; |