Tor 0.4.9.0-alpha-dev
btrack_orconn_maps.c
Go to the documentation of this file.
1/* Copyright (c) 2007-2021, 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
25static inline unsigned int
26bto_gid_hash_(bt_orconn_t *elm)
27{
28 return (unsigned)siphash24g(&elm->gid, sizeof(elm->gid));
29}
30
31static inline int
32bto_gid_eq_(bt_orconn_t *a, bt_orconn_t *b)
33{
34 return a->gid == b->gid;
35}
36
37static inline unsigned int
38bto_chan_hash_(bt_orconn_t *elm)
39{
40 return (unsigned)siphash24g(&elm->chan, sizeof(elm->chan));
41}
42
43static inline int
44bto_chan_eq_(bt_orconn_t *a, bt_orconn_t *b)
45{
46 return a->chan == b->chan;
47}
48
49HT_HEAD(bto_gid_ht, bt_orconn_t);
50HT_PROTOTYPE(bto_gid_ht, bt_orconn_t, node, bto_gid_hash_, bto_gid_eq_);
51HT_GENERATE2(bto_gid_ht, bt_orconn_t, node,
52 bto_gid_hash_, bto_gid_eq_, 0.6,
54static struct bto_gid_ht *bto_gid_map;
55
56HT_HEAD(bto_chan_ht, bt_orconn_t);
57HT_PROTOTYPE(bto_chan_ht, bt_orconn_t, chan_node, bto_chan_hash_,
58 bto_chan_eq_);
59HT_GENERATE2(bto_chan_ht, bt_orconn_t, chan_node,
60 bto_chan_hash_, bto_chan_eq_, 0.6,
62static struct bto_chan_ht *bto_chan_map;
63
64/** Clear the GID hash map, freeing any bt_orconn_t objects that become
65 * unreferenced */
66static 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 */
88static 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 */
109void
110bto_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 **/
137static bt_orconn_t *
138bto_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() */
162static bt_orconn_t *
163bto_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 **/
188bt_orconn_t *
189bto_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 */
209void
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 */
219void
221{
224}
Header file for btrack_orconn.c.
void bto_clear_maps(void)
static void bto_gid_clear_map(void)
static bt_orconn_t * bto_new(const bt_orconn_t *key)
bt_orconn_t * bto_find_or_new(uint64_t gid, uint64_t chan)
static bt_orconn_t * bto_update(bt_orconn_t *bto, const bt_orconn_t *key)
void bto_init_maps(void)
static void bto_chan_clear_map(void)
void bto_delete(uint64_t gid)
Header file for btrack_orconn_maps.c.
HT_PROTOTYPE(hs_circuitmap_ht, circuit_t, hs_circuitmap_node, hs_circuit_hash_token, hs_circuits_have_same_token)
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht
Headers for log.c.
#define LD_BTRACK
Definition: log.h:119
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
Definition: malloc.c:146
void tor_free_(void *mem)
Definition: malloc.c:227
#define tor_free(p)
Definition: malloc.h:56
Master header file for Tor-specific functionality.
#define tor_assert(expr)
Definition: util_bug.h:103