/src/tor/src/feature/hibernate/hibernate.c
Line | Count | Source (jump to first uncovered line) |
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 | | hibernate_state_to_string(hibernate_state_t state) |
166 | 0 | { |
167 | 0 | static char buf[64]; |
168 | 0 | switch (state) { |
169 | 0 | case HIBERNATE_STATE_EXITING: return "EXITING"; |
170 | 0 | case HIBERNATE_STATE_LOWBANDWIDTH: return "SOFT"; |
171 | 0 | case HIBERNATE_STATE_DORMANT: return "HARD"; |
172 | 0 | case HIBERNATE_STATE_INITIAL: |
173 | 0 | case HIBERNATE_STATE_LIVE: |
174 | 0 | 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 | 0 | } |
180 | 0 | } |
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 | | accounting_parse_options(const or_options_t *options, int validate_only) |
191 | 0 | { |
192 | 0 | time_unit_t unit; |
193 | 0 | int ok, idx; |
194 | 0 | long d,h,m; |
195 | 0 | smartlist_t *items; |
196 | 0 | const char *v = options->AccountingStart; |
197 | 0 | const char *s; |
198 | 0 | char *cp; |
199 | |
|
200 | 0 | if (!v) { |
201 | 0 | if (!validate_only) { |
202 | 0 | cfg_unit = UNIT_MONTH; |
203 | 0 | cfg_start_day = 1; |
204 | 0 | cfg_start_hour = 0; |
205 | 0 | cfg_start_min = 0; |
206 | 0 | } |
207 | 0 | return 0; |
208 | 0 | } |
209 | | |
210 | 0 | items = smartlist_new(); |
211 | 0 | smartlist_split_string(items, v, NULL, |
212 | 0 | SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK,0); |
213 | 0 | if (smartlist_len(items)<2) { |
214 | 0 | log_warn(LD_CONFIG, "Too few arguments to AccountingStart"); |
215 | 0 | goto err; |
216 | 0 | } |
217 | 0 | s = smartlist_get(items,0); |
218 | 0 | if (0==strcasecmp(s, "month")) { |
219 | 0 | unit = UNIT_MONTH; |
220 | 0 | } else if (0==strcasecmp(s, "week")) { |
221 | 0 | unit = UNIT_WEEK; |
222 | 0 | } else if (0==strcasecmp(s, "day")) { |
223 | 0 | unit = UNIT_DAY; |
224 | 0 | } else { |
225 | 0 | log_warn(LD_CONFIG, |
226 | 0 | "Unrecognized accounting unit '%s': only 'month', 'week'," |
227 | 0 | " and 'day' are supported.", s); |
228 | 0 | goto err; |
229 | 0 | } |
230 | | |
231 | 0 | switch (unit) { |
232 | 0 | 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 | 0 | "1 (Monday) and 7 (Sunday)"); |
237 | 0 | goto err; |
238 | 0 | } |
239 | 0 | break; |
240 | 0 | 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 | 0 | "1 and 28"); |
245 | 0 | goto err; |
246 | 0 | } |
247 | 0 | break; |
248 | 0 | case UNIT_DAY: |
249 | 0 | d = 0; |
250 | 0 | 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 | 0 | default: |
255 | 0 | tor_assert(0); |
256 | 0 | } |
257 | | |
258 | 0 | idx = unit==UNIT_DAY?1:2; |
259 | 0 | if (smartlist_len(items) != (idx+1)) { |
260 | 0 | log_warn(LD_CONFIG,"Accounting unit '%s' requires %d argument%s.", |
261 | 0 | s, idx, (idx>1)?"s":""); |
262 | 0 | goto err; |
263 | 0 | } |
264 | 0 | s = smartlist_get(items, idx); |
265 | 0 | h = tor_parse_long(s, 10, 0, 23, &ok, &cp); |
266 | 0 | if (!ok) { |
267 | 0 | log_warn(LD_CONFIG,"Accounting start time not parseable: bad hour."); |
268 | 0 | goto err; |
269 | 0 | } |
270 | 0 | if (!cp || *cp!=':') { |
271 | 0 | log_warn(LD_CONFIG, |
272 | 0 | "Accounting start time not parseable: not in HH:MM format"); |
273 | 0 | goto err; |
274 | 0 | } |
275 | 0 | m = tor_parse_long(cp+1, 10, 0, 59, &ok, &cp); |
276 | 0 | if (!ok) { |
277 | 0 | log_warn(LD_CONFIG, "Accounting start time not parseable: bad minute"); |
278 | 0 | goto err; |
279 | 0 | } |
280 | 0 | if (!cp || *cp!='\0') { |
281 | 0 | log_warn(LD_CONFIG, |
282 | 0 | "Accounting start time not parseable: not in HH:MM format"); |
283 | 0 | goto err; |
284 | 0 | } |
285 | | |
286 | 0 | 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 | 0 | } |
292 | 0 | SMARTLIST_FOREACH(items, char *, item, tor_free(item)); |
293 | 0 | smartlist_free(items); |
294 | 0 | return 0; |
295 | 0 | err: |
296 | 0 | SMARTLIST_FOREACH(items, char *, item, tor_free(item)); |
297 | 0 | smartlist_free(items); |
298 | 0 | return -1; |
299 | 0 | } |
300 | | |
301 | | /** If we want to manage the accounting system and potentially |
302 | | * hibernate, return 1, else return 0. |
303 | | */ |
304 | | MOCK_IMPL(int, |
305 | | accounting_is_enabled,(const or_options_t *options)) |
306 | 0 | { |
307 | 0 | if (options->AccountingMax) |
308 | 0 | return 1; |
309 | 0 | return 0; |
310 | 0 | } |
311 | | |
312 | | /** If accounting is enabled, return how long (in seconds) this |
313 | | * interval lasts. */ |
314 | | int |
315 | | accounting_get_interval_length(void) |
316 | 0 | { |
317 | 0 | return (int)(interval_end_time - interval_start_time); |
318 | 0 | } |
319 | | |
320 | | /** Return the time at which the current accounting interval will end. */ |
321 | | MOCK_IMPL(time_t, |
322 | | accounting_get_end_time,(void)) |
323 | 0 | { |
324 | 0 | return interval_end_time; |
325 | 0 | } |
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 | | accounting_add_bytes(size_t n_read, size_t n_written, int seconds) |
332 | 0 | { |
333 | 0 | n_bytes_read_in_interval += n_read; |
334 | 0 | 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 | 0 | n_seconds_active_in_interval += (seconds < 10) ? seconds : 0; |
338 | 0 | } |
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 | | edge_of_accounting_period_containing(time_t now, int get_end) |
345 | 0 | { |
346 | 0 | int before; |
347 | 0 | struct tm tm; |
348 | 0 | 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 | 0 | before = tm.tm_hour < cfg_start_hour || |
353 | 0 | (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 | 0 | switch (cfg_unit) |
358 | 0 | { |
359 | 0 | case UNIT_MONTH: { |
360 | | /* If this is before the Nth, we want the Nth of last month. */ |
361 | 0 | if (tm.tm_mday < cfg_start_day || |
362 | 0 | (tm.tm_mday == cfg_start_day && before)) { |
363 | 0 | --tm.tm_mon; |
364 | 0 | } |
365 | | /* Otherwise, the month is correct. */ |
366 | 0 | tm.tm_mday = cfg_start_day; |
367 | 0 | if (get_end) |
368 | 0 | ++tm.tm_mon; |
369 | 0 | break; |
370 | 0 | } |
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 | 0 | break; |
385 | 0 | } |
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 | 0 | break; |
392 | 0 | default: |
393 | 0 | tor_assert(0); |
394 | 0 | } |
395 | | |
396 | 0 | tm.tm_hour = cfg_start_hour; |
397 | 0 | tm.tm_min = cfg_start_min; |
398 | 0 | tm.tm_sec = 0; |
399 | 0 | tm.tm_isdst = -1; /* Autodetect DST */ |
400 | 0 | return mktime(&tm); |
401 | 0 | } |
402 | | |
403 | | /** Return the start of the accounting period containing the time |
404 | | * <b>now</b>. */ |
405 | | static time_t |
406 | | start_of_accounting_period_containing(time_t now) |
407 | 0 | { |
408 | 0 | return edge_of_accounting_period_containing(now, 0); |
409 | 0 | } |
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 | | start_of_accounting_period_after(time_t now) |
415 | 0 | { |
416 | 0 | return edge_of_accounting_period_containing(now, 1); |
417 | 0 | } |
418 | | |
419 | | /** Return the length of the accounting period containing the time |
420 | | * <b>now</b>. */ |
421 | | static long |
422 | | length_of_accounting_period_containing(time_t now) |
423 | 0 | { |
424 | 0 | return edge_of_accounting_period_containing(now, 1) - |
425 | 0 | edge_of_accounting_period_containing(now, 0); |
426 | 0 | } |
427 | | |
428 | | /** Initialize the accounting subsystem. */ |
429 | | void |
430 | | configure_accounting(time_t now) |
431 | 0 | { |
432 | 0 | time_t s_now; |
433 | | /* Try to remember our recorded usage. */ |
434 | 0 | if (!interval_start_time) |
435 | 0 | read_bandwidth_usage(); /* If we fail, we'll leave values at zero, and |
436 | | * reset below.*/ |
437 | |
|
438 | 0 | s_now = start_of_accounting_period_containing(now); |
439 | |
|
440 | 0 | if (!interval_start_time) { |
441 | | /* We didn't have recorded usage; Start a new interval. */ |
442 | 0 | log_info(LD_ACCT, "Starting new accounting interval."); |
443 | 0 | reset_accounting(now); |
444 | 0 | } else if (s_now == interval_start_time) { |
445 | 0 | log_info(LD_ACCT, "Continuing accounting interval."); |
446 | | /* We are in the interval we thought we were in. Do nothing.*/ |
447 | 0 | interval_end_time = start_of_accounting_period_after(interval_start_time); |
448 | 0 | } 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 | 0 | "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 | 0 | } else { |
466 | 0 | log_warn(LD_ACCT, |
467 | 0 | "Mismatched accounting interval: moved by %.02f%%. " |
468 | 0 | "Starting a fresh one.", delta*100); |
469 | 0 | reset_accounting(now); |
470 | 0 | } |
471 | 0 | } |
472 | 0 | accounting_set_wakeup_time(); |
473 | 0 | } |
474 | | |
475 | | /** Return the relevant number of bytes sent/received this interval |
476 | | * based on the set AccountingRule */ |
477 | | uint64_t |
478 | | get_accounting_bytes(void) |
479 | 0 | { |
480 | 0 | if (get_options()->AccountingRule == ACCT_SUM) |
481 | 0 | return n_bytes_read_in_interval+n_bytes_written_in_interval; |
482 | 0 | else if (get_options()->AccountingRule == ACCT_IN) |
483 | 0 | return n_bytes_read_in_interval; |
484 | 0 | else if (get_options()->AccountingRule == ACCT_OUT) |
485 | 0 | return n_bytes_written_in_interval; |
486 | 0 | else |
487 | 0 | return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval); |
488 | 0 | } |
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 | | update_expected_bandwidth(void) |
495 | 0 | { |
496 | 0 | uint64_t expected; |
497 | 0 | const or_options_t *options= get_options(); |
498 | 0 | uint64_t max_configured = (options->RelayBandwidthRate > 0 ? |
499 | 0 | options->RelayBandwidthRate : |
500 | 0 | 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 | 0 | if (get_options()->AccountingRule == ACCT_SUM) |
505 | 0 | max_configured *= 2; |
506 | |
|
507 | 0 | #define MIN_TIME_FOR_MEASUREMENT (1800) |
508 | |
|
509 | 0 | 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 | 0 | } 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 | 0 | } 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 | 0 | expected = 0; |
533 | 0 | } |
534 | 0 | if (expected > max_configured) |
535 | 0 | expected = max_configured; |
536 | 0 | expected_bandwidth_usage = expected; |
537 | 0 | } |
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 | | reset_accounting(time_t now) |
545 | 0 | { |
546 | 0 | log_info(LD_ACCT, "Starting new accounting interval."); |
547 | 0 | update_expected_bandwidth(); |
548 | 0 | interval_start_time = start_of_accounting_period_containing(now); |
549 | 0 | interval_end_time = start_of_accounting_period_after(interval_start_time); |
550 | 0 | n_bytes_read_in_interval = 0; |
551 | 0 | n_bytes_written_in_interval = 0; |
552 | 0 | n_seconds_active_in_interval = 0; |
553 | 0 | n_bytes_at_soft_limit = 0; |
554 | 0 | soft_limit_hit_at = 0; |
555 | 0 | n_seconds_to_hit_soft_limit = 0; |
556 | 0 | } |
557 | | |
558 | | /** Return true iff we should save our bandwidth usage to disk. */ |
559 | | static inline int |
560 | | time_to_record_bandwidth_usage(time_t now) |
561 | 0 | { |
562 | | /* Note every 600 sec */ |
563 | 0 | #define NOTE_INTERVAL (600) |
564 | | /* Or every 20 megabytes */ |
565 | 0 | #define NOTE_BYTES (20*1024*1024) |
566 | 0 | static uint64_t last_read_bytes_noted = 0; |
567 | 0 | static uint64_t last_written_bytes_noted = 0; |
568 | 0 | static time_t last_time_noted = 0; |
569 | |
|
570 | 0 | if (last_time_noted + NOTE_INTERVAL <= now || |
571 | 0 | last_read_bytes_noted + NOTE_BYTES <= n_bytes_read_in_interval || |
572 | 0 | last_written_bytes_noted + NOTE_BYTES <= n_bytes_written_in_interval || |
573 | 0 | (interval_end_time && interval_end_time <= now)) { |
574 | 0 | last_time_noted = now; |
575 | 0 | last_read_bytes_noted = n_bytes_read_in_interval; |
576 | 0 | last_written_bytes_noted = n_bytes_written_in_interval; |
577 | 0 | return 1; |
578 | 0 | } |
579 | 0 | return 0; |
580 | 0 | } |
581 | | |
582 | | /** Invoked once per second. Checks whether it is time to hibernate, |
583 | | * record bandwidth used, etc. */ |
584 | | void |
585 | | accounting_run_housekeeping(time_t now) |
586 | 0 | { |
587 | 0 | if (now >= interval_end_time) { |
588 | 0 | configure_accounting(now); |
589 | 0 | } |
590 | 0 | if (time_to_record_bandwidth_usage(now)) { |
591 | 0 | if (accounting_record_bandwidth_usage(now, get_or_state())) { |
592 | 0 | log_warn(LD_FS, "Couldn't record bandwidth usage to disk."); |
593 | 0 | } |
594 | 0 | } |
595 | 0 | } |
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 | | accounting_set_wakeup_time(void) |
601 | 0 | { |
602 | 0 | char digest[DIGEST_LEN]; |
603 | 0 | crypto_digest_t *d_env; |
604 | 0 | uint64_t time_to_exhaust_bw; |
605 | 0 | int time_to_consider; |
606 | |
|
607 | 0 | if (! server_identity_key_is_set()) { |
608 | 0 | if (init_keys() < 0) { |
609 | 0 | log_err(LD_BUG, "Error initializing keys"); |
610 | 0 | tor_assert(0); |
611 | 0 | } |
612 | 0 | } |
613 | | |
614 | 0 | 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 | 0 | } |
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 | 0 | } else { |
629 | 0 | crypto_rand(digest, DIGEST_LEN); |
630 | 0 | } |
631 | | |
632 | 0 | if (!expected_bandwidth_usage) { |
633 | 0 | char buf1[ISO_TIME_LEN+1]; |
634 | 0 | char buf2[ISO_TIME_LEN+1]; |
635 | 0 | format_local_iso_time(buf1, interval_start_time); |
636 | 0 | format_local_iso_time(buf2, interval_end_time); |
637 | 0 | interval_wakeup_time = interval_start_time; |
638 | |
|
639 | 0 | log_notice(LD_ACCT, |
640 | 0 | "Configured hibernation. This interval begins at %s " |
641 | 0 | "and ends at %s. We have no prior estimate for bandwidth, so " |
642 | 0 | "we will start out awake and hibernate when we exhaust our quota.", |
643 | 0 | buf1, buf2); |
644 | 0 | return; |
645 | 0 | } |
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 | 0 | time_to_exhaust_bw = INT_MAX; |
651 | 0 | time_to_consider = 0; |
652 | 0 | } else { |
653 | 0 | time_to_consider = accounting_get_interval_length() - |
654 | 0 | (int)time_to_exhaust_bw; |
655 | 0 | } |
656 | |
|
657 | 0 | if (time_to_consider<=0) { |
658 | 0 | interval_wakeup_time = interval_start_time; |
659 | 0 | } 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 | 0 | } |
670 | |
|
671 | 0 | { |
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 | 0 | down_time = TIME_MAX; |
679 | 0 | else |
680 | 0 | down_time = (time_t)(interval_wakeup_time+time_to_exhaust_bw); |
681 | 0 | if (down_time>interval_end_time) |
682 | 0 | 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 | 0 | "Configured hibernation. This interval began at %s; " |
690 | 0 | "the scheduled wake-up time %s %s; " |
691 | 0 | "we expect%s to exhaust our quota for this interval around %s; " |
692 | 0 | "the next interval begins at %s (all times local)", |
693 | 0 | buf1, |
694 | 0 | time(NULL)<interval_wakeup_time?"is":"was", buf2, |
695 | 0 | time(NULL)<down_time?"":"ed", buf3, |
696 | 0 | buf4); |
697 | 0 | } |
698 | 0 | } |
699 | | |
700 | | /* This rounds 0 up to 1000, but that's actually a feature. */ |
701 | 0 | #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 | | accounting_record_bandwidth_usage(time_t now, or_state_t *state) |
706 | 0 | { |
707 | | /* Just update the state */ |
708 | 0 | state->AccountingIntervalStart = interval_start_time; |
709 | 0 | state->AccountingBytesReadInInterval = ROUND_UP(n_bytes_read_in_interval); |
710 | 0 | state->AccountingBytesWrittenInInterval = |
711 | 0 | ROUND_UP(n_bytes_written_in_interval); |
712 | 0 | state->AccountingSecondsActive = n_seconds_active_in_interval; |
713 | 0 | state->AccountingExpectedUsage = expected_bandwidth_usage; |
714 | |
|
715 | 0 | state->AccountingSecondsToReachSoftLimit = n_seconds_to_hit_soft_limit; |
716 | 0 | state->AccountingSoftLimitHitAt = soft_limit_hit_at; |
717 | 0 | state->AccountingBytesAtSoftLimit = n_bytes_at_soft_limit; |
718 | |
|
719 | 0 | or_state_mark_dirty(state, |
720 | 0 | now+(get_options()->AvoidDiskWrites ? 7200 : 60)); |
721 | |
|
722 | 0 | return 0; |
723 | 0 | } |
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 | | read_bandwidth_usage(void) |
730 | 0 | { |
731 | 0 | or_state_t *state = get_or_state(); |
732 | |
|
733 | 0 | { |
734 | 0 | char *fname = get_datadir_fname("bw_accounting"); |
735 | 0 | int res; |
736 | |
|
737 | 0 | res = unlink(fname); |
738 | 0 | if (res != 0 && errno != ENOENT) { |
739 | 0 | log_warn(LD_FS, |
740 | 0 | "Failed to unlink %s: %s", |
741 | 0 | fname, strerror(errno)); |
742 | 0 | } |
743 | |
|
744 | 0 | tor_free(fname); |
745 | 0 | } |
746 | |
|
747 | 0 | if (!state) |
748 | 0 | return -1; |
749 | | |
750 | 0 | log_info(LD_ACCT, "Reading bandwidth accounting data from state file"); |
751 | 0 | n_bytes_read_in_interval = state->AccountingBytesReadInInterval; |
752 | 0 | n_bytes_written_in_interval = state->AccountingBytesWrittenInInterval; |
753 | 0 | n_seconds_active_in_interval = state->AccountingSecondsActive; |
754 | 0 | interval_start_time = state->AccountingIntervalStart; |
755 | 0 | 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 | 0 | 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 | 0 | } else { |
767 | 0 | soft_limit_hit_at = 0; |
768 | 0 | n_bytes_at_soft_limit = 0; |
769 | 0 | n_seconds_to_hit_soft_limit = 0; |
770 | 0 | } |
771 | |
|
772 | 0 | { |
773 | 0 | char tbuf1[ISO_TIME_LEN+1]; |
774 | 0 | char tbuf2[ISO_TIME_LEN+1]; |
775 | 0 | format_iso_time(tbuf1, state->LastWritten); |
776 | 0 | format_iso_time(tbuf2, state->AccountingIntervalStart); |
777 | |
|
778 | 0 | log_info(LD_ACCT, |
779 | 0 | "Successfully read bandwidth accounting info from state written at %s " |
780 | 0 | "for interval starting at %s. We have been active for %lu seconds in " |
781 | 0 | "this interval. At the start of the interval, we expected to use " |
782 | 0 | "about %lu KB per second. (%"PRIu64" bytes read so far, " |
783 | 0 | "%"PRIu64" bytes written so far)", |
784 | 0 | tbuf1, tbuf2, |
785 | 0 | (unsigned long)n_seconds_active_in_interval, |
786 | 0 | (unsigned long)(expected_bandwidth_usage*1024/60), |
787 | 0 | (n_bytes_read_in_interval), |
788 | 0 | (n_bytes_written_in_interval)); |
789 | 0 | } |
790 | |
|
791 | 0 | return 0; |
792 | 0 | } |
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 | | hibernate_hard_limit_reached(void) |
798 | 0 | { |
799 | 0 | uint64_t hard_limit = get_options()->AccountingMax; |
800 | 0 | if (!hard_limit) |
801 | 0 | return 0; |
802 | 0 | return get_accounting_bytes() >= hard_limit; |
803 | 0 | } |
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 | | hibernate_soft_limit_reached(void) |
809 | 0 | { |
810 | 0 | const uint64_t acct_max = get_options()->AccountingMax; |
811 | 0 | #define SOFT_LIM_PCT (.95) |
812 | 0 | #define SOFT_LIM_BYTES (500*1024*1024) |
813 | 0 | #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 | 0 | uint64_t soft_limit = (uint64_t) (acct_max * SOFT_LIM_PCT); |
821 | 0 | if (acct_max > SOFT_LIM_BYTES && acct_max - SOFT_LIM_BYTES > soft_limit) { |
822 | 0 | soft_limit = acct_max - SOFT_LIM_BYTES; |
823 | 0 | } |
824 | 0 | if (expected_bandwidth_usage) { |
825 | 0 | const uint64_t expected_usage = |
826 | 0 | expected_bandwidth_usage * SOFT_LIM_MINUTES; |
827 | 0 | if (acct_max > expected_usage && acct_max - expected_usage > soft_limit) |
828 | 0 | soft_limit = acct_max - expected_usage; |
829 | 0 | } |
830 | |
|
831 | 0 | if (!soft_limit) |
832 | 0 | return 0; |
833 | 0 | return get_accounting_bytes() >= soft_limit; |
834 | 0 | } |
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 | | hibernate_begin(hibernate_state_t new_state, time_t now) |
841 | 0 | { |
842 | 0 | const or_options_t *options = get_options(); |
843 | |
|
844 | 0 | 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 | 0 | hibernate_state == HIBERNATE_STATE_EXITING ? |
848 | 0 | "a second time" : "while hibernating"); |
849 | 0 | tor_shutdown_event_loop_and_exit(0); |
850 | 0 | return; |
851 | 0 | } |
852 | | |
853 | 0 | if (new_state == HIBERNATE_STATE_LOWBANDWIDTH && |
854 | 0 | hibernate_state == HIBERNATE_STATE_LIVE) { |
855 | 0 | soft_limit_hit_at = now; |
856 | 0 | n_seconds_to_hit_soft_limit = n_seconds_active_in_interval; |
857 | 0 | n_bytes_at_soft_limit = get_accounting_bytes(); |
858 | 0 | } |
859 | | |
860 | | /* close listeners. leave control listener(s). */ |
861 | 0 | connection_mark_all_noncontrol_listeners(); |
862 | | |
863 | | /* XXX kill intro point circs */ |
864 | | /* XXX upload rendezvous service descriptors with no intro points */ |
865 | |
|
866 | 0 | if (new_state == HIBERNATE_STATE_EXITING) { |
867 | 0 | log_notice(LD_GENERAL,"Interrupt: we have stopped accepting new " |
868 | 0 | "connections, and will shut down in %d seconds. Interrupt " |
869 | 0 | "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 | | sd_notifyf(0, "EXTEND_TIMEOUT_USEC=%" PRIu64, |
895 | | ((uint64_t)(options->ShutdownWaitLength) + 30) * TOR_USEC_PER_SEC); |
896 | | #endif /* defined(HAVE_SYSTEMD) */ |
897 | 0 | } else { /* soft limit reached */ |
898 | 0 | hibernate_end_time = interval_end_time; |
899 | 0 | } |
900 | |
|
901 | 0 | hibernate_state = new_state; |
902 | 0 | accounting_record_bandwidth_usage(now, get_or_state()); |
903 | |
|
904 | 0 | or_state_mark_dirty(get_or_state(), |
905 | 0 | get_options()->AvoidDiskWrites ? now+600 : 0); |
906 | 0 | } |
907 | | |
908 | | /** Called when we've been hibernating and our timeout is reached. */ |
909 | | static void |
910 | | hibernate_end(hibernate_state_t new_state) |
911 | 0 | { |
912 | 0 | tor_assert(hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH || |
913 | 0 | hibernate_state == HIBERNATE_STATE_DORMANT || |
914 | 0 | hibernate_state == HIBERNATE_STATE_INITIAL); |
915 | | |
916 | | /* listeners will be relaunched in run_scheduled_events() in main.c */ |
917 | 0 | if (hibernate_state != HIBERNATE_STATE_INITIAL) |
918 | 0 | log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity."); |
919 | |
|
920 | 0 | hibernate_state = new_state; |
921 | 0 | hibernate_end_time = 0; /* no longer hibernating */ |
922 | 0 | reset_uptime(); /* reset published uptime */ |
923 | 0 | } |
924 | | |
925 | | /** A wrapper around hibernate_begin, for when we get SIGINT. */ |
926 | | void |
927 | | hibernate_begin_shutdown(void) |
928 | 0 | { |
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 | | MOCK_IMPL(int, |
937 | | we_are_hibernating,(void)) |
938 | 0 | { |
939 | 0 | return hibernate_state != HIBERNATE_STATE_LIVE; |
940 | 0 | } |
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 | | MOCK_IMPL(int, |
947 | | we_are_fully_hibernating,(void)) |
948 | 0 | { |
949 | 0 | return hibernate_state == HIBERNATE_STATE_DORMANT; |
950 | 0 | } |
951 | | |
952 | | /** If we aren't currently dormant, close all connections and become |
953 | | * dormant. */ |
954 | | static void |
955 | | hibernate_go_dormant(time_t now) |
956 | 0 | { |
957 | 0 | connection_t *conn; |
958 | |
|
959 | 0 | if (hibernate_state == HIBERNATE_STATE_DORMANT) |
960 | 0 | return; |
961 | 0 | else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) |
962 | 0 | hibernate_state = HIBERNATE_STATE_DORMANT; |
963 | 0 | else |
964 | 0 | hibernate_begin(HIBERNATE_STATE_DORMANT, now); |
965 | | |
966 | 0 | 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 | 0 | while ((conn = connection_get_by_type(CONN_TYPE_OR)) || |
974 | 0 | (conn = connection_get_by_type(CONN_TYPE_AP)) || |
975 | 0 | (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 | 0 | } |
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 | 0 | 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 | 0 | } else { |
988 | 0 | connection_mark_for_close(conn); |
989 | 0 | } |
990 | 0 | } else { |
991 | 0 | connection_mark_for_close(conn); |
992 | 0 | } |
993 | 0 | } |
994 | |
|
995 | 0 | if (now < interval_wakeup_time) |
996 | 0 | hibernate_end_time = interval_wakeup_time; |
997 | 0 | else |
998 | 0 | hibernate_end_time = interval_end_time; |
999 | |
|
1000 | 0 | accounting_record_bandwidth_usage(now, get_or_state()); |
1001 | |
|
1002 | 0 | or_state_mark_dirty(get_or_state(), |
1003 | 0 | get_options()->AvoidDiskWrites ? now+600 : 0); |
1004 | |
|
1005 | 0 | hibernate_schedule_wakeup_event(now, hibernate_end_time); |
1006 | 0 | } |
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 | | hibernate_schedule_wakeup_event(time_t now, time_t end_time) |
1018 | 0 | { |
1019 | 0 | struct timeval delay = { 0, 0 }; |
1020 | |
|
1021 | 0 | 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 | 0 | delay.tv_sec = 1; |
1025 | 0 | } else { |
1026 | 0 | delay.tv_sec = (end_time - now); |
1027 | 0 | } |
1028 | |
|
1029 | 0 | if (!wakeup_event) { |
1030 | 0 | wakeup_event = mainloop_event_postloop_new(wakeup_event_callback, NULL); |
1031 | 0 | } |
1032 | |
|
1033 | 0 | mainloop_event_schedule(wakeup_event, &delay); |
1034 | 0 | } |
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 | | wakeup_event_callback(mainloop_event_t *ev, void *data) |
1042 | 0 | { |
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 | 0 | return; |
1052 | 0 | } |
1053 | | |
1054 | | /* We're still dormant. */ |
1055 | 0 | if (now < interval_wakeup_time) |
1056 | 0 | hibernate_end_time = interval_wakeup_time; |
1057 | 0 | else |
1058 | 0 | hibernate_end_time = interval_end_time; |
1059 | |
|
1060 | 0 | hibernate_schedule_wakeup_event(now, hibernate_end_time); |
1061 | 0 | } |
1062 | | |
1063 | | /** Called when hibernate_end_time has arrived. */ |
1064 | | static void |
1065 | | hibernate_end_time_elapsed(time_t now) |
1066 | 0 | { |
1067 | 0 | char buf[ISO_TIME_LEN+1]; |
1068 | | |
1069 | | /* The interval has ended, or it is wakeup time. Find out which. */ |
1070 | 0 | accounting_run_housekeeping(now); |
1071 | 0 | 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 | 0 | hibernate_end(HIBERNATE_STATE_LIVE); |
1075 | 0 | return; |
1076 | 0 | } 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 | 0 | "Accounting period ended. Commencing hibernation until " |
1084 | 0 | "%s UTC", buf); |
1085 | 0 | hibernate_go_dormant(now); |
1086 | 0 | } else { |
1087 | 0 | log_notice(LD_ACCT, |
1088 | 0 | "Accounting period ended. This period, we will hibernate" |
1089 | 0 | " until %s UTC",buf); |
1090 | 0 | } |
1091 | 0 | } |
1092 | 0 | } |
1093 | | |
1094 | | /** Consider our environment and decide if it's time |
1095 | | * to start/stop hibernating. |
1096 | | */ |
1097 | | void |
1098 | | consider_hibernation(time_t now) |
1099 | 0 | { |
1100 | 0 | int accounting_enabled = get_options()->AccountingMax != 0; |
1101 | 0 | char buf[ISO_TIME_LEN+1]; |
1102 | 0 | 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 | 0 | 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 | 0 | } |
1113 | 0 | return; /* if exiting soon, don't worry about bandwidth limits */ |
1114 | 0 | } |
1115 | | |
1116 | 0 | if (hibernate_state == HIBERNATE_STATE_DORMANT) { |
1117 | | /* We've been hibernating because of bandwidth accounting. */ |
1118 | 0 | tor_assert(hibernate_end_time); |
1119 | 0 | 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 | 0 | return; |
1123 | 0 | } else { |
1124 | 0 | hibernate_end_time_elapsed(now); |
1125 | 0 | } |
1126 | 0 | } |
1127 | | |
1128 | | /* Else, we aren't hibernating. See if it's time to start hibernating, or to |
1129 | | * go dormant. */ |
1130 | 0 | if (hibernate_state == HIBERNATE_STATE_LIVE || |
1131 | 0 | hibernate_state == HIBERNATE_STATE_INITIAL) { |
1132 | 0 | if (hibernate_soft_limit_reached()) { |
1133 | 0 | log_notice(LD_ACCT, |
1134 | 0 | "Bandwidth soft limit reached; commencing hibernation. " |
1135 | 0 | "No new connections will be accepted"); |
1136 | 0 | hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH, now); |
1137 | 0 | } 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 | 0 | "Commencing hibernation. We will wake up at %s local time.", |
1141 | 0 | buf); |
1142 | 0 | hibernate_go_dormant(now); |
1143 | 0 | } else if (hibernate_state == HIBERNATE_STATE_INITIAL) { |
1144 | 0 | hibernate_end(HIBERNATE_STATE_LIVE); |
1145 | 0 | } |
1146 | 0 | } |
1147 | |
|
1148 | 0 | if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH) { |
1149 | 0 | if (!accounting_enabled) { |
1150 | 0 | hibernate_end_time_elapsed(now); |
1151 | 0 | } else if (hibernate_hard_limit_reached()) { |
1152 | 0 | 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 | 0 | } |
1157 | 0 | } |
1158 | | |
1159 | | /* Dispatch a controller event if the hibernation state changed. */ |
1160 | 0 | if (hibernate_state != prev_state) |
1161 | 0 | on_hibernate_state_change(prev_state); |
1162 | 0 | } |
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 | | getinfo_helper_accounting(control_connection_t *conn, |
1171 | | const char *question, char **answer, |
1172 | | const char **errmsg) |
1173 | 0 | { |
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 | 0 | (n_bytes_read_in_interval), |
1184 | 0 | (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 | 0 | (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 | 0 | (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 | 0 | (limit), (write_left)); |
1206 | 0 | } 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 | 0 | (read_left), (write_left)); |
1214 | 0 | } |
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 | 0 | } else { |
1225 | 0 | *answer = NULL; |
1226 | 0 | } |
1227 | 0 | return 0; |
1228 | 0 | } |
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 | | on_hibernate_state_change(hibernate_state_t prev_state) |
1237 | 0 | { |
1238 | 0 | control_event_server_status(LOG_NOTICE, |
1239 | 0 | "HIBERNATION_STATUS STATUS=%s", |
1240 | 0 | 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 | 0 | if (prev_state != HIBERNATE_STATE_INITIAL) { |
1248 | 0 | rescan_periodic_events(get_options()); |
1249 | 0 | } |
1250 | 0 | } |
1251 | | |
1252 | | /** Free all resources held by the accounting module */ |
1253 | | void |
1254 | | accounting_free_all(void) |
1255 | 0 | { |
1256 | 0 | mainloop_event_free(wakeup_event); |
1257 | 0 | hibernate_state = HIBERNATE_STATE_INITIAL; |
1258 | 0 | hibernate_end_time = 0; |
1259 | 0 | shutdown_time = 0; |
1260 | 0 | } |
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 | | hibernate_set_state_for_testing_(hibernate_state_t newstate) |
1269 | 0 | { |
1270 | 0 | hibernate_state = newstate; |
1271 | 0 | } |
1272 | | #endif /* defined(TOR_UNIT_TESTS) */ |