btrack_orconn_maps.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* Copyright (c) 2007-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file btrack_orconn_maps.c
  5. * \brief Hash map implementation for btrack_orconn.c
  6. *
  7. * These functions manipulate the hash maps that contain bt_orconn
  8. * objects.
  9. **/
  10. #include <stdbool.h>
  11. #include "core/or/or.h"
  12. #include "ht.h"
  13. #include "siphash.h"
  14. #define BTRACK_ORCONN_PRIVATE
  15. #include "feature/control/btrack_orconn.h"
  16. #include "feature/control/btrack_orconn_maps.h"
  17. #include "lib/log/log.h"
  18. static inline unsigned int
  19. bto_gid_hash_(bt_orconn_t *elm)
  20. {
  21. return (unsigned)siphash24g(&elm->gid, sizeof(elm->gid));
  22. }
  23. static inline int
  24. bto_gid_eq_(bt_orconn_t *a, bt_orconn_t *b)
  25. {
  26. return a->gid == b->gid;
  27. }
  28. static inline unsigned int
  29. bto_chan_hash_(bt_orconn_t *elm)
  30. {
  31. return (unsigned)siphash24g(&elm->chan, sizeof(elm->chan));
  32. }
  33. static inline int
  34. bto_chan_eq_(bt_orconn_t *a, bt_orconn_t *b)
  35. {
  36. return a->chan == b->chan;
  37. }
  38. HT_HEAD(bto_gid_ht, bt_orconn_t);
  39. HT_PROTOTYPE(bto_gid_ht, bt_orconn_t, node, bto_gid_hash_, bto_gid_eq_)
  40. HT_GENERATE2(bto_gid_ht, bt_orconn_t, node,
  41. bto_gid_hash_, bto_gid_eq_, 0.6,
  42. tor_reallocarray_, tor_free_)
  43. static struct bto_gid_ht *bto_gid_map;
  44. HT_HEAD(bto_chan_ht, bt_orconn_t);
  45. HT_PROTOTYPE(bto_chan_ht, bt_orconn_t, chan_node, bto_chan_hash_, bto_chan_eq_)
  46. HT_GENERATE2(bto_chan_ht, bt_orconn_t, chan_node,
  47. bto_chan_hash_, bto_chan_eq_, 0.6,
  48. tor_reallocarray_, tor_free_)
  49. static struct bto_chan_ht *bto_chan_map;
  50. /** Clear the GID hash map, freeing any bt_orconn_t objects that become
  51. * unreferenced */
  52. static void
  53. bto_gid_clear_map(void)
  54. {
  55. bt_orconn_t **elt, **next, *c;
  56. for (elt = HT_START(bto_gid_ht, bto_gid_map);
  57. elt;
  58. elt = next) {
  59. c = *elt;
  60. next = HT_NEXT_RMV(bto_gid_ht, bto_gid_map, elt);
  61. c->gid = 0;
  62. /* Don't delete if chan ID isn't zero: it's still in the chan hash map */
  63. if (!c->chan)
  64. tor_free(c);
  65. }
  66. HT_CLEAR(bto_gid_ht, bto_gid_map);
  67. tor_free(bto_gid_map);
  68. }
  69. /** Clear the chan ID hash map, freeing any bt_orconn_t objects that
  70. * become unreferenced */
  71. static void
  72. bto_chan_clear_map(void)
  73. {
  74. bt_orconn_t **elt, **next, *c;
  75. for (elt = HT_START(bto_chan_ht, bto_chan_map);
  76. elt;
  77. elt = next) {
  78. c = *elt;
  79. next = HT_NEXT_RMV(bto_chan_ht, bto_chan_map, elt);
  80. c->chan = 0;
  81. /* Don't delete if GID isn't zero, it's still in the GID hash map */
  82. if (!c->gid)
  83. tor_free(c);
  84. }
  85. HT_CLEAR(bto_chan_ht, bto_chan_map);
  86. tor_free(bto_chan_map);
  87. }
  88. /** Delete a bt_orconn from the hash maps by GID */
  89. void
  90. bto_delete(uint64_t gid)
  91. {
  92. bt_orconn_t key, *bto;
  93. key.gid = gid;
  94. key.chan = 0;
  95. bto = HT_FIND(bto_gid_ht, bto_gid_map, &key);
  96. if (!bto) {
  97. /* The orconn might be unregistered because it's an EXT_OR_CONN? */
  98. log_debug(LD_BTRACK, "tried to delete unregistered ORCONN gid=%"PRIu64,
  99. gid);
  100. return;
  101. }
  102. HT_REMOVE(bto_gid_ht, bto_gid_map, &key);
  103. if (bto->chan) {
  104. key.chan = bto->chan;
  105. HT_REMOVE(bto_chan_ht, bto_chan_map, &key);
  106. }
  107. tor_free(bto);
  108. }
  109. /**
  110. * Helper for bto_find_or_new().
  111. *
  112. * Update GID and chan ID of an existing bt_orconn object if needed,
  113. * given a search key previously used within bto_find_or_new().
  114. **/
  115. static bt_orconn_t *
  116. bto_update(bt_orconn_t *bto, const bt_orconn_t *key)
  117. {
  118. /* ORCONN GIDs shouldn't change once assigned */
  119. tor_assert(!bto->gid || !key->gid || bto->gid == key->gid);
  120. if (!bto->gid && key->gid) {
  121. /* Got a gid when we didn't already have one; insert into gid map */
  122. log_debug(LD_BTRACK, "ORCONN chan=%"PRIu64" newgid=%"PRIu64, key->chan,
  123. key->gid);
  124. bto->gid = key->gid;
  125. HT_INSERT(bto_gid_ht, bto_gid_map, bto);
  126. }
  127. /* association of ORCONN with channel shouldn't change */
  128. tor_assert(!bto->chan || !key->chan || bto->chan == key->chan);
  129. if (!bto->chan && key->chan) {
  130. /* Got a chan when we didn't already have one; insert into chan map */
  131. log_debug(LD_BTRACK, "ORCONN gid=%"PRIu64" newchan=%"PRIu64,
  132. bto->gid, key->chan);
  133. bto->chan = key->chan;
  134. HT_INSERT(bto_chan_ht, bto_chan_map, bto);
  135. }
  136. return bto;
  137. }
  138. /** Helper for bto_find_or_new() */
  139. static bt_orconn_t *
  140. bto_new(const bt_orconn_t *key)
  141. {
  142. struct bt_orconn_t *bto = tor_malloc(sizeof(*bto));
  143. bto->gid = key->gid;
  144. bto->chan = key->chan;
  145. bto->state = 0;
  146. bto->proxy_type = 0;
  147. bto->is_orig = false;
  148. bto->is_onehop = true;
  149. if (bto->gid)
  150. HT_INSERT(bto_gid_ht, bto_gid_map, bto);
  151. if (bto->chan)
  152. HT_INSERT(bto_chan_ht, bto_chan_map, bto);
  153. return bto;
  154. }
  155. /**
  156. * Insert a new bt_orconn with the given GID and chan ID, or update
  157. * the GID and chan ID if one already exists.
  158. *
  159. * Return the found or allocated bt_orconn.
  160. **/
  161. bt_orconn_t *
  162. bto_find_or_new(uint64_t gid, uint64_t chan)
  163. {
  164. bt_orconn_t key, *bto = NULL;
  165. tor_assert(gid || chan);
  166. key.gid = gid;
  167. key.chan = chan;
  168. if (key.gid)
  169. bto = HT_FIND(bto_gid_ht, bto_gid_map, &key);
  170. if (!bto && key.chan) {
  171. /* Not found by GID; look up by chan ID */
  172. bto = HT_FIND(bto_chan_ht, bto_chan_map, &key);
  173. }
  174. if (bto)
  175. return bto_update(bto, &key);
  176. else
  177. return bto_new(&key);
  178. }
  179. /** Initialize the hash maps */
  180. void
  181. bto_init_maps(void)
  182. {
  183. bto_gid_map = tor_malloc(sizeof(*bto_gid_map));
  184. HT_INIT(bto_gid_ht, bto_gid_map);
  185. bto_chan_map = tor_malloc(sizeof(*bto_chan_map));
  186. HT_INIT(bto_chan_ht, bto_chan_map);
  187. }
  188. /** Clear the hash maps, freeing all associated storage */
  189. void
  190. bto_clear_maps(void)
  191. {
  192. bto_gid_clear_map();
  193. bto_chan_clear_map();
  194. }