1 /* Copyright (c) 2013-2016, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 * \brief Manages data structures for associating pairs of fingerprints. Used
8 * to handle combinations of identity/signing-key fingerprints for
15 /* Define fp_pair_map_t structures */
17 struct fp_pair_map_entry_s
{
18 HT_ENTRY(fp_pair_map_entry_s
) node
;
23 struct fp_pair_map_s
{
24 HT_HEAD(fp_pair_map_impl
, fp_pair_map_entry_s
) head
;
28 * Hash function and equality checker for fp_pair_map_t
31 /** Compare fp_pair_entry_t objects by key value. */
33 fp_pair_map_entries_eq(const fp_pair_map_entry_t
*a
,
34 const fp_pair_map_entry_t
*b
)
36 return tor_memeq(&(a
->key
), &(b
->key
), sizeof(fp_pair_t
));
39 /** Return a hash value for an fp_pair_entry_t. */
40 static inline unsigned int
41 fp_pair_map_entry_hash(const fp_pair_map_entry_t
*a
)
43 tor_assert(sizeof(a
->key
) == DIGEST_LEN
*2);
44 return (unsigned) siphash24g(&a
->key
, DIGEST_LEN
*2);
48 * Hash table functions for fp_pair_map_t
51 HT_PROTOTYPE(fp_pair_map_impl
, fp_pair_map_entry_s
, node
,
52 fp_pair_map_entry_hash
, fp_pair_map_entries_eq
)
53 HT_GENERATE2(fp_pair_map_impl
, fp_pair_map_entry_s
, node
,
54 fp_pair_map_entry_hash
, fp_pair_map_entries_eq
,
55 0.6, tor_reallocarray_
, tor_free_
)
57 /** Constructor to create a new empty map from fp_pair_t to void *
63 fp_pair_map_t
*result
;
65 result
= tor_malloc(sizeof(fp_pair_map_t
));
66 HT_INIT(fp_pair_map_impl
, &result
->head
);
70 /** Set the current value for key to val; returns the previous
71 * value for key if one was set, or NULL if one was not.
75 fp_pair_map_set(fp_pair_map_t
*map
, const fp_pair_t
*key
, void *val
)
77 fp_pair_map_entry_t
*resolve
;
78 fp_pair_map_entry_t search
;
85 memcpy(&(search
.key
), key
, sizeof(*key
));
86 resolve
= HT_FIND(fp_pair_map_impl
, &(map
->head
), &search
);
88 oldval
= resolve
->val
;
91 resolve
= tor_malloc_zero(sizeof(fp_pair_map_entry_t
));
92 memcpy(&(resolve
->key
), key
, sizeof(*key
));
94 HT_INSERT(fp_pair_map_impl
, &(map
->head
), resolve
);
101 /** Set the current value for the key (first, second) to val; returns
102 * the previous value for key if one was set, or NULL if one was not.
106 fp_pair_map_set_by_digests(fp_pair_map_t
*map
,
107 const char *first
, const char *second
,
115 memcpy(k
.first
, first
, DIGEST_LEN
);
116 memcpy(k
.second
, second
, DIGEST_LEN
);
118 return fp_pair_map_set(map
, &k
, val
);
121 /** Return the current value associated with key, or NULL if no value is set.
125 fp_pair_map_get(const fp_pair_map_t
*map
, const fp_pair_t
*key
)
127 fp_pair_map_entry_t
*resolve
;
128 fp_pair_map_entry_t search
;
134 memcpy(&(search
.key
), key
, sizeof(*key
));
135 resolve
= HT_FIND(fp_pair_map_impl
, &(map
->head
), &search
);
136 if (resolve
) val
= resolve
->val
;
141 /** Return the current value associated the key (first, second), or
142 * NULL if no value is set.
146 fp_pair_map_get_by_digests(const fp_pair_map_t
*map
,
147 const char *first
, const char *second
)
154 memcpy(k
.first
, first
, DIGEST_LEN
);
155 memcpy(k
.second
, second
, DIGEST_LEN
);
157 return fp_pair_map_get(map
, &k
);
160 /** Remove the value currently associated with key from the map.
161 * Return the value if one was set, or NULL if there was no entry for
162 * key. The caller must free any storage associated with the
167 fp_pair_map_remove(fp_pair_map_t
*map
, const fp_pair_t
*key
)
169 fp_pair_map_entry_t
*resolve
;
170 fp_pair_map_entry_t search
;
176 memcpy(&(search
.key
), key
, sizeof(*key
));
177 resolve
= HT_REMOVE(fp_pair_map_impl
, &(map
->head
), &search
);
186 /** Remove all entries from map, and deallocate storage for those entries.
187 * If free_val is provided, it is invoked on every value in map.
191 fp_pair_map_free(fp_pair_map_t
*map
, void (*free_val
)(void*))
193 fp_pair_map_entry_t
**ent
, **next
, *this;
196 for (ent
= HT_START(fp_pair_map_impl
, &(map
->head
));
197 ent
!= NULL
; ent
= next
) {
199 next
= HT_NEXT_RMV(fp_pair_map_impl
, &(map
->head
), ent
);
200 if (free_val
) free_val(this->val
);
203 tor_assert(HT_EMPTY(&(map
->head
)));
204 HT_CLEAR(fp_pair_map_impl
, &(map
->head
));
209 /** Return true iff map has no entries.
213 fp_pair_map_isempty(const fp_pair_map_t
*map
)
217 return HT_EMPTY(&(map
->head
));
220 /** Return the number of items in map.
224 fp_pair_map_size(const fp_pair_map_t
*map
)
228 return HT_SIZE(&(map
->head
));
231 /** return an iterator pointing to the start of map.
235 fp_pair_map_iter_init(fp_pair_map_t
*map
)
239 return HT_START(fp_pair_map_impl
, &(map
->head
));
242 /** Advance iter a single step to the next entry of map, and return
247 fp_pair_map_iter_next(fp_pair_map_t
*map
, fp_pair_map_iter_t
*iter
)
252 return HT_NEXT(fp_pair_map_impl
, &(map
->head
), iter
);
255 /** Advance iter a single step to the next entry of map, removing the current
256 * entry, and return its new value.
260 fp_pair_map_iter_next_rmv(fp_pair_map_t
*map
, fp_pair_map_iter_t
*iter
)
262 fp_pair_map_entry_t
*rmv
;
269 iter
= HT_NEXT_RMV(fp_pair_map_impl
, &(map
->head
), iter
);
275 /** Set *key_out and *val_out to the current entry pointed to by iter.
279 fp_pair_map_iter_get(fp_pair_map_iter_t
*iter
,
280 fp_pair_t
*key_out
, void **val_out
)
285 if (key_out
) memcpy(key_out
, &((*iter
)->key
), sizeof(fp_pair_t
));
286 if (val_out
) *val_out
= (*iter
)->val
;
289 /** Return true iff iter has advanced past the last entry of its map.
293 fp_pair_map_iter_done(fp_pair_map_iter_t
*iter
)
295 return (iter
== NULL
);
298 /** Assert if anything has gone wrong with the internal
299 * representation of map.
303 fp_pair_map_assert_ok(const fp_pair_map_t
*map
)
305 tor_assert(!fp_pair_map_impl_HT_REP_IS_BAD_(&(map
->head
)));