LCOV - code coverage report
Current view: top level - feature/hibernate - hibernate.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 293 505 58.0 %
Date: 2021-11-24 03:28:48 Functions: 28 35 80.0 %

          Line data    Source code
       1             : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       2             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       3             : /* See LICENSE for licensing information */
       4             : 
       5             : /**
       6             :  * \file hibernate.c
       7             :  * \brief Functions to close listeners, stop allowing new circuits,
       8             :  * etc in preparation for closing down or going dormant; and to track
       9             :  * bandwidth and time intervals to know when to hibernate and when to
      10             :  * stop hibernating.
      11             :  *
      12             :  * Ordinarily a Tor relay is "Live".
      13             :  *
      14             :  * A live relay can stop accepting connections for one of two reasons: either
      15             :  * it is trying to conserve bandwidth because of bandwidth accounting rules
      16             :  * ("soft hibernation"), or it is about to shut down ("exiting").
      17             :  **/
      18             : 
      19             : /*
      20             : hibernating, phase 1:
      21             :   - send destroy in response to create cells
      22             :   - send end (policy failed) in response to begin cells
      23             :   - close an OR conn when it has no circuits
      24             : 
      25             : hibernating, phase 2:
      26             :   (entered when bandwidth hard limit reached)
      27             :   - close all OR/AP/exit conns)
      28             : */
      29             : 
      30             : #define HIBERNATE_PRIVATE
      31             : #include "core/or/or.h"
      32             : #include "core/or/channel.h"
      33             : #include "core/or/channeltls.h"
      34             : #include "app/config/config.h"
      35             : #include "core/mainloop/connection.h"
      36             : #include "core/or/connection_edge.h"
      37             : #include "core/or/connection_or.h"
      38             : #include "feature/control/control_events.h"
      39             : #include "lib/crypt_ops/crypto_rand.h"
      40             : #include "lib/defs/time.h"
      41             : #include "feature/hibernate/hibernate.h"
      42             : #include "core/mainloop/mainloop.h"
      43             : #include "feature/relay/router.h"
      44             : #include "app/config/statefile.h"
      45             : #include "lib/evloop/compat_libevent.h"
      46             : 
      47             : #include "core/or/or_connection_st.h"
      48             : #include "app/config/or_state_st.h"
      49             : 
      50             : #ifdef HAVE_UNISTD_H
      51             : #include <unistd.h>
      52             : #endif
      53             : 
      54             : #ifdef HAVE_SYSTEMD
      55             : #  if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
      56             : /* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse
      57             :  * Coverity. Here's a kludge to unconfuse it.
      58             :  */
      59             : #   define __INCLUDE_LEVEL__ 2
      60             : #endif /* defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__) */
      61             : #include <systemd/sd-daemon.h>
      62             : #endif /* defined(HAVE_SYSTEMD) */
      63             : 
      64             : /** Are we currently awake, asleep, running out of bandwidth, or shutting
      65             :  * down? */
      66             : static hibernate_state_t hibernate_state = HIBERNATE_STATE_INITIAL;
      67             : /** If are hibernating, when do we plan to wake up? Set to 0 if we
      68             :  * aren't hibernating. */
      69             : static time_t hibernate_end_time = 0;
      70             : /** If we are shutting down, when do we plan to finally exit? Set to 0 if we
      71             :  * aren't shutting down. (This is obsolete; scheduled shutdowns are supposed
      72             :  * to happen from mainloop_schedule_shutdown() now.) */
      73             : static time_t shutdown_time = 0;
      74             : 
      75             : /** A timed event that we'll use when it's time to wake up from
      76             :  * hibernation. */
      77             : static mainloop_event_t *wakeup_event = NULL;
      78             : 
      79             : /** Possible accounting periods. */
      80             : typedef enum {
      81             :   UNIT_MONTH=1, UNIT_WEEK=2, UNIT_DAY=3,
      82             : } time_unit_t;
      83             : 
      84             : /*
      85             :  * @file hibernate.c
      86             :  *
      87             :  * <h4>Accounting</h4>
      88             :  * Accounting is designed to ensure that no more than N bytes are sent in
      89             :  * either direction over a given interval (currently, one month, one week, or
      90             :  * one day) We could
      91             :  * try to do this by choking our bandwidth to a trickle, but that
      92             :  * would make our streams useless.  Instead, we estimate what our
      93             :  * bandwidth usage will be, and guess how long we'll be able to
      94             :  * provide that much bandwidth before hitting our limit.  We then
      95             :  * choose a random time within the accounting interval to come up (so
      96             :  * that we don't get 50 Tors running on the 1st of the month and none
      97             :  * on the 30th).
      98             :  *
      99             :  * Each interval runs as follows:
     100             :  *
     101             :  * <ol>
     102             :  * <li>We guess our bandwidth usage, based on how much we used
     103             :  *     last time.  We choose a "wakeup time" within the interval to come up.
     104             :  * <li>Until the chosen wakeup time, we hibernate.
     105             :  * <li> We come up at the wakeup time, and provide bandwidth until we are
     106             :  *    "very close" to running out.
     107             :  * <li> Then we go into low-bandwidth mode, and stop accepting new
     108             :  *    connections, but provide bandwidth until we run out.
     109             :  * <li> Then we hibernate until the end of the interval.
     110             :  *
     111             :  * If the interval ends before we run out of bandwidth, we go back to
     112             :  * step one.
     113             :  *
     114             :  * Accounting is controlled by the AccountingMax, AccountingRule, and
     115             :  * AccountingStart options.
     116             :  */
     117             : 
     118             : /** How many bytes have we read in this accounting interval? */
     119             : static uint64_t n_bytes_read_in_interval = 0;
     120             : /** How many bytes have we written in this accounting interval? */
     121             : static uint64_t n_bytes_written_in_interval = 0;
     122             : /** How many seconds have we been running this interval? */
     123             : static uint32_t n_seconds_active_in_interval = 0;
     124             : /** How many seconds were we active in this interval before we hit our soft
     125             :  * limit? */
     126             : static int n_seconds_to_hit_soft_limit = 0;
     127             : /** When in this interval was the soft limit hit. */
     128             : static time_t soft_limit_hit_at = 0;
     129             : /** How many bytes had we read/written when we hit the soft limit? */
     130             : static uint64_t n_bytes_at_soft_limit = 0;
     131             : /** When did this accounting interval start? */
     132             : static time_t interval_start_time = 0;
     133             : /** When will this accounting interval end? */
     134             : static time_t interval_end_time = 0;
     135             : /** How far into the accounting interval should we hibernate? */
     136             : static time_t interval_wakeup_time = 0;
     137             : /** How much bandwidth do we 'expect' to use per minute?  (0 if we have no
     138             :  * info from the last period.) */
     139             : static uint64_t expected_bandwidth_usage = 0;
     140             : /** What unit are we using for our accounting? */
     141             : static time_unit_t cfg_unit = UNIT_MONTH;
     142             : 
     143             : /** How many days,hours,minutes into each unit does our accounting interval
     144             :  * start? */
     145             : /** @{ */
     146             : static int cfg_start_day = 0,
     147             :            cfg_start_hour = 0,
     148             :            cfg_start_min = 0;
     149             : /** @} */
     150             : 
     151             : static const char *hibernate_state_to_string(hibernate_state_t state);
     152             : static void reset_accounting(time_t now);
     153             : static int read_bandwidth_usage(void);
     154             : static time_t start_of_accounting_period_after(time_t now);
     155             : static time_t start_of_accounting_period_containing(time_t now);
     156             : static void accounting_set_wakeup_time(void);
     157             : static void on_hibernate_state_change(hibernate_state_t prev_state);
     158             : static void hibernate_schedule_wakeup_event(time_t now, time_t end_time);
     159             : static void wakeup_event_callback(mainloop_event_t *ev, void *data);
     160             : 
     161             : /**
     162             :  * Return the human-readable name for the hibernation state <b>state</b>
     163             :  */
     164             : static const char *
     165          14 : hibernate_state_to_string(hibernate_state_t state)
     166             : {
     167          14 :   static char buf[64];
     168          14 :   switch (state) {
     169             :     case HIBERNATE_STATE_EXITING: return "EXITING";
     170           0 :     case HIBERNATE_STATE_LOWBANDWIDTH: return "SOFT";
     171           4 :     case HIBERNATE_STATE_DORMANT: return "HARD";
     172          10 :     case HIBERNATE_STATE_INITIAL:
     173             :     case HIBERNATE_STATE_LIVE:
     174          10 :       return "AWAKE";
     175           0 :     default:
     176           0 :       log_warn(LD_BUG, "unknown hibernate state %d", state);
     177           0 :       tor_snprintf(buf, sizeof(buf), "unknown [%d]", state);
     178           0 :       return buf;
     179             :   }
     180             : }
     181             : 
     182             : /* ************
     183             :  * Functions for bandwidth accounting.
     184             :  * ************/
     185             : 
     186             : /** Configure accounting start/end time settings based on
     187             :  * options->AccountingStart.  Return 0 on success, -1 on failure. If
     188             :  * <b>validate_only</b> is true, do not change the current settings. */
     189             : int
     190         480 : accounting_parse_options(const or_options_t *options, int validate_only)
     191             : {
     192         480 :   time_unit_t unit;
     193         480 :   int ok, idx;
     194         480 :   long d,h,m;
     195         480 :   smartlist_t *items;
     196         480 :   const char *v = options->AccountingStart;
     197         480 :   const char *s;
     198         480 :   char *cp;
     199             : 
     200         480 :   if (!v) {
     201         476 :     if (!validate_only) {
     202           4 :       cfg_unit = UNIT_MONTH;
     203           4 :       cfg_start_day = 1;
     204           4 :       cfg_start_hour = 0;
     205           4 :       cfg_start_min = 0;
     206             :     }
     207         476 :     return 0;
     208             :   }
     209             : 
     210           4 :   items = smartlist_new();
     211           4 :   smartlist_split_string(items, v, NULL,
     212             :                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0);
     213           4 :   if (smartlist_len(items)<2) {
     214           1 :     log_warn(LD_CONFIG, "Too few arguments to AccountingStart");
     215           1 :     goto err;
     216             :   }
     217           3 :   s = smartlist_get(items,0);
     218           3 :   if (0==strcasecmp(s, "month")) {
     219             :     unit = UNIT_MONTH;
     220           3 :   } else if (0==strcasecmp(s, "week")) {
     221             :     unit = UNIT_WEEK;
     222           3 :   } else if (0==strcasecmp(s, "day")) {
     223             :     unit = UNIT_DAY;
     224             :   } else {
     225           0 :     log_warn(LD_CONFIG,
     226             :              "Unrecognized accounting unit '%s': only 'month', 'week',"
     227             :              " and 'day' are supported.", s);
     228           0 :     goto err;
     229             :   }
     230             : 
     231           0 :   switch (unit) {
     232             :   case UNIT_WEEK:
     233           0 :     d = tor_parse_long(smartlist_get(items,1), 10, 1, 7, &ok, NULL);
     234           0 :     if (!ok) {
     235           0 :       log_warn(LD_CONFIG, "Weekly accounting must begin on a day between "
     236             :                "1 (Monday) and 7 (Sunday)");
     237           0 :       goto err;
     238             :     }
     239             :     break;
     240             :   case UNIT_MONTH:
     241           0 :     d = tor_parse_long(smartlist_get(items,1), 10, 1, 28, &ok, NULL);
     242           0 :     if (!ok) {
     243           0 :       log_warn(LD_CONFIG, "Monthly accounting must begin on a day between "
     244             :                "1 and 28");
     245           0 :       goto err;
     246             :     }
     247             :     break;
     248             :   case UNIT_DAY:
     249             :     d = 0;
     250             :     break;
     251             :     /* Coverity dislikes unreachable default cases; some compilers warn on
     252             :      * switch statements missing a case.  Tell Coverity not to worry. */
     253             :     /* coverity[dead_error_begin] */
     254             :   default:
     255             :     tor_assert(0);
     256             :   }
     257             : 
     258           3 :   idx = unit==UNIT_DAY?1:2;
     259           3 :   if (smartlist_len(items) != (idx+1)) {
     260           0 :     log_warn(LD_CONFIG,"Accounting unit '%s' requires %d argument%s.",
     261             :              s, idx, (idx>1)?"s":"");
     262           0 :     goto err;
     263             :   }
     264           3 :   s = smartlist_get(items, idx);
     265           3 :   h = tor_parse_long(s, 10, 0, 23, &ok, &cp);
     266           3 :   if (!ok) {
     267           0 :     log_warn(LD_CONFIG,"Accounting start time not parseable: bad hour.");
     268           0 :     goto err;
     269             :   }
     270           3 :   if (!cp || *cp!=':') {
     271           0 :     log_warn(LD_CONFIG,
     272             :              "Accounting start time not parseable: not in HH:MM format");
     273           0 :     goto err;
     274             :   }
     275           3 :   m = tor_parse_long(cp+1, 10, 0, 59, &ok, &cp);
     276           3 :   if (!ok) {
     277           0 :     log_warn(LD_CONFIG, "Accounting start time not parseable: bad minute");
     278           0 :     goto err;
     279             :   }
     280           3 :   if (!cp || *cp!='\0') {
     281           0 :     log_warn(LD_CONFIG,
     282             :              "Accounting start time not parseable: not in HH:MM format");
     283           0 :     goto err;
     284             :   }
     285             : 
     286           3 :   if (!validate_only) {
     287           0 :     cfg_unit = unit;
     288           0 :     cfg_start_day = (int)d;
     289           0 :     cfg_start_hour = (int)h;
     290           0 :     cfg_start_min = (int)m;
     291             :   }
     292           9 :   SMARTLIST_FOREACH(items, char *, item, tor_free(item));
     293           3 :   smartlist_free(items);
     294           3 :   return 0;
     295           1 :  err:
     296           2 :   SMARTLIST_FOREACH(items, char *, item, tor_free(item));
     297           1 :   smartlist_free(items);
     298           1 :   return -1;
     299             : }
     300             : 
     301             : /** If we want to manage the accounting system and potentially
     302             :  * hibernate, return 1, else return 0.
     303             :  */
     304          27 : MOCK_IMPL(int,
     305             : accounting_is_enabled,(const or_options_t *options))
     306             : {
     307          27 :   if (options->AccountingMax)
     308           1 :     return 1;
     309             :   return 0;
     310             : }
     311             : 
     312             : /** If accounting is enabled, return how long (in seconds) this
     313             :  * interval lasts. */
     314             : int
     315           0 : accounting_get_interval_length(void)
     316             : {
     317           0 :   return (int)(interval_end_time - interval_start_time);
     318             : }
     319             : 
     320             : /** Return the time at which the current accounting interval will end. */
     321           0 : MOCK_IMPL(time_t,
     322             : accounting_get_end_time,(void))
     323             : {
     324           0 :   return interval_end_time;
     325             : }
     326             : 
     327             : /** Called from connection.c to tell us that <b>seconds</b> seconds have
     328             :  * passed, <b>n_read</b> bytes have been read, and <b>n_written</b>
     329             :  * bytes have been written. */
     330             : void
     331           8 : accounting_add_bytes(size_t n_read, size_t n_written, int seconds)
     332             : {
     333           8 :   n_bytes_read_in_interval += n_read;
     334           8 :   n_bytes_written_in_interval += n_written;
     335             :   /* If we haven't been called in 10 seconds, we're probably jumping
     336             :    * around in time. */
     337           8 :   n_seconds_active_in_interval += (seconds < 10) ? seconds : 0;
     338           8 : }
     339             : 
     340             : /** If get_end, return the end of the accounting period that contains
     341             :  * the time <b>now</b>.  Else, return the start of the accounting
     342             :  * period that contains the time <b>now</b> */
     343             : static time_t
     344           9 : edge_of_accounting_period_containing(time_t now, int get_end)
     345             : {
     346           9 :   int before;
     347           9 :   struct tm tm;
     348           9 :   tor_localtime_r(&now, &tm);
     349             : 
     350             :   /* Set 'before' to true iff the current time is before the hh:mm
     351             :    * changeover time for today. */
     352           9 :   before = tm.tm_hour < cfg_start_hour ||
     353           4 :     (tm.tm_hour == cfg_start_hour && tm.tm_min < cfg_start_min);
     354             : 
     355             :   /* Dispatch by unit.  First, find the start day of the given period;
     356             :    * then, if get_end is true, increment to the end day. */
     357           9 :   switch (cfg_unit)
     358             :     {
     359           9 :     case UNIT_MONTH: {
     360             :       /* If this is before the Nth, we want the Nth of last month. */
     361           9 :       if (tm.tm_mday < cfg_start_day ||
     362           0 :           (tm.tm_mday == cfg_start_day && before)) {
     363           0 :         --tm.tm_mon;
     364             :       }
     365             :       /* Otherwise, the month is correct. */
     366           9 :       tm.tm_mday = cfg_start_day;
     367           9 :       if (get_end)
     368           4 :         ++tm.tm_mon;
     369             :       break;
     370             :     }
     371           0 :     case UNIT_WEEK: {
     372             :       /* What is the 'target' day of the week in struct tm format? (We
     373             :          say Sunday==7; struct tm says Sunday==0.) */
     374           0 :       int wday = cfg_start_day % 7;
     375             :       /* How many days do we subtract from today to get to the right day? */
     376           0 :       int delta = (7+tm.tm_wday-wday)%7;
     377             :       /* If we are on the right day, but the changeover hasn't happened yet,
     378             :        * then subtract a whole week. */
     379           0 :       if (delta == 0 && before)
     380           0 :         delta = 7;
     381           0 :       tm.tm_mday -= delta;
     382           0 :       if (get_end)
     383           0 :         tm.tm_mday += 7;
     384             :       break;
     385             :     }
     386           0 :     case UNIT_DAY:
     387           0 :       if (before)
     388           0 :         --tm.tm_mday;
     389           0 :       if (get_end)
     390           0 :         ++tm.tm_mday;
     391             :       break;
     392             :     default:
     393           0 :       tor_assert(0);
     394             :   }
     395             : 
     396           9 :   tm.tm_hour = cfg_start_hour;
     397           9 :   tm.tm_min = cfg_start_min;
     398           9 :   tm.tm_sec = 0;
     399           9 :   tm.tm_isdst = -1; /* Autodetect DST */
     400           9 :   return mktime(&tm);
     401             : }
     402             : 
     403             : /** Return the start of the accounting period containing the time
     404             :  * <b>now</b>. */
     405             : static time_t
     406           5 : start_of_accounting_period_containing(time_t now)
     407             : {
     408           5 :   return edge_of_accounting_period_containing(now, 0);
     409             : }
     410             : 
     411             : /** Return the start of the accounting period that comes after the one
     412             :  * containing the time <b>now</b>. */
     413             : static time_t
     414           4 : start_of_accounting_period_after(time_t now)
     415             : {
     416           4 :   return edge_of_accounting_period_containing(now, 1);
     417             : }
     418             : 
     419             : /** Return the length of the accounting period containing the time
     420             :  * <b>now</b>. */
     421             : static long
     422           0 : length_of_accounting_period_containing(time_t now)
     423             : {
     424           0 :   return edge_of_accounting_period_containing(now, 1) -
     425           0 :     edge_of_accounting_period_containing(now, 0);
     426             : }
     427             : 
     428             : /** Initialize the accounting subsystem. */
     429             : void
     430           4 : configure_accounting(time_t now)
     431             : {
     432           4 :   time_t s_now;
     433             :   /* Try to remember our recorded usage. */
     434           4 :   if (!interval_start_time)
     435           1 :     read_bandwidth_usage(); /* If we fail, we'll leave values at zero, and
     436             :                              * reset below.*/
     437             : 
     438           4 :   s_now = start_of_accounting_period_containing(now);
     439             : 
     440           4 :   if (!interval_start_time) {
     441             :     /* We didn't have recorded usage; Start a new interval. */
     442           1 :     log_info(LD_ACCT, "Starting new accounting interval.");
     443           1 :     reset_accounting(now);
     444           3 :   } else if (s_now == interval_start_time) {
     445           3 :     log_info(LD_ACCT, "Continuing accounting interval.");
     446             :     /* We are in the interval we thought we were in. Do nothing.*/
     447           3 :     interval_end_time = start_of_accounting_period_after(interval_start_time);
     448             :   } else {
     449           0 :     long duration =
     450           0 :       length_of_accounting_period_containing(interval_start_time);
     451           0 :     double delta = ((double)(s_now - interval_start_time)) / duration;
     452           0 :     if (-0.50 <= delta && delta <= 0.50) {
     453             :       /* The start of the period is now a little later or earlier than we
     454             :        * remembered.  That's fine; we might lose some bytes we could otherwise
     455             :        * have written, but better to err on the side of obeying accounting
     456             :        * settings. */
     457           0 :       log_info(LD_ACCT, "Accounting interval moved by %.02f%%; "
     458             :                "that's fine.", delta*100);
     459           0 :       interval_end_time = start_of_accounting_period_after(now);
     460           0 :     } else if (delta >= 0.99) {
     461             :       /* This is the regular time-moved-forward case; don't be too noisy
     462             :        * about it or people will complain */
     463           0 :       log_info(LD_ACCT, "Accounting interval elapsed; starting a new one");
     464           0 :       reset_accounting(now);
     465             :     } else {
     466           0 :       log_warn(LD_ACCT,
     467             :                "Mismatched accounting interval: moved by %.02f%%. "
     468             :                "Starting a fresh one.", delta*100);
     469           0 :       reset_accounting(now);
     470             :     }
     471             :   }
     472           4 :   accounting_set_wakeup_time();
     473           4 : }
     474             : 
     475             : /** Return the relevant number of bytes sent/received this interval
     476             :  * based on the set AccountingRule */
     477             : uint64_t
     478          17 : get_accounting_bytes(void)
     479             : {
     480          17 :   if (get_options()->AccountingRule == ACCT_SUM)
     481           4 :     return n_bytes_read_in_interval+n_bytes_written_in_interval;
     482          13 :   else if (get_options()->AccountingRule == ACCT_IN)
     483           4 :     return n_bytes_read_in_interval;
     484           9 :   else if (get_options()->AccountingRule == ACCT_OUT)
     485           4 :     return n_bytes_written_in_interval;
     486             :   else
     487           5 :     return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval);
     488             : }
     489             : 
     490             : /** Set expected_bandwidth_usage based on how much we sent/received
     491             :  * per minute last interval (if we were up for at least 30 minutes),
     492             :  * or based on our declared bandwidth otherwise. */
     493             : static void
     494           1 : update_expected_bandwidth(void)
     495             : {
     496           1 :   uint64_t expected;
     497           1 :   const or_options_t *options= get_options();
     498           2 :   uint64_t max_configured = (options->RelayBandwidthRate > 0 ?
     499             :                              options->RelayBandwidthRate :
     500           1 :                              options->BandwidthRate) * 60;
     501             :   /* max_configured is the larger of bytes read and bytes written
     502             :    * If we are accounting based on sum, worst case is both are
     503             :    * at max, doubling the expected sum of bandwidth */
     504           1 :   if (get_options()->AccountingRule == ACCT_SUM)
     505           0 :     max_configured *= 2;
     506             : 
     507             : #define MIN_TIME_FOR_MEASUREMENT (1800)
     508             : 
     509           1 :   if (soft_limit_hit_at > interval_start_time && n_bytes_at_soft_limit &&
     510           0 :       (soft_limit_hit_at - interval_start_time) > MIN_TIME_FOR_MEASUREMENT) {
     511             :     /* If we hit our soft limit last time, only count the bytes up to that
     512             :      * time. This is a better predictor of our actual bandwidth than
     513             :      * considering the entirety of the last interval, since we likely started
     514             :      * using bytes very slowly once we hit our soft limit. */
     515           0 :     expected = n_bytes_at_soft_limit /
     516           0 :       (soft_limit_hit_at - interval_start_time);
     517           0 :     expected /= 60;
     518           1 :   } else if (n_seconds_active_in_interval >= MIN_TIME_FOR_MEASUREMENT) {
     519             :     /* Otherwise, we either measured enough time in the last interval but
     520             :      * never hit our soft limit, or we're using a state file from a Tor that
     521             :      * doesn't know to store soft-limit info.  Just take rate at which
     522             :      * we were reading/writing in the last interval as our expected rate.
     523             :      */
     524           0 :     uint64_t used = get_accounting_bytes();
     525           0 :     expected = used / (n_seconds_active_in_interval / 60);
     526             :   } else {
     527             :     /* If we haven't gotten enough data last interval, set 'expected'
     528             :      * to 0.  This will set our wakeup to the start of the interval.
     529             :      * Next interval, we'll choose our starting time based on how much
     530             :      * we sent this interval.
     531             :      */
     532             :     expected = 0;
     533             :   }
     534           1 :   if (expected > max_configured)
     535             :     expected = max_configured;
     536           1 :   expected_bandwidth_usage = expected;
     537           1 : }
     538             : 
     539             : /** Called at the start of a new accounting interval: reset our
     540             :  * expected bandwidth usage based on what happened last time, set up
     541             :  * the start and end of the interval, and clear byte/time totals.
     542             :  */
     543             : static void
     544           1 : reset_accounting(time_t now)
     545             : {
     546           1 :   log_info(LD_ACCT, "Starting new accounting interval.");
     547           1 :   update_expected_bandwidth();
     548           1 :   interval_start_time = start_of_accounting_period_containing(now);
     549           1 :   interval_end_time = start_of_accounting_period_after(interval_start_time);
     550           1 :   n_bytes_read_in_interval = 0;
     551           1 :   n_bytes_written_in_interval = 0;
     552           1 :   n_seconds_active_in_interval = 0;
     553           1 :   n_bytes_at_soft_limit = 0;
     554           1 :   soft_limit_hit_at = 0;
     555           1 :   n_seconds_to_hit_soft_limit = 0;
     556           1 : }
     557             : 
     558             : /** Return true iff we should save our bandwidth usage to disk. */
     559             : static inline int
     560           3 : time_to_record_bandwidth_usage(time_t now)
     561             : {
     562             :   /* Note every 600 sec */
     563             : #define NOTE_INTERVAL (600)
     564             :   /* Or every 20 megabytes */
     565             : #define NOTE_BYTES (20*1024*1024)
     566           3 :   static uint64_t last_read_bytes_noted = 0;
     567           3 :   static uint64_t last_written_bytes_noted = 0;
     568           3 :   static time_t last_time_noted = 0;
     569             : 
     570           3 :   if (last_time_noted + NOTE_INTERVAL <= now ||
     571           2 :       last_read_bytes_noted + NOTE_BYTES <= n_bytes_read_in_interval ||
     572           2 :       last_written_bytes_noted + NOTE_BYTES <= n_bytes_written_in_interval ||
     573           2 :       (interval_end_time && interval_end_time <= now)) {
     574           3 :     last_time_noted = now;
     575           3 :     last_read_bytes_noted = n_bytes_read_in_interval;
     576           3 :     last_written_bytes_noted = n_bytes_written_in_interval;
     577           3 :     return 1;
     578             :   }
     579             :   return 0;
     580             : }
     581             : 
     582             : /** Invoked once per second.  Checks whether it is time to hibernate,
     583             :  * record bandwidth used, etc.  */
     584             : void
     585           3 : accounting_run_housekeeping(time_t now)
     586             : {
     587           3 :   if (now >= interval_end_time) {
     588           3 :     configure_accounting(now);
     589             :   }
     590           3 :   if (time_to_record_bandwidth_usage(now)) {
     591           3 :     if (accounting_record_bandwidth_usage(now, get_or_state())) {
     592           0 :       log_warn(LD_FS, "Couldn't record bandwidth usage to disk.");
     593             :     }
     594             :   }
     595           3 : }
     596             : 
     597             : /** Based on our interval and our estimated bandwidth, choose a
     598             :  * deterministic (but random-ish) time to wake up. */
     599             : static void
     600           4 : accounting_set_wakeup_time(void)
     601             : {
     602           4 :   char digest[DIGEST_LEN];
     603           4 :   crypto_digest_t *d_env;
     604           4 :   uint64_t time_to_exhaust_bw;
     605           4 :   int time_to_consider;
     606             : 
     607           4 :   if (! server_identity_key_is_set()) {
     608           4 :     if (init_keys() < 0) {
     609           0 :       log_err(LD_BUG, "Error initializing keys");
     610           0 :       tor_assert(0);
     611             :     }
     612             :   }
     613             : 
     614           4 :   if (server_identity_key_is_set()) {
     615           0 :     char buf[ISO_TIME_LEN+1];
     616           0 :     format_iso_time(buf, interval_start_time);
     617             : 
     618           0 :     if (crypto_pk_get_digest(get_server_identity_key(), digest) < 0) {
     619           0 :       log_err(LD_BUG, "Error getting our key's digest.");
     620           0 :       tor_assert(0);
     621             :     }
     622             : 
     623           0 :     d_env = crypto_digest_new();
     624           0 :     crypto_digest_add_bytes(d_env, buf, ISO_TIME_LEN);
     625           0 :     crypto_digest_add_bytes(d_env, digest, DIGEST_LEN);
     626           0 :     crypto_digest_get_digest(d_env, digest, DIGEST_LEN);
     627           0 :     crypto_digest_free(d_env);
     628             :   } else {
     629           4 :     crypto_rand(digest, DIGEST_LEN);
     630             :   }
     631             : 
     632           4 :   if (!expected_bandwidth_usage) {
     633           4 :     char buf1[ISO_TIME_LEN+1];
     634           4 :     char buf2[ISO_TIME_LEN+1];
     635           4 :     format_local_iso_time(buf1, interval_start_time);
     636           4 :     format_local_iso_time(buf2, interval_end_time);
     637           4 :     interval_wakeup_time = interval_start_time;
     638             : 
     639           4 :     log_notice(LD_ACCT,
     640             :            "Configured hibernation. This interval begins at %s "
     641             :            "and ends at %s. We have no prior estimate for bandwidth, so "
     642             :            "we will start out awake and hibernate when we exhaust our quota.",
     643             :            buf1, buf2);
     644           4 :     return;
     645             :   }
     646             : 
     647           0 :   time_to_exhaust_bw =
     648           0 :     (get_options()->AccountingMax/expected_bandwidth_usage)*60;
     649           0 :   if (time_to_exhaust_bw > INT_MAX) {
     650             :     time_to_exhaust_bw = INT_MAX;
     651             :     time_to_consider = 0;
     652             :   } else {
     653           0 :     time_to_consider = accounting_get_interval_length() -
     654           0 :                        (int)time_to_exhaust_bw;
     655             :   }
     656             : 
     657           0 :   if (time_to_consider<=0) {
     658           0 :     interval_wakeup_time = interval_start_time;
     659             :   } else {
     660             :     /* XXX can we simplify this just by picking a random (non-deterministic)
     661             :      * time to be up? If we go down and come up, then we pick a new one. Is
     662             :      * that good enough? -RD */
     663             : 
     664             :     /* This is not a perfectly unbiased conversion, but it is good enough:
     665             :      * in the worst case, the first half of the day is 0.06 percent likelier
     666             :      * to be chosen than the last half. */
     667           0 :     interval_wakeup_time = interval_start_time +
     668           0 :       (get_uint32(digest) % time_to_consider);
     669             :   }
     670             : 
     671             :   {
     672           0 :     char buf1[ISO_TIME_LEN+1];
     673           0 :     char buf2[ISO_TIME_LEN+1];
     674           0 :     char buf3[ISO_TIME_LEN+1];
     675           0 :     char buf4[ISO_TIME_LEN+1];
     676           0 :     time_t down_time;
     677           0 :     if (interval_wakeup_time+time_to_exhaust_bw > TIME_MAX)
     678             :       down_time = TIME_MAX;
     679             :     else
     680           0 :       down_time = (time_t)(interval_wakeup_time+time_to_exhaust_bw);
     681           0 :     if (down_time>interval_end_time)
     682             :       down_time = interval_end_time;
     683           0 :     format_local_iso_time(buf1, interval_start_time);
     684           0 :     format_local_iso_time(buf2, interval_wakeup_time);
     685           0 :     format_local_iso_time(buf3, down_time);
     686           0 :     format_local_iso_time(buf4, interval_end_time);
     687             : 
     688           0 :     log_notice(LD_ACCT,
     689             :            "Configured hibernation.  This interval began at %s; "
     690             :            "the scheduled wake-up time %s %s; "
     691             :            "we expect%s to exhaust our quota for this interval around %s; "
     692             :            "the next interval begins at %s (all times local)",
     693             :            buf1,
     694             :            time(NULL)<interval_wakeup_time?"is":"was", buf2,
     695             :            time(NULL)<down_time?"":"ed", buf3,
     696             :            buf4);
     697             :   }
     698             : }
     699             : 
     700             : /* This rounds 0 up to 1000, but that's actually a feature. */
     701             : #define ROUND_UP(x) (((x) + 0x3ff) & ~0x3ff)
     702             : /** Save all our bandwidth tracking information to disk. Return 0 on
     703             :  * success, -1 on failure. */
     704             : int
     705          11 : accounting_record_bandwidth_usage(time_t now, or_state_t *state)
     706             : {
     707             :   /* Just update the state */
     708          11 :   state->AccountingIntervalStart = interval_start_time;
     709          11 :   state->AccountingBytesReadInInterval = ROUND_UP(n_bytes_read_in_interval);
     710          11 :   state->AccountingBytesWrittenInInterval =
     711          11 :     ROUND_UP(n_bytes_written_in_interval);
     712          11 :   state->AccountingSecondsActive = n_seconds_active_in_interval;
     713          11 :   state->AccountingExpectedUsage = expected_bandwidth_usage;
     714             : 
     715          11 :   state->AccountingSecondsToReachSoftLimit = n_seconds_to_hit_soft_limit;
     716          11 :   state->AccountingSoftLimitHitAt = soft_limit_hit_at;
     717          11 :   state->AccountingBytesAtSoftLimit = n_bytes_at_soft_limit;
     718             : 
     719          11 :   or_state_mark_dirty(state,
     720          11 :                       now+(get_options()->AvoidDiskWrites ? 7200 : 60));
     721             : 
     722          11 :   return 0;
     723             : }
     724             : #undef ROUND_UP
     725             : 
     726             : /** Read stored accounting information from disk. Return 0 on success;
     727             :  * return -1 and change nothing on failure. */
     728             : static int
     729           1 : read_bandwidth_usage(void)
     730             : {
     731           1 :   or_state_t *state = get_or_state();
     732             : 
     733             :   {
     734           1 :     char *fname = get_datadir_fname("bw_accounting");
     735           1 :     int res;
     736             : 
     737           1 :     res = unlink(fname);
     738           1 :     if (res != 0 && errno != ENOENT) {
     739           0 :       log_warn(LD_FS,
     740             :                "Failed to unlink %s: %s",
     741             :                fname, strerror(errno));
     742             :     }
     743             : 
     744           1 :     tor_free(fname);
     745             :   }
     746             : 
     747           1 :   if (!state)
     748             :     return -1;
     749             : 
     750           1 :   log_info(LD_ACCT, "Reading bandwidth accounting data from state file");
     751           1 :   n_bytes_read_in_interval = state->AccountingBytesReadInInterval;
     752           1 :   n_bytes_written_in_interval = state->AccountingBytesWrittenInInterval;
     753           1 :   n_seconds_active_in_interval = state->AccountingSecondsActive;
     754           1 :   interval_start_time = state->AccountingIntervalStart;
     755           1 :   expected_bandwidth_usage = state->AccountingExpectedUsage;
     756             : 
     757             :   /* Older versions of Tor (before 0.2.2.17-alpha or so) didn't generate these
     758             :    * fields. If you switch back and forth, you might get an
     759             :    * AccountingSoftLimitHitAt value from long before the most recent
     760             :    * interval_start_time.  If that's so, then ignore the softlimit-related
     761             :    * values. */
     762           1 :   if (state->AccountingSoftLimitHitAt > interval_start_time) {
     763           0 :     soft_limit_hit_at =  state->AccountingSoftLimitHitAt;
     764           0 :     n_bytes_at_soft_limit = state->AccountingBytesAtSoftLimit;
     765           0 :     n_seconds_to_hit_soft_limit = state->AccountingSecondsToReachSoftLimit;
     766             :   } else {
     767           1 :     soft_limit_hit_at = 0;
     768           1 :     n_bytes_at_soft_limit = 0;
     769           1 :     n_seconds_to_hit_soft_limit = 0;
     770             :   }
     771             : 
     772             :   {
     773           1 :     char tbuf1[ISO_TIME_LEN+1];
     774           1 :     char tbuf2[ISO_TIME_LEN+1];
     775           1 :     format_iso_time(tbuf1, state->LastWritten);
     776           1 :     format_iso_time(tbuf2, state->AccountingIntervalStart);
     777             : 
     778           1 :     log_info(LD_ACCT,
     779             :        "Successfully read bandwidth accounting info from state written at %s "
     780             :        "for interval starting at %s.  We have been active for %lu seconds in "
     781             :        "this interval.  At the start of the interval, we expected to use "
     782             :        "about %lu KB per second. (%"PRIu64" bytes read so far, "
     783             :        "%"PRIu64" bytes written so far)",
     784             :        tbuf1, tbuf2,
     785             :        (unsigned long)n_seconds_active_in_interval,
     786             :        (unsigned long)(expected_bandwidth_usage*1024/60),
     787             :        (n_bytes_read_in_interval),
     788             :        (n_bytes_written_in_interval));
     789             :   }
     790             : 
     791           1 :   return 0;
     792             : }
     793             : 
     794             : /** Return true iff we have sent/received all the bytes we are willing
     795             :  * to send/receive this interval. */
     796             : static int
     797           4 : hibernate_hard_limit_reached(void)
     798             : {
     799           4 :   uint64_t hard_limit = get_options()->AccountingMax;
     800           4 :   if (!hard_limit)
     801             :     return 0;
     802           4 :   return get_accounting_bytes() >= hard_limit;
     803             : }
     804             : 
     805             : /** Return true iff we have sent/received almost all the bytes we are willing
     806             :  * to send/receive this interval. */
     807             : static int
     808          14 : hibernate_soft_limit_reached(void)
     809             : {
     810          14 :   const uint64_t acct_max = get_options()->AccountingMax;
     811             : #define SOFT_LIM_PCT (.95)
     812             : #define SOFT_LIM_BYTES (500*1024*1024)
     813             : #define SOFT_LIM_MINUTES (3*60)
     814             :   /* The 'soft limit' is a fair bit more complicated now than once it was.
     815             :    * We want to stop accepting connections when ALL of the following are true:
     816             :    *   - We expect to use up the remaining bytes in under 3 hours
     817             :    *   - We have used up 95% of our bytes.
     818             :    *   - We have less than 500MBytes left.
     819             :    */
     820          14 :   uint64_t soft_limit = (uint64_t) (acct_max * SOFT_LIM_PCT);
     821          14 :   if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) {
     822             :     soft_limit = acct_max - SOFT_LIM_BYTES;
     823             :   }
     824          14 :   if (expected_bandwidth_usage) {
     825           0 :     const uint64_t expected_usage =
     826             :       expected_bandwidth_usage * SOFT_LIM_MINUTES;
     827           0 :     if (acct_max > expected_usage && acct_max - expected_usage > soft_limit)
     828             :       soft_limit = acct_max - expected_usage;
     829             :   }
     830             : 
     831          14 :   if (!soft_limit)
     832             :     return 0;
     833           8 :   return get_accounting_bytes() >= soft_limit;
     834             : }
     835             : 
     836             : /** Called when we get a SIGINT, or when bandwidth soft limit is
     837             :  * reached. Puts us into "loose hibernation": we don't accept new
     838             :  * connections, but we continue handling old ones. */
     839             : static void
     840           4 : hibernate_begin(hibernate_state_t new_state, time_t now)
     841             : {
     842           4 :   const or_options_t *options = get_options();
     843             : 
     844           4 :   if (new_state == HIBERNATE_STATE_EXITING &&
     845           0 :       hibernate_state != HIBERNATE_STATE_LIVE) {
     846           0 :     log_notice(LD_GENERAL,"SIGINT received %s; exiting now.",
     847             :                hibernate_state == HIBERNATE_STATE_EXITING ?
     848             :                "a second time" : "while hibernating");
     849           0 :     tor_shutdown_event_loop_and_exit(0);
     850           0 :     return;
     851             :   }
     852             : 
     853           4 :   if (new_state == HIBERNATE_STATE_LOWBANDWIDTH &&
     854           4 :       hibernate_state == HIBERNATE_STATE_LIVE) {
     855           4 :     soft_limit_hit_at = now;
     856           4 :     n_seconds_to_hit_soft_limit = n_seconds_active_in_interval;
     857           4 :     n_bytes_at_soft_limit = get_accounting_bytes();
     858             :   }
     859             : 
     860             :   /* close listeners. leave control listener(s). */
     861           4 :   connection_mark_all_noncontrol_listeners();
     862             : 
     863             :   /* XXX kill intro point circs */
     864             :   /* XXX upload rendezvous service descriptors with no intro points */
     865             : 
     866           4 :   if (new_state == HIBERNATE_STATE_EXITING) {
     867           0 :     log_notice(LD_GENERAL,"Interrupt: we have stopped accepting new "
     868             :                "connections, and will shut down in %d seconds. Interrupt "
     869             :                "again to exit now.", options->ShutdownWaitLength);
     870             :     /* We add an arbitrary delay here so that even if something goes wrong
     871             :      * with the mainloop shutdown code, we can still shutdown from
     872             :      * consider_hibernation() if we call it... but so that the
     873             :      * mainloop_schedule_shutdown() mechanism will be the first one called.
     874             :      */
     875           0 :     shutdown_time = time(NULL) + options->ShutdownWaitLength + 5;
     876           0 :     mainloop_schedule_shutdown(options->ShutdownWaitLength);
     877             : #ifdef HAVE_SYSTEMD
     878             :     /* tell systemd that we may need more than the default 90 seconds to shut
     879             :      * down so they don't kill us. add some extra time to actually finish
     880             :      * shutting down, otherwise systemd will kill us immediately after the
     881             :      * EXTEND_TIMEOUT_USEC expires. this is an *upper* limit; tor will probably
     882             :      * only take one or two more seconds, but assume that maybe we got swapped
     883             :      * out and it takes a little while longer.
     884             :      *
     885             :      * as of writing, this is a no-op with all-defaults: ShutdownWaitLength is
     886             :      * 30 seconds, so this will extend the timeout to 60 seconds.
     887             :      * default systemd DefaultTimeoutStopSec is 90 seconds, so systemd will
     888             :      * wait (up to) 90 seconds anyways.
     889             :      *
     890             :      * 2^31 usec = ~2147 sec = ~35 min. probably nobody will actually set
     891             :      * ShutdownWaitLength to more than that, but use a longer type so we don't
     892             :      * need to think about UB on overflow
     893             :      */
     894           0 :     sd_notifyf(0, "EXTEND_TIMEOUT_USEC=%" PRIu64,
     895           0 :             ((uint64_t)(options->ShutdownWaitLength) + 30) * TOR_USEC_PER_SEC);
     896             : #endif /* defined(HAVE_SYSTEMD) */
     897             :   } else { /* soft limit reached */
     898           4 :     hibernate_end_time = interval_end_time;
     899             :   }
     900             : 
     901           4 :   hibernate_state = new_state;
     902           4 :   accounting_record_bandwidth_usage(now, get_or_state());
     903             : 
     904           4 :   or_state_mark_dirty(get_or_state(),
     905           4 :                       get_options()->AvoidDiskWrites ? now+600 : 0);
     906             : }
     907             : 
     908             : /** Called when we've been hibernating and our timeout is reached. */
     909             : static void
     910          10 : hibernate_end(hibernate_state_t new_state)
     911             : {
     912          10 :   tor_assert(hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH ||
     913             :              hibernate_state == HIBERNATE_STATE_DORMANT ||
     914             :              hibernate_state == HIBERNATE_STATE_INITIAL);
     915             : 
     916             :   /* listeners will be relaunched in run_scheduled_events() in main.c */
     917          10 :   if (hibernate_state != HIBERNATE_STATE_INITIAL)
     918           3 :     log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity.");
     919             : 
     920          10 :   hibernate_state = new_state;
     921          10 :   hibernate_end_time = 0; /* no longer hibernating */
     922          10 :   reset_uptime(); /* reset published uptime */
     923          10 : }
     924             : 
     925             : /** A wrapper around hibernate_begin, for when we get SIGINT. */
     926             : void
     927           0 : hibernate_begin_shutdown(void)
     928             : {
     929           0 :   hibernate_begin(HIBERNATE_STATE_EXITING, time(NULL));
     930           0 : }
     931             : 
     932             : /**
     933             :  * Return true iff we are currently hibernating -- that is, if we are in
     934             :  * any non-live state.
     935             :  */
     936         336 : MOCK_IMPL(int,
     937             : we_are_hibernating,(void))
     938             : {
     939         336 :   return hibernate_state != HIBERNATE_STATE_LIVE;
     940             : }
     941             : 
     942             : /**
     943             :  * Return true iff we are currently _fully_ hibernating -- that is, if we are
     944             :  * in a state where we expect to handle no network activity at all.
     945             :  */
     946           0 : MOCK_IMPL(int,
     947             : we_are_fully_hibernating,(void))
     948             : {
     949           0 :   return hibernate_state == HIBERNATE_STATE_DORMANT;
     950             : }
     951             : 
     952             : /** If we aren't currently dormant, close all connections and become
     953             :  * dormant. */
     954             : static void
     955           4 : hibernate_go_dormant(time_t now)
     956             : {
     957           4 :   connection_t *conn;
     958             : 
     959           4 :   if (hibernate_state == HIBERNATE_STATE_DORMANT)
     960             :     return;
     961           4 :   else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH)
     962           4 :     hibernate_state = HIBERNATE_STATE_DORMANT;
     963             :   else
     964           0 :     hibernate_begin(HIBERNATE_STATE_DORMANT, now);
     965             : 
     966           4 :   log_notice(LD_ACCT,"Going dormant. Blowing away remaining connections.");
     967             : 
     968             :   /* Close all OR/AP/exit conns. Leave dir conns because we still want
     969             :    * to be able to upload server descriptors so clients know we're still
     970             :    * running, and download directories so we can detect if we're obsolete.
     971             :    * Leave control conns because we still want to be controllable.
     972             :    */
     973           4 :   while ((conn = connection_get_by_type(CONN_TYPE_OR)) ||
     974           4 :          (conn = connection_get_by_type(CONN_TYPE_AP)) ||
     975           4 :          (conn = connection_get_by_type(CONN_TYPE_EXIT))) {
     976           0 :     if (CONN_IS_EDGE(conn)) {
     977           0 :       connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING);
     978             :     }
     979           0 :     log_info(LD_NET,"Closing conn type %d", conn->type);
     980           0 :     if (conn->type == CONN_TYPE_AP) {
     981             :       /* send socks failure if needed */
     982           0 :       connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
     983             :                                     END_STREAM_REASON_HIBERNATING);
     984           0 :     } else if (conn->type == CONN_TYPE_OR) {
     985           0 :       if (TO_OR_CONN(conn)->chan) {
     986           0 :         connection_or_close_normally(TO_OR_CONN(conn), 0);
     987             :       } else {
     988           0 :          connection_mark_for_close(conn);
     989             :       }
     990             :     } else {
     991           0 :       connection_mark_for_close(conn);
     992             :     }
     993             :   }
     994             : 
     995           4 :   if (now < interval_wakeup_time)
     996           0 :     hibernate_end_time = interval_wakeup_time;
     997             :   else
     998           4 :     hibernate_end_time = interval_end_time;
     999             : 
    1000           4 :   accounting_record_bandwidth_usage(now, get_or_state());
    1001             : 
    1002           4 :   or_state_mark_dirty(get_or_state(),
    1003           4 :                       get_options()->AvoidDiskWrites ? now+600 : 0);
    1004             : 
    1005           4 :   hibernate_schedule_wakeup_event(now, hibernate_end_time);
    1006             : }
    1007             : 
    1008             : /**
    1009             :  * Schedule a mainloop event at <b>end_time</b> to wake up from a dormant
    1010             :  * state.  We can't rely on this happening from second_elapsed_callback,
    1011             :  * since second_elapsed_callback will be shut down when we're dormant.
    1012             :  *
    1013             :  * (Note that We might immediately go back to sleep after we set the next
    1014             :  * wakeup time.)
    1015             :  */
    1016             : static void
    1017           4 : hibernate_schedule_wakeup_event(time_t now, time_t end_time)
    1018             : {
    1019           4 :   struct timeval delay = { 0, 0 };
    1020             : 
    1021           4 :   if (now >= end_time) {
    1022             :     // In these cases we always wait at least a second, to avoid running
    1023             :     // the callback in a tight loop.
    1024           4 :     delay.tv_sec = 1;
    1025             :   } else {
    1026           0 :     delay.tv_sec = (end_time - now);
    1027             :   }
    1028             : 
    1029           4 :   if (!wakeup_event) {
    1030           1 :     wakeup_event = mainloop_event_postloop_new(wakeup_event_callback, NULL);
    1031             :   }
    1032             : 
    1033           4 :   mainloop_event_schedule(wakeup_event, &delay);
    1034           4 : }
    1035             : 
    1036             : /**
    1037             :  * Called at the end of the interval, or at the wakeup time of the current
    1038             :  * interval, to exit the dormant state.
    1039             :  **/
    1040             : static void
    1041           0 : wakeup_event_callback(mainloop_event_t *ev, void *data)
    1042             : {
    1043           0 :   (void) ev;
    1044           0 :   (void) data;
    1045             : 
    1046           0 :   const time_t now = time(NULL);
    1047           0 :   accounting_run_housekeeping(now);
    1048           0 :   consider_hibernation(now);
    1049           0 :   if (hibernate_state != HIBERNATE_STATE_DORMANT) {
    1050             :     /* We woke up, so everything's great here */
    1051             :     return;
    1052             :   }
    1053             : 
    1054             :   /* We're still dormant. */
    1055           0 :   if (now < interval_wakeup_time)
    1056           0 :     hibernate_end_time = interval_wakeup_time;
    1057             :   else
    1058           0 :     hibernate_end_time = interval_end_time;
    1059             : 
    1060           0 :   hibernate_schedule_wakeup_event(now, hibernate_end_time);
    1061             : }
    1062             : 
    1063             : /** Called when hibernate_end_time has arrived. */
    1064             : static void
    1065           3 : hibernate_end_time_elapsed(time_t now)
    1066             : {
    1067           3 :   char buf[ISO_TIME_LEN+1];
    1068             : 
    1069             :   /* The interval has ended, or it is wakeup time.  Find out which. */
    1070           3 :   accounting_run_housekeeping(now);
    1071           3 :   if (interval_wakeup_time <= now) {
    1072             :     /* The interval hasn't changed, but interval_wakeup_time has passed.
    1073             :      * It's time to wake up and start being a server. */
    1074           3 :     hibernate_end(HIBERNATE_STATE_LIVE);
    1075           3 :     return;
    1076             :   } else {
    1077             :     /* The interval has changed, and it isn't time to wake up yet. */
    1078           0 :     hibernate_end_time = interval_wakeup_time;
    1079           0 :     format_iso_time(buf,interval_wakeup_time);
    1080           0 :     if (hibernate_state != HIBERNATE_STATE_DORMANT) {
    1081             :       /* We weren't sleeping before; we should sleep now. */
    1082           0 :       log_notice(LD_ACCT,
    1083             :                  "Accounting period ended. Commencing hibernation until "
    1084             :                  "%s UTC", buf);
    1085           0 :       hibernate_go_dormant(now);
    1086             :     } else {
    1087           0 :       log_notice(LD_ACCT,
    1088             :              "Accounting period ended. This period, we will hibernate"
    1089             :              " until %s UTC",buf);
    1090             :     }
    1091             :   }
    1092             : }
    1093             : 
    1094             : /** Consider our environment and decide if it's time
    1095             :  * to start/stop hibernating.
    1096             :  */
    1097             : void
    1098          14 : consider_hibernation(time_t now)
    1099             : {
    1100          14 :   int accounting_enabled = get_options()->AccountingMax != 0;
    1101          14 :   char buf[ISO_TIME_LEN+1];
    1102          14 :   hibernate_state_t prev_state = hibernate_state;
    1103             : 
    1104             :   /* If we're in 'exiting' mode, then we just shut down after the interval
    1105             :    * elapses.  The mainloop was supposed to catch this via
    1106             :    * mainloop_schedule_shutdown(), but apparently it didn't. */
    1107          14 :   if (hibernate_state == HIBERNATE_STATE_EXITING) {
    1108           0 :     tor_assert(shutdown_time);
    1109           0 :     if (shutdown_time <= now) {
    1110           0 :       log_notice(LD_BUG, "Mainloop did not catch shutdown event; exiting.");
    1111           0 :       tor_shutdown_event_loop_and_exit(0);
    1112             :     }
    1113           0 :     return; /* if exiting soon, don't worry about bandwidth limits */
    1114             :   }
    1115             : 
    1116          14 :   if (hibernate_state == HIBERNATE_STATE_DORMANT) {
    1117             :     /* We've been hibernating because of bandwidth accounting. */
    1118           3 :     tor_assert(hibernate_end_time);
    1119           3 :     if (hibernate_end_time > now && accounting_enabled) {
    1120             :       /* If we're hibernating, don't wake up until it's time, regardless of
    1121             :        * whether we're in a new interval. */
    1122             :       return;
    1123             :     } else {
    1124           3 :       hibernate_end_time_elapsed(now);
    1125             :     }
    1126             :   }
    1127             : 
    1128             :   /* Else, we aren't hibernating. See if it's time to start hibernating, or to
    1129             :    * go dormant. */
    1130          14 :   if (hibernate_state == HIBERNATE_STATE_LIVE ||
    1131             :       hibernate_state == HIBERNATE_STATE_INITIAL) {
    1132          14 :     if (hibernate_soft_limit_reached()) {
    1133           4 :       log_notice(LD_ACCT,
    1134             :                  "Bandwidth soft limit reached; commencing hibernation. "
    1135             :                  "No new connections will be accepted");
    1136           4 :       hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH, now);
    1137          10 :     } else if (accounting_enabled && now < interval_wakeup_time) {
    1138           0 :       format_local_iso_time(buf,interval_wakeup_time);
    1139           0 :       log_notice(LD_ACCT,
    1140             :                  "Commencing hibernation. We will wake up at %s local time.",
    1141             :                  buf);
    1142           0 :       hibernate_go_dormant(now);
    1143          10 :     } else if (hibernate_state == HIBERNATE_STATE_INITIAL) {
    1144           7 :       hibernate_end(HIBERNATE_STATE_LIVE);
    1145             :     }
    1146             :   }
    1147             : 
    1148          14 :   if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) {
    1149           4 :     if (!accounting_enabled) {
    1150           0 :       hibernate_end_time_elapsed(now);
    1151           4 :     } else if (hibernate_hard_limit_reached()) {
    1152           4 :       hibernate_go_dormant(now);
    1153           0 :     } else if (hibernate_end_time <= now) {
    1154             :       /* The hibernation period ended while we were still in lowbandwidth.*/
    1155           0 :       hibernate_end_time_elapsed(now);
    1156             :     }
    1157             :   }
    1158             : 
    1159             :   /* Dispatch a controller event if the hibernation state changed. */
    1160          14 :   if (hibernate_state != prev_state)
    1161          14 :     on_hibernate_state_change(prev_state);
    1162             : }
    1163             : 
    1164             : /** Helper function: called when we get a GETINFO request for an
    1165             :  * accounting-related key on the control connection <b>conn</b>.  If we can
    1166             :  * answer the request for <b>question</b>, then set *<b>answer</b> to a newly
    1167             :  * allocated string holding the result.  Otherwise, set *<b>answer</b> to
    1168             :  * NULL. */
    1169             : int
    1170           0 : getinfo_helper_accounting(control_connection_t *conn,
    1171             :                           const char *question, char **answer,
    1172             :                           const char **errmsg)
    1173             : {
    1174           0 :   (void) conn;
    1175           0 :   (void) errmsg;
    1176           0 :   if (!strcmp(question, "accounting/enabled")) {
    1177           0 :     *answer = tor_strdup(accounting_is_enabled(get_options()) ? "1" : "0");
    1178           0 :   } else if (!strcmp(question, "accounting/hibernating")) {
    1179           0 :     *answer = tor_strdup(hibernate_state_to_string(hibernate_state));
    1180           0 :     tor_strlower(*answer);
    1181           0 :   } else if (!strcmp(question, "accounting/bytes")) {
    1182           0 :       tor_asprintf(answer, "%"PRIu64" %"PRIu64,
    1183             :                  (n_bytes_read_in_interval),
    1184             :                  (n_bytes_written_in_interval));
    1185           0 :   } else if (!strcmp(question, "accounting/bytes-left")) {
    1186           0 :     uint64_t limit = get_options()->AccountingMax;
    1187           0 :     if (get_options()->AccountingRule == ACCT_SUM) {
    1188           0 :       uint64_t total_left = 0;
    1189           0 :       uint64_t total_bytes = get_accounting_bytes();
    1190           0 :       if (total_bytes < limit)
    1191           0 :         total_left = limit - total_bytes;
    1192           0 :       tor_asprintf(answer, "%"PRIu64" %"PRIu64,
    1193             :                    (total_left), (total_left));
    1194           0 :     } else if (get_options()->AccountingRule == ACCT_IN) {
    1195           0 :       uint64_t read_left = 0;
    1196           0 :       if (n_bytes_read_in_interval < limit)
    1197           0 :         read_left = limit - n_bytes_read_in_interval;
    1198           0 :       tor_asprintf(answer, "%"PRIu64" %"PRIu64,
    1199             :                    (read_left), (limit));
    1200           0 :     } else if (get_options()->AccountingRule == ACCT_OUT) {
    1201           0 :       uint64_t write_left = 0;
    1202           0 :       if (n_bytes_written_in_interval < limit)
    1203           0 :         write_left = limit - n_bytes_written_in_interval;
    1204           0 :       tor_asprintf(answer, "%"PRIu64" %"PRIu64,
    1205             :                    (limit), (write_left));
    1206             :     } else {
    1207           0 :       uint64_t read_left = 0, write_left = 0;
    1208           0 :       if (n_bytes_read_in_interval < limit)
    1209           0 :         read_left = limit - n_bytes_read_in_interval;
    1210           0 :       if (n_bytes_written_in_interval < limit)
    1211           0 :         write_left = limit - n_bytes_written_in_interval;
    1212           0 :       tor_asprintf(answer, "%"PRIu64" %"PRIu64,
    1213             :                    (read_left), (write_left));
    1214             :     }
    1215           0 :   } else if (!strcmp(question, "accounting/interval-start")) {
    1216           0 :     *answer = tor_malloc(ISO_TIME_LEN+1);
    1217           0 :     format_iso_time(*answer, interval_start_time);
    1218           0 :   } else if (!strcmp(question, "accounting/interval-wake")) {
    1219           0 :     *answer = tor_malloc(ISO_TIME_LEN+1);
    1220           0 :     format_iso_time(*answer, interval_wakeup_time);
    1221           0 :   } else if (!strcmp(question, "accounting/interval-end")) {
    1222           0 :     *answer = tor_malloc(ISO_TIME_LEN+1);
    1223           0 :     format_iso_time(*answer, interval_end_time);
    1224             :   } else {
    1225           0 :     *answer = NULL;
    1226             :   }
    1227           0 :   return 0;
    1228             : }
    1229             : 
    1230             : /**
    1231             :  * Helper function: called when the hibernation state changes, and sends a
    1232             :  * SERVER_STATUS event to notify interested controllers of the accounting
    1233             :  * state change.
    1234             :  */
    1235             : static void
    1236          14 : on_hibernate_state_change(hibernate_state_t prev_state)
    1237             : {
    1238          14 :   control_event_server_status(LOG_NOTICE,
    1239             :                               "HIBERNATION_STATUS STATUS=%s",
    1240             :                               hibernate_state_to_string(hibernate_state));
    1241             : 
    1242             :   /* We are changing hibernation state, this can affect the main loop event
    1243             :    * list. Rescan it to update the events state. We do this whatever the new
    1244             :    * hibernation state because they can each possibly affect an event. The
    1245             :    * initial state means we are booting up so we shouldn't scan here because
    1246             :    * at this point the events in the list haven't been initialized. */
    1247          14 :   if (prev_state != HIBERNATE_STATE_INITIAL) {
    1248           7 :     rescan_periodic_events(get_options());
    1249             :   }
    1250          14 : }
    1251             : 
    1252             : /** Free all resources held by the accounting module */
    1253             : void
    1254         235 : accounting_free_all(void)
    1255             : {
    1256         235 :   mainloop_event_free(wakeup_event);
    1257         235 :   hibernate_state = HIBERNATE_STATE_INITIAL;
    1258         235 :   hibernate_end_time = 0;
    1259         235 :   shutdown_time = 0;
    1260         235 : }
    1261             : 
    1262             : #ifdef TOR_UNIT_TESTS
    1263             : /**
    1264             :  * Manually change the hibernation state.  Private; used only by the unit
    1265             :  * tests.
    1266             :  */
    1267             : void
    1268           7 : hibernate_set_state_for_testing_(hibernate_state_t newstate)
    1269             : {
    1270           7 :   hibernate_state = newstate;
    1271           7 : }
    1272             : #endif /* defined(TOR_UNIT_TESTS) */

Generated by: LCOV version 1.14