Index: /home/karsten/tor/tor-trunk-155-patch3/ChangeLog =================================================================== --- /home/karsten/tor/tor-trunk-155-patch3/ChangeLog (revision 17050) +++ /home/karsten/tor/tor-trunk-155-patch3/ChangeLog (working copy) @@ -3,6 +3,8 @@ - Now NodeFamily and MyFamily config options allow spaces in identity fingerprints, so it's easier to paste them in. Suggested by Lucky Green. + - Increase number of server-side introduction points based on number + of recent hidden service requests (based on work by Christian Wilms). Changes in version 0.2.1.6-alpha - 2008-09-30 Index: /home/karsten/tor/tor-trunk-155-patch3/src/or/circuituse.c =================================================================== --- /home/karsten/tor/tor-trunk-155-patch3/src/or/circuituse.c (revision 17050) +++ /home/karsten/tor/tor-trunk-155-patch3/src/or/circuituse.c (working copy) @@ -464,7 +464,8 @@ } /* Third, see if we need any more hidden service (server) circuits. */ - if (num_rend_services() && num_uptime_internal < 3) { + if (num_rend_services() && + num_uptime_internal < rend_internal_circuits_needed()) { flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL); log_info(LD_CIRC, Index: /home/karsten/tor/tor-trunk-155-patch3/src/or/main.c =================================================================== --- /home/karsten/tor/tor-trunk-155-patch3/src/or/main.c (revision 17050) +++ /home/karsten/tor/tor-trunk-155-patch3/src/or/main.c (working copy) @@ -841,6 +841,7 @@ static time_t time_to_recheck_bandwidth = 0; static time_t time_to_check_for_expired_networkstatus = 0; static time_t time_to_dump_geoip_stats = 0; + static time_t time_to_update_request_history = 0; or_options_t *options = get_options(); int i; int have_dir_info; @@ -1169,6 +1170,14 @@ #define BRIDGE_STATUSFILE_INTERVAL (30*60) time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; } + + /** 11. Update history of requests to our hidden services, so that + * we can better estimate the number of internal circuits. */ + if (time_to_update_request_history < now) { + rend_update_request_history(now); +#define REND_REQUEST_HISTORY_UPDATE_INTERVAL (5 * 60) + time_to_update_request_history = now+REND_REQUEST_HISTORY_UPDATE_INTERVAL; + } } /** Libevent timer: used to invoke second_elapsed_callback() once per Index: /home/karsten/tor/tor-trunk-155-patch3/src/or/or.h =================================================================== --- /home/karsten/tor/tor-trunk-155-patch3/src/or/or.h (revision 17050) +++ /home/karsten/tor/tor-trunk-155-patch3/src/or/or.h (working copy) @@ -4038,6 +4038,10 @@ void rend_service_dump_stats(int severity); void rend_service_free_all(void); +int rend_internal_circuits_needed(void); +void rend_update_request_history(time_t now); +void rend_service_request_history_free_all(void); + /********************************* rendmid.c *******************************/ int rend_mid_establish_intro(or_circuit_t *circ, const char *request, size_t request_len); Index: /home/karsten/tor/tor-trunk-155-patch3/src/or/rendservice.c =================================================================== --- /home/karsten/tor/tor-trunk-155-patch3/src/or/rendservice.c (revision 17050) +++ /home/karsten/tor/tor-trunk-155-patch3/src/or/rendservice.c (working copy) @@ -831,6 +831,87 @@ } DIGESTMAP_FOREACH_END; } +/* + * Logic to record requests to our hidden services and set the number + * of pre-established internal circuits appropriately. + */ + +/** The duration of our hidden service request history that we use to + * better predict the number of internal circuits. */ +#define REND_REQUEST_HISTORY_PERIOD (15 * 60) + +/** Number of requests per minute that justify an additional internal + * circuit. */ +#define REND_REQUESTS_INTERNAL_CIRCUITS_RATIO 5 + +/** The maximum number of internal circuits. */ +#define REND_INTERNAL_CIRCUITS_MAX 12 + +/** History of request to any of our hidden services that is used to help + * predict the number of pre-established internal circuits. */ +static smartlist_t *request_history = NULL; + +/** Release all the storage held in last_hid_serv_requests. + */ +void +rend_service_request_history_free_all(void) +{ + if (!request_history) { + return; + } + SMARTLIST_FOREACH(request_history, time_t *, r, tor_free(r);); + request_history = NULL; +} + +/** The number of internal circuits that we should hold in stock as a + * function of requests. */ +static int internal_circuits_needed = 3; + +/** Add a request to one of our hidden services to the request history. */ +static void +rend_add_request(time_t now) +{ + time_t *request_ptr; + if (!request_history) + request_history = smartlist_create(); + request_ptr = tor_malloc_zero(sizeof(time_t *)); + *request_ptr = now; + smartlist_add(request_history, request_ptr); +} + +/** Determine the number of internal circuits that we should hold in stock + * in the future and prune too old requests. */ +void +rend_update_request_history(time_t now) +{ + time_t cutoff = 0; + int num_requests = 0; + if (!request_history) + return; + cutoff = now - REND_REQUEST_HISTORY_PERIOD; + SMARTLIST_FOREACH(request_history, time_t *, t, { + if (*t < cutoff) { + tor_free(t); + SMARTLIST_DEL_CURRENT(request_history, t); + } else + num_requests++; + }); + internal_circuits_needed = 3 + (num_requests / + (REND_REQUEST_HISTORY_PERIOD / 60 * + REND_REQUESTS_INTERNAL_CIRCUITS_RATIO)); + if (internal_circuits_needed > REND_INTERNAL_CIRCUITS_MAX) + internal_circuits_needed = REND_INTERNAL_CIRCUITS_MAX; + log_info(LD_REND, "Setting the number of pre-built internal circuits to %d", + internal_circuits_needed); +} + +/** Return the number of internal circuits that we should hold in stock. */ +int +rend_internal_circuits_needed(void) +{ + return internal_circuits_needed; +} + /****** * Handle cells ******/ @@ -1114,6 +1195,10 @@ /* help predict this next time */ rep_hist_note_used_internal(time(NULL), circ_needs_uptime, 1); + /* Remember service request to better predict the required number + * of internal circuits in the future. */ + rend_add_request(time(NULL)); + /* Launch a circuit to alice's chosen rendezvous point. */ for (i=0;i