btrack_circuit.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /* Copyright (c) 2007-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file btrack_circuit.c
  5. * \brief Bootstrap tracker for origin circuits
  6. *
  7. * Track state changes of origin circuits, as published by the circuit
  8. * subsystem.
  9. **/
  10. #include "core/or/or.h"
  11. #include "core/or/ocirc_event.h"
  12. #include "feature/control/btrack_circuit.h"
  13. #include "feature/control/control.h"
  14. #include "lib/log/log.h"
  15. /** Pair of a best origin circuit GID with its state or status */
  16. typedef struct btc_best_t {
  17. uint32_t gid;
  18. int val;
  19. } btc_best_t;
  20. /** GID and state of the best origin circuit we've seen so far */
  21. static btc_best_t best_any_state = { 0, -1 };
  22. /** GID and state of the best application circuit we've seen so far */
  23. static btc_best_t best_ap_state = { 0, -1 };
  24. /** GID and status of the best origin circuit we've seen so far */
  25. static btc_best_t best_any_evtype = { 0, -1 };
  26. /** GID and status of the best application circuit we've seen so far */
  27. static btc_best_t best_ap_evtype = { 0, -1 };
  28. /** Reset cached "best" values */
  29. static void
  30. btc_reset_bests(void)
  31. {
  32. best_any_state.gid = best_ap_state.gid = 0;
  33. best_any_state.val = best_ap_state.val = -1;
  34. best_any_evtype.gid = best_ap_state.gid = 0;
  35. best_any_evtype.val = best_ap_evtype.val = -1;
  36. }
  37. /** True if @a state is a "better" origin circuit state than @a best->val */
  38. static bool
  39. btc_state_better(int state, const btc_best_t *best)
  40. {
  41. return state > best->val;
  42. }
  43. /**
  44. * Definine an ordering on circuit status events
  45. *
  46. * The CIRC_EVENT_ constants aren't sorted in a useful order, so this
  47. * array helps to decode them. This approach depends on the statuses
  48. * being nonnegative and dense.
  49. **/
  50. static int circ_event_order[] = {
  51. [CIRC_EVENT_FAILED] = -1,
  52. [CIRC_EVENT_CLOSED] = -1,
  53. [CIRC_EVENT_LAUNCHED] = 1,
  54. [CIRC_EVENT_EXTENDED] = 2,
  55. [CIRC_EVENT_BUILT] = 3,
  56. };
  57. #define N_CIRC_EVENT_ORDER \
  58. (sizeof(circ_event_order) / sizeof(circ_event_order[0]))
  59. /** True if @a state is a "better" origin circuit event status than @a
  60. best->val */
  61. static bool
  62. btc_evtype_better(int state, const btc_best_t *best)
  63. {
  64. if (state < 0)
  65. return false;
  66. if (best->val < 0)
  67. return true;
  68. tor_assert(state >= 0 && (unsigned)state < N_CIRC_EVENT_ORDER);
  69. tor_assert(best->val >= 0 && (unsigned)best->val < N_CIRC_EVENT_ORDER);
  70. return circ_event_order[state] > circ_event_order[best->val];
  71. }
  72. static bool
  73. btc_update_state(const ocirc_state_msg_t *msg, btc_best_t *best,
  74. const char *type)
  75. {
  76. if (btc_state_better(msg->state, best)) {
  77. log_info(LD_BTRACK, "CIRC BEST_%s state %d->%d gid=%"PRIu32, type,
  78. best->val, msg->state, msg->gid);
  79. best->gid = msg->gid;
  80. best->val = msg->state;
  81. return true;
  82. }
  83. return false;
  84. }
  85. static bool
  86. btc_update_evtype(const ocirc_cevent_msg_t *msg, btc_best_t *best,
  87. const char *type)
  88. {
  89. if (btc_evtype_better(msg->evtype, best)) {
  90. log_info(LD_BTRACK, "CIRC BEST_%s evtype %d->%d gid=%"PRIu32, type,
  91. best->val, msg->evtype, msg->gid);
  92. best->gid = msg->gid;
  93. best->val = msg->evtype;
  94. return true;
  95. }
  96. return false;
  97. }
  98. DECLARE_SUBSCRIBE(ocirc_state, btc_state_rcvr);
  99. DECLARE_SUBSCRIBE(ocirc_cevent, btc_cevent_rcvr);
  100. DECLARE_SUBSCRIBE(ocirc_chan, btc_chan_rcvr);
  101. static void
  102. btc_state_rcvr(const msg_t *msg, const ocirc_state_msg_t *arg)
  103. {
  104. (void)msg;
  105. log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d",
  106. arg->gid, arg->state, arg->onehop);
  107. btc_update_state(arg, &best_any_state, "ANY");
  108. if (arg->onehop)
  109. return;
  110. btc_update_state(arg, &best_ap_state, "AP");
  111. }
  112. static void
  113. btc_cevent_rcvr(const msg_t *msg, const ocirc_cevent_msg_t *arg)
  114. {
  115. (void)msg;
  116. log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d",
  117. arg->gid, arg->evtype, arg->reason, arg->onehop);
  118. btc_update_evtype(arg, &best_any_evtype, "ANY");
  119. if (arg->onehop)
  120. return;
  121. btc_update_evtype(arg, &best_ap_evtype, "AP");
  122. }
  123. static void
  124. btc_chan_rcvr(const msg_t *msg, const ocirc_chan_msg_t *arg)
  125. {
  126. (void)msg;
  127. log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d",
  128. arg->gid, arg->chan, arg->onehop);
  129. }
  130. int
  131. btrack_circ_add_pubsub(pubsub_connector_t *connector)
  132. {
  133. if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_chan))
  134. return -1;
  135. if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_cevent))
  136. return -1;
  137. if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_state))
  138. return -1;
  139. return 0;
  140. }
  141. void
  142. btrack_circ_fini(void)
  143. {
  144. btc_reset_bests();
  145. }