"Fossies" - the Fresh Open Source Software Archive

Member "tor-0.4.1.6/src/feature/dircommon/voting_schedule.c" (10 Jun 2019, 6504 Bytes) of package /linux/misc/tor-0.4.1.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "voting_schedule.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.4.0.5_vs_0.4.1.5.

    1 /* Copyright (c) 2018-2019, The Tor Project, Inc. */
    2 /* See LICENSE for licensing information */
    3 
    4 /**
    5  * \file voting_schedule.c
    6  * \brief This file contains functions that are from the directory authority
    7  *        subsystem related to voting specifically but used by many part of
    8  *        tor. The full feature is built as part of the dirauth module.
    9  **/
   10 
   11 #define VOTING_SCHEDULE_PRIVATE
   12 #include "feature/dircommon/voting_schedule.h"
   13 
   14 #include "core/or/or.h"
   15 #include "app/config/config.h"
   16 #include "feature/nodelist/networkstatus.h"
   17 
   18 #include "feature/nodelist/networkstatus_st.h"
   19 
   20 /* =====
   21  * Vote scheduling
   22  * ===== */
   23 
   24 /** Return the start of the next interval of size <b>interval</b> (in
   25  * seconds) after <b>now</b>, plus <b>offset</b>. Midnight always
   26  * starts a fresh interval, and if the last interval of a day would be
   27  * truncated to less than half its size, it is rolled into the
   28  * previous interval. */
   29 time_t
   30 voting_schedule_get_start_of_next_interval(time_t now, int interval,
   31                                            int offset)
   32 {
   33   struct tm tm;
   34   time_t midnight_today=0;
   35   time_t midnight_tomorrow;
   36   time_t next;
   37 
   38   tor_gmtime_r(&now, &tm);
   39   tm.tm_hour = 0;
   40   tm.tm_min = 0;
   41   tm.tm_sec = 0;
   42 
   43   if (tor_timegm(&tm, &midnight_today) < 0) {
   44     // LCOV_EXCL_START
   45     log_warn(LD_BUG, "Ran into an invalid time when trying to find midnight.");
   46     // LCOV_EXCL_STOP
   47   }
   48   midnight_tomorrow = midnight_today + (24*60*60);
   49 
   50   next = midnight_today + ((now-midnight_today)/interval + 1)*interval;
   51 
   52   /* Intervals never cross midnight. */
   53   if (next > midnight_tomorrow)
   54     next = midnight_tomorrow;
   55 
   56   /* If the interval would only last half as long as it's supposed to, then
   57    * skip over to the next day. */
   58   if (next + interval/2 > midnight_tomorrow)
   59     next = midnight_tomorrow;
   60 
   61   next += offset;
   62   if (next - interval > now)
   63     next -= interval;
   64 
   65   return next;
   66 }
   67 
   68 /* Populate and return a new voting_schedule_t that can be used to schedule
   69  * voting. The object is allocated on the heap and it's the responsibility of
   70  * the caller to free it. Can't fail. */
   71 static voting_schedule_t *
   72 get_voting_schedule(const or_options_t *options, time_t now, int severity)
   73 {
   74   int interval, vote_delay, dist_delay;
   75   time_t start;
   76   time_t end;
   77   networkstatus_t *consensus;
   78   voting_schedule_t *new_voting_schedule;
   79 
   80   new_voting_schedule = tor_malloc_zero(sizeof(voting_schedule_t));
   81 
   82   consensus = networkstatus_get_live_consensus(now);
   83 
   84   if (consensus) {
   85     interval = (int)( consensus->fresh_until - consensus->valid_after );
   86     vote_delay = consensus->vote_seconds;
   87     dist_delay = consensus->dist_seconds;
   88 
   89     /* Note down the consensus valid after, so that we detect outdated voting
   90      * schedules in case of skewed clocks etc. */
   91     new_voting_schedule->live_consensus_valid_after = consensus->valid_after;
   92   } else {
   93     interval = options->TestingV3AuthInitialVotingInterval;
   94     vote_delay = options->TestingV3AuthInitialVoteDelay;
   95     dist_delay = options->TestingV3AuthInitialDistDelay;
   96   }
   97 
   98   tor_assert(interval > 0);
   99 
  100   if (vote_delay + dist_delay > interval/2)
  101     vote_delay = dist_delay = interval / 4;
  102 
  103   start = new_voting_schedule->interval_starts =
  104     voting_schedule_get_start_of_next_interval(now,interval,
  105                                       options->TestingV3AuthVotingStartOffset);
  106   end = voting_schedule_get_start_of_next_interval(start+1, interval,
  107                                       options->TestingV3AuthVotingStartOffset);
  108 
  109   tor_assert(end > start);
  110 
  111   new_voting_schedule->fetch_missing_signatures = start - (dist_delay/2);
  112   new_voting_schedule->voting_ends = start - dist_delay;
  113   new_voting_schedule->fetch_missing_votes =
  114     start - dist_delay - (vote_delay/2);
  115   new_voting_schedule->voting_starts = start - dist_delay - vote_delay;
  116 
  117   {
  118     char tbuf[ISO_TIME_LEN+1];
  119     format_iso_time(tbuf, new_voting_schedule->interval_starts);
  120     tor_log(severity, LD_DIR,"Choosing expected valid-after time as %s: "
  121             "consensus_set=%d, interval=%d",
  122             tbuf, consensus?1:0, interval);
  123   }
  124 
  125   return new_voting_schedule;
  126 }
  127 
  128 #define voting_schedule_free(s) \
  129   FREE_AND_NULL(voting_schedule_t, voting_schedule_free_, (s))
  130 
  131 /** Frees a voting_schedule_t. This should be used instead of the generic
  132  * tor_free. */
  133 static void
  134 voting_schedule_free_(voting_schedule_t *voting_schedule_to_free)
  135 {
  136   if (!voting_schedule_to_free)
  137     return;
  138   tor_free(voting_schedule_to_free);
  139 }
  140 
  141 voting_schedule_t voting_schedule;
  142 
  143 /* Using the time <b>now</b>, return the next voting valid-after time. */
  144 time_t
  145 voting_schedule_get_next_valid_after_time(void)
  146 {
  147   time_t now = approx_time();
  148   bool need_to_recalculate_voting_schedule = false;
  149 
  150   /* This is a safe guard in order to make sure that the voting schedule
  151    * static object is at least initialized. Using this function with a zeroed
  152    * voting schedule can lead to bugs. */
  153   if (fast_mem_is_zero((const char *) &voting_schedule,
  154                       sizeof(voting_schedule))) {
  155     need_to_recalculate_voting_schedule = true;
  156     goto done; /* no need for next check if we have to recalculate anyway */
  157   }
  158 
  159   /* Also make sure we are not using an outdated voting schedule. If we have a
  160    * newer consensus, make sure we recalculate the voting schedule. */
  161   const networkstatus_t *ns = networkstatus_get_live_consensus(now);
  162   if (ns && ns->valid_after != voting_schedule.live_consensus_valid_after) {
  163     log_info(LD_DIR, "Voting schedule is outdated: recalculating (%d/%d)",
  164              (int) ns->valid_after,
  165              (int) voting_schedule.live_consensus_valid_after);
  166     need_to_recalculate_voting_schedule = true;
  167   }
  168 
  169  done:
  170   if (need_to_recalculate_voting_schedule) {
  171     voting_schedule_recalculate_timing(get_options(), approx_time());
  172     voting_schedule.created_on_demand = 1;
  173   }
  174 
  175   return voting_schedule.interval_starts;
  176 }
  177 
  178 /** Set voting_schedule to hold the timing for the next vote we should be
  179  * doing. All type of tor do that because HS subsystem needs the timing as
  180  * well to function properly. */
  181 void
  182 voting_schedule_recalculate_timing(const or_options_t *options, time_t now)
  183 {
  184   voting_schedule_t *new_voting_schedule;
  185 
  186   /* get the new voting schedule */
  187   new_voting_schedule = get_voting_schedule(options, now, LOG_INFO);
  188   tor_assert(new_voting_schedule);
  189 
  190   /* Fill in the global static struct now */
  191   memcpy(&voting_schedule, new_voting_schedule, sizeof(voting_schedule));
  192   voting_schedule_free(new_voting_schedule);
  193 }
  194