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