rephist.c 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. /* Copyright 2004-2007 Roger Dingledine, Nick Mathewson. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. const char rephist_c_id[] =
  5. "$Id$";
  6. /**
  7. * \file rephist.c
  8. * \brief Basic history and "reputation" functionality to remember
  9. * which servers have worked in the past, how much bandwidth we've
  10. * been using, which ports we tend to want, and so on.
  11. **/
  12. #include "or.h"
  13. static void bw_arrays_init(void);
  14. static void predicted_ports_init(void);
  15. static void hs_usage_init(void);
  16. uint64_t rephist_total_alloc=0;
  17. uint32_t rephist_total_num=0;
  18. /** History of an OR-\>OR link. */
  19. typedef struct link_history_t {
  20. /** When did we start tracking this list? */
  21. time_t since;
  22. /** When did we most recently note a change to this link */
  23. time_t changed;
  24. /** How many times did extending from OR1 to OR2 succeed? */
  25. unsigned long n_extend_ok;
  26. /** How many times did extending from OR1 to OR2 fail? */
  27. unsigned long n_extend_fail;
  28. } link_history_t;
  29. /** History of an OR. */
  30. typedef struct or_history_t {
  31. /** When did we start tracking this OR? */
  32. time_t since;
  33. /** When did we most recently note a change to this OR? */
  34. time_t changed;
  35. /** How many times did we successfully connect? */
  36. unsigned long n_conn_ok;
  37. /** How many times did we try to connect and fail?*/
  38. unsigned long n_conn_fail;
  39. /** How many seconds have we been connected to this OR before
  40. * 'up_since'? */
  41. unsigned long uptime;
  42. /** How many seconds have we been unable to connect to this OR before
  43. * 'down_since'? */
  44. unsigned long downtime;
  45. /** If nonzero, we have been connected since this time. */
  46. time_t up_since;
  47. /** If nonzero, we have been unable to connect since this time. */
  48. time_t down_since;
  49. /** Map from hex OR2 identity digest to a link_history_t for the link
  50. * from this OR to OR2. */
  51. digestmap_t *link_history_map;
  52. } or_history_t;
  53. /** Map from hex OR identity digest to or_history_t. */
  54. static digestmap_t *history_map = NULL;
  55. /** Return the or_history_t for the named OR, creating it if necessary. */
  56. static or_history_t *
  57. get_or_history(const char* id)
  58. {
  59. or_history_t *hist;
  60. if (tor_mem_is_zero(id, DIGEST_LEN))
  61. return NULL;
  62. hist = digestmap_get(history_map, id);
  63. if (!hist) {
  64. hist = tor_malloc_zero(sizeof(or_history_t));
  65. rephist_total_alloc += sizeof(or_history_t);
  66. rephist_total_num++;
  67. hist->link_history_map = digestmap_new();
  68. hist->since = hist->changed = time(NULL);
  69. digestmap_set(history_map, id, hist);
  70. }
  71. return hist;
  72. }
  73. /** Return the link_history_t for the link from the first named OR to
  74. * the second, creating it if necessary. (ORs are identified by
  75. * identity digest.)
  76. */
  77. static link_history_t *
  78. get_link_history(const char *from_id, const char *to_id)
  79. {
  80. or_history_t *orhist;
  81. link_history_t *lhist;
  82. orhist = get_or_history(from_id);
  83. if (!orhist)
  84. return NULL;
  85. if (tor_mem_is_zero(to_id, DIGEST_LEN))
  86. return NULL;
  87. lhist = (link_history_t*) digestmap_get(orhist->link_history_map, to_id);
  88. if (!lhist) {
  89. lhist = tor_malloc_zero(sizeof(link_history_t));
  90. rephist_total_alloc += sizeof(link_history_t);
  91. lhist->since = lhist->changed = time(NULL);
  92. digestmap_set(orhist->link_history_map, to_id, lhist);
  93. }
  94. return lhist;
  95. }
  96. /** Helper: free storage held by a single link history entry. */
  97. static void
  98. _free_link_history(void *val)
  99. {
  100. rephist_total_alloc -= sizeof(link_history_t);
  101. tor_free(val);
  102. }
  103. /** Helper: free storage held by a single OR history entry. */
  104. static void
  105. free_or_history(void *_hist)
  106. {
  107. or_history_t *hist = _hist;
  108. digestmap_free(hist->link_history_map, _free_link_history);
  109. rephist_total_alloc -= sizeof(or_history_t);
  110. rephist_total_num--;
  111. tor_free(hist);
  112. }
  113. /** Update an or_history_t object <b>hist</b> so that its uptime/downtime
  114. * count is up-to-date as of <b>when</b>.
  115. */
  116. static void
  117. update_or_history(or_history_t *hist, time_t when)
  118. {
  119. tor_assert(hist);
  120. if (hist->up_since) {
  121. tor_assert(!hist->down_since);
  122. hist->uptime += (when - hist->up_since);
  123. hist->up_since = when;
  124. } else if (hist->down_since) {
  125. hist->downtime += (when - hist->down_since);
  126. hist->down_since = when;
  127. }
  128. }
  129. /** Initialize the static data structures for tracking history. */
  130. void
  131. rep_hist_init(void)
  132. {
  133. history_map = digestmap_new();
  134. bw_arrays_init();
  135. predicted_ports_init();
  136. hs_usage_init();
  137. }
  138. /** Remember that an attempt to connect to the OR with identity digest
  139. * <b>id</b> failed at <b>when</b>.
  140. */
  141. void
  142. rep_hist_note_connect_failed(const char* id, time_t when)
  143. {
  144. or_history_t *hist;
  145. hist = get_or_history(id);
  146. if (!hist)
  147. return;
  148. ++hist->n_conn_fail;
  149. if (hist->up_since) {
  150. hist->uptime += (when - hist->up_since);
  151. hist->up_since = 0;
  152. }
  153. if (!hist->down_since)
  154. hist->down_since = when;
  155. hist->changed = when;
  156. }
  157. /** Remember that an attempt to connect to the OR with identity digest
  158. * <b>id</b> succeeded at <b>when</b>.
  159. */
  160. void
  161. rep_hist_note_connect_succeeded(const char* id, time_t when)
  162. {
  163. or_history_t *hist;
  164. hist = get_or_history(id);
  165. if (!hist)
  166. return;
  167. ++hist->n_conn_ok;
  168. if (hist->down_since) {
  169. hist->downtime += (when - hist->down_since);
  170. hist->down_since = 0;
  171. }
  172. if (!hist->up_since)
  173. hist->up_since = when;
  174. hist->changed = when;
  175. }
  176. /** Remember that we intentionally closed our connection to the OR
  177. * with identity digest <b>id</b> at <b>when</b>.
  178. */
  179. void
  180. rep_hist_note_disconnect(const char* id, time_t when)
  181. {
  182. or_history_t *hist;
  183. hist = get_or_history(id);
  184. if (!hist)
  185. return;
  186. ++hist->n_conn_ok;
  187. if (hist->up_since) {
  188. hist->uptime += (when - hist->up_since);
  189. hist->up_since = 0;
  190. }
  191. hist->changed = when;
  192. }
  193. /** Remember that our connection to the OR with identity digest
  194. * <b>id</b> had an error and stopped working at <b>when</b>.
  195. */
  196. void
  197. rep_hist_note_connection_died(const char* id, time_t when)
  198. {
  199. or_history_t *hist;
  200. if (!id) {
  201. /* If conn has no nickname, it didn't complete its handshake, or something
  202. * went wrong. Ignore it.
  203. */
  204. return;
  205. }
  206. hist = get_or_history(id);
  207. if (!hist)
  208. return;
  209. if (hist->up_since) {
  210. hist->uptime += (when - hist->up_since);
  211. hist->up_since = 0;
  212. }
  213. if (!hist->down_since)
  214. hist->down_since = when;
  215. hist->changed = when;
  216. }
  217. /** Remember that we successfully extended from the OR with identity
  218. * digest <b>from_id</b> to the OR with identity digest
  219. * <b>to_name</b>.
  220. */
  221. void
  222. rep_hist_note_extend_succeeded(const char *from_id, const char *to_id)
  223. {
  224. link_history_t *hist;
  225. /* log_fn(LOG_WARN, "EXTEND SUCCEEDED: %s->%s",from_name,to_name); */
  226. hist = get_link_history(from_id, to_id);
  227. if (!hist)
  228. return;
  229. ++hist->n_extend_ok;
  230. hist->changed = time(NULL);
  231. }
  232. /** Remember that we tried to extend from the OR with identity digest
  233. * <b>from_id</b> to the OR with identity digest <b>to_name</b>, but
  234. * failed.
  235. */
  236. void
  237. rep_hist_note_extend_failed(const char *from_id, const char *to_id)
  238. {
  239. link_history_t *hist;
  240. /* log_fn(LOG_WARN, "EXTEND FAILED: %s->%s",from_name,to_name); */
  241. hist = get_link_history(from_id, to_id);
  242. if (!hist)
  243. return;
  244. ++hist->n_extend_fail;
  245. hist->changed = time(NULL);
  246. }
  247. /** Log all the reliability data we have remembered, with the chosen
  248. * severity.
  249. */
  250. void
  251. rep_hist_dump_stats(time_t now, int severity)
  252. {
  253. digestmap_iter_t *lhist_it;
  254. digestmap_iter_t *orhist_it;
  255. const char *name1, *name2, *digest1, *digest2;
  256. char hexdigest1[HEX_DIGEST_LEN+1];
  257. or_history_t *or_history;
  258. link_history_t *link_history;
  259. void *or_history_p, *link_history_p;
  260. double uptime;
  261. char buffer[2048];
  262. size_t len;
  263. int ret;
  264. unsigned long upt, downt;
  265. routerinfo_t *r;
  266. rep_history_clean(now - get_options()->RephistTrackTime);
  267. log(severity, LD_GENERAL, "--------------- Dumping history information:");
  268. for (orhist_it = digestmap_iter_init(history_map);
  269. !digestmap_iter_done(orhist_it);
  270. orhist_it = digestmap_iter_next(history_map,orhist_it)) {
  271. digestmap_iter_get(orhist_it, &digest1, &or_history_p);
  272. or_history = (or_history_t*) or_history_p;
  273. if ((r = router_get_by_digest(digest1)))
  274. name1 = r->nickname;
  275. else
  276. name1 = "(unknown)";
  277. base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
  278. update_or_history(or_history, now);
  279. upt = or_history->uptime;
  280. downt = or_history->downtime;
  281. if (upt+downt) {
  282. uptime = ((double)upt) / (upt+downt);
  283. } else {
  284. uptime=1.0;
  285. }
  286. log(severity, LD_GENERAL,
  287. "OR %s [%s]: %ld/%ld good connections; uptime %ld/%ld sec (%.2f%%)",
  288. name1, hexdigest1,
  289. or_history->n_conn_ok, or_history->n_conn_fail+or_history->n_conn_ok,
  290. upt, upt+downt, uptime*100.0);
  291. if (!digestmap_isempty(or_history->link_history_map)) {
  292. strlcpy(buffer, " Extend attempts: ", sizeof(buffer));
  293. len = strlen(buffer);
  294. for (lhist_it = digestmap_iter_init(or_history->link_history_map);
  295. !digestmap_iter_done(lhist_it);
  296. lhist_it = digestmap_iter_next(or_history->link_history_map,
  297. lhist_it)) {
  298. digestmap_iter_get(lhist_it, &digest2, &link_history_p);
  299. if ((r = router_get_by_digest(digest2)))
  300. name2 = r->nickname;
  301. else
  302. name2 = "(unknown)";
  303. link_history = (link_history_t*) link_history_p;
  304. ret = tor_snprintf(buffer+len, 2048-len, "%s(%ld/%ld); ", name2,
  305. link_history->n_extend_ok,
  306. link_history->n_extend_ok+link_history->n_extend_fail);
  307. if (ret<0)
  308. break;
  309. else
  310. len += ret;
  311. }
  312. log(severity, LD_GENERAL, "%s", buffer);
  313. }
  314. }
  315. }
  316. /** Remove history info for routers/links that haven't changed since
  317. * <b>before</b>.
  318. */
  319. void
  320. rep_history_clean(time_t before)
  321. {
  322. or_history_t *or_history;
  323. link_history_t *link_history;
  324. void *or_history_p, *link_history_p;
  325. digestmap_iter_t *orhist_it, *lhist_it;
  326. const char *d1, *d2;
  327. orhist_it = digestmap_iter_init(history_map);
  328. while (!digestmap_iter_done(orhist_it)) {
  329. digestmap_iter_get(orhist_it, &d1, &or_history_p);
  330. or_history = or_history_p;
  331. if (or_history->changed < before) {
  332. orhist_it = digestmap_iter_next_rmv(history_map, orhist_it);
  333. free_or_history(or_history);
  334. continue;
  335. }
  336. for (lhist_it = digestmap_iter_init(or_history->link_history_map);
  337. !digestmap_iter_done(lhist_it); ) {
  338. digestmap_iter_get(lhist_it, &d2, &link_history_p);
  339. link_history = link_history_p;
  340. if (link_history->changed < before) {
  341. lhist_it = digestmap_iter_next_rmv(or_history->link_history_map,
  342. lhist_it);
  343. rephist_total_alloc -= sizeof(link_history_t);
  344. tor_free(link_history);
  345. continue;
  346. }
  347. lhist_it = digestmap_iter_next(or_history->link_history_map,lhist_it);
  348. }
  349. orhist_it = digestmap_iter_next(history_map, orhist_it);
  350. }
  351. }
  352. /** For how many seconds do we keep track of individual per-second bandwidth
  353. * totals? */
  354. #define NUM_SECS_ROLLING_MEASURE 10
  355. /** How large are the intervals for which we track and report bandwidth use? */
  356. #define NUM_SECS_BW_SUM_INTERVAL (15*60)
  357. /** How far in the past do we remember and publish bandwidth use? */
  358. #define NUM_SECS_BW_SUM_IS_VALID (24*60*60)
  359. /** How many bandwidth usage intervals do we remember? (derived) */
  360. #define NUM_TOTALS (NUM_SECS_BW_SUM_IS_VALID/NUM_SECS_BW_SUM_INTERVAL)
  361. /** Structure to track bandwidth use, and remember the maxima for a given
  362. * time period.
  363. */
  364. typedef struct bw_array_t {
  365. /** Observation array: Total number of bytes transferred in each of the last
  366. * NUM_SECS_ROLLING_MEASURE seconds. This is used as a circular array. */
  367. uint64_t obs[NUM_SECS_ROLLING_MEASURE];
  368. int cur_obs_idx; /**< Current position in obs. */
  369. time_t cur_obs_time; /**< Time represented in obs[cur_obs_idx] */
  370. uint64_t total_obs; /**< Total for all members of obs except
  371. * obs[cur_obs_idx] */
  372. uint64_t max_total; /**< Largest value that total_obs has taken on in the
  373. * current period. */
  374. uint64_t total_in_period; /**< Total bytes transferred in the current
  375. * period. */
  376. /** When does the next period begin? */
  377. time_t next_period;
  378. /** Where in 'maxima' should the maximum bandwidth usage for the current
  379. * period be stored? */
  380. int next_max_idx;
  381. /** How many values in maxima/totals have been set ever? */
  382. int num_maxes_set;
  383. /** Circular array of the maximum
  384. * bandwidth-per-NUM_SECS_ROLLING_MEASURE usage for the last
  385. * NUM_TOTALS periods */
  386. uint64_t maxima[NUM_TOTALS];
  387. /** Circular array of the total bandwidth usage for the last NUM_TOTALS
  388. * periods */
  389. uint64_t totals[NUM_TOTALS];
  390. } bw_array_t;
  391. /** Shift the current period of b forward by one. */
  392. static void
  393. commit_max(bw_array_t *b)
  394. {
  395. /* Store total from current period. */
  396. b->totals[b->next_max_idx] = b->total_in_period;
  397. /* Store maximum from current period. */
  398. b->maxima[b->next_max_idx++] = b->max_total;
  399. /* Advance next_period and next_max_idx */
  400. b->next_period += NUM_SECS_BW_SUM_INTERVAL;
  401. if (b->next_max_idx == NUM_TOTALS)
  402. b->next_max_idx = 0;
  403. if (b->num_maxes_set < NUM_TOTALS)
  404. ++b->num_maxes_set;
  405. /* Reset max_total. */
  406. b->max_total = 0;
  407. /* Reset total_in_period. */
  408. b->total_in_period = 0;
  409. }
  410. /** Shift the current observation time of 'b' forward by one second. */
  411. static INLINE void
  412. advance_obs(bw_array_t *b)
  413. {
  414. int nextidx;
  415. uint64_t total;
  416. /* Calculate the total bandwidth for the last NUM_SECS_ROLLING_MEASURE
  417. * seconds; adjust max_total as needed.*/
  418. total = b->total_obs + b->obs[b->cur_obs_idx];
  419. if (total > b->max_total)
  420. b->max_total = total;
  421. nextidx = b->cur_obs_idx+1;
  422. if (nextidx == NUM_SECS_ROLLING_MEASURE)
  423. nextidx = 0;
  424. b->total_obs = total - b->obs[nextidx];
  425. b->obs[nextidx]=0;
  426. b->cur_obs_idx = nextidx;
  427. if (++b->cur_obs_time >= b->next_period)
  428. commit_max(b);
  429. }
  430. /** Add 'n' bytes to the number of bytes in b for second 'when'. */
  431. static INLINE void
  432. add_obs(bw_array_t *b, time_t when, uint64_t n)
  433. {
  434. /* Don't record data in the past. */
  435. if (when<b->cur_obs_time)
  436. return;
  437. /* If we're currently adding observations for an earlier second than
  438. * 'when', advance b->cur_obs_time and b->cur_obs_idx by an
  439. * appropriate number of seconds, and do all the other housekeeping */
  440. while (when>b->cur_obs_time)
  441. advance_obs(b);
  442. b->obs[b->cur_obs_idx] += n;
  443. b->total_in_period += n;
  444. }
  445. /** Allocate, initialize, and return a new bw_array. */
  446. static bw_array_t *
  447. bw_array_new(void)
  448. {
  449. bw_array_t *b;
  450. time_t start;
  451. b = tor_malloc_zero(sizeof(bw_array_t));
  452. rephist_total_alloc += sizeof(bw_array_t);
  453. start = time(NULL);
  454. b->cur_obs_time = start;
  455. b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
  456. return b;
  457. }
  458. static bw_array_t *read_array = NULL;
  459. static bw_array_t *write_array = NULL;
  460. /** Set up read_array and write_array. */
  461. static void
  462. bw_arrays_init(void)
  463. {
  464. read_array = bw_array_new();
  465. write_array = bw_array_new();
  466. }
  467. /** We read <b>num_bytes</b> more bytes in second <b>when</b>.
  468. *
  469. * Add num_bytes to the current running total for <b>when</b>.
  470. *
  471. * <b>when</b> can go back to time, but it's safe to ignore calls
  472. * earlier than the latest <b>when</b> you've heard of.
  473. */
  474. void
  475. rep_hist_note_bytes_written(int num_bytes, time_t when)
  476. {
  477. /* Maybe a circular array for recent seconds, and step to a new point
  478. * every time a new second shows up. Or simpler is to just to have
  479. * a normal array and push down each item every second; it's short.
  480. */
  481. /* When a new second has rolled over, compute the sum of the bytes we've
  482. * seen over when-1 to when-1-NUM_SECS_ROLLING_MEASURE, and stick it
  483. * somewhere. See rep_hist_bandwidth_assess() below.
  484. */
  485. add_obs(write_array, when, num_bytes);
  486. }
  487. /** We wrote <b>num_bytes</b> more bytes in second <b>when</b>.
  488. * (like rep_hist_note_bytes_written() above)
  489. */
  490. void
  491. rep_hist_note_bytes_read(int num_bytes, time_t when)
  492. {
  493. /* if we're smart, we can make this func and the one above share code */
  494. add_obs(read_array, when, num_bytes);
  495. }
  496. /** Helper: Return the largest value in b->maxima. (This is equal to the
  497. * most bandwidth used in any NUM_SECS_ROLLING_MEASURE period for the last
  498. * NUM_SECS_BW_SUM_IS_VALID seconds.)
  499. */
  500. static uint64_t
  501. find_largest_max(bw_array_t *b)
  502. {
  503. int i;
  504. uint64_t max;
  505. max=0;
  506. for (i=0; i<NUM_TOTALS; ++i) {
  507. if (b->maxima[i]>max)
  508. max = b->maxima[i];
  509. }
  510. return max;
  511. }
  512. /** Find the largest sums in the past NUM_SECS_BW_SUM_IS_VALID (roughly)
  513. * seconds. Find one sum for reading and one for writing. They don't have
  514. * to be at the same time).
  515. *
  516. * Return the smaller of these sums, divided by NUM_SECS_ROLLING_MEASURE.
  517. */
  518. int
  519. rep_hist_bandwidth_assess(void)
  520. {
  521. uint64_t w,r;
  522. r = find_largest_max(read_array);
  523. w = find_largest_max(write_array);
  524. if (r>w)
  525. return (int)(U64_TO_DBL(w)/NUM_SECS_ROLLING_MEASURE);
  526. else
  527. return (int)(U64_TO_DBL(r)/NUM_SECS_ROLLING_MEASURE);
  528. }
  529. /** Print the bandwidth history of b (either read_array or write_array)
  530. * into the buffer pointed to by buf. The format is simply comma
  531. * separated numbers, from oldest to newest.
  532. *
  533. * It returns the number of bytes written.
  534. */
  535. static size_t
  536. rep_hist_fill_bandwidth_history(char *buf, size_t len, bw_array_t *b)
  537. {
  538. char *cp = buf;
  539. int i, n;
  540. if (b->num_maxes_set <= b->next_max_idx) {
  541. /* We haven't been through the circular array yet; time starts at i=0.*/
  542. i = 0;
  543. } else {
  544. /* We've been around the array at least once. The next i to be
  545. overwritten is the oldest. */
  546. i = b->next_max_idx;
  547. }
  548. for (n=0; n<b->num_maxes_set; ++n,++i) {
  549. uint64_t total;
  550. while (i >= NUM_TOTALS) i -= NUM_TOTALS;
  551. /* Round the bandwidth used down to the nearest 1k. */
  552. total = b->totals[i] & ~0x3ff;
  553. if (n==(b->num_maxes_set-1))
  554. tor_snprintf(cp, len-(cp-buf), U64_FORMAT, U64_PRINTF_ARG(total));
  555. else
  556. tor_snprintf(cp, len-(cp-buf), U64_FORMAT",", U64_PRINTF_ARG(total));
  557. cp += strlen(cp);
  558. }
  559. return cp-buf;
  560. }
  561. /** Allocate and return lines for representing this server's bandwidth
  562. * history in its descriptor.
  563. */
  564. char *
  565. rep_hist_get_bandwidth_lines(int for_extrainfo)
  566. {
  567. char *buf, *cp;
  568. char t[ISO_TIME_LEN+1];
  569. int r;
  570. bw_array_t *b;
  571. size_t len;
  572. /* opt (read|write)-history yyyy-mm-dd HH:MM:SS (n s) n,n,n,n,n... */
  573. len = (60+20*NUM_TOTALS)*2;
  574. buf = tor_malloc_zero(len);
  575. cp = buf;
  576. for (r=0;r<2;++r) {
  577. b = r?read_array:write_array;
  578. tor_assert(b);
  579. format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
  580. tor_snprintf(cp, len-(cp-buf), "%s%s %s (%d s) ",
  581. for_extrainfo ? "" : "opt ",
  582. r ? "read-history" : "write-history", t,
  583. NUM_SECS_BW_SUM_INTERVAL);
  584. cp += strlen(cp);
  585. cp += rep_hist_fill_bandwidth_history(cp, len-(cp-buf), b);
  586. strlcat(cp, "\n", len-(cp-buf));
  587. ++cp;
  588. }
  589. return buf;
  590. }
  591. /** Update <b>state</b> with the newest bandwidth history. */
  592. void
  593. rep_hist_update_state(or_state_t *state)
  594. {
  595. int len, r;
  596. char *buf, *cp;
  597. smartlist_t **s_values;
  598. time_t *s_begins;
  599. int *s_interval;
  600. bw_array_t *b;
  601. len = 20*NUM_TOTALS+1;
  602. buf = tor_malloc_zero(len);
  603. for (r=0;r<2;++r) {
  604. b = r?read_array:write_array;
  605. s_begins = r?&state->BWHistoryReadEnds :&state->BWHistoryWriteEnds;
  606. s_interval= r?&state->BWHistoryReadInterval:&state->BWHistoryWriteInterval;
  607. s_values = r?&state->BWHistoryReadValues :&state->BWHistoryWriteValues;
  608. if (*s_values) {
  609. SMARTLIST_FOREACH(*s_values, char *, cp, tor_free(cp));
  610. smartlist_free(*s_values);
  611. }
  612. if (! server_mode(get_options())) {
  613. /* Clients don't need to store bandwidth history persistently;
  614. * force these values to the defaults. */
  615. /* FFFF we should pull the default out of config.c's state table,
  616. * so we don't have two defaults. */
  617. if (*s_begins != 0 || *s_interval != 900) {
  618. time_t now = time(NULL);
  619. time_t save_at = get_options()->AvoidDiskWrites ? now+3600 : now+600;
  620. or_state_mark_dirty(state, save_at);
  621. }
  622. *s_begins = 0;
  623. *s_interval = 900;
  624. *s_values = smartlist_create();
  625. continue;
  626. }
  627. *s_begins = b->next_period;
  628. *s_interval = NUM_SECS_BW_SUM_INTERVAL;
  629. cp = buf;
  630. cp += rep_hist_fill_bandwidth_history(cp, len, b);
  631. tor_snprintf(cp, len-(cp-buf), cp == buf ? U64_FORMAT : ","U64_FORMAT,
  632. U64_PRINTF_ARG(b->total_in_period));
  633. *s_values = smartlist_create();
  634. if (server_mode(get_options()))
  635. smartlist_split_string(*s_values, buf, ",", SPLIT_SKIP_SPACE, 0);
  636. }
  637. tor_free(buf);
  638. if (server_mode(get_options())) {
  639. or_state_mark_dirty(get_or_state(), time(NULL)+(2*3600));
  640. }
  641. }
  642. /** Set bandwidth history from our saved state. */
  643. int
  644. rep_hist_load_state(or_state_t *state, char **err)
  645. {
  646. time_t s_begins, start;
  647. time_t now = time(NULL);
  648. uint64_t v;
  649. int r,i,ok;
  650. int all_ok = 1;
  651. int s_interval;
  652. smartlist_t *s_values;
  653. bw_array_t *b;
  654. /* Assert they already have been malloced */
  655. tor_assert(read_array && write_array);
  656. for (r=0;r<2;++r) {
  657. b = r?read_array:write_array;
  658. s_begins = r?state->BWHistoryReadEnds:state->BWHistoryWriteEnds;
  659. s_interval = r?state->BWHistoryReadInterval:state->BWHistoryWriteInterval;
  660. s_values = r?state->BWHistoryReadValues:state->BWHistoryWriteValues;
  661. if (s_values && s_begins >= now - NUM_SECS_BW_SUM_INTERVAL*NUM_TOTALS) {
  662. start = s_begins - s_interval*(smartlist_len(s_values));
  663. b->cur_obs_time = start;
  664. b->next_period = start + NUM_SECS_BW_SUM_INTERVAL;
  665. SMARTLIST_FOREACH(s_values, char *, cp, {
  666. v = tor_parse_uint64(cp, 10, 0, UINT64_MAX, &ok, NULL);
  667. if (!ok) {
  668. all_ok=0;
  669. log_notice(LD_GENERAL, "Could not parse '%s' into a number.'", cp);
  670. }
  671. add_obs(b, start, v);
  672. start += NUM_SECS_BW_SUM_INTERVAL;
  673. });
  674. }
  675. /* Clean up maxima and observed */
  676. /* Do we really want to zero this for the purpose of max capacity? */
  677. for (i=0; i<NUM_SECS_ROLLING_MEASURE; ++i) {
  678. b->obs[i] = 0;
  679. }
  680. b->total_obs = 0;
  681. for (i=0; i<NUM_TOTALS; ++i) {
  682. b->maxima[i] = 0;
  683. }
  684. b->max_total = 0;
  685. }
  686. if (!all_ok) {
  687. *err = tor_strdup("Parsing of bandwidth history values failed");
  688. /* and create fresh arrays */
  689. tor_free(read_array);
  690. tor_free(write_array);
  691. read_array = bw_array_new();
  692. write_array = bw_array_new();
  693. return -1;
  694. }
  695. return 0;
  696. }
  697. /*********************************************************************/
  698. /** A list of port numbers that have been used recently. */
  699. static smartlist_t *predicted_ports_list=NULL;
  700. /** The corresponding most recently used time for each port. */
  701. static smartlist_t *predicted_ports_times=NULL;
  702. /** We just got an application request for a connection with
  703. * port <b>port</b>. Remember it for the future, so we can keep
  704. * some circuits open that will exit to this port.
  705. */
  706. static void
  707. add_predicted_port(uint16_t port, time_t now)
  708. {
  709. /* XXXX we could just use uintptr_t here, I think. */
  710. uint16_t *tmp_port = tor_malloc(sizeof(uint16_t));
  711. time_t *tmp_time = tor_malloc(sizeof(time_t));
  712. *tmp_port = port;
  713. *tmp_time = now;
  714. rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t);
  715. smartlist_add(predicted_ports_list, tmp_port);
  716. smartlist_add(predicted_ports_times, tmp_time);
  717. }
  718. /** Initialize whatever memory and structs are needed for predicting
  719. * which ports will be used. Also seed it with port 80, so we'll build
  720. * circuits on start-up.
  721. */
  722. static void
  723. predicted_ports_init(void)
  724. {
  725. predicted_ports_list = smartlist_create();
  726. predicted_ports_times = smartlist_create();
  727. add_predicted_port(80, time(NULL)); /* add one to kickstart us */
  728. }
  729. /** Free whatever memory is needed for predicting which ports will
  730. * be used.
  731. */
  732. static void
  733. predicted_ports_free(void)
  734. {
  735. rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t);
  736. SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp));
  737. smartlist_free(predicted_ports_list);
  738. rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t);
  739. SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp));
  740. smartlist_free(predicted_ports_times);
  741. }
  742. /** Remember that <b>port</b> has been asked for as of time <b>now</b>.
  743. * This is used for predicting what sorts of streams we'll make in the
  744. * future and making exit circuits to anticipate that.
  745. */
  746. void
  747. rep_hist_note_used_port(uint16_t port, time_t now)
  748. {
  749. int i;
  750. uint16_t *tmp_port;
  751. time_t *tmp_time;
  752. tor_assert(predicted_ports_list);
  753. tor_assert(predicted_ports_times);
  754. if (!port) /* record nothing */
  755. return;
  756. for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
  757. tmp_port = smartlist_get(predicted_ports_list, i);
  758. tmp_time = smartlist_get(predicted_ports_times, i);
  759. if (*tmp_port == port) {
  760. *tmp_time = now;
  761. return;
  762. }
  763. }
  764. /* it's not there yet; we need to add it */
  765. add_predicted_port(port, now);
  766. }
  767. /** For this long after we've seen a request for a given port, assume that
  768. * we'll want to make connections to the same port in the future. */
  769. #define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
  770. /** Return a pointer to the list of port numbers that
  771. * are likely to be asked for in the near future.
  772. *
  773. * The caller promises not to mess with it.
  774. */
  775. smartlist_t *
  776. rep_hist_get_predicted_ports(time_t now)
  777. {
  778. int i;
  779. uint16_t *tmp_port;
  780. time_t *tmp_time;
  781. tor_assert(predicted_ports_list);
  782. tor_assert(predicted_ports_times);
  783. /* clean out obsolete entries */
  784. for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
  785. tmp_time = smartlist_get(predicted_ports_times, i);
  786. if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
  787. tmp_port = smartlist_get(predicted_ports_list, i);
  788. log_debug(LD_CIRC, "Expiring predicted port %d", *tmp_port);
  789. smartlist_del(predicted_ports_list, i);
  790. smartlist_del(predicted_ports_times, i);
  791. rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t);
  792. tor_free(tmp_port);
  793. tor_free(tmp_time);
  794. i--;
  795. }
  796. }
  797. return predicted_ports_list;
  798. }
  799. /** The user asked us to do a resolve. Rather than keeping track of
  800. * timings and such of resolves, we fake it for now by making treating
  801. * it the same way as a connection to port 80. This way we will continue
  802. * to have circuits lying around if the user only uses Tor for resolves.
  803. */
  804. void
  805. rep_hist_note_used_resolve(time_t now)
  806. {
  807. rep_hist_note_used_port(80, now);
  808. }
  809. /** The last time at which we needed an internal circ. */
  810. static time_t predicted_internal_time = 0;
  811. /** The last time we needed an internal circ with good uptime. */
  812. static time_t predicted_internal_uptime_time = 0;
  813. /** The last time we needed an internal circ with good capacity. */
  814. static time_t predicted_internal_capacity_time = 0;
  815. /** Remember that we used an internal circ at time <b>now</b>. */
  816. void
  817. rep_hist_note_used_internal(time_t now, int need_uptime, int need_capacity)
  818. {
  819. predicted_internal_time = now;
  820. if (need_uptime)
  821. predicted_internal_uptime_time = now;
  822. if (need_capacity)
  823. predicted_internal_capacity_time = now;
  824. }
  825. /** Return 1 if we've used an internal circ recently; else return 0. */
  826. int
  827. rep_hist_get_predicted_internal(time_t now, int *need_uptime,
  828. int *need_capacity)
  829. {
  830. if (!predicted_internal_time) { /* initialize it */
  831. predicted_internal_time = now;
  832. predicted_internal_uptime_time = now;
  833. predicted_internal_capacity_time = now;
  834. }
  835. if (predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME < now)
  836. return 0; /* too long ago */
  837. if (predicted_internal_uptime_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now)
  838. *need_uptime = 1;
  839. if (predicted_internal_capacity_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now)
  840. *need_capacity = 1;
  841. return 1;
  842. }
  843. /** Any ports used lately? These are pre-seeded if we just started
  844. * up or if we're running a hidden service. */
  845. int
  846. any_predicted_circuits(time_t now)
  847. {
  848. return smartlist_len(predicted_ports_list) ||
  849. predicted_internal_time + PREDICTED_CIRCS_RELEVANCE_TIME >= now;
  850. }
  851. /** Return 1 if we have no need for circuits currently, else return 0. */
  852. int
  853. rep_hist_circbuilding_dormant(time_t now)
  854. {
  855. if (any_predicted_circuits(now))
  856. return 0;
  857. /* see if we'll still need to build testing circuits */
  858. if (server_mode(get_options()) && !check_whether_orport_reachable())
  859. return 0;
  860. if (!check_whether_dirport_reachable())
  861. return 0;
  862. return 1;
  863. }
  864. static uint32_t n_signed_dir_objs = 0;
  865. static uint32_t n_signed_routerdescs = 0;
  866. static uint32_t n_verified_dir_objs = 0;
  867. static uint32_t n_verified_routerdescs = 0;
  868. static uint32_t n_onionskins_encrypted = 0;
  869. static uint32_t n_onionskins_decrypted = 0;
  870. static uint32_t n_tls_client_handshakes = 0;
  871. static uint32_t n_tls_server_handshakes = 0;
  872. static uint32_t n_rend_client_ops = 0;
  873. static uint32_t n_rend_mid_ops = 0;
  874. static uint32_t n_rend_server_ops = 0;
  875. /** Increment the count of the number of times we've done <b>operation</b>. */
  876. void
  877. note_crypto_pk_op(pk_op_t operation)
  878. {
  879. switch (operation)
  880. {
  881. case SIGN_DIR:
  882. n_signed_dir_objs++;
  883. break;
  884. case SIGN_RTR:
  885. n_signed_routerdescs++;
  886. break;
  887. case VERIFY_DIR:
  888. n_verified_dir_objs++;
  889. break;
  890. case VERIFY_RTR:
  891. n_verified_routerdescs++;
  892. break;
  893. case ENC_ONIONSKIN:
  894. n_onionskins_encrypted++;
  895. break;
  896. case DEC_ONIONSKIN:
  897. n_onionskins_decrypted++;
  898. break;
  899. case TLS_HANDSHAKE_C:
  900. n_tls_client_handshakes++;
  901. break;
  902. case TLS_HANDSHAKE_S:
  903. n_tls_server_handshakes++;
  904. break;
  905. case REND_CLIENT:
  906. n_rend_client_ops++;
  907. break;
  908. case REND_MID:
  909. n_rend_mid_ops++;
  910. break;
  911. case REND_SERVER:
  912. n_rend_server_ops++;
  913. break;
  914. default:
  915. log_warn(LD_BUG, "Unknown pk operation %d", operation);
  916. }
  917. }
  918. /** Log the number of times we've done each public/private-key operation. */
  919. void
  920. dump_pk_ops(int severity)
  921. {
  922. log(severity, LD_GENERAL,
  923. "PK operations: %lu directory objects signed, "
  924. "%lu directory objects verified, "
  925. "%lu routerdescs signed, "
  926. "%lu routerdescs verified, "
  927. "%lu onionskins encrypted, "
  928. "%lu onionskins decrypted, "
  929. "%lu client-side TLS handshakes, "
  930. "%lu server-side TLS handshakes, "
  931. "%lu rendezvous client operations, "
  932. "%lu rendezvous middle operations, "
  933. "%lu rendezvous server operations.",
  934. (unsigned long) n_signed_dir_objs,
  935. (unsigned long) n_verified_dir_objs,
  936. (unsigned long) n_signed_routerdescs,
  937. (unsigned long) n_verified_routerdescs,
  938. (unsigned long) n_onionskins_encrypted,
  939. (unsigned long) n_onionskins_decrypted,
  940. (unsigned long) n_tls_client_handshakes,
  941. (unsigned long) n_tls_server_handshakes,
  942. (unsigned long) n_rend_client_ops,
  943. (unsigned long) n_rend_mid_ops,
  944. (unsigned long) n_rend_server_ops);
  945. }
  946. /** Free all storage held by the OR/link history caches, by the
  947. * bandwidth history arrays, or by the port history. */
  948. void
  949. rep_hist_free_all(void)
  950. {
  951. digestmap_free(history_map, free_or_history);
  952. tor_free(read_array);
  953. tor_free(write_array);
  954. predicted_ports_free();
  955. }
  956. /****************** hidden service usage statistics ******************/
  957. /** How large are the intervals for which we track and report hidden service
  958. * use? */
  959. #define NUM_SECS_HS_USAGE_SUM_INTERVAL (15*60)
  960. /** How far in the past do we remember and publish hidden service use? */
  961. #define NUM_SECS_HS_USAGE_SUM_IS_VALID (24*60*60)
  962. /** How many hidden service usage intervals do we remember? (derived) */
  963. #define NUM_TOTALS_HS_USAGE (NUM_SECS_HS_USAGE_SUM_IS_VALID/ \
  964. NUM_SECS_HS_USAGE_SUM_INTERVAL)
  965. /** List element containing a service id and the count. */
  966. typedef struct hs_usage_list_elem_t {
  967. /** Service id of this elem. */
  968. char service_id[REND_SERVICE_ID_LEN+1];
  969. /** Number of occurrences for the given service id. */
  970. uint32_t count;
  971. /* Pointer to next list elem */
  972. struct hs_usage_list_elem_t *next;
  973. } hs_usage_list_elem_t;
  974. /* Ordered list that stores service ids and the number of observations. It is
  975. * ordered by the number of occurrences in descending order. Its purpose is to
  976. * calculate the frequency distribution when the period is over. */
  977. typedef struct hs_usage_list_t {
  978. /* Pointer to the first element in the list. */
  979. hs_usage_list_elem_t *start;
  980. /* Number of total occurrences for all list elements. */
  981. uint32_t total_count;
  982. /* Number of service ids, i.e. number of list elements. */
  983. uint32_t total_service_ids;
  984. } hs_usage_list_t;
  985. /** Tracks service-related observations in the current period and their
  986. * history. */
  987. typedef struct hs_usage_service_related_observation_t {
  988. /** Ordered list that stores service ids and the number of observations in
  989. * the current period. It is ordered by the number of occurrences in
  990. * descending order. Its purpose is to calculate the frequency distribution
  991. * when the period is over. */
  992. hs_usage_list_t *list;
  993. /** Circular arrays that store the history of observations. totals stores all
  994. * observations, twenty (ten, five) the number of observations related to a
  995. * service id being accounted for the top 20 (10, 5) percent of all
  996. * observations. */
  997. uint32_t totals[NUM_TOTALS_HS_USAGE];
  998. uint32_t five[NUM_TOTALS_HS_USAGE];
  999. uint32_t ten[NUM_TOTALS_HS_USAGE];
  1000. uint32_t twenty[NUM_TOTALS_HS_USAGE];
  1001. } hs_usage_service_related_observation_t;
  1002. /** Tracks the history of general period-related observations, i.e. those that
  1003. * cannot be related to a specific service id. */
  1004. typedef struct hs_usage_general_period_related_observations_t {
  1005. /** Circular array that stores the history of observations. */
  1006. uint32_t totals[NUM_TOTALS_HS_USAGE];
  1007. } hs_usage_general_period_related_observations_t;
  1008. /** Keeps information about the current observation period and its relation to
  1009. * the histories of observations. */
  1010. typedef struct hs_usage_current_observation_period_t {
  1011. /** Where do we write the next history entry? */
  1012. int next_idx;
  1013. /** How many values in history have been set ever? (upper bound!) */
  1014. int num_set;
  1015. /** When did this period begin? */
  1016. time_t start_of_current_period;
  1017. /** When does the next period begin? */
  1018. time_t start_of_next_period;
  1019. } hs_usage_current_observation_period_t;
  1020. static hs_usage_current_observation_period_t *current_period = NULL;
  1021. static hs_usage_service_related_observation_t *publish_total = NULL;
  1022. static hs_usage_service_related_observation_t *publish_novel = NULL;
  1023. static hs_usage_service_related_observation_t *fetch_total = NULL;
  1024. static hs_usage_service_related_observation_t *fetch_successful = NULL;
  1025. static hs_usage_general_period_related_observations_t *descs = NULL;
  1026. /** Creates an empty ordered list element. */
  1027. static hs_usage_list_elem_t *
  1028. hs_usage_list_elem_new(void)
  1029. {
  1030. hs_usage_list_elem_t *e;
  1031. e = tor_malloc_zero(sizeof(hs_usage_list_elem_t));
  1032. rephist_total_alloc += sizeof(hs_usage_list_elem_t);
  1033. e->count = 1;
  1034. e->next = NULL;
  1035. return e;
  1036. }
  1037. /** Creates an empty ordered list. */
  1038. static hs_usage_list_t *
  1039. hs_usage_list_new(void)
  1040. {
  1041. hs_usage_list_t *l;
  1042. l = tor_malloc_zero(sizeof(hs_usage_list_t));
  1043. rephist_total_alloc += sizeof(hs_usage_list_t);
  1044. l->start = NULL;
  1045. l->total_count = 0;
  1046. l->total_service_ids = 0;
  1047. return l;
  1048. }
  1049. /** Creates an empty structure for storing service-related observations. */
  1050. static hs_usage_service_related_observation_t *
  1051. hs_usage_service_related_observation_new(void)
  1052. {
  1053. hs_usage_service_related_observation_t *h;
  1054. h = tor_malloc_zero(sizeof(hs_usage_service_related_observation_t));
  1055. rephist_total_alloc += sizeof(hs_usage_service_related_observation_t);
  1056. h->list = hs_usage_list_new();
  1057. return h;
  1058. }
  1059. /** Creates an empty structure for storing general period-related
  1060. * observations. */
  1061. static hs_usage_general_period_related_observations_t *
  1062. hs_usage_general_period_related_observations_new(void)
  1063. {
  1064. hs_usage_general_period_related_observations_t *p;
  1065. p = tor_malloc_zero(sizeof(hs_usage_general_period_related_observations_t));
  1066. rephist_total_alloc+= sizeof(hs_usage_general_period_related_observations_t);
  1067. return p;
  1068. }
  1069. /** Creates an empty structure for storing period-specific information. */
  1070. static hs_usage_current_observation_period_t *
  1071. hs_usage_current_observation_period_new(void)
  1072. {
  1073. hs_usage_current_observation_period_t *c;
  1074. time_t now;
  1075. c = tor_malloc_zero(sizeof(hs_usage_current_observation_period_t));
  1076. rephist_total_alloc += sizeof(hs_usage_current_observation_period_t);
  1077. now = time(NULL);
  1078. c->start_of_current_period = now;
  1079. c->start_of_next_period = now + NUM_SECS_HS_USAGE_SUM_INTERVAL;
  1080. return c;
  1081. }
  1082. /** Initializes the structures for collecting hidden service usage data. */
  1083. static void
  1084. hs_usage_init(void)
  1085. {
  1086. current_period = hs_usage_current_observation_period_new();
  1087. publish_total = hs_usage_service_related_observation_new();
  1088. publish_novel = hs_usage_service_related_observation_new();
  1089. fetch_total = hs_usage_service_related_observation_new();
  1090. fetch_successful = hs_usage_service_related_observation_new();
  1091. descs = hs_usage_general_period_related_observations_new();
  1092. }
  1093. /** Clears the given ordered list by resetting its attributes and releasing
  1094. * the memory allocated by its elements. */
  1095. static void
  1096. hs_usage_list_clear(hs_usage_list_t *lst)
  1097. {
  1098. /* walk through elements and free memory */
  1099. hs_usage_list_elem_t *current = lst->start;
  1100. hs_usage_list_elem_t *tmp;
  1101. while (current != NULL) {
  1102. tmp = current->next;
  1103. rephist_total_alloc -= sizeof(hs_usage_list_elem_t);
  1104. tor_free(current);
  1105. current = tmp;
  1106. }
  1107. /* reset attributes */
  1108. lst->start = NULL;
  1109. lst->total_count = 0;
  1110. lst->total_service_ids = 0;
  1111. return;
  1112. }
  1113. /** Frees the memory used by the given list. */
  1114. static void
  1115. hs_usage_list_free(hs_usage_list_t *lst)
  1116. {
  1117. if (!lst)
  1118. return;
  1119. hs_usage_list_clear(lst);
  1120. rephist_total_alloc -= sizeof(hs_usage_list_t);
  1121. tor_free(lst);
  1122. }
  1123. /** Frees the memory used by the given service-related observations. */
  1124. static void
  1125. hs_usage_service_related_observation_free(
  1126. hs_usage_service_related_observation_t *s)
  1127. {
  1128. if (!s)
  1129. return;
  1130. hs_usage_list_free(s->list);
  1131. rephist_total_alloc -= sizeof(hs_usage_service_related_observation_t);
  1132. tor_free(s);
  1133. }
  1134. /** Frees the memory used by the given period-specific observations. */
  1135. static void
  1136. hs_usage_general_period_related_observations_free(
  1137. hs_usage_general_period_related_observations_t *s)
  1138. {
  1139. rephist_total_alloc-=sizeof(hs_usage_general_period_related_observations_t);
  1140. tor_free(s);
  1141. }
  1142. /** Frees the memory used by period-specific information. */
  1143. static void
  1144. hs_usage_current_observation_period_free(
  1145. hs_usage_current_observation_period_t *s)
  1146. {
  1147. rephist_total_alloc -= sizeof(hs_usage_current_observation_period_t);
  1148. tor_free(s);
  1149. }
  1150. /** Frees all memory that was used for collecting hidden service usage data. */
  1151. void
  1152. hs_usage_free_all(void)
  1153. {
  1154. hs_usage_general_period_related_observations_free(descs);
  1155. descs = NULL;
  1156. hs_usage_service_related_observation_free(fetch_successful);
  1157. hs_usage_service_related_observation_free(fetch_total);
  1158. hs_usage_service_related_observation_free(publish_novel);
  1159. hs_usage_service_related_observation_free(publish_total);
  1160. fetch_successful = fetch_total = publish_novel = publish_total = NULL;
  1161. hs_usage_current_observation_period_free(current_period);
  1162. current_period = NULL;
  1163. }
  1164. /** Inserts a new occurrence for the given service id to the given ordered
  1165. * list. */
  1166. static void
  1167. hs_usage_insert_value(hs_usage_list_t *lst, const char *service_id)
  1168. {
  1169. /* search if there is already an elem with same service_id in list */
  1170. hs_usage_list_elem_t *current = lst->start;
  1171. hs_usage_list_elem_t *previous = NULL;
  1172. while (current != NULL && strcasecmp(current->service_id,service_id)) {
  1173. previous = current;
  1174. current = current->next;
  1175. }
  1176. /* found an element with same service_id? */
  1177. if (current == NULL) {
  1178. /* not found! append to end (which could also be the end of a zero-length
  1179. * list), don't need to sort (1 is smallest value). */
  1180. /* create elem */
  1181. hs_usage_list_elem_t *e = hs_usage_list_elem_new();
  1182. /* update list attributes (one new elem, one new occurrence) */
  1183. lst->total_count++;
  1184. lst->total_service_ids++;
  1185. /* copy service id to elem */
  1186. strlcpy(e->service_id,service_id,sizeof(e->service_id));
  1187. /* let either l->start or previously last elem point to new elem */
  1188. if (lst->start == NULL) {
  1189. /* this is the first elem */
  1190. lst->start = e;
  1191. } else {
  1192. /* there were elems in the list before */
  1193. previous->next = e;
  1194. }
  1195. } else {
  1196. /* found! add occurrence to elem and consider resorting */
  1197. /* update list attributes (no new elem, but one new occurrence) */
  1198. lst->total_count++;
  1199. /* add occurrence to elem */
  1200. current->count++;
  1201. /* is it another than the first list elem? and has previous elem fewer
  1202. * count than current? then we need to resort */
  1203. if (previous != NULL && previous->count < current->count) {
  1204. /* yes! we need to resort */
  1205. /* remove current elem first */
  1206. previous->next = current->next;
  1207. /* can we prepend elem to all other elements? */
  1208. if (lst->start->count <= current->count) {
  1209. /* yes! prepend elem */
  1210. current->next = lst->start;
  1211. lst->start = current;
  1212. } else {
  1213. /* no! walk through list a second time and insert at correct place */
  1214. hs_usage_list_elem_t *insert_current = lst->start->next;
  1215. hs_usage_list_elem_t *insert_previous = lst->start;
  1216. while (insert_current != NULL &&
  1217. insert_current->count > current->count) {
  1218. insert_previous = insert_current;
  1219. insert_current = insert_current->next;
  1220. }
  1221. /* insert here */
  1222. current->next = insert_current;
  1223. insert_previous->next = current;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. /** Writes the current service-related observations to the history array and
  1229. * clears the observations of the current period. */
  1230. static void
  1231. hs_usage_write_service_related_observations_to_history(
  1232. hs_usage_current_observation_period_t *p,
  1233. hs_usage_service_related_observation_t *h)
  1234. {
  1235. /* walk through the first 20 % of list elements and calculate frequency
  1236. * distributions */
  1237. /* maximum indices for the three frequencies */
  1238. int five_percent_idx = h->list->total_service_ids/20;
  1239. int ten_percent_idx = h->list->total_service_ids/10;
  1240. int twenty_percent_idx = h->list->total_service_ids/5;
  1241. /* temp values */
  1242. uint32_t five_percent = 0;
  1243. uint32_t ten_percent = 0;
  1244. uint32_t twenty_percent = 0;
  1245. /* walk through list */
  1246. hs_usage_list_elem_t *current = h->list->start;
  1247. int i=0;
  1248. while (current != NULL && i <= twenty_percent_idx) {
  1249. twenty_percent += current->count;
  1250. if (i <= ten_percent_idx)
  1251. ten_percent += current->count;
  1252. if (i <= five_percent_idx)
  1253. five_percent += current->count;
  1254. current = current->next;
  1255. i++;
  1256. }
  1257. /* copy frequencies */
  1258. h->twenty[p->next_idx] = twenty_percent;
  1259. h->ten[p->next_idx] = ten_percent;
  1260. h->five[p->next_idx] = five_percent;
  1261. /* copy total number of observations */
  1262. h->totals[p->next_idx] = h->list->total_count;
  1263. /* free memory of old list */
  1264. hs_usage_list_clear(h->list);
  1265. }
  1266. /** Advances to next observation period */
  1267. static void
  1268. hs_usage_advance_current_observation_period(void)
  1269. {
  1270. /* aggregate observations to history, including frequency distribution
  1271. * arrays */
  1272. hs_usage_write_service_related_observations_to_history(
  1273. current_period, publish_total);
  1274. hs_usage_write_service_related_observations_to_history(
  1275. current_period, publish_novel);
  1276. hs_usage_write_service_related_observations_to_history(
  1277. current_period, fetch_total);
  1278. hs_usage_write_service_related_observations_to_history(
  1279. current_period, fetch_successful);
  1280. /* write current number of descriptors to descs history */
  1281. descs->totals[current_period->next_idx] = rend_cache_size();
  1282. /* advance to next period */
  1283. current_period->next_idx++;
  1284. if (current_period->next_idx == NUM_TOTALS_HS_USAGE)
  1285. current_period->next_idx = 0;
  1286. if (current_period->num_set < NUM_TOTALS_HS_USAGE)
  1287. ++current_period->num_set;
  1288. current_period->start_of_current_period=current_period->start_of_next_period;
  1289. current_period->start_of_next_period += NUM_SECS_HS_USAGE_SUM_INTERVAL;
  1290. }
  1291. /** Checks if the current period is up to date, and if not, advances it. */
  1292. static void
  1293. hs_usage_check_if_current_period_is_up_to_date(time_t now)
  1294. {
  1295. while (now > current_period->start_of_next_period) {
  1296. hs_usage_advance_current_observation_period();
  1297. }
  1298. }
  1299. /** Adds a service-related observation, maybe after advancing to next
  1300. * observation period. */
  1301. static void
  1302. hs_usage_add_service_related_observation(
  1303. hs_usage_service_related_observation_t *h,
  1304. time_t now,
  1305. const char *service_id)
  1306. {
  1307. if (now < current_period->start_of_current_period) {
  1308. /* don't record old data */
  1309. return;
  1310. }
  1311. /* check if we are up-to-date */
  1312. hs_usage_check_if_current_period_is_up_to_date(now);
  1313. /* add observation */
  1314. hs_usage_insert_value(h->list, service_id);
  1315. }
  1316. /** Adds the observation of storing a rendezvous service descriptor to our
  1317. * cache in our role as HS authoritative directory. */
  1318. void
  1319. hs_usage_note_publish_total(const char *service_id, time_t now)
  1320. {
  1321. hs_usage_add_service_related_observation(publish_total, now, service_id);
  1322. }
  1323. /** Adds the observation of storing a novel rendezvous service descriptor to
  1324. * our cache in our role as HS authoritative directory. */
  1325. void
  1326. hs_usage_note_publish_novel(const char *service_id, time_t now)
  1327. {
  1328. hs_usage_add_service_related_observation(publish_novel, now, service_id);
  1329. }
  1330. /** Adds the observation of being requested for a rendezvous service descriptor
  1331. * in our role as HS authoritative directory. */
  1332. void
  1333. hs_usage_note_fetch_total(const char *service_id, time_t now)
  1334. {
  1335. hs_usage_add_service_related_observation(fetch_total, now, service_id);
  1336. }
  1337. /** Adds the observation of being requested for a rendezvous service descriptor
  1338. * in our role as HS authoritative directory and being able to answer that
  1339. * request successfully. */
  1340. void
  1341. hs_usage_note_fetch_successful(const char *service_id, time_t now)
  1342. {
  1343. hs_usage_add_service_related_observation(fetch_successful, now, service_id);
  1344. }
  1345. /** Writes the given circular array to a string */
  1346. static size_t
  1347. hs_usage_format_history(char *buf, size_t len, uint32_t *data)
  1348. {
  1349. char *cp = buf; /* pointer where we are in the buffer */
  1350. int i, n;
  1351. if (current_period->num_set <= current_period->next_idx) {
  1352. i = 0; /* not been through circular array */
  1353. } else {
  1354. i = current_period->next_idx;
  1355. }
  1356. for (n = 0; n < current_period->num_set; ++n,++i) {
  1357. while (i >= NUM_TOTALS_HS_USAGE) i -= NUM_TOTALS_HS_USAGE;
  1358. if (n == (current_period->num_set-1))
  1359. tor_snprintf(cp, len-(cp-buf), "%d", data[i]);
  1360. else
  1361. tor_snprintf(cp, len-(cp-buf), "%d,", data[i]);
  1362. cp += strlen(cp);
  1363. }
  1364. return cp-buf;
  1365. }
  1366. /** Writes the complete usage history as hidden service authoritative directory
  1367. * to a string */
  1368. static char *
  1369. hs_usage_format_statistics(void)
  1370. {
  1371. char *buf, *cp, *s = NULL;
  1372. char t[ISO_TIME_LEN+1];
  1373. int r;
  1374. uint32_t *data = NULL;
  1375. size_t len;
  1376. len = (70+20*NUM_TOTALS_HS_USAGE)*11;
  1377. buf = tor_malloc_zero(len);
  1378. cp = buf;
  1379. for (r = 0; r < 11; ++r) {
  1380. switch (r) {
  1381. case 0:
  1382. s = (char*) "publish-total-history";
  1383. data = publish_total->totals;
  1384. break;
  1385. case 1:
  1386. s = (char*) "publish-novel-history";
  1387. data = publish_novel->totals;
  1388. break;
  1389. case 2:
  1390. s = (char*) "publish-top-5-percent-history";
  1391. data = publish_total->five;
  1392. break;
  1393. case 3:
  1394. s = (char*) "publish-top-10-percent-history";
  1395. data = publish_total->ten;
  1396. break;
  1397. case 4:
  1398. s = (char*) "publish-top-20-percent-history";
  1399. data = publish_total->twenty;
  1400. break;
  1401. case 5:
  1402. s = (char*) "fetch-total-history";
  1403. data = fetch_total->totals;
  1404. break;
  1405. case 6:
  1406. s = (char*) "fetch-successful-history";
  1407. data = fetch_successful->totals;
  1408. break;
  1409. case 7:
  1410. s = (char*) "fetch-top-5-percent-history";
  1411. data = fetch_total->five;
  1412. break;
  1413. case 8:
  1414. s = (char*) "fetch-top-10-percent-history";
  1415. data = fetch_total->ten;
  1416. break;
  1417. case 9:
  1418. s = (char*) "fetch-top-20-percent-history";
  1419. data = fetch_total->twenty;
  1420. break;
  1421. case 10:
  1422. s = (char*) "desc-total-history";
  1423. data = descs->totals;
  1424. break;
  1425. }
  1426. format_iso_time(t, current_period->start_of_current_period);
  1427. tor_snprintf(cp, len-(cp-buf), "%s %s (%d s) ", s, t,
  1428. NUM_SECS_HS_USAGE_SUM_INTERVAL);
  1429. cp += strlen(cp);
  1430. cp += hs_usage_format_history(cp, len-(cp-buf), data);
  1431. strlcat(cp, "\n", len-(cp-buf));
  1432. ++cp;
  1433. }
  1434. return buf;
  1435. }
  1436. /** Writes current statistics to file. */
  1437. void
  1438. hs_usage_write_statistics_to_file(time_t now)
  1439. {
  1440. char *buf;
  1441. size_t len;
  1442. char *fname;
  1443. or_options_t *options;
  1444. /* check if we are up-to-date */
  1445. hs_usage_check_if_current_period_is_up_to_date(now);
  1446. buf = hs_usage_format_statistics();
  1447. options = get_options();
  1448. len = strlen(options->DataDirectory) + 16;
  1449. fname = tor_malloc(len);
  1450. tor_snprintf(fname,len, "%s"PATH_SEPARATOR"hsusage", options->DataDirectory);
  1451. write_str_to_file(fname,buf,0);
  1452. tor_free(buf);
  1453. tor_free(fname);
  1454. }